TypeScriptとNode.jsを使ってSwitchBotのDeviceListを確認する(リクエストの署名)
Table of Contents
概要
前回VSCodeでのTS、Node.jsの開発実行環境を用意しました。
これを使ってSwitchBotAPIを利用する手始めとして、登録されているデバイスを確認したいと思います。
デバイスIDが確認できれば、機器の操作や状態の確認が出来ます。
しかし、SwitchBotAPI v1.1からリクエスト送信時に署名をする必要があるようです。
環境 前提条件
Windows11
VSCode 1.84.2 拡張機能Japanese Language インストール済み
Node.js v20.10.0
PowerShell 5.1.22621.2506
SwitchBotAPI v1.1
プロジェクトのファイル構造
ルートフォルダをtsとしています。
各種jsonの設定は前回の記事を御覧ください。
プロジェクトのファイル構成
/ts/.vscode/launch.json
/ts/.vscode/tasks.json
/ts/dist/index.js
/ts/src/index.ts
/ts/package.json
/ts/tsconfig.json
Nodeモジュールのインストール
1.Powershell /ps/
npm install uuid
npm install --save @types/uuid
デバイスリストの確認
参考
https://github.com/OpenWonderLabs/SwitchBotAPI#javascript-example-code
こちらのコードを参考にTSで書いてみました。
TS初学者のため誤りや正しくない所が散見されると思いますが、ご容赦ください。
/ts/src/index.ts
import crypto from "crypto";
import https from "https";
import { v4 as uuidv4 } from "uuid";
const token: string = "YOUR_TOKEN";
const secret: string = "YOUR_SECRET";
const t: number = Date.now();
const nonce: string = uuidv4();
const data: string = token + t + nonce;
const signTerm: Buffer = crypto
.createHmac("sha256", secret)
.update(Buffer.from(data, "utf-8"))
.digest();
const sign: string = signTerm.toString("base64");
const host: string = "api.switch-bot.com";
const path: string = "/v1.1/devices";
const postOptions: https.RequestOptions = {
host: host,
path: path,
method: "GET",
port: 443,
headers: {
"Content-Type": "application/json",
Authorization: token,
sign: sign,
t: t,
nonce: nonce,
},
};
function getDevices(getOptions: https.RequestOptions): Promise<any> {
return new Promise((resolve, reject) => {
const req = https.request(getOptions, (res) => {
let queue: Buffer[] = [];
res.on("data", (chunk) => {
queue.push(chunk);
});
res.on("end", () => {
const data = Buffer.concat(queue);
resolve(data.toString());
});
});
req.on("error", (e) => {
console.log(`request error:${JSON.stringify(e)}`);
reject(e);
});
req.end();
});
}
(async () => {
try {
const result = await getDevices(postOptions);
JSON.parse(result).body.deviceList.forEach((devices: any) => {
console.log(`devices:${JSON.stringify(devices)}\n`);
});
JSON.parse(result).body.infraredRemoteList.forEach(
(infraredRemote: any) => {
console.log(`infraredRemote:${JSON.stringify(infraredRemote)}\n`);
}
);
} catch (e) {
console.log(`error:${JSON.stringify(e)}`);
}
})();
YOUR_TOKENとYOUR_SECRETを書き換える必要があります。
TokenとSecretの取得
23/12/09 現在、APIv1.1ではiOS,Androidアプリ上でTokenとSecretを取得することができます。
簡単に記述すると、プロフィール-設定-アプリバージョン、アプリバージョンを複数回タップすると開発者オプションが表示されます。開発者オプションを開くとTokenとSecretが表示されており、Secretはタップするごとに変更出来るようです。
リクエストの署名について
APIへのリクエストにはヘッダーに署名情報を付与する必要があるようです。
headers: {
"Content-Type": "application/json",
Authorization: token,
sign: sign,
t: t,
nonce: nonce,
},
Authorizationには取得したTokenをそのまま使用します。
signはtoken + t + nonceを結合した文字列をsecret使って暗号化したものをbase64に変換しています。
この点については各言語サンプルがあるため、基本的にはそれに従って処理すればよいと思います。
tはUNIX時間の整数。
nonceには任意の文字列を入れる様です。今回はUUIDを入れることでリクエストごとに変えています。
実行結果
{
"result": {
"statusCode": 100,
"body": {
"deviceList": [
{
"deviceId": "xxxx",
"deviceName": "ハブ2",
"deviceType": "Hub 2",
"enableCloudService": true,
"hubDeviceId": "xxxx"
},
{
"deviceId": "xxxx",
"deviceName": "人感センサー",
"deviceType": "Motion Sensor",
"enableCloudService": true,
"hubDeviceId": "xxxx"
}
],
"infraredRemoteList": [
{
"deviceId": "xxxx",
"deviceName": "エアコン",
"remoteType": "Air Conditioner",
"hubDeviceId": "xxxx"
}
]
},
"message": "success"
}
}
レスポンスはJsonで帰ってきます。
SwitchBotに登録した製品とHUBに設定したリモコンが表示されました。
この時確認できたdeviceIdを使って特定機器の情報の取得や命令ができます。
まとめ
今回はTSでSwitchBotAPIに署名したリクエストを送信して製品のdeviceIdを確認することができました。
Node.jsで動くようにすることやTSへの書き換えは、公式のJSのサンプルから比較的簡単に作成でき、
署名とリクエストの部分さえ作ってしまえばAPIの各種操作が簡単に行うことができました。
次回はSwitchbotAPIを利用してWebhookを設定し、Lambdaを経由してDiscordにメッセージを飛ばすものを作成したいと考えています。
コメントを残す