KUSONEKOの見る世界

SwitchBot温湿度計の値をLinuxで取得しLINEへ通知

我が家に家族が増え、猛暑が続く中、部屋の温度と湿度を徹底管理することになりました。

どこからでも温湿度が確認でき、異常をアラート通知できるものが良いと考え、SwitchBot 温湿度計プラスを買いました。

しかし、使ってみるとアラート通知はクラウドに繋がっている必要があり、クラウドに繋げるにはSwitchBotハブミニも必要とのこと。
SwitchBotハブミニ無しでもアラートや温湿度のグラフ化もできないかと色々調べ、実現することができましたので、メモを残しておきます。

サーバ環境:
CentOS Stream 8
Zabbix 5.0.26

実現方法

SwitchBot温湿度計は、BLE(Bluetooth Low Energy)を使用し、温度湿度などの情報をスマホアプリやSwitchBotハブミニに送信しています。

Bluetoothを使用し、Linuxサーバで受信さえできれば、あとはどうにでもなります。

そこから、Linuxサーバ上のZabbixでデータを取り込み、温湿度の数値からグラフの作成とアラート情報からトリガーしアクションでLINE Notifyにメッセージを飛ばします。
LINEの通知を受け取ったら、人間が対処をするという具合です。

エアコンも自動制御できれば良いですが、今回はここまでです。

サーバのBluetooth準備

Bluetoothドングル接続

我が家のサーバのマザーボードにはBluetoothが付いていませんので、余っていたUSBのBluetoothドングルをサーバに接続します。

# tail -f /var/log/messages
kernel: usb 1-5.2: new full-speed USB device number 3 using xhci_hcd
kernel: usb 1-5.2: New USB device found, idVendor=0a12, idProduct=0001, bcdDevice=88.91
kernel: usb 1-5.2: New USB device strings: Mfr=0, Product=2, SerialNumber=0
kernel: usb 1-5.2: Product: CSR8510 A10
kernel: usbcore: registered new interface driver btusb

普通に認識してくれました。
使用したBluetoothドングルは、こちらの物です。

Bluetoothパッケージインストール&有効化

Bluetoothを使うためのパッケージをインストールします。

# dnf install bluez
========================================================================================================================
 パッケージ                アーキテクチャー           バージョン                       リポジトリー               サイズ
========================================================================================================================
インストール:
 bluez                     x86_64                     5.63-1.el8                       baseos                     1.4 M

トランザクションの概要
========================================================================================================================
インストール  1 パッケージ

サービスを有効化します。

# systemctl start bluetooth
# systemctl enable bluetooth

PythonのBluetooth Low Energy用のモジュールを使用するため、インストールする。

# pip3 install bluepy
WARNING: Running pip install with root privileges is generally not a good idea. Try `pip3 install --user` instead.
Collecting bluepy
  Downloading https://files.pythonhosted.org/packages/27/91/6cfca10bee9862f93015413cf9e6a52c3081a71f1518963396a055128f8e/bluepy-1.3.0.tar.gz (217kB)
    100% |????????????????????????????????| 225kB 1.5MB/s
Installing collected packages: bluepy
  Running setup.py install for bluepy ... done
Successfully installed bluepy-1.3.0

周囲のBluetooth機器をスキャンテスト

Bluetoothが使えようになったかをスキャンしてテストします。

こちらのソースを使用させてもらいました。

# vi btscan.py
(ソースを張り付ける)
# python3 btscan.py
(snip)
MACアドレス:cb:f7:37:**:**:**:
  アドレスタイプ:random
  RSSI:-63
  アドバタイシングデータ:
    Flags:06
    Manufacturer:**************************
    16b Service Data:****************
(snip)

SwitchBot温湿度計も見えました。

SwitchBot温湿度計プラスの値を取得

SwitchBot温湿度計プラスの温度、湿度、バッテリー残量をPythonを使ってBluetoothで取得します。

ソースは以下をそのまま使用させてもらいました。

Raspberry Piを使ってSwitchBot 温湿度計のデータをMackerelで可視化する | 高木のブログ

