Набор компонентов для Delphi
Инструкция по установке компонентов на Delphi Набор компонентов на GitHubОбщие компоненты
- KRBLEdit – поле ввода с прикрепленной меткой
- KRBluetooth.pas – работа с блютуз устройством
- KRBoundLabel.pas – метка, которую можно прикрепить к любому визуальному компоненту
- KRCheckBox.pas – модифицированный TCheckBox
- KRCheckGroupBox – модифицированный TCheckGroupBox
- KRComboBox – модифицированный TComboBox
- KRComponentCollection – коллекция из TComponent
- KRImageList – модифицированный TImageList
- KRIniConfig – набор компонентов для работы с ini-файлом
- KRListView – модифицированный TListView
- KRNormalArray – компоненты для потокового расчета среднеарифметического значения
- KRProgressBar – модифицированный TProgressBar
- KRRadioButton – модифицированный TRadioButton
- KRThreadQueue – синхронизированная очередь
- KRThread – модифицированный TThread
- KRTimer – таймер
- KRValueEdit – поле для ввода числового значения
- KRVersionInfo – получение информации о приложении
Работа с файловой системой
- KRDriveComboBox – выпадающий список дисковых накопителей
- KRFileList – список файлов
- KROpenFolderDlg – диалоговое окно выбора папки
Сеть
- KRBTSocketClient – сокет клиент для передачи данных по bluetooth
- KRBTSocketServer – сокет сервер для передачи данных по bluetooth
- KRParser – класс для создания потоковых парсеров
- KRParserCfg – конфигурационные данные для KRParser
- KRSockets – набор компонентов для работы с сокетами
- KRTCPSocketClient – сокет клиент для передачи данных по протоколу TCP/IP
- KRTCPSocketServer – сокет сервер для передачи данных по протоколу TCP/IP
- KRUDPSocketServer – сокет сервер для передачи данных по протоколу UDP
Автоматизация
- KRBTConnector – клиент для передачи данных по bluetooth в потоке
- KRBtnVarUpdate – кнопка обновления переменной TKRVariable
- KRBTServer – сервер для передачи данных по bluetooth в потоке
- KRCOMPort – класс для работы с COM-портом
- KRCOMPortSets – форма настройки COM-порта
- KRCOMPortConnector – клиент для передачи данных через COM-порт в потоке
- KRConnector – набор классов для потоковых клиентов
- KRConnectorQueueBar – компонент на основе TKRProgressBar, отображающий уровень заполнения очереди коннектора
- KRField – поле для мониторинга и установки значения переменной TKRVariable
- KRIndicator – индикатор
- KRMBMon – мониторинг пакетов протокола Modbus
- KRMBRegIndex – компонент настройки Modbus регистра, устанавливает индекс
- KRMBRegInterval – компонент настройки Modbus регистра, устанавливает интервал обновления
- KRMBRegReadFunc – компонент настройки Modbus регистра, устанавливает функцию чтения
- KRMBRegs – компонент для отладки Modbus регистров
- KRMBRegWriteFunc – компонент настройки Modbus регистра, устанавливает функцию записи
- KRModbus – компонент для работы по протоколу Modbus
- KRModbusMaster – набор стандартных функций Modbus и инструментов для построения и обработки результата
- KRModbusClient – набор инструментов для управления удаленными переменными, связь с которыми осуществляется по средствам протокола Modbus
- KRNMEA0183 – компонент для работы по протоколу NMEA0183
- KRPlcIO – компонент для работы с файлами контроллеров ОВЕН
- KRServer – сервер для передачи данных в потоке
- KRSpeedInfo – компонент для отображения скорости
- KRTCPConnector – клиент для передачи данных по протоколу TCP/IP в потоке
- KRTCPServer – сервер для передачи данных по протоколу TCP/IP в потоке
- KRVariables – переменные, используются при сетевой передачи данных
- KRVarLabel – компонент для мониторинга значения переменной TKRVariable
- KRVButton – кнопка для установки значения переменной TKRVariable
- KRVCheckBox – checkbox для включения/выключения бита в переменной TKRVariable
- KRVCheckGroupBox – GroupBox с прикрепленным компонентом KRVCheckBox
- KRVComboBox – выпадающий список для установки значения переменной TKRVariable по индексу выбранного элемента
Web
- KRGoogleAuth – авторизация в Google, посредством протокола OAuth 2.0
- KRGoogleContacts – работа с контактами через Google Contacts API
- KRGoogleSheets – работа с таблицами через Google Sheets API
Утилиты
- funcs – набор функция
- KRCRC – функции расчета crc-суммы
- KRHTMLParseUtils – набор функция для поиска в HTML коде
- KRStreamCoder – кодировка потока относительно кодового слова
- KRStrUtils – набор функций для работы со строками
- lgop – логические операции
Версия Delphi должна быть не ниже XE.
Скачать:
![]() | Набор компонентов для Delphi от 30.03.2021 г. |
Вот пример более свежий, там отдельно сервер и клиент
TKRServerEvent = procedure(Sender: TObject; APack: PKRBuffer2k; var ALength: integer)
Это событие вызывается из потока подключенного клиента при получение пакета данных
Если после обработки события ALength установить в ноль то ответ не отправляется. А если нужно отправить ответ, то в APack заганяем данные, а в ALength длину данных
И нужно учитывать, что это событие вызывается из под потока ( нельзя использовать визуальные компоненты и при необходимости использовать методы синхронизации потоков)
1) На сайте выложена старая версия компонентов. В текущей версии максимальная сборка 10.4 (я обычно юзаю последний релиз предпоследней версии, то есть к примеру когда выйдет версия 11.1 я перейду на последний апдейт одиннадцатой версии ). Это сборку я ставил на RAD Studio 11
2) "Все в стало но с пропусками класов string в AnsiString" - не совсем понял
3) "Есть ли у вас время и желание пересобрать компоненты под 11 версию?" - я могу вам выслать текущую версию
4) "И какие из ваших компоненты работают под Androide64\32". Я в Delphi под Android не программирую, по этому точно сказать не могу. В большинстве случаев за основу я беру стандартные компоненты Delphi. Соответственно, если родительские классы поддерживаются в Android, то и мои должны.
Подскажите пожалуйста, как можно прикрутить ModBus подобный протокол счетчиков воды "Пульсар"?
Насколько это будет трудозатратный процесс?
Спасибо.
Я правильно понял, вы имеете ввиду другой протокол, не Modbus, но похожий?
Это будет зависеть от того на сколько сложный и насколько документирован(наличие открытой спецификации) сам протокол.
Спасибо вам за вашу работу.
Я надеюсь, что Google Translate правильно переводит.
Я плохо разбираюсь в Delphi.
У меня есть устройства Modbus RTU. 2 различных типа преобразователя RS485 в TCP, подключенного к ПК.
Я использую компоненты Delphi (TKRTCPConnector, TKRModbusMaster, TKRModbusClient, mbtype = mbtRTU).
1. У меня нет проблем с конвертером rs485TOTCP. (Подключено 12 подчиненных устройств)
2. У меня проблема с конвертером rs485TOTCP. (Подключено 3 ведомых устройства). Опрос Modbus v.s. Я могу подключиться к тестовой программе и читать информацию. Я подключаюсь (TKRTCPConnector, TKRModbusMaster, TKRModbusClient, mbtype = mbtRTU), но не могу получить информацию. Когда я смотрю на это с помощью TKRMBMon, ответом является только SlaveID.
Спасибо
Непонятен вопрос.
Покажите, что выводит TKRMBMon
в папку своего проекта и в строке 188 вставить
Sleep( 35 );
Это может помочь. Но это не есть хороший способ решения данной проблемы
С преобразователем RS485 to USB и TKRCOMPortConnector должно работать.
Причина:
Я TKRTCPConnector использовал для связи с Modbus TCP Slave устройствами. Такие устройства ответ посылают одним пакетом. Преобразователь RS485 to TCP делит ответ на части и отсылает его порциями. Деление пакета происходит по каким-то внутренним таймингам преобразователя. В результате TKRTCPConnector получает часть ответа и считает его за полный ответ.
Я не работал через преобразователь RS485 to TCP и поэтому в компоненте TKRTCPConnector не учел такую проблему.
В комментарии под видео ответил на английском языке
KRTimer1.Enabled:=false;
KRModbusClient1.Active:=false;
KRModbusMaster1.Active:=false;
KRCOMPortConnector1.Active:=false;
отрабатывают штатно.
Ранее с такой проблемой не сталкивался. А не может быть проблема в устройстве?
Если отрабатывает KRCOMPortConnector1.Active:=false , то вызывается процедура KRExecuteLast в которой закрывается порт
В старой версии компонентов порт закрывается в деструкторе KRCOMPortConnector
Но в любом случае ни какой код не может быть идеальным. Попробуйте добавить логи в мои библиотеки, может где-то есть ошибка.
В любом случае, данный юнит я буду переделывать. Я сделал под Arduino и Owen более быстрый и качественный обработчик. Сделаю аналогичный и под Delphi,
Все работает, но читается довольно медленно. В программе обновляю регистры через UpdateValueAsync, тормозит именно эта процедура, не отрицаю что для такой задачи она не предназначена, но можно как-то настроить время между запросами?
И наверняка есть более грамотный способ, например через событие которое возникает сразу после считывания массива регистров?
Вот черновой код который вычитывает строки:
Во первых, желательно работать с компонентом KRModbusMaster, так как в вашем случае при каждом запросе затрачивается дополнительное время на синхронизацию с основным потоком.
Во вторых, если есть возможность, то лучше использовать большее количество регистров.
У меня есть еще не документированный функционал:
DWSTR - передача строк произвольной длинны используя два регистра (4 байта)
Функционал описан в файле KRModbusClient.pas
Для работы нужен дополнительный функционал на Slave устройстве
Вот библиотека для контроллеров ОВЕН
Вот библиотека для Arduino
Если вы реализуете функционал этих библиотек в своем приборе, то в Delphi вам будет достаточно использовать регистр типа MCT_DWSTR
Есть еще функционал для передачи файлов, тоже в KRModbusClient.pas. Там используется переменное количество регистров.
Есть вопросы и возможные ошибки:
1.При записи 32-битного float в HoldingRegisters через поле KRField,
не учитывается свойство переменной HighWordFirst когда оно true
А при чтении учитывается, по этому при записи происходит перестановка слов местами.
Мне почему-то привычно когда байты идут по-порядку, без всяких перестановок слов, хотя многие почему-то переставляют )
2.Возможно ли разбить один регистр на две байтовые переменные, чтобы при этом
запись в двух KRField правильно отрабатывала (не перетирала соседний байт в ноль в регистре)
Это было бы актуально для байтовых переменных не расходуя регистры за зря
3. Возможно ли обновлять состояние индикатора по стандартному таймеру?
Пробую через KRIndicator1.Update - не работает.
4. Не хватает примеров просто отправки пакета по кнопке, а так же интересна работа с отправкой / приемом файла.
Отдельная благодарность за Ваш вклад! Надеюсь проект будет поддерживаться.
1. Если тип переменной MCT_BYTE, то при записи старший байт не стирается
2. Для того чтобы значение переменной типа MCT_BYTE бралось из старшего байта нужно в свойство HighByteFirst установить в false
3. Состояние индикатора можно обновлять с помощью методов Update, Refresh и Repaint
Т.е. если постоянно не читать Holding-регистры, то логика такая: при запуске программы или открытии окна настроек, вычитываются все Holding-регистры и все данные становятся актуальными, а запись происходит уже с учетом тех данных которые в данный момент в полях формы.
Если же постоянно читать из прибора Holding-регистры, то синхронизация данных происходит сама собой и всё правильно записывается. И в принципе можно ничего не исправлять, но об этом моменте нужно помнить.
По поводу отправки пакета, я имею ввиду просто запрос по кнопке через функцию и как я понимаю для Input-регистров это делается через функцию MBMReadInputRegisters(ADevAddr: byte; AStartReg, ACount: Word; AFrom: byte; ABuffer: PKRBuffer; out ARecvLen: Byte)
Хотелось бы увидеть пример её работы, как ловить ответ и куда он принимается, в тот же ABuffer?
И ещё вопрос, анализируется ли в ответе третий байт - кол-во байт данных? Я в своей программе его не анализировал, проверял пакет просто по контрольной сумме, это позволяло передавать прибору около тысячи переменных за один запрос, нужно это было для построения графиков..
таким образом получается, что при подключении к устройству все эти переменные обновят свои значения.
С байтовыми переменными немного сложнее. Так, второй байт(не используемый), после обновления сохраняется и при записи добавляется к регистру. Но тут получается сложность если отдельной переменной используется и второй байт. Тут получается если второй байт будет перезаписан, то первая переменная об этом знать не будет и при ее записи значение второго байта перезапишется в то которое было сохранено. Тут палка о двух концах, по этому я байтовые переменные практически не использую.
2) Для самостоятельной отправки пакетов нужен компонент KRModbusMaster
Вот пример
Тут нужно учесть один момент, что CallBack функция вызывается не в основном потоке.
3) Количество байт данных используется при формирование списка полученных регистров
В файле KRModbusMaster.pas функция(для RTU)
function TKRMBThread.chRTUReadInputRegisters
Также проверяется контрольная сумма и бит ошибки в функции
procedure TKRMBThread._CallBack
Если вы хотите принимать или получать большое количество данных, то можно использовать переменную с типом MCT_ARRAY. Вот пример использования
Есть ещё пара вопросов:
1. В чем разница между компонентами для компорта и блютустовыми компонентами, если в винде блютус так же работает через виртуальный компорт?
2. Будет ли портирование под FireMonkey? Чтобы можно было делать приложения под андроид. Я думаю это дало бы преимущество библиотеке.
3. Двойным кликом по компоненту KRTimer на форме по умолчанию открывается обработчик ошибок, неплохо бы в будущем изменить на обработчик самого таймера.
Не теряю надежды в следующем году увидеть примеры работы с файлами :)
С наступающими праздниками!
2. Я не пользуюсь FireMonkey. Под Android я программирую в Eclipse на Java и я уже давно сделал аналоги своих библиотек для Modbus на Java под Android, но я их еще ни где не выкладывал.
3. ок, если это возможно, то сделаю.
Я много чего хочу выложить на сайт, в том числе и статью про работу с файлами, но у меня не хватает на это времени. По этому статьи добавляю по мере возможности.
И Вас с наступающим Новым Годом!
1. Вроде работает правильно. Преобразование последовательности байтов и у SINGLE и у DWORD производится одной и той же функцией. По этому если неправильно формируется SINGLE то и DWORD должен формироваться неправильно. Пожалуйста, перепроверьте и отпишитесь.
2. Я могу это сделать завтра, но смогу скинуть только измененные файл здесь в комментариях. Полностью обновить пакет компонентов пока нет возможности.
3. Update - эта процедура наследуется от TShape или, если быть точнее, от TControl. Я ее не перегружаю. То есть она просто перерисовывает фигуру с теми же свойствами. Но, хотя, хорошее замечание. Сделаю завтра и тоже скину файлом.
4. Что вы имеете ввиду под фразой "отправки пакета"? Работа с файлами реализована недавно. Это не стандартные возможности modbus, а моя разработка. Для передачи файлов на удаленном устройстве тоже должен быть дополнительный функционал, я его реализовал только для контроллеров Owen и Arduino. По этому вопросу будет отдельная статья.
Проект поддерживаю по мере возможности, пока забрасывать не собираюсь.
Заметил такую проблему в закрытии приложения. При только чтении программа закрывается корректно. Если произвести запись значений TKRMBRegister.Value, а потом закрыть используя
KRTimer1.Enabled:=false;
KRModbusClient1.Active:=false;
KRModbusMaster1.Active:=false;
KRCOMPortConnector1.Active:=false;
программа не завершает работу (только через диспетчер задач). Обмен данными прекращается. Соединение COM, какие есть мысли?
Для начала, вам нужно определить какой именно из компонентов подвисает. Это можно сделать сохраняя логи в файл. Я для этих целей использую модуль KRRuntimeErrors
2019-11-07 08:15:28.942 KRTimer1.Enabled:=false;
2019-11-07 08:15:29.942 KRModbusClient1.Enabled:=false;
2019-11-07 08:15:29.957 KRModbusMaster1.Enabled:=false;
2019-11-07 08:15:29.979 KRCOMPortConnector1.Enabled:=false;
Просто мне MODBUS не нужен, у меня свой протокол.
Я так понял, нужно с KRCOMPortConnector.Send разобраться?
Задача класса KRConnector отправить запрос, получить ответ и вернуть его при помощи callback функции.
Классы KRCOMPortConnector, KRTCPConnector и KRBTConnector определяют способ передачи данных.
Пример работы с KRConnector есть в файле KRModbusMaster.pas
В двух словах:
procedure Send(APack: PKRBuffer; ALength: integer; ACallBack: TKRConnectorCallBack;
AData: Pointer = nil; AWaitResult: boolean = true; ARecvLen: integer = 0;
ADelimiter: Cardinal = 0; ADelimiterLen: integer = 0);
отправляет запрос в очередь на обработку коннектором.
APack: PKRBuffer - указатель на буфер с отправляемыми данными
ALength: integer - длинна пакета данных
ACallBack: TKRConnectorCallBack - callback функция, которая будет вызвана после обработки запроса
AData: Pointer = nil - указатель на дополнительные данные. Указатель будет передан в callback функции.
AWaitResult: boolean = true - ждать ответ на запрос
ARecvLen: integer = 0 - если мы знаем длину ответа, то указываем тут
ADelimiter: Cardinal = 0 - если есть разделитель между пакетами ответа, то указываем тут. Например в текстовой версии modbus есть разделитель <CR><LF>
ADelimiterLen: integer = 0 - количество байт в разделителе (1-4)
функция, которая будет вызвана после обработки запроса
procedure Callback(AError: integer; APack: PKRBuffer; ALength: integer; AData: Pointer) ;
AError: integer - код ошибки (0 - нет ошибок)
APack: PKRBuffer - указатель на буфер с ответом. Это тот-же буфер который использовался при отправке пакета. Если вы его создавали при помощи функции GetMem или New, то в callback функции нужно освободить память буфера. Так сделано в KRModbusMaster.pas
ALength: integer - количество байт данных в ответе
AData: Pointer - указатель на дополнительные данные
Возможные ошибки:
'Нет ошибок.',
ceOK = TKRConnectorError(0);
'Очередь коннектора переполнена.',
ceQueueOverflowed = TKRConnectorError(1);
'Соединение не установлено.',
ceNotConnection = TKRConnectorError(2);
'Не удалось отправить данные.',
ceDataNotSended = TKRConnectorError(3);
'Ответ не получен.',
ceNoResponse = TKRConnectorError(4);
'Истекло время ожидания при отправке данных.',
ceRequestTimeout = TKRConnectorError(5);
'Истекло время ожидания при получении данных.',
ceResponseTimeout = TKRConnectorError(6);
'Соединение не активно.'
ceNotActive = TKRConnectorError(7);
Добавил его на форму, при создании формы делаю KRCOMPortSets.Init
Затем по нажатию кнопки делаю KRCOMPortSets.Execute
Но ничего не происходит. Это я понял из примера с сайта. Или я что-то упустил?
Как я понял, должно открыться окно с настройками порта?
Можно попробовать поставить на Delphi 7, но как минимум точно будет проблема со строками, так как код заточен под двухбайтовые строки, а в седьмой версии используются одно байтовые. По этому, я думаю, проще Вам перейти на Delphi XE.