HEMS gatewayに echonetlite frame を投げつけてみる。

  •  
  •  

HEMSの探索で、'0279'という、"住宅用太陽光発電クラス" という応答が帰ってきたので改めてこの規格を確認して、APPENDIX ECHONET機器オブジェクト詳細規定Release R rev.2 の当該のところを読んでみる。

この 3.3.13「住宅用太陽光発電クラス規定」(3-206)の中で、アクセスルールで 'GET'が出来るものについて片っ端からアクセスして情報を取得することを考える。

プロパティ名称 EPC データ型・サイズ 取得データ 結果
動作状態 0x80 uc x 1B 7201800130 ON
識別番号 0x83 uc x 9B or 17B 72018311fe00006430NNNNNNNNNNNN1e0000000000, 17Byte
NN = MACアドレス
異常内容 0x89 us x 2B 720189020000 異常無し
商品コード 0x8C uc x 12B 72018c0c5043532d5250314120202020 PCS-RP1A
現在時刻設定 0x97 uc x 2B 720197020d2b 1353
現在年月日設定 0x98 uc x 4B 7201980407e80716 20240722
出力制御設定1 0xA0 uc x 4B 5201a000 52:不可応答
出力制御設定2 0xA1 uc x 1B 5201a100 52:不可応答
余剰買取制御機能設定 0xA2 uc x 2B 5201a200 52:不可応答
出力制御スケジュール 0XB0 uc x 100B 5201b000 52:不可応答
次回アクセス日時 0xB1 uc x 7B 5201b100 52:不可応答
余剰買取制御機能タイプ 0xB2 uc x 1B 5201b200 52:不可応答
出力変化時間設定値 0xB3 us x 2B 5201b300 52:不可応答
上限クリップ設定値 0xB4 us x 2B 5201b400 52:不可応答
運転力率設定値 0xC0 uc x 1B 5201c000 52:不可応答
FIT契約タイプ 0XC1 uc x 1B 5201c100 52:不可応答
自家消費タイプ 0xC2 uc x 1B 5201c200 52:不可応答
設備認定容量 0xC3 us x 2B 5201c300 52:不可応答
換算係数 0xC4 uc x 1B 5201c400 52:不可応答
系統連携状態 0xD0 uc x 1B 7201d00100

00:逆潮流可

出力抑制状態 0xD1 uc x 1B 5201d100 52:不可応答
瞬時発電電力計測値 0xE0 us x 2B 7201e00208bf 2239 W
= 2.239 kW
積算発電電力量計測値 0xE1 us x 4B 7201e10400018e36 101942
= 101.942 kWh
積算売電電力量計測値 0xE3 us x 4B 5201e300 52:不可応答
発電電力制限設定1 0xE5 uc x 1B 7201e50164 0x64 = 100%
発電電力制限設定2 0xE6 us x 2B 5201e600 52:不可応答
売電電力制限設定 0xE7 us x 2B 5201e700 52:不可応答
定格発電電力値(系統連携時) 0xE8 us x 2B 7201e802170c 0x170c
= 5900 W (5.9kW)
定格発電電力値(独立時) 0xE9 us x 2B 7201e9020fa0 0x0fa0
=4000 w (4.0kW)


とりあえず、蓄電池を繋いでいない状態で取得出来た情報は上の通り。
0xE0,0xE1 くらいが時系列で取得して意味ある数値か。

HEMS ゲートウェイの応答(hems discovery)

  •  
  •  

ネットにゲートウェイを繋いで、さて、どういうHEMS応答があるのかを探るのに、まずは デバイス探索だろうと思った。ネットにHEMSデバイスの代理応答をしているのだろうと思うので、普通にデバイス探索を行うのにどうすればと思ったら、次のページがあった。

https://end0tknr.hateblo.jp/entry/20170305/1488712308

この script を動かしてみたら、ゲートウェイは反応せず、別のIPアドレスから返答が。

