2022/09/04(Sun)霧ヶ峰REMOTEの機器登録バグの回避方法

2022/09/04 16:17 Hardware::Appliances
2020年に購入した三菱電機のエアコン「霧ヶ峰」をリモート操作するアプリこと「霧ヶ峰REMOTE」をセットアップするのに大変苦労したので、同じように困った人向けにメモを残しておく。

TL;DR

結論から書くと、エアコン内の無線LANソフトバージョンと霧ヶ峰REMOTEアプリのバージョンには一部動作しない組み合わせがあるので、旧アプリを入れてファームウェア更新したあとにアプリを最新にするとよい。
まあセットアップを進める時点では、エアコン側の情報表示も乏しく、スマホだけで障害の原因特定もできないので、結果として使えないという文句が付くのだろうな……。

環境情報

  • エアコン型番:霧ヶ峰 MSZ-ZXV2220-W (2020年モデル、Zシリーズ、無線LANモジュール内蔵型)
    • 無線LANソフトバージョン:31.00
  • 執筆時点の霧ヶ峰REMOTEのバージョン:3.70
  • 検証スマホ:Android 11および12にて検証

必要な技術的要件

公式ページによれば、
  • Android 5~12, iOS 10~15 (as of 2022/08/26)
  • インターネット回線
  • 無線LANルータ
    • WPA2-PSK
    • IPv4でDHCPが有効
    • ネットワーク分離機能が無効
とのことで、まあ、一般的なご家庭ならだいたい問題無さそうなスペック……。

にも関わらず、Google Playや、Apple Storeでは低評価レビューの嵐だったので、こりゃなんかあるな…と予想していた通りあった。
そもそも購入直後の2020年は、コロナ禍で在宅が多くスマホから電源入り切りする必要も無いと言うことで「そんな低評価のアプリなんか入れない~」と放置していたけれど、2022年は外出も増え、酷暑の日々も多く、まあ付けっぱなしでも良いけど、毎日タイマーセットして外出するのも煩わしいということで、使ってみることにしたのがきっかけ。

事前準備

我が家のWi-FiはWPA-EAPがデフォルトで、EAPを喋れない哀れな家電の子達のために一応PSKのSSIDも用意してあるのだけど、セキュリティを高めるために基本的にはネットワーク分離機能を有効にしてあって、他の無線機器とは通信させないので、セットアップの期間中だけ一旦これを解除。ここまでは他の家電達と同じなので手慣れたもの。

そして、アプリ側ではまず各社のアカウントを取得してログイン、その後自宅Wi-FiのSSID/PSKを入力させ、機器に転送してペアリングというのが定石で、この瞬間だけ機器間をWi-Fi Directで繋ぐのは当然かなと思うけど、今回は罠が少々。

kirigamine01.png

エアコン側の無線機能を有効にする

ペアリング操作を開始するためには、リモコンを使って無線機能を有効にする。
うんうん、ここまではよいのだけど、ルータ接続モードがグレーアウトしていて、どうやら一度エアコンをOFFにしないと出来ない。しかも、設定が完了するまで数秒ごとにビープ音が鳴るので、ユーザビリティがなっとらん……。試行錯誤してる間、じわじわと汗かくし、ビープ音が鳴ってるので急かされてるような気もするし。
(いつまでOFFにしないといけないのか書いてないけど)エアコンがインフラストラクチャモードで繋がれば、運転を開始しても問題無かった。

Wi-Fi DirectのPSK

で、先のWi-Fi Directがオンになれば、ME-xxxxxxxx(xはMACアドレスとも違う適当な英数字)というSSIDが吹き始める。
まあ、複数台のエアコンを一気にセットアップする機会がゼロとは限らないので、SSIDを適当に分けておくのは得策だと思うけれど、このSSID/PSKは、室内機の蓋の中に貼られているシールを確認しないと分からない。
なので、ここは予めスマホ撮影しておかないと辛いのだけど、結局、カメラアプリと霧ヶ峰REMOTEを行ったり来たりで面倒。

底面にも製品型番や定格電流などの記載シールがあるのだから、ここに書いて置いてくれれば見上げるだけ良いのにね?しかも乱数パスワードにしなくても良くない?てか、設定用にしか使わないし、そもそもこれにPSK必要ないのでは…て気も。*1


