お疲れ様です。
現在筆者の部屋にはスマートホーム環境を構築しています。
操作は一般的にGoogleHomeに話しかけるorSwitchBotのスマホアプリから操作をするいずれかです。
そうPCから無言で部屋の照明をイジったりできないんですね。
少し調べてみるとCLIから操作できるものを開発している方もいるようなのですが、どうせなら自分で作るかーと
あとはできるだけシンプルにしたいなーって思ったのも大きいです。
要件
- WindowsならTerminal(PowerShell)からMacならTerminal.appから
- SwitchBotデバイスを最低限(ON/OFF)操作できる
- デバイス一覧などは確認できるようにする
- デバイスには自身が考えるユニークな名称をつけ、それを元に操作できる
APIトークンの発行
SwitchBotアプリの「Profile」→「Preferences」

→「About」

→「App Version」を連打する

トークンが出てくる。
ここに出てくるトークンがわかるとデバイスを操作できます。取り扱いにはご注意を。

CurlでAPI叩いてみる
デバイス一覧を取得
curl -X GET "https://api.switch-bot.com/v1.1/devices" \
-H "Authorization: さっきのtoken"
レスポンスを確認し、devicenameと対になっているdeviceIdを元に操作をします。
デバイスをON/OFF
curl -X POST "https://api.switch-bot.com/v1.1/devices/さっきのdeviceid/commands" \
-H "Authorization: さっきのtoken" \
-H "Content-Type: application/json" \
-d '{"command":"turnOn","parameter":"default","commandType":"command"}'
実行結果が返ってきます。
いい感じです。
コードを書いていくぅ
先ほどの情報を元にPowerShellスクリプトとシェルスクリプトに落とし込んでいきました。
要件のとおりにデバイス一覧を取得しjson→ユニークなデバイス名を追加→スクリプトからjsonを読み、ユニークなデバイス名を使用し状態を操作することができました。
参考までにMacでいい感じに動いたシェルスクリプトを貼っておきます。
sb.sh
#!/bin/bash
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
URL="https://api.switch-bot.com/v1.0"
ENV_FILE="$SCRIPT_DIR/.env"
DEVICES_FILE="$SCRIPT_DIR/devices.json"
# .envよりAPI_KEY
if [ -f "$ENV_FILE" ]; then
export $(cat "$ENV_FILE" | xargs)
else
exit 1
fi
# 引数なし
if [ $# -eq 0 ]; then
echo "引数を指定してください"
exit 1
fi
if [[ "$1" == "list" ]]; then
case "$2" in
devices)
cat "$DEVICES_FILE"
exit 0
;;
*)
echo "listの引数を指定してください"
exit 1
;;
esac
fi
# setコマンド
if [[ "$1" == "set" ]]; then
case "$2" in
key)
read -p "Enter your API_KEY: " NEW_KEY
echo "API_KEY=$NEW_KEY" > "$ENV_FILE"
echo "APIKEY を $ENV_FILE に保存しました"
exit 0
;;
devices)
NEW_JSON=$(curl -s -X GET "$URL/devices" -H "Authorization: $API_KEY")
if [ -f "$DEVICES_FILE" ]; then
EXISTING_JSON=$(cat "$DEVICES_FILE")
else
EXISTING_JSON='{"body":{"deviceList":[],"infraredRemoteList":[]}}'
fi
MERGED_JSON=$(jq -s '
.[0] as $existing | .[1] as $new |
{
statusCode: $new.statusCode,
message: $new.message,
body: {
deviceList: (
($existing.body.deviceList + $new.body.deviceList
| map(. + ({unique: (.unique // "")}))
| unique_by(.deviceId))
),
infraredRemoteList: (
($existing.body.infraredRemoteList + $new.body.infraredRemoteList
| map(. + ({unique: (.unique // "")}))
| unique_by(.deviceId))
)
}
}
' <(echo "$EXISTING_JSON") <(echo "$NEW_JSON"))
echo "$MERGED_JSON" | jq '.' | tee "$DEVICES_FILE"
;;
*)
echo "何をsetするか指定してください"
exit 1
;;
esac
fi
# ON/OFF操作
DEVICE_NAME=$(jq -r --arg name "$1" '(.body.deviceList[]?, .body.infraredRemoteList[]?)| select(.unique==$name) | .deviceName' "$DEVICES_FILE")
DEVICE_ID=$(jq -r --arg name "$1" '(.body.deviceList[]?, .body.infraredRemoteList[]?) | select(.unique==$name) | .deviceId' "$DEVICES_FILE")
if [ -z "$DEVICE_ID" ] || [ "$DEVICE_ID" == "null" ]; then
echo "デバイスが見つからない,あるいは変更がありませんでした"
exit 1
fi
case "$2" in
on)
curl -s -X POST "$URL/devices/$DEVICE_ID/commands" \
-H "Authorization: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"command":"turnOn","parameter":"default","commandType":"command"}' >/dev/null
echo "${DEVICE_NAME}をONにしました"
;;
off)
curl -s -X POST "$URL/devices/$DEVICE_ID/commands" \
-H "Authorization: $API_KEY" \
-H "Content-Type: application/json" \
-d '{"command":"turnOff","parameter":"default","commandType":"command"}' >/dev/null
echo "${DEVICE_NAME}をOFFにしました"
;;
*)
echo "ON/OFFを指定してください"
exit 1
;;
esac
適切にパスを通すことで以下のように実行できるようになりました。sb unique-devicename on/off
また上記コードでは.envに認証情報を格納。devices.jsonにデバイス情報を記録しています。
動いているところ
最後に
以上SwitchBotデバイスのON/OFFをTerminal上から操作できるスクリプトを書こーって話でした。
Webアプリ的に実装しても良かったのですが、「ブラウザ開く→該当ページに行く→マウスでポチポチ」よりもCLIでポチポチしたほうが早いんじゃねぇかなって。
ざっついコードなので参考にしないほうが良いですが、参考になれば嬉しいです。
最後まで見ていただきありがとうございました!
コメント