IFTTTを利用したNature Remoの操作に限界を感じたのでAPIを使う

Tech, クライアントの無茶な要求に耐える, 作ってみたGAS, Google Home, IFTTT, IoT, Nature Remo

Nature Remoとは

Nature Remo(ネイチャーリモ)は、お使いの家電をインターネットに繋げることで、手軽にスマートホームを実現するスマートリモコンです。例えば、外出先からスマートフォンでエアコンを操作したり、Google Home(グーグルホーム)やAmazon Echo(アマゾンエコー)から音声でテレビや照明を操作することができます。

https://nature.global/

簡単に言うと、家にあるテレビのリモコンや、リビングの電灯のリモコンの信号を記憶して、スマホやPC, Googleホームから家電を操作できるようにするデバイスです。

IFTTTとは

条件に対して、操作を設定できるツールです。
条件の例:
– Googleホームに「電気つけて」と言ったら
– 渋谷駅に着いたら
– 13:00になったら

操作の例:
– 位置情報をツイートする
– メールを送る
– WebhookでAPIを呼び出す

上記のような条件と操作が膨大に選択肢として提供されています。
ただし、1条件に1操作が基本 ※1 で、複雑な要求には対応できません

※1 渋谷にいるときに(条件1)、14:00になったら(条件2)、リマインダーを通知する(操作1)というようなことはできないわけです。

APIでできるようになること

Nature RemoのAPIは公開されています。
つまり、操作はIFTTTでなくても、プログラミングで実行できます。

条件もプログラムで記述することで、複数条件を設定したり、IFTTTで提供されていないあらゆる情報を条件に設定できます。

※今回は、IFTTTをGoogle Homeの連携部分のみ使用します

APIで電灯をつける

前提

・Nature Remoに家電を設定済みで、スマホから電灯をつけることができる。

トークンを発行する

Nature Remoを操作できるようにするために、トークンを発行します。
下記URLから発行できます。
これが流出すると、誰でもあなたの家の家電を操作できてしまうので気をつけてください。

トークン発行
https://home.nature.global/

トークンのテスト & Signal ID の確認

