calculate power values for DCU (#303)

* calculate power values for DCU

* refactor code
This commit is contained in:
Stefan Allius
2025-03-02 21:09:03 +01:00
committed by GitHub
parent 10b4a84701
commit be60f9ea1e
4 changed files with 160 additions and 47 deletions

View File

@@ -5,6 +5,21 @@ from itertools import chain
from infos import Infos, Register, ProxyMode, Fmt
class RegisterFunc:
@staticmethod
def prod_sum(info: Infos, arr: dict) -> None | int:
result = 0
for sum in arr:
prod = 1
for factor in sum:
val = info.get_db_value(factor)
if val is None:
return None
prod = prod * val
result += prod
return result
class RegisterMap:
# make the class read/only by using __slots__
__slots__ = ()
@@ -121,11 +136,11 @@ class RegisterMap:
0x42010034: {'reg': Register.BATT_PV2_VOLT, 'fmt': '!H', 'ratio': 0.01}, # noqa: E501, PV2 voltage
0x42010036: {'reg': Register.BATT_PV2_CUR, 'fmt': '!H', 'ratio': 0.01}, # noqa: E501, PV2 current
0x42010038: {'reg': Register.BATT_38, 'fmt': '!h'}, # noqa: E501
0x4201003a: {'reg': Register.BATT_3a, 'fmt': '!h'}, # noqa: E501
0x4201003c: {'reg': Register.BATT_3c, 'fmt': '!h'}, # noqa: E501
0x4201003e: {'reg': Register.BATT_3e, 'fmt': '!h'}, # noqa: E501
0x42010040: {'reg': Register.BATT_40, 'fmt': '!h', 'ratio': 0.01}, # noqa: E501
0x42010042: {'reg': Register.BATT_42, 'fmt': '!h', 'ratio': 0.01}, # noqa: E501
0x4201003a: {'reg': Register.BATT_3a, 'fmt': '!h', 'ratio': 0.01}, # noqa: E501
0x4201003c: {'reg': Register.BATT_STATUS_1, 'fmt': '!h'}, # noqa: E501
0x4201003e: {'reg': Register.BATT_STATUS_2, 'fmt': '!h'}, # noqa: E501
0x42010040: {'reg': Register.BATT_VOLT, 'fmt': '!h', 'ratio': 0.01}, # noqa: E501
0x42010042: {'reg': Register.BATT_CUR, 'fmt': '!h', 'ratio': 0.01}, # noqa: E501
0x42010044: {'reg': Register.BATT_SOC, 'fmt': '!H', 'ratio': 0.01}, # noqa: E501, state of charge (SOC) in percent
0x42010046: {'reg': Register.BATT_46, 'fmt': '!h'}, # noqa: E501
0x42010048: {'reg': Register.BATT_48, 'fmt': '!h'}, # noqa: E501
@@ -136,13 +151,22 @@ class RegisterMap:
0x42010066: {'reg': Register.BATT_66, 'fmt': '!h'}, # noqa: E501
0x42010068: {'reg': Register.BATT_68, 'fmt': '!h'}, # noqa: E501
0x4201006a: {'reg': Register.BATT_6a, 'fmt': '!h'}, # noqa: E501
0x4201006c: {'reg': Register.BATT_6c, 'fmt': '!h'}, # noqa: E501
0x4201006e: {'reg': Register.BATT_6e, 'fmt': '!h'}, # noqa: E501
0x4201006c: {'reg': Register.BATT_OUT_VOLT, 'fmt': '!h', 'ratio': 0.01}, # noqa: E501
0x4201006e: {'reg': Register.BATT_OUT_CUR, 'fmt': '!h', 'ratio': 0.01}, # noqa: E501
0x42010070: {'reg': Register.BATT_70, 'fmt': '!h'}, # noqa: E501
0x42010072: {'reg': Register.BATT_72, 'fmt': '!h'}, # noqa: E501
0x42010074: {'reg': Register.BATT_74, 'fmt': '!h'}, # noqa: E501
0x42010076: {'reg': Register.BATT_76, 'fmt': '!h'}, # noqa: E501
0x42010078: {'reg': Register.BATT_78, 'fmt': '!h'}, # noqa: E501
'calc': {
1: {'reg': Register.BATT_PV_PWR, 'func': RegisterFunc.prod_sum, # noqa: E501
'params': [[Register.BATT_PV1_VOLT, Register.BATT_PV1_CUR],
[Register.BATT_PV2_VOLT, Register.BATT_PV2_CUR]]},
2: {'reg': Register.BATT_PWR, 'func': RegisterFunc.prod_sum, # noqa: E501
'params': [[Register.BATT_VOLT, Register.BATT_CUR]]},
3: {'reg': Register.BATT_OUT_PWR, 'func': RegisterFunc.prod_sum, # noqa: E501
'params': [[Register.BATT_OUT_VOLT, Register.BATT_OUT_CUR]]},
}
}
@@ -191,13 +215,20 @@ class InfosG3P(Infos):
# iterate over RegisterMap.map and get the register values
sensor = self.get_db_value(Register.SENSOR_LIST)
if "3026" == sensor:
items = RegisterMap.map_3026.items()
reg_map = RegisterMap.map_3026
elif "02b0" == sensor:
items = RegisterMap.map_02b0.items()
reg_map = RegisterMap.map_02b0
else:
items = {}
reg_map = {}
items = reg_map.items()
if 'calc' in reg_map:
virt = reg_map['calc'].items()
else:
virt = {}
for _, row in chain(RegisterMap.map.items(), items):
for idx, row in chain(RegisterMap.map.items(), items, virt):
if 'calc' == idx:
continue
info_id = row['reg']
if self.__hide_topic(row):
res = self.ha_remove(info_id, node_id, snr) # noqa: E501
@@ -213,7 +244,10 @@ class InfosG3P(Infos):
stores the values in Infos.db
buf: buffer of the sequence to parse'''
for idx, row in RegisterSel.get(sensor).items():
reg_map = RegisterSel.get(sensor)
for idx, row in reg_map.items():
if 'calc' == idx:
continue
addr = idx & 0xffff
ftype = (idx >> 16) & 0xff
mtype = (idx >> 24) & 0xff
@@ -223,16 +257,19 @@ class InfosG3P(Infos):
continue
info_id = row['reg']
result = Fmt.get_value(buf, addr, row)
yield from self.__update_val(node_id, info_id, result)
keys, level, unit, must_incr = self._key_obj(info_id)
if keys:
name, update = self.update_db(keys, must_incr, result)
yield keys[0], update
else:
name = str(f'info-id.0x{addr:x}')
update = False
if 'calc' in reg_map:
for row in reg_map['calc'].values():
info_id = row['reg']
result = row['func'](self, row['params'])
yield from self.__update_val(node_id, info_id, result)
def __update_val(self, node_id, info_id, result):
keys, level, unit, must_incr = self._key_obj(info_id)
if keys:
name, update = self.update_db(keys, must_incr, result)
yield keys[0], update
if update:
self.tracer.log(level, f'[{node_id}] GEN3PLUS: {name}'
f' : {result}{unit}')

View File

@@ -127,10 +127,10 @@ class Register(Enum):
BATT_PV2_CUR = 1003
BATT_38 = 1004
BATT_3a = 1005
BATT_3c = 1006
BATT_3e = 1007
BATT_40 = 1010
BATT_42 = 1011
BATT_STATUS_1 = 1006
BATT_STATUS_2 = 1007
BATT_VOLT = 1010
BATT_CUR = 1011
BATT_SOC = 1012
BATT_46 = 1013
BATT_48 = 1014
@@ -140,13 +140,17 @@ class Register(Enum):
BATT_66 = 1018
BATT_68 = 1019
BATT_6a = 1020
BATT_6c = 1021
BATT_6e = 1022
BATT_OUT_VOLT = 1021
BATT_OUT_CUR = 1022
BATT_70 = 1023
BATT_72 = 1024
BATT_74 = 1025
BATT_76 = 1026
BATT_78 = 1027
BATT_PV_PWR = 1040
BATT_PWR = 1041
BATT_OUT_PWR = 1042
VALUE_1 = 9000
TEST_REG1 = 10000
TEST_REG2 = 10001
@@ -157,7 +161,10 @@ class Fmt:
def get_value(buf: bytes, idx: int, row: dict):
'''Get a value from buf and interpret as in row defined'''
fmt = row['fmt']
res = struct.unpack_from(fmt, buf, idx)
try:
res = struct.unpack_from(fmt, buf, idx)
except Exception:
return None
result = res[0]
if isinstance(result, (bytearray, bytes)):
result = result.decode().split('\x00')[0]
@@ -572,12 +579,12 @@ class Infos:
Register.BATT_PV2_VOLT: {'name': ['batterie', 'pv2', 'Voltage'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'bat_inp_pv2', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_pv2_', 'val_tpl': "{{ (value_json['pv2']['Voltage'] | float)}}", 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_PV2_CUR: {'name': ['batterie', 'pv2', 'Current'], 'level': logging.INFO, 'unit': 'A', 'ha': {'dev': 'bat_inp_pv2', 'dev_cla': 'current', 'stat_cla': 'measurement', 'id': 'cur_pv2_', 'val_tpl': "{{ (value_json['pv2']['Current'] | float)}}", 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_38: {'name': ['batterie', 'Reg_38'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_38_', 'fmt': FMT_FLOAT, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_3a: {'name': ['batterie', 'Reg_3a'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_3a_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_3c: {'name': ['batterie', 'Reg_3c'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_3c_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_3e: {'name': ['batterie', 'Reg_3e'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_3e_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_40: {'name': ['batterie', 'Reg_40'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_40_', 'fmt': FMT_FLOAT, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_42: {'name': ['batterie', 'Reg_42'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_42_', 'fmt': FMT_FLOAT, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_SOC: {'name': ['batterie', 'SOC'], 'level': logging.INFO, 'unit': '%', 'ha': {'dev': 'batterie', 'dev_cla': None, 'stat_cla': 'measurement', 'id': 'soc_', 'fmt': FMT_FLOAT, 'name': 'State of Charge', 'icon': 'mdi:battery-90'}}, # noqa: E501
Register.BATT_3a: {'name': ['batterie', 'Reg_3a'], 'level': logging.INFO, 'unit': 'kWh', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_3a_', 'fmt': FMT_FLOAT, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_STATUS_1: {'name': ['batterie', 'Status_1'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'comp': 'sensor', 'dev_cla': None, 'stat_cla': None, 'id': 'status1_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_STATUS_2: {'name': ['batterie', 'Status_2'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'comp': 'sensor', 'dev_cla': None, 'stat_cla': None, 'id': 'status2_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_VOLT: {'name': ['batterie', 'Voltage'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'batterie', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'volt_bat_', 'fmt': FMT_FLOAT, 'name': 'Bat Voltage', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_CUR: {'name': ['batterie', 'Current'], 'level': logging.INFO, 'unit': 'A', 'ha': {'dev': 'batterie', 'dev_cla': 'current', 'stat_cla': 'measurement', 'id': 'cur_bat_', 'fmt': FMT_FLOAT, 'name': 'Bat Current', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_SOC: {'name': ['batterie', 'SOC'], 'level': logging.INFO, 'unit': '%', 'ha': {'dev': 'batterie', 'dev_cla': None, 'stat_cla': 'measurement', 'id': 'soc_', 'fmt': FMT_FLOAT, 'name': 'State of Charge (SOC)', 'icon': 'mdi:battery-90'}}, # noqa: E501
# Register.BATT_46: {'name': ['batterie', 'Reg_46'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_46_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
# Register.BATT_48: {'name': ['batterie', 'Reg_48'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_48_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
# Register.BATT_4a: {'name': ['batterie', 'Reg_4a'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_4a_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
@@ -587,13 +594,16 @@ class Infos:
Register.BATT_66: {'name': ['batterie', 'Reg_66'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_66_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_68: {'name': ['batterie', 'Reg_68'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_68_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_6a: {'name': ['batterie', 'Reg_6a'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_6a_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_6c: {'name': ['batterie', 'Reg_6c'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_6c_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_6e: {'name': ['batterie', 'Reg_6e'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_6e_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_OUT_VOLT: {'name': ['batterie', 'out', 'Voltage'], 'level': logging.INFO, 'unit': 'V', 'ha': {'dev': 'batterie', 'dev_cla': 'voltage', 'stat_cla': 'measurement', 'id': 'out_volt_', 'val_tpl': "{{ (value_json['out']['Voltage'] | float)}}", 'name': 'Out Voltage', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_OUT_CUR: {'name': ['batterie', 'out', 'Current'], 'level': logging.INFO, 'unit': 'A', 'ha': {'dev': 'batterie', 'dev_cla': 'current', 'stat_cla': 'measurement', 'id': 'out_cur_', 'val_tpl': "{{ (value_json['out']['Current'] | float)}}", 'name': 'Out Current', 'icon': GAUGE, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_70: {'name': ['batterie', 'Reg_70'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_70_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_72: {'name': ['batterie', 'Reg_72'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_72_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_74: {'name': ['batterie', 'Reg_74'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_74_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_76: {'name': ['batterie', 'Reg_76'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_76_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_78: {'name': ['batterie', 'Reg_78'], 'level': logging.INFO, 'unit': '', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'batt_78_', 'fmt': FMT_INT, 'ent_cat': 'diagnostic'}}, # noqa: E501
Register.BATT_PV_PWR: {'name': ['batterie', 'PV_Power'], 'level': logging.INFO, 'unit': 'W', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'pv_power_', 'fmt': FMT_INT, 'name': 'PV Power'}}, # noqa: E501
Register.BATT_PWR: {'name': ['batterie', 'Power'], 'level': logging.INFO, 'unit': 'W', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'power_', 'fmt': FMT_INT, 'name': 'Batterie Power'}}, # noqa: E501
Register.BATT_OUT_PWR: {'name': ['batterie', 'out', 'Power'], 'level': logging.INFO, 'unit': 'W', 'ha': {'dev': 'batterie', 'dev_cla': 'power', 'stat_cla': 'measurement', 'id': 'out_power_', 'val_tpl': "{{ (value_json['out']['Power'] | int)}}", 'name': 'Out Power'}}, # noqa: E501
}
@property