UniSet 2.32.1
Реализация ModbusTCP 'multi' master
См. также

Общее описание ModbusTCPMultiMaster

Класс реализует процесс обмена (опрос/запись) с RTU-устройствами, через TCP-шлюз. Список регистров с которыми работает процесс задаётся в конфигурационном файле в секции <sensors>. см. Конфигурирование ModbusTCPMultiMaster

При этом для шлюза можно задавать несколько ip-адресов (см. <GateList>), если связь пропадает по одному каналу (ip), то происходит переключение на другой канал (через timeout мсек), если пропадает с этим каналом, то переключается на следующий и так по кругу (в порядке уменьшения приоритета, задаваемого для каждого канала (cм. <GateList> priority).

Конфигурирование ModbusTCPMultiMaster

Конфигурирование процесса осуществляется либо параметрами командной строки либо через настроечную секцию.

Секция с настройками
При своём старте, в конфигурационном файле ищётся секция с названием объекта, в которой указываются настроечные параметры по умолчанию. Пример:
<MBMaster1 name="MBMaster1" polltime="200" channelTimeout="..." exchangeModeID="..">
<DeviceList>
<item addr="0x01" respondSensor="RTU1_Not_Respond_FS" force="0" timeout="2000" invert="1"/>
<item addr="0x02" respondSensor="RTU2_Respond_FS" timeout="2000" invert="0"/>
</DeviceList>
<GateList>
<item ip="" port="" respond_id="" priority="" force=""/>
<item ip="" port="" respond_id="" priority="" respond_invert="1"/>
<GateList>
</MBMaster1>
  • channelTimeout - умолчательный timeout для переключения каналов. По умолчанию: берётся общий defaultTimeout.

Секция <DeviceList> позволяет задать параметры обмена с конкретным RTU-устройством.

  • addr - адрес устройства для которого, задаются параметры
  • timeout msec - таймаут, для определения отсутствия связи
  • invert - инвертировать логику. По умолчанию датчик выставляется в "1" при наличии связи.
  • respondSensor - идентификатор датчика связи (DI).
  • force [1,0] - "1" - обновлять значение датчика связи в SM принудительно на каждом цикле проверки ("0" - только по изменению).
  • exchangeModeID - идентификатор датчика режима работы (см. MBExchange::ExchangeMode).
  • ask_every_reg - 1 - опрашивать ВСЕ регистры подряд, не обращая внимания на timeout. По умолчанию - "0" Т.е. опрос устройства (на текущем шаге цикла опроса), прерывается на первом же регистре, при опросе которого возникнет timeout.
  • safemodeXXX - см. Управление режимом "безопасного состояния"

Секция <GateList> позволяет задать несколько каналов связи со Slave-устройством. Это удобно для случая, когда Slave имеет более одного канала связи с ним (основной и резервный например).

  • ip - ip-адрес
  • port - порт
  • respond - датчик связи по данному каналу (помимо обобщённого)
  • priority - приоритет канала (чем больше число, тем выше приоритет)
  • respond_invert - инвертировать датчик связи (DI)
  • force [1,0] - "1" - обновлять значение датчика связи в SM принудительно на каждом цикле проверки ("0" - только по изменению).
  • timeout - таймаут на определение отсутствия связи для данного канала. По умолчанию берётся глобальный.
  • checkFunc - Номер функции для проверки соединения
  • checkAddr - Адрес устройства для проверки соединения
  • checkReg - Регистр для проверки соединения
Параметры запуска

При создании объекта в конструкторе передаётся префикс для определения параметров командной строки. По умолчанию xxx="mbtcp". Далее приведены основные параметры:

  • --xxx-name ID - идентификатор процесса.

IP-адрес шлюза задаётся параметром в конфигурационном файле gateway_iaddr или параметром командной строки --xxx-gateway-iaddr.

Порт задаётся в конфигурационном файле параметром gateway_port или параметром командной строки --xxx-gateway-port. По умолчанию используется порт 502.

  • --xxx-recv-timeout или recv_timeout msec - таймаут на приём одного сообщения. По умолчанию 100 мсек.
  • --xxx-timeout или timeout msec - таймаут на определение отсутствия связи (после этого идёт попытка реинициализировать соединение) По умолчанию 5000 мсек.
  • --xxx-reinit-timeout или reinit_timeout msec - таймаут на реинициализацию канала связи (после потери связи) По умолчанию timeout мсек.
  • --xxx-no-query-optimization или no_query_optimization - [1|0] отключить оптимизацию запросов

    Оптимизация заключается в том, что регистры идущие подряд автоматически запрашиваются/записываются одним запросом. В связи с чем, функция указанная в качестве mbfunc игнорируется и подменяется на работающую с многими регистрами.

  • --xxx-polltime или polltime msec - пауза между опросами. По умолчанию 100 мсек.
  • --xxx-checktime или checktime msec - пауза между проверками связи по разным каналам. По умолчанию 5000 мсек. Если задать <=0, то каналы будут просто переключаться по кругу (по timeout-у) в соответсвии с приоритетом (см. <GateList>). Если >0, то происходит проверка связи (раз в checktime) по всем каналам (см. <GateList>) и в случае потери связи, происходит переключение на следующий канал, по которому связь есть.
  • --xxx-initPause или initPause msec - пауза перед началом работы, после активации. По умолчанию 50 мсек.
  • --xxx-force или force [1|0]
    • 1 - перечитывать значения входов из SharedMemory на каждом цикле
    • 0 - обновлять значения только по изменению
  • --xxx-persistent-connection или persistent_connection - НЕ закрывать соединение после каждого запроса.
  • --xxx-force-out или force_out [1|0]
    • 1 - перечитывать значения выходов из SharedMemory на каждом цикле
    • 0 - обновлять значения только по изменению
  • --xxx-reg-from-id или reg_from_id [1|0]
    • 1 - в качестве регистра использовать идентификатор датчика
    • 0 - регистр брать из поля tcp_mbreg
  • --xxx-heartbeat-id или heartbeat_id ID - идентификатор датчика "сердцебиения" (см. Слежение за "живостью" объектов ("сердцебиение"))
  • --xxx-heartbeat-max или heartbeat_max val - сохраняемое значение счётчика "сердцебиения".
  • --xxx-activate-timeout msec . По умолчанию 2000. - время ожидания готовности SharedMemory к работе.
  • --xxx-check-func [1,2,3,4] - Номер функции для проверки соединения
  • --xxx-check-addr [1..255 ] - Адрес устройства для проверки соединения
  • --xxx-check-reg [1..65535] - Регистр для проверки соединения
  • --xxx-check-init-from-regmap - Взять адрес, функцию и регистр для проверки связи из списка опроса

Конфигурирование списка регистров для ModbusTCP master

Конфигурационные параметры задаются в секции <sensors> конфигурационного файла. Список обрабатываемых регистров задаётся при помощи двух параметров командной строки

  • --xxx-filter-field - задаёт фильтрующее поле для датчиков
  • --xxx-filter-value - задаёт значение фильтрующего поля. Необязательный параметр.
  • --xxx-statistic-sec sec - при наличии выведет кол-во посланных запросов за этот промежуток времени.
  • --xxx-set-prop-prefix [str] - Использовать 'str' в качестве префикса для свойств. Если не указать 'str' будет использован пустой префикс.

Если параметры не заданы, будет произведена попытка загрузить все датчики, у которых присутствуют необходимые настроечные параметры.

Предупреждения
Если в результате список будет пустым, процесс завершает работу.

Пример конфигурационных параметров:

<sensors name="Sensors">
...
<item name="MySensor_S" textname="my sesnsor" iotype="DI"
tcp_mbtype="rtu" tcp_mbaddr="0x01" tcp_mbfunc="0x04" tcp_mbreg="0x02" my_tcp="1"
/>
...
</sensors>
Предупреждения
При помощи –xxx-set-prop-prefix val можно принудительно задать префикс. Если просто указать ключ –xxx-set-prop-prefix - будет использован "пустой" префикс (свойства без префикса). Префикс должен задаваться "полным", т.е. включая _(подчёркивание), если оно используется в свойствах (например для "tcp_mbreg" должен быть задан –xxx-set-prop-prefix tcp_ ).

К основным параметрам относятся следующие (префикс tcp_ - для примера):

  • tcp_mbtype- [rtu] - пока едиственный разрешённый тип.
  • tcp_mbaddr- адрес RTU-устройства.
  • tcp_mbreg - запрашиваемый/записываемый регистр.
  • tcp_mbfunc- [0x1,0x2,0x3,...] функция опроса/записи. Разрешённые см. ModbusRTU::SlaveFunctionCode.

Помимо этого можно задавать следующие параметры:

  • tcp_vtype - тип переменной. см VTypes::VType.
  • tcp_rawdata - [0|1] - игнорировать или нет параметры калибровки
  • tcp_iotype- [DI,DO,AI,AO] - переназначить тип датчика. По умолчанию используется поле iotype.
  • tcp_nbit - номер бита в слове. Используется для DI,DO в случае когда для опроса используется функция читающая слова (03)
  • tcp_nbyte - [1|2] номер байта. Используется если tcp_vtype="byte".
  • tcp_mboffset - "сдвиг"(может быть отрицательным) при опросе/записи. Т.е. фактически будет опрошен/записан регистр "mbreg+mboffset".
  • tcp_pollfactor - [0...n] Частота опроса. n задаёт "частоту" опроса. т.е. опрос каждые 1...n циклов (зависит от общего polltime)

Для инициализации "выходов" (регистров которые пишутся) можно использовать поля:

  • tcp_preinit - [0|1] считать регистр перед использованием (при запуске процесса)
  • tcp_init_mbfunc - Номер функции для инициализации. Если не указана, будет определена автоматически исходя из tcp_mbfunc.
  • tcp_init_mbreg - Номер регистра откуда считывать значение для инициализации. Если это поле не указано используется tcp_mbreg.

Если указано tcp_preinit="1", то прежде чем начать писать регистр в устройство, будет произведено его чтение.

По умолчанию все "записываемые" регистры инициализируются значением из SM. Т.е. пока не будет первый раз считано значение из SM, регистры в устройство писатся не будут. Чтобы отключить это поведение, можно указать параметр

  • tcp_sm_initOK- [0|1] Игнорировать начальную инициализацию из SM (сразу писать в устройство)

При этом будет записывыться значение "default".

Предупреждения
Регистр должен быть уникальным. И может повторятся только если указан параметр nbit или nbyte.

Управление режимом работы MBTCPMultiMaster

В MBTCPMultiMaster заложена возможность управлять режимом работы процесса. Поддерживаются следующие режимы:

  • emNone - нормальная работа (по умолчанию)
  • emWriteOnly - "только посылка данных" (работают только write-функции)
  • emReadOnly - "только чтение" (работают только read-функции)
  • emSkipSaveToSM - "не записывать данные в SM", это особый режим, похожий на emWriteOnly, но отличие в том, что при этом режиме ведётся полноценый обмен (и read и write), только реально данные не записываются в SharedMemory(SM).
  • emSkipExchnage - отключить обмен (при этом данные "из SM" обновляются).

Режимы переключаются при помощи датчика, который можно задать либо аргументом командной строки --prefix-exchange-mode-id либо в конф. файле параметром exchangeModeID="". Константы определяющие режимы объявлены в MBTCPMultiMaster::ExchangeMode.

Проверка соединения

Для контроля состояния связи по "резервным" каналам создаётся специальный поток (check_thread), в котором происходит периодическая проверка связи по всем "пассивным"(резервным) в данный момент каналам. Это используется как для общей диагностики в системе, так и при выборе на какой канал переключаться в случае пропажи связи в основном канале. Т.е. будет выбран ближайший приоритетный канал у которого выставлен признак что есть связь. Период проверки связи по "резервным" каналам задаётся при помощи –prefix-checktime или параметром checktime="" в конфигурационном файле. В MBTCPMultiMaster реализовано два механизма проверки связи.

  • По умолчанию используется простая установка соединения и тут же его разрыв. Т.е. данные никакие не посылаются, но проверяется что host и port доступны для подключения.
  • Второй способ: это проверка соединения с посылкой modbus-запроса. Для этого имеется два способа указать адрес устройства, регистр и функция опроса для проверки. Либо в секции <GateList> для каждого канала можно указать:
    • адрес устройства checkAddr=""
    • функцию проверки checkFunc="" - функция может быть только [01,02,03,04] (т.е. функции чтения).
    • регистр checkReg Либо в командной строке задать параметры –prefix-check-addr, –prefix-check-func, –prefix-check-reg, которые будут одинаковыми для ВСЕХ КАНАЛОВ. Помимо этого если указать в командной строке аргумент –prefix-check-init-from-regmap, то для тестирования соединения будет взят первый попавшийся регистр из списка обмена.
Предупреждения
Способ проверки при помощи "modbus-запроса" имеет ряд проблем: Если фактически производится обмен с несколькими устройствами (несколько mbaddr) через TCP-шлюз, то может быть "ложное" срабатывание, т.к. фактически состояние канала будет определяться только по связи с каким-то одним конкретным устройством. И получается, что если обмен ведётся например с тремя устройствами, но проверка канала происходит только по связи с первым, то если оно перестанет отвечать, это будет считаться сбоем всего канала и этот канал будет исключён из обмена (!). Если ведётся обмен только с одним устройством, такой проблемы не возникает. Но плюсом данного способа проверки связи ("modbus-запросом") является то, что соединение поддерживается постоянным, в отличие от "первого способа" при котором оно создаётся и сразу рвётся и если проверка настроена достаточно часто (< TIME_WAIT для сокетов), то при длительной работе могут закончится дескрипторы на создание сокетов.