MQTTベースのおうち環境にMESHを追加する


おうちハック Advent Calendar 22日目の記事です。ああもう23日・・・遅くなり申し訳ございません。

昨年もおうちハックAdvent Calendarに参加させていただいたわけですが、昨年からはじめたMQTTでIRKitやPhilips Hueの状況確認・操作を集約システムも動き始めて1年が経ちました。1年動かす中で、おうちハックで作ったものを安定して動かしつつ、新しいおもちゃをどう取り込んでいくかが個人的課題の一つとなってきました。

今回は、MESHをネタに、めちゃくちゃ面白そうだなあと思いつつも、買うべきか悩んで周回遅れになった背景、MESHを買ってどう遊んでいるかをざっとまとめてみたいと思います。

おうちハックの醍醐味・課題

昨年作ったこのMQTTベースのおうち管理システムは、部屋の照明一式(赤外線式の蛍光灯とHue)のまとめての制御にけっこう便利でして、意外と奥さんが使ってくれています。そのため、適切な運用管理が必要となっていたりします。(システムが死んでいるとしっかりクレームがくる)
こういう、ステークホルダーが自分自身だったり超近い人だったりするのがおうちハックの醍醐味の一つだなあと思うわけです。

おうちハックのもう一つよいところは各々のデバイスはそこそこ安価(数千~2,3万)で始めやすいことですが、これらのデバイスを組み合わせて連携などをさせていくと、システム全体ではそこそこの金額になり、システムのリプレースなどが難しい(家庭内稟議が通らない)状況になってきます。これはお金以外にも、UIのような慣れの部分のコストもあるような感じがします。(変にUIを改変するとクレームがくる)

そんなわけで、AppleのHomeKitが出てきたのに、移行の労力と奥さんのエクスペリエンスの変化を考えてスルーすることになってしまいました。

そんな感じで、考えるとほとんど仕事(インフラの運用)と同じ話になってしまうわけですが、おうちハックの動機はあくまでも技術的興味であって、遊びの部分もしっかり残しておきたいわけです。

おうちとMESH

MESHについてはさまざま記事が出ていますが、ブロック型の電子タグで、BluetoothでiPhoneなどのデバイスと接続することで、タグの変化により別のタグの状態を変化させたり、Hueのような外部デバイスを制御したりすることができます。

こういう、何というかタンジブル系は大好物ですので、触らずにはいられません。とはいえ、遊ぶだけだと、遊んでそれで終わりになってしまいがちなので、おうちシステムに統合したいと考えました。しかし年末で自由になる時間はない・・・

現在のおうちシステムの構成

MESHをどのような戦略で追加したかを説明するために、現在のおうち管理システムを簡単に紹介してみます。
現在のおうち管理システムのUIはWebベースで、スマートフォンから操作する形になっています。ざっくりと書くと、以下のようなシステム構成です。

この構成について詳しくは、

を参照いただくとして、ここの、モード切替指示用のUIの部分を、MESHを使った物理的なモノ経由での操作に置き換えたいわけです。

あと、今までUIはプログラムで作りこんでしまっていたのですが、MESHのプログラミングの仕掛けで、奥さんがカスタマイズできるとかしておくと広がりがあるかもなあとか思ったりもします。うまいことMESHアプリのうまみを残しつつ、現在のシステムに統合する手を考えたいところです。

おうちシステムへのMESHの追加

もともとMQTTを連携の中心に据えたのは、他のシステムとの相互運用性を考えていたわけですが、MESHは基本的にプロトコルは公開されておらず、MESHアプリを利用する限り、外部連携先は(2016/12/22現在)Hue, Gmail, IFTTT, OLYMPUS AIRに限られてしまいます。

HueならばMESHアプリと直接連携できますが、今回はIRKitとの連携も必要です(赤外線リモコンのLED照明がある)。そこで、MQTTをメッセージの中心に据える形を維持しつつ、IFTTT を介してMQTTとの連携を考えることにしました。

IFTTTはHTTP Requestを投げることはできるから、Request受けてMQTTにPublishするようなコードを書こうかなあ、でもこのエンドポイントの維持管理めんどくせえなと思いつつ IFTTTのトリガーおよびアクションをESP8266で実行する を読んでいると・・・あるじゃないですか、MQTTとRESTの両方をしゃべれるBeebotteなるサービスが・・・!

ということで、こんな構成にすることにしました。

これで(おうち内の話なのに、IFTTTとBeebotteが噛むのはちょっと冗長すぎる気がするけど)連携できる・・・!ということで早速MESHをおうちシステムにつなぎこんでみました。