身に覚えが無いなぁと思いながら、'01013001'という応答を考えてみたら、Panasonic のエアコンだった。
なるほど、これもHEMS一家だったか。
太陽光関係が終わったら、これもデータを取得してみよう。といってもどこまで何が取れるかよくわかってないが。室内外温度、湿度あたり、消費電力あたりくらいか。

で、ゲートウェイがHEMS機器として反応しないのは困った、独自プロトコルなのか?と思って、とりあえずパケットキャプチャーしてみたら、MDNSに応答しているのを発見。

_ossgwsvc._tcp.local: type PTR, class IN, SN._ossgwsvc._tcp.local

SN._ossgwsvc._tcp.local: type TXT, class IN, cache flush

SN._ossgwsvc._tcp.local: type SRV, class IN, cache flush, priority 0, weight 0, port 443, target NN.local

SN.local: type A, class IN, cache flush, addr IPaddress

というレスポンスを返してきた。'SN'は製品のシリアルナンバー、'IPaddress'は、このゲートウェイのIPアドレス。


ということで、どうも ip:224.0.0.251, port 5353で mDNSには応答するらしい。

hemsの規格書には マルチキャストアドレスの "244.0.23.0"でreq/res するとあるが 、このゲートウェイはどうもそのマルチキャストには反応しないようになっているようだ。

なので、もう決め打ちで、echonet liteの port 3610 に broadcast '224.0.0.251' でechonet lite の問い合わせフレームを投げてみたら、ビンゴっぽい。

['1081', '0000', '0ef001', '05ff01', '72', '01', 'd6', '04', '0102791f']

と、 '0279' という住宅用太陽光発電クラス規定のノードだという返答が返ってきた。

このIPアドレスで、port 3610 に udp で通信することで echonet lite のやりとりができるっぽい。

Echonet Lite 機器オブジェクトドキュメント(Release R)

  •  
  •  

いま、Bルートの電力量関連のデータを取得しているが、太陽光発電で逆流が始まったところ、データが吹っ飛んだ!ので、ちょっと変換プログラムの詳細を確認。

データのドキュメントへのリンクが not found になってしまった(前は Release Hだった)ので再度探してみた。

「低圧スマート電力量メータクラス規定」は、このドキュメントの'3-314'にある。


https://echonet.jp/wp/wp-content/uploads/pdf/General/Standard/Release/Release_R/Appendix_Release_R_r2.pdf

いま取得為ているデータを再度これと見比べてみる。

設備機器について

  •  
  •  

導入する太陽光システムはCIC(長州産業)のシステムということで、見積書の内容を見ると機種は、

"スマートPVマルチ全負荷:9.8KWh CB-P98M05A" ということらしい。

ウェブで検索すると、これがパンフレット。

ユニット名 型番 取説関連
マルチ蓄電パワーコンディショナ PVS-RP1A https://esysz.co.jp/wp/wp-content/themes/escosystems/pdf/manual_b_choshu5.pdf
蓄電池ユニット CB-LMP98A
マルチ蓄電システム用ゲートウェイ RC-307A https://cic-solar.jp/member_sekou/wp-content/uploads/SPVM_RC-307A_siyo.pdf
PVユニット DCS-66RP1A
トランスユニット TCS-40RP1A
全負荷用分電盤 KP-DB75 https://cic-solar.jp/member_sekou/wp-content/uploads/SPVM_setu.pdf

各種メトリクスは HEMSで取れると思うが、さて、どうやってHEMS機器を見つけるのか、ゲートウェイの役割とかが全くわかっていない。。。

電源契約メモ:looop 電気

  •  
  •  

太陽光発電を導入することで、電力会社の契約も見直すことを検討する。

電源については、昨今の状況では売電での収入は当てできないので、いかに買電コストを下げることが

できるかということになると思われる。

電源利用については、バッテリーの容量が十分であれば、

  • 太陽光発電時の日中帯では、リアルタイム消費での、余剰分については蓄電
  • 発電出来ない時間帯では、バッテリーからの放電での利用。容量限界(通常はバッテリー容量の20%程度?)まで消費しきったら、安いところから買電。
  • 太陽光発電でバッテリーを満充電できない場合は、単価が安いところ・時間帯で買電して充電する。

