目次: Arduino
M5Stamp C3をBluetooth LEデバイスにして、Linux PCもしくはRaspberry PiなどのLinux SBCとお話する取り組みの続編です。
今回はbluez-dbusを使ってBluetoothデバイスと通信します。
前回の話と少し重複しますが、Bluetoothデバイス特にBLEデバイスとはGATTプロファイルを使って通信します。BLEデバイスはサーバーになります。サーバーはService(=提供する機能)を1つもしくは複数持っていて、Service、Characteristic、ValueとDescriptorが入れ子の構造になっています。
GATTのデータ送受信はCharacteristicのValueを読み書きすることで実現します。まずは簡単な送信側(Write)からご紹介します。
private BluetoothGattCharacteristic GattTx;
byte[] dat = new byte[len];
//送信するデータを用意する
//...
GattTx.writeValue(bpart, null);
バイト配列を用意してwriteValue()を呼びます。書き換え属性を持っているCharacteristicでないと書き込みが失敗します。
次は受信側(Read)です。writeValue()と同様にreadValue()も用意されていて、最後にReadした値を読み出せます。しかし一度読んだ値なのか新しい値なのか区別が付きません、つまり値の更新の有無がわかりません。
BluetoothGattCharacteristic GattRx;
byte[] dat = GattRx.readValue(null);
ではこの方法はダメなのか?というとそんなことはありません。一定時間ごとに現在値を見たい場合、例えば「温度計の値を1分ごとに読み出す」といった用途で役立ちます。
一方でストリームデータを扱う場合、新しい値がきたときだけ読み出したいので更新を検出する必要があります。検出には少しややこしい処理が必要です。bluez-dbusは何かの状態変化が起きるとPropertiesChangedというイベントで知らせてくることを利用します。使い方は、
コードで書くと下記のようになります。
public class PropertiesChangedHandler extends AbstractPropertiesChangedHandler {
@Override
public void handle(Properties.PropertiesChanged props) {
}
}
BluetoothGattCharacteristic GattRx;
DeviceManager deviceManager = DeviceManager.getInstance();
PropertiesChangedHandler handler = new PropertiesChangedHandler(...);
deviceManager.registerPropertyHandler(handler);
GattRx.startNotify();
PropertiesChangedハンドラはCharacteristicsの値の更新も、別の関係ないイベントも何でも受け取るので、何のイベントが発生したか判定する必要があります。bluez-dbusのBluetoothGattCharacteristicクラスと、PropertiesChangedクラスはいずれもD-Busのパス(/org/bluez/hci0/dev_xx_xx_xx_xx_xx_xx/service0028/char0029のような文字列)を返すメソッドを持っていますので、D-Busのパスが一致するかどうかで確かめます。
変化した値と名前のMapをgetPropertiesChanged()で取得できるので、全要素を調べて名前がValueであり、バイト配列を保持していればCharacteristicの値の変化を通知するイベントのはずです。
BluetoothGattCharacteristic GattRx;
Map<String, Variant<?>> mapProp = props.getPropertiesChanged();
if (GattRx.getDbusPath().equalsIgnoreCase(props.getPath())) {
for (Map.Entry<String, Variant<?>> e : mapProp.entrySet()) {
if (e.getValue().getValue() instanceof byte[]) {
dat = (byte[])e.getValue().getValue();
}
}
}
自分でBLEデバイス側の実装をしているなら、意図しないイベントが混ざることはありません。上記のコードのように簡素なチェック(例えば単にバイト配列かどうかだけチェック)でも動作するはずです。
< | 2024 | > | ||||
<< | < | 03 | > | >> | ||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
- | - | - | - | - | 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | - | - | - | - | - | - |
合計:
本日: