Bluetooth Low Energy チップを搭載したカスタム ハードウェアがあります。array[n] == n となるように、500 個の u32 を持つ配列で設定しました。私は、デバイスに接続し、配列の長さを要求し、配列内のデータポイントを一度に 1 つずつ要求できる 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);
}
コマンドの送信が速すぎても問題はないと確信しています。プロジェクトの次の部分に進む前に、より簡単にテストできるように、意図的にそうしました。
私のデバッグ ログの 1 つからのスニペット:
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 デバッグの最初の 16 進バイトはコマンドです。コマンド 02 は、次の 2 バイトに含まれるもののインデックスでデータポイントを要求していることを意味します。
Android ログに、データポイント 51 を要求するための onCharacteristicWrite ログがないことに気付きました。これは、データの取得を停止する直前に毎回発生するようですが、これが重要なのか、それとも単にログバッファの問題。
パターンに注目するためにかなりの数のテストを実行しましたが、デバイスがデバッグ ケーブルに接続されていないときに、より多くのデータポイントを取得しているように見えることに気付きました。この時点での私の唯一の考えは、コールバックを中断する非同期の何かに問題がある可能性があるということですが、それが何をしているのかわかりません。onCharacteristicWrite が呼び出された後に実際にデータを書き込まないように見える理由について、誰か考えがありますか?
ありがとう
編集:
私は Emil の提案に従い、Bluetooth ロギングをオンにしました。私はwiresharkで遊んで、何が起こっているのかを理解しました。アプリをもう一度試してみたところ、停止するまでインデックス 102 まで実行され、停止した時点でデバイスを切断しました。Wireshark でパケットを調べたところ、デバイスの DID が 102 に関するデータを受信していることがわかりましたが、103 の要求は送信されていませんでした。Android のログを再確認したところ、onCharacteristicWrite 内の Log ステートメントで、コマンドを送信したことがわかりました。 02 67 00、これは 103 の要求です。したがって、onCharacteristicWrite が呼び出されているように見えますが、特性は実際には書き込まれていません。
もう少し見つめて考えた結果、1) データが書き込まれていないため、onCharacteristicWrite が不適切に呼び出されているか、2) 何らかの形で非同期の何かがデータを中断して送信を停止していると確信しています。私はこれを何をしているのか分かりません。
最終編集:
私が仕様から理解している限り、onCharacteristicWrite は信頼できる成功した書き込みが進行中の場合にのみ呼び出されるはずですが、writeCharacteristic からの戻り値を確認することにしました。何時間も前にチェックすべきだった。そして、あなたが知っていることは、最後のリクエストで false を返していたことです。
return が false なのに onCharacteristicWrite が呼び出されたのはバグだと思います。onCharacteristicWrite 呼び出しを使用して次のデータ チャンクを書き込むのが安全であることを読みました。それらが間違っていたか、何かおかしなことが起こっているかのどちらかです。いずれにせよ、これらの関数呼び出しの戻り値を確認することはかなり良い考えだと思います。