|
|
@@ -0,0 +1,422 @@
|
|
|
+using System;
|
|
|
+using System.Collections;
|
|
|
+using System.Collections.Generic;
|
|
|
+using Opc.Ua;
|
|
|
+using Opc.Ua.Client;
|
|
|
+
|
|
|
+
|
|
|
+namespace IMCS_CCS.Utils.DeviceProtocol
|
|
|
+{
|
|
|
+ public class FilterDefinition
|
|
|
+ {
|
|
|
+ public NodeId AreaId;
|
|
|
+ public EventSeverity Severity;
|
|
|
+ public IList<NodeId> EventTypes;
|
|
|
+ public bool IgnoreSuppressedOrShelved;
|
|
|
+ public SimpleAttributeOperandCollection SelectClauses;
|
|
|
+
|
|
|
+ public MonitoredItem CreateMonitoredItem(Session session)
|
|
|
+ {
|
|
|
+ if (this.AreaId == (object)null)
|
|
|
+ this.AreaId = ObjectIds.Server;
|
|
|
+ return new MonitoredItem()
|
|
|
+ {
|
|
|
+ DisplayName = (string)null,
|
|
|
+ StartNodeId = this.AreaId,
|
|
|
+ RelativePath = (string)null,
|
|
|
+ NodeClass = NodeClass.Object,
|
|
|
+ AttributeId = 12,
|
|
|
+ IndexRange = (string)null,
|
|
|
+ Encoding = (QualifiedName)null,
|
|
|
+ MonitoringMode = MonitoringMode.Reporting,
|
|
|
+ SamplingInterval = 0,
|
|
|
+ QueueSize = uint.MaxValue,
|
|
|
+ DiscardOldest = true,
|
|
|
+ Filter = (MonitoringFilter)this.ConstructFilter(session),
|
|
|
+ Handle = (object)this
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ public SimpleAttributeOperandCollection ConstructSelectClauses(
|
|
|
+ Session session,
|
|
|
+ params NodeId[] eventTypeIds)
|
|
|
+ {
|
|
|
+ SimpleAttributeOperandCollection eventFields = new SimpleAttributeOperandCollection();
|
|
|
+ eventFields.Add(new SimpleAttributeOperand()
|
|
|
+ {
|
|
|
+ TypeDefinitionId = ObjectTypeIds.BaseEventType,
|
|
|
+ AttributeId = 1U,
|
|
|
+ BrowsePath = new QualifiedNameCollection()
|
|
|
+ });
|
|
|
+ if (eventTypeIds != null)
|
|
|
+ {
|
|
|
+ for (int index = 0; index < eventTypeIds.Length; ++index)
|
|
|
+ this.CollectFields(session, eventTypeIds[index], eventFields);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ this.CollectFields(session, ObjectTypeIds.BaseEventType, eventFields);
|
|
|
+ return eventFields;
|
|
|
+ }
|
|
|
+
|
|
|
+ public EventFilter ConstructFilter(Session session)
|
|
|
+ {
|
|
|
+ EventFilter eventFilter = new EventFilter();
|
|
|
+ eventFilter.SelectClauses = this.SelectClauses;
|
|
|
+ ContentFilter contentFilter = new ContentFilter();
|
|
|
+ ContentFilterElement contentFilterElement1 = (ContentFilterElement)null;
|
|
|
+ if (this.Severity > EventSeverity.Min)
|
|
|
+ {
|
|
|
+ SimpleAttributeOperand attributeOperand = new SimpleAttributeOperand();
|
|
|
+ attributeOperand.TypeDefinitionId = ObjectTypeIds.BaseEventType;
|
|
|
+ attributeOperand.BrowsePath.Add((QualifiedName)"Severity");
|
|
|
+ attributeOperand.AttributeId = 13U;
|
|
|
+ contentFilterElement1 = contentFilter.Push(FilterOperator.GreaterThanOrEqual, (object)attributeOperand, (object)new LiteralOperand()
|
|
|
+ {
|
|
|
+ Value = new Variant((ushort)this.Severity)
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (!this.IgnoreSuppressedOrShelved)
|
|
|
+ {
|
|
|
+ SimpleAttributeOperand attributeOperand = new SimpleAttributeOperand();
|
|
|
+ attributeOperand.TypeDefinitionId = ObjectTypeIds.BaseEventType;
|
|
|
+ attributeOperand.BrowsePath.Add((QualifiedName)"SuppressedOrShelved");
|
|
|
+ attributeOperand.AttributeId = 13U;
|
|
|
+ ContentFilterElement contentFilterElement2 = contentFilter.Push(FilterOperator.Equals, (object)attributeOperand, (object)new LiteralOperand()
|
|
|
+ {
|
|
|
+ Value = new Variant(false)
|
|
|
+ });
|
|
|
+ if (contentFilterElement1 != null)
|
|
|
+ contentFilterElement1 = contentFilter.Push(FilterOperator.And, (object)contentFilterElement1, (object)contentFilterElement2);
|
|
|
+ else
|
|
|
+ contentFilterElement1 = contentFilterElement2;
|
|
|
+ }
|
|
|
+ if (this.EventTypes != null && this.EventTypes.Count > 0)
|
|
|
+ {
|
|
|
+ ContentFilterElement contentFilterElement2 = (ContentFilterElement)null;
|
|
|
+ for (int index = 0; index < this.EventTypes.Count; ++index)
|
|
|
+ {
|
|
|
+ ContentFilterElement contentFilterElement3 = contentFilter.Push(FilterOperator.OfType, (object)new LiteralOperand()
|
|
|
+ {
|
|
|
+ Value = new Variant(this.EventTypes[index])
|
|
|
+ });
|
|
|
+ if (contentFilterElement2 != null)
|
|
|
+ contentFilterElement2 = contentFilter.Push(FilterOperator.Or, (object)contentFilterElement2, (object)contentFilterElement3);
|
|
|
+ else
|
|
|
+ contentFilterElement2 = contentFilterElement3;
|
|
|
+ }
|
|
|
+ if (contentFilterElement1 != null)
|
|
|
+ contentFilter.Push(FilterOperator.And, (object)contentFilterElement1, (object)contentFilterElement2);
|
|
|
+ }
|
|
|
+ eventFilter.WhereClause = contentFilter;
|
|
|
+ return eventFilter;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void CollectFields(
|
|
|
+ Session session,
|
|
|
+ NodeId eventTypeId,
|
|
|
+ SimpleAttributeOperandCollection eventFields)
|
|
|
+ {
|
|
|
+ ReferenceDescriptionCollection descriptionCollection = FormUtils.BrowseSuperTypes(session, eventTypeId, false);
|
|
|
+ if (descriptionCollection == null)
|
|
|
+ return;
|
|
|
+ Dictionary<NodeId, QualifiedNameCollection> foundNodes = new Dictionary<NodeId, QualifiedNameCollection>();
|
|
|
+ QualifiedNameCollection parentPath = new QualifiedNameCollection();
|
|
|
+ for (int index = descriptionCollection.Count - 1; index >= 0; --index)
|
|
|
+ this.CollectFields(session, (NodeId)descriptionCollection[index].NodeId, parentPath, eventFields, foundNodes);
|
|
|
+ this.CollectFields(session, eventTypeId, parentPath, eventFields, foundNodes);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void CollectFields(
|
|
|
+ Session session,
|
|
|
+ NodeId nodeId,
|
|
|
+ QualifiedNameCollection parentPath,
|
|
|
+ SimpleAttributeOperandCollection eventFields,
|
|
|
+ Dictionary<NodeId, QualifiedNameCollection> foundNodes)
|
|
|
+ {
|
|
|
+ ReferenceDescriptionCollection descriptionCollection = FormUtils.Browse(session, new BrowseDescription()
|
|
|
+ {
|
|
|
+ NodeId = nodeId,
|
|
|
+ BrowseDirection = BrowseDirection.Forward,
|
|
|
+ ReferenceTypeId = ReferenceTypeIds.Aggregates,
|
|
|
+ IncludeSubtypes = true,
|
|
|
+ NodeClassMask = 3U,
|
|
|
+ ResultMask = 63U
|
|
|
+ }, false);
|
|
|
+ if (descriptionCollection == null)
|
|
|
+ return;
|
|
|
+ for (int index = 0; index < descriptionCollection.Count; ++index)
|
|
|
+ {
|
|
|
+ ReferenceDescription referenceDescription = descriptionCollection[index];
|
|
|
+ if (!referenceDescription.NodeId.IsAbsolute)
|
|
|
+ {
|
|
|
+ QualifiedNameCollection qualifiedNameCollection = new QualifiedNameCollection((IEnumerable<QualifiedName>)parentPath);
|
|
|
+ qualifiedNameCollection.Add(referenceDescription.BrowseName);
|
|
|
+ if (!this.ContainsPath(eventFields, qualifiedNameCollection))
|
|
|
+ eventFields.Add(new SimpleAttributeOperand()
|
|
|
+ {
|
|
|
+ TypeDefinitionId = ObjectTypeIds.BaseEventType,
|
|
|
+ BrowsePath = qualifiedNameCollection,
|
|
|
+ AttributeId = referenceDescription.NodeClass == NodeClass.Variable ? 13U : 1U
|
|
|
+ });
|
|
|
+ NodeId nodeId1 = (NodeId)referenceDescription.NodeId;
|
|
|
+ if (!foundNodes.ContainsKey(nodeId1))
|
|
|
+ {
|
|
|
+ foundNodes.Add(nodeId1, qualifiedNameCollection);
|
|
|
+ this.CollectFields(session, (NodeId)referenceDescription.NodeId, qualifiedNameCollection, eventFields, foundNodes);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private bool ContainsPath(
|
|
|
+ SimpleAttributeOperandCollection selectClause,
|
|
|
+ QualifiedNameCollection browsePath)
|
|
|
+ {
|
|
|
+ for (int index1 = 0; index1 < selectClause.Count; ++index1)
|
|
|
+ {
|
|
|
+ SimpleAttributeOperand attributeOperand = selectClause[index1];
|
|
|
+ if (attributeOperand.BrowsePath.Count == browsePath.Count)
|
|
|
+ {
|
|
|
+ bool flag = true;
|
|
|
+ for (int index2 = 0; index2 < attributeOperand.BrowsePath.Count; ++index2)
|
|
|
+ {
|
|
|
+ if (attributeOperand.BrowsePath[index2] != browsePath[index2])
|
|
|
+ {
|
|
|
+ flag = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (flag)
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public static class FormUtils
|
|
|
+ {
|
|
|
+ public static NodeId[] KnownEventTypes = new NodeId[8]
|
|
|
+ {
|
|
|
+ ObjectTypeIds.BaseEventType,
|
|
|
+ ObjectTypeIds.ConditionType,
|
|
|
+ ObjectTypeIds.DialogConditionType,
|
|
|
+ ObjectTypeIds.AlarmConditionType,
|
|
|
+ ObjectTypeIds.ExclusiveLimitAlarmType,
|
|
|
+ ObjectTypeIds.NonExclusiveLimitAlarmType,
|
|
|
+ ObjectTypeIds.AuditEventType,
|
|
|
+ ObjectTypeIds.AuditUpdateMethodEventType
|
|
|
+ };
|
|
|
+
|
|
|
+ public static EndpointDescription SelectEndpoint(
|
|
|
+ string discoveryUrl,
|
|
|
+ bool useSecurity)
|
|
|
+ {
|
|
|
+ if (!discoveryUrl.StartsWith("opc.tcp") && !discoveryUrl.EndsWith("/discovery"))
|
|
|
+ discoveryUrl += "/discovery";
|
|
|
+ Uri discoveryUrl1 = new Uri(discoveryUrl);
|
|
|
+ EndpointConfiguration configuration = EndpointConfiguration.Create();
|
|
|
+ configuration.OperationTimeout = 5000;
|
|
|
+ EndpointDescription endpointDescription1 = (EndpointDescription)null;
|
|
|
+ using (DiscoveryClient discoveryClient = DiscoveryClient.Create(discoveryUrl1, configuration))
|
|
|
+ {
|
|
|
+ EndpointDescriptionCollection endpoints = discoveryClient.GetEndpoints((StringCollection)null);
|
|
|
+ for (int index = 0; index < endpoints.Count; ++index)
|
|
|
+ {
|
|
|
+ EndpointDescription endpointDescription2 = endpoints[index];
|
|
|
+ if (endpointDescription2.EndpointUrl.StartsWith(discoveryUrl1.Scheme))
|
|
|
+ {
|
|
|
+ if (endpointDescription1 == null)
|
|
|
+ endpointDescription1 = endpointDescription2;
|
|
|
+ if (useSecurity)
|
|
|
+ {
|
|
|
+ if (endpointDescription2.SecurityMode != MessageSecurityMode.None && (int)endpointDescription2.SecurityLevel > (int)endpointDescription1.SecurityLevel)
|
|
|
+ endpointDescription1 = endpointDescription2;
|
|
|
+ }
|
|
|
+ else if (endpointDescription2.SecurityMode == MessageSecurityMode.None)
|
|
|
+ endpointDescription1 = endpointDescription2;
|
|
|
+ }
|
|
|
+ if (endpointDescription1 == null && endpoints.Count > 0)
|
|
|
+ endpointDescription1 = endpoints[0];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Uri uri = Opc.Ua.Utils.ParseUri(endpointDescription1.EndpointUrl);
|
|
|
+ if (uri != (Uri)null && uri.Scheme == discoveryUrl1.Scheme)
|
|
|
+ endpointDescription1.EndpointUrl = new UriBuilder(uri)
|
|
|
+ {
|
|
|
+ Host = discoveryUrl1.DnsSafeHost,
|
|
|
+ Port = discoveryUrl1.Port
|
|
|
+ }.ToString();
|
|
|
+ return endpointDescription1;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static NodeId FindEventType(
|
|
|
+ MonitoredItem monitoredItem,
|
|
|
+ EventFieldList notification)
|
|
|
+ {
|
|
|
+ EventFilter filter = monitoredItem.Status.Filter as EventFilter;
|
|
|
+ if (filter != null)
|
|
|
+ {
|
|
|
+ for (int index = 0; index < filter.SelectClauses.Count; ++index)
|
|
|
+ {
|
|
|
+ SimpleAttributeOperand selectClause = filter.SelectClauses[index];
|
|
|
+ if (selectClause.BrowsePath.Count == 1 && selectClause.BrowsePath[0] == (QualifiedName)"EventType")
|
|
|
+ return notification.EventFields[index].Value as NodeId;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return (NodeId)null;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static BaseEventState ConstructEvent(
|
|
|
+ Session session,
|
|
|
+ MonitoredItem monitoredItem,
|
|
|
+ EventFieldList notification,
|
|
|
+ Dictionary<NodeId, NodeId> eventTypeMappings)
|
|
|
+ {
|
|
|
+ NodeId eventType = FormUtils.FindEventType(monitoredItem, notification);
|
|
|
+ if (eventType == (object)null)
|
|
|
+ return (BaseEventState)null;
|
|
|
+ NodeId nodeId = (NodeId)null;
|
|
|
+ if (!eventTypeMappings.TryGetValue(eventType, out nodeId))
|
|
|
+ {
|
|
|
+ for (int index = 0; index < FormUtils.KnownEventTypes.Length; ++index)
|
|
|
+ {
|
|
|
+ if (FormUtils.KnownEventTypes[index] == (object)eventType)
|
|
|
+ {
|
|
|
+ nodeId = eventType;
|
|
|
+ eventTypeMappings.Add(eventType, eventType);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (nodeId == (object)null)
|
|
|
+ {
|
|
|
+ ReferenceDescriptionCollection descriptionCollection = FormUtils.BrowseSuperTypes(session, eventType, false);
|
|
|
+ if (descriptionCollection == null)
|
|
|
+ return (BaseEventState)null;
|
|
|
+ for (int index1 = 0; index1 < descriptionCollection.Count; ++index1)
|
|
|
+ {
|
|
|
+ for (int index2 = 0; index2 < FormUtils.KnownEventTypes.Length; ++index2)
|
|
|
+ {
|
|
|
+ if (FormUtils.KnownEventTypes[index2] == (object)descriptionCollection[index1].NodeId)
|
|
|
+ {
|
|
|
+ nodeId = FormUtils.KnownEventTypes[index2];
|
|
|
+ eventTypeMappings.Add(eventType, nodeId);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (nodeId != (object)null)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (nodeId == (object)null)
|
|
|
+ return (BaseEventState)null;
|
|
|
+ uint? identifier = nodeId.Identifier as uint?;
|
|
|
+ if (!identifier.HasValue)
|
|
|
+ return (BaseEventState)null;
|
|
|
+ BaseEventState baseEventState;
|
|
|
+ switch (identifier.Value)
|
|
|
+ {
|
|
|
+ case 2052:
|
|
|
+ baseEventState = (BaseEventState)new AuditEventState((NodeState)null);
|
|
|
+ break;
|
|
|
+ case 2127:
|
|
|
+ baseEventState = (BaseEventState)new AuditUpdateMethodEventState((NodeState)null);
|
|
|
+ break;
|
|
|
+ case 2782:
|
|
|
+ baseEventState = (BaseEventState)new ConditionState((NodeState)null);
|
|
|
+ break;
|
|
|
+ case 2830:
|
|
|
+ baseEventState = (BaseEventState)new DialogConditionState((NodeState)null);
|
|
|
+ break;
|
|
|
+ case 2915:
|
|
|
+ baseEventState = (BaseEventState)new AlarmConditionState((NodeState)null);
|
|
|
+ break;
|
|
|
+ case 9341:
|
|
|
+ baseEventState = (BaseEventState)new ExclusiveLimitAlarmState((NodeState)null);
|
|
|
+ break;
|
|
|
+ case 9906:
|
|
|
+ baseEventState = (BaseEventState)new NonExclusiveLimitAlarmState((NodeState)null);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ baseEventState = new BaseEventState((NodeState)null);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ EventFilter filter = monitoredItem.Status.Filter as EventFilter;
|
|
|
+ baseEventState.Update(session.SystemContext, filter.SelectClauses, notification);
|
|
|
+ baseEventState.Handle = (object)notification;
|
|
|
+ return baseEventState;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static ReferenceDescriptionCollection Browse(
|
|
|
+ Session session,
|
|
|
+ BrowseDescription nodeToBrowse,
|
|
|
+ bool throwOnError)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ ReferenceDescriptionCollection descriptionCollection = new ReferenceDescriptionCollection();
|
|
|
+ BrowseDescriptionCollection nodesToBrowse = new BrowseDescriptionCollection();
|
|
|
+ nodesToBrowse.Add(nodeToBrowse);
|
|
|
+ BrowseResultCollection results = (BrowseResultCollection)null;
|
|
|
+ DiagnosticInfoCollection diagnosticInfos = (DiagnosticInfoCollection)null;
|
|
|
+ session.Browse((RequestHeader)null, (ViewDescription)null, 0U, nodesToBrowse, out results, out diagnosticInfos);
|
|
|
+ ClientBase.ValidateResponse((IList)results, (IList)nodesToBrowse);
|
|
|
+ ClientBase.ValidateDiagnosticInfos(diagnosticInfos, (IList)nodesToBrowse);
|
|
|
+ while (!StatusCode.IsBad(results[0].StatusCode))
|
|
|
+ {
|
|
|
+ for (int index = 0; index < results[0].References.Count; ++index)
|
|
|
+ descriptionCollection.Add(results[0].References[index]);
|
|
|
+ if (results[0].References.Count == 0 || results[0].ContinuationPoint == null)
|
|
|
+ return descriptionCollection;
|
|
|
+ ByteStringCollection continuationPoints = new ByteStringCollection();
|
|
|
+ continuationPoints.Add(results[0].ContinuationPoint);
|
|
|
+ session.BrowseNext((RequestHeader)null, false, continuationPoints, out results, out diagnosticInfos);
|
|
|
+ ClientBase.ValidateResponse((IList)results, (IList)continuationPoints);
|
|
|
+ ClientBase.ValidateDiagnosticInfos(diagnosticInfos, (IList)continuationPoints);
|
|
|
+ }
|
|
|
+ throw new ServiceResultException((ServiceResult)results[0].StatusCode);
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ if (throwOnError)
|
|
|
+ throw new ServiceResultException(ex, 2147549184U);
|
|
|
+ return (ReferenceDescriptionCollection)null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static ReferenceDescriptionCollection BrowseSuperTypes(
|
|
|
+ Session session,
|
|
|
+ NodeId typeId,
|
|
|
+ bool throwOnError)
|
|
|
+ {
|
|
|
+ ReferenceDescriptionCollection descriptionCollection1 = new ReferenceDescriptionCollection();
|
|
|
+ try
|
|
|
+ {
|
|
|
+ BrowseDescription nodeToBrowse = new BrowseDescription();
|
|
|
+ nodeToBrowse.NodeId = typeId;
|
|
|
+ nodeToBrowse.BrowseDirection = BrowseDirection.Inverse;
|
|
|
+ nodeToBrowse.ReferenceTypeId = ReferenceTypeIds.HasSubtype;
|
|
|
+ nodeToBrowse.IncludeSubtypes = false;
|
|
|
+ nodeToBrowse.NodeClassMask = 0U;
|
|
|
+ nodeToBrowse.ResultMask = 63U;
|
|
|
+ for (ReferenceDescriptionCollection descriptionCollection2 = FormUtils.Browse(session, nodeToBrowse, throwOnError); descriptionCollection2 != null && descriptionCollection2.Count > 0; descriptionCollection2 = FormUtils.Browse(session, nodeToBrowse, throwOnError))
|
|
|
+ {
|
|
|
+ descriptionCollection1.Add(descriptionCollection2[0]);
|
|
|
+ if (!descriptionCollection2[0].NodeId.IsAbsolute)
|
|
|
+ nodeToBrowse.NodeId = (NodeId)descriptionCollection2[0].NodeId;
|
|
|
+ else
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ return descriptionCollection1;
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ if (throwOnError)
|
|
|
+ throw new ServiceResultException(ex, 2147549184U);
|
|
|
+ return (ReferenceDescriptionCollection)null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|