/// <summary> /// Creates the ServerObject and attaches it to the NodeManager. /// </summary> private void CreateServerObject() { lock (m_diagnosticsNodeManager.Lock) { // get the server object. ServerObjectState serverObject = m_serverObject = (ServerObjectState)m_diagnosticsNodeManager.FindPredefinedNode( ObjectIds.Server, typeof(ServerObjectState)); // update server capabilities. serverObject.ServiceLevel.Value = 255; serverObject.ServerCapabilities.LocaleIdArray.Value = m_resourceManager.GetAvailableLocales(); serverObject.ServerCapabilities.MinSupportedSampleRate.Value = 0; serverObject.ServerCapabilities.MaxBrowseContinuationPoints.Value = (ushort)m_configuration.ServerConfiguration.MaxBrowseContinuationPoints; serverObject.ServerCapabilities.MaxQueryContinuationPoints.Value = (ushort)m_configuration.ServerConfiguration.MaxQueryContinuationPoints; serverObject.ServerCapabilities.MaxHistoryContinuationPoints.Value = (ushort)m_configuration.ServerConfiguration.MaxHistoryContinuationPoints; // setup callbacks for dynamic values. serverObject.NamespaceArray.OnSimpleReadValue = OnReadNamespaceArray; serverObject.NamespaceArray.MinimumSamplingInterval = 1000; serverObject.ServerArray.OnSimpleReadValue = OnReadServerArray; serverObject.ServerArray.MinimumSamplingInterval = 1000; serverObject.ServerDiagnostics.EnabledFlag.OnSimpleReadValue = OnReadDiagnosticsEnabledFlag; serverObject.ServerDiagnostics.EnabledFlag.MinimumSamplingInterval = 1000; // initialize status. ServerStatusDataType serverStatus = new ServerStatusDataType(); serverStatus.StartTime = DateTime.UtcNow; serverStatus.CurrentTime = DateTime.UtcNow; serverStatus.State = ServerState.Shutdown; serverStatus.BuildInfo.ProductName = m_serverDescription.ProductName; serverStatus.BuildInfo.ProductUri = m_serverDescription.ProductUri; serverStatus.BuildInfo.ManufacturerName = m_serverDescription.ManufacturerName; serverStatus.BuildInfo.SoftwareVersion = m_serverDescription.SoftwareVersion; serverStatus.BuildInfo.BuildNumber = m_serverDescription.BuildNumber; serverStatus.BuildInfo.BuildDate = m_serverDescription.BuildDate; serverObject.ServerStatus.MinimumSamplingInterval = 1000; serverObject.ServerStatus.CurrentTime.MinimumSamplingInterval = 1000; m_serverStatus = new ServerStatusValue( serverObject.ServerStatus, serverStatus, m_dataLock); m_serverStatus.Timestamp = DateTime.UtcNow; m_serverStatus.OnBeforeRead = OnReadServerStatus; // initialize diagnostics. m_serverDiagnostics = new ServerDiagnosticsSummaryDataType(); m_serverDiagnostics.ServerViewCount = 0; m_serverDiagnostics.CurrentSessionCount = 0; m_serverDiagnostics.CumulatedSessionCount = 0; m_serverDiagnostics.SecurityRejectedSessionCount = 0; m_serverDiagnostics.RejectedSessionCount = 0; m_serverDiagnostics.SessionTimeoutCount = 0; m_serverDiagnostics.SessionAbortCount = 0; m_serverDiagnostics.PublishingIntervalCount = 0; m_serverDiagnostics.CurrentSubscriptionCount = 0; m_serverDiagnostics.CumulatedSubscriptionCount = 0; m_serverDiagnostics.SecurityRejectedRequestsCount = 0; m_serverDiagnostics.RejectedRequestsCount = 0; m_diagnosticsNodeManager.CreateServerDiagnostics( m_defaultSystemContext, m_serverDiagnostics, OnUpdateDiagnostics); // set the diagnostics enabled state. m_diagnosticsNodeManager.SetDiagnosticsEnabled( m_defaultSystemContext, m_configuration.ServerConfiguration.DiagnosticsEnabled); // TBD - Load the Software Certificates. } }
/// <summary> /// Creates the ServerObject and attaches it to the NodeManager. /// </summary> private void CreateServerObject() { lock (m_diagnosticsNodeManager.Lock) { // get the server object. ServerObjectState serverObject = m_serverObject = (ServerObjectState)m_diagnosticsNodeManager.FindPredefinedNode( ObjectIds.Server, typeof(ServerObjectState)); // update server capabilities. serverObject.ServiceLevel.Value = 255; serverObject.ServerCapabilities.LocaleIdArray.Value = m_resourceManager.GetAvailableLocales(); serverObject.ServerCapabilities.MinSupportedSampleRate.Value = 0; serverObject.ServerCapabilities.MaxBrowseContinuationPoints.Value = (ushort)m_configuration.ServerConfiguration.MaxBrowseContinuationPoints; serverObject.ServerCapabilities.MaxQueryContinuationPoints.Value = (ushort)m_configuration.ServerConfiguration.MaxQueryContinuationPoints; serverObject.ServerCapabilities.MaxHistoryContinuationPoints.Value = (ushort)m_configuration.ServerConfiguration.MaxHistoryContinuationPoints; // setup callbacks for dynamic values. serverObject.NamespaceArray.OnSimpleReadValue = OnReadNamespaceArray; serverObject.NamespaceArray.MinimumSamplingInterval = 1000; serverObject.ServerArray.OnSimpleReadValue = OnReadServerArray; serverObject.ServerArray.MinimumSamplingInterval = 1000; serverObject.ServerDiagnostics.EnabledFlag.OnSimpleReadValue = OnReadDiagnosticsEnabledFlag; serverObject.ServerDiagnostics.EnabledFlag.OnSimpleWriteValue = OnWriteDiagnosticsEnabledFlag; serverObject.ServerDiagnostics.EnabledFlag.MinimumSamplingInterval = 1000; // initialize status. ServerStatusDataType serverStatus = new ServerStatusDataType(); serverStatus.StartTime = DateTime.UtcNow; serverStatus.CurrentTime = DateTime.UtcNow; serverStatus.State = ServerState.Shutdown; serverStatus.BuildInfo.ProductName = m_serverDescription.ProductName; serverStatus.BuildInfo.ProductUri = m_serverDescription.ProductUri; serverStatus.BuildInfo.ManufacturerName = m_serverDescription.ManufacturerName; serverStatus.BuildInfo.SoftwareVersion = m_serverDescription.SoftwareVersion; serverStatus.BuildInfo.BuildNumber = m_serverDescription.BuildNumber; serverStatus.BuildInfo.BuildDate = m_serverDescription.BuildDate; serverObject.ServerStatus.MinimumSamplingInterval = 1000; serverObject.ServerStatus.CurrentTime.MinimumSamplingInterval = 1000; m_serverStatus = new ServerStatusValue( serverObject.ServerStatus, serverStatus, m_dataLock); m_serverStatus.Timestamp = DateTime.UtcNow; m_serverStatus.OnBeforeRead = OnReadServerStatus; // initialize diagnostics. m_serverDiagnostics = new ServerDiagnosticsSummaryDataType(); m_serverDiagnostics.ServerViewCount = 0; m_serverDiagnostics.CurrentSessionCount = 0; m_serverDiagnostics.CumulatedSessionCount = 0; m_serverDiagnostics.SecurityRejectedSessionCount = 0; m_serverDiagnostics.RejectedSessionCount = 0; m_serverDiagnostics.SessionTimeoutCount = 0; m_serverDiagnostics.SessionAbortCount = 0; m_serverDiagnostics.PublishingIntervalCount = 0; m_serverDiagnostics.CurrentSubscriptionCount = 0; m_serverDiagnostics.CumulatedSubscriptionCount = 0; m_serverDiagnostics.SecurityRejectedRequestsCount = 0; m_serverDiagnostics.RejectedRequestsCount = 0; m_diagnosticsNodeManager.CreateServerDiagnostics( m_defaultSystemContext, m_serverDiagnostics, OnUpdateDiagnostics); // set the diagnostics enabled state. m_diagnosticsNodeManager.SetDiagnosticsEnabled( m_defaultSystemContext, m_configuration.ServerConfiguration.DiagnosticsEnabled); // TBD - Load the Software Certificates. } }
/// <summary> /// Creates the ServerObject and attaches it to the NodeManager. /// </summary> private void CreateServerObject() { lock (m_diagnosticsNodeManager.Lock) { // get the server object. ServerObjectState serverObject = m_serverObject = (ServerObjectState)m_diagnosticsNodeManager.FindPredefinedNode( ObjectIds.Server, typeof(ServerObjectState)); // update server capabilities. serverObject.ServiceLevel.Value = 255; serverObject.ServerCapabilities.LocaleIdArray.Value = m_resourceManager.GetAvailableLocales(); serverObject.ServerCapabilities.ServerProfileArray.Value = m_configuration.ServerConfiguration.ServerProfileArray.ToArray(); serverObject.ServerCapabilities.MinSupportedSampleRate.Value = 0; serverObject.ServerCapabilities.MaxBrowseContinuationPoints.Value = (ushort)m_configuration.ServerConfiguration.MaxBrowseContinuationPoints; serverObject.ServerCapabilities.MaxQueryContinuationPoints.Value = (ushort)m_configuration.ServerConfiguration.MaxQueryContinuationPoints; serverObject.ServerCapabilities.MaxHistoryContinuationPoints.Value = (ushort)m_configuration.ServerConfiguration.MaxHistoryContinuationPoints; serverObject.ServerCapabilities.MaxArrayLength.Value = (uint)m_configuration.TransportQuotas.MaxArrayLength; serverObject.ServerCapabilities.MaxStringLength.Value = (uint)m_configuration.TransportQuotas.MaxStringLength; serverObject.ServerCapabilities.MaxByteStringLength.Value = (uint)m_configuration.TransportQuotas.MaxByteStringLength; // Any operational limits Property that is provided shall have a non zero value. var operationLimits = serverObject.ServerCapabilities.OperationLimits; var configOperationLimits = m_configuration.ServerConfiguration.OperationLimits; if (configOperationLimits != null) { operationLimits.MaxNodesPerRead = SetPropertyValue(operationLimits.MaxNodesPerRead, configOperationLimits.MaxNodesPerRead); operationLimits.MaxNodesPerHistoryReadData = SetPropertyValue(operationLimits.MaxNodesPerHistoryReadData, configOperationLimits.MaxNodesPerHistoryReadData); operationLimits.MaxNodesPerHistoryReadEvents = SetPropertyValue(operationLimits.MaxNodesPerHistoryReadEvents, configOperationLimits.MaxNodesPerHistoryReadEvents); operationLimits.MaxNodesPerWrite = SetPropertyValue(operationLimits.MaxNodesPerWrite, configOperationLimits.MaxNodesPerWrite); operationLimits.MaxNodesPerHistoryUpdateData = SetPropertyValue(operationLimits.MaxNodesPerHistoryUpdateData, configOperationLimits.MaxNodesPerHistoryUpdateData); operationLimits.MaxNodesPerHistoryUpdateEvents = SetPropertyValue(operationLimits.MaxNodesPerHistoryUpdateEvents, configOperationLimits.MaxNodesPerHistoryUpdateEvents); operationLimits.MaxNodesPerMethodCall = SetPropertyValue(operationLimits.MaxNodesPerMethodCall, configOperationLimits.MaxNodesPerMethodCall); operationLimits.MaxNodesPerBrowse = SetPropertyValue(operationLimits.MaxNodesPerBrowse, configOperationLimits.MaxNodesPerBrowse); operationLimits.MaxNodesPerRegisterNodes = SetPropertyValue(operationLimits.MaxNodesPerRegisterNodes, configOperationLimits.MaxNodesPerRegisterNodes); operationLimits.MaxNodesPerTranslateBrowsePathsToNodeIds = SetPropertyValue(operationLimits.MaxNodesPerTranslateBrowsePathsToNodeIds, configOperationLimits.MaxNodesPerTranslateBrowsePathsToNodeIds); operationLimits.MaxNodesPerNodeManagement = SetPropertyValue(operationLimits.MaxNodesPerNodeManagement, configOperationLimits.MaxNodesPerNodeManagement); operationLimits.MaxMonitoredItemsPerCall = SetPropertyValue(operationLimits.MaxMonitoredItemsPerCall, configOperationLimits.MaxMonitoredItemsPerCall); } else { operationLimits.MaxNodesPerRead = operationLimits.MaxNodesPerHistoryReadData = operationLimits.MaxNodesPerHistoryReadEvents = operationLimits.MaxNodesPerWrite = operationLimits.MaxNodesPerHistoryUpdateData = operationLimits.MaxNodesPerHistoryUpdateEvents = operationLimits.MaxNodesPerMethodCall = operationLimits.MaxNodesPerBrowse = operationLimits.MaxNodesPerRegisterNodes = operationLimits.MaxNodesPerTranslateBrowsePathsToNodeIds = operationLimits.MaxNodesPerNodeManagement = operationLimits.MaxMonitoredItemsPerCall = null; } // setup PublishSubscribe Status State value PubSubState pubSubState = PubSubState.Disabled; var default_PubSubState = (BaseVariableState)m_diagnosticsNodeManager.FindPredefinedNode( VariableIds.PublishSubscribe_Status_State, typeof(BaseVariableState)); default_PubSubState.Value = pubSubState; // setup value for SupportedTransportProfiles var default_SupportedTransportProfiles = (BaseVariableState)m_diagnosticsNodeManager.FindPredefinedNode( VariableIds.PublishSubscribe_SupportedTransportProfiles, typeof(BaseVariableState)); default_SupportedTransportProfiles.Value = "uadp"; // setup callbacks for dynamic values. serverObject.NamespaceArray.OnSimpleReadValue = OnReadNamespaceArray; serverObject.NamespaceArray.MinimumSamplingInterval = 1000; serverObject.ServerArray.OnSimpleReadValue = OnReadServerArray; serverObject.ServerArray.MinimumSamplingInterval = 1000; // dynamic change of enabledFlag is disabled to pass CTT serverObject.ServerDiagnostics.EnabledFlag.AccessLevel = AccessLevels.CurrentRead; serverObject.ServerDiagnostics.EnabledFlag.UserAccessLevel = AccessLevels.CurrentRead; serverObject.ServerDiagnostics.EnabledFlag.OnSimpleReadValue = OnReadDiagnosticsEnabledFlag; serverObject.ServerDiagnostics.EnabledFlag.OnSimpleWriteValue = OnWriteDiagnosticsEnabledFlag; serverObject.ServerDiagnostics.EnabledFlag.MinimumSamplingInterval = 1000; // initialize status. ServerStatusDataType serverStatus = new ServerStatusDataType(); serverStatus.StartTime = DateTime.UtcNow; serverStatus.CurrentTime = DateTime.UtcNow; serverStatus.State = ServerState.Shutdown; serverStatus.BuildInfo.ProductName = m_serverDescription.ProductName; serverStatus.BuildInfo.ProductUri = m_serverDescription.ProductUri; serverStatus.BuildInfo.ManufacturerName = m_serverDescription.ManufacturerName; serverStatus.BuildInfo.SoftwareVersion = m_serverDescription.SoftwareVersion; serverStatus.BuildInfo.BuildNumber = m_serverDescription.BuildNumber; serverStatus.BuildInfo.BuildDate = m_serverDescription.BuildDate; serverObject.ServerStatus.MinimumSamplingInterval = 1000; serverObject.ServerStatus.CurrentTime.MinimumSamplingInterval = 1000; m_serverStatus = new ServerStatusValue( serverObject.ServerStatus, serverStatus, m_dataLock); m_serverStatus.Timestamp = DateTime.UtcNow; m_serverStatus.OnBeforeRead = OnReadServerStatus; // initialize diagnostics. m_serverDiagnostics = new ServerDiagnosticsSummaryDataType(); m_serverDiagnostics.ServerViewCount = 0; m_serverDiagnostics.CurrentSessionCount = 0; m_serverDiagnostics.CumulatedSessionCount = 0; m_serverDiagnostics.SecurityRejectedSessionCount = 0; m_serverDiagnostics.RejectedSessionCount = 0; m_serverDiagnostics.SessionTimeoutCount = 0; m_serverDiagnostics.SessionAbortCount = 0; m_serverDiagnostics.PublishingIntervalCount = 0; m_serverDiagnostics.CurrentSubscriptionCount = 0; m_serverDiagnostics.CumulatedSubscriptionCount = 0; m_serverDiagnostics.SecurityRejectedRequestsCount = 0; m_serverDiagnostics.RejectedRequestsCount = 0; m_diagnosticsNodeManager.CreateServerDiagnostics( m_defaultSystemContext, m_serverDiagnostics, OnUpdateDiagnostics); // set the diagnostics enabled state. m_diagnosticsNodeManager.SetDiagnosticsEnabled( m_defaultSystemContext, m_configuration.ServerConfiguration.DiagnosticsEnabled); ConfigurationNodeManager configurationNodeManager = m_diagnosticsNodeManager as ConfigurationNodeManager; configurationNodeManager?.CreateServerConfiguration( m_defaultSystemContext, m_configuration); } }
/// <summary> /// Creates the ServerObject and attaches it to the NodeManager. /// </summary> private void CreateServerObject() { lock (m_diagnosticsNodeManager.Lock) { // get the server object. ServerObjectState serverObject = m_serverObject = (ServerObjectState)m_diagnosticsNodeManager.FindPredefinedNode( ObjectIds.Server, typeof(ServerObjectState)); // update server capabilities. serverObject.ServiceLevel.Value = 255; serverObject.ServerCapabilities.LocaleIdArray.Value = m_resourceManager.GetAvailableLocales(); serverObject.ServerCapabilities.ServerProfileArray.Value = m_configuration.ServerConfiguration.ServerProfileArray.ToArray(); serverObject.ServerCapabilities.MinSupportedSampleRate.Value = 0; serverObject.ServerCapabilities.MaxBrowseContinuationPoints.Value = (ushort)m_configuration.ServerConfiguration.MaxBrowseContinuationPoints; serverObject.ServerCapabilities.MaxQueryContinuationPoints.Value = (ushort)m_configuration.ServerConfiguration.MaxQueryContinuationPoints; serverObject.ServerCapabilities.MaxHistoryContinuationPoints.Value = (ushort)m_configuration.ServerConfiguration.MaxHistoryContinuationPoints; serverObject.ServerCapabilities.MaxArrayLength.Value = (uint)m_configuration.TransportQuotas.MaxArrayLength; serverObject.ServerCapabilities.MaxStringLength.Value = (uint)m_configuration.TransportQuotas.MaxStringLength; serverObject.ServerCapabilities.MaxByteStringLength.Value = (uint)m_configuration.TransportQuotas.MaxByteStringLength; serverObject.ServerCapabilities.OperationLimits.MaxNodesPerRead.Value = 0; serverObject.ServerCapabilities.OperationLimits.MaxNodesPerWrite.Value = 0; serverObject.ServerCapabilities.OperationLimits.MaxNodesPerMethodCall.Value = 1000; serverObject.ServerCapabilities.OperationLimits.MaxNodesPerBrowse.Value = 0; serverObject.ServerCapabilities.OperationLimits.MaxNodesPerRegisterNodes.Value = 0; // setup callbacks for dynamic values. serverObject.NamespaceArray.OnSimpleReadValue = OnReadNamespaceArray; serverObject.NamespaceArray.MinimumSamplingInterval = 1000; serverObject.ServerArray.OnSimpleReadValue = OnReadServerArray; serverObject.ServerArray.MinimumSamplingInterval = 1000; // dynamic change of enabledFlag is disabled to pass CTT serverObject.ServerDiagnostics.EnabledFlag.AccessLevel = AccessLevels.CurrentRead; serverObject.ServerDiagnostics.EnabledFlag.UserAccessLevel = AccessLevels.CurrentRead; serverObject.ServerDiagnostics.EnabledFlag.OnSimpleReadValue = OnReadDiagnosticsEnabledFlag; serverObject.ServerDiagnostics.EnabledFlag.OnSimpleWriteValue = OnWriteDiagnosticsEnabledFlag; serverObject.ServerDiagnostics.EnabledFlag.MinimumSamplingInterval = 1000; // initialize status. ServerStatusDataType serverStatus = new ServerStatusDataType(); serverStatus.StartTime = DateTime.UtcNow; serverStatus.CurrentTime = DateTime.UtcNow; serverStatus.State = ServerState.Shutdown; serverStatus.BuildInfo.ProductName = m_serverDescription.ProductName; serverStatus.BuildInfo.ProductUri = m_serverDescription.ProductUri; serverStatus.BuildInfo.ManufacturerName = m_serverDescription.ManufacturerName; serverStatus.BuildInfo.SoftwareVersion = m_serverDescription.SoftwareVersion; serverStatus.BuildInfo.BuildNumber = m_serverDescription.BuildNumber; serverStatus.BuildInfo.BuildDate = m_serverDescription.BuildDate; serverObject.ServerStatus.MinimumSamplingInterval = 1000; serverObject.ServerStatus.CurrentTime.MinimumSamplingInterval = 1000; m_serverStatus = new ServerStatusValue( serverObject.ServerStatus, serverStatus, m_dataLock); m_serverStatus.Timestamp = DateTime.UtcNow; m_serverStatus.OnBeforeRead = OnReadServerStatus; // initialize diagnostics. m_serverDiagnostics = new ServerDiagnosticsSummaryDataType(); m_serverDiagnostics.ServerViewCount = 0; m_serverDiagnostics.CurrentSessionCount = 0; m_serverDiagnostics.CumulatedSessionCount = 0; m_serverDiagnostics.SecurityRejectedSessionCount = 0; m_serverDiagnostics.RejectedSessionCount = 0; m_serverDiagnostics.SessionTimeoutCount = 0; m_serverDiagnostics.SessionAbortCount = 0; m_serverDiagnostics.PublishingIntervalCount = 0; m_serverDiagnostics.CurrentSubscriptionCount = 0; m_serverDiagnostics.CumulatedSubscriptionCount = 0; m_serverDiagnostics.SecurityRejectedRequestsCount = 0; m_serverDiagnostics.RejectedRequestsCount = 0; m_diagnosticsNodeManager.CreateServerDiagnostics( m_defaultSystemContext, m_serverDiagnostics, OnUpdateDiagnostics); // set the diagnostics enabled state. m_diagnosticsNodeManager.SetDiagnosticsEnabled( m_defaultSystemContext, m_configuration.ServerConfiguration.DiagnosticsEnabled); ConfigurationNodeManager configurationNodeManager = m_diagnosticsNodeManager as ConfigurationNodeManager; configurationNodeManager?.CreateServerConfiguration( m_defaultSystemContext, m_configuration); } }
/// <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); } }