「gatttool を使って NUS( Nordic UART Service ) とつなぐ実験」
https://qiita.com/nanbuwks/items/7c448837eedf439b8ee9
でやったことを、
Adafruit Python BluefruitLE
でやってみます。
Adafruit Python BluefruitLE
https://github.com/adafruit/Adafruit_Python_BluefruitLE
は
Linux,Mac OSXで使えるPythonライブラリです。また、Linux では PC / Raspberry Pi 同様に動作します。
今回、Windows を除く限定的なマルチプラットフォームのツールを作る必要があったのでこれを試してみました。
余談
同じ名前を冠しているハードウェア
nRF52 Bluefruit LE
という製品もあります。nRF5x を Arduino で動かす系の開発環境では、これ用のものが一番うまくできている感じです。
環境
- Raspberry Pi + Raspbian GNU/Linux 9
明示していませんが、PC 上の Ubuntu Linux 16.04 でも同様でした。
インストール
ドキュメントを見ると、bluez 5.33が必要らしいです。
$ sudo apt-get install bluez
Reading package lists... Done
Building dependency tree
Reading state information... Done
bluez is already the newest version (5.43-2+rpt2+deb9u2).
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
5.43が入ってますね。大丈夫かな?
ドキュネントによるとPython2.7用らしいですが、Python3で試してみます。
$ sudo pip3 install Adafruit-BluefruitLE
Collecting Adafruit-BluefruitLE
Downloading https://www.piwheels.org/simple/adafruit-bluefruitle/Adafruit_BluefruitLE-0.9.10-py3-none-any.whl (49kB)
100% |████████████████████████████████| 51kB 86kB/s
Collecting future (from Adafruit-BluefruitLE)
Downloading https://www.piwheels.org/simple/future/future-0.17.1-py3-none-any.whl (488kB)
100% |████████████████████████████████| 491kB 161kB/s
Installing collected packages: future, Adafruit-BluefruitLE
Successfully installed Adafruit-BluefruitLE-0.9.10 future-0.17.1
サンプルプログラムを取得します
$ wget https://github.com/adafruit/Adafruit_Python_BluefruitLE/archive/master.zip
pi@raspberrypi:~ $ unzip master.zip
pi@raspberrypi:~ $ cd Adafruit_Python_BluefruitLE-master/
pi@raspberrypi:~/Adafruit_Python_BluefruitLE-master $ ls
Adafruit_BluefruitLE LICENSE README.md examples setup.py
pi@raspberrypi:~/Adafruit_Python_BluefruitLE-master $ cd examples/
pi@raspberrypi:~/Adafruit_Python_BluefruitLE-master/examples $ ls
device_info.py list_uarts.py low_level.py uart_service.py
実行してみます
pi@raspberrypi:~/Adafruit_Python_BluefruitLE-master/examples $ python3 uart_service.py
ERROR:dbus.proxies:Introspect error on :1.3:/: dbus.exceptions.DBusException: org.freedesktop.DBus.Error.AccessDenied: Rejected send message, 2 matched rules; type="method_call", sender=":1.21" (uid=1000 pid=32656 comm="python3 uart_service.py ") interface="org.freedesktop.DBus.Introspectable" member="Introspect" error name="(unset)" requested_reply="0" destination=":1.3" (uid=0 pid=439 comm="/usr/lib/bluetooth/bluetoothd ")
Traceback (most recent call last):
File "uart_service.py", line 85, in <module>
ble.run_mainloop_with(main)
File "/usr/local/lib/python3.5/dist-packages/Adafruit_BluefruitLE/bluez_dbus/provider.py", line 105, in run_mainloop_with
raise_(self._exception[1], None, self._exception[2])
File "/usr/local/lib/python3.5/dist-packages/future/utils/__init__.py", line 416, in raise_
raise exc
File "/usr/local/lib/python3.5/dist-packages/Adafruit_BluefruitLE/bluez_dbus/provider.py", line 120, in _user_thread_main
self._return_code = target()
File "uart_service.py", line 20, in main
ble.clear_cached_data()
File "/usr/local/lib/python3.5/dist-packages/Adafruit_BluefruitLE/bluez_dbus/provider.py", line 137, in clear_cached_data
for device in self.list_devices():
File "/usr/local/lib/python3.5/dist-packages/Adafruit_BluefruitLE/bluez_dbus/provider.py", line 170, in list_devices
return map(BluezDevice, self._get_objects('org.bluez.Device1'))
File "/usr/local/lib/python3.5/dist-packages/Adafruit_BluefruitLE/bluez_dbus/provider.py", line 181, in _get_objects
for opath, interfaces in iteritems(self._bluez.GetManagedObjects()):
File "/usr/lib/python3/dist-packages/dbus/proxies.py", line 70, in __call__
return self._proxy_method(*args, **keywords)
File "/usr/lib/python3/dist-packages/dbus/proxies.py", line 145, in __call__
**keywords)
File "/usr/lib/python3/dist-packages/dbus/connection.py", line 651, in call_blocking
message, timeout)
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.AccessDenied: Rejected send message, 2 matched rules; type="method_call", sender=":1.21" (uid=1000 pid=32656 comm="python3 uart_service.py ") interface="org.freedesktop.DBus.ObjectManager" member="GetManagedObjects" error name="(unset)" requested_reply="0" destination=":1.3" (uid=0 pid=439 comm="/usr/lib/bluetooth/bluetoothd ")
エラー出ましたね。 bluetooth 関連は pi ユーザーだと使えないことが多いので、 sudo つけて実行してみます。
pi@raspberrypi:~/Adafruit_Python_BluefruitLE-master/examples $ sudo python3 uart_service.py
Using adapter: raspberrypi
Disconnecting any connected UART devices...
Searching for UART device...
Connecting to device...
Discovering services...
Traceback (most recent call last):
File "uart_service.py", line 85, in <module>
ble.run_mainloop_with(main)
File "/usr/local/lib/python3.5/dist-packages/Adafruit_BluefruitLE/bluez_dbus/provider.py", line 105, in run_mainloop_with
raise_(self._exception[1], None, self._exception[2])
File "/usr/local/lib/python3.5/dist-packages/future/utils/__init__.py", line 416, in raise_
raise exc
File "/usr/local/lib/python3.5/dist-packages/Adafruit_BluefruitLE/bluez_dbus/provider.py", line 120, in _user_thread_main
self._return_code = target()
File "uart_service.py", line 59, in main
uart = UART(device)
File "/usr/local/lib/python3.5/dist-packages/Adafruit_BluefruitLE/services/uart.py", line 50, in __init__
self._tx = self._uart.find_characteristic(TX_CHAR_UUID)
File "/usr/local/lib/python3.5/dist-packages/Adafruit_BluefruitLE/interfaces/gatt.py", line 48, in find_characteristic
for char in self.list_characteristics():
File "/usr/local/lib/python3.5/dist-packages/Adafruit_BluefruitLE/bluez_dbus/gatt.py", line 56, in list_characteristics
paths = self._props.Get(_SERVICE_INTERFACE, 'Characteristics')
File "/usr/lib/python3/dist-packages/dbus/proxies.py", line 145, in __call__
**keywords)
File "/usr/lib/python3/dist-packages/dbus/connection.py", line 651, in call_blocking
message, timeout)
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.InvalidArgs: No such property 'Characteristics'
sudo つけると権限関係のエラーはクリアしたみたいですが、別のエラーが出ています。
BlueZ はディストリビューション付属のものですが、それを削除して ダウンロードした 5.50 版(最新)にしてみたり、Ubuntu の PC でやってみたりしましたが同様でした。
ダウンロードしたものは、
https://github.com/adafruit/Adafruit_Python_BluefruitLE
にあるような手順で行っています。
また、以下のように5.33にしてみたりしましたがうまいくいきませんでした。
sudo apt-get update
sudo apt-get -y install libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev
wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.33.tar.gz
tar xvfz bluez-5.33.tar.gz
cd bluez-5.33
./configure --disable-systemd
make
sudo make install
sudo cp ./src/bluetoothd /usr/local/bin/
ディストリビューション付属のBlueZを削除すると、Ubuntuでは依存関係にあった unity-control-center も削除され、「システム設定」が出なくなってしまいました。これが原因と思わなかったのでしばらくあれれーということになりました。
RaspberryPiも似たような依存関係がありそうで、入れ替えるのはやめる方向で調べてみました。
ぐぐってみると、悩んでいる人は多そうです。
これによると、BlueZ の 5.38 以降は D-Bus Object Manager の仕様に準拠したため互換性がなくなっているようです。
ここに BluefruitLE へのパッチも示されてますが、それだけではうまくいきませんでした。
BlueZ の仕様変更に合わせて更に追求すれば動きそうですが、今回 Adafruit Python BluefruitLE を使うモチベーションは Linux と Mac で両対応することでした。この修正で Mac で動作するかどうかの検証に時間がかかりそう(Mac持ってない)ので、 Adafruit Python BluefruitLE を使うのはあきらめ Web-bluetooth を使う方法に乗り換えました。