Nature Remo APIを使ってテレビの電源を確実にOFFにする方法

#はじめに
### 実現したいこと
スマートスピーカーの音声認識機能を使って、スマートリモコン経由で家電を一括操作できるようにしたい。

### 具体例
「OK, Google! おやすみ〜」の一言で、

* 主照明　　➡︎　OFF
* 間接照明　➡︎　ON
* テレビ　　➡︎　OFF
* エアコン　➡︎　OFF
* カーテン　➡︎　CLOSE

みたいなことをやりたいです。

![smarthome.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128340/6be571ad-4ba1-1e83-7652-78086988ce74.png)

### 課題
上記内容の95%くらいは各ガジェットの標準機能を使って実現可能です。
残りの5%が何かというと、それが『テレビの電源を "確実に" OFFにすること』です。


#えっ、テレビの電源をOFFにするのって、そんなに難しいの？

一見すると、テレビの電源をOFFにすることは、リモコン操作の基本中の基本のように思います。

ただ、テレビのリモコンをよくよく見てみると...
テレビのリモコンには「電源OFFボタン」は存在しないことがわかります。

![tv.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128340/877b3bdd-b3ee-f9c1-9394-29b4c5ddb1bd.jpeg)

参考までに、こちらはSONY BRAVIAのリモコンですが、電源ボタンはON／OFF兼用ボタンになっています。

これはトグルボタンと言って、

* 電源がONのときに押すとOFF
* 電源がOFFのときに押すとON

となる仕様のボタンです。

トグルボタンのメリットは、ONとOFFのボタンをそれぞれ用意する必要がないので、物理設計上、効率が良いわけですね。
一方で、このトグルボタンがスマートリモコンでは弊害となる場合があります。

###トグルボタンの弊害

スマートリモコンは、リモコンから発する赤外線コードを学習して使用します。
テレビの電源操作については、このトグル形式の電源ボタンを学習することになりますが、それにより次のような問題が生じます。

テレビの電源が「OFF」の状態で、冒頭に書いたような一括操作を行うと、エアコンや照明は意図どおり「OFF」になるのですが、テレビの電源は「OFF」から「ON」の状態に切り替わってしまうのです...！
（トグルボタンは、単に状態を反転する仕様のため）

結果、真っ暗に静まり返った部屋の中でテレビだけが虚しく流れ、最終的には物理リモコンを使ってテレビの電源を消してから寝る・・・という何ともスマートではない行動を取る羽目になってしまいます。

ということで、テレビの電源を意図どおり「OFF」にする方法について調べました。

#【その１】テレビの仕様を逆手にとった裏技的方法で実現する（非エンジニア向け）

