/// <summary> /// Gets the default history capabilities object. /// </summary> public HistoryServerCapabilitiesState GetDefaultHistoryCapabilities() { lock (Lock) { if (m_historyCapabilities != null) { return m_historyCapabilities; } HistoryServerCapabilitiesState state = new HistoryServerCapabilitiesState(null); NodeId nodeId = CreateNode( SystemContext, null, ReferenceTypeIds.HasComponent, new QualifiedName(BrowseNames.HistoryServerCapabilities), state); state.AccessHistoryDataCapability.Value = false; state.AccessHistoryEventsCapability.Value = false; state.MaxReturnDataValues.Value = 0; state.MaxReturnEventValues.Value = 0; state.ReplaceDataCapability.Value = false; state.UpdateDataCapability.Value = false; state.InsertEventCapability.Value = false; state.ReplaceEventCapability.Value = false; state.UpdateEventCapability.Value = false; state.InsertAnnotationCapability.Value = false; state.InsertDataCapability.Value = false; state.DeleteRawCapability.Value = false; state.DeleteAtTimeCapability.Value = false; NodeState parent = FindPredefinedNode(ObjectIds.Server_ServerCapabilities, typeof(ServerCapabilitiesState)); if (parent != null) { parent.AddReference(ReferenceTypes.HasComponent, false, state.NodeId); state.AddReference(ReferenceTypes.HasComponent, true, parent.NodeId); } AddPredefinedNode(SystemContext, state); m_historyCapabilities = state; return m_historyCapabilities; } }
/// <summary> /// Does any initialization required before the address space can be used. /// </summary> /// <remarks> /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// </remarks> public override void CreateAddressSpace(IDictionary<NodeId, IList<IReference>> externalReferences) { lock (Lock) { // check if the type model needs to be loaded. if (NamespaceIndexes.Length > 1) { LoadPredefinedNodes(SystemContext, externalReferences); } // create the root node. string serverName = m_configuration.ServerName; if (String.IsNullOrEmpty(serverName)) { serverName = "ComHdaServer"; } HdaBranchState root = new HdaBranchState(String.Empty, serverName, NamespaceIndex); root.AddReference(ReferenceTypeIds.Organizes, true, ObjectIds.ObjectsFolder); // link root to objects folder. IList<IReference> references = null; if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out references)) { externalReferences[ObjectIds.ObjectsFolder] = references = new List<IReference>(); } references.Add(new NodeStateReference(ReferenceTypeIds.Organizes, false, root.NodeId)); // create the status node. ComServerStatusState status = new ComServerStatusState(root); status.ReferenceTypeId = ReferenceTypeIds.Organizes; // get the type namepace for the browse name. int typeNamepaceIndex = Server.NamespaceUris.GetIndex(Namespaces.ComInterop); if (typeNamepaceIndex < 0) { typeNamepaceIndex = NamespaceIndex; } status.Create( SystemContext, HdaModelUtils.ConstructIdForInternalNode("ServerStatus", NamespaceIndex), new QualifiedName("ServerStatus", (ushort)typeNamepaceIndex), null, true); root.AddChild(status); // store root folder in the pre-defined nodes. AddPredefinedNode(SystemContext, root); // create the server capabilities object. HistoryServerCapabilitiesState capabilities = m_capabilities = new HistoryServerCapabilitiesState(null); CreateNode( SystemContext, root.NodeId, ReferenceTypeIds.Organizes, new QualifiedName(Opc.Ua.BrowseNames.HistoryServerCapabilities), capabilities); capabilities.AccessHistoryDataCapability.Value = true; capabilities.AccessHistoryEventsCapability.Value = false; capabilities.MaxReturnDataValues.Value = 0; capabilities.MaxReturnEventValues.Value = 0; capabilities.ReplaceDataCapability.Value = false; capabilities.UpdateDataCapability.Value = false; capabilities.InsertEventCapability.Value = false; capabilities.ReplaceEventCapability.Value = false; capabilities.UpdateEventCapability.Value = false; capabilities.InsertAnnotationCapability.Value = false; capabilities.InsertDataCapability.Value = false; capabilities.DeleteRawCapability.Value = false; capabilities.DeleteAtTimeCapability.Value = false; AddPredefinedNode(SystemContext, capabilities); // create the default aggregate configuration object. AggregateConfigurationState aggregateConfiguration = new AggregateConfigurationState(null); aggregateConfiguration.ReferenceTypeId = ReferenceTypeIds.Organizes; aggregateConfiguration.Create( SystemContext, HdaModelUtils.ConstructIdForInternalNode(Opc.Ua.BrowseNames.AggregateConfiguration, NamespaceIndex), Opc.Ua.BrowseNames.AggregateConfiguration, null, true); aggregateConfiguration.TreatUncertainAsBad.Value = m_configuration.TreatUncertainAsBad; aggregateConfiguration.PercentDataBad.Value = m_configuration.PercentDataBad; aggregateConfiguration.PercentDataGood.Value = m_configuration.PercentDataGood; aggregateConfiguration.UseSlopedExtrapolation.Value = m_configuration.SteppedSlopedExtrapolation; AddPredefinedNode(SystemContext, aggregateConfiguration); // create the COM server. m_system.Initialize(SystemContext, m_configuration, status, Lock, OnServerReconnected); StartMetadataUpdates(DoMetadataUpdate, null, 5000, m_configuration.MaxReconnectWait); } }
/// <summary> /// Does any initialization required before the address space can be used. /// </summary> /// <remarks> /// The externalReferences is an out parameter that allows the node manager to link to nodes /// in other node managers. For example, the 'Objects' node is managed by the CoreNodeManager and /// should have a reference to the root folder node(s) exposed by this node manager. /// </remarks> public override void CreateAddressSpace(IDictionary <NodeId, IList <IReference> > externalReferences) { lock (ServerData.DiagnosticsLock) { HistoryServerCapabilitiesState capabilities = ServerData.DiagnosticsNodeManager.GetDefaultHistoryCapabilities(); capabilities.AccessHistoryDataCapability.Value = true; capabilities.InsertDataCapability.Value = true; capabilities.ReplaceDataCapability.Value = true; capabilities.UpdateDataCapability.Value = true; capabilities.DeleteRawCapability.Value = true; capabilities.DeleteAtTimeCapability.Value = true; capabilities.InsertAnnotationCapability.Value = true; } lock (Lock) { dynamicNodes_ = new List <BaseDataVariableState>(); if (!externalReferences.TryGetValue(ObjectIds.ObjectsFolder, out var references)) { externalReferences[ObjectIds.ObjectsFolder] = References = new List <IReference>(); } else { References = references; } LoadPredefinedNodes(SystemContext, externalReferences); // Create the root folder for all nodes of this server var root = CreateFolderState(null, "My Data", new LocalizedText("en", "My Data"), new LocalizedText("en", "Root folder of the Sample Server. All nodes must be placed under this root.")); References.Add(new NodeStateReference(ReferenceTypes.Organizes, false, root.NodeId)); root.EventNotifier = EventNotifiers.SubscribeToEvents; opcServer_.AddRootNotifier(root); try { #region Static var staticFolder = CreateFolderState(root, "Static", "Static", "A folder with a sample static variable."); const string scalarStatic = "Static_"; CreateBaseDataVariableState(staticFolder, scalarStatic + "String", "String", null, DataTypeIds.String, ValueRanks.Scalar, AccessLevels.CurrentReadOrWrite, null); #endregion #region Simulation var simulationFolder = CreateFolderState(root, "Simulation", "Simulation", "A folder with simulated variables."); const string simulation = "Simulation_"; var simulatedVariable = CreateDynamicVariable(simulationFolder, simulation + "Double", "Double", "A simulated variable of type Double. If Enabled is true this value changes based on the defined Interval.", DataTypeIds.Double, ValueRanks.Scalar, AccessLevels.CurrentReadOrWrite, null); simulatedVariable.Historizing = true; var intervalVariable = CreateBaseDataVariableState(simulationFolder, simulation + "Interval", "Interval", "The Interval used for changing the simulated values.", DataTypeIds.UInt16, ValueRanks.Scalar, AccessLevels.CurrentReadOrWrite, simulationInterval_); intervalVariable.OnSimpleWriteValue = OnWriteInterval; var enabledVariable = CreateBaseDataVariableState(simulationFolder, simulation + "Enabled", "Enabled", "Specifies whether the simulation is enabled (true) or disabled (false).", DataTypeIds.Boolean, ValueRanks.Scalar, AccessLevels.CurrentReadOrWrite, simulationEnabled_); enabledVariable.OnSimpleWriteValue = OnWriteEnabled; #endregion #region Simulation with HistoricalAccess var simulationHistoricalAccessFolder = CreateFolderState(root, "SimulationHistoricalAccess", "SimulationHistoricalAccess", "A folder with simulated variables supporting HistoricalAccess."); const string simulationHistoricalAccess = "SimulationHistoricalAccess_"; var simulatedHistoricalAccessVariable = CreateHistoricalAccessVariable(simulationHistoricalAccessFolder, simulationHistoricalAccess + "Double", "Double", "A simulated variable of type Double. If Enabled is true this value changes based on the defined Interval.", DataTypeIds.Double, ValueRanks.Scalar, AccessLevels.CurrentReadOrWrite, null); #endregion } catch (Exception e) { Utils.Trace(e, "Error creating the address space."); } // Add all nodes under root to the server AddPredefinedNode(SystemContext, root); simulationTimer_ = new Timer(DoSimulation, null, 1000, 1000); } }