#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»