自宅に導入を本格的に導入検討しているので、それ関連の話題はこちらhttps://jinkouki.net/solarpower/に。
せっかくなので、MTのテーマも変えてみることに。
といってもあまり複雑なことはしない、https://atstyle.biz/theme_temp/mt6_bootstrap_blog/301/に。
script関連は、google-code-prettifyが標準で使えるようなので、こちらを。
ここらあたりに記述例がある。
https://www.omakase.net/blog/2022/01/google-code-prettify.html
IIJmio の3つのsimで容量シェアしたときに一番安い組み合わせ
いま3つのsim契約をしていて、データ容量シェアしている。使わなかった分は翌月に持ち越しできるので、容量オーバーにならないよう細かに契約料の変更をしていけば、わずかに(200円程度?)は無駄を無くせる。
で、1sim契約あたり、2,5,10,15,20 Gの契約ができて、どの組み合わせが最適(最安)か?というのを計算しておく。
3つの契約で5パターンのコンビネーションで、重複ありのケースは35通りあるようで、そのおのおののケースの契約総容量と金額を作って、金額の順にソートしていったもの。
〇が意味があるところで、×は他の契約パターンで金額が逆転してしまうので選択してはいけないケース。
パターンは、0=2G,1=5G,2=10G,3=15G,4=20G を意味している。
2023/09での金額は、2G=850,5G=990,10G=1500,15G=1800,20G=2000
家族での利用料を見ると月に 7Gから18G あたりをうろちょろしているので、
9G,12G,15G,17G,20Gあたりの契約をうろちょろすることになるか?
あんまり節約にもなってないかもですが、気持ちだけ。
パターン 総容量 契約額 1Gあたり単価(契約額/総容量)
〇 000 6 2550 425.0
〇 001 9 2690 298.8888888888889
〇 011 12 2830 235.83333333333334
〇 111 15 2970 198.0
× 002 14 3200 228.57142857142858
〇 012 17 3340 196.47058823529412
〇 112 20 3480 174.0
× 003 19 3500 184.21052631578948
〇 013 22 3640 165.45454545454547
〇 004 24 3700 154.16666666666666
〇 113 25 3780 151.2
〇 014 27 3840 142.22222222222223
× 022 22 3850 175.0
〇 114 30 3980 132.66666666666666
× 122 25 3990 159.6
× 023 27 4150 153.7037037037037
× 123 30 4290 143.0
〇 024 32 4350 135.9375
× 033 32 4450 139.0625
〇 124 35 4490 128.28571428571428
× 222 30 4500 150.0
× 133 35 4590 131.14285714285714
〇 034 37 4650 125.67567567567568
〇 134 40 4790 119.75
× 223 35 4800 137.14285714285714
〇 044 42 4850 115.47619047619048
〇 144 45 4990 110.88888888888889
× 224 40 5000 125.0
× 233 40 5100 127.5
× 234 45 5300 117.77777777777777
× 333 45 5400 120.0
〇 244 50 5500 110.0
× 334 50 5600 112.0
〇 344 55 5800 105.45454545454545
〇 444 60 6000 100.0
pythonで、組み合わせを一気につくれる関数が使えるので、それで。
comb = itertools.combinations_with_replacement('01234', 3)
influxdb + grafana + python3 + python-influx データ投入 stringになってしまった。
InfluxDB Error: unsupported mean iterator type: *query.booleanInterruptIterator
というエラーが出た。meanが取れない?何でと思って、influxの中で各種データを見たら、ジャイロ、加速度、温度、気圧、その他全てのデータが 'string'になっていた。 cactiで使っているプログラム(python3)で、redisからデータを取ってきて do.wirte_points で書き込んでるだけだけど、redisで引っ張ってきたデータが文字列処理をしていることもあり、string形式を保ったまま influxdbに放り込まれてたっぽい。 float()とか int()(バッテリーは%の整数値)とcastして放り込み直して解決。
switchbot 温湿度計2つ目 交換品
がamazonから送られてきたのでさっそくつ買ってみた。冷蔵庫の中に新しいものと古いものをほぼ同じ場所に置いて計測。(cactiから influxdb + grafana に移行中)
データは5分に1回取得するように設定。一目瞭然で、新しい方はほぼデータを拾えているのに、古い方は1時間1回程度。
製品の性能にばらつきありすぎのような気もするけど、中華製ならこんなもんですか?
とりあえずこの新しいものを冷蔵庫に。
また、gatt でエラーが出る件についても、新しい方では解消しなかった。
charastaristicsは同じようだが。。。
ただ、公式githubには、同じことを言っている人がいる。2022/02/10 の投稿のようなのでやはり最近の話っぽい。公式のレスポンスは無いが、そろそろ何か書き込みあるかも。
スマートメーター HEMS データのグラフ化 for python3
HEMSでデータが取得出来るようになったので、時系列でグラフ化してみる。
自宅では特に発電してるわけでもないので、「定時積算電力量計測値(逆方向計測値)」とか、履歴はいらないか。
ここでは「瞬時電流計測値」「瞬時電力計測値」「積算電力量計測値(正方向計測値)」「積算電力量計測値(逆方向計測値)」を測り、cacti の scriptsで動かして5分毎のデータをグラフ化。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# smartmeter.py3
#
from __future__ import print_function
import sys
import serial
import time
# Bルート認証ID(東京電力パワーグリッドから郵送で送られてくる)
rbid = "AAAABBBBCCCCDDDD"
# Bルート認証パスワード(東京電力パワーグリッドからメールで送られてくる)
rbpwd = "PASSWORDDDDDDD"
# シリアルポートデバイス名
#serialPortDev = 'COM3' # Windows の場合
serialPortDev = '/dev/ttyUSB0' # Linux(ラズパイなど)の場合
#serialPortDev = '/dev/cu.usbserial-A103BTPR' # Mac の場合
#
ser = serial.Serial(serialPortDev, 115200)
#
# Bルート認証パスワード設定
wcom="SKSETPWD C " + rbpwd + "\r\n"
ser.write(str.encode(wcom))
# Bルート認証ID設定
wcom="SKSETRBID " + rbid + "\r\n"
ser.write(str.encode(wcom))
scanRes = {} # スキャン結果の入れ物
scanRes["Channel"]="33"
scanRes["Channel Page"]="09"
scanRes["Pan ID"]="24EF"
scanRes["Addr"]="00FFEEDDCCBBAA99"
scanRes["LQI"]="3C"
scanRes["PairID"]="12345678"
# スキャン結果からChannelを設定。
wcom="SKSREG S3 " + scanRes["Pan ID"] + "\r\n"
ser.write(str.encode(wcom))
#print(ser.readline(), end="") # エコーバック
ser.readline()
#print(ser.readline(), end="") # OKが来るはず(チェック無し)
ser.readline()
# スキャン結果からPan IDを設定
wcom="SKSREG S3 " + scanRes["Pan ID"] + "\r\n"
ser.write(str.encode(wcom))
#print(ser.readline(), end="") # エコーバック
ser.readline()
#print(ser.readline(), end="") # OKが来るはず(チェック無し)
ser.readline()
# 直接指定しちゃう
ipv6Addr = "FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99"
#
# いきなり SKJOINをしてもつながらないことがあるため、SKPINGしてみます。
#
while True:
wcom="SKPING " + ipv6Addr + "\r\n"
ser.write(str.encode(wcom))
time.sleep(1)
# print(ser.readline(), end="") # echo
# print(ser.readline(), end="") # res
pingres = ser.readline() #
if pingres.startswith(b"OK"):
break
#
#
#
# PANA 接続シーケンスを開始します。
#time.sleep(1)
wcom="SKJOIN " + ipv6Addr + "\r\n"
ser.write(str.encode(wcom))
# PANA 接続完了待ち(10行ぐらいなんか返してくる)
bConnected = False
while not bConnected :
line = ser.readline()
# print(line, end="")
if line.startswith(b"EVENT 24") :
# print("PANA 接続失敗")
sys.exit() #### 糸冬了 ####
elif line.startswith(b"EVENT 25") :
# 接続完了!
bConnected = True
# これ以降、シリアル通信のタイムアウトを設定
ser.timeout = 2
# スマートメーターがインスタンスリスト通知を投げてくる
# (ECHONET-Lite_Ver.1.12_02.pdf p.4-16)
#print(ser.readline(), end="") #無視
while True:
# ECHONET Lite フレーム作成
# 参考資料
# ・ECHONET-Lite_Ver.1.12_02.pdf (以下 EL) : 最新版は ver 1.13_02
# ・Appendix_H.pdf (以下 AppH) : 最新版は J (2018/07/30現在)
# for EPC = 0xE7 (瞬時電力計測値)
echonetLiteFrame = b"" # echonetLiteFrame type is byte
echonetLiteFrame += b'\x10\x81' # EHD (参考:EL p.3-2) : 2byte目は \x81(電文形式1) or \x82(電文形式2)
echonetLiteFrame += b'\x00\x01' # TID (参考:EL p.3-3) : TID= Transaction ID
# ここから EDATA
echonetLiteFrame += b'\x05\xFF\x01' # SEOJ (参考:EL p.3-3 AppH p.3-408~) : コントローラクラス規定
echonetLiteFrame += b'\x02\x88\x01' # DEOJ (参考:EL p.3-3 AppH p.3-274~) : 低圧スマート電力量メータクラス規定
echonetLiteFrame += b'\x62' # ESV(62:プロパティ値読み出し要求) (参考:EL p.3-5) : Get
echonetLiteFrame += b'\x01' # OPC(1個)(参考:EL p.3-7)
# echonetLiteFrame += "\x02" # OPC(2個)(参考:EL p.3-7) : 2つのデータを取得する。
echonetLiteFrame += b'\xE7' # EPC(参考:EL p.3-7 AppH p.3-275) : 瞬時電力計測値
echonetLiteFrame += b'\x00' # PDC(参考:EL p.3-9)
# echonetLiteFrame += "\xE8" # EPC(参考:EL p.3-7 AppH p.3-275) : 瞬時電流計測値 R相T相
# echonetLiteFrame += "\x00" # PDC(参考:EL p.3-9)
# コマンド送信
com1 = "SKSENDTO 1 {0} 0E1A 1 {1:04X} ".format(ipv6Addr, len(echonetLiteFrame))
command = com1.encode() + echonetLiteFrame
ser.write(command)
ser.readline()
# print(ser.readline(), end="") # EVENT 21 が来るはず(チェック無し)
ser.readline()
# print(ser.readline(), end="") # OKが来るはず(チェック無し)
ser.readline()
line = ser.readline() # ERXUDPが来るはず
# print(line, end="")
# 取りこぼしたりして変なデータを拾うことがあるので
# チェックを厳しめにしてます。
if line.startswith(b"ERXUDP") :
line = line.decode()
cols = line.strip().split(' ')
res = cols[8] # UDP受信データ部分
#tid = res[4:4+4];
seoj = res[8:8+6]
#deoj = res[14,14+6]
ESV = res[20:20+2]
#OPC = res[22,22+2]
if seoj == "028801" and ESV == "72" :
# スマートメーター(028801)から来た応答(72)なら
EPC = res[24:24+2]
if EPC == "E7" :
# 内容が瞬時電力計測値(E7)だったら
hexPower = line[-8:] # 最後の4バイト(16進数で8文字)が瞬時電力計測値
intPower = int(hexPower, 16)
outputE7=intPower
break
#####################################################################################################
#
# for EPC = 0xE8 (瞬時電流計測値)
#
while True:
# ECHONET Lite フレーム作成
# 参考資料
# ・ECHONET-Lite_Ver.1.12_02.pdf (以下 EL)
# ・Appendix_H.pdf (以下 AppH)
# for EPC = 0xE7 (瞬時電力計測値)
echonetLiteFrame = b""
echonetLiteFrame += b'\x10\x81' # EHD (参考:EL p.3-2) : 2byte目は \x81(電文形式1) or \x82(電文形式2)
echonetLiteFrame += b'\x00\x01' # TID (参考:EL p.3-3) : TID= Transaction ID
# ここから EDATA
echonetLiteFrame += b'\x05\xFF\x01' # SEOJ (参考:EL p.3-3 AppH p.3-408~) : コントローラクラス規定
echonetLiteFrame += b'\x02\x88\x01' # DEOJ (参考:EL p.3-3 AppH p.3-274~) : 低圧スマート電力量メータクラス規定
echonetLiteFrame += b'\x62' # ESV(62:プロパティ値読み出し要求) (参考:EL p.3-5) : Get
echonetLiteFrame += b'\x01' # OPC(1個)(参考:EL p.3-7)
# echonetLiteFrame += "\x02" # OPC(2個)(参考:EL p.3-7) : 2つのデータを取得する。
# echonetLiteFrame += "\xE7" # EPC(参考:EL p.3-7 AppH p.3-275) : 瞬時電力計測値
# echonetLiteFrame += "\x00" # PDC(参考:EL p.3-9)
echonetLiteFrame += b'\xE8' # EPC(参考:EL p.3-7 AppH p.3-275) : 瞬時電流計測値 R相T相
echonetLiteFrame += b'\x00' # PDC(参考:EL p.3-9)
# コマンド送信
com1 = "SKSENDTO 1 {0} 0E1A 1 {1:04X} ".format(ipv6Addr, len(echonetLiteFrame))
command = com1.encode() + echonetLiteFrame
ser.write(command)
# print(ser.readline(), end="") # エコーバック
ser.readline()
# print(ser.readline(), end="") # EVENT 21 が来るはず(チェック無し)
ser.readline()
# print(ser.readline(), end="") # OKが来るはず(チェック無し)
ser.readline()
line = ser.readline() # ERXUDPが来るはず
# print(line, end="")
# 取りこぼしたりして変なデータを拾うことがあるので
# チェックを厳しめにしてます。
if line.startswith(b"ERXUDP") :
line = line.decode()
cols = line.strip().split(' ')
res = cols[8] # UDP受信データ部分
#tid = res[4:4+4];
seoj = res[8:8+6]
#deoj = res[14,14+6]
ESV = res[20:20+2]
#OPC = res[22,22+2]
if seoj == "028801" and ESV == "72" :
# スマートメーター(028801)から来た応答(72)なら
EPC = res[24:24+2]
if EPC == "E8" :
# 内容が瞬時電流力計測値(E8)だったら
# hexPower = line[-8:] # 最後の4バイト(16進数で8文字)が瞬時電力計測値
# intPower = int(hexPower, 16)
rCur = res[-8:-4]
tCur = res[-4:]
intrCur = round( float( int(rCur, 16) * 0.1 ), 1)
inttCur = round( float( int(tCur, 16) * 0.1 ), 1)
break
##################################################################################################
#
# for EPC = 0xE0 (積算電力量計測値(正方向計測値))
#
while True:
# ECHONET Lite フレーム作成
# 参考資料
# ・ECHONET-Lite_Ver.1.12_02.pdf (以下 EL)
# ・Appendix_H.pdf (以下 AppH)
# for EPC = 0xE7 (瞬時電力計測値)
echonetLiteFrame = b""
echonetLiteFrame += b'\x10\x81' # EHD (参考:EL p.3-2) : 2byte目は \x81(電文形式1) or \x82(電文形式2)
echonetLiteFrame += b'\x00\x01' # TID (参考:EL p.3-3) : TID= Transaction ID
# ここから EDATA
echonetLiteFrame += b'\x05\xFF\x01' # SEOJ (参考:EL p.3-3 AppH p.3-408~) : コントローラクラス規定
echonetLiteFrame += b'\x02\x88\x01' # DEOJ (参考:EL p.3-3 AppH p.3-274~) : 低圧スマート電力量メータクラス規定
echonetLiteFrame += b'\x62' # ESV(62:プロパティ値読み出し要求) (参考:EL p.3-5) : Get
echonetLiteFrame += b'\x01' # OPC(1個)(参考:EL p.3-7)
# echonetLiteFrame += "\x02" # OPC(2個)(参考:EL p.3-7) : 2つのデータを取得する。
# echonetLiteFrame += "\xE7" # EPC(参考:EL p.3-7 AppH p.3-275) : 瞬時電力計測値
# echonetLiteFrame += "\x00" # PDC(参考:EL p.3-9)
echonetLiteFrame += b'\xE0' # EPC(参考:EL p.3-7 AppH p.3-275) : 積算電力量計測値
echonetLiteFrame += b'\x00' # PDC(参考:EL p.3-9)
# コマンド送信
com1 = "SKSENDTO 1 {0} 0E1A 1 {1:04X} ".format(ipv6Addr, len(echonetLiteFrame))
command = com1.encode() + echonetLiteFrame
ser.write(command)
# print(ser.readline(), end="") # エコーバック
ser.readline()
# print(ser.readline(), end="") # EVENT 21 が来るはず(チェック無し)
ser.readline()
# print(ser.readline(), end="") # OKが来るはず(チェック無し)
ser.readline()
line = ser.readline() # ERXUDPが来るはず
# print(line, end="")
# 取りこぼしたりして変なデータを拾うことがあるので
# チェックを厳しめにしてます。
if line.startswith(b"ERXUDP") :
line = line.decode()
cols = line.strip().split(' ')
res = cols[8] # UDP受信データ部分
#tid = res[4:4+4];
seoj = res[8:8+6]
#deoj = res[14,14+6]
ESV = res[20:20+2]
#OPC = res[22,22+2]
if seoj == "028801" and ESV == "72" :
# スマートメーター(028801)から来た応答(72)なら
EPC = res[24:24+2]
if EPC == "E0" :
# 内容が瞬時電流力計測値(E8)だったら
hexPower = line[-8:] # 最後の4バイト(16進数で8文字)が瞬時電力計測値
# intPower = int(hexPower, 16)
# floatPower = round ( float( int( hexPower, 16) * 0.1 ),1)
# cacti の Data Source で COUNTER を使いたい、となるとデータは intでなくてはいけなくて、floatはだめ。
# なので、係数を使わずにそのままにする。
intPower = int( hexPower, 16)
break
##################################################################################################
#
# for EPC = 0xE3 (積算電力量計測値(逆方向計測値))
#
while True:
# for EPC = 0xE3
echonetLiteFrame = b""
echonetLiteFrame += b'\x10\x81' # EHD (参考:EL p.3-2) : 2byte目は \x81(電文形式1) or \x82(電文形式2)
echonetLiteFrame += b'\x00\x01' # TID (参考:EL p.3-3) : TID= Transaction ID
# ここから EDATA
echonetLiteFrame += b'\x05\xFF\x01' # SEOJ (参考:EL p.3-3 AppH p.3-408~) : コントローラクラス規定
echonetLiteFrame += b'\x02\x88\x01' # DEOJ (参考:EL p.3-3 AppH p.3-274~) : 低圧スマート電力量メータクラス規定
echonetLiteFrame += b'\x62' # ESV(62:プロパティ値読み出し要求) (参考:EL p.3-5) : Get
echonetLiteFrame += b'\x01' # OPC(1個)(参考:EL p.3-7)
echonetLiteFrame += b'\xE3' # EPC(参考:EL p.3-7 AppH p.3-275) : 積算電力量計測値
echonetLiteFrame += b'\x00' # PDC(参考:EL p.3-9)
# コマンド送信
com1 = "SKSENDTO 1 {0} 0E1A 1 {1:04X} ".format(ipv6Addr, len(echonetLiteFrame))
command = com1.encode() + echonetLiteFrame
ser.write(command)
ser.readline()
ser.readline()
ser.readline()
line = ser.readline() # ERXUDPが来るはず
# 取りこぼしたりして変なデータを拾うことがあるので
# チェックを厳しめにしてます。
if line.startswith(b"ERXUDP") :
line = line.decode()
cols = line.strip().split(' ')
res = cols[8] # UDP受信データ部分
#tid = res[4:4+4];
seoj = res[8:8+6]
#deoj = res[14,14+6]
ESV = res[20:20+2]
#OPC = res[22,22+2]
if seoj == "028801" and ESV == "72" :
# スマートメーター(028801)から来た応答(72)なら
EPC = res[24:24+2]
if EPC == "E3" :
# 内容が瞬時電流力計測値(E8)だったら
hexPower = line[-8:] # 最後の4バイト(16進数で8文字)が瞬時電力計測値
# intPower = int(hexPower, 16)
intPowerM = int(hexPower, 16)
break
#######################################################################################################
#
print ("E7:{0} E8r:{1} E8t:{2} E0:{3} E3:{4}".format(outputE7,intrCur,inttCur,intPower,intPowerM),end="")
#
#
ser.close()
出力はcactiに食わせる形式にしていて、E7:瞬時電力計測値,E8r:瞬時電流計測値(R相),E8t:瞬時電流計測値(T相),E0:積算電力量計測値(正方向計測値),E3:積算電力量計測値(逆方向計測値)。
raspberrypi:~/smartmeter3# python3 /usr/share/cacti/scripts/smartmeter.py3 E7:686 E8r:7.0 E8t:1.0 E0:86704 E3:10瞬間電力値、瞬間電流値は5分に1回のピンポイントの計測なので、瞬発的な消費は拾えてないこともある。
瞬間電流値の5分グラフ(T相、R相)
電子レンジ、電気ポットなどでの瞬間ピークが出ている。
積算電力量を cactiの counterでグラフ化したもの。
5分データだと、最小単位(0.1 KWH)を超えないときがある。もっと細かな数値が取れると良いけど HEMS機器の出力積算電力量単位(EPC 0xE1)が 0.1 kWhなので難しい。
今後は、この資料のP.32にもあるように、「通信負担を軽減する目的から、1つのパケットで複数のコマンド処理が可能なマルチゲットコマンド(エコーネットコンソーシアムが定義)などの実装が推奨される。」を行ってみることか? 最近はいろいろな Bルート製品が出ているのも気になる。
スマートメーター HEMS データの取得 for python3
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# see https://qiita.com/kanon700/items/d4df13d45c2a9d16b8b0
#
from __future__ import print_function
import sys
import serial
import time
# Bルート認証ID(東京電力パワーグリッドから郵送で送られてくる)
rbid = "AAAABBBBCCCCDDDD"
# Bルート認証パスワード(東京電力パワーグリッドからメールで送られてくる)
rbpwd = "PASSWORDDDDDDD"
# シリアルポートデバイス名
#serialPortDev = 'COM3' # Windows の場合
serialPortDev = '/dev/ttyUSB0' # Linux(ラズパイなど)の場合
#serialPortDev = '/dev/cu.usbserial-A103BTPR' # Mac の場合
#
ser = serial.Serial(serialPortDev, 115200)
#
# Bルート認証パスワード設定
wcom="SKSETPWD C " + rbpwd + "\r\n"
ser.write(str.encode(wcom))
print(ser.readline().decode('utf-8'), end="",flush=True) # エコーバック
print(ser.readline().decode('utf-8'), end="",flush=True) # OKが来るはず(チェック無し)
# Bルート認証ID設定
wcom="SKSETRBID " + rbid + "\r\n"
ser.write(str.encode(wcom))
print(ser.readline().decode('utf-8'), end="",flush=True) # エコーバック
print(ser.readline().decode('utf-8'), end="",flush=True) # OKが来るはず(チェック無し)
scanDuration = 4; # スキャン時間。サンプルでは6なんだけど、4でも行けるので。(ダメなら増やして再試行)
scanRes = {} # スキャン結果の入れ物
scanRes["Channel"]="33"
scanRes["Channel Page"]="09"
scanRes["Pan ID"]="24EF"
scanRes["Addr"]="00FFEEDDCCBBAA99"
scanRes["LQI"]="32"
scanRes["PairID"]="12345678"
# スキャン結果からChannelを設定。
wcom="SKSREG S2 " + scanRes["Channel"] + "\r\n"
ser.write(str.encode(wcom))
print(ser.readline().decode('utf-8'), end="",flush=True) # エコーバック
print(ser.readline().decode('utf-8'), end="",flush=True) # OKが来るはず(チェック無し)
# スキャン結果からPan IDを設定
wcom="SKSREG S3 " + scanRes["Pan ID"] + "\r\n"
ser.write(str.encode(wcom))
print(ser.readline().decode('utf-8'), end="",flush=True) # エコーバック
print(ser.readline().decode('utf-8'), end="",flush=True) # OKが来るはず(チェック無し)
# MACアドレス(64bit)をIPV6リンクローカルアドレスに変換。
# (BP35A1の機能を使って変換しているけど、単に文字列変換すればいいのではという話も??)
#ser.write("SKLL64 " + scanRes["Addr"] + "\r\n")
#print(ser.readline(), end="") # エコーバック
#ser.readline()
#time.sleep(2)
#ipv6Addr = ser.readline().strip()
#
# 直接指定しちゃう
ipv6Addr = "FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99"
#
# いきなり SKJOINをしてもつながらないことがあるため、SKPINGしてみます。
#
while True:
wcom="SKPING " + ipv6Addr + "\r\n"
ser.write(str.encode(wcom))
print(ser.readline().decode('utf-8'), end="",flush=True) # echo
# print(ser.readline(), end="") # res
pingres = ser.readline() #
if pingres.startswith(b'OK'):
print("come OK break")
break
pingres = ser.readline() #
if pingres.startswith(b'OK'):
print("come OK break")
break
#
#
# PANA 接続シーケンスを開始します。
#
time.sleep(1)
wcom="SKJOIN " + ipv6Addr + "\r\n"
ser.write(str.encode(wcom))
time.sleep(1)
print(ser.readline().decode('utf-8'), end="",flush=True) # エコーバック
#ser.readline()
#print(ser.readline(), end="") # OKが来るはず(チェック無し)
#ser.readline()
# PANA 接続完了待ち(10行ぐらいなんか返してくる)
bConnected = False
while not bConnected :
line = ser.readline()
print(line.decode('utf-8'), end="",flush=True)
if line.startswith(b'EVENT 24') :
# print("PANA 接続失敗")
sys.exit() #### 糸冬了 ####
elif line.startswith(b'EVENT 25') :
# 接続完了!
print("connect PANA OK",flush=True)
bConnected = True
# これ以降、シリアル通信のタイムアウトを設定
ser.timeout = 2
# スマートメーターがインスタンスリスト通知を投げてくる
# (ECHONET-Lite_Ver.1.12_02.pdf p.4-16)
#print(ser.readline(), end="") #無視
#
#
# Appendix_H.pdf
#
#
# python3 で変更。key を str として定義。
# bytes.fromhex(key) にて、byte1文字に変換し、コマンドとして送信するよ
echonetproperty = { '80':["status","80","動作状態"], 'D3':["keisuu","D3","係数"],'D7':["sekisanpower","D7","積算電力有効桁数"], \
'E0':["sekisanpowerplus","E0","積算電力量計測値(正方向計測値)"] ,'E1':["sekisanpowerplusminus","E1","積算電力量単位"],\
'E2':["sekisanpowerplushis","E2","積算電力量計測値履歴1"] ,'E3':["sekisanpowerminus","E3","積算電力量計測値(逆方向計測値)"],\
'E4':["sekisanpowerminushis","E4","積算電力量計測値履歴1(逆方向計測値)"],'E5':["sekisanhiscollectday","E5","積算履歴収集日1"],\
'E7':["nowpower","E7","瞬時電力計測値"], 'E8':["nowcurrent","E8","瞬時電流計測値"],'EA':["teijisekisanpowerplus","EA","定時積算電力量計測値(正方向計測値)"],\
'EB':["teijisekisanpowerminus","EB","定時積算電力量計測値(逆方向計測値)"],'EC':["teijisekisanpowerplusminus","EC","積算電力量計測値履歴1(正方向,逆方向)"],\
'ED':["sekisanhiscollectday2","ED","積算履歴収集日2"] }
#
#
#
for key,value in sorted(echonetproperty.items()):
keystr = str(echonetproperty[key][1])
keydesc = echonetproperty[key][2]
print(key,keystr,keydesc,end="",flush=True)
# print(key,keystr,keydesc)
# print (u"EPC = {0}".format(keyecho))
while True:
# ECHONET Lite フレーム作成
# 参考資料
# ・ECHONET-Lite_Ver.1.12_02.pdf (以下 EL)
# ・Appendix_H.pdf (以下 AppH)
# for EPC = 0xE7 (瞬時電力計測値)
echonetLiteFrame = b"" # echonetLiteFrame type is byte
echonetLiteFrame += b'\x10\x81' # EHD (参考:EL p.3-2) : 2byte目は \x81(電文形式1) or \x82(電文形式2)
echonetLiteFrame += b'\x00\x01' # TID (参考:EL p.3-3) : TID= Transaction ID
# ここから EDATA
echonetLiteFrame += b'\x05\xFF\x01' # SEOJ (参考:EL p.3-3 AppH p.3-408~) : コントローラクラス規定
echonetLiteFrame += b'\x02\x88\x01' # DEOJ (参考:EL p.3-3 AppH p.3-274~) : 低圧スマート電力量メータクラス規定
echonetLiteFrame += b'\x62' # ESV(62:プロパティ値読み出し要求) (参考:EL p.3-5) : Get
echonetLiteFrame += b'\x01' # OPC(1個)(参考:EL p.3-7)
# echonetLiteFrame += "\x02" # OPC(2個)(参考:EL p.3-7) : 2つのデータを取得する。
# echonetLiteFrame += "\xE7" # EPC(参考:EL p.3-7 AppH p.3-275) : 瞬時電力計測値
key2=bytes.fromhex(key)
# print("key2 = ",key2,flush=True)
echonetLiteFrame += key2
echonetLiteFrame += b'\x00' # PDC(参考:EL p.3-9)
# echonetLiteFrame += "\xE8" # EPC(参考:EL p.3-7 AppH p.3-275) : 瞬時電流計測値 R相T相
# echonetLiteFrame += "\x00" # PDC(参考:EL p.3-9)
# コマンド送信
# command = "SKSENDTO 1 {0} 0E1A 1 {1:04X} {2}".format(ipv6Addr, len(echonetLiteFrame), echonetLiteFrame)
com1 = "SKSENDTO 1 {0} 0E1A 1 {1:04X} ".format(ipv6Addr, len(echonetLiteFrame))
command = com1.encode() + echonetLiteFrame
# print(command,end="",flush=True)
ser.write(command)
# ser.write(str.encode(command))
# print(readl.decode('utf-8').encode(),end="",flush=True)
print(ser.readline().decode('utf-8'), end="",flush=True) # エコーバック
print(ser.readline().decode('utf-8'), end="",flush=True) # EVENT 21 が来るはず(チェック無し)
print(ser.readline().decode('utf-8'), end="",flush=True) # OKが来るはず(チェック無し)
# line = ser.readline() # ERXUDPが来るはず
line = ser.readline() # 本来のデータ?をこちらで取得する
# 取りこぼしたりして変なデータを拾うことがあるので
# チェックを厳しめにしてます。
if line.startswith(b'ERXUDP') :
# print("ERXUDP found",flush=True)
print(line.decode('utf-8'),end="",flush=True)
line = line.decode()
cols = line.strip().split(' ')
# print(cols)
res = cols[8] # UDP受信データ部分
# print("res=",res)
#tid = res[4:4+4];
seoj = res[8:8+6]
#deoj = res[14,14+6]
ESV = res[20:20+2]
if seoj == "028801" and ESV == "72" :
# スマートメーター(028801)から来た応答(72)なら
EPC = res[24:24+2]
# if EPC == "E7" :
if EPC == keystr :
# 内容が瞬時電力計測値(E7)だったら
# hexPower = line[-8:] # 最後の4バイト(16進数で8文字)が瞬時電力計測値
# intPower = int(hexPower, 16)
# print(u"瞬時電力計測値:{0}[W]".format(intPower))
# print((u"瞬時電力計測値:{0}[W]".format(intPower)).encode('utf-8'))
break
#
ser.close()
コメントにも書いているが、SKJOINをいきなり行っても繋がらないケースがままあった。SKPING を叩いて寝ているデバイス?インターフェースを起こす(?)必要がある感じ。出力結果は次の通り(一部省略)
SKSETPWD C PASSWORDDDDDDD OK SKSETRBID AAAABBBBCCCCDDDD OK SKSREG S2 33 OK SKSREG S3 24EF OK SKPING FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 come OK break EPONG FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 SKJOIN FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 OK (省略) EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 00 EVENT 25 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 connect PANA OK 80 80 動作状態SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 00 OK ERXUDP FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 FF02:0000:0000:0000:0000:0000:0000:0001 0E1A 0E1A 00808700301224EF 1 0012 108100000EF0010EF0017301D50401028801 ERXUDP FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA88 0E1A 0E1A 00808700301224EF 1 000F 1081000102880105FF017201800130 SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 00 SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 00 OK ERXUDP FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA88 0E1A 0E1A 00808700301224EF 1 000F 1081000102880105FF017201800130 D3 D3 係数SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 00 OK ERXUDP FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA88 0E1A 0E1A 00808700301224EF 1 000F 1081000102880105FF017201800130 SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 00 OK ERXUDP FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA88 0E1A 0E1A 00808700301224EF 1 0012 1081000102880105FF017201D30400000001 D7 D7 積算電力有効桁数SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 00 OK ERXUDP FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA88 0E1A 0E1A 00808700301224EF 1 0012 1081000102880105FF017201D30400000001 SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 00 OK ERXUDP FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA88 0E1A 0E1A 00808700301224EF 1 000F 1081000102880105FF017201D70106 E0 E0 積算電力量計測値(正方向計測値)SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 01 OK ERXUDP FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA88 0E1A 0E1A 00808700301224EF 1 000F 1081000102880105FF017201D70106 SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 00 OK ERXUDP FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA88 0E1A 0E1A 00808700301224EF 1 0012 1081000102880105FF017201E00400015208 E1 E1 積算電力量単位SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 01 OK SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 00 OK ERXUDP FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA88 0E1A 0E1A 00808700301224EF 1 000F 1081000102880105FF017201E10101 E2 E2 積算電力量計測値履歴1SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 00 OK ERXUDP FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA88 0E1A 0E1A 00808700301224EF 1 00D0 1081000102880105FF017201E2C200FFFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE E3 E3 積算電力量計測値(逆方向計測値)SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 00 OK ERXUDP FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA88 0E1A 0E1A 00808700301224EF 1 0012 1081000102880105FF017201E3040000000A E4 E4 積算電力量計測値履歴1(逆方向計測値)SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 00 OK ERXUDP FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA88 0E1A 0E1A 00808700301224EF 1 00D0 1081000102880105FF017201E4C200FFFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE E5 E5 積算履歴収集日1SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 00 OK ERXUDP FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA88 0E1A 0E1A 00808700301224EF 1 000F 1081000102880105FF017201E501FF E7 E7 瞬時電力計測値SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 01 OK SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 00 OK ERXUDP FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA88 0E1A 0E1A 00808700301224EF 1 0012 1081000102880105FF017201E70400000274 E8 E8 瞬時電流計測値SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 00 OK ERXUDP FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA88 0E1A 0E1A 00808700301224EF 1 0012 1081000102880105FF017201E80400320014 EA EA 定時積算電力量計測値(正方向計測値)SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 00 OK ERXUDP FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA88 0E1A 0E1A 00808700301224EF 1 0019 1081000102880105FF017201EA0B07E4030E081E0000015206 EB EB 定時積算電力量計測値(逆方向計測値)SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 00 OK ERXUDP FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA88 0E1A 0E1A 00808700301224EF 1 0019 1081000102880105FF017201EB0B07E4030E081E000000000A EC EC 積算電力量計測値履歴1(正方向,逆方向)SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 00 OK ERXUDP FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA88 0E1A 0E1A 00808700301224EF 1 001D 1081000102880105FF017201EC0FFFFFFFFFFFFF01FFFFFFFEFFFFFFFE ED ED 積算履歴収集日2SKSENDTO 1 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 0E1A 1 000E EVENT 21 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 00 OK ERXUDP FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99 FE80:0000:0000:0000:02FF:EEDD:CCBB:AA88 0E1A 0E1A 00808700301224EF 1 0015 1081000102880105FF017201ED07FFFFFFFFFFFF01
スマートメーター HEMS デバイススキャン for python3
このサンプルプログラムはpython2 でのプログラムだったので、今後のためにもpython3 用に書き直しておいたほうが良かったので、作成してみた。例示してあるプログラムはデバイスを探索してデータを取得するのだが、定期的にデータを取得して時系列データを作成するのであれば、デバイス探索は毎回繰り返さなくても良い(スマートメーターのサイトローカルのIPv6アドレスで特定できる)ので、(1)デバイスを探索し、アクセスするための諸元データを取得する。(2)データを定期的に取得する。の2つにわけてしまうほうが良さそうで、それを実施してみた。 まずは (1)の python3 に自分なりに書き換えたものを。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from __future__ import print_function
import sys
import serial
import time
# Bルート認証ID(東京電力パワーグリッドから郵送で送られてくる)
rbid = "AAAABBBBCCCCDDDD"
# Bルート認証パスワード(東京電力パワーグリッドからメールで送られてくる)
rbpwd = "PASSWORDDDDDDD"
# シリアルポートデバイス名
#serialPortDev = 'COM3' # Windows の場合
serialPortDev = '/dev/ttyUSB0' # Linux(ラズパイなど)の場合
#serialPortDev = '/dev/cu.usbserial-A103BTPR' # Mac の場合
#
ser = serial.Serial(serialPortDev, 115200)
#
wcom = "SKVER\r\n"
ser.write(str.encode(wcom))
print(ser.readline().decode('utf-8'), end="",flush=True) # エコーバック
print(ser.readline().decode('utf-8'), end="",flush=True) # バージョン
#
# Bルート認証パスワード設定
wcom = "SKSETPWD C " + rbpwd + "\r\n"
ser.write(str.encode(wcom))
ser.readline() # エコーバック
# Bルート認証ID設定
wcom = "SKSETRBID " + rbid + "\r\n"
ser.write(str.encode(wcom))
print(ser.readline().decode('utf-8'), end="",flush=True) # エコーバック
ser.readline()
print(ser.readline().decode('utf-8'), end="",flush=True) # OKが来るはず(チェック無し)
ser.readline()
scanDuration = 4; # スキャン時間。サンプルでは6なんだけど、4でも行けるので。(ダメなら増やして再試行)
scanRes = {} # スキャン結果の入れ物
# スキャンのリトライループ(何か見つかるまで)
#while not scanRes.has_key("Channel") : python2
while not 'Channel' in scanRes :
# アクティブスキャン(IE あり)を行う
# 時間かかります。10秒ぐらい?
#ser.write(str.encode("SKSCAN 2 FFFFFFFF " + str(scanDuration) + "\r\n"))
wcom = "SKSCAN 2 FFFFFFFF " + str(scanDuration) + "\r\n"
ser.write(str.encode(wcom))
# スキャン1回について、スキャン終了までのループ
scanEnd = False
while not scanEnd :
line = ser.readline()
print(line.decode(), end="",flush=True)
#
line = line.decode()
if line.startswith("EVENT 22") :
# # スキャン終わったよ(見つかったかどうかは関係なく)
scanEnd = True
elif line.startswith(" ") :
# スキャンして見つかったらスペース2個あけてデータがやってくる
# 例
# Channel:39
# Channel Page:09
# Pan ID:FFFF
# Addr:FFFFFFFFFFFFFFFF
# LQI:A7
# PairID:FFFFFFFF
cols = line.strip().split(':')
scanRes[cols[0]] = cols[1]
scanDuration+=1
if 7 < scanDuration and not scanRes.has_key("Channel"):
# 引数としては14まで指定できるが、7で失敗したらそれ以上は無駄っぽい
print("スキャンリトライオーバー")
sys.exit() #### 糸冬了 ####
これを実行すると次のような結果が出てくる。
raspberrypi:~/smartmeter3# ./test-bs_scan.py SKVER EVER 1.2.8 SKSETPWD C PASSWORDDDDDDD SKSETRBID AAAABBBBCCCCDDDD SKSCAN 2 FFFFFFFF 4 OK EVENT 20 FE80:0000:0000:0000:1234:5678:9ABC:DEF0 EPANDESC Channel:33 Channel Page:09 Pan ID:24EF Addr:00FFEEDDCCBBAA99 LQI:32 PairID:12345678 EVENT 22 FE80:0000:0000:0000:1234:5678:9ABC:DEF0Addr は64bit、これを IPv6のリンクローカルアドレスに変換するには SKLL64 コマンドを使う、ようだが 単純に、MACアドレス 48bit を、EUI-64で変換する場合の、'FF:FE'の挿入をやめただけのよう。先頭の7bit目を反転させて、後半64bit の IPv6 アドレスにしてしまえば良いみたい。例の 'Addr:00FFEEDDCCBBAA99' なら、IPv6アドレスは 'FE80:0000:0000:0000:02FF:EEDD:CCBB:AA99' になる、と思われる。
これで取得できた Channel, Channel Page, Pan ID,PairID, 生成した IPv6アドレスを利用して定期的なデータ取得 scriptを動かす。
raspberry pi3 で HEMS測定がときどき中断する
原因はよくわかっていないが、マニュアルで接続してデータを見ているときに、python3 + pyserial の組み合わせで
'device disconnected or multiple access on port' のエラーが出るときがある。
複数プロセスでttyを掴むような仕様にはしていないつもりだった(/dev/ttyUSB0 を排他にする)ので
何が原因かよくわからなかったが、https://www.suzu6.net/posts/32/に「原因は、シリアルポートからシェルのアクセスを許しているためです。シリアル通信だけ許可して、シェルログインは許可しない設定に変更しましょう。」とある。なこともあるのか。。。?
とりあえず、このページにあるように、raspi-config で設定を変更して様子みてみる。
20190908 台風15号の気圧変化
HEMS 機器オブジェクトスーパークラス
電力スマートメーターは「住宅・設備関連機器クラスグループ」の「低圧スマート電力量メータクラス」だそうで、クラスグループ"0x02",クラスコード "0x88" になる。その他に取れるデータが無いかと見てみたら、一番上位の「機器オブジェクトスーパークラス」のデータにGetできるものがあるようなので、とりあえず見てみた。
| プロパティ名称 | EPC | 取得データ | 内容 | 備考 |
|---|---|---|---|---|
| 動作状態 | 0x80 | 30 | ON | |
| 設置場所 | 0x81 | 61 | 庭・外周 | 場所番号 01 |
| 規格Version情報 | 0x82 | 00004600 | Release F (?) | |
| 識別番号 | 0x83 | ESV=52,読み出し応答不可 | ||
| 瞬時消費電力計測値 | 0x84 | ESV=52,読み出し応答不可 | ||
| 積算消費電力計測値 | 0x85 | ESV=52,読み出し応答不可 | ||
| メーカ異常コード | 0x86 | ESV=52,読み出し応答不可 | ||
| 電流制限設定 | 0x87 | ESV=52,読み出し応答不可 | ||
| 異常発生状態 | 0x88 | 42 | 異常発生無 | |
| 異常内容 | 0x89 | ESV=52,読み出し応答不可 | ||
| メーカコード | 0x8A | 000016 | ||
| 事業場コード | 0x8B | ESV=52,読み出し応答不可 | ||
| 商品コード | 0x8C | ESV=52,読み出し応答不可 | ||
| 製造番号 | 0x8D | 313233343536373839300000 | 1234567890 | |
| 製造年月日 | 0x8E | ESV=52,読み出し応答不可 | ||
| 節電動作設定 | 0x8F | ESV=52,読み出し応答不可 | ||
| 遠隔操作設定 | 0x93 | ESV=52,読み出し応答不可 | ||
| 現在時刻設定 | 0x97 | 0C35 | 12時41分 | |
| 現在年月日設定 | 0x98 | 07E20803 | 2018年8月3日 | |
| 電力制限設定 | 0x99 | ESV=52,読み出し応答不可 | ||
| 積算運転時間 | 0x9A | ESV=52,読み出し応答不可 |
意味があるデータは製造番号くらいで、ほぼ読み出し応答不可が帰ってきた。
excel 2 table にはここを利用