SwitchBot API v1.1を使って、スマートプラグ プラグミニの状態をZabbixでモニタリングできるようにした

# 背景、事の始まり
私はSwitchBotのスマートプラグミニを3カ月ほど使用してきましたが、せっかくなら電圧や消費電力といった情報を取得したいと考えました。そこで調べてみたところ、SwitchBotには開発者用APIがあり、私でも利用することが可能であることを知りました。実は私はAPIを使用したことがなかったのですが、この機会に挑戦してみることにしました。

また、Grafanaを使ってモニタリングしている方がいるというのもTwitterで知り、私もそれにならって試してみようと考えましたが、自宅には既にZabbixが導入されているため、折角ならZabbixを利用して管理することにしました。

## 調べ始め
### SwitchBotAPI v1.0でのモニタリング
どうやら同じことを考えた人は居たようです。
こちらの方は温湿度計をZabbixでモニタリングしているようですが、v1.0で利用しているみたいです。

https://satoweb.net/2021/09/switchbotonzabbix/

### SwitchBotAPI v1.1について
2022年9月にAPIのバージョンが1.1が公開されたようです。

https://blog.switchbot.jp/announcement/api-v1-1/

どうやら今後発売される製品にはAPI v1.0が対応されないようです。
主な変更点としてはAPIの認証方法が変わり、API Headerに付与する情報が増えたようです。

- v1.0の認証で必要なもの
    token（Switchbot Appで取得可能）

- v1.1の認証で必要なもの
    Authorization(v1.0と同じtokenのこと)
    sign（特定のアルゴリズムを使用してトークンと秘密鍵から生成された署名）
    t（13 桁のタイムスタンプ）
    nonce（署名する文字列に組み込むために開発者自身が生成したランダムな UUID）

v1.1になったことでSwitchBotサーバーとの通信は安全になったらしいですが、特定のアルゴリズムで計算しないと認証が出来ないので、ちょっと面倒になったみたいです。

# 環境
- Zabbix6.0
- Ubuntu22.04
- Python 3.10.6

# 手順
## tokenとクライアントシークレット(秘密鍵)を取得する
iPhoneやAndroidでSwitchBot Appをダウンロードして、公式サイトの通りにトークンとクライアントシークレットを取得してください。

https://support.switch-bot.com/hc/ja/articles/12822710195351-%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%AE%E5%8F%96%E5%BE%97%E6%96%B9%E6%B3%95

## デバイスID一覧を取得する
各デバイスのパラメータを取得する前にデバイスIDが必要になるため、それを取得していきます。
```python
import time
import hashlib
import hmac
import base64
import uuid
import requests
import pprint

def make_secret(secret_key):
    secret_key = bytes(secret_key, 'utf-8')
    return secret_key

def make_sign(secret_key, t, nonce):
    string_to_sign = '{}{}{}'.format(token, t, nonce)
    string_to_sign = bytes(string_to_sign, 'utf-8')
    sign = base64.b64encode(hmac.new(secret_key, msg=string_to_sign, digestmod=hashlib.sha256).digest())
    return sign

def make_t():
    t = int(round(time.time() * 1000))
    return str(t)

def make_nonce():
    nonce = str(uuid.uuid4())
    return nonce

#SwitchBotアプリから取得
secret_key = "your key"
token = "your token"

#Requestパラメータ作成
secret_key = make_secret(secret_key)
t = make_t()
nonce = make_nonce()
sign = make_sign(secret_key, t, nonce)

#URL指定
url = "https://api.switch-bot.com/v1.1/devices"

#APIheader作成
headers = {
    "Authorization": token,
    "sign": sign,
    "t": t,
    "nonce": nonce,
    "Content-Type": "application/json; charset=utf-8"
}

#requests処理
response = requests.get(url,headers=headers)

pprint.pprint(response.json())
```
これでデバイスIDの一覧が取得できたはずです。

```
[サンプル]
{'body': {'deviceList': [
    {
    'deviceId': '************',
    'deviceName': 'K10+',
    'deviceType': 'WoSweeperMini',
    'enableCloudService': True,
    'hubDeviceId': ''
    }
]},
 'message': 'success',
 'statusCode': 100}
```

## Pythonファイルを作成する
### デバイスのパラメータを取得するスクリプト
Pythonでパラメータを作成し、APIリクエストを実行するスクリプトを記述します。
また、後述しますがSwitchBotのデバイスIDと取得したい値のキーを引数として利用するため、引数の処理を入れています。

