Стартовая страница › Форумы › Разработка и интеграция › Драйвер в режиме TcpServer
- В этой теме 14 ответов, 3 участника, последнее обновление 1 месяц назад сделано
JurasskPark.
-
АвторСообщения
-
19.05.2025 в 15:30 #38406
JurasskPark
УчастникМихаил, подскажите, если канал в режиме TcpServer
Behavior = Slave
ClientLifetime = 3600
ConnectionMode = Shared
DeviceMapping = ByIPAddress
TcpPort = 5008
То как в драйвере через TcpServer получать данные?
Я попробовал так/// <summary> /// Performs a communication session. /// </summary> public override void Session() { base.Session(); Stopwatch stopwatch = Stopwatch.StartNew(); string hex = string.Empty; string logText = string.Empty; if (project.SystemSettings.AsClient) { } else if (project.SystemSettings.AsServer) { int countConnection = Connection.Read(bufferReceiver, offset, count, timeout, format, out logText); hex = Hex.StringX16.ToStringFormatDot(bufferReceiver); } stopwatch.Stop(); Log.WriteLine(Locale.IsRussian ? "Получено за {0} мс" : "Received in {0} ms", stopwatch.ElapsedMilliseconds); LogDriver(hex); LogDriver(logText); FinishRequest(); FinishSession(); }
19.05.2025 в 16:53 #38407JurasskPark
УчастникКоммуникатор пишет «Ошибка при создании линии связи [1801] METRO-Server: Поведение Slave канала связи не поддерживается устройством [18000] Server.»
А как это поведение поддержать в режиме Slave?)
Какие условие нужно выполнить?19.05.2025 в 17:00 #38408JurasskPark
Участник/// <summary> /// Checks that all devices on the communication line support the channel behavior. /// </summary> protected void CheckBehaviorSupport() { HashSet<string> deviceTypeNames = new HashSet<string>(); foreach (DeviceLogic deviceLogic in LineContext.SelectDevices()) { deviceTypeNames.Add(deviceLogic.GetType().FullName); if (!deviceLogic.CheckBehaviorSupport(Behavior)) { throw new ScadaException(Locale.IsRussian ? "Поведение {0} канала связи не поддерживается устройством {1}." : "{0} behavior of the communication channel is not supported by the device {1}", Behavior, deviceLogic.Title); } } if (Behavior == ChannelBehavior.Slave && deviceTypeNames.Count > 1) { Log.WriteWarning(Locale.IsRussian ? "Не рекомендуется использовать устройства разных типов на одной линии связи" : "It is not recommended to use devices of different types on the same communication line"); } }
То есть драйвер не прошел проверку deviceLogic.CheckBehaviorSupport(Behavior)…
Значит нужно указать… Но как и где… )19.05.2025 в 17:05 #38409Mikhail
МодераторВ режиме Slave нужно вместо метода Session использовать методы ReceiveIncomingRequest и ProcessIncomingRequest.
Примеры из DrvModbusSlave
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; } } public override bool CheckBehaviorSupport(ChannelBehavior behavior) { return behavior == ChannelBehavior.Slave; }
19.05.2025 в 17:07 #38410Mikhail
МодераторВ Session() можно, например, устанавливать недостоверность данных, если они давно не приходили.
19.05.2025 в 17:22 #38411JurasskPark
УчастникСпасибо! Буду пробовать!
19.05.2025 в 17:30 #38412JurasskPark
УчастникЗаработало!
Вот этого мне счастья не хватало! 🙂
public override bool CheckBehaviorSupport(ChannelBehavior behavior) { return behavior == ChannelBehavior.Slave; }
20.05.2025 в 12:05 #38413JurasskPark
УчастникВопрос номер 2.
public override void ReceiveIncomingRequest(Connection conn, IncomingRequestArgs requestArgs) — вызывается и всё что там есть — я вижу.public override void ProcessIncomingRequest(byte[] buffer, int offset, int count, IncomingRequestArgs requestArgs) — не вызывается. Что я делаю не так?
При этом я в логе вижу, постоянные попытки подключиться.
20.05.2025 в 13:08 #38417Mikhail
МодераторВариант ReceiveIncomingRequest вызывается в зависимости от типа канала связи. Попробуйте канал UDP — скорее всего вызовется другой вариант метода.
Один из них вызывается, когда уже пришли и считаны все данные, а другой когда данные пришли, но ещё не считаны.20.05.2025 в 13:39 #38419JurasskPark
УчастникПри UDP пишет ошибку
2025-05-20 13:38:32 Сеанс связи с устройством [18000] Server
2025-05-20 13:38:32 Ошибка при вызове метода Session устройства [18000] Server:
Scada.ScadaException: Ошибка при считывании данных: An invalid IP address was specified.
—> System.FormatException: An invalid IP address was specified.
—> System.Net.Sockets.SocketException (10022): Получен недопустимый аргумент.
— End of inner exception stack trace —
at System.Net.IPAddressParser.Parse(ReadOnlySpan`1 ipSpan, Boolean tryParse)
at System.Net.IPAddress.Parse(String ipString)
at Scada.Comm.Drivers.DrvCnlBasic.Logic.UdpConnection.CreateRemoteEndPoint()
at Scada.Comm.Drivers.DrvCnlBasic.Logic.UdpConnection.Read(Byte[] buffer, Int32 offset, Int32 count, Int32 timeout, ProtocolFormat format, String& logText)
— End of inner exception stack trace —
at Scada.Comm.Drivers.DrvCnlBasic.Logic.UdpConnection.Read(Byte[] buffer, Int32 offset, Int32 count, Int32 timeout, ProtocolFormat format, String& logText)
at Scada.Comm.Drivers.DrvHSMSLogic.Logic.DevHSMSLogic.Session()
at Scada.Comm.Engine.DeviceWrapper.Session()20.05.2025 в 13:43 #38420JurasskPark
УчастникСмерил тип TCP-сервер на общий
2025-05-20 13:42:50 Приём входящего запроса от 10.50.*.*
2025-05-20 13:42:50 Ошибка при вызове метода Session устройства [18000] Server:
Scada.ScadaException: Ошибка при считывании данных: Timeout can be only be set to ‘System.Threading.Timeout.Infinite’ or a value > 0. (Parameter ‘value’)
—> System.ArgumentOutOfRangeException: Timeout can be only be set to ‘System.Threading.Timeout.Infinite’ or a value > 0. (Parameter ‘value’)
at System.Net.Sockets.NetworkStream.set_ReadTimeout(Int32 value)
at Scada.Comm.Drivers.DrvCnlBasic.Logic.TcpConnection.Read(Byte[] buffer, Int32 offset, Int32 count, Int32 timeout, ProtocolFormat format, String& logText)
— End of inner exception stack trace —
at Scada.Comm.Drivers.DrvCnlBasic.Logic.TcpConnection.Read(Byte[] buffer, Int32 offset, Int32 count, Int32 timeout, ProtocolFormat format, String& logText)
at Scada.Comm.Drivers.DrvHSMSLogic.Logic.DevHSMSLogic.Session()
at Scada.Comm.Engine.DeviceWrapper.Session()20.05.2025 в 13:46 #38421manjey73
УчастникTimeout в настройках 0? это поле не считываешь и не указываешь явно ?
20.05.2025 в 15:32 #38423JurasskPark
Участник>>а другой когда данные пришли, но ещё не считаны.
Короче, хотите обижайтесь, хотите баньте, но я через дебаггер посмотрел исходных код ModbusSlave, и посмотрел там как происходит./// <summary> /// Receives an unread incoming request in slave mode. /// </summary> public override void ReceiveIncomingRequest(Connection conn, IncomingRequestArgs requestArgs) { Log.WriteLine(); if (string.IsNullOrEmpty(conn.RemoteAddress)) { Log.WriteAction(Locale.IsRussian ? "Приём входящего запроса" : "Receive incoming request"); } else { Log.WriteAction(Locale.IsRussian ? "Приём входящего запроса от {0}" : "Receive incoming request from {0}", conn.RemoteAddress); } string logText = string.Empty; bool a = ReadDataConnection(conn, out logText); } public bool ReadDataConnection(Connection connection, out string logText) { //bool result = false; string text = string.Empty; int num = connection.Read(this.buffer, 0, 1000, ((DeviceLogic)this).PollingOptions.Timeout, ProtocolFormat.Hex, out logText); Log.WriteAction(@$"Num = {num}"); Log.WriteAction(@$"Buffer = " + Hex.StringX16.ToStringFormatDot(buffer)); Log.WriteAction(@$"Offset = {0}"); Log.WriteAction(@$"Count = {1000}"); Log.WriteAction(@$"Timeout = {((DeviceLogic)this).PollingOptions.Timeout}"); Log.WriteAction(@$"Protocol = {ProtocolFormat.Hex}"); Log.WriteAction(@$"Log Text = {logText}"); return true; }
Вот так работает.
20.05.2025 в 15:33 #38424JurasskPark
УчастникТо есть действительно, нужно было после появление коннекта делать обращение на чтение данных.
Непривычно просто. 🙂20.05.2025 в 15:41 #38425JurasskPark
УчастникА. И еще в драйвере нужно было выставить ((DeviceLogic)this).ConnectionectionRequired = false;
-
АвторСообщения
- Вы должны авторизироваться для ответа в этой теме.