Android:通过BLE发送> 20个字节的数据

Ank*_*wal 47 java android bluetooth-lowenergy

通过连接到外部BLE设备,我能够发送最多20个字节的数据.如何发送大于20个字节的数据.我已经读过,我们必须将数据分段或将特征分割为所需的部分.如果我假设我的数据是32个字节,你能否告诉我需要在我的代码中进行的更改才能使其正常工作?以下是我的代码中所需的代码段:

public boolean send(byte[] data) {
    if (mBluetoothGatt == null || mBluetoothGattService == null) {
        Log.w(TAG, "BluetoothGatt not initialized");
        return false;
    }

    BluetoothGattCharacteristic characteristic =
            mBluetoothGattService.getCharacteristic(UUID_SEND);

    if (characteristic == null) {
        Log.w(TAG, "Send characteristic not found");
        return false;
    }

    characteristic.setValue(data);
    characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
    return mBluetoothGatt.writeCharacteristic(characteristic);
}
Run Code Online (Sandbox Code Playgroud)

这是我用来发送数据的代码."发送"功能用于以下onclick事件.

sendValueButton = (Button) findViewById(R.id.sendValue);
    sendValueButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            String text = dataEdit.getText().toString();                           
            yableeService.send(text.getBytes());
        }
    });
Run Code Online (Sandbox Code Playgroud)

String text大于20个字节时,仅接收前20个字节.如何纠正这个?

为了测试发送多个特性我试过这个:

sendValueButton = (Button) findViewById(R.id.sendValue);
sendValueButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        String text = "Test1";                           
        yableeService.send(text.getBytes());

        text = "Test2";                           
        yableeService.send(text.getBytes());

        text = "Test3";                           
        yableeService.send(text.getBytes());
    }
});
Run Code Online (Sandbox Code Playgroud)

但我只收到了"Test3",即最后一个特征.我犯了什么错误?我是BLE的新手所以请忽略任何天真

编辑:

在接受任何后来观看此内容的人的回答后.

两种方法可以实现这一目标.1.分割数据并按所选答案的循环写入.2.拆分数据并使用回调写入,即onCharacterisitcWrite().如果在写作期间有任何错误,这将使您免于错误.

但是,如果您只是编写而不是等待固件的响应,则写入之间最重要的是使用a Thread.sleep(200).这将确保您的所有数据都达到.没有sleep我总是得到最后一个包.如果您注意到他也使用sleep过的答案.

Huy*_*wer 28

BLE允许您传输最大值为20个字节.

如果要发送更多20个字节,则应定义数组byte []包括所需的数据包数.

如果要发送<160个字符(160个字节),示例工作正常.

p/s:按照你的意愿编辑.完全没跟着我.

实际上,当我们使用BLE时,移动端和固件端需要设置密钥(例如0x03 ......)来定义两端之间的连接门.

这个想法是:

  • 当我们仍然继续传输数据包时,不是最后一个.门是byte[].

  • 如果我们发送最后一个,门是0x03.

数据构造(20字节):

1 - byte[1] = 0x01- 定义byte[1] = 0x00:ex.消息门ID Byte 1.

2 - Gate ID- 定义byte[0] = 0x03:是最后一个数据包Byte 2还是继续发送数据包recognization.

3 - 0x00(减去0x01&后应为18个字节Byte 3) - 在此处附加消息内容.

请在阅读下面的代码之前了解我的逻辑.

下面是关于发送带有许多数据包的消息的示例,每个数据包:byte [20].

private void sendMessage(BluetoothGattCharacteristic characteristic, String CHARACTERS){
        byte[] initial_packet = new byte[3];
        /**
         * Indicate byte
         */
        initial_packet[0] = BLE.INITIAL_MESSAGE_PACKET;
        if (Long.valueOf(
                String.valueOf(CHARACTERS.length() + initial_packet.length))
                > BLE.DEFAULT_BYTES_VIA_BLE) {
            sendingContinuePacket(characteristic, initial_packet, CHARACTERS);
        } else {
            sendingLastPacket(characteristic, initial_packet, CHARACTERS);
        }
    }

