diff --git a/FroniusReg.py b/FroniusReg.py index 6c7a038..152a2c3 100644 --- a/FroniusReg.py +++ b/FroniusReg.py @@ -6,7 +6,7 @@ from enum import Enum from pymodbus.constants import Endian -from pymodbus.payload import BinaryPayloadDecoder +from pymodbus.payload import BinaryPayloadDecoder, BinaryPayloadBuilder #from pymodbus.client.tcp import ModbusTcpClient as ModbusClient #from pymodbus.diag_message import * #from pymodbus.file_message import * @@ -65,6 +65,35 @@ class DataType(Enum): else: return str(decoder.decode_bits()) + def encode(self, value): + encoder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Big) + + if (self == DataType.String8) or (self == DataType.String16) or (self == DataType.String32): + return encoder.add_string(value).build() + + elif (self == DataType.Int16): + encoder.add_16bit_int(int(value)) + return encoder.build() + # return int(value) + + elif (self == DataType.UInt16): + encoder.add_16bit_uint(int(value)) + return encoder.build() + + elif (self == DataType.Int32): + return encoder.add_32bit_int(value).build() + + elif (self == DataType.UInt32): + return encoder.add_32bit_uint(value).build() + + elif (self == DataType.Float32): + return encoder.add_32bit_float(value).build() + + else: + return encoder.add_bits(value).build() + + + class registerReadError(Exception): pass @@ -78,8 +107,8 @@ class FroniusReg: def getValue(self, modbusClient): return self.__getRegisterValue(modbusClient) - def setValue(self, modbusClient): - return self.__setRegisterValue(modbusClient) + def setValue(self, modbusClient, value): + return self.__setRegisterValue(modbusClient, value) def __getRegisterValue(self, modbusClient): modbusValue = modbusClient.read_holding_registers(self.address-1, @@ -91,10 +120,12 @@ class FroniusReg: raise registerReadError("It's NONE!") return self.datatype.decode(modbusValue) - def __setRegisterValue(self, modbusClient): - modbusValue = modbusClient.write_holding_registers(self.address-1, - self.datatype.getRegisterLength(), - slave=self.unit) + def __setRegisterValue(self, modbusClient, value): + modbusValue = modbusClient.write_registers(self.address-1, + self.datatype.encode(value), + count=self.datatype.getRegisterLength(), + slave=self.unit, + skip_encode=True) return modbusValue @@ -106,18 +137,38 @@ class ScaledFroniusReg: def getValue(self, modbusClient): return self.valueReg.getValue(modbusClient) * 10 ** self.scaleReg.getValue(modbusClient) - def setValue(self, modbusClient): - return self.valueReg.setValue(modbusClient, self.scaleReg.getValue(modbusClient)) + def setValue(self, modbusClient, value): + return self.valueReg.setValue(modbusClient, value / 10 ** self.scaleReg.getValue(modbusClient)) +MaxChaRte = FroniusReg(40155, DataType.UInt16, 1, "Max Charge Rate") +MaxChaRte_SF = FroniusReg(40156, DataType.Int16, 1, "Max Charge Rate SF") +wChaGra = FroniusReg(40357, DataType.UInt16, 1, "Max Charge Power") storageStateOfCharge = FroniusReg(40362, DataType.UInt16, 1, "Storage State of Charge") storageStateOfChargeSF = FroniusReg(40376, DataType.Int16, 1, "Storage State of Charge Scaling Factor") scaledStateOfCharge = ScaledFroniusReg(storageStateOfCharge, storageStateOfChargeSF) -OutWRte = FroniusReg(40367, DataType.Int16, 1, "DischargeRate, Negative means Charging") +OutWRte = FroniusReg(40366, DataType.Int16, 1, "DischargeRate") +InWRte = FroniusReg(40367, DataType.Int16, 1, "ChargeRate") WRteSF = FroniusReg(40379, DataType.Int16, 1, "ScalingFactor for storage Watts") -scaledDischarge = ScaledFroniusReg(OutWRte, WRteSF) +StorCtl_Mode = FroniusReg(40359, DataType.UInt16, 1, "Hold/Charge/Discharge enable") +MinRsvPct = FroniusReg(40361, DataType.UInt16, 1, "Reserve Percentage") + +InOutWRte_RvrtTms = FroniusReg(40369, DataType.UInt16, 1, "Revert timer for charge settings") + +ChaGriSet = FroniusReg(40371, DataType.UInt16, 1, "enum16, 0 = PV only, 1 = Grid enabled") +WChaDisChaGra_SF = FroniusReg(40373, DataType.Int16, 1, "Charge/Discharge Power SF") + +MinRsvPct_SF = FroniusReg(40375, DataType.Int16, 1, "Reserve Percentage Scaling") + +scaledOutWRte = ScaledFroniusReg(OutWRte, WRteSF) +scaledInWRte = ScaledFroniusReg(InWRte, WRteSF) +scaledReserve = ScaledFroniusReg(MinRsvPct, MinRsvPct_SF) + +scaledMaxChaRte = ScaledFroniusReg(MaxChaRte, MaxChaRte_SF) + +scaledMaxWChaGra = ScaledFroniusReg(wChaGra, WChaDisChaGra_SF) diff --git a/SoCtest.py b/SoCtest.py deleted file mode 100755 index 1d8ffe8..0000000 --- a/SoCtest.py +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env python3 - -import FroniusReg - -from pymodbus.client.tcp import ModbusTcpClient - -fronius1 = ModbusTcpClient("172.19.107.211", port=502, timeout=10) -fronius1.connect() - -soc = FroniusReg.scaledStateOfCharge.getValue(fronius1) -print(" SOC: %s%%" % soc) - -discharge = FroniusReg.scaledDischarge.getValue(fronius1) -print(" Rate: %dW" % discharge) diff --git a/force_charge.py b/force_charge.py new file mode 100755 index 0000000..cf840b1 --- /dev/null +++ b/force_charge.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 + +import FroniusReg + +from pymodbus.client.tcp import ModbusTcpClient + +fronius1 = ModbusTcpClient("172.19.107.211", port=502, timeout=10) +fronius1.connect() + +soc = FroniusReg.scaledStateOfCharge.getValue(fronius1) +print(" SOC: %s%%" % soc) + +discharge = FroniusReg.scaledOutWRte.getValue(fronius1) +print("Pre DRate: %d%%" % discharge) + +charge = FroniusReg.scaledInWRte.getValue(fronius1) +print("Pre CRate: %d%%" % charge) + +mode = FroniusReg.StorCtl_Mode.getValue(fronius1) +print("Pre Mode: %d" % mode) + +# This should be 'limit discharge' mode +err = FroniusReg.StorCtl_Mode.setValue(fronius1, 2) +# Charge battery at a rate from -2% discharge to 100% charge +# as a percentage of the MaxChaRte, which in our case is 25600W +err = FroniusReg.scaledOutWRte.setValue(fronius1, -10) +err = FroniusReg.scaledInWRte.setValue(fronius1, 100) + +discharge = FroniusReg.scaledOutWRte.getValue(fronius1) +print("Post DRate: %d%%" % discharge) + +charge = FroniusReg.scaledInWRte.getValue(fronius1) +print("Post CRate: %d%%" % charge) + +mode = FroniusReg.StorCtl_Mode.getValue(fronius1) +print("Post Mode: %d" % mode) +