Nature RemoのAPIは下記ドキュメントで仕様を確認できます。
まずは先程のトークンを用いて、Postmanからリクエストを送ってみます。
Postmanがインストールされて無い方はこちら(https://www.getpostman.com/) からインストールしてください。

API DOC
http://swagger.nature.global/#/

スマホで設定した家電の情報を見るには、 /appliancesにアクセスすれば良さそうです。
リクエストを送信してみます。

赤枠は画像のとおりに設定してください。モザイク部分は、先程取得したトークンを設定

レスポンスの全量は下記です。
signalsプロパティ以下のidは後で必要になります。
リビングの電灯1をon/off切り替えする操作には、6e7d903a-16fe-41c6-aa2a-910eae3da077 というidが振られていることがわかります。
ちなみに、ウチのリビングの電灯は2つあり、電灯1はシーリングファンなので、「送風」という操作が存在します。

[
    {
        "id": "f1332d9b-fca3-4442-808b-9c0e7f85c158",
        "device": {
            "name": "mini",
            "id": "fb2ab435-4fd2-41a4-8a7e-d355a06d0174",
            "created_at": "2018-07-24T11:42:41Z",
            "updated_at": "2019-06-17T01:41:13Z",
            "mac_address": "84:f3:eb:a2:85:50",
            "serial_number": "2W8601310",
            "firmware_version": "Remo-mini/1.0.87-g8b06f0e",
            "temperature_offset": 0,
            "humidity_offset": 0
        },
        "model": null,
        "type": "IR",
        "nickname": "リビングの電灯1",
        "image": "ico_light",
        "settings": null,
        "aircon": null,
        "signals": [
            {
                "id": "6e7d903a-16fe-41c6-aa2a-910eae3da077", //   ⇐  操作にidが振られている
                "name": "電灯on_off",
                "image": "ico_io"
            },
            {
                "id": "501ff56d-28f5-48af-af50-d3f8cde403a5",
                "name": "送風on",
                "image": "ico_blast"
            },
            {
                "id": "688ad68a-ad8e-44cd-9a04-4ffdc100f454",
                "name": "送風off",
                "image": "ico_blast"
            }
        ]
    },
    {
        "id": "121ef362-e34c-4f39-8bf4-ed0abb35e742",
        "device": {
            "name": "mini",
            "id": "fb2ab435-4fd2-41a4-8a7e-d355a06d0174",
            "created_at": "2018-07-24T11:42:41Z",
            "updated_at": "2019-06-17T01:41:13Z",
            "mac_address": "84:f3:eb:a2:85:50",
            "serial_number": "2W8601310",
            "firmware_version": "Remo-mini/1.0.87-g8b06f0e",
            "temperature_offset": 0,
            "humidity_offset": 0
        },
        "model": null,
        "type": "IR",
        "nickname": "リビングの電灯2",
        "image": "ico_light",
        "settings": null,
        "aircon": null,
        "signals": [
            {
                "id": "1d709741-37ac-4300-a93d-5bda30737998",
                "name": "on",
                "image": "ico_lightdown"
            },
            {
                "id": "1b8b0f82-9b8e-4e95-806b-ea7a826d3037",
                "name": "off",
                "image": "ico_lightup"
            },
            {
                "id": "5a242001-d8b7-4b40-ae36-88b3d8d637ff",
                "name": "豆電球",
                "image": "ico_color_red"
            }
        ]
    }
]

APIで電灯を操作する

signal ID(=操作ID)がわかったので、APIで実行してみます。
POSTで /signals/{signal id}/send にアクセスしてみます。

POSTにすることを忘れずに

電気が点いたので成功。
次はGASから実行してみます。

GASプログラムから実行する

できるだけお金を掛けたくないので、 無料であるGASを使用します。
GASで適当なシートを作成し、ツール -> スクリプトエディタを開きます

ソースコードの例は下記です。モザイク部分は、トークンが入ります

function doGet() {
  
  /*
    リビングの電灯1を on/off する
                             */
  var options = {
    'method': 'post',
    'headers': {
       'Authorization': 'Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
    }
  };

  var response = UrlFetchApp.fetch('https://api.nature.global/1/signals/6e7d903a-16fe-41c6-aa2a-910eae3da077/send', options);
}

手動実行して動いたら、APIとして公開して、IFTTTからアクセスできるようにします。(Google Home連携のため)

公開する際の設定値は、上記の画像通りにしてください

複雑な条件を設定する

操作の記述はできました。
次は、複雑な条件を設定します。
今回は、スプレッドシートに保存した家電の状態を参照して、電灯の操作を切り替えるようにします。

複雑な条件の背景

一方は電源ボタンが1つだけ。一方は電源ボタンが2つある。

我が家のリビングには、電灯が2つあって、それぞれリモコンのボタンの仕様が異なります。(変な家。。。)
要件としては、「Ok Google, リビング」と言ったら、両方の電灯が消える / 両方の点灯が点く という結果になってほしいのです。

2つの電灯のオンオフを同期するには、下記の操作が必要になります

明かりが点いている場合:
電灯1の電源ボタンを押す
 電灯2のOFFボタンを押す

明かりが点いていない場合:
電灯1の電源ボタンを押す
 電灯2のONボタンを押す

これを、GASでプログラミングすることで実現します。

シートで状態を保持する

「シート1」にリビングの電灯が点いているか、点いていないかを判定する変数を用意します。
電灯をつけたらon、消したらoffにするよう、プログラムを書きます(後述)

明かりが点いているかどうかをシートで保持する

状態に応じて電灯を制御する

// シート接続情報
var sheet = SpreadsheetApp.openById('1ZhMNKabzOofdo3H51lpDsg1NpA59sTgtTn8q_AQkjws') // スプレッドシートのurlの d/・・・・・・・?editの部分
            .getSheetByName('シート1');


function doGet(e) {

  switch(e.parameter.method){
      case 'livingLight':
          switchLivingLight();
          break;
  }
  
  /*
    リビングの電灯を on/off する
                             */
  function switchLivingLight(){
      var state = sheet.getRange('B2').getValue();
      if(state === 'on'){
          //リビング1が点灯中なら、リビングの電灯2を消灯する
          sendSignal('1b8b0f82-9b8e-4e95-806b-ea7a826d3037');
      } else if(state === 'off'){
          //リビング1が消灯中なら、リビングの電灯2を点灯する
          sendSignal('1d709741-37ac-4300-a93d-5bda30737998');
      }
    
    //リビングの電灯1を on/off する
    sendSignal('6e7d903a-16fe-41c6-aa2a-910eae3da077');
    
    //変更後の状態をシートに保存する
    sheet.getRange('B2').setValue(state === 'on' ? 'off' : 'on');
    
  };
  
  
  //Remoに信号を送信
  function sendSignal(signalId){
      UrlFetchApp.fetch('https://api.nature.global/1/signals/' + signalId +'/send', {
        'method': 'post',
        'headers': {
            'Authorization': 'Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' // ⇐自分のトークンを使ってね
        }
    });
  
  }
}

IFTTTでGoogle Homeと連携をする

この部分については、他のブログにも沢山書いてあるので、さっくり設定の画像だけ貼っておきます。
Google Homeで「リビング」と言ったら、公開したGASのURLにWebhookを送るように設定します。

「OK Google, リビング!!!」

2つの照明が両方点灯しました。
もう一度唱えると、両方消えました。


長い闘いでした。

脆弱性について

家電操作をWebに公開するのは、ちょっと危険です。
今回の場合、最低限秘匿しないといけない情報は
・IFTTTのAPIトークン
・GASの「現在のウェブアプリケーションのURL」
です。お気をつけて。

以後は、声で操作するしかない

お気づきの方もいらっしゃるかと思いますが、Googleスプレッドシートに保存したstateは、GASでしか書き換えられることがありません。
つまり、家のリモコンで普通に電灯を消したり付けたりすると、実際の状態とスプレッドシートに記載された状態が乖離することになります。
以後は、手で電灯を操作しないようにしましょう(欠陥設計)