У меня есть специальное оборудование с чипом Bluetooth с низким энергопотреблением. Я настроил его с помощью массива с 500 u32, так что 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?
Спасибо
РЕДАКТИРОВАТЬ:
Я последовал совету Эмиля и включил ведение журнала Bluetooth. Я поигрался с wireshark и понял, что происходит. Я снова попробовал свое приложение, и оно достигло индекса 102, пока не остановилось, после чего я отключил устройство. Я копался в пакетах в Wireshark и обнаружил, что мое устройство ДЕЙСТВИТЕЛЬНО получило данные о 102, но не отправило запрос на 103. Я дважды проверил свой журнал Android, и оператор журнала изнутри onCharacteristicWrite сказал, что он отправил команду 02 67 00, что является запросом на 103. Итак, похоже, что onCharacteristicWrite вызывается, но на самом деле характеристика не записывается.
Еще немного посмотрев и подумав, я совершенно уверен, что либо 1) onCharacteristicWrite вызывается неправильно, потому что данные никогда не записываются, либо 2) каким-то образом что-то асинхронное прерывает их и останавливает их передачу. Я понятия не имею, что будет делать это.
ПОСЛЕДНЕЕ РЕДАКТИРОВАНИЕ:
Несмотря на то, что, насколько я понимаю из спецификации, onCharacteristicWrite должен вызываться только тогда, когда выполняется надежная и успешная запись, я решил проверить возвращаемое значение из writeCharacteristic. Который я должен был проверить несколько часов назад. И что вы знаете, он возвращал false на последний запрос.
Я думаю, что тот факт, что onCharacteristicWrite был вызван, хотя возврат был ложным, является ошибкой. Я читал, что безопасно использовать вызов onCharacteristicWrite для записи следующего фрагмента данных. Либо они ошиблись, либо здесь происходит что-то странное. В любом случае, я думаю, неплохо было бы проверить эти возвращаемые значения вызова функции.