で、無事Wi-Fi Directに繋がると、エアコン側が192.168.11.1でHTTPサーバを立ち上げ、http://192.168.11.1/networkにSSIDとPSKを送信するフォームが準備される。
ふむふむ、あとはこれをアプリ側からkickして設定完了やな…?と思ってたら


繋がらん。

kirigamine02.png
kirigamine03.png


無線LANルータ側のネットワーク分離は外したのに何故?通信できるでしょ、と思ったけれど、どうやらスマホ側でファイアウォール替わりに常時VPNをオンにしてたのが原因ぽく、おそらく192.168.11.0/24でないアドレスが振られている!と勘違いしてのエラーっぽい。
この時だけVPNを解除し、先に進んだ…

kirigamine04.png
kirigamine05.png


MAC番号は選ぶだけ(といっても実質一択なのに何故?)で、ID番号ってなんじゃらほいと思ったら、さっきの室内機のシールに貼ってあった10桁の番号を入れさせるものだった。
適当に入れたら通信する間も無く、即時エラー表示されるので、なんらかのハッシュで求められる物?というか、このID番号を入力する意義が分からない。
クラウドからコントロールするための一意なIDのだと想像しているけど、それをユーザに入れさせる必要は無いと思う。

まあ仕方なく入力して次へ。

kirigamine06.png
kirigamine07.png


は?ナメとんのか……

しばらく時間をおいてみるも状況変わらず、この時点で分かることは
  • リモコンから無線設定の「状態確認」をすると、「エアコンの無線機能は『入』です。ルーターとの接続も完了しています」と表示される
  • 無線APコントローラから見て、エアコンはアソシエーションに成功していて、IPアドレスを取得し、外部と通信できるような状態である
  • ルータ側からping疎通に反応する
ので、外に繋がらないわけでは無さそう。何故???

全然分からないので、スマホにUSBデバッグで接続して、logを読んでみる。

air.jp.co.MitsubishiElectric.KirigamineRemoteのPIDを取得して、logcatで参照。
$ ./adb.exe shell ps | grep Mitsu | tr -s [:space:] ' ' | cut -d ' ' -f2
15264

