Scaled writing reg works, sample usage

This commit is contained in:
Paul Warren 2024-10-08 15:09:16 +11:00
parent 10e03f927d
commit 5de47d78b0
3 changed files with 99 additions and 25 deletions

View file

@ -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)

View file

@ -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)

37
force_charge.py Executable file
View file

@ -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)