private void sendingContinuePacket(BluetoothGattCharacteristic characteristic,
            byte[] initial_packet, String CHARACTERS){
        /**
         * TODO If data length > Default data can sent via BLE : 20 bytes
         */
        // Check the data length is large how many times with Default Data (BLE)
        int times = Byte.valueOf(String.valueOf(
                CHARACTERS.length() / BLE.DEFAULT_BYTES_IN_CONTINUE_PACKET));

        Log.i(TAG, "CHARACTERS.length() " + CHARACTERS.length());
        Log.i(TAG, "times " + times);

        // TODO
        // 100 : Success
        // 101 : Error
        byte[] sending_continue_hex = new byte[BLE.DEFAULT_BYTES_IN_CONTINUE_PACKET];
        for (int time = 0; time <= times; time++) {
            /**
             * Wait second before sending continue packet 
             */
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            if (time == times) {
                Log.i(TAG, "LAST PACKET ");

                /**
                 * If you do not have enough characters to send continue packet,
                 * This is the last packet that will be sent to the band
                 */

                /**
                 * Packet length byte :
                 */
                /**
                 * Length of last packet
                 */
                int character_length = CHARACTERS.length()
                        - BLE.DEFAULT_BYTES_IN_CONTINUE_PACKET*times;

                initial_packet[1] = Byte.valueOf(String.valueOf(character_length
                        + BLE.INITIAL_MESSAGE_PACKET_LENGTH));
                initial_packet[2] = BLE.SENDING_LAST_PACKET;

                Log.i(TAG, "character_length " + character_length);

                /**
                 * Message
                 */
                // Hex file
                byte[] sending_last_hex = new byte[character_length];

                // Hex file : Get next bytes
                for (int i = 0; i < sending_last_hex.length; i++) {
                    sending_last_hex[i] = 
                            CHARACTERS.getBytes()[sending_continue_hex.length*time + i];
                }

                // Merge byte[]
                byte[] last_packet = 
                        new byte[character_length + BLE.INITIAL_MESSAGE_PACKET_LENGTH];
                System.arraycopy(initial_packet, 0, last_packet,
                        0, initial_packet.length);
                System.arraycopy(sending_last_hex, 0, last_packet, 
                        initial_packet.length, sending_last_hex.length);

                // Set value for characteristic
                characteristic.setValue(last_packet);
            } else {
                Log.i(TAG, "CONTINUE PACKET ");
                /**
                 * If you have enough characters to send continue packet,
                 * This is the continue packet that will be sent to the band
                 */
                /**
                 * Packet length byte
                 */
                int character_length = sending_continue_hex.length;

                /**
                 * TODO Default Length : 20 Bytes
                 */
                initial_packet[1] = Byte.valueOf(String.valueOf(
                        character_length + BLE.INITIAL_MESSAGE_PACKET_LENGTH));

                /**
                 * If sent data length > 20 bytes (Default : BLE allow send 20 bytes one time)
                 * -> set 01 : continue sending next packet
                 * else or if after sent until data length < 20 bytes
                 * -> set 00 : last packet
                 */
                initial_packet[2] = BLE.SENDING_CONTINUE_PACKET;
                /**
                 * Message
                 */
                // Hex file : Get first 17 bytes
                for (int i = 0; i < sending_continue_hex.length; i++) {
                    Log.i(TAG, "Send stt : " 
                            + (sending_continue_hex.length*time + i));

                    // Get next bytes
                    sending_continue_hex[i] = 
                            CHARACTERS.getBytes()[sending_continue_hex.length*time + i];
                }

                // Merge byte[]
                byte[] sending_continue_packet = 
                        new byte[character_length + BLE.INITIAL_MESSAGE_PACKET_LENGTH];
                System.arraycopy(initial_packet, 0, sending_continue_packet, 
                        0, initial_packet.length);
                System.arraycopy(sending_continue_hex, 0, sending_continue_packet, 
                        initial_packet.length, sending_continue_hex.length);

                // Set value for characteristic
                characteristic.setValue(sending_continue_packet);
            }

            // Write characteristic via BLE
            mBluetoothGatt.writeCharacteristic(characteristic);
        }
    }

