/// <summary>
        /// Creates the diagnostics node for a subscription.
        /// </summary>
        public NodeId CreateSubscriptionDiagnostics(
            ServerSystemContext systemContext, 
            SubscriptionDiagnosticsDataType diagnostics,
            NodeValueSimpleEventHandler updateCallback)
        {
            NodeId nodeId = null;

            lock (Lock)
            {
                // check if diagnostics have been enabled.
                if (!m_diagnosticsEnabled)
                {
                    return null;
                }

                SubscriptionDiagnosticsState diagnosticsNode = new SubscriptionDiagnosticsState(null);

                // create a new instance and assign ids.
                nodeId = CreateNode(
                    systemContext,
                    null,
                    ReferenceTypeIds.HasComponent,
                    new QualifiedName(diagnostics.SubscriptionId.ToString()),
                    diagnosticsNode);

                // add reference to subscription array.
                diagnosticsNode.AddReference(
                    ReferenceTypeIds.HasComponent,
                    true,
                    VariableIds.Server_ServerDiagnostics_SubscriptionDiagnosticsArray);

                // wrap diagnostics in a thread safe object.
                SubscriptionDiagnosticsValue diagnosticsValue = new SubscriptionDiagnosticsValue(diagnosticsNode, diagnostics, Lock);
                diagnosticsValue.CopyPolicy = Opc.Ua.VariableCopyPolicy.Never;
                diagnosticsValue.OnBeforeRead = OnBeforeReadDiagnostics;
                
                // must ensure the first update gets sent.
                diagnosticsValue.Value = null;
                diagnosticsValue.Error = StatusCodes.BadWaitingForInitialData;

                m_subscriptions.Add(new SubscriptionDiagnosticsData(diagnosticsValue, updateCallback));

                // add reference from subscription array.
                SubscriptionDiagnosticsArrayState array = (SubscriptionDiagnosticsArrayState)FindPredefinedNode(
                    VariableIds.Server_ServerDiagnostics_SubscriptionDiagnosticsArray,
                    typeof(SubscriptionDiagnosticsArrayState));
                                            
                if (array != null)
                {
                    array.AddReference(ReferenceTypeIds.HasComponent, false, diagnosticsNode.NodeId);
                }
                
                // add reference to session subscription array.
                diagnosticsNode.AddReference(
                    ReferenceTypeIds.HasComponent,
                    true,
                    diagnostics.SessionId);

                // add reference from session subscription array.
                SessionDiagnosticsObjectState sessionNode = (SessionDiagnosticsObjectState)FindPredefinedNode(
                    diagnostics.SessionId,
                    typeof(SessionDiagnosticsObjectState));
                                            
                if (sessionNode != null)
                {
                    // add reference from subscription array.
                    array = (SubscriptionDiagnosticsArrayState)sessionNode.CreateChild(
                        systemContext,
                        BrowseNames.SubscriptionDiagnosticsArray);
                                                
                    if (array != null)
                    {
                        array.AddReference(ReferenceTypeIds.HasComponent, false, diagnosticsNode.NodeId);
                    }
                }

                // send initial update.
                DoScan(true);
            }

            return nodeId;
        }
        /// <summary>
        /// Creates the diagnostics node for a subscription.
        /// </summary>
        public NodeId CreateSessionDiagnostics(
            ServerSystemContext systemContext, 
            SessionDiagnosticsDataType diagnostics,
            NodeValueSimpleEventHandler updateCallback,
            SessionSecurityDiagnosticsDataType securityDiagnostics,
            NodeValueSimpleEventHandler updateSecurityCallback)
        {
            NodeId nodeId = null;

            lock (Lock)
            {
                SessionDiagnosticsObjectState sessionNode = new SessionDiagnosticsObjectState(null);
                
                // create a new instance and assign ids.
                nodeId = CreateNode(
                    systemContext,
                    null,
                    ReferenceTypeIds.HasComponent,
                    new QualifiedName(diagnostics.SessionName),
                    sessionNode);

                diagnostics.SessionId = nodeId;
                securityDiagnostics.SessionId = nodeId;
                
                // check if diagnostics have been enabled.
                if (!m_diagnosticsEnabled)
                {
                    return nodeId;
                }

                // add reference to session summary object.
                sessionNode.AddReference(
                    ReferenceTypeIds.HasComponent,
                    true,
                    ObjectIds.Server_ServerDiagnostics_SessionsDiagnosticsSummary);
                
                // add reference from session summary object.
                SessionsDiagnosticsSummaryState summary = (SessionsDiagnosticsSummaryState)FindPredefinedNode(
                    ObjectIds.Server_ServerDiagnostics_SessionsDiagnosticsSummary,
                    typeof(SessionsDiagnosticsSummaryState));
                                            
                if (summary != null)
                {
                    summary.AddReference(ReferenceTypeIds.HasComponent, false, sessionNode.NodeId);
                }

                // initialize diagnostics node.
                SessionDiagnosticsVariableState diagnosticsNode = sessionNode.CreateChild(
                   systemContext,
                   BrowseNames.SessionDiagnostics) as SessionDiagnosticsVariableState;
                
                // wrap diagnostics in a thread safe object.
                SessionDiagnosticsVariableValue diagnosticsValue = new SessionDiagnosticsVariableValue(
                    diagnosticsNode, 
                    diagnostics, 
                    Lock);
                
                // must ensure the first update gets sent.
                diagnosticsValue.Value = null;
                diagnosticsValue.Error = StatusCodes.BadWaitingForInitialData;
                diagnosticsValue.CopyPolicy = Opc.Ua.VariableCopyPolicy.Never;
                diagnosticsValue.OnBeforeRead = OnBeforeReadDiagnostics;
                
                // initialize security diagnostics node.
                SessionSecurityDiagnosticsState securityDiagnosticsNode = sessionNode.CreateChild(
                   systemContext,
                   BrowseNames.SessionSecurityDiagnostics) as SessionSecurityDiagnosticsState;
                
                // wrap diagnostics in a thread safe object.
                SessionSecurityDiagnosticsValue securityDiagnosticsValue = new SessionSecurityDiagnosticsValue(
                    securityDiagnosticsNode, 
                    securityDiagnostics, 
                    Lock);
                
                // must ensure the first update gets sent.
                securityDiagnosticsValue.Value = null;
                securityDiagnosticsValue.Error = StatusCodes.BadWaitingForInitialData;
                securityDiagnosticsValue.CopyPolicy = Opc.Ua.VariableCopyPolicy.Never;
                securityDiagnosticsValue.OnBeforeRead = OnBeforeReadDiagnostics;
                
                // save the session.
                SessionDiagnosticsData sessionData = new SessionDiagnosticsData(
                    sessionNode,
                    diagnosticsValue, 
                    updateCallback, 
                    securityDiagnosticsValue, 
                    updateSecurityCallback);

                m_sessions.Add(sessionData);

                // send initial update.
                DoScan(true);
            }

            return nodeId;
        }
 public SubscriptionDiagnosticsData(
     SubscriptionDiagnosticsValue value,
     NodeValueSimpleEventHandler updateCallback)
 {
     Value = value;
     UpdateCallback = updateCallback;
 }
        /// <summary>
        /// Creates the diagnostics node for the server.
        /// </summary>
        public void CreateServerDiagnostics(
            ServerSystemContext systemContext, 
            ServerDiagnosticsSummaryDataType diagnostics,
            NodeValueSimpleEventHandler updateCallback)
        {
            lock (Lock)
            {
                // get the node.
                ServerDiagnosticsSummaryState diagnosticsNode = (ServerDiagnosticsSummaryState)FindPredefinedNode(
                    VariableIds.Server_ServerDiagnostics_ServerDiagnosticsSummary,
                    typeof(ServerDiagnosticsSummaryState));
                                
                // wrap diagnostics in a thread safe object.
                ServerDiagnosticsSummaryValue diagnosticsValue = new ServerDiagnosticsSummaryValue(
                    diagnosticsNode, 
                    diagnostics, 
                    Lock);
                
                // must ensure the first update gets sent.
                diagnosticsValue.Value = null;
                diagnosticsValue.Error = StatusCodes.BadWaitingForInitialData;
                diagnosticsValue.CopyPolicy = Opc.Ua.VariableCopyPolicy.Never;
                diagnosticsValue.OnBeforeRead = OnBeforeReadDiagnostics;
                
                m_serverDiagnostics = diagnosticsValue;
                m_serverDiagnosticsCallback = updateCallback;
                
                // set up handler for session diagnostics array.
                SessionDiagnosticsArrayState array1 = (SessionDiagnosticsArrayState)FindPredefinedNode(
                    VariableIds.Server_ServerDiagnostics_SessionsDiagnosticsSummary_SessionDiagnosticsArray,
                    typeof(SessionDiagnosticsArrayState));
                                            
                if (array1 != null)
                {
                    array1.OnSimpleReadValue = OnReadDiagnosticsArray;
                }
                
                // set up handler for session security diagnostics array.
                SessionSecurityDiagnosticsArrayState array2 = (SessionSecurityDiagnosticsArrayState)FindPredefinedNode(
                    VariableIds.Server_ServerDiagnostics_SessionsDiagnosticsSummary_SessionSecurityDiagnosticsArray,
                    typeof(SessionSecurityDiagnosticsArrayState));
                                            
                if (array2 != null)
                {
                    array2.OnSimpleReadValue = OnReadDiagnosticsArray;
                }
                
                // set up handler for subscription security diagnostics array.
                SubscriptionDiagnosticsArrayState array3 = (SubscriptionDiagnosticsArrayState)FindPredefinedNode(
                    VariableIds.Server_ServerDiagnostics_SubscriptionDiagnosticsArray,
                    typeof(SubscriptionDiagnosticsArrayState));
                                            
                if (array3 != null)
                {
                    array3.OnSimpleReadValue = OnReadDiagnosticsArray;
                }

                // send initial update.
                DoScan(true);
            }
        }
 public SessionDiagnosticsData(
     SessionDiagnosticsObjectState summary,
     SessionDiagnosticsVariableValue value,
     NodeValueSimpleEventHandler updateCallback,
     SessionSecurityDiagnosticsValue securityValue,
     NodeValueSimpleEventHandler securityUpdateCallback)
 {
     Summary = summary;
     Value = value;
     UpdateCallback = updateCallback;
     SecurityValue = securityValue;
     SecurityUpdateCallback = securityUpdateCallback;
 }