SwitchBotハブのAPIの使い方。エアコンをコントロールするプログラムをJavaScriptで書いた!

2021年8月9日プログラミング

こんにちは!

東京2020五輪も終わり、夏休み楽しんでますか?

暑いですね〜。あまりエアコンを使わない生活をしていましたが、歳のせいか最近はエアコン頼みです。

久しぶりにエアコンを使おうと思うと、リモコンに電池が入っていなかったり、書斎のエアコンのリモコンが他の部屋のリモコンとして移動していたり、なかなか思うように使えません。

意外とエアコンの冷気に慣れていなくて、つけっぱなしというのも気分が悪い。付けたり、消したりするのにリモコンを手に取ることも多い私。週末は、趣味の諸々をUbuntuパソコンであれこれするのが習慣です。なので、どうせなら、パソコンでコマンドライン一発でエアコンを付けたり、消したりできると、便利なんじゃないか?

そんな訳で、以前買ってひとしきり遊んだ後、机の奥に眠っていたSwitchBot ハブミニ を引っ張り出してきました。スマホやスマートスピーカーから一般的なリモコン対応機器を操作できるようにするガジェットです。

今日は、こいつをJavaScriptで調理していきます。

SwitchBotの開発者向け機能

SwitchBotブランドの商品には色々なものあります。

物理スイッチを遠隔操作するためのSwitchBotや、赤外線リモコンの代わりに使える、SwitchBotハブ。カーテンを自動開閉させるためのSwitchBotカーテン。部屋の温度や湿度をリモートから確認する、SwitchBot温湿度計、などなど。

その中でも、私が利用しているのが、SwitchBotハブミニです。

SwitchBot商品は、なんと、週末プログラマーにとっては大変うれしいことに、下のリンクの説明(英語)のように、HTTPSベースのREST APIが用意されているではありませんか。

これを使って、お決まりのNodejsのJavaScriptでプログラミングをしてみます。APIはシンプルで、

例えば、以下のようなURLを叩くと、SwitchBotのアプリで管理しているデバイスのリストが取り出せます。

https://api.switch-bot.com/v1.0/devices

また、以下のようなURLに対して、POSTでコマンドを送ると、該当デバイスの電源Off/Onなどが行なえます。{deviceId}の部分はSwitchBot側で定義された適切なデバイスIDです。

https://api.switch-bot.com/v1.0/devices/{deviceId}/commands

さて、では、どうやって「私の」デバイスを特定するのでしょう?

そのカギがtokenです。

SwitchBot APIの認証の方法

SwitchBotのREST APIの認証の仕組みは簡単です。オフィシャルサイトのGetting Startedに以下のように記載があります。

1. Download the SwitchBot app on App Store or Google Play Store

2. Register a SwitchBot account and log in into your account

3. Generate an Open Token within the app a) Go to Profile > Preference b) Tap App Version 10 times. Developer Options will show up c) Tap Developer Options d) Tap Get Token

4. Roll up your sleeves and get your hands dirty with SwitchBot OpenAPI!

つまり、まずは、Google Play Storeでアプリをダウンロード(iOS版もあり、同様の仕組みがあります)して、ログインします。そして、プロフィール > 設定 > アプリバージョン と進み。アプリバージョンが出ているところを10回タップします。

するとどうでしょう。「開発向けオプション」という特権情報を表示するための項目が得られるのです。

開発者向けで表示される「トークン」をHTTPSのリクエスト時に、「Authorization」ヘッダとして加えてあげるだけです。

実際のコードは、以下のようになります。GETでデバイスリストを得るコードを例に説明します。NodejsのHTTPSのライブラリ axiosを使っています。以下のコードで、8行目から10行目が、ヘッダを付加している部分です。9行目のtokenは、SwitchBotアプリで得られるトークン文字列です。

  GetDevices() {
    let _self = this
    return new Promise(function(resolve, reject) {
   
      _self.axios({
        method: 'GET',
        url: 'https://api.switch-bot.com/v1.0/devices',
        headers: {
          'Authorization': token,
        }
      }).then((response) => {
        let sbres = response.data
        if (sbres.statusCode != 100) {
          reject(new Error(sbres.message))
        } else {
          _self.deviceList = sbres.body.deviceList
          _self.infraredRemoteList = sbres.body.infraredRemoteList
          resolve(sbres.body)
        }
      })
    })
  }

