見出し画像

bluez-dbus を使って BLE デバイスを利用してみる

Bluetooth Low Energy (以下、BLE と略記します)のセンサーや機材からデータを取得することは多いのですが、今まで敢えて選択してこなかった Java を使っての実装機会があり bluez-dbus というライブラリを使いました。若干、悩ましいポイントがありましたので、使う上でのポイントを書きたいと思います。


はじめに

なぜ Java での実装を行ってこなかったかというと、私の守備範囲においては Java であることの必然性がほとんどないからです。

タブレットやスマートフォンで BLE 機器と連携するのならば、Flutter と BLE 向けのプラグインの組み合わせ。
データの取得をエッジ側の機材にまかせられ、シングルボードコンピューター(以下、SBCと略記します)を使えるのであれば、Python で bleak を選択して外部に連携します。
エッジ側に設置できる機材が MCU だけであればそれ向けのフレームワークなりライブラリーで対応して別システムに連携するなどします。

今回は弊社製品の MotionBoard にて直接 BLE 機器からデータを収集したい状況となり、その手段として拡張プログラムの利用を選択したため Java による実装となりました。

拡張プログラム

MotionBoard はいろいろなデータを可視化/分析することができます。
ただ、標準ではサポートしていないサービスや機器からデータを取得したい場合、ユーザーに対して解放されている拡張プログラムを利用することになります。

拡張プログラムで行えることや実装方法などは今回の主題ではありませんので、 MotionBoard のオンラインマニュアルをご覧ください。

利用したバージョンについて

今回は Java 11 での利用であったため、利用した bluez-dbus, dbus-java の各バージョンは以下となっています。

  • bluez-dbus: 0.2.0-SNAPSHOT

  • dbus-java: 4.3.2

参考にした情報

BlueZ, D-Bus, Python で検索すると山のように情報やオープンソースがでてきますが、Java となると bluez-dbus の一択で情報もごくわずかです。
ドキュメントに関しては javadoc.ioこちらを有効に利用させて頂きました。

参考にさせて頂いた情報

bluze-dbus を使えばいきなり幸せな世界が待っているわけではなく、BlueZ, D-Bus についてはある程度理解している必要があります。
公式サイトより、以下のものが分かりやすかったです。

bluez-dbus を使った実装例

端的にもうしますと、こちらのブログ「屋内環境を手軽にモニタリングする~①動機とコンセプト~」と公開してくださっている bluetooth-scanner および cc2650-driver がなければ短時間で実装できませんでした。大変参考にさせていただきました。

使う上でのポイント

一言でいうと、AbstractPropertiesChangedHandler を extendsした実装クラスの handler メソッドを実装し、DeviceManager#registerPropertyHandle にて登録し、通知を元に動かしましょう、に尽きます。

デバイスの検出が遅い

bluetoothctl コマンドの scan では早々にデバイスが見つかるのですが、bluez-dbus を元にした実装内でディスカバリー処理をやっても デバイスが見つからないことが何度かありました。
冒頭に書いたように、AbstractPropertiesChangedHandler の実装クラスを登録して、興味があるデバイスが通知されてくるのをしっかり待ちましょう。

ディスカバリー処理については、アクティブスキャンやパッシブスキャンなどを制御できるとよいのですが、bluez-dbus にはそのインターフェースは見つけられませんでした。

サービスの取得が極端に遅い

困ったのがこちらです。
BluetoothDevice#connect で接続後、デバイスが提供するサービスを取得するために BluetoothDevice#getGattServices を呼び出すのですが空のリストが返ります。
connect メソッドも速くはなく数百ミリ秒のオーダーですが、getGattServices は非常に遅く、サービスUUIDが取得できるまで秒オーダーの時間がかかります。
適当にスリープしながら getGattServices を繰り返して呼び出し、リストが空ではなかったらというやりかたもありますが、空でない場合にすべてのサービスが取得できたかは判断がつきません(試行した範囲では、空ではないリストの場合はすべてのサービスUUIDが取得できていましたが、保証されているという説明は見つけられませんでした)。

この問題も AbstractPropertiesChangedHandler の実装クラス handler メソッドへの通知を待つのが妥当です。

connect, getGattService の処理が完了した場合、handler メソッドに通知される通知データのクラス PropertiesChanged から getPropertiesChanged で取得できる Map<String, Variant<?>> のキーである文字列は以下のようになります。

  • connect - "Connected class"

  • getGattServices - "ServicesResolved class"

あとがき

今回は使い始めた bluez-dbus について、現時点で気がついたことなどを少しばかり書かせて頂きました。今後、より使いこんで改めてノウハウなどを公開させて頂きたいと思います。


この記事が気に入ったらサポートをしてみませんか?