public boolean writeCharacteristic(BluetoothGattCharacteristic characteristic,
            String data) {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return false;
        }

        if (ActivityBLEController.IS_FIRST_TIME) {
            /**
             * In the first time, 
             * should send the Title
             */
            byte[] merge_title = sendTitle(data);

            // Set value for characteristic
            characteristic.setValue(merge_title);

            // Write characteristic via BLE
            mBluetoothGatt.writeCharacteristic(characteristic);

            // Reset
            ActivityBLEController.IS_FIRST_TIME = false;

            return true;
        } else {
            /**
             * In the second time, 
             * should send the Message
             */
            if (data.length() <= BLE.LIMIT_CHARACTERS) {
                sendMessage(characteristic, data);

                // Reset
                ActivityBLEController.IS_FIRST_TIME = true; 

                return true;
            } else {
                // Typed character
                typed_character = data.length();

                return false;
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 对于这样的事情,我觉得你应该通过{@code} onCharacteristicWrite(){@ code}得到回复,而不是随机休息一段时间.您可以消除以下风险:(a)无法长时间睡眠和(b)睡眠时间过长,从而使您的代码效率非常低,具体取决于您发送的字节数 (3认同)
  • 其他人可以用其他的话来解释这个问题吗?也许还有一个小例子?BLE的包装是什么?如果有人实现了它,请发送代码链接. (2认同)
  • 其中是sendingLastPacket()和setTitle(). (2认同)

Tho*_*asW 19

在Lollipop上,您最多可以发送512个字节.您需要使用 BluetoothGatt.requestMtu()值512.此外,正如@Devunwired所提到的,您需要等到任何先前的操作完成后再调用它.

  • 只有当服务器端的设备支持更改其MTU时才是如此. (2认同)
  • @AndréFratelliNo.您没有收到回复,因为服务器不承认或支持更改MTU. (2认同)

小智 10

这里有很多误导.

BLE能够发送超过20个字节,并且可以在android中轻松完成.

您需要更改的是默认情况下设置为23的链接MTU(其中只有20个可用于设置值).如果要发送的给定数据包大于当前链接MTU(这是onCharacteristicRead(...)API中offset参数的目的),Android会提供碎片机制.

因此,您可以将MTU做大,作为来自中央使用:requestMtu(...)API 的请求.后者将onMtuChanged在外围端引起回叫呼叫,这将通知他新的MTU.完成此操作后,您可以发送更大的数据包,而无需发出Android碎片机制.

替代方案是建立自己的碎片机制,而不是发送大于MTU的数据包.或者依赖Android机制并使用'offset'参数来处理它.


Dev*_*red 9

您是正确的,BLE规范不允许写操作超过20个字节.如果你不能将你的有效载荷细分为多个特征(这在逻辑上会更容易维护),那么你的分块机制就是另一种方法.

但是,当您尝试排队多个操作时,请注意BLE堆栈不喜欢.每个读/写都是异步的,结果来自实例上的onCharacteristicRead()onCharacteristicWrite()回调BluetoothGattCallback.您编写的代码尝试在彼此之上发送三个特征写操作,而无需等待其间的回调.您的代码需要遵循以下路径:

send(Test1)
  -> Wait for onCharacteristicWrite()
  -> send(Test2)
    -> Wait for onCharacteristicWrite()
    -> send(Test3)
      -> Wait for onCharacteristicWrite()
Done!
Run Code Online (Sandbox Code Playgroud)


小智 8

您需要请求 MTU 更新。这是最大传输单位。与现在一样,BLE 在单个数据包中最多接受 512 个字节。但是,如果不请求此 MTU 更新,您的设备将不会发送超过 23 个字节的数据包(当前)。


使用您的 BluetoothGatt 对象调用requestMtu()

这是开发者页面的链接

在此处输入图片说明


BluetoothGattCallback将接收onMtuChanged()事件,如下所示。MTU 更新成功后,您可以将数据作为一个数据包发送。这是此开发人员页面的链接

在此处输入图片说明


我通常在连接到我希望写入的特征后调用 requestMtu() 。祝你好运。


小智 6

如果另一端的设备支持,则实际上可以触发BLE Long写入.

您可以通过将写入类型设置为BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT来执行此操作

在这种情况下,您可以发送超过20个字节.

  • 我在哪里可以找到这个代码?你能添加一个链接到你的答案吗?谢谢! (2认同)

Zom*_*omb 5

如果要通过BLE发送大量数据,那么最好的选择是使用两个特征,一个特征发送大量数据,另一个特征发送最后一个数据段。这样,您无需将响应设置为WRITE_NO_RESPONSE并使用回调来一直发送下一个片段,直到到达最后一个片段为止,此时您将把它写入第二个特征,这将使设备知道您已经完成了数据写入,并且可以将所有数据连接在一起以形成一个大数据包。