これで得られるresponseの中にSwitchBotが管理するデータが含まれます。以下のようなJSON形式のオブジェクトが返ります。

statusCode: 100,
  body: {
    deviceList: [
      {
        deviceId: "XXXX",
        deviceName: "Hub Mini AF",
        deviceType: "Hub Mini",
        enableCloudService: false,
        hubDeviceId: "000000000000",
      },
    ],
    infraredRemoteList: [
      {
        deviceId: "XX-XXXXX-XXXXXX",
        deviceName: "テレビ",
        remoteType: "TV",
        hubDeviceId: "XXXX",
      },
      {
        deviceId: "XX-XXXXX-XXXXXX",
        deviceName: "プロジェクター",
        remoteType: "Projector",
        hubDeviceId: "XXXX",
      },
      {
        deviceId: "XX-XXXXX-XXXXXX",
        deviceName: "エアコン",
        remoteType: "Air Conditioner",
        hubDeviceId: "XXXX",
      },]
    },
    message: "success",

ここで、操作したいデバイスのデバイスID(deviceId)が得られます。リモコン操作するデバイスは、virtual deviceになっているので、infraredRemoteListという構造の一覧で得られます(上記の12行目以降)。機器を操作する場合は、操作したい機器のIDを指定して、以下のURLにPOSTします。XX-XXXXX-XXXXXXのところは、上記のJSONで得られたIDを使います。

https://api.switch-bot.com/v1.0/devices/XX-XXXXX-XXXXXX/commands

肝心のPOSTするデータの中身はというと、エアコンであれば、以下のような感じになります。

{
  "command": "setAll",
  "parameter": "26,2,2,on",
  "commandType": 'command'
}

parameterの26,2,2,on意味するところはというと、オフィシャルサイトの説明によれば、以下のようになります。

パラメータの名前
temperature温度を摂氏で表現
modeモードで、以下の値。
1: 自動, 2:冷房, 3:ドライ, 4:送風, 5:暖房
fan speed送風の強度で、以下の値。
1: 自動, 2:弱, 3:中, 4:強
power state電源。以下の値。
on, off

ですので、26,2,2,onというのは、26℃設定で、冷房、送風は弱で、電源入れる、という意味です。

コマンドを送るソースコードは以下のようになります。

  ExecCommand(device, command, params) {
    let _self = this
    return new Promise(function(resolve, reject) {

      console.log(`going to send command: ${command}${(params) ? ' with ' + params : ''}`)

      _self.axios({
        method: 'POST',
        url: `https://api.switch-bot.com/v1.0/devices/${device.deviceId}/commands`,
        headers: {
          'Authorization': token,
        },
        data: {
          command: command,
          parameter: params,
          commandType: 'command',
        },
      }).then((response) => {
        let sbres = response.data
        if (sbres.statusCode) {
          resolve(sbres)
        } else {
          console.log(`statusCode{${sbres.statusCode}}: ${sbres.message}`)
          reject(new Error(`statusCode{${sbres.statusCode}}: ${sbres.message}`))
        }
      })

    })
  }

上記の15行目のparams変数には、得体の知れない"26,2,2,on"が入ります。(14行目は、"setAll"という文字列)

SwitchBotでエアコンを操作する全ソースコード

コマンドラインでエアコンが操作できる全ソースはGithubに上げました。sb_airconという、雑な名前のスクリプトです。雑に作ったソースコードで、私個人の目的で使うことしか想定をしていないので、あまり汎用性はありません。しかし、エアコンをコマンドラインで操作するにはもってこいです。

使い方もREADME.mdに書いています(英語)のでご覧ください。

暑い2020年夏。何かのお役にたてば!

SwitchBot温湿度計があると、より自動化できて便利かも知れない…↓

カーテンが操作できると、より生活が豊かになるかも知れない…↓

物理的なスイッチを操作してくれたら、冬は床暖の自動化が出来るかも…↓