この記事は、「Raspberry Pi Advent Calendar 2020」16日目の記事です。 はじめに 最近、SwitchBot 温湿度計を購入しました。 いろいろ連携させるためには別でSwitchBotハブというものが必要みたいで、急遽代わりにRaspberry Piも購入しました。 (SwitchBot…

MACアドレスの部分は、スマホのSwitchBotアプリで確認し、小文字で書きます。
# vi switchbot-meter.py
(ソースを張り付ける)

実行します。

# python3 switchbot-meter.py
switchbot.meter.battery 100     1659846132.6004095
switchbot.meter.temperature     24.8    1659846132.6005688
switchbot.meter.humidity        67      1659846132.6006074

取得ができました。
ここまで出来れば、あとは何でもできますね。

       +
     +  +       / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
     ∧_∧    <  わーいSwitchBotだー! SwitchBotだー
  □r(´∀` )ワーイ ! |    何でもできるぞー
 +   ヽ    つ     \_______________
      (⌒_ノ
       し'ゝ ;;::⌒::

ZabbixでSwitchBot温湿度計プラスの値を取得

Zabbix用スクリプト作成

温度や湿度だけでなく、温度、湿度アラート情報も取得します。
アラート設定はスマホアプリ上で有効化し、範囲を指定しておきます。

SwitchBot 温湿度計プラス アラート設定

アラートは、温度、湿度それぞれHighとLowがあり、これらがTrueかFalseかを取得します。

SwitchBot 温湿度計の測定値を BLE Advertisement パケットから直接読み取る - Qiita

はじめに先日、Amazon でセールになっていたので SwitchBot 温湿度計(SwitchBot Meter) を購入しました。この機器は Bluetooth を内蔵しており、温度・湿度を本体でデジタル表示するとともに、...

上記、ソースも使わせて頂き値を取得します。

# vi switchbot-meter_zabbix.py
(switchbot-meter.pyに以下を追記する形。)
      isTemperatureHighAlert = ( servicedata[3] & 0b10000000 ) >> 7
      isTemperatureLowAlert  = ( servicedata[3] & 0b01000000 ) >> 6
      isHumidityHighAlert    = ( servicedata[3] & 0b00100000 ) >> 5
      isHumidityLowAlert     = ( servicedata[3] & 0b00010000 ) >> 4

      print( 'isTemperatureHighAlert: ' + str( bool( isTemperatureHighAlert ) ) )
      print( 'isTemperatureLowAlert: '  + str( bool( isTemperatureLowAlert ) ) )
      print( 'isHumidityHighAlert: '    + str( bool( isHumidityHighAlert ) ) )
      print( 'isHumidityLowAlert: '     + str( bool( isHumidityLowAlert ) ) )
      
(時刻は不要なので、以下を削除。)
import time

, str(time.time()

実行します。

# python3 switchbot-meter_zabbix.py
switchbot.meter.battery 100
switchbot.meter.temperature     25.9
switchbot.meter.humidity        67
isTemperatureHighAlert: False
isTemperatureLowAlert: False
isHumidityHighAlert: False
isHumidityLowAlert: False

Trueなった場合に障害検知、Falseで障害復旧とします。

Zabbix Agentで実行テスト

Zabbix Agentの設定変更。

# vi /etc/zabbix/zabbix_agentd.conf
(デフォルト3秒から変更)
Timeout=10
(最後に追記)
AllowKey=system.run[python3 /root/switchbot-meter_zabbix.py]

ZabbixでPythonを実行するには、rootユーザある必要があります。

# vi /usr/lib/systemd/system/zabbix-agent.service
(ユーザ、グループを変更)
User=root
Group=root
# systemctl daemon-reload
# systemctl restart zabbix-agent

作成したスクリプトをZabbix Agentで実行します。

# zabbix_agentd -t "system.run[python3 /root/switchbot-meter_zabbix.py]"
system.run[python3 /root/switchbot-meter_zabbix.py] [t|switchbot.meter.battery  100
switchbot.meter.temperature     26.5
switchbot.meter.humidity        66
isTemperatureHighAlert: False
isTemperatureLowAlert: False
isHumidityHighAlert: False
isHumidityLowAlert: False]

Zabbix グラフ作成

SwitchBot温湿度計プラスの値の取得は、マスターアイテムで一括取得し、依存アイテムでマスターから必要な値を取ることにします。

アイテム作成(マスター)

[設定]→[ホスト]→[Zabbix server]→[アイテム]
[アイテムの作成]を押下。

名前:SwitchBot Meter Master
タイプ:Zabbixエージェント
キー:system.run[python3 /root/switchbot-meter_zabbix.py]
データ型:文字列
監視間隔:1m

[追加]を押下。

アイテム作成(依存アイテム)温湿度

[設定]→[ホスト]→[Zabbix server]→[アイテム]
[アイテムの作成]を押下。

名前:SwitchBot Meter Temperature
タイプ:依存アイテム
キー:switchbot.meter.temperature
マスターアイテム:SwitchBot Meter Master
データ型:数値(浮動小数)
単位:℃

保存前処理
名前:正規表現
パラメータ:switchbot\.meter\.temperature.+?(\d.+\.\d)
               :\1

[追加]を押下。

湿度も作成する。

アイテム作成(依存アイテム)アラート

アラートは以下のように作成する。

名前:SwitchBot Meter Temperature HighAlert
タイプ:依存アイテム
キー:switchbot.meter.temperaturehighalert
マスターアイテム:SwitchBot Meter Master
データ型:文字列

保存前処理
名前:正規表現
パラメータ:isTemperatureHighAlert:.+?(True|False)
               :\1

[追加]を押下。

Temperature LowAlert、Humidity HighAlert、Humidity LowAlertも作成する。

グラフ作成

[設定]→[ホスト]→[Zabbix server]→[グラフ]
[グラフの作成]を押下。

名前:SwitchBot Meter
アイテム: Zabbix server: SwitchBot Meter Temperature とSwitchBot Meter Humidityを追加する。
    [追加]を押下。
    アイテムで作成した名前を選択。
    グラフの形式:線
    Y軸:温度は左、湿度は右
    色:お好きな色に

[追加]を押下。

SwitchBot 温湿度計プラス Zabbixグラフ

Zabbix 障害通知

トリガー作成

[設定]→[ホスト]→[Zabbix server]→[トリガー]
[トリガーの作成]を押下。

名前:SwitchBot Meter Temperature High Alert
深刻度:重度の障害
条件式:{Zabbix server:switchbot.meter.temperaturehighalert.last()}="True"
正常イベントの生成:復旧条件式
復旧条件式:{Zabbix server:switchbot.meter.temperaturehighalert.last()}="False"

[追加]を押下。

Temperature LowAlert、Humidity HighAlert、Humidity LowAlertも作成する。

アクション設定

[設定]→[ホスト]→[アクション]
[Report problems to Zabbix administrators]を押下。

有効:チェックを入れる

[更新]を押下。

LINEに通知するメッセージを編集したい場合は、ここの[実行内容]で修正する。
以下のような変数をメッセージに入れることで、温度と湿度を送ることもできる。

Temperature: {Zabbix server:switchbot.meter.temperature.last()}
Humidity: {Zabbix server:switchbot.meter.humidity.last()}

LINE通知用スクリプト作成

通知に使用するスクリプトを作成する。

以下のスクリプトを参考にさせて頂きました。
https://github.com/kenzo0107/Zabbix3-LineNotify

# vi /usr/lib/zabbix/alertscripts/line_zabbix.sh
#!/bin/bash

# LINE Notify Token - Media > "Send to".
TOKEN="$1"

# {ALERT.SUBJECT}
subject="$2"

# {ALERT.MESSAGE}
message="$3"

# Line Notify notice message.
notice="
${subject}
[Message]: ${message}"

curl https://notify-api.line.me/api/notify -H "Authorization: Bearer ${TOKEN}" -F "message=${notice}"
# chmod +x /usr/lib/zabbix/alertscripts/line_zabbix.sh

Zabbix用 LINEトークルーム作成

Zabbixからの通知を載せるLINEのトークルームを作成する。
作成できれば、スマホからでもWindowsからでも良い。

[トーク]→[💬+]→[グループ]をタップ。

[LINE Notify]を選択し、[次へ]をタップ。
名前は適当に入れ、[作成]をタップ。

LINE Notify トークン取得

以下にアクセスする。
https://notify-bot.line.me/ja/

右上のログインから普段使っているユーザーでログインする。

右上からマイページに移動する。

[トークンを発行する]を押下。 
トークン名を適当に。
トークルームを作成したものを選択。
[発行する]を押下。

発行したトークンを控えておく。

メディアタイプ設定

[管理]→[メディアタイプ]
[メディアタイプの作成]を押下。

名前:Line
タイプ:スクリプト
スクリプト名:line_zabbix.sh
スクリプトパラメータ:{ALERT.SENDTO}
                             :{ALERT.SUBJECT}
                             :{ALERT.MESSAGE}

[追加]を押下。

ユーザー設定

[管理]→[ユーザー]
[Admin]を押下。

[メディア]を押下。

[追加]を押下。

タイプ:Line
送信先:発行したトークンを入れる

[追加]を押下。

[更新]を押下。

LINE受信

SwitchBot温湿度計プラスの温度をアラート範囲にする。
アラート範囲外に戻す。

以下の通り、発生と復旧をLINEで受信できました。

SwitchBot 温湿度計プラス Zabbix LINE通知

SwitchBotハブミニを持っている人は

SwitchBot温湿度計プラスが、ハブミニ経由でクラウドに接続出来ていれば、LinuxでBluetoothを使わなくても、curlで温湿度の取得ができます。

SwitchBotアプリの[プロフィール]→[設定]
アプリバージョンをタップしまくる。
表示された[開発者向けオプション]でクラウドのトークンを取得できます。

[温湿度計プラス]→[設定]→[デバイス情報]
でMACアドレスを確認できます。

あとは、以下のようにcurlで情報が取得できます。(私はハブミニを持っていないので、温度湿度は出てきません)

curl -s -X GET "https://api.switch-bot.com/v1.0/devices/MACアドレスの大文字コロン無し/status" -H "Authorization: トークン" -H "Content-Type: application/json; charset=utf8" | jq
{
  "statusCode": 100,
  "body": {
    "deviceId": "CBF737******",
    "deviceType": "MeterPlus"
  },
  "message": "success"
}

トラブルメモ

Python実行時、SwitchBot温湿度計の値が表示されない

MACアドレスが大文字になっているかもしれません。
小文字で書く。

Python実行時、Tracebackが出る

Traceback (most recent call last):
  File "swithbot-meter2.py", line 34, in <module>
    scanner.scan(10)
  File "/usr/local/lib/python3.6/site-packages/bluepy/btle.py", line 854, in scan
    self.stop()
  File "/usr/local/lib/python3.6/site-packages/bluepy/btle.py", line 803, in stop
    self._mgmtCmd(self._cmd()+"end")
  File "/usr/local/lib/python3.6/site-packages/bluepy/btle.py", line 312, in _mgmtCmd
    raise BTLEManagementError("Failed to execute management command '%s'" % (cmd), rsp)
bluepy.btle.BTLEManagementError: Failed to execute management command 'scanend' (code: 11, error: Rejected)<module>

bluezが入っていないかもしれません。

Zabbix Unsupported item key

system.run[python3 /root/switchbot-meter_zabbix.py] [m|ZBX_NOTSUPPORTED] [Unsupported item key.]

zabbix_agentd.confに、AllowKey=が正しく記述できているか確認。

Zabbix Timeout while executing a shell script

system.run[python3 /root/switchbot-meter_zabbix.py]zabbix_agentd [197296]: Warning: Failed to execute command "python3 /root/switchbot-meter_zabbix.py": Timeout while executing a shell script.
 [m|ZBX_NOTSUPPORTED] [Timeout while executing a shell script.]

値の取得に時間が掛かることがあるため、zabbix_agentd.confのTimeout=を長くする。

【未解決→解決】日本語が使用できない

  • トリガー名を漢字にすると、障害発生時、ダッシュボード等で漢字が?になる
  • アクションの実行内容で漢字を使用すると、LINEメッセージの漢字が?になる
    ただし、メディアタイプのテストからだと、漢字が送れる。

→ Zabbix 5.0.28にバージョンアップした所、漢字でも問題なく使えるようになりました。

5.0.275.0.28のどちらかで修正が加えられました。
怪しいのは以下です。

ZBX-21385     Fixed setting of character set for MySQL and MariaDB when utf8mb3 is missing while utf8 is present

参考