【问题标题】:OPC UA client KeepAliveOPC UA 客户端 KeepAlive
【发布时间】:2020-07-24 04:55:00
【问题描述】:

尊敬的 OPC UA 社区!

我想使用OPC Foundation 和MS Azure 中的示例为我们的软件开发一个OPC UA 客户端。我担心这些例子之间的差异。在第一个示例中,使用 ReconnectHandler 执行 KeepAlive 失败后的重新连接:

        private void Client_KeepAlive(Session sender, KeepAliveEventArgs e)
        {
            if (e.Status != null && ServiceResult.IsNotGood(e.Status))
            {
                Console.WriteLine("{0} {1}/{2}", e.Status, sender.OutstandingRequestCount, sender.DefunctRequestCount);

                if (reconnectHandler == null)
                {
                    Console.WriteLine("--- RECONNECTING ---");
                    reconnectHandler = new SessionReconnectHandler();
                    reconnectHandler.BeginReconnect(sender, ReconnectPeriod * 1000, Client_ReconnectComplete);
                }
            }
        }

        private void Client_ReconnectComplete(object sender, EventArgs e)
        {
            // ignore callbacks from discarded objects.
            if (!Object.ReferenceEquals(sender, reconnectHandler))
            {
                return;
            }

            session = reconnectHandler.Session;
            reconnectHandler.Dispose();
            reconnectHandler = null;

            Console.WriteLine("--- RECONNECTED ---");
        }

第二次,会话断开并重新创建:

        private void StandardClient_KeepAlive(Session session, KeepAliveEventArgs e)
        {
            // ignore if we are shutting down
            if (ShutdownTokenSource.IsCancellationRequested == true)
            {
                return;
            }

            if (e != null && session != null && session.ConfiguredEndpoint != null && OpcUaClientSession != null)
            {
                try
                {
                    if (!ServiceResult.IsGood(e.Status))
                    {
                        Logger.Warning($"Session endpoint: {session.ConfiguredEndpoint.EndpointUrl} has Status: {e.Status}");
                        Logger.Information($"Outstanding requests: {session.OutstandingRequestCount}, Defunct requests: {session.DefunctRequestCount}");
                        Logger.Information($"Good publish requests: {session.GoodPublishRequestCount}, KeepAlive interval: {session.KeepAliveInterval}");
                        Logger.Information($"SessionId: {session.SessionId}");

                        if (State == SessionState.Connected)
                        {
                            MissedKeepAlives++;
                            Logger.Information($"Missed KeepAlives: {MissedKeepAlives}");
                            if (MissedKeepAlives >= OpcKeepAliveDisconnectThreshold)
                            {
                                Logger.Warning($"Hit configured missed keep alive threshold of {OpcKeepAliveDisconnectThreshold}. Disconnecting the session to endpoint {session.ConfiguredEndpoint.EndpointUrl}.");
                                session.KeepAlive -= StandardClient_KeepAlive;
                                Task t = Task.Run(async () => await DisconnectAsync());
                            }
                        }
                    }
                    else
                    {
                        if (MissedKeepAlives != 0)
                        {
                            // reset missed keep alive count
                            Logger.Information($"Session endpoint: {session.ConfiguredEndpoint.EndpointUrl} got a keep alive after {MissedKeepAlives} {(MissedKeepAlives == 1 ? "was" : "were")} missed.");
                            MissedKeepAlives = 0;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error(ex, $"Error in keep alive handling for endpoint '{session.ConfiguredEndpoint.EndpointUrl}'. (message: '{ex.Message}'");
                }
            }
            else
            {
                Logger.Warning("Keep alive arguments seems to be wrong.");
            }
        }

哪个例子是正确的?对于这些选项中的任何一个,服务器是否会丢弃对监视项目的订阅?我可以依靠这些示例来创建可靠的客户端,还是缺少一些东西?

感谢您的帮助!

【问题讨论】:

    标签: c# .net opc opc-ua


    【解决方案1】:

    这是查看Reference Client 和Reference Server 实施的最佳方式(例如,通过“UA 快速启动应用程序”解决方案),因为它们已经过认证。如有疑问,请作为参考:

    来自ConnectServerCtrl:

    private void Session_KeepAlive(Session session, KeepAliveEventArgs e)
    {
        if (this.InvokeRequired)
        {
            this.BeginInvoke(new KeepAliveEventHandler(Session_KeepAlive), session, e);
            return;
        }
    
        try
        {
            // check for events from discarded sessions.
            if (!Object.ReferenceEquals(session, m_session))
            {
                return;
            }
    
            // start reconnect sequence on communication error.
            if (ServiceResult.IsBad(e.Status))
            {
                if (m_reconnectPeriod <= 0)
                {
                    UpdateStatus(true, e.CurrentTime, "Communication Error ({0})", e.Status);
                    return;
                }
    
                UpdateStatus(true, e.CurrentTime, "Reconnecting in {0}s", m_reconnectPeriod);
    
                if (m_reconnectHandler == null)
                {
                    if (m_ReconnectStarting != null)
                    {
                        m_ReconnectStarting(this, e);
                    }
    
                    m_reconnectHandler = new SessionReconnectHandler();
                    m_reconnectHandler.BeginReconnect(m_session, m_reconnectPeriod * 1000, Server_ReconnectComplete);
                }
    
                return;
            }
    
            // update status.
            UpdateStatus(false, e.CurrentTime, "Connected [{0}]", session.Endpoint.EndpointUrl);
                            
            // raise any additional notifications.
            if (m_KeepAliveComplete != null)
            {
                m_KeepAliveComplete(this, e);
            }
        }
        catch (Exception exception)
        {
            ClientUtils.HandleException(this.Text, exception);
        }
    }
    

    【讨论】:

    • 感谢您的回复。在这种情况下,我感兴趣的是如何在重新连接会话后检查关联的订阅是否仍然存在。为此,我打电话给subscription.Republish(0),我不确定这是否是设计意图
    • 订阅存在于会话中。重新连接后会话所做的最后一件事是发布到订阅(您可以查看Opc.Ua.Client.Session。我会说您不必调用 Republish。
    • 我“手动”执行重新连接,不使用事件来确定订阅状态。 OnPublishComplete 方法为我澄清了哪些状态代码表明订阅已失效。谢谢你的回答!
    猜你喜欢
    • 2020-08-28
    • 1970-01-01
    • 2020-03-08
    • 2020-12-23
    • 2018-09-01
    • 2018-10-18
    • 2019-01-15
    • 1970-01-01
    • 2022-08-17
    相关资源
    最近更新 更多