テレビを確実に電源オフにできるリモコン隠しコードをNature Remoに登録する

テレビのリモコンには標準リモコンから送信できない隠しコマンドがあるのをご存じでしょうか。具体的には、リモコンには存在しない電源オンと電源オフのコマンドを大半の会社が実装しています[^mitsubishi-tv]。

[^mitsubishi-tv]: 全社全機種で実装されているわけではなさそうです。実際、我が家の三菱のテレビでは実装されていませんでした。三菱で実装されている機種もあるようです。

テレビの標準リモコンにも電源ボタンあるよね？って思う人がいるかもしれませんが、リモコンの電源ボタンはトグル（オンのときオフに、オフのときオンにする）なんですよね。電源トグルのコマンドとは別に、今の電源オンオフ状態がどうであろうと必ずオンになったり必ずオフになったりするコマンドが存在しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46856/f06a1b03-4c33-44b6-2a50-7aa356a9656d.png)

今回、我が家の日立のテレビの電源オン・電源オフのコマンドをスマートリモコンNature Remoに登録して使えるようにしました。その手順を紹介します。

必ず電源オフになるコマンドの何が嬉しいかというと、スマートスピーカーとの連携がやりやすくなる点です。私はGoogle Homeから「全部消して」と言ったら電気もテレビも全部消えて欲しいんですけど、電源トグルコマンドを登録していると全部消すつもりが消えていたテレビが点いてしまったりします。悲しいですね。

# 手順1：リモコンの隠しコードを探す

早速テレビの電源オンと電源オフのコマンドをNature Remoに登録したいところですが、まずはリモコンの隠しコードを探す必要があります。

完全に同じことをしている仲間がいれば話が早いのですが、意外と情報は見つからないんですよね。また、見つかった情報を理解する上でも赤外線リモコンの仕組みを知っていた方が良いでしょう。私は下記の文章・ソースコードを参考にしました。

- [赤外線リモコンの通信フォーマット](http://elm-chan.org/docs/ir_format.html)
- [IRremote Arduino Library](https://github.com/Arduino-IRremote/Arduino-IRremote)

また、日立テレビの電源オンオフコマンドは下記URLで見つけました。

- https://github.com/probonopd/irdb/blob/master/codes/Hitachi/TV/80%2C-1.csv

これによれば、NECフォーマットで「50af3ec1」「50af3fc0」というコードが電源オンと電源オフに対応するようです。

上記CSVファイルが含まれるリポジトリ[probonopd/irdb](https://github.com/probonopd/irdb)は赤外線リモコンのオープンソースのデータベースのようです。他社のテレビについてもここで見つかるのではないでしょうか。

# 手順2：隠しコードをNature Remo Local APIで動作確認する

Nature RemoにはLocal APIというNature Remo実機に対して直接HTTPアクセスできるAPIが提供されており、家庭内LANなど同一ネットワーク内からアクセスできます。

- [Nature Remo Local API](https://local-swagger.nature.global/)

上記ページにあるとおりNature RemoはBonjourでアクセスできるので、Nature Remoのホスト名を下記のように探すことができます[^1]。

[^1]: Macなら何もせずに動くはずですが、Linuxの場合はavahiをインストールする必要があるかもしれません。Windowsは何しても無理かも…

```
$ dns-sd -B _remo._tcp

Browsing for _remo._tcp
DATE: ---Wed 23 Feb 2022---
15:01:18.839  ...STARTING...
Timestamp     A/R    Flags  if Domain               Service Type         Instance Name
15:01:19.058  Add        2   5 local.               _remo._tcp.          Remo-******
15:01:19.200  Add        2   5 local.               _remo._tcp.          Remo-******
15:01:19.296  Add        2   5 local.               _remo._tcp.          Remo-******
```

ここで見つかった `Remo-******.local` という名前をホスト名としてNature Remoにアクセス可能です。ただし、家の中にNature Remoが複数台ある場合は上記のように複数出てきてしまうので、どれがどれだか区別する必要があります。

このLocal APIを使うと任意の赤外線信号列を発信することができます。例えば、日立テレビの電源オフのコマンドは次のように実行できます。

```bash
$ curl -X POST http://Remo-******.local/messages -H "X-Requested-With: local" \
  -d '{"format":"us","freq":38,"data":[8960, 4480, 560, 560, 560, 560, 560, 560, 560, 560, 560, 1680,
  560, 560, 560, 1680, 560, 560, 560, 1680, 560, 1680, 560, 1680, 560, 1680, 560, 560, 560, 1680,
  560, 560, 560, 1680, 560, 1680, 560, 1680, 560, 1680, 560, 1680, 560, 1680, 560, 1680, 560, 560,
  560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 1680, 560, 1680, 560, 40000]}'
```

上記の信号列を表すJSONは[IRremote Arduino Library](https://github.com/Arduino-IRremote/Arduino-IRremote)を参考に[自作スクリプト](https://github.com/hnw/analyze-ir-signal/blob/main/encode-ir-signal.py)で生成したものです。

これで実際に動作確認をしてみて、期待通りに動くようなら次のステップに進みます。

ここでうまく動かない場合は命令コードが間違っている可能性があります。同じメーカーでもリモコンのコードが何種類かあるパターンもあるようですから、標準リモコンが出している信号を解析するなどして手がかりを探す必要があるでしょう。標準リモコンからの信号データもLocal APIで取得可能です。詳しくは公式ドキュメントなどをご確認ください。

# 手順3：隠しコードをNature Remo Cloud APIから登録する

スマホアプリからも先ほどの隠しコードを使えるようにしていきましょう。これにはNature Remo Cloud APIを使います。

- [Nature Developer Page](https://developer.nature.global/)
- [Nature Remo Cloud API](https://swagger.nature.global/)

まず[Nature Developer Page](https://developer.nature.global/)の説明に沿ってOAuth2のアクセストークンを取得します。このトークンを使い、下記APIを利用すれば新しいリモコンボタンを登録できます。

- [GET /1/appliances](https://swagger.nature.global/#/default/get_1_appliances)
- [POST /1/appliances/{appliance}/signals](https://swagger.nature.global/#/default/post_1_appliances__appliance__signals)

`/1/appliances/{appliance}/signals`　の `message` パラメータはLocal APIのときに使ったJSONそのままで大丈夫です。

これでNature Remoアプリのリモコンにテレビの「電源オン」「電源オフ」ボタンを追加することができます。ただし、それだとGoogle Homeからオンとオフを呼び出せません[^2]。

[^2]: Nature Remo側の制約だと思うんですが、デバイスの種類が「テレビ」のときは電源トグルボタンしかない前提になっていて、電源オフや電源オンをGoogle Homeから呼び出せません。

あまり良い方法ではないのですが、私はNature Remoのデバイスとしてのテレビを削除し、新たな「AV機器」としてテレビのオン・オフを登録してみました。これならGoogle Homeから利用できます。ただしこのやり方だとテレビのチャンネルやボリュームの調整はできなくなってしまいますのでご注意ください[^3]。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46856/2b62d6ba-71d1-0d12-4c93-5b8eb709ca93.png)

[^3]: 私はGoogle Homeから「全部消して」を実現したかったので、電源トグルしかないテレビは削除するしか選択肢がありませんでしたが、不便でないなら「AV機器」と「ＴＶ」2つとも残して運用してもよいでしょう。