リンクプラスの照明8灯がenlで見えない——犯人はWSL2だった
「ECHONET Lite対応」のはずの機器が、探索コマンドにいっさい応答しない。pingは通る。専用アプリからは普通に操作できる。なのに、ECHONET Liteの窓口であるUDPポート3610だけが沈黙している——そんな状況に心当たりはないでしょうか。
先日、うちの照明でまさにこれが起きました。壁スイッチはPanasonicのアドバンスシリーズ「リンクプラス」。壁のスイッチたちを家のネットワークにつなぐための専用アダプタ「WTY2001」を経由して、スマホアプリから点けたり消したりできるやつです。
このWTY2001はECHONET Liteに対応していて、認証機器としてECHONETコンソーシアムにも登録されている、公式のお墨付き。前回の記事「ECHONET Liteとは?家のシャッターを3コマンドで動かす」で家じゅうの機器を探しシャッターを閉じた、自作CLIの enl で動かないはずがない。
——そう思っていたんですが、これがまったく見えませんでした。原因を突き止めるまでの顛末を書きます。先に言っておくと、犯人は機器ではありませんでした。
discoverに出てこない
まずはいつもどおり、LANを探索します。--cidr に渡しているのはCIDR記法という、IPアドレスの範囲をまとめて表す書き方です。192.168.213.0/24 なら「192.168.213.0〜192.168.213.255 の256個ぶん」という意味で、ここでは自宅LANのアドレス帯を指定しています(本記事のIPアドレスはすべて例に置き換えています)。
$ enl discover --cidr 192.168.213.0/24
返ってきたのは2台だけでした。
| IP | メーカー | 機器 |
|---|---|---|
| 192.168.213.21 | シャープ | ヘルシオ ホットクック(調理器) |
| 192.168.213.22 | 三和シヤッター工業 | 電動シャッター ×5 |
シャッターとホットクックは元気に返事をしてくる。でも、肝心のリンクプラスがいない。
LAN上に生きているホストは約31台。そのうちECHONET Lite(UDPポート3610)に応答したのが、この2台だけということです。
アダプタのIPはルーターのDHCP一覧からわかっていたので、直接叩いてみます。
$ enl get 192.168.213.30 0EF001 D6
タイムアウト。無言です。pingには応答するし、Web UIも生きていて、点灯・消灯・調光のボタンまで表示される。つまり本体は元気なのに、3610だけが沈黙している。
容疑者を並べる
ここから原因の切り分けです。考えられる容疑者はこのあたりでした。
- ファームウェアがECHONET Lite対応前——認証の登録は2025年9月とごく最近。対応はファーム更新で入った可能性がある
- どこかにECHONET Liteの有効化設定がある——Web UIには該当項目なし。アプリ側にあるのかも
- AiSEGとの共存問題——Panasonicの公式ページに「AiSEG連携時は無線アダプタを使用できない」という注記がある。うちにはAiSEG2がいる
ファームウェアを確認し、更新チェックをかけ(「更新なし」)、初期設定をやり直し、アダプタ本体の登録ボタンを押しに行き……と一通り潰しましたが、状況は変わらず。unicastのGetにもマルチキャストの探索にも、いっさい応答しません。
このあたりで、だいぶ心が折れかけていました。
「マルチキャストにしか応答しない」説
転機は、検証マシンを変えたことでした。
それまで叩いていたのはWSL2上のLinuxです。試しにWindowsホスト側から直接フレームを送ってみると——挙動が変わりました。
ここで言うマルチキャストは「グループ宛の一斉送信」のことです。ECHONET Liteでは 224.0.23.0 という専用のマルチキャストアドレスが規格で決められていて、ここ宛に1発送ると、LAN上の対応機器がまとめて受け取ってくれます。機器のIPアドレスに1対1で直接送るunicastと対になる送り方です。
- マルチキャスト(224.0.23.0宛)のGet → 応答が返る
- 直後に同じ内容をunicast(機器のIP宛)で送る → 無視
見えた、と思いました。「WTY2001はunicastを無視して、マルチキャスト宛のフレームにしか応答しない機器なんだ」と。
実はこの仮説、enlの設計と正面からぶつかります。enlの discover は「CIDRスイープ方式」で作っていました。指定した範囲(たとえば 192.168.213.0/24 の256アドレス)の1つ1つに向かって、順番にunicastのGetを送り、返事があったアドレスを機器とみなすやり方です。マルチキャストを使わなかったのは、Wi-Fi経由の通信や、IGMP(ルーターやスイッチがマルチキャストの配送先を管理するための仕組み)まわりの設定しだいで取りこぼしが起きやすい、という理由でした。ただこの方式では、マルチキャストにしか応答しない機器は原理的に見つけられません。
しかも、マルチキャストで探索してみるとLAN全体で8ノードが応答しました。スイープで見えていたのは2台。AiSEG系の機器など、残りは全部見逃していたことになります。
というわけで、enlにマルチキャスト対応を実装しました。
get/set/describe/rawに--multicastフラグを追加(送信先を224.0.23.0に切り替え、応答は指定IPから待つ)discoverはスイープとマルチキャストの常時併用に変更
マルチキャスト探索は「グループ宛に1発送れば、対応機器のほうから名乗り出てくる」方式なので、スイープと違ってアドレス範囲の指定がそもそも要りません。おかげでCIDRを省略して、enl discover と引数なしで打つだけでも動くようになりました。
そしてマルチキャスト経由で、ついにリンクプラスの中身が見えました。照明システム(02a301)と、一般照明が8灯(029101〜08)。ワイルドカード指定のGetを1発投げると、8灯ぶんの点灯状態がまとめて返ってきます。
やった、解決だ——と、このときは思っていました。
どんでん返し——真犯人はWSL2
実装を終えて、LANに直結して常時起動しているラズパイにenlをデプロイして、実機検証をしたときのことです。
unicastでも、普通に応答が返ってきました。
リンクプラスを含む全機器が、unicastのGetにちゃんと答える。「WTY2001はマルチキャストにしか応答しない」という観測は、誤りだったんです。
では、あの沈黙はなんだったのか。真犯人は、検証環境のほうでした。
WTY2001は、unicastへの応答をエフェメラルポート(毎回変わる送信元ポート)から返すタイプの機器でした。そしてWSL2やWindowsを経由するUDPは、この「3610以外の送信元ポートから戻ってくる応答」を取りこぼすことがある。
なぜ取りこぼすのか。UDP自体はコネクションを持ちませんが、WSL2のNATやWindowsのファイアウォールは、外へ出たパケットを「送信元と宛先のIP・ポートの組」でフローとして記録し、その組がひっくり返って一致する戻りパケットだけを「さっきの応答だ」とみなして通します。こちらは 機器のIP:3610 宛に送っているので、応答と認められるのは 機器のIP:3610 から返ってくるパケットだけ。エフェメラルポートから返ってきた応答は、記録したフローに一致しない「頼んでいない着信」と判定され、ソケットに渡る前に捨てられます。機器はずっと返事をしていたのに、その返事がこちらのソケットに届く前に消えていたわけです。
思い返せば、伏線はありました。シャープと三和シヤッターの機器は、応答を送信元ポート3610から返します。WSL2から見えていたのがこの2台だけだったのは、偶然ではなく「ポート3610から返す機器だけが生き残っていた」から。tcpdumpを取ると、応答フレームはネットワークインタフェース(マシンのネットワークの入り口)までは届いているのに、ソケット(プログラムがOSからパケットを受け取る窓口)には渡ってきていませんでした。取りこぼしていたのは機器でも配線でもなく、OSがパケットをプログラムへ渡すまでの経路だったということです。
Windowsホストでの「unicastは無視される」も、同じ取りこぼしを機器のせいだと誤読していただけでした。
この失敗から持ち帰ったこと
機器を疑う前に、検証環境を疑う。 今回いちばんの教訓はこれです。そもそもWSL2は、Windowsの中の仮想環境からNATを介してLANに出ていく特殊なネットワーク構成で、素のLinuxと同じようには振る舞いません。LAN内のUDPを検証するなら、最初からLAN直結の素のLinux(ラズパイなど)でやるべきでした。
「応答がない」は「機器が応答していない」を意味しません。送ったフレームが届いていないのか、応答が出ていないのか、応答は出ているのに自分が受け取れていないのか。UDPはこの3つを区別してくれないので、疑わしいときは機器の近く(LAN直結のマシン)でパケットキャプチャを取るのが確実です。
一方で、誤った仮説から生まれたマルチキャスト対応は、そのまま残しました。マルチキャスト探索はECHONET Liteの標準的な探索方式ですし、CIDRを知らなくても enl discover が引数なしで動くのは普通に便利。--multicast フラグも、今回のように「経路のどこかでunicastが損なわれる環境」を切り分ける道具として使えます。動機は間違っていたけれど、機能は正しかった、という着地です。
いまは8灯の照明の状態が、ラズパイ上のenlから一発で読めるようになりました。読めるということは、あとは点けたり消したりするだけ。次はこの照明たちを casa の自動化に組み込んでいくところを書ければと思っています。
同じようにWSL2でECHONET Liteやスマートホーム機器と格闘している方がいたら、この記事がまるごと一日ぶんの回り道の短縮になれば幸いです。