Принцип работы коннекторов в Delphi компонентах

В моих компонентах для Delphi коннектор – это объект, осуществляющий связь с внешними объектами(объектом). Внешним объектом может выступать другая программа или другое устройство, которое поддерживает тот же интерфейс или протокол связи. В процессе связи коннектор выступает клиентом. То есть задача коннектора отправить запрос и при необходимости дождаться ответа и отправить его по обратной связи (CallBack).

TKRConnector – это базовый класс всех коннекторов. Ниже представлена схема работы коннектора

Схема работы KRConnector

Для отправки запроса используется метод Send

Задача данного метода отправить информацию о запросе в очередь на обработку. В методе Send передаются следующие параметры:

  • APack – указатель на буфер в котором находятся данные предназначенные для отправки. Если нужно получить ответ, то он сохранится в этот же буфер.
  • ALength – длинна отправляемых данных в байтах.
  • ACallBack – метод обратной связи типа TKRConnectorCallBack. Данный метод будет вызван после обработки запроса. Если нет необходимости в обратной связи, то можно передать nil.
  • AData – указатель на дополнительные данные, который будет передан в метод обратной связи (CallBack). Если есть необходимость передать дополнительную информацию о пакете, которые понадобятся в методе обратной связи, то указатель на эти данные передается в этом параметре. Если нет необходимости что-либо передавать, то устанавливаем nil.
  • AWaitResult – указывает на то, нужно ли ждать ответ на запрос. Если должен прийти ответ, но он не будет получен, то это будет считаться ошибкой ceNoResponse.
  • ARecvLen – если заранее известна длина ответа, то ее нужно указать в этом параметре. Заранее зная длину ответа коннектор будет быстрее обрабатывать входящие данные.
  • ADelimiter – разделитель или последовательность байт разделяющая входящие пакеты. Например в протоколе Modbus ASCII разделителем является последовательность #13#10 и для передачи этой последовательности нужно установить значение $0D0A в данный параметр. Если разделитель не используется, то устанавливаем ноль.
  • ADelimiterLen – длина разделителя в байтах. Если разделитель не используется, то устанавливаем ноль.

После вызова Send, информация о запросе попадает во входящую очередь коннектора, которая из себя представляет сблокированный упорядоченный список типа TKRThreadQueue. Максимальное количество запросов в очереди установлено в константе CE_QUEUE_MAX_ITEMS, а текущее количество можно узнать из свойства коннектора QueueCount. Если в момент вызова метода Send в очереди будет максимально возможное количество запросов, то будет вызван метод обратной связи с ошибкой ceQueueOverflowed.

Из входящей очереди запрос попадает в поток обработки данных типа TKRThread. Свойства коннектора WaitTime и WaitPauseTime являются настройками данного потока. Функционал потока описывается для каждого коннектора отдельно, но основные задачи во всех случаях одинаковы:

  1. Установить соединение. Если связь не установлена, то коннектор пытается подключиться с таймаутом указанным в свойстве ConnectTimeout. Если связи нет, то коннектор будет постоянно пытаться подключиться с периодом между попытками указанным в свойстве ReconnectTime. Все запросы до установки связи будут возвращать ошибку ceNotConnection.
  2. Отправить запрос. Отправка последовательности бай с таймаутом указанным в свойстве WriteTimeout. Если за указанный период данные отправить не удается, то возвращается ошибка ceDataNotSended.
  3. При необходимости дождаться ответа. Если при вызове метода Send в параметре AWaitResult передано True, то будет ожидаться ответ в течении времени указанного в свойстве WaitRespTime. Общий таймаут ожидания ответа устанавливается в свойстве ReadTimeout, но промежутки по времени между частями входящего пакета не должны превышать значение свойства WaitRespTime. То есть , фактически, если в течении времени WaitRespTime ничего не будет получено, то коннектор будет считать, что ответа нет. Если в методе Send передано значение ARecvLen больше нуля, то коннектор считает, что ответ получен, если длина полученных данных больше или ровна ARecvLen и прекращает ожидание дополнительных данных. Если ответ получить не удалось, то возвращается ошибка ceNoResponse.
  4. Результат отправить в исходящую очередь.

Исходящая очередь из себя представляет сблокированный упорядоченный список типа TKRThreadQueue. Максимальное количество запросов в очереди установлено в константе CE_QUEUE_MAX_ITEMS, а текущее количество можно узнать из свойства коннектора QueueOutCount.

Второй поток коннектора предназначен для отправки результата, то есть для вызова метода обратной связи. Свойства коннектора WaitOutTime и WaitPauseOutTime являются настройками данного потока.

