我有一个定制的硬件和蓝牙低能芯片。我用一个带有500个u32s的数组来设置它,比如arrayn == n。我正在开发一个安卓应用程序,它可以连接到设备上,请求数组的长度,然后一次请求数组中的数据点。
这款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中,没有用于请求数据点51的onCharacteristicWrite日志。在每次停止获取数据之前,这种情况似乎都会发生,但我不确定这是否重要,还是只是日志缓冲区的问题。
我已经运行了相当多的测试试图注意到任何模式,并且我注意到当设备没有连接到调试电缆时,它似乎得到了更多的数据点。在这一点上,我唯一的想法是,也许我对异步中断回调有问题,但我不知道会做什么。有没有人想过为什么在调用onCharacteristicWrite之后,它似乎没有真正地编写数据呢?
谢谢
编辑:
我听从了Emil的建议,打开了蓝牙日志。我和wireshark一起玩,弄明白了到底发生了什么。我再次试用了我的应用程序,它一直运行到索引102,直到它停止运行,这时我断开了设备的连接。我在Wireshark中搜索了数据包,发现我的设备确实收到了大约102的数据,但它没有发送103的请求。我再次检查了我的android日志,onCharacteristicWrite内部的一条日志语句说它发送了命令02 67 00,这是对103的请求。因此,onCharacteristicWrite似乎正在被调用,但其特性并不是实际编写的。
经过更多的凝视和思考之后,我非常肯定,要么是onCharacteristicWrite被错误地调用了,因为数据从未被写入,要么是某种异步的东西正在中断它并阻止它传输。我不知道会怎么做。
最后编辑:
尽管据我从规范中了解到,只有在进行可靠、成功的写入时才会调用onCharacteristicWrite,但我还是决定检查writeCharacteristic的返回值。我几个小时前就该查过了。你知道吗,上次的请求是假的。
我认为,即使返回是假的,onCharacteristicWrite也被调用了,这是一个错误。我已经读到,使用onCharacteristicWrite调用来编写下一个数据块是安全的。要么他们错了,要么这里出了什么乱七八糟的事情。不管怎样,我想检查那些函数调用返回值是个不错的主意。
发布于 2016-08-24 18:18:59
现在我想我看到了。有时,通知会在onWriteCharacteristic回调之前到达。由于您在通知回调中发出下一个写,所以前面的写仍然挂起。您必须确保在发出下一次写入之前已经调用了onWriteCharacteristic。
https://stackoverflow.com/questions/39109178
复制相似问题