houseリンクプラスをBLEから操作するとか赤外線リモコンの信号を見るを行いました。次はどうする?こうして調べた情報をもとに、壁スイッチとかエアコンをスマホから操作したいですね。自前でアプリを作って操作するのも手ではありますが、いまさらイチから作るのは大変。できれば既存の仕組みに乗っかりたい。Watchなので、基本「ホーム」アプリを使うことになるでしょう。このアプリを使うためには、HomeKit1に対応したデバイスが必要です。リンクプラスの操作を考えて任意のBLEパケットを読み書きするような製品を探しましたが見当たらず、やっぱり心の中の🤖が「自分で作れば良いのに...」と語りかけてきます。いうことで対応デバイスを作って、最終的にはこんな感じの画面から操作できるようにしました。以下で詳細を述べていきます。HomeKitデバイスを作るまず対応デバイスを作りましょう。ここでは方法2「ブリッジ経由で対応させる」を選びました。理由として何かこだわりがあるわけではなく、単に参考にしたページがその方法を採用していたからです。その参考にしたページは下記のとおり。plugin)を使うという構成にしています。Homebridge本体とMQTTブローカーはNAS上のコンテナで動かしました。Piなどを用意するというのも無駄に思えて、こうしています。Homebridgeとデバイス間は必ずしもMQTTである必要はありません。別にHTTPで通信しても良いでしょう。MQTTにはRetainの機能がありこれは便利でした。Retainはトピックにメッセージを保持する機能です。パブリッシャーがRetainフラグを付けてメッセージを流すと、ブローカーはそのメッセージをサブスクライバーにすぐ配信するとともに、メッセージを保持しておき今後新たなサブスクライバーが接続すると同時にそこに向けてもメッセージを再送します。これで何が嬉しいかですが、デバイスが再起動し状態を復元するのに便利です。例として照明などのアクセサリを操作する場合のHomebridgeとデバイスにおけるやり取りの流れは、HomebridgeがsetOnトピックで操作データを流すことで、デバイスに指示するデバイスはgetOnトピックで現在の状態(操作結果など)を流すことで、Homebridgeに報告となっています。ここで、2.のデバイス側ではRetainフラグを付けてメッセージを流しておき、さらに自分自身でサブスクライブ(とそれをもとに現在の状態を把握)もしておきます。すると、何らかの原因でデバイスが再起動した場合でもgetOnをサブスクライブした瞬間に以前自分が送ったメッセージからアクセサリの状態を復元できます。初期値を「OFF」など固定値にしておくと実際の状態とはズレる可能性があり、また不揮発性の領域は追加で部品が必要だったり書き換え回数の制約があったりするのでこれは避けたいです。APIを叩くことでもアクセサリの状態は取得できますが、これはlogin用エンドポイントにアクセスしてJWTを取得して......という手間がかかる一方、MQTTならRetainとサブスクライブだけで済みます。Retainによって保持されるメッセージは各トピックにつき最新1件のみです。何かRetainフラグ付きのメッセージが(他のパブリッシャーからであっても)送られれば上書きされ、また(他のパブリッシャーでも)削除することもできます。そのため、ブローカーに不特定多数がアクセスする状況だと難があると思いますが、ここではブローカーは自分専用、自分が管理するデバイスしかアクセスしないという前提です。作ったもの以上を踏まえて作ったデバイスについて紹介します。赤外線リモコン信号の送信器についてです。照明」、ほかは余裕があれば操作するくらいの気でいました。壁や天井などによる反射を期待するならもっと電流を流さないといけないようです。設置位置を考えると、すべての機器に向けてLEDを配置することはできません。電流を流すのもなぁ......まぁ最悪、エアコンが操作できれば満足なのでは?外出時にOFFにして、帰宅前にONにしたりさ......。いうことで、エアコンの操作だけを目的とし受光部めがけて赤外線LEDを配置した送信器を作りました(次図)。赤外線リモコン送信器ケースも設計し3Dプリンタで出力、基板はJLCPCBに注文しました。いう安価な発送方法が増えており、かかった費用は基板5枚と送料含めて$3程度(!)です。タイミングが良かったのか配送がめちゃめちゃ早く進んで注文から6日で受け取れました。MCUはESP-WROOM-02を使っています。理由は余っていたからです。新規でやるならESP32系のほうがBLEも使えて便利......だと思いますが、このESP-WROOM-02はたいぶ前に購入して持て余していたところ活用できて良かった。ESP-WROOM-02でもファームウェアの書き換えはOTAで行える2ので便利です。プログラムでは、MQTTメッセージに対するデバウンスを工夫しました。エアコンの操作に関するMQTTのメッセージは、setActiveトピック(ON/OFF)やsetTargetHeaterCoolerStateトピック(冷房/暖房の切り替え)、setCoolingThresholdTemperatureトピック(冷房時の設定温度)など複数のトピックに分かれて届きます。オフ状態から冷房/暖房を開始するタイミングでは各トピックに対してバースト的にデータが送られており、何かデータが届くたびに赤外線リモコン信号を送信していては無駄が多く、エアコン側でも受理してくれないかも知れません。そこで、「あるトピックでデータを受信したら100ms待って、他のトピックにデータが来ていなかったら赤外線リモコン信号を送信。データが来ていたら再びそこから100ms待って他のトピックに......」という処理を実装しています。JavaScriptでいうところのsetTimeout()とキャンセルの組み合わせのようなもの、具体的なESP-WROOM-02における実装ではTicker.hのdetach()とonce_ms()を組み合わせました。いう設定を通じてメッセージのデバウンスを行ってくれる機能もあります。これは単一のあるトピック内でのデバウンスの話っぽく今回のようにトピックまたぎでデバウンスしたい場合には適しません。赤外線リモコン送信器の話は以上。次は(リンクプラス操作用に)BLEパケットを読み書きするデバイスです。これには次図のM5Stackを使いました。残り時間」「Yahoo!デベロッパーネットワークの気象情報APIから取得した降水強度」も表示3しています。いずれの情報も外部のプログラムからMQTT経由で配信される構成です。「締切までの残り時間」の話は、後でもちょっと述べます。ホームハブはい、HomeKit対応のデバイスを作りました。これでホームアプリから操作できるといえばできるのですが......次の問題があります。Watchからの操作が不安定HAPではホームアプリとHomeKitデバイスの間でmDNSが使われる、ということで外出先からは使えません。Repeaterを使ったり、L2VPN4を使えばいける?かも知れませんが未検証です。(なお、今回のデバイスはMQTTのメッセージにより動いているため、ホームアプリが使えなくて良いなら外出先からでもVPNを張ったりして直接MQTTメッセージを送りつければ一応の操作はできます。)また、現状ではホームアプリから「オートメーション」の機能が使えません。オートメーションは時間や状態に応じてデバイスを自動的に操作してくれる機能で、これを使うためには後述の「ホームハブ」が必要です。(ここでも、今回に関してはホームアプリに頼らずデバイスに直接MQTTメッセージを投げることで似たようなことは実現できるとは思います。WatchからHomeKitデバイスを操作する場合、直接デバイスにアクセスするようです。iPhoneとペアリングしていてBluetooth経由で繋がっていたとしてもその経路は使われず、別途Wi-Fi経由でデバイスに繋ぐ必要があります。WatchのWi-Fiは不安定なようでたまにホームアプリ上のデバイスが「応答なし」になっていました。似た話でiPhoneのロック画面にホームアプリのウィジェット(現在の室温)を表示していたところ、たまにスリープから復帰する際に「応答なし」5になっていたりこの辺も不安定です。これらの問題は「ホームハブ」の導入で解決します。ホームハブはHomeKitデバイスとホームアプリを繋ぐもので、iCloudを経由することで外出先からでもデバイスの操作を可能にし、オートメーションの実行も担当します。WatchのWi-Fiをオフにしても操作できるようになります。この操作は試した限りでは安定しており、“似た話”で述べたiPhoneのロック画面でもホームハブ導入後は「応答なし」になることもなく満足です。TVなどの製品に付随する機能として提供されています。miniの中古品を購入しホームハブとしました。自分が購入した際の相場としてはだいたい8,000円ちょっとくらい。直近の相場についてはなんか安くなっていたら嫌なので調べていません。死んだ子の年を数えるな。miniに話しかけるとSiriを介したHomeKitデバイスの操作も可能です。このSiriの音量はうるさいですね......と思うこともあるかも知れません。miniの「アクセシビリティ」から「Siriの音量を自動的に調整」をオフにし、さらに音楽再生の音量を調整することで小さくできます。サイネージ以上でHomeKitの話は終わり。ついでにGrafanaで作ったサイネージも修正したので自慢します。現状はこうだ!!!Grafanaの画面これをサブモニターの一部に表示している。J1のAPI調査で得られた値を使っています。35m”とあるのはM5Stackのところで述べた何らかの「締切までの残り時間」です。この残り時間は、特定のiCloudカレンダーに登録された予定から拾っています。password)」を発行して、CalDAV経由でアクセスして予定を拾っています。