古いスマホにエアコンの番をさせる

[おうちハック Advent Calendar 2016](http://qiita.com/advent-calendar/2016/ouch-hack) の9日目の記事です。

ネットワークに繋がる赤外線リモコン送信機を作って、外出先からエアコンを操作できるようにしたという話です。まあ定番ネタですし [IRKit](http://getirkit.com/) などの専用機器を買ってくればすぐにできるんですが、今回はそうした製品を使わずDIY精神でやってみます。

## 用意するもの

- 古いAndroidスマートフォン/タブレット（機種によっては使えない場合あり。後述）
- 要らなくなったイヤホン（百均で買ってきてもOK）
- [3極ミニプラグ](http://akizukidenshi.com/catalog/g/gC-05749/)
- [赤外線LED](http://akizukidenshi.com/catalog/g/gI-04311/)数個
- はんだごて（もしあれば）

Androidデバイス以外の部品はワンコインで揃いますね。

## リモコン信号をキャプチャする
まずは実際のリモコンからの信号を記録します。

センサーには赤外線LEDを使います。LEDは光を当てると起電力を生じるので、赤外線LEDをPCのサウンドカードにつないで録音しつつ、リモコンの信号をLEDに当ててやると信号を取り込めます。

3極ミニプラグのGND端子（一番長いやつ）と左右どちらかの端子に赤外線LEDを接続します。端子の穴にLEDの足を引っ掛けるだけでOKです。LEDの+-はどちらでも構いません。

<img width=640 src="https://qiita-image-store.s3.amazonaws.com/0/65923/fd92bb7d-e1c7-7508-b0f3-cb03aa641c7e.jpeg">

プラグをPCの音声入力（マイク端子）に差し込みます。ノートPCとかだと無いかもしれませんが…。

<img height=512 src="https://qiita-image-store.s3.amazonaws.com/0/65923/e14855cd-2e34-aff7-ef41-4e9625c30f24.jpeg">


信号の取り込みと解析用にWeb Audioを使ったWebアプリを作りました。Google Chrome (Windows / Mac)とMicrosoft Edgeでのみ動作確認しています。Firefoxは[音声入力の前処理を完全オフにできない](https://github.com/irori/IRCodeAnalyzer/commit/b0813ed1d1629b2823fb0c43b8e8195ae07d53d8)みたいでうまく動きませんでした…。

https://irori.github.io/IRCodeAnalyzer/

「Start Recording」を押すとマイクの使用許可を求められ、許可すると待ち受け状態になります。この状態でリモコンの送信用LEDと受信用LEDを近づけてリモコンのボタンを押すと、受信した信号と解析結果が表示されます。なるべく正面から信号を当てるようにすると認識されやすいです。

テレビのリモコンを受信した例です。
<img width=548 src="https://qiita-image-store.s3.amazonaws.com/0/65923/a13d3648-b097-9fd1-8110-2bd28be23ef3.png">

こっちはエアコンの信号です。長いです。

<img width=549 src="https://qiita-image-store.s3.amazonaws.com/0/65923/654eaa2e-aae5-874e-4289-444d56d87c51.png">


表示されるJSONデータは[IRKitの赤外線信号フォーマット](http://getirkit.com/#section-5-JSON)に合わせたつもりですが、私はIRKitを持っていないので実際に使えるかは確認していません。

JSONの下には受信した信号を解析した結果が表示されます。信号のフォーマットは[赤外線リモコンの通信フォーマット](http://elm-chan.org/docs/ir_format.html)のページを参考にしました。

## 送信機の作成
さて、記録した信号を使うには先ほどのプラグを音声出力端子に挿し直して、録音したリモコン信号を再生すればOK…というわけには残念ながらいきません。

リモコンの信号は38kHz前後の搬送波を使って送られ、受信部ではフィルタ回路でその周波数を取り出す（自然光と区別するため）ようになっています。現在の一般的なPCやスマホの音声入出力はサンプリング周波数が44.1kHzとか48kHzなので、扱える音の周波数はその半分の22.05kHz / 24kHzまでです。なので38kHzの搬送波を上のアプリで取り込むと潰れてしまいます。同じ理由で、38kHzの音声を出力することもできません。

ではどうするのかというと、+-を交互にした2つの赤外線LEDをヘッドフォン端子に繋いで、19kHzの音声を再生するとLEDが交互に点滅して38kHzの信号が得られます。iOS用カメラ制御アプリ[DSLR.bot](http://www.dslrbot.com/)はこの方法で実現されています。賢いですね。

もう少し詳しい説明とデバイスの作り方が [リモコンプラグキットについて](http://trac.switch-science.com/wiki/ir-remote-plug-kit) のページで解説されています（残念ながら、このキットは販売終了のようです。）このページではプラグに直にLEDを取り付けていますが、設置形態を考えるとLEDとプラグの間にケーブルがあったほうが便利かもしれません。
イヤホンを使った作例が [DIY Infrared transmitter for iPhone, iPod](http://www.instructables.com/id/DIY-Infrared-transmitter-for-iPhone-iPod/) にありますが、ケーブルを剥がして出てきた線をLEDに巻きつけるだけです。（可能ならはんだ付けしたほうが安定動作すると思いますが）

私は家にあったイヤホンをちょん切って使いました。

<img width=512 src="https://qiita-image-store.s3.amazonaws.com/0/65923/0ebcf01b-ae29-e3fc-9be4-99e2b175d7c6.jpeg">

ただしAndroidはイヤホンジャックからLEDを動かすほどの出力を出せない機種が多いようで、この方法は動かないかもしれません。家にあったAndroidデバイスを一通り試してみたところ、

| 機種 | 動作 |
|:-:|:-:|
| Xperia X10 | × |
| Nexus S | × |
| Galaxy Nexus | ○ |
| Nexus 7 (2012) | ○ |
| Kobo Arc 7HD | ○ |
| Nexus 5 | × |
| Nexus 5X | × |

3勝4敗でした。あんまり分が良くないですね…。

私の手元にはありませんでしたが、赤外線送受信機能があるAndroidデバイスならそちらを使ったほうが手っ取り早いかもしれません。[赤外線API](https://developer.android.com/reference/android/hardware/ConsumerIrManager.html)はAndroid 4.4で追加されましたが、それ以前のバージョンでもメーカー独自のAPIで制御できる場合があります。下で紹介するAndroidアプリを改造して、音声の代わりに赤外線APIを使うようにするのはそれほど難しくないと思います（たぶん）。

## Android用ソフトウェアの作成
さてハードウェアの準備ができたら今度はリモコン信号を再生するソフトが必要です。ネットワーク経由で動かしたいので、[NanoHTTPD](https://github.com/NanoHttpd/nanohttpd)を使ったHTTPサーバーにしました。

ソースコードは以下にあります。後述しますがセキュリティ的にちょっとアレなので、ストアでの公開はしていません。試したい方はソースコードからビルドしてください。

https://github.com/irori/IRControlServer

起動するとサーバーのURLが表示されます。Webアプリで記録したJSON形式の赤外線情報をHTTP POSTで送ると、信号に対応する音声を生成して再生します。下はcurlで信号を送る例です。

```
curl http://192.168.1.5:8080/ -H 'Content-Type: application/json' \
  -d '{"format":"raw","freq":38,"data":[20000000]}'
```

イヤホンジャックからはLEDをギリギリ光らせるくらいの出力しか出ないので、あらかじめボリュームは最大まで上げておいてください。ちなみに上のJSONを送ると10秒間信号を出し続けるので、その間にカメラでLEDを覗くことで本当に赤外線が出ているかどうか確認できます。

AndroidのWi-Fi詳細設定で「スリープ時にWi-Fi接続を維持」を「常に接続」にしておくと画面オフの状態でも待ち受けできます。

ブラウザから操作したい場合は、どこかのサーバーに以下のようなHTMLファイルを置いておくと、ボタンを押すとJSONが送られるようにできます。（scriptタグ内の`IRControlServerURL`と`COMMANDS`を適宜書き換えてください。）

https://github.com/irori/IRControlServer/blob/master/example/remocon.html

ただしこれを使うとURLを知っている人なら誰でもリモコンを操作できてしまうので、GitHub Pagesとかに置くのはやめておきましょう。また暗号化されていないので、変なWiFiアクセスポイントなどからアクセスすると覗き見られる可能性もあります。さらに[IRKitで修正された問題](http://maaash.jp/2015/09/irkit-firmware-update/)もバッチリ残っています。

## 運用
上のようなセキュリティの問題があるため我が家ではAndroidで動いているサーバー自体はインターネットに公開せず、Linuxの自宅サーバーを経由してリモコン操作できるようにしています。

悩ましいのが設置方法で、LEDをかなり近くから、しかも良い角度で向けてやらないと反応しません。試行錯誤の結果、LEDをエアコンのリモコン受光部にセロテープで貼り付けるという原始的な方法に落ち着きました。

<img height=512 src="https://qiita-image-store.s3.amazonaws.com/0/65923/19e701b0-cf88-5607-c749-6338b99f2753.jpeg">

せめて白いケーブルのイヤホンを使えばよかった…。

この状態で数ヶ月運用していますが、見栄え以外はなかなかいい感じです。会社を出る頃にスマホのブラウザからエアコンをONしておけば帰ったときには快適な室温に。常時WiFi待ち受けしてる割には電池の持ちも良好で、Galaxy Nexusで5日くらいは充電なしで使えます。（充電器繋ぎっぱなしでもいい気がしますが）

## まとめ
家でホコリを被っていた古いAndroidを活用して、エアコンをネットワーク経由で操作できるデバイスを作りました。イヤホンジャックにLEDを取り付けるだけの単純な仕組みで、ちゃんとリモコンとして動くものができるのは面白いですね。工作も簡単なので（お手持ちの機種で動くかは運次第ですが）、冬休みの自由研究に試してみてはいかがでしょうか。

※工作は自己責任でお願いします。