LoginSignup
0
0

Pico WでSwitchbot Hub miniの温度と湿度を取得してZabbixに投げる

Posted at

背景

これまでRaspberry Pi 4でSwitchbot Hub miniの温度と湿度を取得してZabbixに投げていたけど、RP4の設定場所を変えたのでbluetoothが届かなくなった。
使っていないPico Wがあったので、代わりにやらせてみた。

Bluetooth

読むフレーム

RP4はbluepy、Pico Wはubluetoothを使いました。
RP4の方はインターネットに多くあるコードを使ってできました。そのコードの意味は深く理解していなかったせいで、Pico Wの最初コードではtypeの判定をしていなかった。そのためアドバタイズフレームを読んでいて、温度・湿度が含まれていませんでした。
Bluetooth LE自体を調査して、SCAN_RSPフレームを読まないといけないことを理解しました。

addr_type, addr, adv_type, rssi, adv_data = data
addr_str = ':'.join(['{:02x}'.format(b) for b in addr])
if addr_str == self.target_addr and adv_type == 4:  # SCAN_RSPフレーム
    self._parseData(adv_data)

サービスデータの取得

Switchbotのドキュメントを読んで0x16のブロックを見つける必要がありました。bluepyではそこがイテレータになっているみたいです。

i = 0
while i < len(adv_data):
    length = adv_data[i]
    type = adv_data[i + 1]

    if type == 0x16:  # サービスデータ
        uuid = bytes(reversed(adv_data[i + 2:i + 4])).hex()
        service_data = adv_data[i + 4:i + length + 1]
        return uuid, service_data

    i += length + 1
return None, None

Zabbixへの送信

RP4では cron -> python -> data.json -> fluentd -> zabbix の流れで動かしていたので、zabbixのことは全部fluentdにお任せしていましたが、Pico Wでは自前で書く必要がありました。
早速インターネットにあふれているコードを持ってきて動かしましたが送信できず、zabbixのドキュメントを読んだらヘッダーが必要とのことで、ヘッダーを付加したら成功しました。

data = {
    "request": "sender data",
    "data": [
        {
            'host': self.zabbix_host,
            'key': key,
            'value': value,
        }
        for key, value in data.items()
    ]
}
data = str(json.dumps(data)).encode('utf-8')
packet = b"ZBXD\1" + struct.pack("<II", len(data), 0) + data

ソース

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0