スイッチボット温湿度計のデータをBleakを用いて取得する方法は以前紹介しました。
今回はスイッチボットプラグミニのデータを扱ってみたいと思います。
公式APIを使う方法は以前取り上げましたが、コマンドの発行数に限度があったりして使いにくいのでBLEでアドバタイズされている情報を拾ってみます。
準備
必要なライブラリのインストール準備
今回検証に使用したのはRaspberryPi5(8GB) RasperryPiOS Bookworm 64bit Liteです。
$sudo apt update $sudo apt upgrade $sudo apt -y install libglib2.0-dev libbluetooth-dev $sudo apt -y install python3-dev $sudo apt -y install python3-pip
仮想化環境の準備
仮想化環境を準備します。ここではホームディレクトリ以下に作成していますが、各自お好きな場所に。
$python3 -m venv ~/bleak-env $source ~/bleak-env/bin/activate $pip install bleak
プログラムリスト
BLEのアドバタイズデータの仕様はこちらで公開されています。
SwitchBotAPI-BLE/devicetypes/plugmini.md at latest · OpenWonderLabs/SwitchBotAPI-BLE
SwitchBot BLE open API. Contribute to OpenWonderLabs/SwitchBotAPI-BLE development by creating an account on GitHub.
これを見るとManufacturerの12-13バイト目に電力情報が乗っているようです。
しかし、Bleakをつかってアドバタイズデータ(Manufacture)を受信した場合は先頭のUUID2バイト分は捨てられてしまいますので、実質的に10-11バイト目にデータが入っていることになります。
で、プログラムは以下のようになります。
python (sbpm.py)
import asyncio import sys from bleak import BleakScanner import binascii macaddr = sys.argv[1].lower() power = None async def run(): scan_complete = asyncio.get_event_loop().create_future() def parse_advertisement_data(advertisement_data): global power manufacturer_data = advertisement_data.manufacturer_data if not manufacturer_data: return raw_data = next(iter(manufacturer_data.values())) #print("Raw Manufacturer Data:", binascii.hexlify(raw_data)) if len(raw_data) < 12: return # データ長が足りない場合はスキップ onoff = (raw_data[7] >> 7)&0x01 byte10 = raw_data[10] byte11 = raw_data[11] power = (((byte10 & 0x7F) << 8) + byte11)/10.0 if power is not None and not scan_complete.done(): print(f"{onoff},{power}") scan_complete.set_result(True) def detection_callback(device, advertisement_data): if device.address.lower() == macaddr: parse_advertisement_data(advertisement_data) scanner = BleakScanner(detection_callback,scanning_mode="active") await scanner.start() try: await asyncio.wait_for(scan_complete, timeout=10.0) except asyncio.TimeoutError: print("タイムアウトしました。デバイスが見つかりません。") await scanner.stop() asyncio.run(run())
実行方法
(bleak-env) hoge@raspberrypi:~ $ python3 sbpm.py 'aa:aa:aa:aa:aa:aa' 1,12.0
カンマ区切りの最初のデータが、スイッチが入っているかどうかです。1ならON,0ならOFFです。
次のデータが消費電力(W)です。消費電力が反映されるまでにはラグがあるようなので、スイッチがOFFでも消費電力が表示される場合やその逆もあります。
bashスクリプトを使う方法
使用する仮想環境を指定して実行する方法です。
#!/bin/bash SCRIPT_DIR=`dirname $0` cd $SCRIPT_DIR #引数(MACアドレス) macaddr=$1 # 仮想環境のパス VENV_PATH="./bleak-env" # 実行したい Python スクリプト SCRIPT_PATH="./sbpm.py" # 仮想環境の Python を使って実行 "$VENV_PATH/bin/python" "$SCRIPT_PATH" $macaddr
まとめ
これでデータの取得ができましたね。
スイッチのON/OFFもBLE経由でできるらしいですがそれはまた今度。
コメント