/// <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 the node from the element. /// </summary> /// <param name="context">The context.</param> /// <param name="itemId">The item id.</param> /// <param name="property">The property.</param> /// <param name="namespaceIndex">Index of the namespace.</param> public void Initialize(ISystemContext context, string itemId, DaProperty property, ushort namespaceIndex) { m_itemId = itemId; m_property = property; if (property == null) { return; } this.NodeId = ModelUtils.ConstructIdForDaElement(m_itemId, property.PropertyId, namespaceIndex); this.BrowseName = new QualifiedName(property.Name, namespaceIndex); this.DisplayName = new LocalizedText(property.Name); this.TypeDefinitionId = Opc.Ua.VariableTypeIds.PropertyType; this.Value = null; this.StatusCode = StatusCodes.BadWaitingForInitialData; this.Timestamp = DateTime.UtcNow; bool isArray = false; this.DataType = ComUtils.GetDataTypeId(property.DataType, out isArray); this.ValueRank = (isArray)?ValueRanks.OneOrMoreDimensions:ValueRanks.Scalar; this.ArrayDimensions = null; // assume that properties with item ids are writeable. the server may still reject the write. if (String.IsNullOrEmpty(property.ItemId)) { this.AccessLevel = AccessLevels.CurrentRead; } else { this.AccessLevel = AccessLevels.CurrentReadOrWrite; } this.UserAccessLevel = this.AccessLevel; this.MinimumSamplingInterval = MinimumSamplingIntervals.Indeterminate; this.Historizing = false; // add a reference to the parent node. NodeId parentNodeId = ModelUtils.ConstructIdForDaElement(itemId, -1, namespaceIndex); this.AddReference(ReferenceTypeIds.HasProperty, true, parentNodeId); }
/// <summary> /// Validates the items. /// </summary> /// <param name="group">The group.</param> /// <param name="requests">The requests.</param> /// <returns>The items. May contain null is validation failed.</returns> public ComDaGroupItem[] ValidateItems(ComDaGroup group, ComDaCreateItemRequest[] requests) { TraceState("ValidateItems", group.Name); // get the session to use for the operation. Session session = m_session; if (session == null) { throw ComUtils.CreateComException(ResultIds.E_FAIL); } // validate items. ComDaGroupItem[] items = new ComDaGroupItem[requests.Length]; for (int ii = 0; ii < requests.Length; ii += 10000) { ValidateItems(session, group, requests, items, ii, 10000); } // process results. for (int ii = 0; ii < requests.Length; ii++) { // check for the results. ComDaCreateItemRequest request = requests[ii]; if (request.Error < 0) { items[ii] = null; continue; } // check access path. if (!String.IsNullOrEmpty(request.AccessPath)) { items[ii] = null; request.Error = ResultIds.E_UNKNOWNPATH; continue; } ComDaGroupItem item = items[ii]; // validate the datatype. if (request.RequestedDataType != 0) { NodeId dataTypeId = ComUtils.GetDataTypeId(request.RequestedDataType); if (NodeId.IsNull(dataTypeId)) { items[ii] = null; request.Error = ResultIds.E_BADTYPE; continue; } bool reqTypeIsArray = (request.RequestedDataType & (short)VarEnum.VT_ARRAY) != 0; bool actualTypeIsArray = (item.CanonicalDataType & (short)VarEnum.VT_ARRAY) != 0; if (reqTypeIsArray != actualTypeIsArray) { items[ii] = null; request.Error = ResultIds.E_BADTYPE; continue; } } // create a new monitored item. MonitoredItem monitoredItem = new MonitoredItem(); monitoredItem.StartNodeId = item.NodeId; monitoredItem.RelativePath = null; monitoredItem.AttributeId = Attributes.Value; monitoredItem.MonitoringMode = (request.Active)?MonitoringMode.Reporting:MonitoringMode.Disabled; monitoredItem.SamplingInterval = group.UpdateRate / 2; monitoredItem.QueueSize = 0; monitoredItem.DiscardOldest = true; monitoredItem.Filter = null; // update item. item.ServerHandle = (int)monitoredItem.ClientHandle; item.MonitoredItem = monitoredItem; // link the monitored item back to the group item. monitoredItem.Handle = item; // update return parameters. request.ServerHandle = item.ServerHandle; request.CanonicalDataType = item.CanonicalDataType; request.AccessRights = item.AccessRights; request.Error = ResultIds.S_OK; } return(items); }
/// <summary> /// Initializes a new instance of the <see cref="AeEventTypeState"/> class. /// </summary> public AeEventTypeState(EventType eventType, ushort namespaceIndex) { m_eventType = eventType; // create the name for the event type. string name = eventType.Description; if (!String.IsNullOrEmpty(eventType.ConditionName)) { name = eventType.ConditionName; } if (!name.EndsWith("Type")) { if (eventType.EventTypeId == OpcRcw.Ae.Constants.CONDITION_EVENT) { name += "AlarmType"; } else { name += "EventType"; } } // the attributes. this.NodeId = AeParsedNodeId.Construct(eventType, null, namespaceIndex); this.BrowseName = new QualifiedName(name, namespaceIndex); this.DisplayName = eventType.Description; this.IsAbstract = false; this.SuperTypeId = AeParsedNodeId.Construct(eventType.EventTypeMapping, namespaceIndex); // add the attributes as properties. if (eventType.Attributes != null) { for (int ii = 0; ii < eventType.Attributes.Count; ii++) { string propertyName = eventType.Attributes[ii].Description; if (AeTypeCache.IsKnownName(propertyName, "ACK COMMENT")) { continue; } PropertyState property = new PropertyState(this); property.SymbolicName = propertyName; property.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasProperty; property.TypeDefinitionId = Opc.Ua.VariableTypeIds.PropertyType; property.ModellingRuleId = Opc.Ua.ObjectIds.ModellingRule_Optional; property.NodeId = AeParsedNodeId.Construct(eventType, propertyName, namespaceIndex); property.BrowseName = new QualifiedName(propertyName, namespaceIndex); property.DisplayName = property.BrowseName.Name; property.AccessLevel = AccessLevels.None; property.UserAccessLevel = AccessLevels.None; property.MinimumSamplingInterval = MinimumSamplingIntervals.Indeterminate; property.Historizing = false; bool isArray = false; property.DataType = ComUtils.GetDataTypeId(eventType.Attributes[ii].VarType, out isArray); property.ValueRank = (isArray) ? ValueRanks.OneDimension : ValueRanks.Scalar; this.AddChild(property); } } }
/// <summary> /// Gets the result for the read operayoin. /// </summary> /// <param name="context">The context.</param> /// <param name="item">The item.</param> /// <param name="nodeToRead">The node to read.</param> /// <param name="value">The value.</param> /// <param name="diagnosticsMasks">The diagnostics masks.</param> /// <returns></returns> public ServiceResult GetResult( ISystemContext context, DaItemState item, ReadValueId nodeToRead, DataValue value, DiagnosticsMasks diagnosticsMasks) { if (nodeToRead.AttributeId == Attributes.Value) { ServiceResult result = GetItemValue(m_value, value, diagnosticsMasks); if (ServiceResult.IsBad(result)) { return(result); } return(ApplyIndexRangeAndDataEncoding(context, nodeToRead, value)); } switch (nodeToRead.AttributeId) { case Attributes.Description: { string description = this.GetPropertyValue <string>(Opc.Ua.Com.PropertyIds.Description, value, false); if (StatusCode.IsGood(value.StatusCode)) { value.Value = new LocalizedText(description); } break; } case Attributes.DataType: { short datatype = this.GetPropertyValue <short>(Opc.Ua.Com.PropertyIds.DataType, value, false); if (StatusCode.IsGood(value.StatusCode)) { value.Value = ComUtils.GetDataTypeId(datatype); } break; } case Attributes.ValueRank: { short datatype = this.GetPropertyValue <short>(Opc.Ua.Com.PropertyIds.DataType, value, false); if (StatusCode.IsGood(value.StatusCode)) { value.Value = ComUtils.GetValueRank(datatype); } break; } case Attributes.AccessLevel: case Attributes.UserAccessLevel: { int accessRights = this.GetPropertyValue <int>(Opc.Ua.Com.PropertyIds.AccessRights, value, false); if (StatusCode.IsGood(value.StatusCode)) { value.Value = (byte)accessRights; } break; } case Attributes.MinimumSamplingInterval: { float scanRate = this.GetPropertyValue <float>(Opc.Ua.Com.PropertyIds.ScanRate, value, false); if (StatusCode.IsGood(value.StatusCode)) { value.Value = (double)scanRate; } break; } default: { return(StatusCodes.BadAttributeIdInvalid); } } // check if the property value is missing. if (value.StatusCode == StatusCodes.BadNotFound) { return(StatusCodes.BadAttributeIdInvalid); } return(ApplyIndexRangeAndDataEncoding(context, nodeToRead, value)); }
/// <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; }
/// <summary> /// Gets the result for the read operayoin. /// </summary> /// <param name="context">The context.</param> /// <param name="item">The item.</param> /// <param name="nodeToRead">The node to read.</param> /// <param name="value">The value.</param> /// <param name="diagnosticsMasks">The diagnostics masks.</param> /// <returns></returns> public ServiceResult GetResult( ISystemContext context, HdaItemState item, ReadValueId nodeToRead, DataValue value, DiagnosticsMasks diagnosticsMasks) { switch (nodeToRead.AttributeId) { case Attributes.Description: { string description = this.GetAttributeValue <string>(Constants.OPCHDA_DESCRIPTION, value, false); if (StatusCode.IsGood(value.StatusCode)) { value.Value = new LocalizedText(description); } break; } case Attributes.DataType: { short datatype = this.GetAttributeValue <short>(Constants.OPCHDA_DATA_TYPE, value, false); if (StatusCode.IsGood(value.StatusCode)) { value.Value = ComUtils.GetDataTypeId(datatype); } else { value.Value = DataTypeIds.BaseDataType; value.StatusCode = StatusCodes.GoodLocalOverride; } break; } case Attributes.ValueRank: { short datatype = this.GetAttributeValue <short>(Constants.OPCHDA_DATA_TYPE, value, false); if (StatusCode.IsGood(value.StatusCode)) { value.Value = ComUtils.GetValueRank(datatype); } else { value.Value = ValueRanks.Any; value.StatusCode = StatusCodes.GoodLocalOverride; } break; } case Attributes.Historizing: { bool archiving = this.GetAttributeValue <bool>(Constants.OPCHDA_ARCHIVING, value, false); if (StatusCode.IsGood(value.StatusCode)) { value.Value = archiving; } else { value.Value = false; value.StatusCode = StatusCodes.GoodLocalOverride; } break; } default: { return(StatusCodes.BadAttributeIdInvalid); } } // check if the attribute value is missing. if (value.StatusCode == StatusCodes.BadNotFound) { return(StatusCodes.BadAttributeIdInvalid); } return(ApplyIndexRangeAndDataEncoding(context, nodeToRead, value)); }
/// <summary> /// Initializes a new instance of the <see cref="DaItemState"/> class. /// </summary> /// <param name="configuration">The configuration.</param> /// <param name="itemId">The item id.</param> /// <param name="attribute">The attribute.</param> /// <param name="namespaceIndex">Index of the namespace.</param> public HdaAttributeState( ComHdaClientConfiguration configuration, string itemId, HdaAttribute attribute, ushort namespaceIndex) : base(null) { m_itemId = itemId; m_attribute = attribute; this.NodeId = HdaModelUtils.ConstructIdForHdaItemAttribute(itemId, attribute.Id, namespaceIndex); this.SymbolicName = attribute.Id.ToString(); this.Description = attribute.Description; this.AccessLevel = AccessLevels.CurrentRead; this.UserAccessLevel = AccessLevels.CurrentRead; this.MinimumSamplingInterval = MinimumSamplingIntervals.Indeterminate; this.Historizing = false; this.ReferenceTypeId = Opc.Ua.ReferenceTypeIds.HasProperty; this.TypeDefinitionId = Opc.Ua.VariableTypeIds.PropertyType; this.Value = null; this.StatusCode = StatusCodes.BadWaitingForInitialData; bool isConfigItem = false; // handle built-in properties. switch (attribute.Id) { default: { bool isArray = false; this.BrowseName = new QualifiedName(this.SymbolicName, namespaceIndex); this.DisplayName = attribute.Name; this.DataType = ComUtils.GetDataTypeId(attribute.DataType, out isArray); this.ValueRank = (isArray)?ValueRanks.OneDimension:ValueRanks.Scalar; break; } case Constants.OPCHDA_ENG_UNITS: { this.BrowseName = Opc.Ua.BrowseNames.EngineeringUnits; this.DisplayName = this.BrowseName.Name; this.DataType = Opc.Ua.DataTypeIds.EUInformation; this.ValueRank = ValueRanks.Scalar; break; } case Constants.OPCHDA_NORMAL_MAXIMUM: { this.BrowseName = Opc.Ua.BrowseNames.EURange; this.DisplayName = this.BrowseName.Name; this.DataType = Opc.Ua.DataTypeIds.Range; this.ValueRank = ValueRanks.Scalar; break; } case Constants.OPCHDA_HIGH_ENTRY_LIMIT: { this.BrowseName = Opc.Ua.BrowseNames.InstrumentRange; this.DisplayName = this.BrowseName.Name; this.DataType = Opc.Ua.DataTypeIds.Range; this.ValueRank = ValueRanks.Scalar; break; } case Constants.OPCHDA_STEPPED: { this.BrowseName = Opc.Ua.BrowseNames.Stepped; this.DisplayName = this.BrowseName.Name; this.DataType = Opc.Ua.DataTypeIds.Boolean; this.ValueRank = ValueRanks.Scalar; isConfigItem = true; break; } case Constants.OPCHDA_DERIVE_EQUATION: { this.BrowseName = Opc.Ua.BrowseNames.Definition; this.DisplayName = this.BrowseName.Name; this.DataType = Opc.Ua.DataTypeIds.String; this.ValueRank = ValueRanks.Scalar; isConfigItem = true; break; } case Constants.OPCHDA_MIN_TIME_INT: { this.BrowseName = Opc.Ua.BrowseNames.MinTimeInterval; this.DisplayName = this.BrowseName.Name; this.DataType = Opc.Ua.DataTypeIds.Duration; this.ValueRank = ValueRanks.Scalar; isConfigItem = true; break; } case Constants.OPCHDA_MAX_TIME_INT: { this.BrowseName = Opc.Ua.BrowseNames.MaxTimeInterval; this.DisplayName = this.BrowseName.Name; this.DataType = Opc.Ua.DataTypeIds.Duration; this.ValueRank = ValueRanks.Scalar; isConfigItem = true; break; } case Constants.OPCHDA_EXCEPTION_DEV: { this.BrowseName = Opc.Ua.BrowseNames.ExceptionDeviation; this.DisplayName = this.BrowseName.Name; this.DataType = Opc.Ua.DataTypeIds.Double; this.ValueRank = ValueRanks.Scalar; isConfigItem = true; break; } case Constants.OPCHDA_EXCEPTION_DEV_TYPE: { this.BrowseName = Opc.Ua.BrowseNames.ExceptionDeviationFormat; this.DisplayName = this.BrowseName.Name; this.DataType = Opc.Ua.DataTypeIds.ExceptionDeviationFormat; this.ValueRank = ValueRanks.Scalar; isConfigItem = true; break; } } // set the parent id. NodeId parentId = null; if (isConfigItem) { parentId = HdaParsedNodeId.Construct(HdaModelUtils.HdaItemConfiguration, itemId, null, namespaceIndex); } else { parentId = HdaModelUtils.ConstructIdForHdaItem(itemId, namespaceIndex); } this.AddReference(ReferenceTypeIds.HasProperty, true, parentId); }