$ ./adb.exe logcat | grep -F 15264
09-03 01:51:20.130 15264 19918 W System.err: java.net.SocketException: already bound
09-03 01:51:20.133 15264 19918 W System.err:    at java.net.DatagramSocket.bind(DatagramSocket.java:396)
09-03 01:51:20.133 15264 19918 W System.err:    at air.jp.co.MitsubishiElectric.KirigamineRemote.MainActivity.lambda$startReceiveUdpBroadcast$1(MainActivity.java:398)
09-03 01:51:20.133 15264 19918 W System.err:    at air.jp.co.MitsubishiElectric.KirigamineRemote.-$$Lambda$MainActivity$ogPkL6qy_ULKAUtYZsX9UKHkVTA.run(Unknown Source:2)
09-03 01:51:20.133 15264 19918 W System.err:    at java.lang.Thread.run(Thread.java:923)
09-03 01:51:20.294 15264 15264 E TEST    : NetworkStatusReceiver
09-03 01:51:20.294 15264 15264 E TEST    : NetworkStatusReceiver
09-03 01:51:24.989 15264 19918 W System.err: java.net.SocketException: Socket closed
09-03 01:51:25.002 15264 19918 W System.err:    at libcore.io.Linux.recvfromBytes(Native Method)
09-03 01:51:25.002 15264 19918 W System.err:    at libcore.io.Linux.recvfrom(Linux.java:210)
09-03 01:51:25.002 15264 19918 W System.err:    at libcore.io.ForwardingOs.recvfrom(ForwardingOs.java:182)
09-03 01:51:25.002 15264 19918 W System.err:    at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:335)
09-03 01:51:25.002 15264 19918 W System.err:    at libcore.io.ForwardingOs.recvfrom(ForwardingOs.java:182)
09-03 01:51:25.002 15264 19918 W System.err:    at libcore.io.IoBridge.recvfrom(IoBridge.java:594)
09-03 01:51:25.002 15264 19918 W System.err:    at java.net.PlainDatagramSocketImpl.doRecv(PlainDatagramSocketImpl.java:153)
09-03 01:51:25.003 15264 19918 W System.err:    at java.net.PlainDatagramSocketImpl.receive0(PlainDatagramSocketImpl.java:141)
09-03 01:51:25.003 15264 19918 W System.err:    at java.net.AbstractPlainDatagramSocketImpl.receive(AbstractPlainDatagramSocketImpl.java:164)
09-03 01:51:25.003 15264 19918 W System.err:    at java.net.DatagramSocket.receive(DatagramSocket.java:847)
09-03 01:51:25.003 15264 19918 W System.err:    at air.jp.co.MitsubishiElectric.KirigamineRemote.MainActivity.lambda$startReceiveUdpBroadcast$1(MainActivity.java:405)
09-03 01:51:25.003 15264 19918 W System.err:    at air.jp.co.MitsubishiElectric.KirigamineRemote.-$$Lambda$MainActivity$ogPkL6qy_ULKAUtYZsX9UKHkVTA.run(Unknown Source:2)
09-03 01:51:25.003 15264 19918 W System.err:    at java.lang.Thread.run(Thread.java:923)
09-03 01:51:30.832 15264 15277 W irigamineRemot: Reducing the number of considered missed Gc histogram windows from 143 to 100
09-03 01:52:50.286 15264 20295 W System.err: java.net.SocketException: already bound
09-03 01:52:50.294 15264 20295 W System.err:    at java.net.DatagramSocket.bind(DatagramSocket.java:396)
09-03 01:52:50.294 15264 20295 W System.err:    at air.jp.co.MitsubishiElectric.KirigamineRemote.MainActivity.lambda$startReceiveUdpBroadcast$1(MainActivity.java:398)
09-03 01:52:50.294 15264 20295 W System.err:    at air.jp.co.MitsubishiElectric.KirigamineRemote.-$$Lambda$MainActivity$ogPkL6qy_ULKAUtYZsX9UKHkVTA.run(Unknown Source:2)
09-03 01:52:50.294 15264 20295 W System.err:    at java.lang.Thread.run(Thread.java:923)
09-03 01:52:50.461 15264 15264 E TEST    : NetworkStatusReceiver
09-03 01:52:50.461 15264 15264 E TEST    : NetworkStatusReceiver
09-03 01:55:49.318 15264 20295 W System.err: java.net.SocketException: Socket closed
09-03 01:55:49.376 15264 20295 W System.err:    at libcore.io.Linux.recvfromBytes(Native Method)
09-03 01:55:49.376 15264 20295 W System.err:    at libcore.io.Linux.recvfrom(Linux.java:210)
09-03 01:55:49.376 15264 20295 W System.err:    at libcore.io.ForwardingOs.recvfrom(ForwardingOs.java:182)
09-03 01:55:49.376 15264 20295 W System.err:    at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:335)
09-03 01:55:49.376 15264 20295 W System.err:    at libcore.io.ForwardingOs.recvfrom(ForwardingOs.java:182)
09-03 01:55:49.376 15264 20295 W System.err:    at libcore.io.IoBridge.recvfrom(IoBridge.java:594)
09-03 01:55:49.376 15264 20295 W System.err:    at java.net.PlainDatagramSocketImpl.doRecv(PlainDatagramSocketImpl.java:153)
09-03 01:55:49.376 15264 20295 W System.err:    at java.net.PlainDatagramSocketImpl.receive0(PlainDatagramSocketImpl.java:141)
09-03 01:55:49.376 15264 20295 W System.err:    at java.net.AbstractPlainDatagramSocketImpl.receive(AbstractPlainDatagramSocketImpl.java:164)
09-03 01:55:49.376 15264 20295 W System.err:    at java.net.DatagramSocket.receive(DatagramSocket.java:847)
09-03 01:55:49.376 15264 20295 W System.err:    at air.jp.co.MitsubishiElectric.KirigamineRemote.MainActivity.lambda$startReceiveUdpBroadcast$1(MainActivity.java:405)
09-03 01:55:49.376 15264 20295 W System.err:    at air.jp.co.MitsubishiElectric.KirigamineRemote.-$$Lambda$MainActivity$ogPkL6qy_ULKAUtYZsX9UKHkVTA.run(Unknown Source:2)
09-03 01:55:49.376 15264 20295 W System.err:    at java.lang.Thread.run(Thread.java:923)
いやいや……。ソケット周りでチョンボしている様子。
スマホ側のファイアウォールのログから、AWSと通信しているようだけど、通信相手が間違ってるか、ネゴシエーション手順が変わったとかか…。
ありがちなのは、TLS 1.0や1.1が切られたり、証明書の検証失敗でネゴシエーションできないという話だけど、DatagramSocketといっているのでUDPぽく、already boundからSocketが閉じられているので、何かポート番号決めうちでbindしようとして失敗?これ以上は、ログから分からないので一旦打ち止め。

