Pymodbus Server write callback

Viewed 419

i am setting up a ModbusServer with pymodbus. i read a datalist over Serial port an write it into datastore of the server. so i can see data f.e. in ModbusPoll

now i want write back datapoints f.e. dp 1, value 10 function 16 on my modbus server

is there any callback or method to catch which address and value hast changed?

Many Thanks

class CustomDataBlock(ModbusSparseDataBlock):

    def setValues(self, address, value):
     super(CustomDataBlock, self).setValues(address, value)
     print("wrote {} to {}".format(value, address))

    def setValuesInternal(self, address, value):
     ModbusSparseDataBlock.setValues(CustomDataBlock, self).setValues(address, value)



def updating_writer(context):
 context[0].setValuesInternal(16, 0, valueDataAct) #update Datastore with Serial values

def run_updating_server():
 block  = CustomDataBlock([0]*378)
 store  = ModbusSlaveContext(di=block, co=block, hr=block, ir=block) 

 context = ModbusServerContext(slaves=store, single=True)


 time = 1  #in seconds
 loop = LoopingCall(f=updating_writer, context=(context))
 loop.start(time, now=False)

 StartTcpServer(context, address=('0.0.0.0', 502))   

 if __name__ == "__main__":
 run_updating_server()
1 Answers

You can do this by implementing a custom datablock - see the example in the documentation. You can then do whatever you want in setValues; the relevant section from the example is:

# --------------------------------------------------------------------------- #
# import the modbus libraries we need
# --------------------------------------------------------------------------- #
from pymodbus.version import version
from pymodbus.server.asynchronous import StartTcpServer
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.datastore import ModbusSparseDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
from pymodbus.transaction import ModbusRtuFramer, ModbusAsciiFramer

# --------------------------------------------------------------------------- #
# import the twisted libraries we need
# --------------------------------------------------------------------------- #
from twisted.internet.task import LoopingCall

# --------------------------------------------------------------------------- #
# configure the service logging
# --------------------------------------------------------------------------- #
import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)

class CustomDataBlock(ModbusSparseDataBlock):
    def setValues(self, address, value):
     super(CustomDataBlock, self).setValues(address, value)
     print("wrote {} to {}".format(value, address))

    def setValuesInternal(self, address, value):
     ModbusSparseDataBlock.setValues(self, address, value)


def updating_writer(context):
 print("value before update: " + str(context[0].getValues(4, 1, 1)))
 context[0].store['d'].setValuesInternal(2, [251]) #update Datastore with Serial values
 print("value after update: " + str(context[0].getValues(4, 1, 1)))

def run_updating_server():
 block  = CustomDataBlock([0]*378)
 store  = ModbusSlaveContext(di=block, co=block, hr=block, ir=block)

 context = ModbusServerContext(slaves=store, single=True)


 time = 1  #in seconds
 loop = LoopingCall(f=updating_writer, context=(context))
 loop.start(time, now=False)

 StartTcpServer(context, address=('0.0.0.0', 502))

if __name__ == "__main__":
 run_updating_server()
Related