Вам нужен сервер обновлений , который вы можете использовать для заполнения регистров.Вам нужно сосредоточиться на функции def updating_writer
и выполнять последовательное чтение, обрабатывать их и записывать в регистры по вашему выбору.Пример трудно прочитать и понять с первого взгляда.Я изменил пример , чтобы удовлетворить ваши потребности.Но вот некоторые ключевые понятия, которые будут полезны для понимания кода.
ModbusSlaveContext
BinaryPayloadBuilder
Также обратите внимание,В этом примере используется асинхронный сервер на основе витой. Если вы новичок в витой или у вас есть ограничения, которые не позволят вам использовать витую на своей цели, вы можете добиться того же с помощью простых потоков.Дизайн будет примерно таким:
- Запустите функцию обновления в отдельном потоке
- Запустите ваш TCP-сервер в конце (блокировка)
# Complete gist here --> https://gist.github.com/dhoomakethu/540b15781c62de6d1f7c318c3fc8ae22
def updating_writer(context, device, baudrate):
""" A worker process that runs every so often and
updates live values of the context. It should be noted
that there is a race condition for the update.
:param arguments: The input arguments to the call
"""
log.debug("updating the context")
log.debug("device - {}, baudrate-{}".format(device, baudrate))
data = serial_reader(device, baudrate) # Implement your serial reads, return list of floats.
if data:
# We can not directly write float values to registers, Use BinaryPayloadBuilder to convert float to IEEE-754 hex integer
for d in data:
builder.add_32bit_float(d)
registers = builder.to_registers()
context = context
register = 3 # Modbus function code (3) read holding registers. Just to uniquely identify what we are reading from /writing in to.
slave_id = 0x01 # Device Unit address , refer ModbusSlaveContext below
address = 0x00 # starting offset of register to write (0 --> 40001)
log.debug("new values: " + str(registers))
context[slave_id].setValues(register, address, registers)
Когда сервер запущен и значения обновляются, вы можете использовать клиент для считывания значений и синтаксического разбора его на плавающее значение.
from pymodbus.client.sync import ModbusTcpClient as Client
from pymodbus.payload import BinaryPayloadDecoder, Endian
client = Client(<IP-ADDRESS>, port=5020)
# Each 32 bit float is stored in 2 words, so we will read 10 registers
raw_values = client.read_holding_registers(0, 10, unit=1)
if not registers.isError():
registers = raw_values.registers
decoder = BinaryPayloadDecoder.fromRegisters(registers,
wordorder=Endian.Big, byteorder=Endian.Big)
for _ in range(5):
print(decoder.decode_32bit_float())