[Nature Remoでテレビを確実に消す方法ってあるの？](https://nature.global/jp/blog/2020/8/26/tv-off-certainly#:~:text=%E6%93%8D%E4%BD%9C%E3%81%AF%E3%82%B7%E3%83%BC%E3%83%B3%E3%81%AE%E8%BF%BD%E5%8A%A0,%E3%81%A6%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82&text=%E3%81%9D%E3%81%AE%E5%BE%8C%E3%81%AB%E6%99%AE%E9%80%9A%E3%81%AB%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%AB,%E6%B6%88%E3%81%99%E3%81%93%E3%81%A8%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82)

こちらは Nature Remo の公式ブログですが、

1. 各テレビメーカー固有の仕様を使った方法
1. 赤外線電波を連続送信したときの受信挙動を逆手にとった方法

などの裏技的方法が紹介されています。

最初はこの方法で設定してみたのですが、いまいち挙動が安定せず、想定どおりに動かないときがありました。

また、「テレビの電源を消す」という単一の指示に対して

* 一度チャンネルが切り替わってから「OFF」になる
* テレビの電源が一瞬「ON」になってから数秒後「OFF」になる

など、本来の指示とは異なる挙動を間に挟むのが「全然スマートじゃないなぁ…」と思い、個人的にはあまり好みの解決方法ではなかったです。
（こ、こんなのは自分が求めているスマートホームではないっ！）

#【その２】リモコンに標準装備されていない赤外線コードを、スマートリモコンに学習させる（エンジニア向け）

そこで、何か別の方法はないかと調べていると、テレビのリモコンに関する新事実を発見しました！

それは、リモコンに実装こそされていないが、実は、内部的には電源ON／OFF固有の赤外線コードは定義されているとのことです。
（通常は使用しないが、リモコンの規格として定義はされているんですね）

ということは、その固有の赤外線コードをスマートリモコンに学習させることができれば、電源ON／OFFの操作を独立して実行できる！ということになります。
（こっちの方がスマートでワクワクしますね！）

### 1） 実装環境
はじめに、今回の実装環境を書いておきます。

* テレビ　　　　　　　：SONY BRAVIA KJ-49X8000H
* スマートリモコン　　：Nature Remo mini 2
* パソコン（設定用）　：MacBook Pro

テレビについては、おそらく同一メーカー（SONY）であれば共通の赤外線コードが使えるのではないかと思います。他メーカーの場合は赤外線コードを別途調べる必要がありますが、それ以外の手順は共通です。

また、スマートリモコンが別メーカーの場合は、同様のAPIが提供されていれば実現できるかと思いますが、今回そこまでは調べられていません。

※ 以下、Nature Remoの家電登録作業は完了している前提で説明を行います。

### 2） Nature Remo Cloud API のアクセストークンを取得する
https://home.nature.global/home
まずはこちらのサイトにアクセスし、APIのAccess tokenを取得します。

※ 注意：ここで取得したトークンを漏らすと、あなたの家の家電を勝手に操作されちゃうかもしれないので取り扱いには十分気をつけましょう〜
（とはいえ、ボタン登録後にトークンを削除して無効にしておけば良いので、必要以上に恐れる必要はありません）

### 3） テレビの Appliances ID を取得する
次に、Nature Remo に登録した家電のうち、テレビの Appliances ID（デバイスを識別するための固有値）を取得します。

下記のAPI仕様書を参考にして頂きながら、
https://swagger.nature.global/#/default/get_1_appliances
Appliances情報をGETするコマンドを生成します。

```:AppliancesをGET
curl -X GET "https://api.nature.global/1/appliances" -H "accept: application/json" -k --header "Authorization: Bearer {2で取得したアクセストークン}" | jq
```
※ jqコマンドをインストールしておくと、返ってきたjsonデータが整形されて見やすくなります
参考（Macの場合）：https://qiita.com/tomitz/items/f48a6bfae1123cadc69a

```json:実行結果
[
  {
    "id": "????????????????????????????",
    "device": {
      "name": "リビング",
      "id": "*************************************",
      "created_at": "2021-02-07T07:39:32Z",
      "updated_at": "2021-02-24T15:18:07Z",
      "mac_address": "*************************************",
      "bt_mac_address": "*************************************",
      "serial_number": "*************************************",
      "firmware_version": "Remo-mini/1.4.7",
      "temperature_offset": 0,
      "humidity_offset": 0
    },
    "model": {
      "id": "*************************************",
      "country": "JP",
      "manufacturer": "sony",
      "remote_name": "rm-jd018",
      "name": "Sony TV 001",
      "image": "ico_tv"
    },
    "type": "TV",
    "nickname": "テレビ",
    "image": "ico_tv",
    "settings": null,
    "aircon": null,
    ・・・

※一部抜粋かつマスキングしています
```

冒頭の `"id": "????????????????????????????",` 部分がテレビの Appliances ID になります。

### 4） 電源ON／OFFボタンをそれぞれ登録する

次に、
https://swagger.nature.global/#/default/post_1_appliances__appliance__signals
こちらのAPI仕様書を参考にしていただきながら、テレビの電源ONボタン、電源OFFボタンを個別に登録するコマンドを取得します。
（このときに、3で取得した Appliances ID を使います）

また、SONY製テレビの電源ON／OFFの赤外線コードはそれぞれ下記の通りになります。
※ SONY以外のテレビを使用している場合は別途ググって調べてください

```json:電源ONの赤外線コード
{\"format\":\"us\",\"freq\":40,\"data\":[2269,694,480,690,1100,690,1100,690,1100,690,480,690,1100,690,480,690,1100,690,480,690,480,690,480,690,480,25500,2269,694,480,690,1100,690,1100,690,1100,690,480,690,1100,690,480,690,1100,690,480,690,480,690,480,690,480,25500,2269,694,480,690,1100,690,1100,690,1100,690,480,690,1100,690,480,690,1100,690,480,690,480,690,480,690,480,25500,2269,694,480,690,1100,690,1100,690,1100,690,480,690,1100,690,480,690,1100,690,480,690,480,690,480,690,480,25500,2269,694,480,690,1100,690,1100,690,1100,690,480,690,1100,690,480,690,1100,690,480,690,480,690,480,690,480,25500,2269,694,480,690,1100,690,1100,690,1100,690,480,690,1100,690,480,690,1100,690,480,690,480,690,480,690,480,25500]}
```

```json:電源OFFの赤外線コード
{\"format\":\"us\",\"freq\":40,\"data\":[2269,694,1100,690,1100,690,1100,690,1100,690,480,690,1100,690,480,690,1100,690,480,690,480,690,480,690,480,24900,2269,694,1100,690,1100,690,1100,690,1100,690,480,690,1100,690,480,690,1100,690,480,690,480,690,480,690,480,24900,2269,694,1100,690,1100,690,1100,690,1100,690,480,690,1100,690,480,690,1100,690,480,690,480,690,480,690,480,24900,2269,694,1100,690,1100,690,1100,690,1100,690,480,690,1100,690,480,690,1100,690,480,690,480,690,480,690,480,24900,2269,694,1100,690,1100,690,1100,690,1100,690,480,690,1100,690,480,690,1100,690,480,690,480,690,480,690,480,24900,2269,694,1100,690,1100,690,1100,690,1100,690,480,690,1100,690,480,690,1100,690,480,690,480,690,480,690,480,24900,2269,694,1100,690,1100,690,1100,690,1100,690,480,690,1100,690,480,690,1100,690,480,690,480,690,480,690,480,24900]}
```

以上を入力し、生成されたPOSTコマンドは下記の通りです。

```:電源ONボタンの登録コマンド
curl -X POST "https://api.nature.global/1/appliances/{3で取得したテレビのAppliancesID}/signals" -H "accept: application/json" -H "Content-Type: application/x-www-form-urlencoded" -d "message=%7B%5C%22format%5C%22%3A%5C%22us%5C%22%2C%5C%22freq%5C%22%3A40%2C%5C%22data%5C%22%3A%5B2269%2C694%2C480%2C690%2C1100%2C690%2C1100%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C480%2C690%2C480%2C690%2C480%2C25500%2C2269%2C694%2C480%2C690%2C1100%2C690%2C1100%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C480%2C690%2C480%2C690%2C480%2C25500%2C2269%2C694%2C480%2C690%2C1100%2C690%2C1100%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C480%2C690%2C480%2C690%2C480%2C25500%2C2269%2C694%2C480%2C690%2C1100%2C690%2C1100%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C480%2C690%2C480%2C690%2C480%2C25500%2C2269%2C694%2C480%2C690%2C1100%2C690%2C1100%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C480%2C690%2C480%2C690%2C480%2C25500%2C2269%2C694%2C480%2C690%2C1100%2C690%2C1100%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C480%2C690%2C480%2C690%2C480%2C25500%5D%7D&image=ico_on&name=%E3%82%AA%E3%83%B3" -k --header "Authorization: Bearer {2で取得したアクセストークン}" | jq
```

```:電源OFFボタンの登録コマンド
curl -X POST "https://api.nature.global/1/appliances/{3で取得したテレビのAppliancesID}/signals" -H "accept: application/json" -H "Content-Type: application/x-www-form-urlencoded" -d "message=%7B%5C%22format%5C%22%3A%5C%22us%5C%22%2C%5C%22freq%5C%22%3A40%2C%5C%22data%5C%22%3A%5B2269%2C694%2C1100%2C690%2C1100%2C690%2C1100%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C480%2C690%2C480%2C690%2C480%2C24900%2C2269%2C694%2C1100%2C690%2C1100%2C690%2C1100%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C480%2C690%2C480%2C690%2C480%2C24900%2C2269%2C694%2C1100%2C690%2C1100%2C690%2C1100%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C480%2C690%2C480%2C690%2C480%2C24900%2C2269%2C694%2C1100%2C690%2C1100%2C690%2C1100%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C480%2C690%2C480%2C690%2C480%2C24900%2C2269%2C694%2C1100%2C690%2C1100%2C690%2C1100%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C480%2C690%2C480%2C690%2C480%2C24900%2C2269%2C694%2C1100%2C690%2C1100%2C690%2C1100%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C480%2C690%2C480%2C690%2C480%2C24900%2C2269%2C694%2C1100%2C690%2C1100%2C690%2C1100%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C1100%2C690%2C480%2C690%2C480%2C690%2C480%2C690%2C480%2C24900%5D%7D&image=ico_off&name=%E3%82%AA%E3%83%95" -k --header "Authorization: Bearer {2で取得したアクセストークン}" | jq
```

### 5） 電源ON／OFFボタンの登録状況を確認する

上記コマンド実行後、Nature Remo のスマホアプリからテレビのリモコン操作画面を確認します。プリセットで登録されるリモコン画面の右隣の画面に、今回登録したボタンが表示されているかと思います↓
![custumn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128340/87fa46b7-85aa-3666-b470-623b40c3d8cf.png)

これで、

* ONボタンを押すと電源ON
* OFFボタンを押すと電源OFF

それぞれ独立して実行することができるようになりました🙌

このカスタムボタンを Google Home 等のスマートスピーカーから呼び出すように設定すると、トグルボタン問題をスマートに解決することができます！

![smarthome.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128340/6be571ad-4ba1-1e83-7652-78086988ce74.png)