From 7287600b8b074890facde682265eecbe1e1f6a5b Mon Sep 17 00:00:00 2001 From: Max Kirchberger Date: Fri, 1 Mar 2024 12:03:49 +0100 Subject: [PATCH 1/3] add eventmonitored item impl --- Libraries/Opc.Ua.Client/Events/EventField.cs | 38 +++++ Libraries/Opc.Ua.Client/Events/EventMethod.cs | 23 +++ .../Events/EventMethodCollection.cs | 30 ++++ Libraries/Opc.Ua.Client/Events/Extensions.cs | 92 ++++++++++++ Libraries/Opc.Ua.Client/Events/IEvent.cs | 31 ++++ .../Opc.Ua.Client/Events/IEventMethod.cs | 19 +++ .../Events/IEventMethodCollection.cs | 23 +++ .../Opc.Ua.Client/Events/ISessionContainer.cs | 13 ++ Libraries/Opc.Ua.Client/Events/MethodBase.cs | 135 ++++++++++++++++++ Libraries/Opc.Ua.Client/Events/OpcEvent.cs | 67 +++++++++ .../OpcUaEventFieldNotFoundException.cs | 65 +++++++++ .../Methods/MethodCallReturnValue.cs | 33 +++++ .../Opc.Ua.Client/Methods/OutputArgument.cs | 24 ++++ Libraries/Opc.Ua.Client/MonitoredItem.cs | 125 ++++++++++++++++ 14 files changed, 718 insertions(+) create mode 100644 Libraries/Opc.Ua.Client/Events/EventField.cs create mode 100644 Libraries/Opc.Ua.Client/Events/EventMethod.cs create mode 100644 Libraries/Opc.Ua.Client/Events/EventMethodCollection.cs create mode 100644 Libraries/Opc.Ua.Client/Events/Extensions.cs create mode 100644 Libraries/Opc.Ua.Client/Events/IEvent.cs create mode 100644 Libraries/Opc.Ua.Client/Events/IEventMethod.cs create mode 100644 Libraries/Opc.Ua.Client/Events/IEventMethodCollection.cs create mode 100644 Libraries/Opc.Ua.Client/Events/ISessionContainer.cs create mode 100644 Libraries/Opc.Ua.Client/Events/MethodBase.cs create mode 100644 Libraries/Opc.Ua.Client/Events/OpcEvent.cs create mode 100644 Libraries/Opc.Ua.Client/Events/OpcUaEventFieldNotFoundException.cs create mode 100644 Libraries/Opc.Ua.Client/Methods/MethodCallReturnValue.cs create mode 100644 Libraries/Opc.Ua.Client/Methods/OutputArgument.cs diff --git a/Libraries/Opc.Ua.Client/Events/EventField.cs b/Libraries/Opc.Ua.Client/Events/EventField.cs new file mode 100644 index 0000000000..b00b4ac1b7 --- /dev/null +++ b/Libraries/Opc.Ua.Client/Events/EventField.cs @@ -0,0 +1,38 @@ +namespace Opc.Ua.Client.Events +{ + /// + /// Object representing an event field + /// + public class EventField + { + /// + /// Name of this event field + /// + public string Name { get; } + + /// + /// Value of this event + /// + public Variant Value { get; } + + /// + /// Object representing an event field + /// + /// Name of the field + /// Value of the field + public EventField(string name, Variant value) + { + Name = name; + Value = value; + } + + /// + /// String representation: [Name]: [Value] + /// + /// + public override string ToString() + { + return $"{Name}: {Value}"; + } + } +} diff --git a/Libraries/Opc.Ua.Client/Events/EventMethod.cs b/Libraries/Opc.Ua.Client/Events/EventMethod.cs new file mode 100644 index 0000000000..b4af20075b --- /dev/null +++ b/Libraries/Opc.Ua.Client/Events/EventMethod.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using Opc.Ua.Client.Methods; + +namespace Opc.Ua.Client.Events +{ + /// + /// A standard event method + /// + internal class EventMethod : MethodBase, IEventMethod + { + internal EventMethod(ISession session, NodeId methodNodeId) : base(session, methodNodeId) + { + } + + /// + /// Call this method + /// + public MethodCallReturnValue CallMethod(NodeId objectNodeId, byte[] eventId, LocalizedText comment) + { + return Call(objectNodeId, new List { eventId, comment }); + } + } +} diff --git a/Libraries/Opc.Ua.Client/Events/EventMethodCollection.cs b/Libraries/Opc.Ua.Client/Events/EventMethodCollection.cs new file mode 100644 index 0000000000..dad6552576 --- /dev/null +++ b/Libraries/Opc.Ua.Client/Events/EventMethodCollection.cs @@ -0,0 +1,30 @@ +namespace Opc.Ua.Client.Events +{ + /// + /// Method collection for standard events + /// + public class EventMethodCollection : IEventMethodCollection + { + /// + /// Acknowledge + /// + public IEventMethod Acknowledge { get; } + + /// + /// Confirm + /// + public IEventMethod Confirm { get; } + + /// + /// Add comment + /// + public IEventMethod AddComment { get; } + + internal EventMethodCollection(ISession session) + { + Acknowledge = new EventMethod(session, MethodIds.AcknowledgeableConditionType_Acknowledge); + Confirm = new EventMethod(session, MethodIds.AcknowledgeableConditionType_Confirm); + AddComment = new EventMethod(session, MethodIds.ConditionType_AddComment); + } + } +} diff --git a/Libraries/Opc.Ua.Client/Events/Extensions.cs b/Libraries/Opc.Ua.Client/Events/Extensions.cs new file mode 100644 index 0000000000..4cf5e0d3f0 --- /dev/null +++ b/Libraries/Opc.Ua.Client/Events/Extensions.cs @@ -0,0 +1,92 @@ +using System; +using System.Linq; + +namespace Opc.Ua.Client.Events +{ + /// + /// + /// + public static class Extensions + { + + /// + /// + /// + /// + /// + /// + /// + /// + public static ReferenceDescriptionCollection FetchReferences(this ISession session, NodeId nodeId, BrowseDirection browseDirection, NodeId referenceTypeId) + { + if (session is null) + { + throw new ArgumentNullException(nameof(session)); + } + // browse for all references. + byte[] continuationPoint; + ReferenceDescriptionCollection descriptions; + + session.Browse( + null, + null, + nodeId, + 0, + browseDirection, + referenceTypeId, + true, + 0, + out continuationPoint, + out descriptions); + + // process any continuation point. + while (continuationPoint != null) + { + byte[] revisedContinuationPoint; + ReferenceDescriptionCollection additionalDescriptions; + + session.BrowseNext( + null, + false, + continuationPoint, + out revisedContinuationPoint, + out additionalDescriptions); + + continuationPoint = revisedContinuationPoint; + + descriptions.AddRange(additionalDescriptions); + } + + return descriptions; + } + + /// + /// + /// + /// + /// + /// + public static DataValueCollection Read(this ISession session, ReadValueIdCollection rvic) + { + session.Read(null, 0, TimestampsToReturn.Neither, rvic, out DataValueCollection dt, out DiagnosticInfoCollection dg); + return dt; + } + + /// + /// + /// + /// + /// + /// + public static DataValue Read(this ISession session, ReadValueId rvi) + { + return session.Read(new ReadValueIdCollection { rvi }).First(); + } + + + public static NodeId ToNodeId(this ReferenceDescription id) + { + return ExpandedNodeId.ToNodeId(id.NodeId, new NamespaceTable()); + } + } +} diff --git a/Libraries/Opc.Ua.Client/Events/IEvent.cs b/Libraries/Opc.Ua.Client/Events/IEvent.cs new file mode 100644 index 0000000000..38532ad8c1 --- /dev/null +++ b/Libraries/Opc.Ua.Client/Events/IEvent.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using Opc.Ua.Client.Methods; + +namespace Opc.Ua.Client.Events +{ + /// + /// Interface of an event + /// + public interface IEvent + { + /// + /// Event fields + /// + IReadOnlyList Fields { get; } + + /// + /// Acknowledge + /// + MethodCallReturnValue Acknowledge(LocalizedText comment); + + /// + /// Confirm + /// + MethodCallReturnValue Confirm(LocalizedText comment); + + /// + /// Add comment to this event + /// + MethodCallReturnValue AddComment(LocalizedText comment); + } +} diff --git a/Libraries/Opc.Ua.Client/Events/IEventMethod.cs b/Libraries/Opc.Ua.Client/Events/IEventMethod.cs new file mode 100644 index 0000000000..0a447847a4 --- /dev/null +++ b/Libraries/Opc.Ua.Client/Events/IEventMethod.cs @@ -0,0 +1,19 @@ +using Opc.Ua.Client.Methods; + +namespace Opc.Ua.Client.Events +{ + /// + /// A standard event method + /// + public interface IEventMethod + { + /// + /// Call this method and Return a MethodCallReturnValue + /// + /// the Object NodeId + /// the EventId + /// Comment to set for the event + /// MethodCallReturnValue + MethodCallReturnValue CallMethod(NodeId objectNodeId, byte[] eventId, LocalizedText comment); + } +} diff --git a/Libraries/Opc.Ua.Client/Events/IEventMethodCollection.cs b/Libraries/Opc.Ua.Client/Events/IEventMethodCollection.cs new file mode 100644 index 0000000000..96832e9c58 --- /dev/null +++ b/Libraries/Opc.Ua.Client/Events/IEventMethodCollection.cs @@ -0,0 +1,23 @@ +namespace Opc.Ua.Client.Events +{ + /// + /// Method collection for standard events + /// + public interface IEventMethodCollection + { + /// + /// Acknowledge + /// + IEventMethod Acknowledge { get; } + + /// + /// Confirm + /// + IEventMethod Confirm { get; } + + /// + /// Add comment + /// + IEventMethod AddComment { get; } + } +} diff --git a/Libraries/Opc.Ua.Client/Events/ISessionContainer.cs b/Libraries/Opc.Ua.Client/Events/ISessionContainer.cs new file mode 100644 index 0000000000..65fb9e704a --- /dev/null +++ b/Libraries/Opc.Ua.Client/Events/ISessionContainer.cs @@ -0,0 +1,13 @@ +namespace Opc.Ua.Client.Events +{ + /// + /// Interface for an object containing the session + /// + public interface ISessionContainer + { + /// + /// The contained session object + /// + ISession Session { get; set; } + } +} diff --git a/Libraries/Opc.Ua.Client/Events/MethodBase.cs b/Libraries/Opc.Ua.Client/Events/MethodBase.cs new file mode 100644 index 0000000000..b3d6f415aa --- /dev/null +++ b/Libraries/Opc.Ua.Client/Events/MethodBase.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Opc.Ua.Client.Methods; + +namespace Opc.Ua.Client.Events +{ + /// + /// Base object for method object + /// + internal abstract class MethodBase + { + private readonly ISession _session; + private NodeId _inputArgumentsNodeId; + + /// + /// Node id of the input arguments, null if it does not exist + /// + protected NodeId InputArgumentsNodeId + { + get + { + if (_inputArgumentsNodeId == null) + { + LoadArguments(); + } + return _inputArgumentsNodeId; + } + } + + private NodeId _outputArgumentsNodeId; + + /// + /// Node id of the output arguments, null if it does not exist + /// + protected NodeId OutputArgumentsNodeId + { + get + { + if (_outputArgumentsNodeId == null) + { + LoadArguments(); + } + return _outputArgumentsNodeId; + } + } + + /// + /// NodeId of the method + /// + public NodeId MethodNodeId { get; } + + /// + /// Constructor + /// + protected MethodBase(ISession session, NodeId methodNodeId) + { + _session = session; + MethodNodeId = methodNodeId; + } + + private void LoadArguments() + { + var references = _session.FetchReferences(MethodNodeId, BrowseDirection.Forward, ReferenceTypeIds.HasProperty); + foreach (var reference in references) + { + if (reference.BrowseName.Name.Equals("InputArguments", StringComparison.Ordinal)) + { + _inputArgumentsNodeId = reference.ToNodeId(); + } + else if (reference.BrowseName.Name.Equals("OutputArguments", StringComparison.Ordinal)) + { + _outputArgumentsNodeId = reference.ToNodeId(); + } + } + } + + /// + /// Internal function call + /// + /// object NodeId + /// the list of parameter. if there are none, an empty list + protected MethodCallReturnValue Call(NodeId objectNodeId, IEnumerable parameters) + { + var callMethodRequestCollection = new CallMethodRequestCollection + { + new CallMethodRequest() + { + ObjectId = objectNodeId, + MethodId = MethodNodeId, + InputArguments = new VariantCollection(parameters) + } + }; + CallMethodResultCollection results; + DiagnosticInfoCollection diagnosticInfos; + + _session.Call(GetHeader(), callMethodRequestCollection, out results, out diagnosticInfos); + + VariantCollection outputValues = results[0].OutputArguments; + List arguments = null; + if (OutputArgumentsNodeId != null) + { + var extObjs = (ExtensionObject[])_session.ReadValue(OutputArgumentsNodeId).Value; + arguments = extObjs.Select(x => (Argument)x.Body).ToList(); + } + + var convertedOutputArgs = GetOutputParameters(outputValues, arguments); + + return new MethodCallReturnValue(results[0].StatusCode, convertedOutputArgs.ToList(), results[0].InputArgumentResults.ToList()); + + } + + private RequestHeader GetHeader() + { + return new RequestHeader(); + } + + private List GetOutputParameters(VariantCollection values, IEnumerable arguments) + { + var convertedOutputArgs = new List(); + for (int i = 0; i < values.Count; i++) + { + convertedOutputArgs.Add(GetOutputParameter(values[i], arguments.ElementAt(i))); + } + return convertedOutputArgs; + } + + /// + /// Get output parameters + /// + protected virtual OutputArgument GetOutputParameter(Variant value, Argument argument) + { + return new OutputArgument() { Name = argument.Name, Value = value.Value }; + } + } diff --git a/Libraries/Opc.Ua.Client/Events/OpcEvent.cs b/Libraries/Opc.Ua.Client/Events/OpcEvent.cs new file mode 100644 index 0000000000..8ef0061f4c --- /dev/null +++ b/Libraries/Opc.Ua.Client/Events/OpcEvent.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Opc.Ua.Client.Methods; + +namespace Opc.Ua.Client.Events +{ + /// + /// Object for an event + /// + public class OpcEvent : IEvent + { + /// + /// Event fields + /// + public IReadOnlyList Fields { get; } + + private readonly NodeId _objectNodeId; + private readonly byte[] _eventId; + private readonly IEventMethodCollection _eventMethods; + + /// + /// Constructor + /// + public OpcEvent(IEventMethodCollection eventMethods, IEnumerable fields) + { + Fields = fields.ToList(); + _eventMethods = eventMethods; + _objectNodeId = GetEventField("ConditionNodeId", x => x.Name.Equals("ConditionId", StringComparison.Ordinal)); + _eventId = GetEventField("EventId", x => x.Name.Equals("/EventId", StringComparison.Ordinal)); + } + + /// + /// Acknowledge this event + /// + public MethodCallReturnValue Acknowledge(LocalizedText comment) + { + return _eventMethods.Acknowledge.CallMethod(_objectNodeId, _eventId, comment); + } + + /// + /// Confirm this event + /// + public MethodCallReturnValue Confirm(LocalizedText comment) + { + return _eventMethods.Confirm.CallMethod(_objectNodeId, _eventId, comment); + } + + /// + /// Add comment to this event + /// + public MethodCallReturnValue AddComment(LocalizedText comment) + { + return _eventMethods.AddComment.CallMethod(_objectNodeId, _eventId, comment); + } + + private T GetEventField(string eventFieldName, Func searchCriteria) + { + var relevantField = Fields.FirstOrDefault(searchCriteria); + if (relevantField is null) + { + throw new OpcUaEventFieldNotFoundException(eventFieldName); + } + return (T)relevantField.Value.Value; + } + } +} diff --git a/Libraries/Opc.Ua.Client/Events/OpcUaEventFieldNotFoundException.cs b/Libraries/Opc.Ua.Client/Events/OpcUaEventFieldNotFoundException.cs new file mode 100644 index 0000000000..3c0b583b41 --- /dev/null +++ b/Libraries/Opc.Ua.Client/Events/OpcUaEventFieldNotFoundException.cs @@ -0,0 +1,65 @@ +using System; + +namespace Opc.Ua.Client.Events +{ + /// + /// Exception when event field not found + /// + public class OpcUaEventFieldNotFoundException : Exception + { + private const string DefaultMessage = "Event field with given name not found!"; + + /// + /// Name of the event field + /// + public string EventFieldName { get; } + + /// + /// Exception when event field not found + /// + public OpcUaEventFieldNotFoundException(string eventFieldName) + : this(eventFieldName, "") + { + EventFieldName = eventFieldName; + } + + /// + /// Exception when event field not found + /// + public OpcUaEventFieldNotFoundException(string eventFieldName, string userMessage) + : this(eventFieldName, userMessage, null) + { + + } + + /// + /// Exception when event field not found + /// + public OpcUaEventFieldNotFoundException() : this("") + { + + } + + /// + /// Exception when event field not found + /// + /// + /// + public OpcUaEventFieldNotFoundException(string message, Exception innerException) : this("", message, innerException) + { + + } + + /// + /// Exception when event field not found + /// + /// Field that was not found + /// userdefined message for the exception + /// Inner Exception + public OpcUaEventFieldNotFoundException(string eventFieldName, string userMessage, Exception innerException) + : base($"{DefaultMessage}{eventFieldName}{userMessage}", innerException) + { + EventFieldName = eventFieldName; + } + } +} diff --git a/Libraries/Opc.Ua.Client/Methods/MethodCallReturnValue.cs b/Libraries/Opc.Ua.Client/Methods/MethodCallReturnValue.cs new file mode 100644 index 0000000000..5144545573 --- /dev/null +++ b/Libraries/Opc.Ua.Client/Methods/MethodCallReturnValue.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace Opc.Ua.Client.Methods +{ + /// + /// Return values of a method call + /// + public class MethodCallReturnValue + { + /// + /// Result of the method call + /// + public StatusCode Result { get; set; } + + /// + /// Return values from the method call + /// + public ReadOnlyCollection ReturnValue { get; set; } + + /// + /// Results of the parameters + /// + public ReadOnlyCollection ParameterResult { get; set; } + + internal MethodCallReturnValue(StatusCode s, List returnValue, List parameterResult) + { + Result = s; + ReturnValue = new ReadOnlyCollection(returnValue); + ParameterResult = new ReadOnlyCollection(parameterResult); + } + } +} diff --git a/Libraries/Opc.Ua.Client/Methods/OutputArgument.cs b/Libraries/Opc.Ua.Client/Methods/OutputArgument.cs new file mode 100644 index 0000000000..857ee13f96 --- /dev/null +++ b/Libraries/Opc.Ua.Client/Methods/OutputArgument.cs @@ -0,0 +1,24 @@ +namespace Opc.Ua.Client.Methods +{ + /// + /// An output argument of a method + /// + public class OutputArgument + { + /// + /// Name of this argument + /// + public string Name { get; set; } + + /// + /// Value of this argument + /// + public object Value { get; set; } + + /// + /// Method Name + /// + /// The Method Name + public override string ToString() => Name; + } +} diff --git a/Libraries/Opc.Ua.Client/MonitoredItem.cs b/Libraries/Opc.Ua.Client/MonitoredItem.cs index fb02141ba1..18f10fb1d7 100644 --- a/Libraries/Opc.Ua.Client/MonitoredItem.cs +++ b/Libraries/Opc.Ua.Client/MonitoredItem.cs @@ -30,6 +30,7 @@ using System; using System.Collections.Generic; using System.Runtime.Serialization; +using Opc.Ua.Client.Events; namespace Opc.Ua.Client { @@ -175,7 +176,112 @@ private void Initialize() // assign a unique handle. m_clientHandle = Utils.IncrementIdentifier(ref s_globalClientHandle); + AddEventHandler(); } + + private bool AddedEventHandlers = false; + + /// + /// Add Event Handler to MonitoredItem -> Notification + /// + public void AddEventHandler() + { + if (!AddedEventHandlers) + { + m_Notification += MonitoredItem_Notification; + AddedEventHandlers = true; + EventNotification += Event_Notification; + } + } + + private void Event_Notification(EventFilter eventFilter, EventFieldList eventFieldList) + { + var acknowledgeableEvent = GetAcknowledgeableEvent(eventFilter, eventFieldList); + + foreach (var field in acknowledgeableEvent.Fields) + { + Console.WriteLine($"{field.Name}:{field.Value}"); + } + try + { + acknowledgeableEvent.AddComment(new LocalizedText("Commented!")); + Console.WriteLine($"Commented!"); + } + catch (Exception e) + { + Console.WriteLine($"couldnt comment! {e}"); + } + try + { + acknowledgeableEvent.Confirm(new LocalizedText("Confirmed!")); + Console.WriteLine($"Confirmed!"); + } + catch (Exception e) + { + Console.WriteLine($"couldnt Confirm! {e}"); + } + try + { + acknowledgeableEvent.Acknowledge(new LocalizedText("Acknowledged!")); + Console.WriteLine($"Acknowledged!"); + } + catch (Exception e) + { + Console.WriteLine($"couldnt Acknowledge! {e}"); + } + } + + private void MonitoredItem_Notification(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e) + { + var dataChangeNotification = e.NotificationValue as MonitoredItemNotification; + if (dataChangeNotification != null) + { + DataChangeNotification?.Invoke(dataChangeNotification); + return; + } + + var eventMonitoredItemNotification = e.NotificationValue as EventFieldList; + if (eventMonitoredItemNotification != null) + { + EventNotification?.Invoke((EventFilter)monitoredItem.Filter, eventMonitoredItemNotification); + } + } + + /// + /// Get an Acknowledgeable event + /// + /// + /// + /// + public IEvent GetAcknowledgeableEvent(EventFilter eventFilter, EventFieldList eventFieldList) + { + ArgumentNullException.ThrowIfNull(eventFilter, nameof(eventFilter)); + ArgumentNullException.ThrowIfNull(eventFieldList, nameof(eventFieldList)); + return new OpcEvent(new EventMethodCollection(this.Subscription.Session), GetWrappedEventFields(eventFilter, eventFieldList)); + } + + /// + /// + /// + /// + /// + /// + private List GetWrappedEventFields(EventFilter eventFilter, EventFieldList eventFieldList) + { + var eventFields = eventFieldList.EventFields; + var wrappedEventFields = new List(); + for (int i = 0; i < eventFields.Count; i++) + { + var eventName = eventFilter.SelectClauses[i].ToString(); + if (eventFilter.SelectClauses[i].AttributeId == Attributes.NodeId) + { + eventName = "ConditionId"; + } + wrappedEventFields.Add(new EventField(eventName, eventFields[i])); + } + return wrappedEventFields; + } + #endregion #region Persistent Properties @@ -593,6 +699,15 @@ public event MonitoredItemNotificationEventHandler Notification } } + /// + /// DataChangeNotification for the Monitored Item + /// + public event MonitoredItemNotificationHandler DataChangeNotification; + /// + /// Event Notification for the Monitored Item + /// + public event EventMonitoredItemNotificationNotificationHandler EventNotification; + /// /// Reset the notification event handler. /// @@ -1155,6 +1270,16 @@ internal MonitoredItemNotificationEventArgs(IEncodeable notificationValue) /// The delegate used to receive monitored item value notifications. /// public delegate void MonitoredItemNotificationEventHandler(MonitoredItem monitoredItem, MonitoredItemNotificationEventArgs e); + + /// + /// Handler for data change notification + /// + public delegate void MonitoredItemNotificationHandler(MonitoredItemNotification notification); + + /// + /// Handler for event change notification + /// + public delegate void EventMonitoredItemNotificationNotificationHandler(EventFilter eventFilter, EventFieldList eventFieldList); #endregion /// From 09bfc268552020fc5c7a9e1a91f0a4a44959d470 Mon Sep 17 00:00:00 2001 From: Max Kirchberger Date: Fri, 1 Mar 2024 12:16:03 +0100 Subject: [PATCH 2/3] move method stuff to methods --- Libraries/Opc.Ua.Client/Events/Extensions.cs | 5 +++++ .../{Events => Methods}/EventMethod.cs | 3 +-- .../{Events => Methods}/EventMethodCollection.cs | 2 +- .../{Events => Methods}/IEventMethod.cs | 4 +--- .../{Events => Methods}/IEventMethodCollection.cs | 2 +- .../Opc.Ua.Client/{Events => Methods}/MethodBase.cs | 7 ++++--- Libraries/Opc.Ua.Client/MonitoredItem.cs | 13 +++++++++++-- 7 files changed, 24 insertions(+), 12 deletions(-) rename Libraries/Opc.Ua.Client/{Events => Methods}/EventMethod.cs (90%) rename Libraries/Opc.Ua.Client/{Events => Methods}/EventMethodCollection.cs (96%) rename Libraries/Opc.Ua.Client/{Events => Methods}/IEventMethod.cs (90%) rename Libraries/Opc.Ua.Client/{Events => Methods}/IEventMethodCollection.cs (93%) rename Libraries/Opc.Ua.Client/{Events => Methods}/MethodBase.cs (97%) diff --git a/Libraries/Opc.Ua.Client/Events/Extensions.cs b/Libraries/Opc.Ua.Client/Events/Extensions.cs index 4cf5e0d3f0..c0136d38bf 100644 --- a/Libraries/Opc.Ua.Client/Events/Extensions.cs +++ b/Libraries/Opc.Ua.Client/Events/Extensions.cs @@ -84,6 +84,11 @@ public static DataValue Read(this ISession session, ReadValueId rvi) } + /// + /// + /// + /// + /// public static NodeId ToNodeId(this ReferenceDescription id) { return ExpandedNodeId.ToNodeId(id.NodeId, new NamespaceTable()); diff --git a/Libraries/Opc.Ua.Client/Events/EventMethod.cs b/Libraries/Opc.Ua.Client/Methods/EventMethod.cs similarity index 90% rename from Libraries/Opc.Ua.Client/Events/EventMethod.cs rename to Libraries/Opc.Ua.Client/Methods/EventMethod.cs index b4af20075b..031db64c85 100644 --- a/Libraries/Opc.Ua.Client/Events/EventMethod.cs +++ b/Libraries/Opc.Ua.Client/Methods/EventMethod.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; -using Opc.Ua.Client.Methods; -namespace Opc.Ua.Client.Events +namespace Opc.Ua.Client.Methods { /// /// A standard event method diff --git a/Libraries/Opc.Ua.Client/Events/EventMethodCollection.cs b/Libraries/Opc.Ua.Client/Methods/EventMethodCollection.cs similarity index 96% rename from Libraries/Opc.Ua.Client/Events/EventMethodCollection.cs rename to Libraries/Opc.Ua.Client/Methods/EventMethodCollection.cs index dad6552576..3c322d6bc3 100644 --- a/Libraries/Opc.Ua.Client/Events/EventMethodCollection.cs +++ b/Libraries/Opc.Ua.Client/Methods/EventMethodCollection.cs @@ -1,4 +1,4 @@ -namespace Opc.Ua.Client.Events +namespace Opc.Ua.Client.Methods { /// /// Method collection for standard events diff --git a/Libraries/Opc.Ua.Client/Events/IEventMethod.cs b/Libraries/Opc.Ua.Client/Methods/IEventMethod.cs similarity index 90% rename from Libraries/Opc.Ua.Client/Events/IEventMethod.cs rename to Libraries/Opc.Ua.Client/Methods/IEventMethod.cs index 0a447847a4..133edc244e 100644 --- a/Libraries/Opc.Ua.Client/Events/IEventMethod.cs +++ b/Libraries/Opc.Ua.Client/Methods/IEventMethod.cs @@ -1,6 +1,4 @@ -using Opc.Ua.Client.Methods; - -namespace Opc.Ua.Client.Events +namespace Opc.Ua.Client.Methods { /// /// A standard event method diff --git a/Libraries/Opc.Ua.Client/Events/IEventMethodCollection.cs b/Libraries/Opc.Ua.Client/Methods/IEventMethodCollection.cs similarity index 93% rename from Libraries/Opc.Ua.Client/Events/IEventMethodCollection.cs rename to Libraries/Opc.Ua.Client/Methods/IEventMethodCollection.cs index 96832e9c58..265d51dafd 100644 --- a/Libraries/Opc.Ua.Client/Events/IEventMethodCollection.cs +++ b/Libraries/Opc.Ua.Client/Methods/IEventMethodCollection.cs @@ -1,4 +1,4 @@ -namespace Opc.Ua.Client.Events +namespace Opc.Ua.Client.Methods { /// /// Method collection for standard events diff --git a/Libraries/Opc.Ua.Client/Events/MethodBase.cs b/Libraries/Opc.Ua.Client/Methods/MethodBase.cs similarity index 97% rename from Libraries/Opc.Ua.Client/Events/MethodBase.cs rename to Libraries/Opc.Ua.Client/Methods/MethodBase.cs index b3d6f415aa..57fe265df0 100644 --- a/Libraries/Opc.Ua.Client/Events/MethodBase.cs +++ b/Libraries/Opc.Ua.Client/Methods/MethodBase.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; -using Opc.Ua.Client.Methods; +using Opc.Ua.Client.Events; -namespace Opc.Ua.Client.Events +namespace Opc.Ua.Client.Methods { /// /// Base object for method object @@ -61,7 +61,7 @@ protected MethodBase(ISession session, NodeId methodNodeId) private void LoadArguments() { - var references = _session.FetchReferences(MethodNodeId, BrowseDirection.Forward, ReferenceTypeIds.HasProperty); + var references = _session.FetchReferences(MethodNodeId/*, BrowseDirection.Forward, ReferenceTypeIds.HasProperty*/); foreach (var reference in references) { if (reference.BrowseName.Name.Equals("InputArguments", StringComparison.Ordinal)) @@ -133,3 +133,4 @@ protected virtual OutputArgument GetOutputParameter(Variant value, Argument argu return new OutputArgument() { Name = argument.Name, Value = value.Value }; } } +} diff --git a/Libraries/Opc.Ua.Client/MonitoredItem.cs b/Libraries/Opc.Ua.Client/MonitoredItem.cs index 18f10fb1d7..7b065ac21f 100644 --- a/Libraries/Opc.Ua.Client/MonitoredItem.cs +++ b/Libraries/Opc.Ua.Client/MonitoredItem.cs @@ -31,6 +31,7 @@ using System.Collections.Generic; using System.Runtime.Serialization; using Opc.Ua.Client.Events; +using Opc.Ua.Client.Methods; namespace Opc.Ua.Client { @@ -255,8 +256,16 @@ private void MonitoredItem_Notification(MonitoredItem monitoredItem, MonitoredIt /// public IEvent GetAcknowledgeableEvent(EventFilter eventFilter, EventFieldList eventFieldList) { - ArgumentNullException.ThrowIfNull(eventFilter, nameof(eventFilter)); - ArgumentNullException.ThrowIfNull(eventFieldList, nameof(eventFieldList)); + //ArgumentNullException.ThrowIfNull(eventFilter, nameof(eventFilter)); + //ArgumentNullException.ThrowIfNull(eventFieldList, nameof(eventFieldList)); + if (eventFilter == null) + { + throw new ArgumentNullException(nameof(eventFilter)); + } + if (eventFieldList == null) + { + throw new ArgumentNullException(nameof(eventFieldList)); + } return new OpcEvent(new EventMethodCollection(this.Subscription.Session), GetWrappedEventFields(eventFilter, eventFieldList)); } From 9616b835efc9ad089b9350f003b54ca0bfd9d7e5 Mon Sep 17 00:00:00 2001 From: Max Kirchberger Date: Fri, 1 Mar 2024 12:20:43 +0100 Subject: [PATCH 3/3] use 'smaller' fetchreferences --- Libraries/Opc.Ua.Client/Methods/MethodBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Libraries/Opc.Ua.Client/Methods/MethodBase.cs b/Libraries/Opc.Ua.Client/Methods/MethodBase.cs index 57fe265df0..032be183a2 100644 --- a/Libraries/Opc.Ua.Client/Methods/MethodBase.cs +++ b/Libraries/Opc.Ua.Client/Methods/MethodBase.cs @@ -61,7 +61,7 @@ protected MethodBase(ISession session, NodeId methodNodeId) private void LoadArguments() { - var references = _session.FetchReferences(MethodNodeId/*, BrowseDirection.Forward, ReferenceTypeIds.HasProperty*/); + var references = _session.FetchReferences(MethodNodeId, BrowseDirection.Forward, ReferenceTypeIds.HasProperty); foreach (var reference in references) { if (reference.BrowseName.Name.Equals("InputArguments", StringComparison.Ordinal))