スイッチボットプラグミニの消費電力をBLEで読み取る(Bookworm対応)

スイッチボットプラグミニ PC/デジモノ

スイッチボット温湿度計のデータをBleakを用いて取得する方法は以前紹介しました。
今回はスイッチボットプラグミニのデータを扱ってみたいと思います。
公式APIを使う方法は以前取り上げましたが、コマンドの発行数に限度があったりして使いにくいのでBLEでアドバタイズされている情報を拾ってみます。

準備

必要なライブラリのインストール準備

今回検証に使用したのはRaspberryPi5(8GB) RasperryPiOS Bookworm 64bit Liteです。

Raspberrypi5 8G ラズベリーパイ5 技適取得済マーク入り商品

Raspberrypi5 8G ラズベリーパイ5 技適取得済マーク入り商品

12,700円(09/10 09:39時点)
Amazonの情報を掲載しています
$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経由でできるらしいですがそれはまた今度。

 

コメント