ということでいいのだろう。買電先をリアルタイムでオンデマンドで変えることは現在は出来ないが、月単位では変更することは可能だろう。

ということで、電力会社の買電価格(時間帯による変化)についての概略を見て、どういうことにするか検討する。

まずは一番面倒(面白そう)な looop電気から。

JEPXのオンデマンド価格に連動するということで、当日・翌日の30分単位での価格が「でんき予報」として公表されている。

https://looop-denki.com/home/denkiforecast/

2024/07/07でみると、14時くらいまでは 15 円/kWh くらい、17時から21時までの26 円/kWh、深夜帯は安く、昼閒や夕方は高い。

「でんき注意報」「でんき警報」というアラート出しているので、この時間帯にはできるだけ買電しないように、という設定を都度設定できると良いということか?

翌日の単価は16時頃に更新とのこと。

契約関係では、

「切り替わりは、検針日」

「契約期間は1年で1年ごとに自動更新。ただし契約期間中に中途解約した場合でも解約金は発生しない。い」https://looop-denki.com/home/faq/

あと、あれ?

「Q:売電した電力料金の支払い方法を教えてください。 矢印アイコン

Looopでんきのお支払いと相殺させていただくため、直接現金でお支払いすることはございません。」

売電先って、東電一択という話を太陽光発電設置会社からされていたけど、そうじゃないのか。

電力使用状況のデータ保存用 script(influxdb, google spreadsheet)

  •  
  •  

とりあえず、いま、HEMSで取ってきたデータを、influx と Google Spreadsheet に投げ込んでいるスクリプトを再掲。

#!/root/venv/bin/python3.9
#
# put_gcp_sheet4.py
#    2024/06/08
#
#    merge get HEMS data and put_gcp_sheet
#
from __future__ import print_function
# for google spread sheet
from google.oauth2 import service_account
from googleapiclient.discovery import build
# for HEMS
import sys
import serial
import time
import argparse
import datetime
from datetime import datetime,timezone,timedelta
#import influxdb
from icecream import ic
ic.disable()
#
from influxdb_client import InfluxDBClient,Point
from influxdb_client.client.write_api import SYNCHRONOUS
#
from dotenv import load_dotenv
import os
# setting for google spread sheet
SPREADSHEET_ID = os.getenv('SPREADSHEET_ID')
RANGE_NAME = 'Sheet1!A:G'
SCOPES = ['https://www.googleapis.com/auth/spreadsheets']
SERVICE_ACCOUNT_FILE = os.getenv('SERVICE_ACCOUNT_FILE')
#creds = Credentials.from_service_account_file(CREDENTIALS_FILE, scopes=['https://www.googleapis.com/auth/spreadsheets'])
creds = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
service = build('sheets', 'v4', credentials=creds)
# setting for HEMS ( from ../influs_sm39.py )
org = "homemetrics"
bucket = "environment"
token = os.getenv('token')
clienturl = os.getenv('CLIENTURL')
client = InfluxDBClient(url=clienturl,token=token,org=org)
write_api = client.write_api(write_options=SYNCHRONOUS)
query_api = client.query_api()
#
def jsttimestr(unix_time,tz_offset_hours=9):
    # 現在のUTC時刻を取得
    dt_utc = datetime.fromtimestamp(unix_time,tz=timezone.utc)
    # 任意のタイムゾーン(例:日本標準時 JST)
    target_tz = timezone(timedelta(hours=tz_offset_hours))
    dt_target_tz = dt_utc.astimezone(target_tz)
    # 汎用的なフォーマットで時刻を文字列に変換
    formatted_time = dt_target_tz.strftime('%Y-%m-%d %H:%M:%S%z')
    # タイムゾーンオフセットを '+09:00' の形式に変換
    formatted_time = formatted_time[:-2] + ':' + formatted_time[-2:]
    return(formatted_time)
