Содержание
Модуль PfeifferProxy - это прокси драйвер (драйвер шины) для подключения устройств, работающих по протоколу Pfeiffer.
Модуль PfeifferProxy основан и работает по аналогии с ModbusProxy, то есть суть его работы аналогична.
Модуль PfeifferProxy реализует протокол приемо-передачи Pfeiffer (клиент, мастер), в соответствии со спецификацией "Pfeiffer Vacuum Protocol Interface RS232, RS485". В текущей версии поддерживается до 16 логических портов.
Клиент PfeifferProxy ничего не делает сам по себе, он лишь обеспечивает прием и передачу данных через порты по протоколу Pfeiffer, выстраивая опросы от драйверов в очередь и предотвращая конфликты при наличии множества устройств на каждом порте. В то же время подчиненные драйверы напрямую не работают с физическими портами COM, они работают с логическими портами (номерами 1..16). Всю работу, связанную с физическими портами, берет на себя клиент PfeifferProxy.
Подчиненные драйверы периодически посылают в консоль &PfeifferProxy команду [@Pfeiffer.Poll](#poll_logic) которая помещается в очередь для последующего выполнения. Когда приходит очередь, клиент PfeifferProxy инициирует опрос физического порта, связанного с указанным в запросе логическим портом и по результатам опроса посылает драйверу результат в виде консольной команды: @Pfeiffer.Reply, @Pfeiffer.Refuse или @Pfeiffer.TimeOut.
&PfeifferProxy не требует регистрации драйверов, которые к нему обращаются, поскольку в каждом запросе указывается имя (или ссылка) драйвера, которому надо передать ответ для последующей обработки. Таким образом, драйверы могут пользоваться услугами клиента PfeifferProxy в довольно свободном режиме. Например, драйвер может обрабатывать ввод-вывод нескольких модулей на разных портах, а разные драйверы могут опрашивать один модуль. Клиент &PfeifferProxy обеспечивает бесконфликтную сериализацию (выстраивание опросов в очередь) и канальный уровень приемо-передачи (порты, заголовки, контрольные суммы, отработка таймаутов). Таким образом, подчиненные драйверы могут сосредоточиться на обработке данных.
При написании подчиненных драйверов (как и самого клиента &PfeifferProxy) используется библиотека NetPfeiff.
Имеется работающий пример demo_edutc110.
Конфигурация клиента &PfeifferProxy имеет примерно такой вид:
[DeviceList]
&PfeifferProxy = device software program
[&PfeifferProxy]
Comment = PFEIFFER PROXY MASTER.
InquiryPeriod = 0
DevicePolling = 10, tpHigher
ProgramSource = ~~\resource\daqsite\pfeifferproxy\pfeifferproxy.pas
DebugFlags = 3
OpenConsole = 2
StdInFifo = 512
StdOutFifo = 512
StartingOrder = -1024
StoppingOrder = +1024
StartupScript = [&PfeifferProxy.StartupScript]
FinallyScript = [&PfeifferProxy.FinallyScript]
[]
либо просто делается ссылка на стандартную конфигурацию
[ConfigFileList]
ConfigFile = ~~\resource\daqsite\default\pfeifferproxy.cfg
[]
при этом
в секцию [&PfeifferProxy.StartupScript] надо поместить описание портов Pfeiffer.Таблица логических портов Pfeiffer задается в секции [&PfeifferProxy.StartupScript] через консольные команды, описанные ниже. Поэтому эта секция обязательно должна быть описана. Хотя, строго говоря, все описание может генерироваться и динамически, через посылку сообщений. При этом размер буфера StdInFifo должен быть достаточным для размещения таблиц из секции StartupScript.
Команда @Reset очищает все таблицы портов и приводит клиент в исходное состояние. С этой команды рекомендуется начинать описание таблиц портов клиента.
Команда @ZeroPortCounters очищает все теги со счетчиками ошибок. Эту команду можно дать при старте, после инициализации всех таблиц портов.
Команда @Port port decl - задает таблицу логических портов.
Логический порт - это просто номер (индекс в таблице физических портов) для последующего подключения к нему устройств. Каждый логический порт имеет номер port и определение decl. В данной версии номера логических портов port занимают диапазон (1..16). Определение decl может содержать писание порта TCP или COM, как описано в справке по функции pipe_init() (при этом TCP подключение должно быть клиентским).
Например:
@port 2 com port 8 baudrate 9600 parity even databits 8 stopbits 1
- логический порт №2 использует COM порт №4, скорость 9600 бит/сек,
- контроль четности EVEN, 8 бит данных, 1 стоповый бит.Допускается любая комбинация типов портов и протоколов, например "RTU over TCP/IP".
Командой @PortErrorCounters port Rx Tx Ex можно задать теги счетчиков ошибок данного порта.
Командой @PortErrorRates port Rx Tx Ex можно задать теги скорости счета ошибок данного порта.
Здесь
port - номер порта.
Rx - имя тега для счетчика ошибок приемника, когда приходят запросы с неверным адресом устройства, неверной контрольной суммой и т.д.
Tx - имя тега для счетчика ошибок передатчика, когда не удается отправить ответ на запрос.
Ex - имя тега для счетчика ошибок - исключений Pfeiffer, когда в запросе указан неверный адрес статусного или регистрового входа-выхода.
Аналогично задаются теги для подсчета траффика:
Командой @PortPollCounters port Rx Tx можно задать теги счетчиков запросов данного порта.
Командой @PortPollRates port Rx Tx можно задать теги скорости поступления запросов данного порта.
Командой @PortByteCounters port Rx Tx можно задать теги счетчиков потока байтов данного порта.
Командой @PortByteRates port Rx Tx можно задать теги скорости счета потока байтов данного порта.
Теги счетчиков могут иметь тип Integer или (лучше) Real. При необходимости общего счетчика допустимо многократно ссылаться на один и тот же тег, в этом случае счета из разных источников будут складываться.
Использование тегов счетчиков является необязательным. Если счетчики не нужны, их можно не описывать.
В случае, если теги ошибок не указаны, будут инкрементироваться стандартные счетчики ошибок, общие для всех портов. Эти стандартные ошибки влияют на статус DAQ-системы (улыбающийся человечек пожелтеет и покраснеет). В случае, когда теги ошибок указаны, они будут инкрементироваться при ошибках на данном порте, но при этом стандартные счетчики задействованы не будут (поэтому статус DAQ-системы при ошибках не изменится). Это позволяет делать индивидуальную обработку ошибок, по выбору прикладного программиста.
Команда @View port служит для отображения (в консоли) таблицы данных для данного порта. Если порт не указан, то в консоли отображается таблица всех портов. Эта команда применяется для контроля задания таблиц при отладке.
Команды @PfeifferPoll, @PfeifferHelp служат для отладочных и справочных целей.
@Reset
@View
@View port
@Port port decl
@Node node port neta
@PortErrorRates port Rx Tx Ex
@PortErrorCounters port Rx Tx Ex
@PortPollRates port Rx Tx
@PortPollCounters port Rx Tx
@PortByteRates port Rx Tx
@PortByteCounters port Rx Tx
@CheckOpt port
@TimeGap port gap
где
port - логический порт, 1..16
decl - описание порта: (tcp port 502 client localhost),(com port 1 baudrate 9600 parity even databits 8 stopbits 1)
Rx - имя тега (integer,real) для накопления счетчиков приема/передачи/ошибок приемника
Tx - имя тега (integer,real) для накопления счетчиков приема/передачи/ошибок передатчика
Ex - имя тега (integer,real) для накопления счетчиков приема/передачи/ошибок - исключений
gap - временной зазор (пауза) между опросами, мс
пауза необходима для разделения сообщений в Pfeiffer RTU,
для других протоколов (IP,ASCII) может отсутствовать (=0)
Например:
[&PfeifferProxy.StartupScript]
;--- Задание таблицы портов (порт,протокол,описание)
;--- Задание счетчиков приема/передачи/ошибок
;--- Логический порт 1
@Port 1 com port 8
@PortByteCounters 1 BYTECOUNT.RX BYTECOUNT.TX
@PortPollCounters 1 POLLCOUNT.RX POLLCOUNT.TX
@PortErrorCounters 1 BUGSCOUNT.RX BUGSCOUNT.TX BUGSCOUNT.EX
@PortByteRates 1 BYTERATE.RX BYTERATE.TX
@PortPollRates 1 POLLRATE.RX POLLRATE.TX
@PortErrorRates 1 BUGSRATE.RX BUGSRATE.TX BUGSRATE.EX
@CheckOpt 1 LPTUF
@TimeGap 1 0
;--- Логический порт 2
@Port 2 rtu com port 4 baudrate 9600 parity even databits 8 stopbits 1
@PortByteCounters 2 BYTECOUNT.RX BYTECOUNT.TX
@PortPollCounters 2 POLLCOUNT.RX POLLCOUNT.TX
@PortErrorCounters 2 BUGSCOUNT.RX BUGSCOUNT.TX BUGSCOUNT.EX
@PortByteRates 2 BYTERATE.RX BYTERATE.TX
@PortPollRates 2 POLLRATE.RX POLLRATE.TX
@PortErrorRates 2 BUGSRATE.RX BUGSRATE.TX BUGSRATE.EX
@CheckOpt 2 *
@TimeGap 2 10
;--- Очистка счетчиков ошибок
@ZeroPortCounters
;--- Просмотр состояния
@View
[]Работа клиента &PfeifferProxy происходит в пассивном режиме ожидания запросов со стороны подчиненных драйверов. Предполагается, что драйверы периодически посылают сообщение @Pfeiffer.Poll ... и ждут ответа. При этом драйверы формируют и интерпретируют только данные протокольного уровня PDU (Protocol Data Unit), не заботясь об их передаче и приеме по протоколам канального уровня. Клиент &PfeifferProxy самостоятельно переводит данные PDU к нужному для приемо-передачи формату ADU (Application Data Unit), добавляя требуемые заголовки и контрольные суммы.
Для отказоустойчивости драйверы должны периодически (скажем, раз в минуту) проверять наличие ответа на посланный запрос и генерировать новый запрос, если ответ все еще не пришел (эта ситуация возможна при перезапуске клиента &PfeifferProxy).
Команда @Pfeiffer.Poll ref cid tot port uid fid $$dat служит для инициирования операции опроса данных для данного порта.
@Pfeiffer.Poll ref cid tot port adr par len $$dat
ref - reference, числовая ссылка или имя драйвера, инициировавшего опрос. Ответное сообщение будут послано ему.
cid - command id, пользовательская команда - любое число, идентифицирующее команду, которая возвращается в ответе
tot - максимальное время ожидания ответа, ms, (1..MaxInt). Время ожидания должно быть положительным числом.
port - номер логического порта, (1..16). Порт должен быть открыт командой @Port.
uid - идентификатор (адрес) устройства, (1..247).
fid - функция Pfeiffer, (1,2,3,4,5,6,15,16).
dat - данные запроса (request) в формате HEX_ENCODE, зависящие от функции fid.
например:
@Pfeiffer.Poll &demo.driver 33 200 1 5 3 $$00090006
@Pfeiffer.Poll &EDUTC.TC110.DRIVER 44 500 8 11 326 6 $$=?
Инициировать опрос модуля с адресом 5, подключенного к порту 1,
ждать не более 200 ms, ответ переслать драйверу &demo.driver.
При опросе вызывается Pfeiffer функция 3 (чтение регистров), читать
6 регистров начиная с адреса 9 (адресация начинается с нуля).
В запросе передается номер команды 33 для использования драйвером.В результате выполнения команды @Pfeiffer.Poll в ответ устройству &sender посылается одно из следующих сообщений:
- @Pfeiffer.Refuse (опрос отклонен),
- @Pfeiffer.Reply (опрос выполнен, получен ответ),
- @Pfeiffer.TimeOut (время ожидания истекло).
@Pfeiffer.Refuse ref cid tim port adr par msg
@Pfeiffer.Reply ref cid tim port adr par ans
@Pfeiffer.TimeOut ref cid tim port adr par req
ref - reference, имя или ссылка устройства, пославшего ответ; значение должно быть ссылкой &PfeifferProxy
cid - command id, идентификатор команды; значение должно совпадать с посланным
tim - измеренное время выполнения цикла запрос-ответ, ms; значение должно быть неотрицательным
port - логический порт, значение должно быть неотрицательным и совпадать с посланным
adr - адрес устройства, значение должно быть (1..247) и совпадать с посланным
par - номер функции; значение должно совпадать с посланным, но возможно, с установленным флагом ошибки (128)
ans - ответ устройства возвращаемый при Reply
req - исходный запрос возвращаемый при TimeOut
msg - строка с описанием причины, по которой запрос был отклонен - например, "Bad Func"= неверный номер функции
например:
@Pfeiffer.Reply 1049090 33 10 1 5 3 $$0C4148890D00004159BFB90000
@Pfeiffer.TimeOut 1049090 33 210 1 5 3 $$00090006
@Pfeiffer.Refuse &PfeifferProxy 33 0 1 5 3 Bad Port 0
здесь 1049090 - ссылка устройства &PfeifferProxyPfeifferProxy Copyright (c) 2022-2024 Alexey Zhirunov rvricov@gmail.com.