Protect against zero reads in counter

This commit is contained in:
Max 2024-03-26 09:56:54 +01:00
parent d9657f1858
commit ac90840d29
2 changed files with 20 additions and 3 deletions

View File

@ -79,7 +79,8 @@ def main():
yield (date, 'firmware_version', {'version': common.version}, 1) yield (date, 'firmware_version', {'version': common.version}, 1)
for (m,a,v) in export(inv, meters): 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', prom.run(collect, metric_data, 'SolarEdge Modbus/TCP Exporter\n',

View File

@ -45,6 +45,16 @@ class Registers:
def read_scale(self, address): def read_scale(self, address):
return 10 ** self.read_int16(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: class CommonBlock:
def __init__(self, regs): def __init__(self, regs):
self.did = regs.read_uint16(0) self.did = regs.read_uint16(0)
@ -98,7 +108,8 @@ class Meter:
data = {} data = {}
scale = regs.read_scale(offset + len(labels)*2) scale = regs.read_scale(offset + len(labels)*2)
for (i, key) in enumerate(labels): 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.__dict__[metric] = data
self.frequency = regs.read_int16(14, scale=15) 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.ac_reactive_power = regs.read_int16(20, scale=21)
self.power_factor = regs.read_int16(22, scale=23) 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_current = regs.read_uint16(27, scale=28)
self.dc_voltage = regs.read_uint16(29, scale=30) self.dc_voltage = regs.read_uint16(29, scale=30)
self.dc_power = regs.read_int16(31, scale=32) self.dc_power = regs.read_int16(31, scale=32)
@ -139,6 +149,9 @@ class InverterBlock:
self.status = status_codes[self.status_code] self.status = status_codes[self.status_code]
self.status_vendor = regs.read_uint16(39) 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: class Inverter:
def __init__(self, host, port=1502, device=1): def __init__(self, host, port=1502, device=1):
self._conn = ModbusTcpClient(host, port) self._conn = ModbusTcpClient(host, port)
@ -155,6 +168,9 @@ class Inverter:
rs = self._conn.read_holding_registers(addr, length, slave=device) rs = self._conn.read_holding_registers(addr, length, slave=device)
return Registers(rs, length) return Registers(rs, length)
def header(self, base):
return Header(self.registers(base, 2), base)
def common_block(self): def common_block(self):
return CommonBlock(self.registers(40002, 67)) return CommonBlock(self.registers(40002, 67))