Siri + IRKit + Homebridge でエアコンを操作すると快適

追記

MacじゃなくてRaspberry Pi で動作させるようにしました。
Siri - Raspberry Pi - iRKit でエアコン操作 - rochefort’s blog


概要

赤外線のデータ送信を行える IRKitを買った時から、Siriでエアコンの ON / OFF を行いたいと思っていました。
iPhone 6s 以降、充電中以外も Siri が反応してくれていますので、昨年iPhone7を購入したので実現してみました。
 
やってみたところ、まずまず快適です。なんつーか、楽しいです。
あえて文句を言うなら「Hey, Siri」を「Siriちゃん」に変更したいくらいでしょうか。
 
図にするとこんな感じ。
f:id:rochefort:20170106042045j:plain

IRKit

赤外線を送信するこの手のやつでは、格安の上にAPIが充実しています。Rest APIが叩ける人であれば、買って損はないでしょう。
リモコンで赤外線を送信するタイプの家電であれば、リモコン不要で操作できるようになりますし、インターネット経由での利用も可能です。位置情報やIFTTTなどと組み合わせるのも可能です。

赤外線データの確認

初期設定などは省略して、データの確認方法から。
通常は、公式に記載されている通り(IRKit - Open Source WiFi Connected Infrared Remote Controller)以下を実行すれば、最新のデータ内容が確認できます。

curl -i "http://10.0.1.2/messages" -H "X-Requested-With: curl"

しかし、先日実施したFirmwareのUpdate のせいか、bodyが取得できなくなってしまっていました。

iPhoneのパケットキャプチャ

仕方がないので、WireshirkでiPhoneをCaptureしてみました。
ググると沢山出てきますが、
iPhone端末とかのパケットキャプチャ - Qiita
iPhoneMacにつないで、XcodeでUDIDを確認(Window –> Devices)し、仮装インターフェースを作成し、あとはお好きな方法でキャプチャすればOKです。
こんなに簡単にできるとは知りませんでした。

# 仮装Interfaceの作成方法
rvictl -s <your_iphone_udid>

以降、ここでキャプチャしたデータを使います。

homebridge

こいつがイカしてるのですが、iOS HomeKit API をエミュレートする Nodeのサーバー とのこと。
nfarina/homebridge: HomeKit support for the impatient
いろんなデバイスプラグインに対応しており、roomba、hue などの面白家電達のプラグインも実装されています。
 
ただ、少々不安定。

Installation

npm -g install homebridge

あとは、 ~/.homebridge/config.json を作成(後述)し、homebridge を実行すれば、 iPhoneでHome Kit アプリとして登録することができてしまいます。

homebridge-irkit

IRKitのプラグイン
senyoltw/homebridge-irkit: Supports IRKit on Homebridge Platform. IRKitをSiri(Homekit)で操作するやつ。

Installation

nmp -g install homebridge-irkit

config.json

以下は、githubのsampleコード。 irkit_hostは、dns-sd -B irkit.tcp で調べた値を設定。 on_form、off_form は、パケットキャプチャした内容を設定。

# ~/.homebridge/config.json 
{
    "bridge": {
        "name": "Homebridge",
        "username": "CD:22:3D:E3:CE:30",
        "port": 51826,
        "pin": "031-45-156"
    },
    
    "description": "The Onion!",

    "platforms": [],

    "accessories": [
        {
            "accessory": "IRKit",
            "name": "irkit control device",
            "irkit_host": "irkitxxxxx.local",
            "on_form": {"format":"raw","freq":38,"data":[]},
            "off_form": {"format":"raw","freq":38,"data":[]},
        }
    ]
}

homebridge の launchd 登録

ここまでくると、homebridgeを起動するだけなのですが、今回はMacのサービスとして稼働させるためlaunchd へ登録します。 Install Homebridge on OSX · nfarina/homebridge Wiki
ここに記載の通り、 ~/Library/LaunchAgents/com.homebridge.server.plist を作成

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
    <key>Label</key>
    <string>com.homebridge.server</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/rochefort/.nodebrew/current/bin/homebridge</string>
        <string>-D</string>
    </array>
    <key>StandardOutPath</key>
            <string>/var/log/homebridge/homebridge.log</string>
    <key>StandardErrorPath</key>
            <string>/var/log/homebridge/homebridge_error.log</string>
    <key>EnvironmentVariables</key>
    <dict>
            <key>PATH</key>
            <string>PATH=/Users/rochefort/.rbenv/shims:/Users/rochefort/.rbenv/bin:/Users/rochefort/.nodebrew/current/bin:$PATH</string>
    </dict>
</dict>
</plist>

各種パスを適切なものに変更。
ログの場所をどうするか悩んだのですが、とりあえず、/var/log/homebridge 以下に保存。(権限に注意。とりあえずlogrotateは後回し。)
デフォルトだと、-I オプションを指定するようになっていましたが、helpを見る限り必要なさそうなのと、実際になくても動作するので無くしました。代わりに -D のdebugオプションをつけています。

allow unauthenticated requests (for easier hacking)

あとは、launchctlで登録。プロセスが起動していればok

launchctl load ~/Library/LaunchAgents/com.homebridge.server.plist

iPhoneホームアプリへの登録

登録自体は、インストラクションに従うだけですので割愛。
手動でPIN登録(config.jsonの値)すれば homebridge本体とエアコンのアクセサリーが登録されます。

こんな感じ

エアコンをつけて/消して などで操作できるようになりました。
f:id:rochefort:20170106023456p:plain かわいいw。
無駄に何度も点けたり消したりしてしまってます。

その他

iPhoneのホームアプリから、アクセサリを追加できなくなった場合

色々試しているうちに、動作が不安定になったため、一度ホームアプリからアクセサリの削除をしてみたところ、再追加できなくなってしまいました。
ググるとhomebridgeの再インストールで可能などと書かれていたりしましたが、こちらでは不可でした。
正しい対応かどうか不明ですが、とりあえず、~/.homebridge/persist を削除することで対応できました。

homebridge が socket hang up する

連続で実行すると socke hang up というメッセージがログに出力され以降の処理は失敗し続けます。
debugまではできていないのですが、こうなると、homebridge の再起動が必要なようです。