Каков синтаксис pymodbus для присвоения значений регистрам TCP-сервера? - PullRequest
2 голосов
/ 05 апреля 2019

Я пытаюсь реализовать простой синхронный TCP-сервер, используя Пример синхронного сервера .Однако я не понимаю объяснения синтаксиса в документации.Пример включает следующий блок кода:

store = ModbusSlaveContext(
     di=ModbusSequentialDataBlock(0, [17]*100),
     co=ModbusSequentialDataBlock(0, [17]*100),
     hr=ModbusSequentialDataBlock(0, [17]*100),
     ir=ModbusSequentialDataBlock(0, [17]*100))

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

Предположим, я хочу сохранить значение от 152 до Input Register (ir) адрес 30001 и значение от 276 до адреса 30002?Как мне адаптировать вышеуказанный код?

Ответы [ 2 ]

1 голос
/ 08 апреля 2019

Предположим, я хочу сохранить значение 152 для адреса 30001 'Input Register (ir)' и значение 276 для адреса 30002?Как мне адаптировать вышеуказанный код?

Вам нужен следующий код:

from pymodbus.server.sync import StartTcpServer
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext

import logging
FORMAT = ('%(asctime)-15s %(threadName)-15s'
          ' %(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)


def run_server():
    store = ModbusSlaveContext(
        ir=ModbusSequentialDataBlock(30001, [152, 276]), 
        zero_mode=True
    )
    context = ModbusServerContext(slaves=store, single=True)
    StartTcpServer(context, address=("localhost", 5020))


if __name__ == "__main__":
    run_server()

Контрольный пример:

from pymodbus.client.sync import ModbusTcpClient as ModbusClient

cli = ModbusClient('127.0.0.1', port=5020)
assert cli.connect()
res = cli.read_input_registers(30001, count=2, unit=1)
assert not res.isError()
print(res.registers)

Out:

[152, 276]
0 голосов
/ 06 апреля 2019

Из документов Pymodbus.

Хранилища данных отвечают только на те адреса, на которые они инициализированы Поэтому, если вы инициализируете DataBlock по адресам от 0x00 до 0xFF, на запрос 0x100 ответит недопустимым адресом исключения. Это потому что многие устройства демонстрируют такое поведение (но не все) ::

 block = ModbusSequentialDataBlock(0x00, [0]*0xff)

ModbusSequentialDataBlock принимает два аргумента во время инициализации address и value.

address – The starting address
values –  List of values to initialise each address with. 

Общий размер блока данных зависит от len(values).

Итак, взглянув на приведенный выше пример, мы пытаемся создать последовательный блок данных размером 0xFF, и каждый адрес инициализируется значением 0. так же В вашем случае, если вы хотите сохранить значение 152 для адреса 30001 «Входной регистр (и)» и значение 276 для адреса 30002. Вот что вам нужно сделать.

store = ModbusSlaveContext (

         di=ModbusSequentialDataBlock(0, [17]*100),
         co=ModbusSequentialDataBlock(0, [17]*100),
         hr=ModbusSequentialDataBlock(0, [17]*100),
         ir=ModbusSequentialDataBlock(0, [152, 276]), zero_mode=True)

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

Обратите внимание, что использование kwarg zero_mode=True без этого запроса read_input_registers против смещения 0 вернет 276 вместо 152, это потому, что без zero_mode=True pymodbus пытается сохранить значения на основе раздела 4.4 спецификация, поэтому адрес (0-7) будет соответствовать (1-8). Если вы не хотите использовать zero_mode, инициализируйте блок данных как ir=ModbusSequentialDataBlock(1, [152, 276]).

...