スマートメーターから電力消費量を取得する

東京電力のでんき家計簿のサービスが終わってしまったので、自由化前のプランを捨てて新プランに移行しました。
新しいプランは「くらしTEPCOweb」で使用量のグラフが見られるらしいのですが、移行してから最初の検針が終わるまでグラフを見ることができないので、ルートB経由でスマートメーターからデータを貰ってみることにしました。

Qiita だけでも同じことをやっている記事はたくさんあるのですが、一応やったことを書いておきます。

参考にした記事は以下です。

* [Skyley Networks　/　Bルートやってみた](http://www.skyley.com/products/b-route.html)
  * Tips のところにとても役に立つ情報が書いてあります  
* [スマートメーターの情報を最安ハードウェアで引っこ抜く - Qiita](https://qiita.com/rukihena/items/82266ed3a43e4b652adb)
* [Pythonでスマートメーターの情報を引っこ抜く - Qiita](https://qiita.com/kanon700/items/d4df13d45c2a9d16b8b0)
  * ここのソースをベースにさせていただきました。
* [電気スマートメーターに替えて自作で電気の見える化装置製作  |  ページ 2](https://bey.jp/?p=72123&page=2)
  * USBデバイス名を固定する方法が載っています。
  * ここに乗っていた実際の電文のログが役に立ちました。

# 準備

必要なのは、ルートBに対応した Wi-SUN のモジュールです。
メジャーなのは ROHM の BP35A1, BP35C0 あたりです。
これらは、モジュールだけでなくアダプターボードやインターフェイスボードが必要で、集めるとそこそこの値段、大きさになります。
他に、USB接続ができる BP35C2 のような製品もあります。
Raspberry Pi で使おうと思っていたので、USBドングルタイプの方がお手軽です。
USBドングルタイプの製品について調べたところ、最安値で買えそうなのが TESSERA の [RL7023 Stick-D/IPS](https://www.tessera.co.jp/rl7023stick-d_ips.html) でした。
私は TESSERA さんに直接注文して買いましたが、製品が 10,000円、送料800円、消費税込みで 11,880円でした。
ホームページから見積依頼を出すと、メールで見積が返ってきて、返事をして銀行振込をすると、商品を送って貰えます。見積書の納期は1.5週間でしたが、見積依頼をした翌日には見積書が届き、その日に発送通知、さらに翌日には届きました。(足かけ3日)
他に、[Chip One Stop](https://www.chip1stop.com/view/dispDetail/DispDetail?partId=TSRA-0000042) さんでも購入することができ、こちらだと送料、税込みで8,060円でした。

Wi-SUN モジュールの他に、電力会社に依頼してBルートの申し込みをする必要があります。
[東京電力の場合はこちら](https://www.tepco.co.jp/pg/consignment/liberalization/smartmeter-broute.html)から。
申し込むのは、小売事業者ではなく配電事業者です。
こちらは、申し込んでから受領のメールが来るまで1日、パスワードがメールで来るまで+5日、IDが郵送で来るまで+1日、合計8日かかりました。

# 参考資料

* エコーネット規格（一般公開） | ECHONET
  * [ECHONET Lite規格書 Ver.1.12（日本語版）のダウンロード ファイルリスト](https://echonet.jp/spec_v112_lite/)
      * [第2部 ECHONET Lite 通信ミドルウェア仕様](https://echonet.jp/wp/wp-content/uploads/pdf/General/Standard/ECHONET_lite_V1_12_jp/ECHONET-Lite_Ver.1.12_02.pdf)
  * [APPENDIX ECHONET機器オブジェクト詳細規定 Release Hのダウンロード ファイルリスト](https://echonet.jp/spec_object_rh/)
      * [APPENDIX ECHONET機器オブジェクト詳細規定 Release H](https://echonet.jp/wp/wp-content/uploads/pdf/General/Standard/Release/Release_H_jp/Appendix_H.pdf)
* Wi-SUN モジュールのマニュアル
  * RL7023 の場合は SKコマンドリファレンスマニュアルと言うのがダウンロードできるのですが、購入者に知らされるIDとパスワードがないとダウンロードできないので、ここにはURLを貼りません。(ROHMのものもマニュアルは一般公開ではないようです)

# 試してみる

まずは、MacBook Pro に繋いで手でコマンドを叩いてみます。
ドングルを繋いで `/dev/tty.usbserial-` で始まるファイルを探すと、シリアルデバイスが見つかります。
Unix系のOSでシリアルにアクセスするにいは tip みたいなコマンドを使った記憶があるのですが、macOS には入っていません。
screen コマンドがシリアルターミナルにもなることを知ったので、繋いでコマンドを打ってみます。

```
screen /dev/tty.usbserial-XXXXXXXX 115200
SKINFO
EINFO FE80:0000:0000:0000:XXXX:XXXX:XXXX:XXXX YYYYYYYYYYYYYYYY 21 FFFF FFFE
OK
```

他にもちょこちょこ打ってみましたが、この段階ではまだBルートのID/パスワードがないため、実際にスマートメーターに繋ぐことはできませんでした。

# Raspberry Pi に繋ぐ

Raspberry Pi に刺すと、いきなり OS が crash して再起動しました。電源OFFで繋いだ方が安全かもしれません。
うちの環境ではシリアルデバイスはこのドングル一つだけなので、`/dev/ttyUSB0`として認識しました。複数のUSBシリアルデバイスがある人は、参考記事に従ってファイル名を固定すると便利だと思います。

後は、ひたすらソースを書きます。
この記事はコードは載せませんが、書いたコードは [github](https://github.com/false-git/power-consumption) に公開してあります。

ID/パスワードがないので、他のサイトに載っている電文のやり取りを見ながら実装しました。

あ、構成ですが、以下のようになっています。

* Raspberry Pi
  * 家庭内に置いてあり、Wi-SUN ドングルを繋いである
  * 書いたプログラムのデータ収集部分を実行
* FreeBSD
  * VPS にあり、Raspberry Pi とは Wireguard で VPN を張っている
  * PostgreSQL Server と apache が動いていて、1分に一度グラフを更新している

# 結果

web ブラウザから、以下のようなグラフが見られます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3357/89654bb4-aec5-3b1f-19f6-cda9855b048c.png)
power.png

# わかったこと

* PAN の SCAN を行う SKSCAN コマンドの引数 DURATION は、マニュアルでは 6 以上を推奨していて、サイトによって 4 くらいから試しているところと、7 より上は意味がないてきなことを書いているところがありました。
 * この数字の意味は、チャンネル毎のスキャン時間を `0.01 sec * (2^<DURATION> + 1)` にすると言うもので、指数的に待ち時間が長くなります。
 * 実際に試してみた感じでは、4だと運が良ければスキャンに成功し、5だとだいたい成功するようでした。(電波状態によると思われます)
* PANA接続シーケンスの SKJOIN コマンドを呼んでから、接続成功の EVENT 0x25 が返ってくるまでに、何度か UDP パケットの送信(EVENT 0x21)や UDP パケットの受信(ERXUDP)があります。
* ECHONETLite プロパティ受信のための UDP 送信(SKSENDTO コマンド)に対し、たまに応答の UDP パケットの受信(ERXUDP) がないことがあります。通常は、3〜4秒で応答があります。今回のプログラムでは5秒でタイムアウトして再送するようにしました。
* 定常的なプロパティ受信のための UDP のやり取りとは別に、30分に一回スマートメーターから勝手に UDP パケットを送ってきます。このときの ESV は 0x73 (プロパティ値通知) です。
* 参考記事の最初のものに書いてありますが、スマートメーターとのセッションは一定時間で切れます。ほっておけば再接続が行われるのですが、そのときに UDP の送受信(EVENT 0x21, ERXUDP)があるのと、 EVENT 0x29(セッションのライフタイムが経過して期限切れになった)、EVENT 0x25(PANA による接続が完了した)が発生します。
  * これを正しく読み飛ばすことが必要です。
  * ここで、EVENT 0x24(PANA による接続過程でエラーが発生した)が発生したときは、SKSCAN または SKJOIN からやり直す必要があると思われますが、現時点では未実装です。
* ROHM の BP35A1 だと、応答の ECHONETLite 電文の部分はバイナリで返すか HEXテキストで返すかを設定で選べるようですが、RL7023 だとテキスト一択のようです。(全然困らないと言うか、この方が良い)
* (わからないこと) Channelって変わることあるの？

# おまけ

他の人の通信ログが役に立ったので、私も自分のログを出しておきます。(ID/パスワードはマスクしましたが、IPv6 のリンクローカルアドレスはマスクしていません。何かわかるかも知れないけど・・・)

## 初期シーケンス(初回のプロパティ読み出しが成功するまで)

```
2021-02-18 21:24:26.138590 SEND [SKSETPWD C XXXXXXXXXXXX]
2021-02-18 21:24:26.158053 RECEIVE [SKSETPWD C XXXXXXXXXXXX]
2021-02-18 21:24:26.180490 RECEIVE [OK]
2021-02-18 21:24:26.189826 SEND [SKSETRBID YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY]
2021-02-18 21:24:26.225616 RECEIVE [SKSETRBID YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY]
2021-02-18 21:24:26.233448 RECEIVE [OK]
2021-02-18 21:24:26.238500 SEND [SKSCAN 2 FFFFFFFF 4]
2021-02-18 21:24:26.268975 RECEIVE [SKSCAN 2 FFFFFFFF 4]
2021-02-18 21:24:26.276719 RECEIVE [OK]
2021-02-18 21:24:31.374059 RECEIVE [EVENT 22 FE80:0000:0000:0000:1207:23FF:FEA0:77F0]
2021-02-18 21:24:31.378891 SEND [SKSCAN 2 FFFFFFFF 5]
2021-02-18 21:24:31.405059 RECEIVE [SKSCAN 2 FFFFFFFF 5]
2021-02-18 21:24:31.411965 RECEIVE [OK]
2021-02-18 21:24:36.607964 RECEIVE [EVENT 20 FE80:0000:0000:0000:1207:23FF:FEA0:77F0]
2021-02-18 21:24:36.617376 RECEIVE [EPANDESC]
2021-02-18 21:24:36.628564 RECEIVE [  Channel:31]
2021-02-18 21:24:36.641159 RECEIVE [  Channel Page:09]
2021-02-18 21:24:36.652536 RECEIVE [  Pan ID:627F]
2021-02-18 21:24:36.669099 RECEIVE [  Addr:008087003017627F]
2021-02-18 21:24:36.679204 RECEIVE [  LQI:31]
2021-02-18 21:24:36.693133 RECEIVE [  PairID:00F6D083]
2021-02-18 21:24:40.380488 RECEIVE [EVENT 22 FE80:0000:0000:0000:1207:23FF:FEA0:77F0]
2021-02-18 21:24:40.558611 SEND [SKLL64 008087003017627F]
2021-02-18 21:24:40.587178 RECEIVE [SKLL64 008087003017627F]
2021-02-18 21:24:40.608980 RECEIVE [FE80:0000:0000:0000:0280:8700:3017:627F]
2021-02-18 21:24:40.621518 SEND [SKSREG S02 31]
2021-02-18 21:24:40.644997 RECEIVE [SKSREG S02 31]
2021-02-18 21:24:40.652690 RECEIVE [OK]
2021-02-18 21:24:40.657776 SEND [SKSREG S03 627F]
2021-02-18 21:24:40.682997 RECEIVE [SKSREG S03 627F]
2021-02-18 21:24:40.690605 RECEIVE [OK]
2021-02-18 21:24:40.695594 SEND [SKJOIN FE80:0000:0000:0000:0280:8700:3017:627F]
2021-02-18 21:24:40.727477 RECEIVE [SKJOIN FE80:0000:0000:0000:0280:8700:3017:627F]
2021-02-18 21:24:40.735089 RECEIVE [OK]
2021-02-18 21:24:41.128546 RECEIVE [EVENT 21 FE80:0000:0000:0000:0280:8700:3017:627F 00]
2021-02-18 21:24:41.254346 RECEIVE [ERXUDP FE80:0000:0000:0000:0280:8700:3017:627F FE80:0000:0000:0000:1207:23FF:FEA0:77F0 02CC 02CC 008087003017627F 0 0028 00000028C0000002279F1796A50FADBB00060000000400000000000500030000000400000000000C]
2021-02-18 21:24:41.485520 RECEIVE [EVENT 21 FE80:0000:0000:0000:0280:8700:3017:627F 00]
2021-02-18 21:24:41.668894 RECEIVE [ERXUDP FE80:0000:0000:0000:0280:8700:3017:627F FE80:0000:0000:0000:1207:23FF:FEA0:77F0 02CC 02CC 008087003017627F 0 0068 0000006880000002279F1796A50FADBC000500000010000070AEF4E152A68771C21C76355D3EC3A4000200000038000001C000382F000EDE3A2CDF8969A72218D0D678CB519B534D3030303030303939303231353030303030303030303030303030463644303833]
2021-02-18 21:24:41.800034 RECEIVE [EVENT 21 FE80:0000:0000:0000:0280:8700:3017:627F 00]
2021-02-18 21:24:41.996082 RECEIVE [ERXUDP FE80:0000:0000:0000:0280:8700:3017:627F FE80:0000:0000:0000:1207:23FF:FEA0:77F0 02CC 02CC 008087003017627F 0 0054 0000005480000002279F1796A50FADBD00020000003B000001C1003B2F800EDE3A2CDF8969A72218D0D678CB519B8F0C2C932CF434E8ECED9BFA87C53ECC00000000452BA112AF1B9E952F34558CCBBC80D6F400]
2021-02-18 21:24:42.254817 RECEIVE [EVENT 21 FE80:0000:0000:0000:0280:8700:3017:627F 00]
2021-02-18 21:24:42.474510 RECEIVE [ERXUDP FE80:0000:0000:0000:0280:8700:3017:627F FE80:0000:0000:0000:1207:23FF:FEA0:77F0 02CC 02CC 008087003017627F 0 0058 00000058A0000002279F1796A50FADBE000700000004000000000000000200000004000003C1000400040000000400000000070100080000000400000001518000010000001000005FEE3C1DB8585B2C53825D69664EAF88]
2021-02-18 21:24:42.839296 RECEIVE [EVENT 21 FE80:0000:0000:0000:0280:8700:3017:627F 00]
2021-02-18 21:24:42.864029 RECEIVE [EVENT 25 FE80:0000:0000:0000:0280:8700:3017:627F]
2021-02-18 21:24:43.042837 SEND [SKSENDTO 1 FE80:0000:0000:0000:0280:8700:3017:627F 0E1A 1 0016 1081000105ff010288016205d300e000e100e700e800]
2021-02-18 21:24:43.109318 RECEIVE [SKSENDTO 1 FE80:0000:0000:0000:0280:8700:3017:627F 0E1A 1 0016 ]
2021-02-18 21:24:43.308941 RECEIVE [EVENT 21 FE80:0000:0000:0000:0280:8700:3017:627F 00]
2021-02-18 21:24:43.320996 RECEIVE [OK]
2021-02-18 21:24:43.570062 RECEIVE [ERXUDP FE80:0000:0000:0000:0280:8700:3017:627F FF02:0000:0000:0000:0000:0000:0000:0001 0E1A 0E1A 008087003017627F 1 0012 108100000EF0010EF0017301D50401028801]
2021-02-18 21:24:43.575399 telegram not for me.
2021-02-18 21:24:46.784305 RECEIVE [ERXUDP FE80:0000:0000:0000:0280:8700:3017:627F FE80:0000:0000:0000:1207:23FF:FEA0:77F0 0E1A 0E1A 008087003017627F 1 0027 1081000102880105FF017205D30400000001E00400020CE7E10101E704000007C1E80400AA0032]
```

* 再接続シーケンス

```
2021-02-19 16:36:39.061889 DROP [EVENT 29 FE80:0000:0000:0000:0280:8700:3017:627F]
2021-02-19 16:36:39.383243 DROP [EVENT 21 FE80:0000:0000:0000:0280:8700:3017:627F 00]
2021-02-19 16:36:39.534179 DROP [ERXUDP FE80:0000:0000:0000:0280:8700:3017:627F FE80:0000:0000:0000:1207:23FF:FEA0:77F0 02CC 02CC 008087003017627F 0 0028 0000002810000004279F1796A50FADBC00010000001000006246C59FA52453BC332C74459EE12BBD]
2021-02-19 16:36:39.779480 DROP [ERXUDP FE80:0000:0000:0000:0280:8700:3017:627F FE80:0000:0000:0000:1207:23FF:FEA0:77F0 02CC 02CC 008087003017627F 0 0080 0000008080000002279F1796A50FADBF00050000001000005F7A8434032D58214A1E00E95CE5B1F30002000000380000013200382F00E34F4E16C5A962DB3997B00CB61A5975534D30303030303039393032313530303030303030303030303030304636443038330001000000100000F021E6A349DD6EF9041E07356640423B]
2021-02-19 16:36:39.822157 DROP [EVENT 21 FE80:0000:0000:0000:0280:8700:3017:627F 00]
2021-02-19 16:36:40.099365 DROP [ERXUDP FE80:0000:0000:0000:0280:8700:3017:627F FE80:0000:0000:0000:1207:23FF:FEA0:77F0 02CC 02CC 008087003017627F 0 006C 0000006C80000002279F1796A50FADC000020000003B00000133003B2F80E34F4E16C5A962DB3997B00CB61A5975771FE1E12BF4E2F785AF395016563A2C00000000CBC4F088BA748FCEB6E0861F6DEAFA11BA00000100000010000030F2EBE5404C15916F60BA0BCB37CCA6]
2021-02-19 16:36:40.163939 DROP [EVENT 21 FE80:0000:0000:0000:0280:8700:3017:627F 00]
2021-02-19 16:36:40.474481 DROP [ERXUDP FE80:0000:0000:0000:0280:8700:3017:627F FE80:0000:0000:0000:1207:23FF:FEA0:77F0 02CC 02CC 008087003017627F 0 0058 00000058A0000002279F1796A50FADC10007000000040000000000000002000000040000033300040004000000040000000007020008000000040000000151800001000000100000ABF04F5B29704D9B9EF0D1CEE42F1225]
2021-02-19 16:36:40.877655 DROP [EVENT 21 FE80:0000:0000:0000:0280:8700:3017:627F 00]
2021-02-19 16:36:40.911858 DROP [EVENT 25 FE80:0000:0000:0000:0280:8700:3017:627F]
2021-02-19 16:36:41.564139 DROP [ERXUDP FE80:0000:0000:0000:0280:8700:3017:627F FF02:0000:0000:0000:0000:0000:0000:0001 0E1A 0E1A 008087003017627F 1 0012 108100000EF0010EF0017301D50401028801]
```