🌡️
Raspberry Pi Pico W で Switchbot 温湿度計からBLEで値を取得する
Switchbot温湿度計(小さい方)を購入したので、その値をRaspberry Pi Pico Wから取得できるようにしました。
先駆者はたくさんいるようでしたが、Pico WのBLEで、MicroPythonを使った上でライブラリとしてaiobleを使った作例は見当たらなかったので、主に自分向けに簡単にやり方を書いておきます。
要約
MicroPythonから扱えるaiobleだとSwitchbot 温湿度計から出力されるService Dataを示すデータタイプ値 0x16 を判別できずUUIDを取り出せない。
aiobleのソースを参考にしてresp_dataをデコードするプログラムを用意して上げる必要がある。
前提条件
Pimoroni から 発売されている Pico Display Pack を使いたかったので、Pimoroni の MicroPythonファームウェア を使用しています。
おそらくMicroPython公式ファームウェア でも動くとは思いますが、未確認です。
ファームウェアをPico Wへ書き込む方法はよその記事を参照してください。
aioble ライブラリ とは
aioble はMicroPythonで使用できるBLEを用いた通信のためのライブラリです。
その名前のとおり、asyncioベースとなっており、非同期パターンを用いたプログラムの記述ができます。
しかし、今回はその部分に関してはあまり活用しておらず、ほぼ参考としているExampleのまま使用しています。
コード
以下に aioble を参考にしたデコード関数を示します。
def decode_servicedata(result, *adv_type):
if result.resp_data is None:
return None
i = 0
while i + 1 < len(result.resp_data):
if result.resp_data[i + 1] in adv_type:
yield result.resp_data[i + 2 : i + result.resp_data[i] + 1]
i += 1 + result.resp_data[i]
aioble と組み合わせてScan結果をデコードするにはこのように書きます。
_ADV_TYPE_UUID16_SERVICEDATA = const(0x16)
async def find_temp_sensor():
results = []
async with aioble.scan(5000, interval_us=30000, window_us=30000, active=True) as scanner:
async for result in scanner:
result.serviceUUID = None
result.servicePayload = None
if result.adv_data is not None and result.resp_data is not None:
for i in decode_servicedata(result, _ADV_TYPE_UUID16_SERVICEDATA):
result.serviceUUID = bluetooth.UUID(i[0:2])
result.servicePayload = i[2:len(i)]
# See if it matches UUID and has Service Data payload.
if _ENV_SENSE_UUID == result.serviceUUID and result.servicePayload is not None:
if result not in results:
results.append(result)
return results
gist にコード全体を置いておきます。
以上。
Discussion