*1 : 実際、SHARPの空気清浄機をセットアップしたとき、同じような手順ではPSK不要でした。

アプリバージョン変更

あんまり野良apkからインストールするものでは無いというのは鉄則だけど、どうやら上記の調査結果から、アプリ側に不備がありそうな挙動なので、一つ前のバージョンを試してみることに。
apkpure.comから、V3.6.0をダウンロードしてきてUSB経由でインストール。
一応、Trusted badgeという仕組み*2があるので、Signatureがverified 🛡 となっているのは信用してます。

kirigamine08.png
kirigamine09.png


で、試してみると

kirigamine10.png


あっけなく完了。ということは、V3.7.0で何か壊したようですね………(ぉぃ)少なくとも3ヶ月は放置されてるみたいですけど。


で、エアコンの名称設定などが済んだら、メインメニューへ。長かった…

kirigamine11.png
kirigamine12.png


*2 : 以前バージョンあるいは、同じ開発者の別アプリと同じ署名が一致されているかのチェック

無線LANソフトを更新

で、現状を確認すると、無線LANソフトを更新できますということで、V31.00をアップデートしてみる。
kirigamine13.png
kirigamine14.png
kirigamine15.png


スマホ画面を戻ったり再度開いたりしてリロードしていること2分、バージョンがV36.00に更新された。

kirigamine16.png
kirigamine17.png


この状態で、Google Playから最新版にしておく。
kirigamine18.png
kirigamine19.png


すると、更新後もエアコンの登録は維持されていたし、再登録し直しても問題無く完了できた。
しかも一度アカウントに紐づけてしまえば、他のスマホではアカウントにログインするだけで登録機器を共有できるのは良い実装。(SHARPのは、スマホ毎に機器登録が必要で面倒。なんのためにログインしてると思ってるんじゃい)

自宅モード/宅外モード

家電によっては、設定完了後に再びネットワーク分離機能をONにし、機器と直接通信出来ない状況にすると動作が怪しくなるパターンもあったりしたが、この点に限っては優秀な感じ。
普段のスマホは、WPA2-PSKではなくWPA-EAPのSSIDで(ネットワークはPSKと同一だが、無線機器同士が直接通信できない)、しかも常時VPNで変なローカルアドレスが付いているものの、自宅モードとして認識でき、おそらくクラウドのAWS経由で電源の入り切り、熱画像のやりとりも出来ている。

kirigamine20.png

最後に

最新のエアコンは出荷時に新しいファームウェアにしてるでしょうから問題無いでしょうけど、こうやって旧機種を発売後時間が経ってから初めてセットアップする事も考えて、互換性維持は頑張ってもらいたい物ですね。フォールバックロジックを入れるとか。

ただ霧ヶ峰、エアコンとしては非常に優秀なので、総合的には満足してます。
これまで2年間使ったところでは、夏場あんなに冷房・除湿で酷使したのに、回転フィンやルーバに全く黒カビが付かなくて(ウェットティッシュで擦っても何も付かない)、フィルタも全然汚れて無くて、「んなアホな…」と思ったらお掃除ボックスにはきっちり埃が溜まってて。
カビガート・内部乾燥をきちんとオンにして使っているのもあるけれど、高温多湿の最近の夏を2度も過ごして、ここまでメンテフリーだと驚くばかりです。(前住居の他社備え付けエアコンは、同様の使い方をしてても黒カビが定期的に発生)