Стартовая страница › Форумы › Разработка и интеграция › Драйвер в режиме TcpServer
- В этой теме 73 ответа, 4 участника, последнее обновление 1 месяц, 1 неделя назад сделано
Mikhail.
-
АвторСообщения
-
17.10.2025 в 11:13 #40794
JurasskParkУчастникЕще бы понять логику вашего действия:
public override void ReceiveIncomingRequest(Connection conn, IncomingRequestArgs requestArgs) { if (f) { requestArgs.NextDevice = true; return; } ((DeviceLogic)this).ReceiveIncomingRequest(conn, requestArgs); if (i(conn, out var A_)) { a(conn, A_, requestArgs); } else { requestArgs.HasError = true; } }Можно оригинал и описание?
17.10.2025 в 14:06 #40799
MikhailМодераторЭто откуда взято?
17.10.2025 в 15:39 #40808
JurasskParkУчастникSlave Modbus driver…
20.10.2025 в 17:37 #40824
MikhailМодераторpublic override void ReceiveIncomingRequest(Connection conn, IncomingRequestArgs requestArgs) { if (fatalError) { requestArgs.NextDevice = true; } else { base.ReceiveIncomingRequest(conn, requestArgs); if (receiveRequest(conn, out ModbusRequest request)) ProcessRequest(conn, request, requestArgs); else requestArgs.HasError = true; } } public override void ProcessIncomingRequest(byte[] buffer, int offset, int count, IncomingRequestArgs requestArgs) { if (fatalError) { requestArgs.NextDevice = true; } else { base.ProcessIncomingRequest(buffer, offset, count, requestArgs); if (parseRequest(buffer, offset, count, out ModbusRequest request)) ProcessRequest(Connection, request, requestArgs); else requestArgs.HasError = true; } }20.10.2025 в 17:39 #40825
MikhailМодераторModbusSlave сложнее, чем обычный драйвер, потому что формат данных разный для RTU и TCP.
20.10.2025 в 17:40 #40826
MikhailМодераторПри использовании TCP будет вызываться только ReceiveIncomingRequest, насколько я помню.
ProcessIncomingRequest вызывается для канала UDP.20.10.2025 в 20:31 #40836
JurasskParkУчастникModbusSlave сложнее, чем обычный драйвер, потому что формат данных разный для RTU и TCP
У меня тоже два протокола заложено: SECS и HSMS.
04.12.2025 в 13:20 #41268
JurasskParkУчастникМожете меня наконец-то поздравить. Я разобрался, как работает
BinStopCondition stopCond.Оставляю здесь для себя.
BinStopCondition stopCond = new ClientStopCondition(device.TypeProtocol); int count = connection.Read(this.buffer, 0, this.buffer.Length, ((DeviceLogic)this).PollingOptions.Timeout, stopCond, out bool stopReceived, ProtocolFormat.Hex, out logText);using DebugerLog; using Scada.Comm.Channels; public class ClientStopCondition : BinStopCondition { private int _bytesRead = 0; private int _expectedLength = -1; private readonly NetCoreSECS.Protocol _protocol; private bool _isLengthDetermined = false; public ClientStopCondition(NetCoreSECS.Protocol protocol) : base(0) { _protocol = protocol; StopSeq = null; Debuger.Log($"Создан ClientStopCondition для протокола: {_protocol}"); } public override bool CheckCondition(byte[] buffer, int index) { _bytesRead++; // Для HSMS: определяем длину после 4 байт if (_protocol == NetCoreSECS.Protocol.HSMS && !_isLengthDetermined && _bytesRead >= 4) { // Читаем длину ДАННЫХ из первых 4 байт int dataLength = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; // Общая длина = 4 байта длины + длина данных _expectedLength = 4 + dataLength; _isLengthDetermined = true; Debuger.Log($"✓ HSMS: Длина данных = {dataLength}, Общая длина = {_expectedLength} байт"); } // Для SECS: определяем длину после 1 байта else if (_protocol == NetCoreSECS.Protocol.SECS && !_isLengthDetermined && _bytesRead >= 1) { // SECS: первый байт = длина данных int dataLength = buffer[0]; _expectedLength = 1 + dataLength + 2; // Длина + данные + CRC _isLengthDetermined = true; Debuger.Log($"✓ SECS: Длина данных = {dataLength}, Общая длина = {_expectedLength} байт"); } // Проверяем условие остановки bool shouldStop = _isLengthDetermined && _bytesRead >= _expectedLength; if (shouldStop) { Debuger.Log($"✅ Прочитан полный пакет: {_bytesRead} байт"); } return shouldStop; } public void Reset() { _bytesRead = 0; _expectedLength = -1; _isLengthDetermined = false; } }04.12.2025 в 13:36 #41269
manjey73Участникдык спросил бы, я давно пользуюсь 🙂
со времен когда Михаила попросил добавить остановку по массив(АМ) байт, а не по одному байту или одному массиву.27.02.2026 в 00:14 #42150
JurasskParkУчастникif (deviceLogic.NumAddress != request.UnitID) LineContext.GetDeviceByAddress(request.UnitID, out deviceLogic)Для информации.
Я попался на LineContext.GetDeviceByAddress.LineContext.GetDeviceByAddress — если int передать, то это поиск по адресу устройства.
LineContext.GetDeviceByAddress — если передать string, то это поиск по ip.А у меня стояло — LineContext.GetDevice — это поиск по номеру устройства.
P.S. Нашёл, когда отлаживал DrvDebug…
Точнее везде в начале темы я пишу LineContext.GetDeviceByAddress, но потом была вспышка на солнце и в коде уже было LineContext.GetDevice. 😀28.02.2026 в 11:48 #42168
MikhailМодераторСпасибо.
03.03.2026 в 10:22 #42205
JurasskParkУчастникМихаил, для закрепления темы и повторения.
1. Приходит команда, по которой мы определяем адрес устройства.
Библиотека понимает, что адрес устройства в полученной команде и адрес в конфигурации проекта совпадают, то мы всё равно делаем поиск через
LineContext.GetDeviceByAddress(address, out deviceLogic)?if(deviceLogic.NumAddress == address) { LineContext.GetDeviceByAddress(address, out deviceLogic); }2. Приходит команда, по которой мы определяем адрес устройства.
Библиотека понимает, что адрес устройства в полученной команде и адрес в конфигурации проекта НЕ совпадают, то мы делаем поиск через
LineContext.GetDeviceByAddress(address, out deviceLogic)?if(deviceLogic.NumAddress != address) { LineContext.GetDeviceByAddress(address, out deviceLogic); }3. Приходит команда, по которой мы НЕ можем определить адрес устройства, т.к. это команда установки связи.
Библиотека понимает, что адрес устройства в полученной команде и адрес в конфигурации проекта НЕ совпадают, но для установления связи нужно всё равно ответить.
LineContext.GetDeviceByAddress(address, out deviceLogic) — вызывать бессмылено, устройство мы не найдем.
Значит не вызываем?4. В каких случаях нужно вызывать requestArgs.TargetDevices.Add(deviceLogic)?
Каждый раз про получении данных от устройства?
Объясню сложность вопроса для себя.
Если пришли данные от устройства и мы не вызвали requestArgs.TargetDevices.Add(deviceLogic), то мы не узнали, что устройство подключилось новое.
Если мы каждый раз при получении команды, будет вызывать, то не будет ли количество TargetDevices стремится к бесконечности? Или они очищаются после каждого опроса через период времени?5. Нужно ли ReceiveIncomingRequest(Connection connection, IncomingRequestArgs requestArgs) завершать командами, при удачном выполнении
LastRequestOK = true;
FinishRequest();
SleepPollingDelay();
FinishSession();или ничего не должно быть?
03.03.2026 в 15:06 #42234
MikhailМодератор1-3. вроде бы так.
4. Вызывать каждый раз, если мы нашли устройство, к которому относится запрос. Бесконечно ссылки не накопятся, потому что requestArgs существует короткое время для одного запроса.
5. Я использую FinishRequest. Откройте код метода, посмотрите, что он делает. Он весьма короткий. FinishSession не нужен, потому что это не сеанс опроса в терминах Коммуникатора.
03.03.2026 в 15:07 #42235
MikhailМодераторВозможно, это уже было:
public override void ReceiveIncomingRequest(Connection conn, IncomingRequestArgs requestArgs) { base.ReceiveIncomingRequest(conn, requestArgs); int readCnt = conn.Read(inBuf, 0, InBufLenght, PollingOptions.Timeout, StopCond, out bool stopReceived); if (!stopReceived) Log.WriteLine("Ошибка: пакет данных не обнаружен"); bool procDataOK = stopReceived && ProcData(inBuf, 0, readCnt, conn, requestArgs); FinishRequest(requestArgs.GetFirstDevice(), procDataOK); } public override void ProcessIncomingRequest(byte[] buffer, int offset, int count, IncomingRequestArgs requestArgs) { base.ProcessIncomingRequest(buffer, offset, count, requestArgs); bool procDataOK = ProcData(buffer, offset, count, Connection, requestArgs); FinishRequest(requestArgs.GetFirstDevice(), procDataOK); }03.03.2026 в 15:09 #42237
MikhailМодераторИз другого драйвера:
public override void ReceiveIncomingRequest(Connection conn, IncomingRequestArgs requestArgs) { if (fatalError) { requestArgs.NextDevice = true; } else { base.ReceiveIncomingRequest(conn, requestArgs); if (receiveRequest(conn, out ModbusRequest request)) ProcessRequest(conn, request, requestArgs); else requestArgs.HasError = true; } } public override void ProcessIncomingRequest(byte[] buffer, int offset, int count, IncomingRequestArgs requestArgs) { if (fatalError) { requestArgs.NextDevice = true; } else { base.ProcessIncomingRequest(buffer, offset, count, requestArgs); if (parseRequest(buffer, offset, count, out ModbusRequest request)) ProcessRequest(Connection, request, requestArgs); else requestArgs.HasError = true; } } -
АвторСообщения
- Для ответа в этой теме необходимо авторизоваться.