Bluetooth Low Energyの話
みんな大好きBLE。
人は誰しもBLEで長いデータを
送りたくなることがあると思います。
通常のWrite
ある書き込み可能なCharacteristicに対して、(そこまで長くない)任意のバイト列を
送りつける際は、
BluetoothGatt gatt;
BluetoothGattCharacteristic characteristics;
byte[] data;
characteristic.setValue(data);
gatt.writeCharacteristic(characteristic);
みたいにやってあげれば、その後に BluetoothGattCallback
の onCharacteristicWrite()
が呼ばれて、 メデタシメデタシとなる。
20バイト以上のデータ送る
MTUの関係である一定以上の長さのデータを送る際はすこし厄介な話になる。
もちろんそのままでは送ることはできないので、
以下の2つの方法を検討する必要がある。
- MTUの値を引き上げる
- PrepareWrite/ExecuteWriteを使う
MTUを変更する
これは特に問題なく動いている感じ。
BluetoothGatt#requestMtu()
をつかって MTUサイズを変更してあげるやり方。
Peripheralとの通信の部分は詳しくないので、
よく分からずひどいシーケンス図ですが、
MTUサイズ変更後は、それを超えない
データ列であれば、そのままCharacteristicに
setしてWriteできます。
Prepare/Execute Writeをする
今回のメインの愚痴はこれ。
MTUサイズを変更せずに、データ列を分割して
ペリフェラルにWriteを行う方法。
LongWriteとも呼ばれる。
Android的には
beginReliableWrite()
と executeReliableWrite()
を使うそうです。これがまぁ、まともに動かない。
onCharacteristicWrite()
が来なかったり、 データ列のオフセット情報がPeripheralに
伝わらなかったりひどい状態でした。
Issue 158619: BLE write long data
IssueTrackerにも挙がっているので、
みんな苦しんでいる様子・・・。
というわけで、MTUを変更して送るほうが吉のようです。
悪夢はここから
ひょんなことから、MTUの変更もせずに、
ReliableWriteも使わずに長いデータ列を
送りつけるとどうなるかやってみたが、
これが酷かった。
こんな感じで、何事もなかったかのように
onCharacteristicWrite()
がAPPに飛んでくる。 その裏ではAndroidがせっせと
Prepare/ExecuteWriteを繰り返している…。
ただし、
onReliableWriteCompleted()
は 飛んでこない。
もうね、何なんだろう。
何のためにReliableWriteがAndroidに
存在しているのか本当にわからない。
百歩譲って、ちゃんとWriteできてるんだから、
writeCharacteristic()
はtrueを返してほしい。
勘違いだと思われ。
返信削除beginReliableWrite()、executeReliableWrite() メソッドは複数の characteristic をまとめて write するためのものでは?
BT 仕様だと
Core Vol.3, Part G GATT, 4.9.4 Write Long Characteristic ではなく
4.9.5 Reliable Writes
コメントありがとうございます。
返信削除つまり、LongWriteとは別物なんですね・・・勉強になりました。
とはいえ、APIをコールしても、リファレンス通りの挙動になっていないのでちょっと気持ち悪いのも事実です。