我有一个带有蓝牙低能耗芯片的定制硬件。我用一个500 u32s的数组来设置它,这样数组[n]==n。我正在开发一个android应用程序,它可以连接到设备,请求数组的长度,然后一次一个地请求数组中的数据点。
android应用程序似乎基本上运行良好。它连接到设备,请求长度,并在收到上一条数据后继续请求下一条数据。但是,在数组的中途(从-2到450个元素中的任何一个元素看起来不一致),它将编写另一个命令,并使其一直指向onCharacteristicWrite(),但它从未收到响应。我的BLE外设连接到CoolTerm,它甚至从来没有收到命令。以下是我的代码和日志片段:
BLEService:
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日志中,没有用于请求datapoint 51的oncharacteristicwrite日志。这种情况似乎每次都发生在它停止获取数据之前,但我不确定这是否重要,或者这是否只是日志缓冲区的问题。
我运行了很多测试,试图注意到任何模式,我注意到,当设备没有连接到调试电缆时,它似乎获得了更多的数据点。在这一点上,我唯一的想法是,也许我有一个异步中断回调的问题,但我不知道该怎么做。有没有人想过为什么在调用oncharacteristicwrite之后它似乎没有真正写入数据?
谢谢
编辑:
我听从了埃米尔的建议,打开了蓝牙日志。我和Wireshark玩了一圈,弄清楚了发生了什么事。我再次尝试我的应用程序,它运行到索引102,直到它停止,在这一点上,我断开了设备。我在wireshark中搜索数据包,发现我的设备确实收到了大约102个数据包,但它没有发送103个请求。我再次检查了我的android日志,oncharacteristicwrite内部的一条日志语句说它发送了命令026700,这是一个103的请求。因此,oncharacteristicwrite似乎正在被调用,但实际上并没有被编写。
经过更多的凝视和思考,我非常确定,要么1)oncharacteristicwrite被不正确地调用,因为数据从未被写入,要么2)不知何故,某种异步的东西正在中断它并阻止它传输。我不知道会做什么。
最后编辑:
尽管,据我从规范中了解,oncharacteristicwrite只应在进行可靠、成功的写入时调用,但我还是决定检查writecharacteristic的返回值。我几个小时前就该检查的。你知道吗,在最后一次请求时它返回了false。
我认为调用oncharacteristicwrite的事实(即使返回值为false)是一个错误。我已经读到使用onCharacteristicWrite调用来写入下一个数据块是安全的。不是他们错了,就是这里发生了什么怪事。不管怎样,我想检查那些函数调用返回值是个不错的主意。
最佳答案
现在我想我看到了。有时通知会在onwritecharacteristic回调之前到达。由于您在通知回调中发出了下一次写入,上一次写入仍处于挂起状态。在发出下一个write之前,必须确保已调用onwritecharacteristic。
关于android - onCharacteristicWrite()被调用,但并不总是写,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39109178/