以前からSwitchBotのMeterPlusをv1.0を使ってHTTPエージェントアイテムで取得していました。
今回新にMeterProを追加しようとしたところAPIのバージョンが上がって認証方法が変更になっていました。
調べてみると外部にPythonコードを置いてそちら経由で取得しているようなのですが、従来通りZabbixの機能だけで取得できないか試してみました。
なお、この記事におけるZabbixのバージョンは7.2となっています。
SwitchBotのAPI認証仕様
v1.1になって認証の仕様が変更になり、シークレットキーを利用した署名が必要となりました。
こちらの
https://github.com/OpenWonderLabs/SwitchBotAPI
を確認するとHMAC-SHA256で行えばいいようです。
それ以外にも13桁のタイムスタンプ、ランダムなUUIDも必要です。
Zabbixのスクリプトアイテムの仕様
Zabbixではスクリプトを利用することが出来ますが、基本的には保存前処理で利用することが多いと思います。しかし保存前処理ではAPIからのデータ取得時に署名を付与することはできません。
そこでスクリプトアイテムを利用します。
スクリプトアイテムはスクリプトからの戻り値をアイテムの取得値として扱えるのでうまくスクリプトが組めれば目的を達成できそうです。
ただ、Zabbixで利用できるスクリプトがJavascriptベースであるのはわかるのですが、どこまで使えるかイマイチわかりにくいので手探りで確認していきます。
https://www.zabbix.com/documentation/7.0/en/manual/config/items/preprocessing/javascript/javascript_objects
このページにある情報から、hmac('<hash type>',key,data)
でHMAC-SHA256のハッシュ値が生成できそうです。btoa(data)
でBase64にコンバートできそうです。
完成したスクリプトアイテムのスクリプト
こちらが最終的に動作したスクリプトアイテムのスクリプトになります。
const token = "{$TOKEN}";
const secret = "{$SECRET}";
const t = Date.now();
var d = Date.now();
const nonce = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
const data = token + t + nonce;
var sign0 = hmac('sha256', secret, data);
var sign1 = new Uint8Array(sign0.length / 2);
for (var i = 0; i < sign0.length; i += 2) {
sign1[i / 2] = parseInt(sign0.substring(i, i + 2), 16);
}
var sign2 = btoa(sign1).toUpperCase();
var request = new HttpRequest();
request.addHeader("Authorization:"+token);
request.addHeader("sign:"+sign2);
request.addHeader("nonce:"+nonce);
request.addHeader("t:"+t);
request.addHeader("Content-Type:application/json");
return request.get("https://api.switch-bot.com/v1.1/devices/{$DEVICEID}/status");UUIDはZabbixのスクリプトで利用できる生成方式を参考にnonceという名前でヘッダにセットして送信します。
注意点としてはhmac関数を利用して返されるHMACハッシュは16 進形式の文字列であるという点です。
これをそのままBase64にしても全く違う結果になってしまいます。
そこで16進数形式の文字列をUnit8Arrayに入れることでバイナリ形式として扱っています。
このサンプルを使ったスクリプトアイテムでは返ってきた値を文字列として保存しています。
このスクリプトアイテムを依存先として依存アイテムを作成し、そこで保存前処理でJsonから温度や湿度のデータを数値で取り出すことが出来ます。
その他の注意点
SwitchBotのAPIでは一日のリクエスト数を10,000回に制限しています。
このサンプルを利用したアイテムでは取得タイミングを5分に設定していますが、たくさんのデバイスを監視する場合は総リクエスト数で10,000回を下回るように設定する必要があります。
Zabbixのマクロ設定
サンプルを見ると{$TOKEN}、{$SECRET}、{$DEVICEID}の3つがマクロになっています。
私はスクリプトアイテム、依存アイテム(取得したい数値データ数分用意する)をセットにしてデバイスの種類ごとにテンプレートを作っています。
そのテンプレートを適用している監視ホストごとに3つのホストマクロを設定しています。
このあたりは別途、運用に合わせて検討してみてください。
特に{$TOKEN}、{$SECRET}は扱いに気をつけなければいけない値なのでSecretユーザーマクロにする等、検討していただけたらと思います。
最後に
本記事を参考に快適なSwitchBot生活を送れたら幸いですが、なにか不具合等あったとしても責任は取れませんのであしからずご了承ください。