/// <summary> /// Handles a method call. /// </summary> private ServiceResult DoGenerateRandomValues( ISystemContext context, MethodState method, IList <object> inputArguments, IList <object> outputArguments) { ComDaClientManager system = (ComDaClientManager)this.SystemContext.SystemHandle; ComDaClient client = system.SelectClient((ServerSystemContext)context, false); Opc.Ua.Test.DataGenerator generator = new Opc.Ua.Test.DataGenerator(null); IDaElementBrowser browser = client.CreateBrowser((string)method.Handle); // create write requests. WriteRequestCollection requests = new WriteRequestCollection(); try { for (DaElement element = browser.Next(); element != null; element = browser.Next()) { if (element.ElementType == DaElementType.Branch) { continue; } // generate a random value of the correct data tyoe. bool isArray = false; NodeId dataTypeId = ComUtils.GetDataTypeId(element.DataType, out isArray); object value = generator.GetRandom( dataTypeId, (isArray)?ValueRanks.OneDimension:ValueRanks.Scalar, null, context.TypeTable); // create a request. requests.Add(new Opc.Ua.Com.Client.WriteRequest(element.ItemId, new DataValue(new Variant(value)), 0)); } } finally { browser.Dispose(); } // write values. client.Write(requests); return(ServiceResult.Good); }
/// <summary> /// Initializes a new instance of the <see cref="DaItemState"/> class. /// </summary> /// <param name="context">The context.</param> /// <param name="element">The element.</param> /// <param name="namespaceIndex">Index of the namespace.</param> public DaItemState( ISystemContext context, DaElement element, ushort namespaceIndex) : base(null) { this.TypeDefinitionId = Opc.Ua.VariableTypeIds.DataItemType; this.Description = null; this.WriteMask = 0; this.UserWriteMask = 0; if (element != null) { Initialize(context, element, namespaceIndex); } }
/// <summary> /// Constructs a branch or item node from a DaElement returned from the COM server. /// </summary> /// <param name="context">The context.</param> /// <param name="element">The element.</param> /// <param name="namespaceIndex">Index of the namespace for the NodeId.</param> /// <returns>The node.</returns> public static NodeState ConstructElement(ISystemContext context, DaElement element, ushort namespaceIndex) { if (element.ElementType == DaElementType.Branch) { return new DaBranchState(context, element, namespaceIndex); } return new DaItemState(context, element, namespaceIndex); }
/// <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 = "ComDaServer"; } DaElement element = new DaElement(); element.ItemId = String.Empty; element.Name = serverName; element.ElementType = DaElementType.Branch; DaBranchState root = new DaBranchState(SystemContext, element, 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, DaModelUtils.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 COM server. m_system.Initialize(SystemContext, m_configuration, status, Lock, OnServerReconnected); StartMetadataUpdates(null, null, 5000, m_configuration.MaxReconnectWait); } }
/// <summary> /// Updates a element. /// </summary> /// <param name="element">The element.</param> /// <param name="name">The name.</param> /// <param name="parentId">The parent id.</param> private void UpdateElement(DaElement element, string name, string parentId) { // only update the name if specified. if (name != null) { element.Name = name; } // same for the parent id. if (parentId != null) { element.ParentId = parentId; } // read item property values. DaValue[] values = ReadPropertyValues(element.ItemId, m_CoreProperties); // must be an item if the data type property exists. if (values[0].Error >= 0) { element.ElementType = DaElementType.Item; element.DataType = values[0].GetValue<short>(); element.AccessRights = values[1].GetValue<int>(); element.ScanRate = values[2].GetValue<float>(); element.Description = values[3].GetValue<string>(); element.EngineeringUnits = values[4].GetValue<string>(); element.EuInfo = values[5].GetValue<string[]>(); element.EuType = values[6].GetValue<int>(); element.HighEU = values[7].GetValue<double>(); element.LowEU = values[8].GetValue<double>(); element.OpenLabel = values[9].GetValue<string>(); element.CloseLabel = values[10].GetValue<string>(); element.HighIR = values[11].GetValue<double>(); element.LowIR = values[12].GetValue<double>(); // check if the time zone is specified. if (values[13].Error >= 0) { element.TimeZone = values[13].GetValue<int>(); } // check for analog item (checks for HighEU if EuType property not supported). if ((values[7].Error < 0 && values[7].Error >= 0) || element.EuType == (int)OPCEUTYPE.OPC_ANALOG) { element.ElementType = DaElementType.AnalogItem; } // check for enumerated item. else if (element.EuType == (int)OPCEUTYPE.OPC_ENUMERATED) { element.ElementType = DaElementType.EnumeratedItem; } // check for digital item (checks for CloseLabel property). else if (values[10].Error >= 0) { element.ElementType = DaElementType.DigitalItem; } } // the element must be a branch. else { element.ElementType = DaElementType.Branch; // branches could have description property. element.Description = values[3].GetValue<string>(); } }
/// <summary> /// Creates a new element. /// </summary> /// <param name="itemId">The item id.</param> /// <param name="name">The name.</param> /// <param name="parentId">The parent id.</param> /// <returns>The element.</returns> private DaElement CreateElement(string itemId, string name, string parentId) { DaElement element = new DaElement(); element.ItemId = itemId; UpdateElement(element, name, parentId); return element; }
/// <summary> /// Saves the element in cache. /// </summary> /// <param name="element">The element.</param> private void SaveElementInCache(DaElement element) { lock (m_cache) { m_cache[element.ItemId] = element; } }
/// <summary> /// Initializes the node from the element. /// </summary> /// <param name="context">The context.</param> /// <param name="element">The element.</param> /// <param name="namespaceIndex">Index of the namespace.</param> public void Initialize(ISystemContext context, DaElement element, ushort namespaceIndex) { m_element = element; if (element == null) { return; } this.NodeId = DaModelUtils.ConstructIdForDaElement(element.ItemId, -1, namespaceIndex); this.BrowseName = new QualifiedName(element.Name, namespaceIndex); this.DisplayName = new LocalizedText(element.Name); // check if TimeZone is supported. if (element.TimeZone != null) { PropertyState property = this.AddProperty<Range>(Opc.Ua.BrowseNames.LocalTime, DataTypeIds.TimeZoneDataType, ValueRanks.Scalar); property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); property.Value = new Range(element.HighIR, element.LowIR); } // set the TypeDefinition based on the ElementType. switch (element.ElementType) { case DaElementType.AnalogItem: { this.TypeDefinitionId = Opc.Ua.VariableTypeIds.AnalogItemType; // EURange is always present. PropertyState property = this.AddProperty<Range>(Opc.Ua.BrowseNames.EURange, DataTypeIds.Range, ValueRanks.Scalar); property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); property.Value = new Range(element.HighEU, element.LowEU); // check if InstrumentRange is supported. if (element.HighIR != 0 || element.LowIR != 0) { property = this.AddProperty<Range>(Opc.Ua.BrowseNames.InstrumentRange, DataTypeIds.Range, ValueRanks.Scalar); property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); property.Value = new Range(element.HighIR, element.LowIR); } // check if EngineeringUnits is supported. if (element.EngineeringUnits != null) { property = this.AddProperty<EUInformation>(Opc.Ua.BrowseNames.EngineeringUnits, DataTypeIds.EUInformation, ValueRanks.Scalar); property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); // use the server's namespace uri to qualify the engineering units. string namespaceUri = context.NamespaceUris.GetString(namespaceIndex); property.Value = new EUInformation(element.EngineeringUnits, namespaceUri); } break; } case DaElementType.DigitalItem: { this.TypeDefinitionId = Opc.Ua.VariableTypeIds.TwoStateDiscreteType; // check if CloseLabel is supported. if (element.CloseLabel != null) { PropertyState property = this.AddProperty<LocalizedText>(Opc.Ua.BrowseNames.TrueState, DataTypeIds.LocalizedText, ValueRanks.Scalar); property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); property.Value = element.CloseLabel; } // check if OpenLabel is supported. if (element.OpenLabel != null) { PropertyState property = this.AddProperty<LocalizedText>(Opc.Ua.BrowseNames.FalseState, DataTypeIds.LocalizedText, ValueRanks.Scalar); property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); property.Value = element.OpenLabel; } break; } case DaElementType.EnumeratedItem: { this.TypeDefinitionId = Opc.Ua.VariableTypeIds.MultiStateDiscreteType; // check if EuInfo is supported. if (element.EuInfo != null) { PropertyState property = this.AddProperty<LocalizedText[]>(Opc.Ua.BrowseNames.EnumStrings, DataTypeIds.LocalizedText, ValueRanks.OneDimension); property.NodeId = DaModelUtils.ConstructIdForComponent(property, namespaceIndex); LocalizedText[] strings = new LocalizedText[element.EuInfo.Length]; for (int ii = 0; ii < strings.Length; ii++) { strings[ii] = element.EuInfo[ii]; } property.Value = strings; } break; } } if (element.Description != null) { this.Description = element.Description; } this.Value = null; this.StatusCode = StatusCodes.BadWaitingForInitialData; this.Timestamp = DateTime.UtcNow; bool isArray = false; this.DataType = ComUtils.GetDataTypeId(element.DataType, out isArray); this.ValueRank = (isArray)?ValueRanks.OneOrMoreDimensions:ValueRanks.Scalar; this.AccessLevel = AccessLevels.None; if ((element.AccessRights & OpcRcw.Da.Constants.OPC_READABLE) != 0) { this.AccessLevel |= AccessLevels.CurrentRead; } if ((element.AccessRights & OpcRcw.Da.Constants.OPC_WRITEABLE) != 0) { this.AccessLevel |= AccessLevels.CurrentWrite; } this.UserAccessLevel = this.AccessLevel; this.MinimumSamplingInterval = element.ScanRate; }