この文書の目的
switchbot の Web API は現時点(2023年3月)から6ヶ月前に version 1.1 が公開され、旧バージョンの 1.0 は今後新製品への対応がなされないと告知された。
注意事項
APIご利用の際は以下の点にご注意ください
今後はv1.1の利用が標準となるようだが、現時点で、node-redから switchbot の Web API v1.1 を叩く方法を解説した文書がweb上に無いようである。
そのような状態でいろいろ試して失敗しながら数時間にわたって 401 Unauthorized エラーに悩まされ続けた末に成功した。
同じようなことをやろうとする人が費やすことになる無駄な時間を無くすためにこれを書いた。
実行環境
OS: windows 10 64bit 22H2
node.js: v18.15.0
node-red: v3.0.2
モジュールの準備
switchbot API v1.1 のリクエストヘッダを構成するには crypto モジュールを使う必要がある。
色々と試した現在の環境では、npm で crypto モジュールをインストールする必要は無いように見えるが、環境によってはインストールする必要があるかもしれない。
フロー配置
上図のように、inject -> function -> http request -> debug をシリーズでつなぐ。
inject (開始トリガ)
デフォルトのままでOK。
function (リクエストヘッダ生成)
まず設定タブを開き、
追加 をクリックして
crypto モジュールを追加する。GUIでモジュール追加ができるようになっていたのは知らなかった。
次に コード タブを開き、以下のようにコードを追加する。
const token = "switchbotアプリで取得できる トークン をここに記入"; const secret = "switchbotアプリで取得できる クライアントシークレットをここに記入"; const t = Date.now(); const N = 16; const nonce = crypto.randomBytes(N).toString('base64').substring(0, N); // const nonce = ""; //でも問題ない。 const data = token + t + nonce; const signTerm = crypto.createHmac('sha256', secret) .update(Buffer.from(data, 'utf-8')) .digest(); const sign = signTerm.toString("base64"); // header情報をmsgに入れて次の http request ノードに送信 msg.token = token; msg.sign = sign; msg.t = t; msg.nonce = nonce;
http request
下図のように構成する。なお、URLの v1.1 を v1.0 に変更しても問題なく動作する。今回はデバイスのリストを見たいだけなのでメソッドにGET、URLの最後に devices を指定する。
debug
出力を全部見たいので下図のように構成する。
実行
デプロイをクリックして
inject(タイムスタンプ)ノードの□ボタンを押すと
debugノードの statusCode が 100 に変わって成功したことが分かる。
http リクエストに失敗すると、statusCode が 100 以外のエラーになって悲しい。
画面右のdebugタブを開くと
msg オブジェクトの概略が表示されており、これをクリックすると
様々なデバイスのIDなどが確認できる。このIDを使って、適切にPOSTリクエストを構成すればデバイスの操作などを行うことができる。ここまで成功していれば失敗する要因はほぼ無い。
nonce についての補足
ここから先は読まなくて良い蛇足である。
function ノードの nonce は定数や固定文字列でも問題ないようである。公式のAPIの説明でも
const nonce = "requestID";
と固定文字列が指定されている。
語源は何なのか
nonce とは何なのか日本語のwikipediaで調べてみて、意味はわかったが語源はわからなかった。
英語のwikipediaに語源を含めた答えがあった。
a nonce is an arbitrary Number that can be used just ONCE in a cryptographic communication.
(NとONCEのキャピタル化は筆者による)
日本語に訳すと:
「nonceとは、暗号通信で一度だけ使用できる任意の数値のことです。」
というわけで、せっかく node-red で crypto モジュールを使えるようにしたので、nonce の意味ないし目的に従って毎回ランダムに変化する文字列を指定するようにしたのが今回のサンプルコードである。
matter 対応には関係するか?
知らない。
いろいろな業種で様々な規格が乱立している。
switchbot が関連するであろう「スマートホーム」のコンテクストの中で、 matter と称される団体の標準化活動がある。
switchbot もその標準化活動の一員として名を連ねているようだ。
Web API も標準化されていくのだろうか?
まとめ
switchbotのAPIのドキュメントと、node-redのドキュメントはよく書けていて、賢い人間が見れば何の問題もなくアプリを書けるようにはなっていると思う。
しかし、俺のようなアホはこれらを見ても数時間の試行錯誤を要するのが現状である。
このへんは AI がなんとかするのかもしれないが、AIが今よりもう少しだけ賢くなってしまったら、そもそも俺のようなアホがコードを書くという行為が必要無くなるのかもしれない。