/// <summary> /// Create new /// </summary> /// <param name="session"></param> /// <param name="codec"></param> /// <returns></returns> internal void Create(Session session, IVariantEncoder codec) { Item = new MonitoredItem { Handle = this, DisplayName = Template.DisplayName, AttributeId = ((uint?)Template.AttributeId) ?? Attributes.Value, IndexRange = Template.IndexRange, RelativePath = Template.RelativePath? .ToRelativePath(session.MessageContext)? .Format(session.NodeCache.TypeTree), MonitoringMode = Template.MonitoringMode.ToStackType() ?? Opc.Ua.MonitoringMode.Reporting, StartNodeId = Template.StartNodeId.ToNodeId(session.MessageContext), QueueSize = Template.QueueSize ?? 0, SamplingInterval = (int?)Template.SamplingInterval?.TotalMilliseconds ?? -1, DiscardOldest = !(Template.DiscardNew ?? false), Filter = Template.DataChangeFilter.ToStackModel() ?? codec.Decode(Template.EventFilter, true) ?? ((MonitoringFilter)Template.AggregateFilter .ToStackModel(session.MessageContext)) }; }
/// <summary> /// Decode with data type as string /// </summary> /// <param name="encoder"></param> /// <param name="value"></param> /// <param name="type"></param> /// <param name="context"></param> /// <returns></returns> public static Variant Decode(this IVariantEncoder encoder, JToken value, string type, ServiceMessageContext context) { return(encoder.Decode(value, string.IsNullOrEmpty(type) || context == null ? BuiltInType.Null : TypeInfo.GetBuiltInType(type.ToNodeId(context)), context)); }
/// <summary> /// Encode extension object /// </summary> /// <param name="codec"></param> /// <param name="result"></param> /// <returns></returns> internal static ExtensionObject DecodeExtensionObject(this IVariantEncoder codec, JToken result) { if (result == null) { return(null); } var variant = codec.Decode(result, BuiltInType.ExtensionObject); return(variant.Value as ExtensionObject); }
/// <summary> /// Convert from service result to diagnostics info /// </summary> /// <param name="result"></param> /// <param name="config"></param> /// <param name="codec"></param> /// <param name="code"></param> /// <returns></returns> public static DiagnosticInfo Decode(this IVariantEncoder codec, ServiceResultModel result, DiagnosticsModel config, out StatusCode code) { if (result == null) { code = StatusCodes.Good; return(null); } code = new StatusCode(result.StatusCode ?? StatusCodes.Good); var results = codec.Decode(result, config); return(results?.LastOrDefault()?.DiagnosticsInfo); }
/// <summary> /// Convert to stack model /// </summary> /// <param name="model"></param> /// <param name="encoder"></param> /// <param name="onlySimpleAttributeOperands"></param> /// <returns></returns> public static ContentFilter Decode(this IVariantEncoder encoder, ContentFilterModel model, bool onlySimpleAttributeOperands = false) { if (model == null) { return(new ContentFilter()); } return(new ContentFilter { Elements = new ContentFilterElementCollection(model.Elements == null ? Enumerable.Empty <ContentFilterElement>() : model.Elements .Select(e => encoder.Decode(e, onlySimpleAttributeOperands))) }); }
/// <summary> /// Convert to stack model /// </summary> /// <param name="model"></param> /// <param name="encoder"></param> /// <param name="onlySimpleAttributeOperands"></param> /// <returns></returns> public static ContentFilterElement Decode(this IVariantEncoder encoder, ContentFilterElementModel model, bool onlySimpleAttributeOperands = false) { if (model == null) { return(null); } return(new ContentFilterElement { FilterOperands = new ExtensionObjectCollection(model?.FilterOperands == null ? Enumerable.Empty <ExtensionObject>() : model.FilterOperands .Select(e => new ExtensionObject( encoder.Decode(e, onlySimpleAttributeOperands)))), FilterOperator = model.FilterOperator.ToStackType() }); }
/// <summary> /// Convert to stack model /// </summary> /// <param name="model"></param> /// <param name="encoder"></param> /// <param name="noDefaultFilter"></param> /// <returns></returns> public static EventFilter Decode(this IVariantEncoder encoder, EventFilterModel model, bool noDefaultFilter = false) { if (model == null || !(model.SelectClauses?.Any() ?? false)) { return(noDefaultFilter ? null : GetDefaultEventFilter()); } return(new EventFilter { SelectClauses = new SimpleAttributeOperandCollection( model.SelectClauses == null ? Enumerable.Empty <SimpleAttributeOperand>() : model.SelectClauses.Select(c => c.ToStackModel(encoder.Context))), // // Per Part 4 only allow simple attribute operands in where clause // elements of event filters. // WhereClause = encoder.Decode(model.WhereClause, true) }); }
/// <summary> /// Convert read event details /// </summary> /// <param name="codec"></param> /// <param name="details"></param> /// <returns></returns> public static JToken Encode(this IVariantEncoder codec, ReadEventsDetailsModel details) { if (details == null) { throw new ArgumentNullException(nameof(details)); } if (details.EndTime == null && details.StartTime == null) { throw new ArgumentException("Start time and end time cannot both be null", nameof(details)); } if ((details.StartTime == null || details.EndTime == null) && ((details.NumEvents ?? 0) == 0)) { throw new ArgumentException("Value bound must be set", nameof(details.NumEvents)); } return(codec.Encode(new ExtensionObject(new ReadEventDetails { EndTime = details.EndTime ?? DateTime.MinValue, StartTime = details.StartTime ?? DateTime.MinValue, Filter = codec.Decode(details.Filter), NumValuesPerNode = details.NumEvents ?? 0 }))); }
/// <summary> /// Convert update event details /// </summary> /// <param name="codec"></param> /// <param name="details"></param> /// <returns></returns> public static JToken Encode(this IVariantEncoder codec, InsertEventsDetailsModel details) { if (details == null) { throw new ArgumentNullException(nameof(details)); } if (details.Events == null || details.Events.Count == 0) { throw new ArgumentException(nameof(details.Events)); } return(codec.Encode(new ExtensionObject(new UpdateEventDetails { NodeId = NodeId.Null, PerformInsertReplace = PerformUpdateType.Insert, Filter = codec.Decode(details.Filter), EventData = new HistoryEventFieldListCollection(details.Events .Select(d => new HistoryEventFieldList { EventFields = new VariantCollection(d.EventFields .Select(f => new Variant(new EncodeableJToken(f)))) })) }))); }
/// <summary> /// Convert to stack model /// </summary> /// <param name="model"></param> /// <param name="encoder"></param> /// <param name="onlySimpleAttributeOperands"></param> /// <returns></returns> public static FilterOperand Decode(this IVariantEncoder encoder, FilterOperandModel model, bool onlySimpleAttributeOperands = false) { if (model == null) { return(null); } if (model.Index != null) { return(new ElementOperand { Index = model.Index.Value }); } if (model.Value != null) { return(new LiteralOperand { Value = encoder.Decode(model.Value, null) }); } if (model.Alias != null && !onlySimpleAttributeOperands) { return(new AttributeOperand { Alias = model.Alias, NodeId = model.NodeId.ToNodeId(encoder.Context), AttributeId = (uint)(model.AttributeId ?? NodeAttribute.Value), BrowsePath = model.BrowsePath.ToRelativePath(encoder.Context), IndexRange = model.IndexRange }); } return(new SimpleAttributeOperand { TypeDefinitionId = model.NodeId.ToNodeId(encoder.Context), AttributeId = (uint)(model.AttributeId ?? NodeAttribute.Value), BrowsePath = new QualifiedNameCollection(model.BrowsePath == null ? Enumerable.Empty <QualifiedName>() : model.BrowsePath?.Select(n => n.ToQualifiedName(encoder.Context))), IndexRange = model.IndexRange }); }
/// <summary> /// Decode nodeset node to node state /// </summary> /// <param name="vertex"></param> /// <param name="dataTypeId"></param> /// <param name="nodeReferences"></param> /// <param name="rolePermissions"></param> /// <param name="userRolePermissions"></param> /// <param name="codec"></param> /// <param name="context"></param> /// <returns></returns> public static BaseNodeModel ToNodeModel(this BaseNodeVertexModel vertex, string dataTypeId, IEnumerable <ReferenceNodeVertexModel> nodeReferences, IEnumerable <RolePermissionEdgeModel> rolePermissions, IEnumerable <RolePermissionEdgeModel> userRolePermissions, IVariantEncoder codec, ServiceMessageContext context) { BaseNodeModel decoded; switch (vertex) { case ObjectNodeVertexModel uaObject: decoded = new ObjectNodeModel(null) { EventNotifier = (byte?)uaObject.EventNotifier }; break; case PropertyNodeVertexModel uaProperty: decoded = new PropertyNodeModel(null) { DataType = dataTypeId.ToNodeId(context), ValueRank = (int?)uaProperty.ValueRank, ArrayDimensions = uaProperty.ArrayDimensions, AccessLevelEx = (uint?)uaProperty.AccessLevel, AccessLevel = uaProperty.AccessLevel == null ? null : (byte?)((uint)uaProperty.AccessLevel.Value & 0xff), UserAccessLevel = uaProperty.UserAccessLevel == null ? null : (byte?)((uint)uaProperty.UserAccessLevel.Value & 0xff), MinimumSamplingInterval = uaProperty.MinimumSamplingInterval, Historizing = uaProperty.Historizing, Value = codec.Decode(uaProperty.Value, uaProperty.BuiltInType, context), TypeDefinitionId = null }; break; case VariableNodeVertexModel uaVariable: decoded = new DataVariableNodeModel(null) { DataType = dataTypeId.ToNodeId(context), ValueRank = (int?)uaVariable.ValueRank, ArrayDimensions = uaVariable.ArrayDimensions, AccessLevelEx = (uint?)uaVariable.AccessLevel, AccessLevel = uaVariable.AccessLevel == null ? null : (byte?)((uint)uaVariable.AccessLevel.Value & 0xFF), UserAccessLevel = uaVariable.UserAccessLevel == null ? null : (byte?)((uint)uaVariable.UserAccessLevel.Value & 0xff), MinimumSamplingInterval = uaVariable.MinimumSamplingInterval, Historizing = uaVariable.Historizing, Value = codec.Decode(uaVariable.Value, uaVariable.BuiltInType, context), TypeDefinitionId = null }; break; case MethodNodeVertexModel uaMethod: decoded = new MethodNodeModel(null) { Executable = uaMethod.Executable ?? false, UserExecutable = uaMethod.UserExecutable ?? false, TypeDefinitionId = null }; break; case ViewNodeVertexModel uaView: decoded = new ViewNodeModel { ContainsNoLoops = uaView.ContainsNoLoops }; break; case ObjectTypeNodeVertexModel uaObjectType: decoded = new ObjectTypeNodeModel { IsAbstract = uaObjectType.IsAbstract }; break; case PropertyTypeNodeVertexModel uaPropertyType: decoded = new PropertyTypeNodeModel { IsAbstract = uaPropertyType.IsAbstract, DataType = dataTypeId.ToNodeId(context), ValueRank = (int?)uaPropertyType.ValueRank, ArrayDimensions = uaPropertyType.ArrayDimensions, Value = codec.Decode(uaPropertyType.Value, uaPropertyType.BuiltInType, context) }; break; case VariableTypeNodeVertexModel uaVariableType: decoded = new DataVariableTypeNodeModel { IsAbstract = uaVariableType.IsAbstract, DataType = dataTypeId.ToNodeId(context), ValueRank = (int?)uaVariableType.ValueRank, ArrayDimensions = uaVariableType.ArrayDimensions, Value = codec.Decode(uaVariableType.Value, uaVariableType.BuiltInType, context) }; break; case DataTypeNodeVertexModel uaDataType: decoded = new DataTypeNodeModel { IsAbstract = uaDataType.IsAbstract, Definition = uaDataType.DataTypeDefinition == null ? null : (DataTypeDefinition)(codec.Decode(uaDataType.DataTypeDefinition, BuiltInType.ExtensionObject, context).Value as ExtensionObject)?.Body, Purpose = Opc.Ua.Nodeset.Schema.DataTypePurpose.Normal }; break; case ReferenceTypeNodeVertexModel uaReferenceType: decoded = new ReferenceTypeNodeModel { IsAbstract = uaReferenceType.IsAbstract, InverseName = uaReferenceType.InverseName.ToLocalizedText(), Symmetric = uaReferenceType.Symmetric }; break; default: return(null); } decoded.NodeId = vertex.NodeId; decoded.BrowseName = vertex.BrowseName.ToQualifiedName(context); decoded.DisplayName = vertex.DisplayName.ToLocalizedText(); decoded.Description = vertex.Description.ToLocalizedText(); decoded.WriteMask = (AttributeWriteMask)vertex.WriteMask; decoded.UserWriteMask = (AttributeWriteMask)vertex.UserWriteMask; decoded.RolePermissions = rolePermissions? .Select(r => new RolePermissionType { Permissions = (uint)(PermissionType)(r.Permissions ?? 0), RoleId = r.RoleId.ToNodeId(context) }) .ToList(); decoded.UserRolePermissions = userRolePermissions? .Select(r => new RolePermissionType { Permissions = (uint)(PermissionType)(r.Permissions ?? 0), RoleId = r.RoleId.ToNodeId(context) }) .ToList(); if (!string.IsNullOrEmpty(vertex.SymbolicName)) { decoded.SymbolicName = vertex.SymbolicName; } // Decode references var references = new List <IReference>(); if (nodeReferences != null) { foreach (var reference in nodeReferences) { var referenceTypeId = reference.ReferenceTypeId.ToNodeId(context); var isInverse = reference.TargetId == vertex.NodeId; var targetId = isInverse ? reference.OriginId.ToNodeId(context) : reference.TargetId.ToNodeId(context); if (decoded is InstanceNodeModel instance) { if (referenceTypeId == ReferenceTypeIds.HasModellingRule && !isInverse) { instance.ModellingRuleId = ExpandedNodeId.ToNodeId( targetId, context.NamespaceUris); continue; } if (referenceTypeId == ReferenceTypeIds.HasTypeDefinition && !isInverse) { instance.TypeDefinitionId = ExpandedNodeId.ToNodeId( targetId, context.NamespaceUris); continue; } } if (decoded is TypeNodeModel type) { if (referenceTypeId == ReferenceTypeIds.HasSubtype && isInverse) { type.SuperTypeId = ExpandedNodeId.ToNodeId(targetId, context.NamespaceUris); continue; } } references.Add(new NodeStateReference(referenceTypeId, isInverse, targetId)); } } decoded.AddReferences(references); return(decoded); }
/// <summary> /// Parse token to variant /// </summary> /// <param name="encoder"></param> /// <param name="value"></param> /// <returns></returns> public static Variant Decode(this IVariantEncoder encoder, JToken value) { return(encoder.Decode(value, BuiltInType.Null)); }
/// <summary> /// Decode with data type as string /// </summary> /// <param name="encoder"></param> /// <param name="value"></param> /// <param name="type"></param> /// <returns></returns> public static Variant Decode(this IVariantEncoder encoder, VariantValue value, string type) { return(encoder.Decode(value, string.IsNullOrEmpty(type) ? BuiltInType.Null : TypeInfo.GetBuiltInType(type.ToNodeId(encoder.Context)))); }