我有一个带有蓝牙低功耗芯片的定制硬件。我已经设置了一个包含 500 个 u32 的数组,这样数组 [n] == n。我正在开发一个可以连接到设备的 android 应用程序,请求数组的长度,然后一次请求数组中的数据点。
android 应用程序似乎大部分工作正常。它连接到设备,请求长度,并在收到上一条数据后继续请求下一条数据。但是,在数组的中途(从 2 到 450 个元素的任何地方 - 似乎不一致),它会编写另一个命令,并且会一直执行到 onCharacteristicWrite(),但它永远不会收到响应。我的 BLE 外围设备连接到 CoolTerm,它甚至从未收到命令。以下是我的代码和日志中的片段:
BLE服务:
private final BluetoothGattCallback bleGattCallback = new BluetoothGattCallback() {
@Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
super.onCharacteristicRead(gatt, characteristic, status);
Log.d("onCharacteristicRead", byteArrToHex(characteristic.getValue()));
}
@Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
if(status != BluetoothGatt.GATT_SUCCESS){
Log.d("onCharacteristicWrite", "Failed write, retrying");
gatt.writeCharacteristic(characteristic);
}
Log.d("onCharacteristicWrite", byteArrToHex(characteristic.getValue()));
super.onCharacteristicWrite(gatt, characteristic, status);
}
@Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
super.onCharacteristicChanged(gatt, characteristic);
Log.d("onCharacteristicChanged", byteArrToHex(characteristic.getValue()));
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
}
};
我省略了与描述符写入、连接状态更改等相关的回调中不必要的部分。广播数据时,它在 MainActivity 的这一部分中接收:
private BroadcastReceiver messageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String receivedUUID = intent.getStringExtra("uuid");
byte[] data = intent.getByteArrayExtra("data");
Log.d("messageReceiver", "received intent in mainActivity with uuid " + receivedUUID.toString());
if(receivedUUID.equals(READ_LEN_UUID.toString()) && currentlyReading) {
datapoints = new ArrayList<Long>();
numberOfDatapoints = 0;
numberOfDatapoints |= (data[0] & 0xff);
numberOfDatapoints |= (data[1] & 0xff) << 8;
numberOfDatapoints |= (data[2] & 0xff) << 16;
numberOfDatapoints |= (data[3] & 0xff) << 24;
Log.d("RECEIVER TEST:", "number of datapoints = " + numberOfDatapoints);
if(numberOfDatapoints > 0) {
bleService.requestDatapoint(0);
}
} else if (receivedUUID.equals(READ_DATAPOINT_UUID.toString()) && currentlyReading){
long message = 0;
message |= (data[0] & 0xff);
message |= (data[1] & 0xff) << 8;
message |= (data[2] & 0xff) << 16;
message |= (data[3] & 0xff) << 24;
Log.d("Datapoint Recieved", "Index " + datapoints.size() + " = " + message);
datapoints.add(message);
if(datapoints.size() < numberOfDatapoints){
bleService.requestDatapoint(datapoints.size());
}
}
}
};
调用 writeCharacteristic 的代码:
public void requestDatapoint(int index){
Log.d("requestDatapoint", "Requested datapoint at " + index);
BluetoothGattCharacteristic commandChar = this.gattService.getCharacteristic(WRITE_UUID);
byte[] request = new byte[3];
// command - 2 = get index
request[0] = (byte) (2 & 0xff);
// index
request[1] = (byte) ((index) & 0xff);
request[2] = (byte) ((index >> 8) & 0xff);
commandChar.setValue(request);
bleGatt.writeCharacteristic(commandChar);
}
我相当肯定发送命令太快没有问题。它实际上非常慢,我是故意这样做的,这样我就可以在继续进行项目的下一部分之前更轻松地进行测试。
我的调试日志之一的片段:
08-23 12:08:18.470 16753-16753/sethp.datalogcollector D/requestDatapoint: Requested datapoint at 49
08-23 12:08:18.570 16753-16765/sethp.datalogcollector D/onCharacteristicWrite: 02 31 00
08-23 12:08:18.570 16753-16765/sethp.datalogcollector D/onCharacteristicChanged: 31 00 00 00
08-23 12:08:18.570 16753-16765/sethp.datalogcollector D/BLEService: Characteristic found. UUID: 00020000-5f5f-4a49-4847-464544434241
08-23 12:08:18.575 16753-16753/sethp.datalogcollector D/messageReceiver: received intent in mainActivity with uuid 00020000-5f5f-4a49-4847-464544434241
08-23 12:08:18.575 16753-16753/sethp.datalogcollector D/Datapoint Recieved: Index 49 = 49
08-23 12:08:18.575 16753-16753/sethp.datalogcollector D/requestDatapoint: Requested datapoint at 50
08-23 12:05:55.585 16753-16765/sethp.datalogcollector D/onCharacteristicWrite: 02 32 00
08-23 12:05:55.585 16753-16765/sethp.datalogcollector D/onCharacteristicChanged: 32 00 00 00
08-23 12:05:55.585 16753-16765/sethp.datalogcollector D/BLEService: Characteristic found. UUID: 00020000-5f5f-4a49-4847-464544434241
08-23 12:05:55.585 16753-16753/sethp.datalogcollector D/messageReceiver: received intent in mainActivity with uuid 00020000-5f5f-4a49-4847-464544434241
08-23 12:05:55.590 16753-16753/sethp.datalogcollector D/Datapoint Recieved: Index 50 = 50
08-23 12:05:55.590 16753-16753/sethp.datalogcollector D/requestDatapoint: Requested datapoint at 51
08-23 12:05:55.680 16753-16845/sethp.datalogcollector D/onCharacteristicWrite: 02 33 00
08-23 12:05:55.685 16753-16764/sethp.datalogcollector D/onCharacteristicChanged: 33 00 00 00
08-23 12:05:55.685 16753-16764/sethp.datalogcollector D/BLEService: Characteristic found. UUID: 00020000-5f5f-4a49-4847-464544434241
08-23 12:05:55.685 16753-16753/sethp.datalogcollector D/messageReceiver: received intent in mainActivity with uuid 00020000-5f5f-4a49-4847-464544434241
08-23 12:05:55.685 16753-16753/sethp.datalogcollector D/Datapoint Recieved: Index 51 = 51
08-23 12:05:55.685 16753-16753/sethp.datalogcollector D/requestDatapoint: Requested datapoint at 52
08-23 12:05:55.785 16753-16765/sethp.datalogcollector D/onCharacteristicChanged: 34 00 00 00
08-23 12:05:55.785 16753-16765/sethp.datalogcollector D/BLEService: Characteristic found. UUID: 00020000-5f5f-4a49-4847-464544434241
08-23 12:05:55.785 16753-16753/sethp.datalogcollector D/messageReceiver: received intent in mainActivity with uuid 00020000-5f5f-4a49-4847-464544434241
08-23 12:05:55.785 16753-16753/sethp.datalogcollector D/Datapoint Recieved: Index 52 = 52
08-23 12:05:55.785 16753-16753/sethp.datalogcollector D/requestDatapoint: Requested datapoint at 53
08-23 12:05:55.790 16753-16765/sethp.datalogcollector D/onCharacteristicWrite: 02 35 00
和我相应的 CoolTerm 日志片段:
command: 02
index: 0031
command = 2
datapoint at 49 = 49
attempting to send 49
command: 02
index: 0032
command = 2
datapoint at 50 = 50
attempting to send 50
command: 02
index: 0033
command = 2
datapoint at 51 = 51
attempting to send 51
command: 02
index: 0034
command = 2
datapoint at 52 = 52
attempting to send 52
请注意,在我的外围日志中,它似乎没有收到对数据点 53 的请求。作为参考,onCharacteristicWrite 调试中的第一个十六进制字节是命令。命令 02 只是意味着我在接下来的 2 个字节包含的任何索引处请求一个数据点。
我注意到在 Android 日志中,没有用于请求数据点 51 的 onCharacteristicWrite 日志。这似乎每次都在它停止获取数据之前发生,但我不确定这是否重要或只是一个日志缓冲区问题。
我已经运行了很多测试,试图注意到任何模式,并且我注意到当设备未连接到调试电缆时,它似乎获得了更多数据点。在这一点上,我唯一的想法是,也许我遇到了异步中断回调的问题,但我不知道该怎么做。有人对为什么在调用 onCharacteristicWrite 后它似乎没有实际写入数据有任何想法吗?
谢谢
编辑:
我按照 Emil 的建议打开了蓝牙记录。我玩了wireshark并弄清楚发生了什么。我再次尝试了我的应用程序,它运行到索引 102 直到它停止,此时我断开了设备的连接。我在Wireshark中挖掘了数据包,发现我的设备确实收到了102的数据,但它没有发送103的请求。我仔细检查了我的android日志,onCharacteristicWrite内部的一条Log语句说它发送了命令02 67 00,这是对 103 的请求。因此,似乎正在调用 onCharacteristicWrite,但实际上并未写入特征。
经过更多的凝视和思考,我很确定 1)onCharacteristicWrite 被不正确地调用,因为数据从未被写入,或者 2)不知何故,异步正在中断它并阻止它传输。我不知道会做什么。
最终编辑:
尽管据我从规范中了解,onCharacteristicWrite 只应该在可靠、成功的写入正在进行时被调用,但我决定检查 writeCharacteristic 的返回值。我应该在几个小时前检查一下。你知道吗,它在最后一个请求中返回 false。
我认为即使返回为 false 也调用 onCharacteristicWrite 的事实是一个错误。我读过使用 onCharacteristicWrite 调用来写入下一块数据是安全的。要么他们错了,要么这里发生了一些奇怪的事情。无论哪种方式,我想检查这些函数调用返回值是个好主意。