Bleak
https://gyazo.com/674a07c50bb4666caec065e3dcad100e
クロスプラットフォーム対応しており、各 OS の BLE 通信機能のラッパーとして実装されている
大抵の環境でほぼそのまま動いてくれるすごいやつだよ
インストール
$ pip install bleak
これだけ
Linux の場合は必要に応じて Bluez のインストールを
その他注意点
Linux で動かす時は Bluetooth 機能触るのに管理者権限が必要なのでsudoを付ける必要がある Python の非同期のスタンダードが今後もasyncioであり続けることを祈ろう…… 使い方
接続可能な端末を探すサンプル
code:search.py
import asyncio
from bleak import discover
async def main():
devices = await discover()
for d in devices:
print((d.address, d.name, d.rssi))
if __name__ == "__main__":
asyncio.run(main())
実行結果
接続可能な端末の MAC アドレス・端末名・通信強度が表示される
解説
discover()関数が接続可能な端末を探してくれる
この関数はコルーチンなのでawait式でスキャン完了を待機してから結果を受け取る
await式はコルーチンの中でしか使えないのでasync defによってmain関数をコルーチンにする
コルーチンはasyncio.run()で実行する
適当に通信をするサンプル
code:ble_sample.py
import asyncio
from bleak import BleakClient
address = "XX:XX:XX:XX:XX:XX"
NUS_RX = "6e400002-b5a3-f393-e0a9-e50e24dcca9e"
NUS_TX = "6e400003-b5a3-f393-e0a9-e50e24dcca9e"
def notif_hndlr(_, data):
"""Simple notification handler which prints the data received."""
print(data)
async def main(address):
async with BleakClient(address) as client:
print("Start notify")
await client.start_notify(NUS_TX, notif_hndlr)
print("Sending Message...")
await client.write_gatt_char(NUS_RX, b"\x00")
print("Stopping notify after 3s")
await asyncio.sleep(3)
await client.stop_notify(NUS_TX)
print("fin")
if __name__ == "__main__":
asyncio.run(main(address))
実行結果
子機からの信号は受け取り次第表示
子機に0x00という 1 byte のメッセージを送る
3 秒ほど様子を見てプログラム終了
解説
この通信では Nordic UART という通信方式を採用している
NUS_RX及びNUS_TXはそれぞれ子機への送信用・受信用の Characteristic の UUID を表している
UUID は Nordic UART で定められたもの
独自の通信がしたい場合は独自の UUID を作る
子機がどの通信方式か分からない場合は Bluetooth をモニタリングするアプリを使うと便利 https://gyazo.com/b27f8c23313a8f3815be2bdd4ce75fd0
読み取った UUID で検索かければ大体分かる
notif_hndlr()は NOTIFY でデータ受信した時用のコールバック関数
第一引数は受信した Characteristic の UUID だけど一種しか受信してなくて不要なので読み捨て
async withは非同期用のwith文
要は接続や切断終了処理をよろしくやってくれる便利構文の async 版
BleakClient()で BLE 通信クライアントのインスタンスを生成
ただし予め接続相手はペアリングしておく必要がある
Mac OS の場合はアドレスの代わりに OS 側が設定する端末の UUID を指定することになる client.start_notify()で NOTIFY 受信用の口を開く
第一引数は受信する Characteristic の UUID
裏で受信処理を実行し続け、受信した時は第二引数で指定したコールバック関数が実行される
client.write_gatt_char()でバイト列を送信する
子機の様子を見るためにasyncio.sleep()で3秒ほど待機
普通のtime.sleepは async では使ってはいけない
client.stop_notify()で NOTIFY の受信停止
切断等の終了処理は先述の通りasync with構文がよしなにやってくれる
まとめ
予めペアリングを済ませておく
Linux では sudo で実行する
この2つの情報があれば通信できる
子機の MAC アドレス( Mac OS の場合は UUID)
Characteristic の UUID
asyncio という非同期モジュールを扱うのでその作法に従う必要がある