#
#
################## for hems data and write influxdb
# Bルート認証ID(東京電力パワーグリッドから郵送で送られてくる)
rbid  = os.getenv('RBID')
# Bルート認証パスワード(東京電力パワーグリッドからメールで送られてくる)
rbpwd = os.getenv('RBPWD')
# シリアルポートデバイス名
#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))
#scanDuration = 4;   # スキャン時間。サンプルでは6なんだけど、4でも行けるので。(ダメなら増やして再試行)
scanRes = {} # スキャン結果の格納用
#
scanRes["Channel"]="33"
scanRes["Channel Page"]="09"
scanRes["Pan ID"]="24EF"
scanRes["Addr"]="00808700301224EF"
scanRes["LQI"]="3C"
scanRes["PairID"]="00E798AF"
# スキャン結果からChannelを設定。
wcom="SKSREG S3 " + scanRes["Pan ID"] + "\r\n"
ser.write(str.encode(wcom))
ser.readline()
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:0280:AABB:CCDD:EEFF"
# いきなり SKJOINをしてもつながらないことがあるため、SKPINGする。
#
while True:
    wcom="SKPING " + ipv6Addr + "\r\n"
    ser.write(str.encode(wcom))
    time.sleep(2)
    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()
    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)
#
# その瞬間値として取るべき値は、
# EPC: 0xE0 : 積算電力量計測値(正方向計測値)
#      0xE3 : 積算電力量計測値(逆方向計測値)
#      0xE7 : 瞬時電力計測値
#      0xE8 : 瞬時電流計測値 (R相、T相両方の値が入っている)
#      0xEA : 定時積算電力量計測値(正方向計測値) これは不要?0xE0と同じ?
#      0xEB : 定時積算電力量計測値(逆方向計測値) これも不要? 0xE3と同じ?
#  の6つでいいか?(または、最初の4つ?)
#
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)
#    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 == "E7" :
                # 内容が瞬時電力計測値(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'))
                outputE7=intPower
#                print("E7:{0}".format(outputE7))
#                time.sleep(5)
                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:]
#                print 'rCur = {0}'.format(rCur)
#                print 'tCur = {0}'.format(tCur)
#                print ('rCur = {0}'.format(rCur))
#                print ('tCur = {0}'.format(tCur))
                intrCur = round( float( int(rCur, 16) * 0.1 ), 1)
                inttCur = round( float( int(tCur, 16) * 0.1 ), 1)
#                print(u"瞬時電力計測値:{0}[W]".format(intPower))
#                print((u"瞬時電力計測値:{0}[W]".format(intPower)).encode('utf-8'))
#                print((u"R相電流計測値:{0}[A]".format(intrCur)).encode('utf-8'))
#                print((u"T相電流計測値:{0}[A]".format(inttCur)).encode('utf-8'))
#                print("E8r:{0} E8t:{1}".format(intrCur,inttCur))
                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)
#                print(u"積算電力量計測値:{0}[kWh]".format(intPower))
#                print((u"瞬時電力計測値:{0}[W]".format(intPower)).encode('utf-8'))
#                print("E0:{0}".format(floatPower))
                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)
#                print(u"積算電力量計測値:{0}[kWh]".format(intPower))
#                print((u"瞬時電力計測値:{0}[W]".format(intPower)).encode('utf-8'))
#                print("E0:{0}".format(floatPower))
                break
ser.close()
#
################################################
#
# for influxdb2  2022/06/20
#
#print("start write influxdb2")
#
p = Point("smartmerter")\
        .tag("location","home")\
        .field("outputE7",int(outputE7))\
        .field("rCurrent",float(intrCur))\
        .field("tCurrent",float(inttCur))\
        .field("Power",int(intPower))\
        .field("PowerM",int(intPowerM))
write_api.write(bucket=bucket,record=p)
################## for google spread sheet
utime = int(time.time())
# データを書き込む要求を追加
#row_data = [['14:00', 550], ['15:00', 600]]
row_data = [[str(utime),jsttimestr(utime),int(outputE7),float(intrCur),float(inttCur),int(intPower),int(intPowerM)]]
# データを追加
request = service.spreadsheets().values().append(
    spreadsheetId=SPREADSHEET_ID,
    range=RANGE_NAME,
    valueInputOption='USER_ENTERED',
    insertDataOption='INSERT_ROWS',
    body={'values': row_data}
)
response = request.execute()

