ときは2025年1月。
自宅に設置されている、三菱電機製太陽光発電システム (PV-DR004J) から情報を取得し、Grafanaで消費電力を可視化しようとしていました。
そもそもPV-DR004Jって何? ¶
ソーラー発電システムのソーラー抜きの部分(電力外形監視装置)です。
以下のふたつのパーツから構成されています。
- 計測ユニット
- 屋根裏に設置
- クランプメーターをぶら下げ電流測定を行い記録
- 表示ユニット
- リビングなどに設置
- 観測値をいい感じに表示するAndroidタブレット
なんとかして計測ユニット・表示ユニット間の通信を覗き見るなり、表示ユニットのフリをするなり、により情報を取得したいわけです。
しかし、その間の通信がWi-Fiなのか、Bluetoothなのか、ZigBeeなのか、Wi-SUNなのか全くわかっていませんでした。
説明書をよく読む ¶
ところで、説明書をよく見ると、「エアコン設定モード」なるモードがあることに気づきました。
「エアコン設定モード」は、「エアコン設定/操作説明書」(別冊)を見ると良いらしいです。
よく読むと、どうやらエアコンと接続するために、ネットワークに「中継機(無線LANルーター)」を含める構成な様です。
実際に設定してみると、以下のような構成になる事がわかりました。
ここで、アクセスポイントとして、OpenWRTを焼いた例のAP (ELECOM WAB-I1750-PS) を取り出し、tcpdumpを用い通信を横取りしてみました。
おまけ: どうやってIPアドレスは決まっている? ¶
タブレット側はOpenWRT側にDHCPでIPアドレスを聞きに来ました。Androidなのでそれはそうか、という気持ちです。
一方、計測ユニット側は192.168.43.10の固定IPなようです。適当だなあ。
実際の通信 ¶
タブレットを操作しながらWiresharkで通信を眺めたところ、消費電力のやり取りなどもしっかりと、Wireshark上に現れました。やったー!
実際の通信はというと、POST-fulでCSV-fulなAPIでした。素敵。
まず、表示ユニットが計測ユニットに対し、以下のようなPOSTリクエストを投げます。
POST /cgi-bin/moment_val.cgi HTTP/1.1\r\n
content-type: text/plain\r\n
content-length: 69\r\n
User-Agent: Dalvik/1.2.0 (Linux; U; Android 2.2.2; D000-000001-R07 Build/00.21.29-01.05)\r\n
Host: 192.168.43.10\r\n
Connection: Keep-Alive\r\n
\r\n
0078,020020,7913030012,1001,time 20250123050115,time 20250123050115\r\n
そうすると、以下のようなレスポンスが返ってくるわけですね。
result OK
value 0079,020301,7913030012,1002,time 20250123040724,time 20250123040809,0,0,763,763,,,0,,,462,222,0,0,D2,,,C,time 20250123000001,0,,,,,time 20250123000001,0,,,,,,,0,F,F
カンマ区切りで、このままでは各フィールドが何のことだかわかりません。
しかし、表示ユニット上に表示される値や、据付工事説明書などと突き合わせることで、値がないカラムを含め「全ての」カラムの意味がわかりました。やったー!
他にも、 /cgi-bin/minute_val.cgi
、/cgi-bin/hour_value.cgi
などというエンドポイントも存在し、それらも同様の手法で全てのフィールドの意味を特定しました。本当に大変だった。
需要があれば、API仕様を整備し、公開します。
謎のエンドポイント ¶
謎のエンドポイント/cgi-bin/setup.cgi
の詳細は未だ追っていません。
やる気のある人でPV-DR004Jをお持ちの方、これからお持ちになる方がいれば一緒に解析しましょう。
次回:APIクライアントの開発 ¶
これで、すぐにでもInfluxDBにでもデータを移し、可視化出来る!と思いきや。
次回:破壊と復活編 ¶
一緒に解析していた私の某友人 (✨️Security Researcher✨️ として界隈を賑わせる…!)が、計測ユニットを恒久的に破壊してしまいました!