事の始まり
Switchbotのデータを読み込んだり、操作するために必要なことを調べていたら、Switchbot APIを利用するのが良さそうだと言うことで、【SwitchBot】基本的な API の使い方と言う記事に辿り着きました。とりあえず試してみようと思ったのですが、なぜかエラーが発生。コピペだけで済ましているので、エラーの本質的な理由が分かりませんでした。
何が悪かったのか、結論
簡単に書くと、参考記事の時とAPIのバージョンが変わっていました。バージョンが変わっていようと、今でも古いv1.0は残っているので、とりあえず動作しないかと色々原因を追求したところ、v1.0のAPIでは新しいデバイス(当方の環境ではSwitchbotキーパッドタッチが該当)の情報を返すことができないと言うのが理由でした。新しめのデバイスを利用するには否が応でもv1.1に対応する必要がありました。
動作確認環境
- Linux(Raspberry Pi) or macos
- Python3(ちょっと修正すればPython2でも動くはずです)
Switchbot API V1.1について
Swithbot APIの最初の方の記述を見ると、結構最近にAPIの仕様が変わったようです。以前のバージョンではtoken(APIキー)だけで利用でしたのですが、V1.1では
- token
- secret(Switchbot App V6.14以降で取得可)
- t(13桁のタイムスタンプ)
- sign(特定のアルゴリズムで作成した文字列)
- nonce (利用するプログラムで生成したUUIDキー)
これらが必須の情報だそうです。
上記APIのページにはPython(2or3)とjavascriptでの作成サンプルがありましたので、これをまんま利用しました。
#!/usr/bin/env python3
# coding: utf-8
''' Create Switchbot sign header '''
import time
import hashlib
import hmac
import base64
import json
import uuid
def gensign(token, secret):
'''
Generate Switchbot API v1.1 sign header
Args:
token: string :copy and paste from the SwitchBot app V6.14 or later
secret: string :copy and paste from the SwitchBot app V6.14 or later
Returns:
Switchbot API v1.1 sign header
'''
nonce = str(uuid.uuid4())
t = int(round(time.time() * 1000))
string_to_sign = '{}{}{}'.format(token, t, nonce)
string_to_sign = bytes(string_to_sign, 'utf-8')
secret = bytes(secret, 'utf-8')
sign = base64.b64encode(hmac.new(secret, msg=string_to_sign, digestmod=hashlib.sha256).digest())
header={}
header["Authorization"] = token
header["sign"] = str(sign, 'utf-8')
header["t"] = str(t)
header["nonce"] = nonce
return header
(https://gist.github.com/iCarrot0605/472dd85f887985a67b9f956070cf9864)
コードの難しいことは分かりませんが、「token、t、nonce」を繋ぎ合わせた文字列をsecretを使って署名?することでsignは出来上がります。
nonceはuuid.uuid4()を使ってみました。元々のサンプルにあるように何も指定しなくても動作します。
tokenとsecretはSwitchbot App(V6.14以降)で、「プロフィール」>「設定」へと進み、「アプリバージョン」のフィールドを10回タップすると表示される「開発者向けオプション」から取得することができます。
APIを利用してみる
サンプルコードは【SwitchBot】基本的な API の使い方にあるコードを少し修正しました。上に書いたコード(switchbot_sign.py)と同じディレクトリに以下のコードを置きます。
#!/usr/bin/env python3
# coding: utf-8
import requests
import json
import switchbot_sign
token = '' # copy and paste from the SwitchBot app V6.14 or later
secret = '' # copy and paste from the SwitchBot app V6.14 or later
header = switchbot_sign.gensign(token, secret)
# Get all device information in your switchbot hub
response = requests.get("https://api.switch-bot.com/v1.1/devices", headers=header)
devices = json.loads(response.text)
# Get switchbot bot "deviceId" in all device information
bots_id = [device["deviceId"] for device in devices['body']['deviceList'] if "Bot" == device["deviceType"]]
# Get all switchbot bot power state and output on your display
for bot_id in bots_id:
response = requests.get("https://api.switch-bot.com/v1.1/devices/" + bot_id + "/status", headers=header)
bot = json.loads(response.text)
power = bot['body']['power']
print("bot id (" + bot_id + ") power : " + power)
あとは
python3 (保存したスクリプト名)
実行結果
bot id (XXXXXXXX) power : off
となるはずです。
APIの利用について
1日に利用できる回数が10000回です。上記のサンプルスクリプトでは2回APIを利用しています。よっぽどのことがないと使い切ることはないと思いますが。
まとめ
まとめというよりは初めてのQiitaでの記事作成にMarkdown記法の勉強から始まりました。ちゃんとした体裁になっているかも良く分かりませんが、誰かの参考になれば幸いです。