Метод обратной связи представляет из себя процедуру какого либо объекта со следующими параметрами:

  • AError – ошибка типа TKRConnectorError, возникшая при обработке запроса. Если в параметре придёт ноль ceOK, то значит, что в процессе обработки запроса ошибок не возникло. Текстовые представления ошибок находятся в константе CONNECTOR_ERRORS_MSG. Также текстовое представление ошибки можно получить при помощи метода коннектора ErrorMsg.
  • APack – указатель на тот же буфер который был передан в методе Send. В этот буфер записывается ответ, поверх запроса.
  • ALength – длина ответа.
  • AData – указатель на дополнительные данные который был передан в методе коннектора Send.

В методе обратной связи нужно учитывать то, что он напрямую вызывается из исходящего потока коннектора, то есть асинхронно основному потоку.

На данный момент есть три коннектора основанные на TKRConnector:

  • KRBTConnector – беспроводная связь Bluetooth
  • KRCOMPortConnector – связь через последовательный порт
  • KRTCPConnector – сетевая связь по стеку протоколов TCP/IP

Пример использования

В приведенном ниже примере через коннектор последовательного порта опрашиваются три переменные удаленного устройства по протоколу Modbus RTU. Первая переменная будет типа Word в регистре 0, вторая типа SmallInt в регистре 1 и третья типа DWORD в регистрах 2 и 3. При корректном ответе устройства значения записываются в поля TEdit, а при ошибке в эти же поля записывается текстовое представление этих ошибок. Для синхронизации метода обратной связи с основным потоком используем оконные сообщения Windows.

Пример использование коннектора на основе класса TKRConnector
 
Поделиться:
0
Владимиров Константин
01.12.2020 19:26
 
Здравствуйте! Спасибо за ваш труд. Возможно глупый вопрос, но: как заполняются параметры в TForm1.callBack, откуда они попадают в метод?
Показать полностью
5
Руслан Кандирал
01.12.2020 21:03
Владимиров Константин
 
Здравствуйте, Константин!

CallBack - это обратная связь с коннекторам. Мы не можем получить ответ от коннектора сразу, так как нужно дождаться ответа от удаленного устройства. По этому, для получения ответа от коннектора мы ему передаем указатель на нашу функцию CallBack:
После того как коннектор получит ответ от удаленного устройства или при ошибке он вызывает функцию CallBack. То есть коннектор вызывает функцию CallBack и вкладывает в нее параметры:
AError - это код ошибки или ноль, если ошибки нет
APack - указатель на буфер который был передан коннектору. Ответ коннектор вкладывает в тот же буфер в котором вы ему передали запрос. Если буфер был зарезервирован в памяти с помощью процедур New или GetMem, то в CallBack нужно очистить память процедурой Dispose или FreeMem
ALength - длина ответного пакета, который находится в буфере
AData - указатель на дополнительные данные, если нужно. Мы его передаем коннектору просто для того, чтобы он его вернул в CallBack

Нужно всегда учитывать тот факт, что CallBack коннектор вызывает из потока. По-этому нужно позаботится о синхронизации с основным потоком.
Показать полностью

Новости сайта

05.05.2020 15:34
Новая статья про удаленное управление принтером Domino V-series
Реализация протокола передачи данных для связи с термотрансферным принтером Domino V-series из Delphi
24.04.2020 22:14
Добавлена статья по работе с сенсором Omron FQ-CR1 из Delphi
Подключение по сети к считывателю штрих-кодов Omron FQ-CR1 из программы на Delphi
17.03.2020 20:46
Обновлен пакет компонентов для Delphi
Доступна для скачивания новая версия компонентов для Delphi, от 17.03.2020г. С данной версии библиотеки доступны и на GitHub
28.01.2020 16:15
Опубликована статья о принципе работы коннекторов в Delphi
Коннектор – это объект, осуществляющий связь с внешними объектами(объектом). Внешним объектом может выступать другая программа или другое устройство, которое поддерживает тот же интерфейс или протокол связи.

Популярные статьи

Экспорт таблиц Google Sheets в PDF файл, на email и на Google диск
Экспорт таблиц Google Sheets в PDF файл с помощью Google Script с последующим скачиванием или сохранением на Google Drive или отправкой на почту
Инструкция по установке компонентов на Delphi
Подробная инструкция по установке компонентов на Delphi с видео обзором
Modbus Slave на Arduino
Реализация клиентской части протокола Modbus RTU и Modbus ASCII для контроллеров Arduino
Пример передачи данных по протоколу Modbus на Delphi
Пример передачи данных с контроллера ОВЕН ПЛК100 в программу на Delphi по протоколу Modbus