Bluetooth ワットチェッカー(RS-BTWATTCH2)で遊ぶ with Raspberry Pi 4

殴り書きなので雑です。。。

目次

  1. 本日のおもちゃ
  2. やりたいこと・できたやつ
  3. 事前準備
  4. 仕様とペイロード
  5. 実際に送信してみる
  6. 参考にしたもの

本日のおもちゃ

Bluetoothワットチェッカー RS-BTWATTCH2[RATOC]

スマホアプリから Bluetooth 経由で電圧・電流・消費電力をモニターできるすごいワットチェッカー!
スマートスイッチ機能も付いているらしいのでいろいろ遊べそうなんだけれど、
専用アプリからしか操作できないので扱いづらいのがちょっと難点。。。
今回は仕様を調べて公開してくれていた方がいたので、それをもとにRaspberry Pi で動作するツールキットを作ってみました。

やりたいこと・できたやつ

・電圧 / 電流 / 消費電力を取得できるようにする
・スマートスイッチ機能を操作できるようにする
・L チカ(専用アプリの「LED を点滅する」ボタン相当の機能)
・取得結果を Mackerel に投稿

👇

事前準備

あらかじめ Bluetooth を使用可能にした状態で RS-BTWATTCH2 とペアリングしておく。

# bluetoothctl 
[NEW] Controller 00:10:20:30:40:50 pi [default]
[bluetooth]# power on
Changing power on succeeded
[bluetooth]# scan on
Discovery started
[CHG] Controller 00:10:20:30:40:50 Discovering: yes
[NEW] Device DD:C8:BA:12:34:56 BTWATTCH2_1234
[bluetooth]# pair DD:C8:BA:12:34:56
Attempting to pair with DD:C8:BA:12:34:56
[CHG] Device DD:C8:BA:12:34:56 Connected: yes
Request PIN code
[agent] Enter PIN code: 0000
[CHG] Device DD:C8:BA:12:34:56 Paired: yes
Pairing successful
[bluetooth]# trust DD:C8:BA:12:34:56
Changing DD:C8:BA:12:34:56 trust succeeded

(Arch Linux ARM をインストールした Raspberry Pi 4 で Bluetooth デバイスが見えない問題があったけれどそれはまた別のエントリーで…)

仕様とペイロード

RS-BTWATTCH2 は、Bluetooth Low Energy の GATT (Generic Attribute Profile) を使用してデータのやり取りをしている。
GATT の説明についてはキリがないので省きます、ここ とか ここ が詳しいかも。
BlueZ に同梱の GATT クライアントツール (btgatt-client) を使って作業します。

BTWATTCH2 ではコマンド送受信用の Service があり (6e400001-b5a3-f393-e0a9-e50e24dcca9e) その下に送信チャネル (6e400002-b5a3-f393-e0a9-e50e24dcca9e) と受信チャネル (6e400003-b5a3-f393-e0a9-e50e24dcca9e) があるので、受信チャネルの通知(Characteristic value notification)をオンにして送信チャネルに書き込めば OK。シンプル。
なお、送信フォーマットについては以下の通り、

CMD ヘッダー(0xAA固定) +
ペイロード長(固定、2バイト) +
ペイロード(可変) +
CRC8(生成多項式 X8 + X7 + X2 + 1)

ペイロードは現在判明しているもので以下の通り、

・0x01(RTC設定命令)(※)
・0x08(計測結果リクエスト)
・0xA7 0x00(スマートスイッチオフ)
・0xA7 0x01(スマートスイッチオン)
・0x3E 0x01 0x02 0x02 0x0F(Lチカ)

※0x01 の後に時刻を記述する、リトルエンディアンなので後ろから

RTC 設定命令(0x01) +
秒分時(それぞれ1バイト、計3バイト) +
日月年(月は0から始まる、年は1900年からの差分、それぞれ1バイト、計3バイト) +
曜日(0x00〜0x06、日曜日から開始?)

例(2020/12/31 23:59:59 の場合):
0x01 0x3B 0x3B 0x17 0x1F 0x0B 0x78 0x04

実際に送信してみる

# btgatt-client -d [device mac address] -t random -v


接続すると Service とそれに付随する Characteristic が見える。
まず受信チャネルの通知をオンにする、これをしないと応答が取れない。
6e400003-b5a3-f393-e0a9-e50e24dcca9e の value は 0x001f なので、これを register-notify する。

あとは、送信チャネルの 0x001d にペイロードを書き込む、今回は計測結果リクエストを送信してみる。

[GATT client]# register-notify 0x001f
Registered notify handler!
Registering notify handler with id: 1
[GATT client]# write-value 0x001d 0xaa 0x00 0x01 0x08 0xb3
Write successful
        Handle Value Not/Ind: 0x001f - (20 bytes): aa 00 1b 08 00 10 27 26 66 00 00 18 0b 2f 51 00 00 e8 cc ad
        Handle Value Not/Ind: 0x001f - (11 bytes): 74 00 00 2e 32 15 1f 0b 78 01 33

応答は送信フォーマットと基本的に同じ、先端 3 バイトは CMD ヘッダー〜ペイロード長で最後の 1 バイトが CRC8。
20 バイトを超えると分割されるっぽいので、先頭が 0xAA かどうかで判定して結合してやると良さそう。
リトルエンディアンなので、処理時には注意されたし。

4〜5 バイト目の 0x08 0x00 が計測結果リクエストの宣言。
6〜11 バイト目の 0x10 0x27 0x26 0x66 0x00 0x00 が電圧(6^16 で割る、102.149033546)。
12〜17 バイト目の 0x18 0x0b 0x2f 0x51 0x00 0x00 が電流(6^32 で割る、1.2684962973)。
18〜23 バイト目の 0xe8 0xcc 0xad 0x74 0x00 0x00 が消費電力(6^16 で割る、116.678907871)。
24〜29 バイト目は測定日時(フォーマットは RTC 設定の部分を参考)。
30 バイト目は 0x01 固定。
31 バイト目の 0x33 は CRC8。

となる。
他のコマンドもあるけど疲れたのでまた後で…。

参考にしたもの

Python GUI client for RS-BTWATTCH2 bluetooth power meter

(あれっ、ラズパイ要素あった??)