おうちシステムへのMESH統合

自分の備忘録代わりに、おうちシステムへとどのようにMESH統合をしたか、簡単にまとめてみます。

Beebotteのアカウント作成

Beebotteにアカウントを作成し、おうち用のチャンネル home を作成しました。

今回は、従来のMQTTアクセス用に hue, irkit, itunes というリソースを用意しています。これをRaspberry Pi用に使ってみることにします。livingには、今回MESH用のsubscriberを新規に用意し、IFTTTからPOSTされるメッセージを監視することにします。

現行MQTTサーバをBeebotteに切り替える

以前作成したMQTT-デバイス間のブリッジに与える接続先パラメータを、Beebotteのものに変更します。これらのブリッジはRaspberry Pi中のSupervisordで管理していたので、hueならば以下のような感じで修正します。(MY_CHANNEL_TOKENはBeebotteが提供するものに変更すること)


[program:hue]
command=mqtt-hue -H mqtt.beebotte.com -p 1883 -u token:MY_CHANNEL_TOKEN -t home/hue/
numprocs=1
redirect_stderr=true
stdout_logfile=/var/log/hue.log
user=root

これで各mqtt-*サービスを再起動すれば、MQTTの接続先がBeebotteに変わってくれます。非常にらくちん。

MESHからのメッセージ送信-おうちでの受付

これでIFTTTを介して、MESHとおうちシステムが連携する準備が整いました。
今回はMESHの動きタグを使って、タグが表向きになったらリビングの照明点灯、裏返しになったら消灯を実現してみたいと思います。

MESHアプリからのメッセージ受付処理

Beebotteに対して home/livingをsubscribeし、与えられたメッセージに応じて各デバイスへとメッセージをpublishするようなロジックを実装します。例えば以下のような感じ。

    def on_message(client, userdata, msg):
        status = json.loads(msg.payload)['data']
        if 'mode' in status and status['mode'] == 'dinner':
            client.publish(dining_light, payload=json.dumps(dining_dinner_on))
            client.publish(irkit_messages, payload=json.dumps(living_dinner_on))
        elif 'mode' in status and status['mode'] == 'library':
            client.publish(dining_light, payload=json.dumps(dining_library_on))
            client.publish(irkit_messages, payload=json.dumps(living_library_on))
        elif 'mode' in status and status['mode'] == 'off':
            client.publish(dining_light, payload=json.dumps(dining_off))
            client.publish(irkit_messages, payload=json.dumps(living_off))
        else:
            print('Unknown mode: {}'.format(status))

BeebotteのREST API経由でデータをPOSTする場合は、 {"data": 任意のJSONデータ} みたいな形でないとBad Requestとなるようです。とりあえずは、えいやで {"data": {"mode": "library"}} のような感じで、変更すべきリビングの状態を指示することができるようにしています。

MESHアプリからBeebotteへの送信設定

MESHアプリでは動きタグの向きに応じて、IFTTTへのイベント送信と、動作確認のためのLEDタグ点滅を行う処理を記述しています。

で、IFTTT側には次のようなAppletを設定しています。
MESHアプリからのイベント受付定義は以下のような感じ。

MESHアプリから発行された living イベントを受けたら、という定義です。これに対するアクションとして、

という感じで、BeebotteのhomeチャンネルのlivingリソースにデータをPOSTしています。このとき、JSONメッセージ中に、MESHアプリからのイベントで受けた値(Text)を埋め込むようにしています。

これだけで、タグをひっくり返す行為が MESHアプリ→IFTTT→MQTTと伝わり、HueとIRKitの制御が可能になります。

まとめ

既存のMQTTベースのおうちシステムを、BeebotteのようなREST APIもサポートするサービスに接続することで、MQTTと直接接続できないMESHのようなアプリも簡単におうちシステムと連携させることができるようになりました。「タグをひっくり返したらリビングの照明が点灯・消灯する」という単純な例ですが、短時間で簡単に(仕事の合間を縫って)作って遊ぶことができました。

今回えいやで追加した感じなので、どの程度安定して稼働できるかは未知の部分もありますが(特にMESHアプリのバックグラウンド実行の継続性とか)、Beebotteのような相互運用に強いサービスを見つけたことで、IFTTTのような別のエコシステムとの接続も簡単になりそうな予感がしています。

まだまだ、おうちハックに登場するようなデバイス群は一つのプラットフォームに統一され切るのは難しそうな感じなので、うまい連携方法を探しながら、面白いものを作れるといいですねー。
ということで!