Обратный вызов записи сервера Pymodbus

#python #modbus

Вопрос:

я настраиваю сервер ModbusServer с помощью pymodbus. я считываю данные через последовательный порт и записываю их в хранилище данных сервера. так что я могу видеть данные, например, в ModbusPoll

теперь я хочу записать точки данных, например, dp 1, значение 10, функция 16 на моем сервере modbus

есть ли какой-либо обратный вызов или метод, чтобы узнать, какой адрес и значение изменились?

большое спасибо

 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:

Вы можете сделать это, реализовав пользовательский блок данных — см. Пример в документации. Затем вы можете делать все, что захотите setValues ; соответствующий раздел из примера:

 # --------------------------------------------------------------------------- #
# 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()
 

Комментарии:

1. спасибо, что работает… теперь у меня есть еще одна проблема, когда я записываю данные из последовательного интерфейса в хранилище данных, также вызываются реализованные значения набора CustomDataBlock… есть ли какое-либо решение для определения места записи данных?

2. Вы действительно не предоставили достаточно информации, чтобы ответить на этот вопрос. Я предполагаю, что вам нужно написать другую функцию, которая обновляет блок данных без вызова вашего пользовательского кода, и использовать ее для обновлений из вашего собственного кода.

3. я обновил свой вопрос псевдокодом, здесь вы можете увидеть, как в методе updating_writer я записал данные из сериального порта в хранилище данных с функцией «setValue», поэтому функция «setValues» в CustomDataBlock также вызывается, но это не то, что я хочу. эта функция должна просто вызываться, когда я писал данные на стороне клиента (например, из ModbusPoll)

4. Пожалуйста, ознакомьтесь с моим расширенным ответом.

5. я обновил свой код… теперь я получаю это сообщение об ошибке «ModbusSlaveContext» объект не имеет атрибута «setValuesInternal»