Sesame と Nature Remo を使って帰宅時に自動でリビングの電気をつける

# 概要

鍵の解錠 (or 施錠) をトリガーに、[Sesame Webhook](https://docs.candyhouse.co/#sesame-webhook) と [Nature Remo](https://nature.global/jp/nature-remo) を使って帰宅時にリビングの電気を自動でつける仕組みを実現しました。

実現するにあたって、Sesame Webhook では「デバイス ID」 と 「鍵の状態 (`locked` or `unlocked`)」しか取得できないため(2019/10/28 現在)、鍵の状態が変わったのが **帰宅時** なのか **外出時** なのかを別途判定させる必要があります。

そこで、Nature Remo を使って部屋の照度を Google スプレッドシート に毎分記録しておき、 鍵の状態が変わる **5 分前の照度が低いなら帰宅時である** と判定させるようにしました。

# 構成

## 部屋の照度の記録

**必要なもの**

- Nature Remo
- GAS
- Google スプレッドシート

**フロー**

1. 時間ベースのマイトリガーで 1 分おきに GAS を起動
2. (GAS) Nature Remo API を叩き、部屋の照度を取得
3. (GAS) 取得した照度を Google スプレッドシートに記録

> **Nature Remo API のリクエスト制限**
>  サーバは 5分以内に30回 以上のリクエストを受けるとその後ステータスコード 429 を返す。
> https://developer.nature.global/

## 解錠 (or 施錠) → リビング ON

**必要なもの**

- Sesame Webhook
- GAS
- Google スプレッドシート
- IFTTT

**フロー**

1. (Sesame Webhook) 解錠 or 施錠をトリガーに GAS へリクエスト
2. (GAS) 5 分前の部屋の照度が低ければ、IFTTT へリクエスト
3. (IFTTT) Nature Remo でリビングの電気をつける (or 帰宅時用のシーンを起動)

# 各種設定など

## IFTTT

1. [Applet 作成ページ](https://ifttt.com/create) へアクセス
2. `This` > `Webhooks` > `Receive a web request` を選択
3. `Event Name` に適当なイベント名を設定して (ここでは `arrived_home` とします) `Create trigger` を選択
4. `That` > `Execute scene` または `Control light` を選択して、帰宅時の状態を設定 (リビングの電気をつける等)
5. `Create Action` を選択して Applet を作成

その後、`My services` > `Webhooks` > `Documentation` から Webhook URL を確認します。
具体的には、`https://maker.ifttt.com/trigger/arrived_home/with/key/{YOUR_KEY}` になります。

> `{YOUR_KEY}` はご自身のものと置き換えてください

## GAS

Remo API を叩いてセンサー情報を取得する部分は、[リビングの環境監視ダッシュボードを６０分で作る方法（Nature Remo Cloud APIとGoogleサービス連携）](https://qiita.com/t-chi/items/01b9a9b98fbccef880c3) を参考にしています。

### スプレッドシートの用意

1. https://docs.google.com/spreadsheets/u/0/ から新しいスプレッドシートを作成
2. ワークブックの名前は任意に、シートの名前は `log` に変更
3. A1に `日時`、B1に `気温`、C1に `湿度`、D1に`照度` を入力してヘッダー行を作成

こんな感じになります。 (もちろん実際にはまだデータは入らないです)
<img width="573" alt="スクリーンショット 2019-10-28 20.13.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222294/f877cb50-c9aa-cb37-8e52-f3b70c7685d4.png">

### コード

スプレッドシートの用意ができたら、`ツール` > `スクリプトエディタ` を選択して、以下をおこなうコードを作成します。

- Nature Remo API を叩いてスプレッドシートにデータを記録
- (Sesame Webhook からの) POST リクエストを受け付けて、5 分前の部屋の照度が低ければ IFTTT へリクエストを送信

```javascript:コード.gs
var spreadsheetId = 'xxx'; // 書き換える

// データを取得してシートへ書き込む
function remo() {
  var data = getDevicesData();
  writeNewestEvents(
    {
      te: data[0].newest_events.te.val,	// 気温
      hu: data[0].newest_events.hu.val,	// 湿度
      il: data[0].newest_events.il.val,	// 照度
    },
    // 最下行
    SpreadsheetApp.openById(spreadsheetId).getSheetByName('log').getDataRange().getValues().length + 1
  );
}

// Nature Remo API からデータを取得する
function getDevicesData() {
  var remo_url = "https://api.nature.global/1/devices";
  var remo_access_token = 'xxx'; // 書き換える
    "Content-Type" : "application/json;",
    'Authorization': 'Bearer ' + remo_access_token
  };
  var params = {
    "method": "get",
    "headers": headers
  };
  
  return JSON.parse(UrlFetchApp.fetch(remo_url, params));
}

// シートへ書き込む
function writeNewestEvents(events, row) {
  var sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName('log');
  sheet.getRange(row, 1).setValue(new Date());
  sheet.getRange(row, 2).setValue(events.te);
  sheet.getRange(row, 3).setValue(events.hu);
  sheet.getRange(row, 4).setValue(events.il);
}

function doPost(e) {
  var sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName('log');
  var row_num = sheet.getDataRange().getValues().length;
  var il_5_minutes_ago = sheet.getRange(row_num - 5, 4).getValue();
  
  // 5 分前の部屋の照度が低いなら帰宅時
  if (il_5_minutes_ago < 50) {
    var ifttt_url = "https://maker.ifttt.com/trigger/arrived_home/with/key/xxx";	// 書き換える
    var params = {
      "method": "post",
    };
    UrlFetchApp.fetch(ifttt_url, params);
  }
}
```

以下はそれぞれご自身のものに書き換えてください。

- `spreadsheetId`
    - スプレッドシートの URL の `https://docs.google.com/spreadsheets/d/` **この部分の文字列** `/edit#gid=0`
- `remo_access_token`
    - Nature Remo のアクセストークン
    - また取得していなければ、[公式ページ](https://home.nature.global/home) から取得してください
- `ifttt_url`
    - 上で作成した IFTTT の URL (`https://maker.ifttt.com/trigger/arrived_home/with/key/{YOUR_KEY}`)

> **Note:**
> このコードでは Sesame Webhook から受け取ったリクエストが解錠時のものなのか施錠時のものなのかを判別していません。
> 現状 Sesame Webhook は不安定で動作したりしなかったりするので、あえて状態を絞らない実装としています。

### Web アプリとして公開

1. スクリプトエディタの `公開` > `Webアプリケーションとして導入...` を選択
3. `Who has access to the app:` を `Anyone, even anonymous` に設定して公開

表示された URL が Sesame Webhook でのリクエスト送信先になります。

### マイトリガー

上で作成した `remo()` 関数を 1 分おきに実行する設定をおこないます。

1. スクリプトエディタの `編集` > `現在のプロジェクトのトリガー` を選択
2. `トリガーを作成` から以下のとおり設定して `保存` を選択

<img width="684" alt="スクリーンショット 2019-10-28 20.40.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222294/d7a9fac1-fbc6-b194-a127-4bdd54994886.png">

## Sesame Webhook

リクエストの送信先 URL を設定します。

1. [Sesame Dashboard の API 設定ページ](https://my.candyhouse.co/#/credentials) へアクセス
2. `Webhook` > `Edit` から、メソッドは `POST` を URL は 先ほど GAS を Web アプリとして公開したときに取得した URL を設定して `Save` を選択

# おわりに

Sesame の「手ぶらで解錠」とあわせて、帰宅時にドアの前に来るだけで自動で解錠されてリビングの電気がつくようになりました。
電気をつけるところは Sesame Webhook から取得できる情報が少ないので諦めかけていましたが照度を利用して実現することができました。

みなさんの参考になれば幸いです！