次に、取得した接続情報を元に、HEMSのデータを取得する。
HEMSスマートメーターからの出力で例示した ECHONETの「低圧スマート電力量メータクラス規定」で、素のデータを読み出すシンプルなscriptを。前ページで取得した Channel,Channel Page, Pan ID, PairID,ついでにLQI(これは不要と思うけど・・・),IPv6アドレスを指定してすみやかにデータ取得するようにした。コメントが重複している部分が多いが、自分用の備忘録として。。。
#!/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