From ac90840d29355f4857732980afb116a6c920cfd4 Mon Sep 17 00:00:00 2001 From: Max Date: Tue, 26 Mar 2024 09:56:54 +0100 Subject: [PATCH] Protect against zero reads in counter --- solaredge_modbus.py | 3 ++- sunspec.py | 20 ++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/solaredge_modbus.py b/solaredge_modbus.py index 24acafb..01edc00 100644 --- a/solaredge_modbus.py +++ b/solaredge_modbus.py @@ -79,7 +79,8 @@ def main(): yield (date, 'firmware_version', {'version': common.version}, 1) for (m,a,v) in export(inv, meters): - yield (date,m,a,v) + if v is not None: + yield (date,m,a,v) prom.run(collect, metric_data, 'SolarEdge Modbus/TCP Exporter\n', diff --git a/sunspec.py b/sunspec.py index cf8eed3..994cfca 100644 --- a/sunspec.py +++ b/sunspec.py @@ -45,6 +45,16 @@ class Registers: def read_scale(self, address): return 10 ** self.read_int16(address) +class Header: + def __init__(self, regs, base): + self.did = regs.read_uint16(0) + self.len = regs.read_uint16(1) + self.base = base + self.end = base + self.len + + def __str__(self): + return f"SunSpec(DID={self.did}, [{self.base}:{self.end}]" + class CommonBlock: def __init__(self, regs): self.did = regs.read_uint16(0) @@ -98,7 +108,8 @@ class Meter: data = {} scale = regs.read_scale(offset + len(labels)*2) for (i, key) in enumerate(labels): - data[key] = regs.read_uint32(offset + 2*i) * scale / 10 + value = regs.read_uint32(offset + 2*i) * scale / 10 + data[key] = value if value > 1 else None self.__dict__[metric] = data self.frequency = regs.read_int16(14, scale=15) @@ -130,7 +141,6 @@ class InverterBlock: self.ac_reactive_power = regs.read_int16(20, scale=21) self.power_factor = regs.read_int16(22, scale=23) - self.ac_energy = regs.read_uint32(24, scale=26) self.dc_current = regs.read_uint16(27, scale=28) self.dc_voltage = regs.read_uint16(29, scale=30) self.dc_power = regs.read_int16(31, scale=32) @@ -139,6 +149,9 @@ class InverterBlock: self.status = status_codes[self.status_code] self.status_vendor = regs.read_uint16(39) + ac_energy = regs.read_uint32(24, scale=26) + self.ac_energy = ac_energy if ac_energy > 1 else None + class Inverter: def __init__(self, host, port=1502, device=1): self._conn = ModbusTcpClient(host, port) @@ -155,6 +168,9 @@ class Inverter: rs = self._conn.read_holding_registers(addr, length, slave=device) return Registers(rs, length) + def header(self, base): + return Header(self.registers(base, 2), base) + def common_block(self): return CommonBlock(self.registers(40002, 67))