diff --git a/FroniusReg.py b/FroniusReg.py index 302a3a4..73afc78 100644 --- a/FroniusReg.py +++ b/FroniusReg.py @@ -3,6 +3,16 @@ # Copyright 2024, Paul Warren # Licensed under AGPLv3, See LICENSE.md for terms +from enum import Enum + +from pymodbus.constants import Endian +from pymodbus.payload import BinaryPayloadDecoder +from pymodbus.client.tcp import ModbusTcpClient as ModbusClient +#from pymodbus.diag_message import * +#from pymodbus.file_message import * +#from pymodbus.other_message import * +#from pymodbus.mei_message import * + class DataType(Enum): String8 = 1 String16 = 2 @@ -32,7 +42,7 @@ class DataType(Enum): return int(2) def decode(self, value): - decoder = BinaryPayloadDecoder.fromRegisters(result.registers, byteorder=Endian.Big, wordorder=Endian.Big) + decoder = BinaryPayloadDecoder.fromRegisters(value.registers, byteorder=Endian.Big, wordorder=Endian.Big) if (self == DataType.String8) or (self == DataType.String16) or (self == DataType.String32): return str(decoder.decode_string(16).decode('utf-8')) @@ -55,6 +65,9 @@ class DataType(Enum): else: return str(decoder.decode_bits()) +class registerReadError(Exception): + pass + class FroniusReg: def __init__(self, address, datatype, unit, description): self.address = address @@ -68,12 +81,12 @@ class FroniusReg: self.datatype, self.unit) - def __getRegisterValue(modbusClient, address, dataType, unit): + def __getRegisterValue(self, modbusClient, address, dataType, unit): modbusValue = modbusClient.read_holding_registers(address-1, dataType.getRegisterLength(), slave=unit) if(modbusValue.isError()): - raise registerReadError() + raise registerReadError("Unable to read from Fronius Register: %d, %s" % (self.id, self.description)) return dataType.decode(modbusValue) diff --git a/froniustest.py b/froniustest.py index 2ff8dbe..65e7595 100644 --- a/froniustest.py +++ b/froniustest.py @@ -98,8 +98,6 @@ def main(): # [REGISTERADDRESS, DATATYPE, MODBUSUNITNUMBER] # the MODBUSUNITNUMBER is commonly 1 for the inverter and a user defined value for the primary smart meter (common values are 200 or 240) - print ("Register Overview:") - reg_map = ( [40092, DataType.Float32, 1], # Inverter AC Output in W [40285, DataType.UInt16, 1], # PV String 1 Output in W (scaled) @@ -126,50 +124,15 @@ def main(): "PWSF": [40268, DataType.Int16, 1, "Power Scaling Factor"] } - soc = getRegisterValue(modbusClient, - target_map["soc"][0], - target_map["soc"][1], - target_map["soc"][2]) - - socSF = getRegisterValue(modbusClient, - target_map["socSF"][0], - target_map["socSF"][1], - target_map["socSF"][2]) - - print(" SoC: " + str(soc)) - print("SoCSF: " + str(socSF)) - print(" SoC: %.2f %%" % (float(soc * 10 ** socSF))) - - PWSF = getRegisterValue(modbusClient, - target_map["PWSF"][0], - target_map["PWSF"][1], - target_map["PWSF"][2]) - - print(" PWSF: " + str(PWSF)) - - to_bat = getRegisterValue(modbusClient, - target_map["to_bat"][0], - target_map["to_bat"][1], - target_map["to_bat"][2]) - - print("To Bat: " + str(to_bat)) - - print("To Bat: %.2f" % (to_bat * 10 ** (int(PWSF)))) - - from_bat = getRegisterValue(modbusClient, - target_map["from_bat"][0], - target_map["from_bat"][1], - target_map["from_bat"][2]) - - print("Fr Bat: " + str(from_bat * 10 ** (int(PWSF)))) - - - num_avgs = 5 - count = 1 + num_avgs = 1 + count = 0 while count < num_avgs: - print("To AVG: " + str(get_avg_scaled(modbusClient, target_map["to_bat"], target_map["PWSF"]))) - print("Fr AVG: " + str(get_avg_scaled(modbusClient, target_map["from_bat"], target_map["PWSF"]))) + print("To AVG: %.2f" % get_avg_scaled(modbusClient, target_map["to_bat"], target_map["PWSF"])) + print("Fr AVG: %.2f" % get_avg_scaled(modbusClient, target_map["from_bat"], target_map["PWSF"])) count += 1 + + soc = get_avg_scaled(modbusClient, target_map["soc"], target_map['socSF'], points=2) + print(" SOC: %.2f%%" % soc) modbusClient.close()