我が家のSmartHouse化計画Lv2


# はじめに
## 要約

* Smartボタンを押したら、色々Smart家電を操作したい

![pic1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/35fd615e-9c94-c7c5-919a-bbcfc3abfa10.png)


## モチベーション
* 我が家にはSmartな家電とAmazonEcho/GoogleHomeがあり、しゃべると家電が操作できる環境があります
    * どんなものをつないで、どんな設定をしているかは関連記事を御覧ください
    * しゃべれば動くのですが、毎回細かく伝えるのは無理があります
        * オールONとかオールOFFはよいのですが、中途半端な状態だと面倒です
* ベッドに入りそろそろ寝るかという状態で、「alexa ○○ して」を何回も言うのは地味に面倒です
    * スマートスピーカーは1つずつしか処理できませんので
    * 毎回同じ状態なら定形フレーズにすればいいのですが、ライトを付ける/付けないなど毎回少しだけ違うのが、悩ましい。。。
* どこかにアナログなものを残したい所があって、ボタンって押したくなりますよね

## 関連する記事

* [我が家のSmartHouse化計画](https://qiita.com/kazutxt/items/f56f8eb339fc7da952ea)
* [Nature RemoとNode-REDでテレビを操作する](https://qiita.com/kazutxt/items/e7ca6c062eff0f279455)
* [Node-RED系の記事のまとめ](https://qiita.com/kazutxt/items/8c72448eefcba56dabef)

# 実現方法
## 全体の連携イメージ
![pic2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/b255cd85-e856-675e-a777-e71773ec511d.png)

* SmartButton(Flic)を使って、照明/テレビ/エアコンを操作します
    * クリック/ダブルクリック/ホールド(長押し)が使えるので、この3種類をそれぞれ割り当てます
* RaspberryPi上のNode-REDと(ライト以外)NatureRemoを使って、各家電を操作します
* ボタンを押して正しく動作したかわからないので、出力先としてGoogleNestHubに通知します

### 備考
* NatureRemoには各家電のリモコンが学習されている前提です
* 項番とはずれるのですが、わかりやすい順(処理のかんたんな順)で①->③->④->⑤->②の順に紹介します

## ①ボタンを押してNode-REDに通知する
* まず、SmartButtonはFlicを使います。
    * Flicにはスマホを使うパターンとFlicHubを使うパターンの2つパターンがありどちらでもできます
        * どちらでも設定自体はスマホで行います
    * スマホアプリがありますので、インストールをして、ペアリングをします

<img src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/b23cfe24-6ea8-49dd-f302-d92f86c90117.jpeg" width="50%">

* 次に、スマホアプリでクリック/ダブルクリック/ホールド時の動作を定義します
    * アプリは使いやすいですし、仕掛けられるイベントはたくさんあります
    * 今回は汎用性を上げるために、WebHookで自宅のRaspberryPi上のNode-REDにつなぎます
  
<img src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/0c74120b-51ce-0ff7-bb79-1b5f18fdf01e.png" width="50%">



## ③ダブルクリックでテレビをつける

### フロー
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/eba95317-8912-867a-507a-418e5d9d4418.png)

* <サーバURL:PORT>/white_dbclickにGETメソッドで通知が来ると、NatureRemoのTokenを設定し、テレビ用のWebHookに通知します

### 重要な処理
``` RemoToken.js
msg.headers = {
    "Content-Type":"application/x-www-form-urlencoded",
    "accept" : "application/json",
    "Authorization": "Bearer <省略>"
};
msg.payload = {
    "button" : "power"
}
return msg;
```

* テレビ操作ノード
    * メソッド：`POST`
    * URL : `https://api.nature.global/1/appliances/<ID>/tv`

### 備考
* テレビの場合は、`button=Power` で電源のON/OFFの両方ができるため、共通させています
* テレビの電源の切り替えノード側のフローはGoogleNestHub通知用なので、後述します。

## ④ホールドでエアコンをつける

### フロー
![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/63eeed5f-6353-8ca6-d288-22198bfa1f8e.png)

* テレビの場合に加えて、ON/OFFが個別になっていますが、それ以外は同じです
* 設定部分はフラグ管理用でON/OFFを交互に設定し、後続のswitchで処理を分けています

### 重要な処理

``` 設定.js
var aircon_flag = flow.get("aircon_flag")|false;
aircon_flag = !aircon_flag;
flow.set("aircon_flag",aricon_flag);
return msg;
```

``` ON.js
msg.headers = {
    "Content-Type":"application/x-www-form-urlencoded",
    "accept" : "application/json",
    "Authorization": "Bearer <省略>"
};
msg.payload = {
    "button" : ""
}
return msg;
```

``` OFF.js
msg.headers = {
    "Content-Type":"application/x-www-form-urlencoded",
    "accept" : "application/json",
    "Authorization": "Bearer <省略>"
};
msg.payload = {
    "button" : "power-off"
}
return msg;
```

* エアコン操作ノード
    * メソッド：`POST`
    * URL : `https://api.nature.global/1/appliances/<ID>/aircon_settings`

### 備考
* ONはbuttonが空文字ですが、OFFはbuttonがpower-offという非対称なので気をつけてください
* 通知先もairconではなく、aircon_settingsとテレビと少し異なります


## ⑤GoogleNestHubに通知する

### フロー
![図3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/5407dff1-a2ac-4d57-3adc-c33d44a78635.png)

* まず、事前に以下の方法で、GoogleNestHubのIPを調べます
    1. GoogleHomeアプリからGoogleNestHubを選択します
    2. 右上の歯車の設定をクリックします
    3. デバイス設定で、一番下の情報のIPアドレス：XXX.XXX.XXX.XXXを確認します
* 次にノードをインストールします
    * [node-red-contrib-cast](https://flows.nodered.org/node/node-red-contrib-cast)

### 重要な処理


``` テレビの電源の切り替え.js
msg.payload.message = "テレビの電源を切り替えました" // TTS用の喋らせる文章
msg.payload.language = "ja" // 言語
```

* castノード
    * IP: `上記で調べたIP`
    * Port: `8009(デフォルト)`

### 備考
* castノードには、音声ではなく画像を表示するなどカスタマイズパターンもあります
* 自分でわかってアクションを起こしているので、通知はいらないかも。。。
    * NWやNode-REDなどでエラーになったときに気づけるので良いは良いのですが


## ②クリックで照明/ライトをつける
### フロー

![図5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/6ada2a86-c4fd-be43-bc00-ec69efa0ef23.png)


* 照明とライトの2つを制御します。両方ONは必要ないので3パターンを下記の通りローテーションします。
    1. 照明OFF/ライトON
    2. 照明ON/ライトOFF
    3. 照明OFF/ライトOFF
* 最初は[tplink-smarthome-api](https://github.com/plasticrake/tplink-smarthome-api)を入れて、jsでの実装を考えていのたですが、うまく行かなかったことと、これを使ったノードがあったので、以下をインストールしました
    * [node-red-contrib-tplink-smarthome](https://flows.nodered.org/node/node-red-contrib-tplink-smarthome)

* ただし、SmartライトのIPを調べるために、このライブラリは役立ちました
    * `npm install tplink-smarthome-api`で入れた後に、`tplink-smarthome-api search` で探せます
        * 他のやり方ともあると思いますが、スマホアプリからはIPを見つけられませんでしたので、一例として紹介いたします

### 重要な処理

#### tplinkのライト側のフロー

``` 設定.js
var light_count = flow.get("light_count")||0;
light_count += 1;
if (light_count > 2) {light_count=0}
flow.set("light_count",light_count);
return msg;
```

``` ライトオン.js
msg.payload=true // ライトオフの場合はfalse
return msg;
```

* smartplugノード
    * DeviceIP:`<上記で調べたIP＞`

#### NatureRemoの照明側のフロー

``` ON.js
msg.headers = {
    "Content-Type":"application/x-www-form-urlencoded",
    "accept" : "application/json",
    "Authorization": "Bearer <省略>"
};
msg.payload = {
    "button" : "on" // OFFの場合はoff
}
return msg;
``` 

* 照明操作ノード
    * メソッド：`POST`
    * URL : `https://api.nature.global/1/appliances/<ID>/light`

# まとめ
* 今回は、SmartButton(Flic)を使って、照明/ライト＆TV＆エアコンを操作できるようにしました。

* 我が家でよくある「alexa 電気消して->alexa 照明つけて->alexa テレビ消して->alexa エアコン付けて」が、ボタンのクリック/ダブルクリック/ホールドの3連コンボになったので、一瞬になりました。
    * alexaの返答を待たずに、連続でできるのがいいですね

#　その他
* 認証情報などをハードコーディングしているしているため、ソースの公開ができません。すみません。。。