我有一个带有蓝牙低能耗芯片的定制硬件。我用一个500 u32s的数组设置它,使得array [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日志中,没有onCharacteristicWrite日志来请求数据点51.这似乎每次都在它停止获取数据之前发生,但我不确定这是否是重要的,或者它只是日志缓冲区的一个问题。
我已经运行了很多试图注意任何模式的测试,并且我注意到当设备未连接到调试电缆时似乎获得了更多的数据点。我在这一点上唯一的想法是,我可能遇到异步中断回调的问题,但我不知道会做什么。在调用onCharacteristicWrite之后,有没有人想过为什么它似乎没有实际写入数据?
由于
编辑:
我遵循了Emil的建议并开启了蓝牙记录功能。我和wireshark一起玩,想出发生了什么事。我再次尝试了我的应用程序,它跑到索引102直到它停止,此时我断开了设备。我挖掘了Wireshark中的数据包,发现我的设备DID收到了大约102的数据,但它没有发送103的请求。我仔细检查了我的android日志,并且来自onCharacteristicWrite里面的一条Log语句说它发送了命令02 67 00,这是103的请求。因此,似乎正在调用onCharacteristicWrite,但实际上并未写入该特性。
经过一些更多的凝视和思考后,我非常肯定1)onCharacteristicWrite被正确调用,因为数据永远不会被写入,或者2)某种程度上异步正在中断它并阻止它发送。我不知道会做什么。
最终编辑:
即使我从规范中理解,onCharacteristicWrite只应在可靠,成功的写入进行时调用,我决定检查writeCharacteristic的返回值。几小时前我应该检查一下。而且你知道什么,它在最后一次请求时返回false。
我认为onCharacteristicWrite被调用的事实即使返回为假也是一个错误。我已经读过使用onCharacteristicWrite调用来编写下一个数据块是安全的。他们错了,或者在这里发生了什么事情。无论哪种方式,我认为检查这些函数调用返回值是个不错的主意。
答案 0 :(得分:2)
现在我想我明白了。有时,通知会在onWriteCharacteristic回调之前到达。由于您在通知回调中发出下一个写入,因此上一次写入仍处于暂挂状态。在发出下一次写入之前,必须确保已调用onWriteCharacteristic。