発電量予測サイトでの検討その1

  •  
  •  

発電量を予測するのに使ったサイト。

PVWatts® Calculator
アメリカのgovサイトだけど、地域名に日本の地名を入れてもちゃんと動いてくれる(単にgoogle map で緯度経度を引っ張ってきてるだけか)。
Rooftop Size Estimatorというのがあって、google map で自宅の屋上を拡大して、ポチ・ポチとパネルを置く想定の四角(またはそれ以上の多角形)を指定すると、ちゃんと緯度経度、面積、東西南北方向、屋根の角度まで推定して、発電量(system capacity) を kWdc(kW DC直流?)単位で出してきて、20%ぐらいの誤差はあるかな?という感じだが、まあまあ正確な気がする。手動で、Tilt(屋根の角度),Azimuth(屋根の向き)を入れればなお正確のような。
また月別の発電量・年間量も計算してくれる。

「東京ソーラー屋根台帳」(ポテンシャルマップ)
東京都地球温暖化防止活動推進センターで推奨?している、発電量予測のサイト。航空写真から勝手に(!)発電量を予測している。
このサイト、すでに勝手に発電量を診断してくれていて、自分の家をクリックするとその推定値が出てくる。

tokyosolar.netmap.jp.png
面積で 7m^2、0.7Kwというのはちょっと低すぎる。
たぶん、うちの屋根は北向き(+東に15度くらい)で2段(1/10= 5.71度, 5.2/10 = 27.61度)なので、屋根に置いたのではなくて、南面の壁に垂直に設置したものを想定しているのだろうか?よく分からない。周りの家の推定値を見てもちょっと???な数字ばかり。

契約

  •  
  •  

このブログ、太陽光発電の導入の検討・経緯を書いていくつもりだったが、初手からいきなり話が飛んですいませんが、契約してしまいました。

で工事請負契約書には、いわゆる重要事項説明のように確認事項がありました。

  • お支払金額について説明をうけました。
  • 設置する蓄電池のタイプについて説明をうけました。
  • 工事期間中の在宅要否について説明を受けました。
  • ご提示したシミュレーションが、設置状況や天候などの影響で変動する旨の説明を受けました。
  • 東京都助成金の受け取り時期、売電開始時期の説明を受けました。
  • 市区町村の補助金の申請に関して説明を受けました。

改めて上のことを確認した上で当初想定(思い込み?)とは違っていたところがあるのでメモ。

  • 支払金額については特に異論なし。見積りの内容の精査や値切りはしてないけど、まぁこんなもんだろうと。
  • 蓄電池のタイプについては、容量が大きいほうがいいだろうと思っていたが、設置スペースが無い(奥行きが敷地内に足りない。放熱などがあるので、ある程度まわりにスペースが必要)ということで、想定より1つ小さいサイズ(9Kwh)で、かつ、壁掛けになった。12Kwhのものにしたかったけど。。。メーカーさん、薄いものを作ってくれるとありがたいんですがね。
  • 在宅可否については、工事の1日は停電を伴う(電源の系統?の変更がある)ので会社を休んで対応してくれとのこと。
  • シミュレーション結果については、おおよそ問題無し。
  • 助成金の受け取りについては、工事終了から3,4ヶ月後に口座入金とのこと。もしローンを考えていたら、その間は全額を一時的に立替払いする必要がある。入金後にローンを一部繰り上げ返済となる。ここはちょっと想定外だった。
  • 売電については、東京電力と経産省の認可?が必要でおよそ6ヶ月かかるとのこと。その間、電気は送電網に流れていく(?)ことはあっても、それは収入対象にはならないとのこと。積極的に蓄電して自己消費に努めることしかないか?
  • 市区町村の補助金については、工事後の申請で、かつ、枠に漏れる可能性があるのですみやかに申請しないといけないとのこと。これもうまく行って入金は4ヶ月後くらいとのこと。うちの場合は20万くらいだが、これが貰えないのは大きい。