通过连接到外部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); }
这是我用来发送数据的代码."发送"功能用于以下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()); } });
当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()); } });
但我只收到了"Test3",即最后一个特征.我犯了什么错误?我是BLE的新手所以请忽略任何天真
编辑:
在接受任何后来观看此内容的人的回答后.
有两种方法可以实现这一目标.1.分割数据并按所选答案的循环写入.2.拆分数据并使用回调写入,即onCharacterisitcWrite()
.如果在写作期间有任何错误,这将使您免于错误.
但是,如果您只是编写而不是等待固件的响应,则写入之间最重要的是使用a Thread.sleep(200)
.这将确保您的所有数据都达到.没有sleep
我总是得到最后一个包.如果您注意到他也使用sleep
过的答案.
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; } } }
在Lollipop上,您最多可以发送512个字节.您需要使用 BluetoothGatt.requestMtu()
值512.此外,正如@Devunwired所提到的,您需要等到任何先前的操作完成后再调用它.
如果另一端的设备支持,则实际上可以触发BLE Long写入.
您可以通过将写入类型设置为BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT来执行此操作
在这种情况下,您可以发送超过20个字节.
这里有很多误导.
BLE能够发送超过20个字节,并且可以在android中轻松完成.
您需要更改的是默认情况下设置为23的链接MTU(其中只有20个可用于设置值).如果要发送的给定数据包大于当前链接MTU(这是onCharacteristicRead(...)
API中offset参数的目的),Android会提供碎片机制.
因此,您可以将MTU做大,作为来自中央使用:requestMtu(...)
API 的请求.后者将onMtuChanged
在外围端引起回叫呼叫,这将通知他新的MTU.完成此操作后,您可以发送更大的数据包,而无需发出Android碎片机制.
替代方案是建立自己的碎片机制,而不是发送大于MTU的数据包.或者依赖Android机制并使用'offset'参数来处理它.
如果要通过BLE发送大量数据,那么最好的选择是使用两个特征,一个特征发送大量数据,另一个特征发送最后一个数据段。这样,您无需将响应设置为WRITE_NO_RESPONSE并使用回调来一直发送下一个片段,直到到达最后一个片段为止,此时您将把它写入第二个特征,这将使设备知道您已经完成了数据写入,并且可以将所有数据连接在一起以形成一个大数据包。
您是正确的,BLE规范不允许写操作超过20个字节.如果你不能将你的有效载荷细分为多个特征(这在逻辑上会更容易维护),那么你的分块机制就是另一种方法.
但是,当您尝试排队多个操作时,请注意BLE堆栈不喜欢.每个读/写都是异步的,结果来自实例上的onCharacteristicRead()
或onCharacteristicWrite()
回调BluetoothGattCallback
.您编写的代码尝试在彼此之上发送三个特征写操作,而无需等待其间的回调.您的代码需要遵循以下路径:
send(Test1) -> Wait for onCharacteristicWrite() -> send(Test2) -> Wait for onCharacteristicWrite() -> send(Test3) -> Wait for onCharacteristicWrite() Done!