SwitchBot温湿度計をGrafanaで可視化

Bluetoothで通信できる"SwitchBot温湿度計"を利用して、Goで温湿度を取得・Prometheusへメトリクスを投げ込み、Grafanaで可視化する話です。

DSC 7339

説明書によると単4電池2本で1年持つらしいです。すごい。

DSC 7340

一応URL https://www.switchbot.jp/meter

BLE

よく出回っている他の温湿度計(tuya home等)は、ほとんどBLE通信が暗号化されており、利用者が自由に内容を参照することが出来ません。 生活周期だとかのパーソナルデータなので、当然といえば当然の流れなんですが寂しい。 そんな中、SwitchBotは技適付き・暗号化なしというプログラマーフレンドリーな仕様です。

ペイロード内容も公開されており、その内容は非常にシンプルです。 サービスUUID cba20d00-224d-11e6-9fb8-0002a5d5c51b で8byte読んで、その内容をパースするのみです。 詳しい内容は以下を参照してください。

https://github.com/OpenWonderLabs/python-host/wiki/Meter-BLE-open-API

ハマった箇所としては、PassiveScanだとServiceDataを返さないようで、データを取得するためにはActiveScanを行う必要が有るということでした。 こちらの記事で記述されており非常に助かりました。

https://qiita.com/warpzone/items/11ec9bef21f5b965bce3

Goでの記述

Pythonでの取得コードは上のGitHubリポジトリで公開されているのですが、どうしてもGoで書きたいという気持ちがあったので温湿度を取得するコードをGoで記述しました。 Prometheusへとストアしたいので、Exporterの実装も合わせて行っています。

https://github.com/kamijin-fanta/temperature-collector/blob/master/main.go

最初はBLEライブラリに https://github.com/paypal/gatt を利用しようと思っていたのですが、ActiveScanを行う方法が無く、独自のHCIコマンドを送信するのも難しそうなので https://github.com/go-ble/ble を利用しています。

Prometheus, Grafana

Raspberry Pi 3で動かしたかったので、 GOOS=linux GOARCH=arm GOARM=7 をつけてビルドを行い、以下のような雑なSystemd Unitファイルを作成してデーモンとして動作させます。

#cat /etc/systemd/system/temperature-collector.service 
[Unit]
Description=Temperature prometheus collector
After=network-online.target

[Service]
Type=simple
Restart=always
LimitCORE=infinity
ExecStart=/home/pi/temperature-collector_armv7
PermissionsStartOnly=true
StandardOutput=null

[Install]
WantedBy=multi-user.target

適当にPrometheusの設定も追記しておきます。

scrape_configs:
  - job_name: 'temperature'
    static_configs:
      - targets:
        - hostname:2112

Grafanaでダッシュボードを用意してやれば完成です。

temperature collector 2021 03 17 00 06 36

温度計本体は、適当に袋を被せて室外に置いてみました。