#!/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