```python
import time
import hashlib
import hmac
import base64
import uuid

#クライアントシークレットをbytes方に変更
def make_secret(secret_key):
    secret_key = bytes(secret_key, 'utf-8')
    return secret_key

#signを作成
def make_sign(secret_key, t, nonce):
    string_to_sign = '{}{}{}'.format(token, t, nonce)
    string_to_sign = bytes(string_to_sign, 'utf-8')
    sign = base64.b64encode(hmac.new(secret_key, msg=string_to_sign, digestmod=hashlib.sha256).digest())
    return sign

#tを作成
def make_t():
    t = int(round(time.time() * 1000))
    return str(t)

#nonceを作成
def make_nonce():
    nonce = str(uuid.uuid4())
    return nonce

#リクエストのレスポンス処理（jsonへの変更とデータ型の指定）
def get_value(response):
    if response.status_code == 200:
        data = response.json()
        if key == any(["voltage","weight","electricCurrent","temperature"]):
            value = float(data["body"][key])
        elif key == any(["electricityOfDay","battery","humidity"]):
            value = int(data["body"][key])
        else:
            value = str(data["body"][key])
        return value
    else:
        value = 0
        return value

#SwitchBotアプリから取得
secret_key = "your key"
token = "your token"

#引数を格納
key = sys.argv[1]
device_id = sys.argv[2]

#必要なパラメータを作成する
secret_key = make_secret(secret_key)
t = make_t()
nonce = make_nonce()
sign = make_sign(secret_key, t, nonce)

#URL指定
url = "https://api.switch-bot.com/v1.1/devices/{}/status".format(device_id)

#APIheader作成
headers = {
    "Authorization": token,
    "sign": sign,
    "t": t,
    "nonce": nonce,
    "Content-Type": "application/json; charset=utf-8"
}

#requests処理
response = requests.get(url,headers=headers)

#レスポンス処理とデータ型変更
print(get_value(response))
```
※secret_keyとtokenの値は各個人で異なるため、個別に入力してください。

## zabbixサーバにPythonファイルを作成する
zabbixを構築しているサーバに先ほど作成したPythonファイルを配置します。
私は面倒なので`/etc/zabbix/`に保存しています。
ファイル名は任意ですが、私は`switchbot_api.py`にしています。

## zabbix_agented.confファイルに設定を追加する
Zabbix Agentの設定ファイルにUserParameterと呼ばれるカスタムアイテムの定義を行います。
UserParameterの設定構文は下記の通り
```
UserParameter=<キー名>,<スクリプトのパス>
```

zabbix_agented.confファイルの末尾に下記の通り記述します。

```
UserParameter=switchbot.api[*],/usr/bin/python3 /etc/zabbix/switchbot_api.py "$1" "$2"
```

Zabbixエージェントサービスを再起動します。
```
systemctl restart zabbix-agent.service
```

# Zabbixでの操作
## ホストの作成
設定 > ホストで「ホストの作成」をクリックします。
任意でホスト名とグループを設定します。
インターフェースはエージェントを選び、127.0.0.1を設定すればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1675077/29090ccc-c2e9-1abc-a54c-1542b3839e0b.png)
※私は後々の管理のためにSwitchBotというグループを作成しました。

## アイテムの作成
先ほど作成したホストのアイテムをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1675077/6d20dab6-0f54-e0ce-17d3-ed92be55dbd7.png)

右上のアイテムの作成をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1675077/21ecc689-1c19-b865-6154-802b79e7a020.png)

任意の名前を設定します。
キーには`switchbot.api[key,deviceID]`を設定します。
取得したい値のkeyは[SwitchBot公式](https://github.com/OpenWonderLabs/SwitchBotAPI#hub-hub-plus-hub-mini-hub-2)が出しています。
今回は電圧を取得するのでvoltageを設定しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1675077/36a84f68-5d8c-5439-6c11-950f52fb90e1.png)
データ型についても任意で設定しますが、今回は浮動小数点数が含まれるので数値（浮動小数）を設定しています。


ページの一番下にテストボタンがあるのでクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1675077/c2b9aaf6-7f97-d9a6-52a4-4b0856a88995.png)

下図が出てきたら「値の取得とテスト」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1675077/e3a52b2c-2e26-1d25-de0f-0d6e9e26995c.png)

無事に値が取得出来たら問題ありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1675077/aced5ffe-1e52-b085-a4c2-ed5356eb9d50.png)

## グラフ閲覧
Zabbixで監視データ > 最新データから任意のSwitchBotのアイテムを選択すればグラフが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1675077/031d296a-fbde-a6b0-279b-02ce29732c8c.png)

ダッシュボードを変更して、各プラグの状況をモニタリングしてもいいかもですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1675077/ac4d9df2-447d-4fe1-2139-b51ce16135ce.png)

# 最後に
初めてAPIを使いましたが、中々奥深いものがありますね。
どうやらSwitchBotのAPIは機器の操作もできるらしいので、次は温湿度計の値を取得して、それをトリガーにエアコンの温度設定を自動で変更するとかやってみたいですね。

今回の記事が少しでも皆様のためになりますように。