OPC Studio User's Guide and Reference
UAFilterElements Class
Members  Example 



OpcLabs.EasyOpcUA Assembly > OpcLabs.EasyOpc.UA.Filtering Namespace : UAFilterElements Class
Provides an easy way to construct basic filter elements (literal, attribute, or a simple attribute), and elements with various operators.
Syntax
'Declaration
 
<ComVisibleAttribute(False)>
Public MustInherit NotInheritable Class UAFilterElements 
'Usage
 
Dim instance As UAFilterElements
[ComVisible(false)]
public static class UAFilterElements 
[ComVisible(false)]
public ref class UAFilterElements abstract sealed 
Remarks

 

General

The Where clause contains the criteria limiting the notifications that the OPC UA server sends - and the OPC UA client receives. The Where clause in OPC UA is similar to the WHERE clause in SQL queries, with the difference that ity operates on events and not on table rows: It is a filter that allows you to choose the events of interest, out of all events provided by the chosen notifier node in the OPC UA server. The OPC UA server itself controls which events are generated by the notifier (for particular types of events, this may be prescribed by OPC UA specifications or other standards). For example, the event might be triggered by a process value exceeding specific limit. In OPC UA, there is no generic way to influence which events get internally generated in the OPC UA server; but the Where clause allows you to pick the events that are of interest to your application.

Obviously, you can also do event filtering on the client side (in your application), and throw away the events that you do not need. But this aproach requires all these events be transferred from the server to the client, which represents a load on all parts involved (server, network, client). Not all filtering criteria can be specified using the Where clause, but whenever you can, you should use it, because the filtering then occurs in the OPC UA server and close to the source, which greatly reduces the load on other parts of the system.

Coding

The Where clause of the event filter is represented using the UAContentFilterElement object. This objects contains the filter operand to be evaluated (the FilterOperator property, which is a UAFilterOperator enumeration), and the operands used by the selected operator (the FilterOperands property, which is a UAFilterOperandCollection). The UAFilterOperator enumeration contains all operators supported by OPC UA (EqualsIsNullGreaterThanLessThanGreaterThanOrEqualLessThanOrEqualLikeNotBetweenInListAndOrCastInViewOfTypeRelatedToBitwiseAndBitwiseOr). The UAFilterOperandCollection is a collection of content filter operands (UAFilterOperand).

The UAFilterOperand is a base class for four different types of filter operands: UAAttributeOperand (an operand consisting of an attribute of a node in a type, with optional relative path and alias), UAContentFilterElement (essentially, an operator with operands), UALiteralOperand (an operand consisting of a literal value), or UASimpleAttributeOperand (an operand consisting of an attribute of a node in a type, with optional simple relative path, and no alias).

In order to make the creation of Where clauses appear shorter in the code, a UAContentFilterElementBuilder class is provided. Instances of this builder can be implicitly converted to the content filter element itself (hence you can create just the UAContentFilterElementBuilder objects, and use them at all places where the UAContentFilterElement object is expected). The builder contains an operator and is a collection of operands; you can use the C# collection initializer to specify the operands.

For further simplification of the coding, the UAFilterElements static class provides an easy way to construct basic filter elements (literal, attribute, or a simple attribute), and elements with various operators. Using the UAFilterElements class is for most cases the recommended way to create the Where clause of the event filter. For example, UAFilterElements.GreaterThanOrEqual creates a Where clause with the ‘>=’ operator. There are methods for each of the OPC UA operators, with various overloads. The UAFilterElements.AttributeUAFilterElements.Literal and UAFilterElements.SimpleAttribute methods can be used to create other types of filter elements. Moreover, useful overloads exist that assure that you can actually use .NET objects directly as values of operands, and they will be interpreted as literal elements. With use of all these code simplifying features, you can write, for example, the following Where clause:

UAFilterElements.GreaterThanOrEqual(UABaseEventObject.Operands.Severity, 500).

Example 

.NET

// This example shows how to specify criteria for event notifications.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

using System;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.AddressSpace;
using OpcLabs.EasyOpc.UA.AddressSpace.Standard;
using OpcLabs.EasyOpc.UA.AlarmsAndConditions;
using OpcLabs.EasyOpc.UA.Filtering;
using OpcLabs.EasyOpc.UA.OperationModel;

namespace UADocExamples.AlarmsAndConditions
{
    class WhereClause
    {
        public static void Main1()
        {
            UAEndpointDescriptor endpointDescriptor =
                "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer";

            // Instantiate the client object and hook events.
            var client = new EasyUAClient();
            client.EventNotification += client_EventNotification;

            Console.WriteLine("Subscribing...");
            client.SubscribeEvent(
                endpointDescriptor,
                UAObjectIds.Server,
                1000,
                new UAEventFilterBuilder(
                    // Either the severity is >= 500, or the event comes from a specified source node
                    UAFilterElements.Or(
                        UAFilterElements.GreaterThanOrEqual(UABaseEventObject.Operands.Severity, 500),
                        UAFilterElements.Equals(
                            UABaseEventObject.Operands.SourceNode, 
                            new UANodeId("nsu=http://opcfoundation.org/Quickstarts/AlarmCondition ;ns=2;s=1:Metals/SouthMotor"))),
                    UABaseEventObject.AllFields));

            Console.WriteLine("Processing event notifications for 30 seconds...");
            System.Threading.Thread.Sleep(30 * 1000);

            Console.WriteLine("Unsubscribing...");
            client.UnsubscribeAllMonitoredItems();

            Console.WriteLine("Waiting for 5 seconds...");
            System.Threading.Thread.Sleep(5 * 1000);

            Console.WriteLine("Finished.");
        }

        static void client_EventNotification(object sender, EasyUAEventNotificationEventArgs e)
        {
            // Display the event.
            Console.WriteLine(e);
        }


        // Example output:
        //
        //Subscribing...
        //13000008
        //Processing event notifications for 30 seconds...
        //[] Success
        //[] Success; Refresh; RefreshInitiated
        //[] Success; Refresh; [SouthMotor] 100! {DialogConditionType} "The dialog was activated" @9/9/2021 2:22:18 PM (10 fields)
        //[] Success; Refresh; [SouthMotor] 700! {ExclusiveDeviationAlarmType} "The alarm severity has increased." @9/22/2021 7:17:59 AM (10 fields)
        //[] Success; Refresh; [SouthMotor] 900! {NonExclusiveLevelAlarmType} "The alarm severity has increased." @9/22/2021 7:17:57 AM (10 fields)
        //[] Success; Refresh; [SouthMotor] 100! {TripAlarmType} "The alarm is active." @9/22/2021 7:17:59 AM (10 fields)
        //[] Success; Refresh; [SouthMotor] 100! {TripAlarmType} "The alarm severity has increased." @9/9/2021 3:39:51 PM (10 fields)
        //[] Success; Refresh; [SouthMotor] 100! {TripAlarmType} "The alarm severity has increased." @9/9/2021 3:38:57 PM (10 fields)
        //[] Success; Refresh; RefreshComplete
        //[] Success; [SouthMotor] 100! {NonExclusiveLevelAlarmType} "The alarm was deactivated by the system." @9/22/2021 7:18:05 AM (10 fields)
        //[] Success; [SouthMotor] 300! {TripAlarmType} "The alarm severity has increased." @9/22/2021 7:18:08 AM (10 fields)
        //[] Success; [SouthMotor] 900! {ExclusiveDeviationAlarmType} "The alarm severity has increased." @9/22/2021 7:18:10 AM (10 fields)
        //[] Success; [SouthMotor] 100! {NonExclusiveLevelAlarmType} "The alarm is active." @9/22/2021 7:18:13 AM (10 fields)
        //[] Success; [SouthMotor] 500! {TripAlarmType} "The alarm severity has increased." @9/22/2021 7:18:17 AM (10 fields)
        //[] Success; [SouthMotor] 100! {ExclusiveDeviationAlarmType} "The alarm was deactivated by the system." @9/22/2021 7:18:21 AM (10 fields)
        //[] Success; [SouthMotor] 300! {NonExclusiveLevelAlarmType} "The alarm severity has increased." @9/22/2021 7:18:21 AM (10 fields)
        //[] Success; [SouthMotor] 700! {TripAlarmType} "The alarm severity has increased." @9/22/2021 7:18:26 AM (10 fields)
        //[] Success; [SouthMotor] 500! {NonExclusiveLevelAlarmType} "The alarm severity has increased." @9/22/2021 7:18:29 AM (10 fields)
        //[] Success; [SouthMotor] 100! {ExclusiveDeviationAlarmType} "The alarm is active." @9/22/2021 7:18:32 AM (10 fields)
        //Unsubscribing...
        //Waiting for 5 seconds...
        //Finished.
    }
}
# This example shows how to specify criteria for event notifications.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

#requires -Version 5.1
using namespace OpcLabs.EasyOpc.UA
using namespace OpcLabs.EasyOpc.UA.AddressSpace
using namespace OpcLabs.EasyOpc.UA.AddressSpace.Standard

# The path below assumes that the current directory is [ProductDir]/Examples-NET/PowerShell/Windows .
Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.EasyOpcUA.dll"
Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.EasyOpcUAComponents.dll"

# Define which server we will work with.
[UAEndpointDescriptor]$endpointDescriptor = "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer"

# Instantiate the client object.
$client = New-Object EasyUAClient

# Event notification handler
Register-ObjectEvent -InputObject $client -EventName EventNotification -Action { 
    # Display the event.
    Write-Host $EventArgs
}

Write-Host "Subscribing..."
[IEasyUAClientExtension]::SubscribeEvent($client, 
    $endpointDescriptor, 
    [UAObjectIds]::Server, 
    1000,
    [UAEventFilter](New-Object UAEventFilterBuilder(
        [UAFilterElements]::Equals(
            [UABaseEventObject+Operands]::SourceNode, 
            (New-Object UANodeId("nsu=http://opcfoundation.org/Quickstarts/AlarmCondition ;ns=2;s=1:Metals/SouthMotor"))),
        [UABaseEventObject]::AllFields))
    )

Write-Host "Processing event notifications for 30 seconds..."
$stopwatch =  [System.Diagnostics.Stopwatch]::StartNew() 
while ($stopwatch.Elapsed.TotalSeconds -lt 30) {    
    Start-Sleep -Seconds 1
}

Write-Host "Unsubscribing..."
$client.UnsubscribeAllMonitoredItems()

Write-Host "Waiting for 5 seconds..."
Start-Sleep -Seconds 5

Write-Host "Finished."


# Example output:
#
#Subscribing...
#13000008
#Processing event notifications for 30 seconds...
#[] Success
#[] Success; Refresh; RefreshInitiated
#[] Success; Refresh; [SouthMotor] 100! {DialogConditionType} "The dialog was activated" @9/9/2021 2:22:18 PM (10 fields)
#[] Success; Refresh; [SouthMotor] 700! {ExclusiveDeviationAlarmType} "The alarm severity has increased." @9/22/2021 7:17:59 AM (10 fields)
#[] Success; Refresh; [SouthMotor] 900! {NonExclusiveLevelAlarmType} "The alarm severity has increased." @9/22/2021 7:17:57 AM (10 fields)
#[] Success; Refresh; [SouthMotor] 100! {TripAlarmType} "The alarm is active." @9/22/2021 7:17:59 AM (10 fields)
#[] Success; Refresh; [SouthMotor] 100! {TripAlarmType} "The alarm severity has increased." @9/9/2021 3:39:51 PM (10 fields)
#[] Success; Refresh; [SouthMotor] 100! {TripAlarmType} "The alarm severity has increased." @9/9/2021 3:38:57 PM (10 fields)
#[] Success; Refresh; RefreshComplete
#[] Success; [SouthMotor] 100! {NonExclusiveLevelAlarmType} "The alarm was deactivated by the system." @9/22/2021 7:18:05 AM (10 fields)
#[] Success; [SouthMotor] 300! {TripAlarmType} "The alarm severity has increased." @9/22/2021 7:18:08 AM (10 fields)
#[] Success; [SouthMotor] 900! {ExclusiveDeviationAlarmType} "The alarm severity has increased." @9/22/2021 7:18:10 AM (10 fields)
#[] Success; [SouthMotor] 100! {NonExclusiveLevelAlarmType} "The alarm is active." @9/22/2021 7:18:13 AM (10 fields)
#[] Success; [SouthMotor] 500! {TripAlarmType} "The alarm severity has increased." @9/22/2021 7:18:17 AM (10 fields)
#[] Success; [SouthMotor] 100! {ExclusiveDeviationAlarmType} "The alarm was deactivated by the system." @9/22/2021 7:18:21 AM (10 fields)
#[] Success; [SouthMotor] 300! {NonExclusiveLevelAlarmType} "The alarm severity has increased." @9/22/2021 7:18:21 AM (10 fields)
#[] Success; [SouthMotor] 700! {TripAlarmType} "The alarm severity has increased." @9/22/2021 7:18:26 AM (10 fields)
#[] Success; [SouthMotor] 500! {NonExclusiveLevelAlarmType} "The alarm severity has increased." @9/22/2021 7:18:29 AM (10 fields)
#[] Success; [SouthMotor] 100! {ExclusiveDeviationAlarmType} "The alarm is active." @9/22/2021 7:18:32 AM (10 fields)
#Unsubscribing...
#Waiting for 5 seconds...
#Finished.

# This example shows how to specify criteria for event notifications.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python .
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc
import time

# Import .NET namespaces.
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.AddressSpace import *
from OpcLabs.EasyOpc.UA.AddressSpace.Standard import *
from OpcLabs.EasyOpc.UA.AlarmsAndConditions import *
from OpcLabs.EasyOpc.UA.Filtering import *
from OpcLabs.EasyOpc.UA.OperationModel import *


def eventNotification(sender, eventArgs):
    # Display the event.
    print(eventArgs)


# Define which server we will work with.
endpointDescriptor = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer')

# Instantiate the client object and hook events.
client = EasyUAClient()
client.EventNotification += eventNotification

print('Subscribing...')

eventFilterBuilder = UAEventFilterBuilder(
    # Either the severity is >= 500, or the event comes from a specified source node.
    UAFilterElements.Or(
        UAFilterElements.GreaterThanOrEqual(UABaseEventObject.Operands.Severity, 500),
        UAFilterElements.Equals(
            UABaseEventObject.Operands.SourceNode,
            UANodeId('nsu=http://opcfoundation.org/Quickstarts/AlarmCondition ;ns=2;s=1:Metals/SouthMotor'))),
    UABaseEventObject.AllFields)

IEasyUAClientExtension.SubscribeEvent(
    client,
    endpointDescriptor,
    UANodeDescriptor(UAObjectIds.Server),
    1000,
    UAEventFilterBuilder.ToUAEventFilter(eventFilterBuilder))

print('Processing event notifications for 30 seconds...')
time.sleep(30)

print('Unsubscribing...')
client.UnsubscribeAllMonitoredItems()

print('Waiting for 5 seconds...')
time.sleep(5)

print('Finished.')
' This example shows how to specify criteria for event notifications.
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.AddressSpace
Imports OpcLabs.EasyOpc.UA.AddressSpace.Standard
Imports OpcLabs.EasyOpc.UA.AlarmsAndConditions
Imports OpcLabs.EasyOpc.UA.Filtering
Imports OpcLabs.EasyOpc.UA.OperationModel

Namespace AlarmsAndConditions
    Friend Class WhereClause
        Public Shared Sub Main1()
            ' Instantiate the client object and hook events
            Dim client = New EasyUAClient()
            AddHandler client.EventNotification, AddressOf client_EventNotification

            Console.WriteLine("Subscribing...")
            ' Either the severity is >= 500, or the event comes from a specified source node
            client.SubscribeEvent( _
                "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer", _
                UAObjectIds.Server, _
                1000, _
                New UAEventFilterBuilder( _
                    UAFilterElements.Or( _
                        UAFilterElements.GreaterThanOrEqual(UABaseEventObject.Operands.Severity, 500),
                        UAFilterElements.Equals( _
                            UABaseEventObject.Operands.SourceNode,
                            New UANodeId("nsu=http://opcfoundation.org/Quickstarts/AlarmCondition ;ns=2;s=1:Metals/SouthMotor"))),
                    UABaseEventObject.AllFields))

            Console.WriteLine("Processing event notifications for 30 seconds...")
            Threading.Thread.Sleep(30 * 1000)

            Console.WriteLine("Unsubscribing...")
            client.UnsubscribeAllMonitoredItems()

            Console.WriteLine("Waiting for 5 seconds...")
            Threading.Thread.Sleep(5 * 1000)
        End Sub

        Private Shared Sub client_EventNotification(ByVal sender As Object, ByVal e As EasyUAEventNotificationEventArgs)
            ' Display the event
            Console.WriteLine(e)
        End Sub
    End Class
End Namespace

COM

// This example shows how to specify criteria for event notifications.
//
// Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

type
  THelperMethods10 = class
    class function ObjectTypeIds_BaseEventType: _UANodeId; static;
    class function UABaseEventObject_Operands_EventId: _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_EventType: _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_NodeId: _UASimpleAttributeOperand; static;
    class function UAFilterElements_SimpleAttribute(TypeId: _UANodeId; simpleRelativeBrowsePathString: string): _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_SourceName: _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_Time: _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_ReceiveTime: _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_LocalTime: _UASimpleAttributeOperand;
    class function UABaseEventObject_Operands_SourceNode: _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_Message: _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_Severity: _UASimpleAttributeOperand; static;
    class function UABaseEventObject_AllFields: _UAAttributeFieldCollection; static;
  end;

type
  TClientEventHandlers10 = class
    procedure Client_EventNotification(
      ASender: TObject;
      sender: OleVariant;
      const eventArgs: _EasyUAEventNotificationEventArgs);
  end;

procedure TClientEventHandlers10.Client_EventNotification(
  ASender: TObject;
  sender: OleVariant;
  const eventArgs: _EasyUAEventNotificationEventArgs);
begin
  // Display the event
  WriteLn(eventArgs.ToString);
end;

class procedure WhereClause.Main;
const
  UAObjectIds_Server = 'nsu=http://opcfoundation.org/UA/;i=2253';
var
  Arguments: OleVariant;
  Client: TEasyUAClient;
  ClientEventHandlers: TClientEventHandlers10;
  Element1, Element2: _UAContentFilterElement;
  EndpointDescriptor: string;
  EventFilter: _UAEventFilter;
  MonitoredItemArguments: _EasyUAMonitoredItemArguments;
  MonitoringParameters: _UAMonitoringParameters;
  Operand1, Operand3: _UASimpleAttributeOperand;
  Operand2, Operand4: _UALiteralOperand;
  SourceNodeId: _UANodeId;
  WhereClause: _UAContentFilterElement;
begin
  EndpointDescriptor := 'opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer';

  // Instantiate the client object and hook events
  Client := TEasyUAClient.Create(nil);
  ClientEventHandlers := TClientEventHandlers10.Create;
  Client.OnEventNotification := ClientEventHandlers.Client_EventNotification;

  WriteLn('Subscribing...');

  WhereClause := CoUAContentFilterElement.Create;

  // Either the severity is >= 500, or the event comes from a specified source node
  Operand1 := THelperMethods10.UABaseEventObject_Operands_Severity;
  Operand2 := CoUALiteralOperand.Create;
  Operand2.Value := 500;
  Element1 := CoUAContentFilterElement.Create;
  Element1.FilterOperator := UAFilterOperator_GreaterThanOrEqual;
  Element1.FilterOperands.Add(Operand1);
  Element1.FilterOperands.Add(Operand2);
  Operand3 := THelperMethods10.UABaseEventObject_Operands_SourceNode;
  SourceNodeId := CoUANodeId.Create;
  SourceNodeId.ExpandedText := 'nsu=http://opcfoundation.org/Quickstarts/AlarmCondition;ns=2;s=1:Metals/SouthMotor';
  Operand4 := CoUALiteralOperand.Create;
  Operand4.Value := SourceNodeId;
  Element2 := CoUAContentFilterElement.Create;
  Element2.FilterOperator := UAFilterOperator_Equals;
  Element2.FilterOperands.Add(Operand3);
  Element2.FilterOperands.Add(Operand4);
  WhereClause.FilterOperator := UAFilterOperator_Or;
  WhereClause.FilterOperands.Add(Element1);
  WhereClause.FilterOperands.Add(Element2);

  EventFilter := CoUAEventFilter.Create;
  EventFilter.SelectClauses := THelperMethods10.UABaseEventObject_AllFields;
  EventFilter.WhereClause := WhereClause;

  MonitoringParameters := CoUAMonitoringParameters.Create;
  MonitoringParameters.SamplingInterval := 1000;
  MonitoringParameters.EventFilter := EventFilter;
  MonitoringParameters.QueueSize := 1000;

  MonitoredItemArguments := CoEasyUAMonitoredItemArguments.Create;
  MonitoredItemArguments.EndpointDescriptor.UrlString := 'opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer';
  MonitoredItemArguments.NodeDescriptor.NodeId.StandardName := 'Server';
  MonitoredItemArguments.MonitoringParameters := MonitoringParameters;
  //MonitoredItemArguments.SubscriptionParameters.PublishingInterval := 0;
  MonitoredItemArguments.AttributeId := UAAttributeId_EventNotifier;

  Arguments := VarArrayCreate([0, 0], varVariant);
  Arguments[0] := MonitoredItemArguments;

  Client.SubscribeMultipleMonitoredItems(Arguments);

  WriteLn('Processing event notifications for 30 seconds...');
  PumpSleep(30*1000);

  WriteLn('Unsubscribing...');
  Client.UnsubscribeAllMonitoredItems;

  WriteLn('Waiting for 5 seconds...');
  Sleep(5*1000);

  WriteLn('Finished.');
  VarClear(Arguments);
  FreeAndNil(Client);
  FreeAndNil(ClientEventHandlers);
end;


class function THelperMethods10.ObjectTypeIds_BaseEventType: _UANodeId;
  var NodeId: _UANodeId;
  begin
    NodeId := CoUANodeId.Create;
    NodeId.StandardName := 'BaseEventType';
    Result := NodeId;
  end;

class function THelperMethods10.UAFilterElements_SimpleAttribute(TypeId: _UANodeId; simpleRelativeBrowsePathString: string): _UASimpleAttributeOperand;
var
  BrowsePathParser: _UABrowsePathParser;
  Operand: _UASimpleAttributeOperand;
begin
  BrowsePathParser := CoUABrowsePathParser.Create;
  Operand := CoUASimpleAttributeOperand.Create;
  Operand.TypeId.NodeId := TypeId;
  Operand.QualifiedNames := BrowsePathParser.ParseRelative(simpleRelativeBrowsePathString).ToUAQualifiedNameCollection;
  Result := Operand;
end;

class function THelperMethods10.UABaseEventObject_Operands_EventId: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/EventId');
end;

class function THelperMethods10.UABaseEventObject_Operands_EventType: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/EventType');
end;

class function THelperMethods10.UABaseEventObject_Operands_NodeId: _UASimpleAttributeOperand;
var
  Operand: _UASimpleAttributeOperand;
begin
  Operand := CoUASimpleAttributeOperand.Create;
  Operand.TypeId.NodeId.StandardName := 'BaseEventType';
  Operand.AttributeId := UAAttributeId_NodeId;
  Result := Operand;
end;

class function THelperMethods10.UABaseEventObject_Operands_SourceNode: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/SourceNode');
end;

class function THelperMethods10.UABaseEventObject_Operands_SourceName: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/SourceName');
end;

class function THelperMethods10.UABaseEventObject_Operands_Time: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Time');
end;

class function THelperMethods10.UABaseEventObject_Operands_ReceiveTime: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/ReceiveTime');
end;

class function THelperMethods10.UABaseEventObject_Operands_LocalTime: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/LocalTime');
end;

class function THelperMethods10.UABaseEventObject_Operands_Message: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Message');
end;

class function THelperMethods10.UABaseEventObject_Operands_Severity: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Severity');
end;

class function THelperMethods10.UABaseEventObject_AllFields: _UAAttributeFieldCollection;
var
  Fields: _UAAttributeFieldCollection;
begin
  Fields := CoUAAttributeFieldCollection.Create;
  Fields.Add(UABaseEventObject_Operands_NodeId.ToUAAttributeField);
  Fields.Add(UABaseEventObject_Operands_EventId.ToUAAttributeField);
  Fields.Add(UABaseEventObject_Operands_EventType.ToUAAttributeField);
  Fields.Add(UABaseEventObject_Operands_SourceNode.ToUAAttributeField);
  Fields.Add(UABaseEventObject_Operands_SourceName.ToUAAttributeField);
  Fields.Add(UABaseEventObject_Operands_Time.ToUAAttributeField);
  Fields.Add(UABaseEventObject_Operands_ReceiveTime.ToUAAttributeField);
  Fields.Add(UABaseEventObject_Operands_LocalTime.ToUAAttributeField);
  Fields.Add(UABaseEventObject_Operands_Message.ToUAAttributeField);
  Fields.Add(UABaseEventObject_Operands_Severity.ToUAAttributeField);

  Result := Fields;
end;
// This example shows how to specify criteria for event notifications.
//
// Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

const UAAttributeId_NodeId = 1;
const UAAttributeId_EventNotifier = 12;

const UAFilterOperator_Equals = 1;
const UAFilterOperator_GreaterThanOrEqual = 5;
const UAFilterOperator_Or = 12;

const UAObjectIds_Server = 'nsu=http://opcfoundation.org/UA/;i=2253';

class ClientEvents {
    function EventNotification($Sender, $E)
    {
        // Display the event
        printf("%s\n", $E);
    }
}

$EndpointDescriptor = "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer";

// Instantiate the client object and hook events
$Client = new COM("OpcLabs.EasyOpc.UA.EasyUAClient");
$ClientEvents = new ClientEvents();
com_event_sink($Client, $ClientEvents, "DEasyUAClientEvents");

$WhereClause = new COM("OpcLabs.EasyOpc.UA.Filtering.UAContentFilterElement");

// Either the severity is >= 500, or the event comes from a specified source node
$Operand1 = UABaseEventObject_Operands_Severity();
$Operand2 = new COM("OpcLabs.EasyOpc.UA.Filtering.UALiteralOperand");
$Operand2->Value = 500;
$Element1 = new COM("OpcLabs.EasyOpc.UA.Filtering.UAContentFilterElement");
$Element1->FilterOperator = UAFilterOperator_GreaterThanOrEqual;
$Element1->FilterOperands->Add($Operand1);
$Element1->FilterOperands->Add($Operand2);
$Operand3 = UABaseEventObject_Operands_SourceNode();
$SourceNodeId = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
$SourceNodeId->ExpandedText = "nsu=http://opcfoundation.org/Quickstarts/AlarmCondition;ns=2;s=1:Metals/SouthMotor";
$Operand4 = new COM("OpcLabs.EasyOpc.UA.Filtering.UALiteralOperand");
$Operand4->Value = $SourceNodeId;
$Element2 = new COM("OpcLabs.EasyOpc.UA.Filtering.UAContentFilterElement");
$Element2->FilterOperator = UAFilterOperator_Equals;
$Element2->FilterOperands->Add($Operand3);
$Element2->FilterOperands->Add($Operand4);
$WhereClause->FilterOperator = UAFilterOperator_Or;
$WhereClause->FilterOperands->Add($Element1);
$WhereClause->FilterOperands->Add($Element2);

$EventFilter = new COM("OpcLabs.EasyOpc.UA.UAEventFilter");
$EventFilter->SelectClauses = UABaseEventObject_AllFields();
$EventFilter->WhereClause = $WhereClause;

$MonitoringParameters = new COM("OpcLabs.EasyOpc.UA.UAMonitoringParameters");
$MonitoringParameters->SamplingInterval = 1000;
$MonitoringParameters->EventFilter = $EventFilter;
$MonitoringParameters->QueueSize = 1000;

$MonitoredItemArguments = new COM("OpcLabs.EasyOpc.UA.OperationModel.EasyUAMonitoredItemArguments");
$MonitoredItemArguments->EndpointDescriptor->UrlString = $EndpointDescriptor;
$MonitoredItemArguments->NodeDescriptor->NodeId->StandardName = "Server";
$MonitoredItemArguments->MonitoringParameters = $MonitoringParameters;
/$MonitoredItemArguments->SubscriptionParameters->PublishingInterval = 0;
$MonitoredItemArguments->AttributeId = UAAttributeId_EventNotifier;

$arguments[0] = $MonitoredItemArguments;

printf("Subscribing...\n");
$Client->SubscribeMultipleMonitoredItems($arguments);

printf("Processing monitored item changed events for 30 seconds...\n");
$startTime = time(); do { com_message_pump(1000); } while (time() < $startTime + 30);

printf("Unsubscribing...\n");
$Client->UnsubscribeAllMonitoredItems;

printf("Waiting for 5 seconds...\n");
$startTime = time(); do { com_message_pump(1000); } while (time() < $startTime + 5);


function ObjectTypeIds_BaseEventType() {
    $NodeId = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
    $NodeId->StandardName = "BaseEventType";
    return $NodeId;
}

function UAFilterElements_SimpleAttribute($TypeId, $simpleRelativeBrowsePathString) {
  $BrowsePathParser = new COM("OpcLabs.EasyOpc.UA.Navigation.Parsing.UABrowsePathParser");
  $Operand = new COM("OpcLabs.EasyOpc.UA.Filtering.UASimpleAttributeOperand");
  $Operand->TypeId->NodeId = $TypeId;
  $Operand->QualifiedNames = $BrowsePathParser->ParseRelative($simpleRelativeBrowsePathString)->ToUAQualifiedNameCollection;
  return $Operand;
}

function UABaseEventObject_Operands_NodeId() {
    $Operand = new COM("OpcLabs.EasyOpc.UA.Filtering.UASimpleAttributeOperand");
    $Operand->TypeId->NodeId->StandardName = "BaseEventType";
    $Operand->AttributeId = UAAttributeId_NodeId;
    return $Operand;
}

function UABaseEventObject_Operands_EventId() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/EventId");
}

function UABaseEventObject_Operands_EventType() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/EventType");
}

function UABaseEventObject_Operands_SourceNode() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/SourceNode");
}

function UABaseEventObject_Operands_SourceName() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/SourceName");
}

function UABaseEventObject_Operands_Time() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/Time");
}

function UABaseEventObject_Operands_ReceiveTime() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/ReceiveTime");
}

function UABaseEventObject_Operands_LocalTime() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/LocalTime");
}

function UABaseEventObject_Operands_Message() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/Message");
}

function UABaseEventObject_Operands_Severity() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/Severity");
}

function UABaseEventObject_AllFields() {
    $Fields = new COM("OpcLabs.EasyOpc.UA.UAAttributeFieldCollection");
    $Fields->Add(UABaseEventObject_Operands_NodeId()->ToUAAttributeField);
    $Fields->Add(UABaseEventObject_Operands_EventId()->ToUAAttributeField);
    $Fields->Add(UABaseEventObject_Operands_EventType()->ToUAAttributeField);
    $Fields->Add(UABaseEventObject_Operands_SourceNode()->ToUAAttributeField);
    $Fields->Add(UABaseEventObject_Operands_SourceName()->ToUAAttributeField);
    $Fields->Add(UABaseEventObject_Operands_Time()->ToUAAttributeField);
    $Fields->Add(UABaseEventObject_Operands_ReceiveTime()->ToUAAttributeField);
    $Fields->Add(UABaseEventObject_Operands_LocalTime()->ToUAAttributeField);
    $Fields->Add(UABaseEventObject_Operands_Message()->ToUAAttributeField);
    $Fields->Add(UABaseEventObject_Operands_Severity()->ToUAAttributeField);

    return $Fields;
}
// This example shows how to specify criteria for event notifications.
//
// Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

type
  TClientEventHandlers3 = class
    procedure OnEventNotification(
      Sender: TObject;
      sender0: OleVariant;
      eventArgs: _EasyUAEventNotificationEventArgs);
  end;

procedure TClientEventHandlers3.OnEventNotification(
  Sender: TObject;
  sender0: OleVariant;
  eventArgs: _EasyUAEventNotificationEventArgs);
begin
  // Display the event
  WriteLn(eventArgs.ToString);
end;

class procedure WhereClause.Main;

  function ToUAAttributeField(Operand: UASimpleAttributeOperand): UAAttributeField;
  var
    AttributeField: UAAttributeField;
  begin
    AttributeField := CoUAAttributeField.Create;
    AttributeField.Operand := Operand;
    ToUAAttributeField := AttributeField;
  end;

  function ObjectTypeIds_BaseEventType: UANodeId;
  var
    NodeId: UANodeId;
  begin
    NodeId := CoUANodeId.Create;
    NodeId.StandardName := 'BaseEventType';
    ObjectTypeIds_BaseEventType := NodeId;
  end;

  function UAFilterElements_SimpleAttribute(TypeId: UANodeId; SimpleRelativeBrowsePathString: string): UASimpleAttributeOperand;
  var
    Operand: UASimpleAttributeOperand;
    BrowsePathParser: UABrowsePathParser;
  begin
    BrowsePathParser := CoUABrowsePathParser.Create;
    Operand := CoUASimpleAttributeOperand.Create;
    Operand.TypeId.NodeId := TypeId;
    Operand.QualifiedNames := BrowsePathParser.ParseRelative(SimpleRelativeBrowsePathString).ToUAQualifiedNameCollection;
    UAFilterElements_SimpleAttribute := Operand;
  end;

  function UABaseEventObject_Operands_NodeId: UASimpleAttributeOperand;
  var
    Operand: UASimpleAttributeOperand;
  begin
    Operand := CoUASimpleAttributeOperand.Create;
    Operand.TypeId.NodeId.StandardName := 'BaseEventType';
    Operand.AttributeId := UAAttributeId_NodeId;
    UABaseEventObject_Operands_NodeId := Operand;
  end;

  function UABaseEventObject_Operands_EventId: UASimpleAttributeOperand;
  begin
    UABaseEventObject_Operands_EventId := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/EventId');
  end;

  function UABaseEventObject_Operands_EventType: UASimpleAttributeOperand;
  begin
    UABaseEventObject_Operands_EventType := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/EventType');
  end;

  function UABaseEventObject_Operands_SourceNode: UASimpleAttributeOperand;
  begin
    UABaseEventObject_Operands_SourceNode := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/SourceNode');
  end;

  function UABaseEventObject_Operands_SourceName: UASimpleAttributeOperand;
  begin
    UABaseEventObject_Operands_SourceName := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/SourceName');
  end;

  function UABaseEventObject_Operands_Time: UASimpleAttributeOperand;
  begin
    UABaseEventObject_Operands_Time := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Time');
  end;

  function UABaseEventObject_Operands_ReceiveTime: UASimpleAttributeOperand;
  begin
    UABaseEventObject_Operands_ReceiveTime := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/ReceiveTime');
  end;

  function UABaseEventObject_Operands_LocalTime: UASimpleAttributeOperand;
  begin
    UABaseEventObject_Operands_LocalTime := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/LocalTime');
  end;

  function UABaseEventObject_Operands_Message: UASimpleAttributeOperand;
  begin
    UABaseEventObject_Operands_Message := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Message');
  end;

  function UABaseEventObject_Operands_Severity: UASimpleAttributeOperand;
  begin
    UABaseEventObject_Operands_Severity := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Severity');
  end;

  function UABaseEventObject_AllFields: UAAttributeFieldCollection;
  var
    Fields: UAAttributeFieldCollection;
  begin
    Fields := CoUAAttributeFieldCollection.Create;

    Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_NodeId));

    Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_EventId));
    Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_EventType));
    Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_SourceNode));
    Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_SourceName));
    Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_Time));
    Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_ReceiveTime));
    Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_LocalTime));
    Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_Message));
    Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_Severity));

    UABaseEventObject_AllFields := Fields;
  end;

var
  Arguments: OleVariant;
  EvsClient: TEvsEasyUAClient;
  Client: EasyUAClient;
  ClientEventHandlers: TClientEventHandlers3;
  Handle: Cardinal;
  HandleArray: OleVariant;
  MonitoredItemArguments: EasyUAMonitoredItemArguments;
  MonitoringParameters: UAMonitoringParameters;
  EventFilter: UAEventFilter;
  WhereClause: UAContentFilterElement;
  Operand1: UASimpleAttributeOperand;
  Operand2: UALiteralOperand;
  Operand3: UASimpleAttributeOperand;
  Operand4: UALiteralOperand;
  SourceNodeId: UANodeId;
  Element1, Element2: UAContentFilterElement;
  BaseEventType: UANodeId;
begin
  // Instantiate the client object and hook events
  EvsClient := TEvsEasyUAClient.Create(nil);
  Client := EvsClient.ComServer;
  ClientEventHandlers := TClientEventHandlers3.Create;
  EvsClient.OnEventNotification := @ClientEventHandlers.OnEventNotification;

  WriteLn('Subscribing...');

  WhereClause := CoUAContentFilterElement.Create;
  BaseEventType := CoUaNodeId.Create;
  BaseEventType.StandardName := 'BaseEventType';

  // Either the severity is >= 500, or the event comes from a specified source node
  Operand1 := UABaseEventObject_Operands_Severity;
  Operand2 := CoUALiteralOperand.Create;
  Operand2.Value := 500;
  Element1 := CoUAContentFilterElement.Create;
  Element1.FilterOperator := UAFilterOperator_GreaterThanOrEqual;
  Element1.FilterOperands.Add(Operand1);
  Element1.FilterOperands.Add(Operand2);
  Operand3 := UABaseEventObject_Operands_SourceNode;
  SourceNodeId := CoUANodeId.Create;
  SourceNodeId.ExpandedText := 'nsu=http://opcfoundation.org/Quickstarts/AlarmCondition;ns=2;s=1:Metals/SouthMotor';
  Operand4 := CoUALiteralOperand.Create;
  Operand4.Value := SourceNodeId;
  Element2 := CoUAContentFilterElement.Create;
  Element2.FilterOperator := UAFilterOperator_Equals;
  Element2.FilterOperands.Add(Operand3);
  Element2.FilterOperands.Add(Operand4);
  WhereClause.FilterOperator := UAFilterOperator_Or;
  WhereClause.FilterOperands.Add(Element1);
  WhereClause.FilterOperands.Add(Element2);

  EventFilter := CoUAEventFilter.Create;
  EventFilter.SelectClauses := UABaseEventObject_AllFields;
  EventFilter.WhereClause := WhereClause;

  MonitoringParameters := CoUAMonitoringParameters.Create;
  MonitoringParameters.SamplingInterval := 1000;
  MonitoringParameters.EventFilter := EventFilter;
  MonitoringParameters.QueueSize := 1000;

  MonitoredItemArguments := CoEasyUAMonitoredItemArguments.Create;
  MonitoredItemArguments.EndpointDescriptor.UrlString := 'opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer';
  MonitoredItemArguments.NodeDescriptor.NodeId.StandardName := 'Server';
  MonitoredItemArguments.MonitoringParameters := MonitoringParameters;
  //MonitoredItemArguments.SubscriptionParameters.PublishingInterval := 0;
  MonitoredItemArguments.AttributeId := UAAttributeId_EventNotifier;

  Arguments := VarArrayCreate([0, 0], varVariant);
  Arguments[0] := MonitoredItemArguments;

  TVarData(HandleArray).VType := varArray or varVariant;
  TVarData(HandleArray).VArray := PVarArray(
    Client.SubscribeMultipleMonitoredItems(PSafeArray(TVarData(Arguments).VArray)));

  WriteLn('Processing event notifications for 30 seconds...');
  PumpSleep(30*1000);

  WriteLn('Unsubscribing...');
  Client.UnsubscribeAllMonitoredItems;

  WriteLn('Waiting for 5 seconds...');
  PumpSleep(5*1000);

  WriteLn('Finished...');
end;

 

 

 

Example

.NET

COM

.NET

COM

.NET

// This example shows how to select fields for event notifications.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

using System;
using System.Collections.Generic;
using OpcLabs.BaseLib.OperationModel;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.AddressSpace.Standard;
using OpcLabs.EasyOpc.UA.AlarmsAndConditions;
using OpcLabs.EasyOpc.UA.Filtering;
using OpcLabs.EasyOpc.UA.OperationModel;

namespace UADocExamples.AlarmsAndConditions
{
    class SelectClauses
    {
        public static void Main1()
        {
            UAEndpointDescriptor endpointDescriptor =
                "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer";

            // Instantiate the client object and hook events.
            var client = new EasyUAClient();
            client.EventNotification += client_EventNotification;

            Console.WriteLine("Subscribing...");
            client.SubscribeEvent(
                endpointDescriptor,
                UAObjectIds.Server,
                1000,
                new UAAttributeFieldCollection
                {
                    // Select specific fields using standard operand symbols.
                    UABaseEventObject.Operands.NodeId,
                    UABaseEventObject.Operands.SourceNode,
                    UABaseEventObject.Operands.SourceName,
                    UABaseEventObject.Operands.Time,

                    // Select specific fields using an event type ID and a simple relative path.
                    UAFilterElements.SimpleAttribute(UAObjectTypeIds.BaseEventType, "/Message"),
                    UAFilterElements.SimpleAttribute(UAObjectTypeIds.BaseEventType, "/Severity")
                });

            Console.WriteLine("Processing event notifications for 30 seconds...");
            System.Threading.Thread.Sleep(30 * 1000);

            Console.WriteLine("Unsubscribing...");
            client.UnsubscribeAllMonitoredItems();

            Console.WriteLine("Waiting for 5 seconds...");
            System.Threading.Thread.Sleep(5 * 1000);

            Console.WriteLine("Finished.");
        }

        static void client_EventNotification(object sender, EasyUAEventNotificationEventArgs e)
        {
            Console.WriteLine();

            // Display the event.
            if (e.EventData is null)
            {
                Console.WriteLine(e);
                return;
            }
            Console.WriteLine("All fields:");
            foreach (KeyValuePair<UAAttributeField, ValueResult> pair in e.EventData.FieldResults)
            {
                UAAttributeField attributeField = pair.Key;
                ValueResult valueResult = pair.Value;
                Console.WriteLine($"  {attributeField} -> {valueResult}");
            }

            // Extracting a specific field using a standard operand symbol.
            Console.WriteLine($"Source name: {e.EventData.FieldResults[UABaseEventObject.Operands.SourceName]}");

            // Extracting a specific field using an event type ID and a simple relative path.
            Console.WriteLine(
                $"Message: {e.EventData.FieldResults[UAFilterElements.SimpleAttribute(UAObjectTypeIds.BaseEventType, "/Message")]}");
        }
    }
}
# This example shows how to select fields for event notifications.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

#requires -Version 5.1
using namespace OpcLabs.BaseLib.OperationModel
using namespace OpcLabs.EasyOpc.UA
using namespace OpcLabs.EasyOpc.UA.AddressSpace
using namespace OpcLabs.EasyOpc.UA.AddressSpace.Standard
using namespace OpcLabs.EasyOpc.UA.AlarmsAndConditions
using namespace OpcLabs.EasyOpc.UA.Filtering

# The path below assumes that the current directory is [ProductDir]/Examples-NET/PowerShell/Windows .
Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.EasyOpcUA.dll"
Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.EasyOpcUAComponents.dll"

# Define which server we will work with.
[UAEndpointDescriptor]$endpointDescriptor = "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer"

# Instantiate the client object.
$client = New-Object EasyUAClient

# Event notification handler
Register-ObjectEvent -InputObject $client -EventName EventNotification -Action { 
    Write-Host 

    # Display the event.
    if ($EventArgs.EventData -eq $null) {
        Write-Host $EventArgs
        return
    }
    Write-Host "All fields:"
    foreach ($pair in $EventArgs.EventData.FieldResults.GetEnumerator()) {
        [UAAttributeField]$attributeField = $pair.Key
        [ValueResult]$valueResult = $pair.Value
        Write-Host "  $($attributeField) -> $($valueResult)"
    }

    # Extracting a specific field using a standard operand symbol.
    Write-Host "Source name: $($EventArgs.EventData.FieldResults[[UABaseEventObject+Operands]::SourceName])"

    # Extracting a specific field using an event type ID and a simple relative path.
    Write-Host `
        "Message: $($EventArgs.EventData.FieldResults[[UAFilterElements]::SimpleAttribute([UAObjectTypeIds]::BaseEventType, "/Message")])"
}

Write-Host "Subscribing..."

$attributeFieldCollection = New-Object UAAttributeFieldCollection

# Select specific fields using standard operand symbols.
$attributeFieldCollection.Add([UABaseEventObject+Operands]::NodeId)
$attributeFieldCollection.Add([UABaseEventObject+Operands]::SourceNode)
$attributeFieldCollection.Add([UABaseEventObject+Operands]::SourceName) 
$attributeFieldCollection.Add([UABaseEventObject+Operands]::Time)

# Select specific fields using an event type ID and a simple relative path.
$attributeFieldCollection.Add([UAFilterElements]::SimpleAttribute([UAObjectTypeIds]::BaseEventType, "/Message"))
$attributeFieldCollection.Add([UAFilterElements]::SimpleAttribute([UAObjectTypeIds]::BaseEventType, "/Severity"))

[IEasyUAClientExtension]::SubscribeEvent($client, 
    $endpointDescriptor, [UAObjectIds]::Server, 1000, [UAEventFilter]$attributeFieldCollection)

Write-Host "Processing event notifications for 30 seconds..."
$stopwatch =  [System.Diagnostics.Stopwatch]::StartNew() 
while ($stopwatch.Elapsed.TotalSeconds -lt 30) {    
    Start-Sleep -Seconds 1
}

Write-Host "Unsubscribing..."
$client.UnsubscribeAllMonitoredItems()

Write-Host "Waiting for 5 seconds..."
Start-Sleep -Seconds 5

Write-Host "Finished."
# This example shows how to select fields for event notifications.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python .
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc
import time

# Import .NET namespaces.
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.AddressSpace.Standard import *
from OpcLabs.EasyOpc.UA.AlarmsAndConditions import *
from OpcLabs.EasyOpc.UA.Filtering import *
from OpcLabs.EasyOpc.UA.OperationModel import *


def eventNotification(sender, eventArgs):
    print()

    # Display the event.
    if eventArgs.EventData is None:
        print(eventArgs)
        return
    print('All fields:')
    for pair in eventArgs.EventData.FieldResults:
        attributeField = pair.Key
        valueResult = pair.Value
        print('  ', attributeField, ' -> ', valueResult, sep='')

    # Extracting a specific field using a standard operand symbol.
    print('Source name: ',
          eventArgs.EventData.FieldResults.get_Item(UAAttributeField(UABaseEventObject.Operands.SourceName)),
          sep='')

    # Extracting a specific field using an event type ID and a simple relative path.
    print('Message: ',
          eventArgs.EventData.FieldResults.get_Item(UAAttributeField(
              UAFilterElements.SimpleAttribute(UANodeDescriptor(UAObjectTypeIds.BaseEventType), '/Message'))),
          sep='')


# Define which server we will work with.
endpointDescriptor = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer')

# Instantiate the client object and hook events.
client = EasyUAClient()
client.EventNotification += eventNotification

print('Subscribing...')
attributeFieldCollection = UAAttributeFieldCollection([
    # Select specific fields using standard operand symbols.
    UAAttributeField(UABaseEventObject.Operands.NodeId),
    UAAttributeField(UABaseEventObject.Operands.SourceNode),
    UAAttributeField(UABaseEventObject.Operands.SourceName),
    UAAttributeField(UABaseEventObject.Operands.Time),

    # Select specific fields using an event type ID and a simple relative path.
    UAAttributeField(UAFilterElements.SimpleAttribute(UANodeDescriptor(UAObjectTypeIds.BaseEventType), "/Message")),
    UAAttributeField(UAFilterElements.SimpleAttribute(UANodeDescriptor(UAObjectTypeIds.BaseEventType), "/Severity"))
    ])
IEasyUAClientExtension.SubscribeEvent(
    client,
    endpointDescriptor,
    UANodeDescriptor(UAObjectIds.Server),
    1000,
    UAEventFilter(attributeFieldCollection))

print('Processing event notifications for 30 seconds...')
time.sleep(30)

print()
print('Unsubscribing...')
client.UnsubscribeAllMonitoredItems()

print('Waiting for 5 seconds...')
time.sleep(5)

print('Finished.')
' This example shows how to select fields for event notifications.
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.AddressSpace.Standard
Imports OpcLabs.EasyOpc.UA.AlarmsAndConditions
Imports OpcLabs.EasyOpc.UA.Filtering
Imports OpcLabs.EasyOpc.UA.OperationModel

Namespace AlarmsAndConditions
    Friend Class SelectClauses
        Public Shared Sub Main1()
            ' Instantiate the client object and hook events
            Dim client = New EasyUAClient()
            AddHandler client.EventNotification, AddressOf client_EventNotification

            Console.WriteLine("Subscribing...")
            ' Select specific fields using standard operand symbols
            ' Select specific fields using an event type ID and a simple relative path
            client.SubscribeEvent( _
                "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer", _
                UAObjectIds.Server, _
                1000, _
                New UAAttributeFieldCollection() From
                {
                    UABaseEventObject.Operands.NodeId,
                    UABaseEventObject.Operands.SourceNode,
                    UABaseEventObject.Operands.SourceName,
                    UABaseEventObject.Operands.Time,
 _
                    UAFilterElements.SimpleAttribute(UAObjectTypeIds.BaseEventType, "/Message"),
                    UAFilterElements.SimpleAttribute(UAObjectTypeIds.BaseEventType, "/Severity")
                })

            Console.WriteLine("Processing event notifications for 30 seconds...")
            Threading.Thread.Sleep(30 * 1000)

            Console.WriteLine("Unsubscribing...")
            client.UnsubscribeAllMonitoredItems()

            Console.WriteLine("Waiting for 5 seconds...")
            Threading.Thread.Sleep(5 * 1000)
        End Sub

        Private Shared Sub client_EventNotification(ByVal sender As Object, ByVal e As EasyUAEventNotificationEventArgs)
            Console.WriteLine()

            ' Display the event
            If e.EventData Is Nothing Then
                Console.WriteLine(e)
                Exit Sub
            End If
            For Each pair In e.EventData.FieldResults
                Dim attributeField = pair.Key
                Dim valueResult = pair.Value
                Console.WriteLine("  {0} -> {1}", attributeField, valueResult)
            Next pair
            ' Extracting a specific field using a standard operand symbol
            Console.WriteLine("Source name: {0}", _
                e.EventData.FieldResults(UABaseEventObject.Operands.SourceName))
            ' Extracting a specific field using an event type ID and a simple relative path
            Console.WriteLine("Message: {0}", _
                e.EventData.FieldResults(UAFilterElements.SimpleAttribute(UAObjectTypeIds.BaseEventType, "/Message")))
        End Sub
    End Class
End Namespace
// This example shows how to select fields for event notifications.
//
// Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

type
  TClientEventHandlers4 = class
    procedure OnEventNotification(
      Sender: TObject;
      sender0: OleVariant;
      eventArgs: _EasyUAEventNotificationEventArgs);
  end;

procedure TClientEventHandlers4.OnEventNotification(
  Sender: TObject;
  sender0: OleVariant;
  eventArgs: _EasyUAEventNotificationEventArgs);

  function ToUAAttributeField(Operand: UASimpleAttributeOperand): UAAttributeField;
  var
    AttributeField: UAAttributeField;
  begin
    AttributeField := CoUAAttributeField.Create;
    AttributeField.Operand := Operand;
    ToUAAttributeField := AttributeField;
  end;

  function UAFilterElements_SimpleAttribute(TypeId: UANodeId; SimpleRelativeBrowsePathString: string): UASimpleAttributeOperand;
  var
    Operand: UASimpleAttributeOperand;
    BrowsePathParser: UABrowsePathParser;
  begin
    BrowsePathParser := CoUABrowsePathParser.Create;
    Operand := CoUASimpleAttributeOperand.Create;
    Operand.TypeId.NodeId := TypeId;
    Operand.QualifiedNames := BrowsePathParser.ParseRelative(SimpleRelativeBrowsePathString).ToUAQualifiedNameCollection;
    UAFilterElements_SimpleAttribute := Operand;
  end;

  function ObjectTypeIds_BaseEventType: UANodeId;
  var
    NodeId: UANodeId;
  begin
    NodeId := CoUANodeId.Create;
    NodeId.StandardName := 'BaseEventType';
    ObjectTypeIds_BaseEventType := NodeId;
  end;

var
  Count: Cardinal;
  Element: OleVariant;
  EntryEnumerator: IEnumVariant;
  Entry: DictionaryEntry2;
  AttributeField: UAAttributeField;
  AValueResult: ValueResult;
begin
  WriteLn;

  // Display the event
  if eventArgs.EventData = nil then
  begin
    WriteLn(eventArgs.ToString);
    Exit;
  end;
  WriteLn('All fields:');
  EntryEnumerator := eventArgs.EventData.FieldResults.GetEnumerator;
  while EntryEnumerator.Next(1, Element, Count) = S_OK do
  begin
    Entry := IUnknown(Element) as DictionaryEntry2;
    AttributeField := IUnknown(Entry.key) as UAAttributeField;
    AValueResult := IUnknown(Entry.Value) as ValueResult;
    WriteLn('  ', AttributeField.ToString, ' -> ', AValueResult.ToString);
  end;
  // Extracting a specific field using an event type ID and a simple relative path
  WriteLn('Source name: ',
    eventArgs.EventData.FieldResults[ToUAAttributeField(UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/SourceName'))].ToString);
  WriteLn('Message: ',
    eventArgs.EventData.FieldResults[ToUAAttributeField(UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Message'))].ToString);
end;

class procedure SelectClauses.Main;

  function ToUAAttributeField(Operand: UASimpleAttributeOperand): UAAttributeField;
  var
    AttributeField: UAAttributeField;
  begin
    AttributeField := CoUAAttributeField.Create;
    AttributeField.Operand := Operand;
    ToUAAttributeField := AttributeField;
  end;

  function ObjectTypeIds_BaseEventType: UANodeId;
  var
    NodeId: UANodeId;
  begin
    NodeId := CoUANodeId.Create;
    NodeId.StandardName := 'BaseEventType';
    ObjectTypeIds_BaseEventType := NodeId;
  end;

  function UABaseEventObject_Operands_NodeId: UASimpleAttributeOperand;
  var
    Operand: UASimpleAttributeOperand;
  begin
    Operand := CoUASimpleAttributeOperand.Create;
    Operand.TypeId.NodeId.StandardName := 'BaseEventType';
    Operand.AttributeId := UAAttributeId_NodeId;
    UABaseEventObject_Operands_NodeId := Operand;
  end;

  function UAFilterElements_SimpleAttribute(TypeId: UANodeId; SimpleRelativeBrowsePathString: string): UASimpleAttributeOperand;
  var
    Operand: UASimpleAttributeOperand;
    BrowsePathParser: UABrowsePathParser;
  begin
    BrowsePathParser := CoUABrowsePathParser.Create;
    Operand := CoUASimpleAttributeOperand.Create;
    Operand.TypeId.NodeId := TypeId;
    Operand.QualifiedNames := BrowsePathParser.ParseRelative(SimpleRelativeBrowsePathString).ToUAQualifiedNameCollection;
    UAFilterElements_SimpleAttribute := Operand;
  end;

var
  Arguments: OleVariant;
  EvsClient: TEvsEasyUAClient;
  Client: EasyUAClient;
  ClientEventHandlers: TClientEventHandlers4;
  Handle: Cardinal;
  HandleArray: OleVariant;
  MonitoredItemArguments: EasyUAMonitoredItemArguments;
  MonitoringParameters: UAMonitoringParameters;
  EventFilter: UAEventFilter;
  SelectClauses: UAAttributeFieldCollection;
begin
  // Instantiate the client object and hook events
  EvsClient := TEvsEasyUAClient.Create(nil);
  Client := EvsClient.ComServer;
  ClientEventHandlers := TClientEventHandlers4.Create;
  EvsClient.OnEventNotification := @ClientEventHandlers.OnEventNotification;

  WriteLn('Subscribing...');

  SelectClauses := CoUAAttributeFieldCollection.Create;
  // Select specific fields using an event type ID and a simple relative path
  SelectClauses.Add(ToUAAttributeField(UABaseEventObject_Operands_NodeId));
  SelectClauses.Add(ToUAAttributeField(UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/SourceNode')));
  SelectClauses.Add(ToUAAttributeField(UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/SourceName')));
  SelectClauses.Add(ToUAAttributeField(UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Time')));
  SelectClauses.Add(ToUAAttributeField(UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Message')));
  SelectClauses.Add(ToUAAttributeField(UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Severity')));

  EventFilter := CoUAEventFilter.Create;
  EventFilter.SelectClauses := SelectClauses;

  MonitoringParameters := CoUAMonitoringParameters.Create;
  MonitoringParameters.SamplingInterval := 1000;
  MonitoringParameters.EventFilter := EventFilter;
  MonitoringParameters.QueueSize := 1000;

  MonitoredItemArguments := CoEasyUAMonitoredItemArguments.Create;
  MonitoredItemArguments.EndpointDescriptor.UrlString := 'opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer';
  MonitoredItemArguments.NodeDescriptor.NodeId.StandardName := 'Server';
  MonitoredItemArguments.MonitoringParameters := MonitoringParameters;
  //MonitoredItemArguments.SubscriptionParameters.PublishingInterval := 0;
  MonitoredItemArguments.AttributeId := UAAttributeId_EventNotifier;

  Arguments := VarArrayCreate([0, 0], varVariant);
  Arguments[0] := MonitoredItemArguments;

  TVarData(HandleArray).VType := varArray or varVariant;
  TVarData(HandleArray).VArray := PVarArray(
    Client.SubscribeMultipleMonitoredItems(PSafeArray(TVarData(Arguments).VArray)));

  WriteLn('Processing event notifications for 30 seconds...');
  PumpSleep(30*1000);

  WriteLn('Unsubscribing...');
  Client.UnsubscribeAllMonitoredItems;

  WriteLn('Waiting for 5 seconds...');
  PumpSleep(5*1000);

  WriteLn('Finished...');
end;
// This example shows how to select fields for event notifications.
//
// Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

type
  THelperMethods17 = class
    class function ObjectTypeIds_BaseEventType: _UANodeId; static;
    class function UABaseEventObject_Operands_NodeId: _UASimpleAttributeOperand;
    class function UAFilterElements_SimpleAttribute(TypeId: _UANodeId; simpleRelativeBrowsePathString: string): _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_SourceName: _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_Time: _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_SourceNode: _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_Message: _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_Severity: _UASimpleAttributeOperand; static;
  end;

type
  TClientEventHandlers17 = class
    procedure Client_EventNotification(
      ASender: TObject;
      sender: OleVariant;
      const eventArgs: _EasyUAEventNotificationEventArgs);
  end;

procedure TClientEventHandlers17.Client_EventNotification(
  ASender: TObject;
  sender: OleVariant;
  const eventArgs: _EasyUAEventNotificationEventArgs);
var
  AttributeField: OleVariant;
  Count: Cardinal;
  Element: OleVariant;
  EntryEnumerator: IEnumVARIANT;
  ValueResult: OleVariant;
begin
  WriteLn;

  // Display the event
  if eventArgs.EventData = nil then
  begin
    WriteLn(eventArgs.ToString);
    Exit;
  end;

  WriteLn('All fields:');

  EntryEnumerator := eventArgs.EventData.FieldResults.GetEnumerator;
  while (EntryEnumerator.Next(1, Element, Count) = S_OK) do
  begin
    AttributeField := IUnknown(Element.Key) as _UAAttributeField;
    ValueResult := IUnknown(Element.Value) as _ValueResult;
    WriteLn(' ', AttributeField.ToString, ' -> ', ValueResult.ToString);
  end;

  // Extracting specific fields using an event type ID and a simple relative path
  WriteLn('Source name: ', eventArgs.EventData.FieldResults.Item[THelperMethods17.UABaseEventObject_Operands_SourceName.ToUAAttributeField].ToString);
  WriteLn('Message: ', eventArgs.EventData.FieldResults.Item[THelperMethods17.UABaseEventObject_Operands_Message.ToUAAttributeField].ToString);
end;

class procedure SelectClauses.Main;
const
  UAObjectIds_Server = 'nsu=http://opcfoundation.org/UA/;i=2253';
var
  Arguments: OleVariant;
  Client: TEasyUAClient;
  ClientEventHandlers: TClientEventHandlers17;
  EndpointDescriptor: string;
  EventFilter: _UAEventFilter;
  MonitoredItemArguments: _EasyUAMonitoredItemArguments;
  MonitoringParameters: _UAMonitoringParameters;
  SelectClauses: UAAttributeFieldCollection;
begin
  EndpointDescriptor := 'opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer';

  // Instantiate the client object and hook events
  Client := TEasyUAClient.Create(nil);
  ClientEventHandlers := TClientEventHandlers17.Create;
  Client.OnEventNotification := ClientEventHandlers.Client_EventNotification;

  WriteLn('Subscribing...');

  SelectClauses := CoUAAttributeFieldCollection.Create;
  // Select specific fields using an event type ID and a simple relative path
  SelectClauses.Add(THelperMethods17.UABaseEventObject_Operands_NodeId.ToUAAttributeField);
  SelectClauses.Add(THelperMethods17.UABaseEventObject_Operands_SourceNode.ToUAAttributeField);
  SelectClauses.Add(THelperMethods17.UABaseEventObject_Operands_SourceName.ToUAAttributeField);
  SelectClauses.Add(THelperMethods17.UABaseEventObject_Operands_Time.ToUAAttributeField);
  SelectClauses.Add(THelperMethods17.UABaseEventObject_Operands_Message.ToUAAttributeField);
  SelectClauses.Add(THelperMethods17.UABaseEventObject_Operands_Severity.ToUAAttributeField);

  EventFilter := CoUAEventFilter.Create;
  EventFilter.SelectClauses := SelectClauses;

  MonitoringParameters := CoUAMonitoringParameters.Create;
  MonitoringParameters.SamplingInterval := 1000;
  MonitoringParameters.EventFilter := EventFilter;
  MonitoringParameters.QueueSize := 1000;

  MonitoredItemArguments := CoEasyUAMonitoredItemArguments.Create;
  MonitoredItemArguments.EndpointDescriptor.UrlString := EndpointDescriptor;
  MonitoredItemArguments.NodeDescriptor.NodeId.StandardName := 'Server';
  MonitoredItemArguments.MonitoringParameters := MonitoringParameters;
  //MonitoredItemArguments.SubscriptionParameters.PublishingInterval := 0;
  MonitoredItemArguments.AttributeId := UAAttributeId_EventNotifier;

  Arguments := VarArrayCreate([0, 0], varVariant);
  Arguments[0] := MonitoredItemArguments;

  Client.SubscribeMultipleMonitoredItems(Arguments);

  WriteLn('Processing event notifications for 30 seconds...');
  PumpSleep(30*1000);

  WriteLn('Unsubscribing...');
  Client.UnsubscribeAllMonitoredItems;

  WriteLn('Waiting for 5 seconds...');
  Sleep(5*1000);

  WriteLn('Finished.');
  VarClear(Arguments);
  FreeAndNil(Client);
  FreeAndNil(ClientEventHandlers);
end;


class function THelperMethods17.ObjectTypeIds_BaseEventType: _UANodeId;
  var NodeId: _UANodeId;
  begin
    NodeId := CoUANodeId.Create;
    NodeId.StandardName := 'BaseEventType';
    Result := NodeId;
  end;

class function THelperMethods17.UAFilterElements_SimpleAttribute(TypeId: _UANodeId; simpleRelativeBrowsePathString: string): _UASimpleAttributeOperand;
var
  BrowsePathParser: _UABrowsePathParser;
  Operand: _UASimpleAttributeOperand;
begin
  BrowsePathParser := CoUABrowsePathParser.Create;
  Operand := CoUASimpleAttributeOperand.Create;
  Operand.TypeId.NodeId := TypeId;
  Operand.QualifiedNames := BrowsePathParser.ParseRelative(simpleRelativeBrowsePathString).ToUAQualifiedNameCollection;
  Result := Operand;
end;

class function THelperMethods17.UABaseEventObject_Operands_NodeId: _UASimpleAttributeOperand;
var
  Operand: _UASimpleAttributeOperand;
begin
  Operand := CoUASimpleAttributeOperand.Create;
  Operand.TypeId.NodeId.StandardName := 'BaseEventType';
  Operand.AttributeId := UAAttributeId_NodeId;
  Result := Operand;
end;

class function THelperMethods17.UABaseEventObject_Operands_SourceNode: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/SourceNode');
end;

class function THelperMethods17.UABaseEventObject_Operands_SourceName: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/SourceName');
end;

class function THelperMethods17.UABaseEventObject_Operands_Time: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Time');
end;

class function THelperMethods17.UABaseEventObject_Operands_Message: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Message');
end;

class function THelperMethods17.UABaseEventObject_Operands_Severity: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Severity');
end;
// This example shows how to select fields for event notifications.
//
// Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

const UAAttributeId_NodeId = 1;
const UAAttributeId_EventNotifier = 12;

class ClientEvents {
    function EventNotification($Sender, $E)
    {
        printf("\n");

        // Display the event
        if (is_null($E->EventData)) {
            printf("%s\n", $E);
            return;
        }

        printf("All fields:\n");

        foreach ($E->EventData->FieldResults as $Pair)
        {
            $AttributeField = $Pair->Key;
            $ValueResult = $Pair->Value;
            printf("  %s -> %s\n", $AttributeField, $ValueResult);
        }

        // Extracting specific fields using an event type ID and a simple relative path
        printf("Source name: %s\n", $E->EventData->FieldResults->Item(UABaseEventObject_Operands_SourceName()->ToUAAttributeField()));
        printf("Message: %s\n", $E->EventData->FieldResults->Item(UABaseEventObject_Operands_Message()->ToUAAttributeField()));
    }
}

const UAObjectIds_Server = "nsu=http://opcfoundation.org/UA/;i=2253";

$EndpointDescriptor = "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer";

// Instantiate the client object and hook events
$Client = new COM("OpcLabs.EasyOpc.UA.EasyUAClient");
$ClientEvents = new ClientEvents();
com_event_sink($Client, $ClientEvents, "DEasyUAClientEvents");

printf("Subscribing...\n");

$SelectClauses = new COM("OpcLabs.EasyOpc.UA.UAAttributeFieldCollection");
// Select specific fields using an event type ID and a simple relative path
$SelectClauses->Add(UABaseEventObject_Operands_NodeId()->ToUAAttributeField());
$SelectClauses->Add(UABaseEventObject_Operands_SourceNode()->ToUAAttributeField());
$SelectClauses->Add(UABaseEventObject_Operands_SourceName()->ToUAAttributeField());
$SelectClauses->Add(UABaseEventObject_Operands_Time()->ToUAAttributeField());
$SelectClauses->Add(UABaseEventObject_Operands_Message()->ToUAAttributeField());
$SelectClauses->Add(UABaseEventObject_Operands_Severity()->ToUAAttributeField());

$EventFilter = new COM("OpcLabs.EasyOpc.UA.UAEventFilter");
$EventFilter->SelectClauses = $SelectClauses;

$MonitoringParameters = new COM("OpcLabs.EasyOpc.UA.UAMonitoringParameters");
$MonitoringParameters->EventFilter = $EventFilter;
$MonitoringParameters->QueueSize = 1000;
$MonitoringParameters->SamplingInterval = 1000;

$MonitoredItemArguments = new COM("OpcLabs.EasyOpc.UA.OperationModel.EasyUAMonitoredItemArguments");
$MonitoredItemArguments->EndpointDescriptor->UrlString = $EndpointDescriptor;
$MonitoredItemArguments->NodeDescriptor->NodeId->StandardName = "Server";
$MonitoredItemArguments->MonitoringParameters = $MonitoringParameters;
// $MonitoredItemArguments->SubscriptionParameters->PublishingInterval = 0;
$MonitoredItemArguments->AttributeId = UAAttributeId_EventNotifier;

$Arguments[0] = $MonitoredItemArguments;

$Client->SubscribeMultipleMonitoredItems($Arguments);

printf("Processing event notifications for 30 seconds...\n");
$startTime = time(); do { com_message_pump(1000); } while (time() < $startTime + 30);

printf("Unsubscribing...\n");
$Client->UnsubscribeAllMonitoredItems;

printf("Waiting for 5 seconds...\n");
$startTime = time(); do { com_message_pump(1000); } while (time() < $startTime + 5);


function ObjectTypeIds_BaseEventType() {
    $NodeId = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
    $NodeId->StandardName = "BaseEventType";
    return $NodeId;
}

function UAFilterElements_SimpleAttribute($TypeId, $simpleRelativeBrowsePathString) {
  $BrowsePathParser = new COM("OpcLabs.EasyOpc.UA.Navigation.Parsing.UABrowsePathParser");
  $Operand = new COM("OpcLabs.EasyOpc.UA.Filtering.UASimpleAttributeOperand");
  $Operand->TypeId->NodeId = $TypeId;
  $Operand->QualifiedNames = $BrowsePathParser->ParseRelative($simpleRelativeBrowsePathString)->ToUAQualifiedNameCollection;
  return $Operand;
}

function UABaseEventObject_Operands_NodeId() {
    $Operand = new COM("OpcLabs.EasyOpc.UA.Filtering.UASimpleAttributeOperand");
    $Operand->TypeId->NodeId->StandardName = "BaseEventType";
    $Operand->AttributeId = UAAttributeId_NodeId;
    return $Operand;
}

function UABaseEventObject_Operands_SourceNode() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/SourceNode");
}

function UABaseEventObject_Operands_SourceName() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/SourceName");
}

function UABaseEventObject_Operands_Time() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/Time");
}

function UABaseEventObject_Operands_Message() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/Message");
}

function UABaseEventObject_Operands_Severity() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/Severity");
}


// Example output (truncated):
//Subscribing...
//Processing event notifications for 30 seconds...
//
//[] Success
//
//[] Success; Refresh; RefreshInitiated
//
//All fields:
//  NodeId="BaseEventType", NodeId -> Success; nsu=http://opcfoundation.org/Quickstarts/AlarmCondition ;ns=2;s=1:Colours/EastTank?OnlineState {OpcLabs.EasyOpc.UA.AddressSpace.UANodeId}
//  NodeId="BaseEventType"/EventId -> Success; [16] {95, 68, 22, 205, 114, ...} {System.Byte[]}
//  NodeId="BaseEventType"/EventType -> Success; DialogConditionType {OpcLabs.EasyOpc.UA.AddressSpace.UANodeId}
//  NodeId="BaseEventType"/SourceNode -> Success; nsu=http://opcfoundation.org/Quickstarts/AlarmCondition ;ns=2;s=1:Colours/EastTank {OpcLabs.EasyOpc.UA.AddressSpace.UANodeId}
//  NodeId="BaseEventType"/SourceName -> Success; EastTank {System.String}
//  NodeId="BaseEventType"/Time -> Success; 9/10/2019 8:08:23 PM {System.DateTime}
//  NodeId="BaseEventType"/ReceiveTime -> Success; 9/10/2019 8:08:23 PM {System.DateTime}
//  NodeId="BaseEventType"/LocalTime -> Success; 00:00, DST {OpcLabs.EasyOpc.UA.UATimeZoneData}
//  NodeId="BaseEventType"/Message -> Success; The dialog was activated {System.String}
//  NodeId="BaseEventType"/Severity -> Success; 100 {System.Int32}
//Source name: Success; EastTank {System.String}
//Message: Success; The dialog was activated {System.String}
//
//All fields:
//  NodeId="BaseEventType", NodeId -> Success; nsu=http://opcfoundation.org/Quickstarts/AlarmCondition ;ns=2;s=1:Colours/EastTank?Red {OpcLabs.EasyOpc.UA.AddressSpace.UANodeId}
//  NodeId="BaseEventType"/EventId -> Success; [16] {124, 156, 219, 54, 120, ...} {System.Byte[]}
//  NodeId="BaseEventType"/EventType -> Success; ExclusiveDeviationAlarmType {OpcLabs.EasyOpc.UA.AddressSpace.UANodeId}
//  NodeId="BaseEventType"/SourceNode -> Success; nsu=http://opcfoundation.org/Quickstarts/AlarmCondition ;ns=2;s=1:Colours/EastTank {OpcLabs.EasyOpc.UA.AddressSpace.UANodeId}
//  NodeId="BaseEventType"/SourceName -> Success; EastTank {System.String}
//  NodeId="BaseEventType"/Time -> Success; 10/14/2019 4:00:13 PM {System.DateTime}
//  NodeId="BaseEventType"/ReceiveTime -> Success; 10/14/2019 4:00:13 PM {System.DateTime}
//  NodeId="BaseEventType"/LocalTime -> Success; 00:00, DST {OpcLabs.EasyOpc.UA.UATimeZoneData}
//  NodeId="BaseEventType"/Message -> Success; The alarm was acknoweledged. {System.String}
//  NodeId="BaseEventType"/Severity -> Success; 500 {System.Int32}
//Source name: Success; EastTank {System.String}
//Message: Success; The alarm was acknoweledged. {System.String}
//
//...

// This example shows how to specify criteria for event notifications.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

using System;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.AddressSpace;
using OpcLabs.EasyOpc.UA.AddressSpace.Standard;
using OpcLabs.EasyOpc.UA.AlarmsAndConditions;
using OpcLabs.EasyOpc.UA.Filtering;
using OpcLabs.EasyOpc.UA.OperationModel;

namespace UADocExamples.AlarmsAndConditions
{
    class WhereClause
    {
        public static void Main1()
        {
            UAEndpointDescriptor endpointDescriptor =
                "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer";

            // Instantiate the client object and hook events.
            var client = new EasyUAClient();
            client.EventNotification += client_EventNotification;

            Console.WriteLine("Subscribing...");
            client.SubscribeEvent(
                endpointDescriptor,
                UAObjectIds.Server,
                1000,
                new UAEventFilterBuilder(
                    // Either the severity is >= 500, or the event comes from a specified source node
                    UAFilterElements.Or(
                        UAFilterElements.GreaterThanOrEqual(UABaseEventObject.Operands.Severity, 500),
                        UAFilterElements.Equals(
                            UABaseEventObject.Operands.SourceNode, 
                            new UANodeId("nsu=http://opcfoundation.org/Quickstarts/AlarmCondition ;ns=2;s=1:Metals/SouthMotor"))),
                    UABaseEventObject.AllFields));

            Console.WriteLine("Processing event notifications for 30 seconds...");
            System.Threading.Thread.Sleep(30 * 1000);

            Console.WriteLine("Unsubscribing...");
            client.UnsubscribeAllMonitoredItems();

            Console.WriteLine("Waiting for 5 seconds...");
            System.Threading.Thread.Sleep(5 * 1000);

            Console.WriteLine("Finished.");
        }

        static void client_EventNotification(object sender, EasyUAEventNotificationEventArgs e)
        {
            // Display the event.
            Console.WriteLine(e);
        }


        // Example output:
        //
        //Subscribing...
        //13000008
        //Processing event notifications for 30 seconds...
        //[] Success
        //[] Success; Refresh; RefreshInitiated
        //[] Success; Refresh; [SouthMotor] 100! {DialogConditionType} "The dialog was activated" @9/9/2021 2:22:18 PM (10 fields)
        //[] Success; Refresh; [SouthMotor] 700! {ExclusiveDeviationAlarmType} "The alarm severity has increased." @9/22/2021 7:17:59 AM (10 fields)
        //[] Success; Refresh; [SouthMotor] 900! {NonExclusiveLevelAlarmType} "The alarm severity has increased." @9/22/2021 7:17:57 AM (10 fields)
        //[] Success; Refresh; [SouthMotor] 100! {TripAlarmType} "The alarm is active." @9/22/2021 7:17:59 AM (10 fields)
        //[] Success; Refresh; [SouthMotor] 100! {TripAlarmType} "The alarm severity has increased." @9/9/2021 3:39:51 PM (10 fields)
        //[] Success; Refresh; [SouthMotor] 100! {TripAlarmType} "The alarm severity has increased." @9/9/2021 3:38:57 PM (10 fields)
        //[] Success; Refresh; RefreshComplete
        //[] Success; [SouthMotor] 100! {NonExclusiveLevelAlarmType} "The alarm was deactivated by the system." @9/22/2021 7:18:05 AM (10 fields)
        //[] Success; [SouthMotor] 300! {TripAlarmType} "The alarm severity has increased." @9/22/2021 7:18:08 AM (10 fields)
        //[] Success; [SouthMotor] 900! {ExclusiveDeviationAlarmType} "The alarm severity has increased." @9/22/2021 7:18:10 AM (10 fields)
        //[] Success; [SouthMotor] 100! {NonExclusiveLevelAlarmType} "The alarm is active." @9/22/2021 7:18:13 AM (10 fields)
        //[] Success; [SouthMotor] 500! {TripAlarmType} "The alarm severity has increased." @9/22/2021 7:18:17 AM (10 fields)
        //[] Success; [SouthMotor] 100! {ExclusiveDeviationAlarmType} "The alarm was deactivated by the system." @9/22/2021 7:18:21 AM (10 fields)
        //[] Success; [SouthMotor] 300! {NonExclusiveLevelAlarmType} "The alarm severity has increased." @9/22/2021 7:18:21 AM (10 fields)
        //[] Success; [SouthMotor] 700! {TripAlarmType} "The alarm severity has increased." @9/22/2021 7:18:26 AM (10 fields)
        //[] Success; [SouthMotor] 500! {NonExclusiveLevelAlarmType} "The alarm severity has increased." @9/22/2021 7:18:29 AM (10 fields)
        //[] Success; [SouthMotor] 100! {ExclusiveDeviationAlarmType} "The alarm is active." @9/22/2021 7:18:32 AM (10 fields)
        //Unsubscribing...
        //Waiting for 5 seconds...
        //Finished.
    }
}
# This example shows how to specify criteria for event notifications.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

#requires -Version 5.1
using namespace OpcLabs.EasyOpc.UA
using namespace OpcLabs.EasyOpc.UA.AddressSpace
using namespace OpcLabs.EasyOpc.UA.AddressSpace.Standard

# The path below assumes that the current directory is [ProductDir]/Examples-NET/PowerShell/Windows .
Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.EasyOpcUA.dll"
Add-Type -Path "../../../Components/Opclabs.QuickOpc/net472/OpcLabs.EasyOpcUAComponents.dll"

# Define which server we will work with.
[UAEndpointDescriptor]$endpointDescriptor = "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer"

# Instantiate the client object.
$client = New-Object EasyUAClient

# Event notification handler
Register-ObjectEvent -InputObject $client -EventName EventNotification -Action { 
    # Display the event.
    Write-Host $EventArgs
}

Write-Host "Subscribing..."
[IEasyUAClientExtension]::SubscribeEvent($client, 
    $endpointDescriptor, 
    [UAObjectIds]::Server, 
    1000,
    [UAEventFilter](New-Object UAEventFilterBuilder(
        [UAFilterElements]::Equals(
            [UABaseEventObject+Operands]::SourceNode, 
            (New-Object UANodeId("nsu=http://opcfoundation.org/Quickstarts/AlarmCondition ;ns=2;s=1:Metals/SouthMotor"))),
        [UABaseEventObject]::AllFields))
    )

Write-Host "Processing event notifications for 30 seconds..."
$stopwatch =  [System.Diagnostics.Stopwatch]::StartNew() 
while ($stopwatch.Elapsed.TotalSeconds -lt 30) {    
    Start-Sleep -Seconds 1
}

Write-Host "Unsubscribing..."
$client.UnsubscribeAllMonitoredItems()

Write-Host "Waiting for 5 seconds..."
Start-Sleep -Seconds 5

Write-Host "Finished."


# Example output:
#
#Subscribing...
#13000008
#Processing event notifications for 30 seconds...
#[] Success
#[] Success; Refresh; RefreshInitiated
#[] Success; Refresh; [SouthMotor] 100! {DialogConditionType} "The dialog was activated" @9/9/2021 2:22:18 PM (10 fields)
#[] Success; Refresh; [SouthMotor] 700! {ExclusiveDeviationAlarmType} "The alarm severity has increased." @9/22/2021 7:17:59 AM (10 fields)
#[] Success; Refresh; [SouthMotor] 900! {NonExclusiveLevelAlarmType} "The alarm severity has increased." @9/22/2021 7:17:57 AM (10 fields)
#[] Success; Refresh; [SouthMotor] 100! {TripAlarmType} "The alarm is active." @9/22/2021 7:17:59 AM (10 fields)
#[] Success; Refresh; [SouthMotor] 100! {TripAlarmType} "The alarm severity has increased." @9/9/2021 3:39:51 PM (10 fields)
#[] Success; Refresh; [SouthMotor] 100! {TripAlarmType} "The alarm severity has increased." @9/9/2021 3:38:57 PM (10 fields)
#[] Success; Refresh; RefreshComplete
#[] Success; [SouthMotor] 100! {NonExclusiveLevelAlarmType} "The alarm was deactivated by the system." @9/22/2021 7:18:05 AM (10 fields)
#[] Success; [SouthMotor] 300! {TripAlarmType} "The alarm severity has increased." @9/22/2021 7:18:08 AM (10 fields)
#[] Success; [SouthMotor] 900! {ExclusiveDeviationAlarmType} "The alarm severity has increased." @9/22/2021 7:18:10 AM (10 fields)
#[] Success; [SouthMotor] 100! {NonExclusiveLevelAlarmType} "The alarm is active." @9/22/2021 7:18:13 AM (10 fields)
#[] Success; [SouthMotor] 500! {TripAlarmType} "The alarm severity has increased." @9/22/2021 7:18:17 AM (10 fields)
#[] Success; [SouthMotor] 100! {ExclusiveDeviationAlarmType} "The alarm was deactivated by the system." @9/22/2021 7:18:21 AM (10 fields)
#[] Success; [SouthMotor] 300! {NonExclusiveLevelAlarmType} "The alarm severity has increased." @9/22/2021 7:18:21 AM (10 fields)
#[] Success; [SouthMotor] 700! {TripAlarmType} "The alarm severity has increased." @9/22/2021 7:18:26 AM (10 fields)
#[] Success; [SouthMotor] 500! {NonExclusiveLevelAlarmType} "The alarm severity has increased." @9/22/2021 7:18:29 AM (10 fields)
#[] Success; [SouthMotor] 100! {ExclusiveDeviationAlarmType} "The alarm is active." @9/22/2021 7:18:32 AM (10 fields)
#Unsubscribing...
#Waiting for 5 seconds...
#Finished.
# This example shows how to specify criteria for event notifications.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python .
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc
import time

# Import .NET namespaces.
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.AddressSpace import *
from OpcLabs.EasyOpc.UA.AddressSpace.Standard import *
from OpcLabs.EasyOpc.UA.AlarmsAndConditions import *
from OpcLabs.EasyOpc.UA.Filtering import *
from OpcLabs.EasyOpc.UA.OperationModel import *


def eventNotification(sender, eventArgs):
    # Display the event.
    print(eventArgs)


# Define which server we will work with.
endpointDescriptor = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer')

# Instantiate the client object and hook events.
client = EasyUAClient()
client.EventNotification += eventNotification

print('Subscribing...')

eventFilterBuilder = UAEventFilterBuilder(
    # Either the severity is >= 500, or the event comes from a specified source node.
    UAFilterElements.Or(
        UAFilterElements.GreaterThanOrEqual(UABaseEventObject.Operands.Severity, 500),
        UAFilterElements.Equals(
            UABaseEventObject.Operands.SourceNode,
            UANodeId('nsu=http://opcfoundation.org/Quickstarts/AlarmCondition ;ns=2;s=1:Metals/SouthMotor'))),
    UABaseEventObject.AllFields)

IEasyUAClientExtension.SubscribeEvent(
    client,
    endpointDescriptor,
    UANodeDescriptor(UAObjectIds.Server),
    1000,
    UAEventFilterBuilder.ToUAEventFilter(eventFilterBuilder))

print('Processing event notifications for 30 seconds...')
time.sleep(30)

print('Unsubscribing...')
client.UnsubscribeAllMonitoredItems()

print('Waiting for 5 seconds...')
time.sleep(5)

print('Finished.')
' This example shows how to specify criteria for event notifications.
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.AddressSpace
Imports OpcLabs.EasyOpc.UA.AddressSpace.Standard
Imports OpcLabs.EasyOpc.UA.AlarmsAndConditions
Imports OpcLabs.EasyOpc.UA.Filtering
Imports OpcLabs.EasyOpc.UA.OperationModel

Namespace AlarmsAndConditions
    Friend Class WhereClause
        Public Shared Sub Main1()
            ' Instantiate the client object and hook events
            Dim client = New EasyUAClient()
            AddHandler client.EventNotification, AddressOf client_EventNotification

            Console.WriteLine("Subscribing...")
            ' Either the severity is >= 500, or the event comes from a specified source node
            client.SubscribeEvent( _
                "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer", _
                UAObjectIds.Server, _
                1000, _
                New UAEventFilterBuilder( _
                    UAFilterElements.Or( _
                        UAFilterElements.GreaterThanOrEqual(UABaseEventObject.Operands.Severity, 500),
                        UAFilterElements.Equals( _
                            UABaseEventObject.Operands.SourceNode,
                            New UANodeId("nsu=http://opcfoundation.org/Quickstarts/AlarmCondition ;ns=2;s=1:Metals/SouthMotor"))),
                    UABaseEventObject.AllFields))

            Console.WriteLine("Processing event notifications for 30 seconds...")
            Threading.Thread.Sleep(30 * 1000)

            Console.WriteLine("Unsubscribing...")
            client.UnsubscribeAllMonitoredItems()

            Console.WriteLine("Waiting for 5 seconds...")
            Threading.Thread.Sleep(5 * 1000)
        End Sub

        Private Shared Sub client_EventNotification(ByVal sender As Object, ByVal e As EasyUAEventNotificationEventArgs)
            ' Display the event
            Console.WriteLine(e)
        End Sub
    End Class
End Namespace
// This example shows how to specify criteria for event notifications.
//
// Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

type
  TClientEventHandlers3 = class
    procedure OnEventNotification(
      Sender: TObject;
      sender0: OleVariant;
      eventArgs: _EasyUAEventNotificationEventArgs);
  end;

procedure TClientEventHandlers3.OnEventNotification(
  Sender: TObject;
  sender0: OleVariant;
  eventArgs: _EasyUAEventNotificationEventArgs);
begin
  // Display the event
  WriteLn(eventArgs.ToString);
end;

class procedure WhereClause.Main;

  function ToUAAttributeField(Operand: UASimpleAttributeOperand): UAAttributeField;
  var
    AttributeField: UAAttributeField;
  begin
    AttributeField := CoUAAttributeField.Create;
    AttributeField.Operand := Operand;
    ToUAAttributeField := AttributeField;
  end;

  function ObjectTypeIds_BaseEventType: UANodeId;
  var
    NodeId: UANodeId;
  begin
    NodeId := CoUANodeId.Create;
    NodeId.StandardName := 'BaseEventType';
    ObjectTypeIds_BaseEventType := NodeId;
  end;

  function UAFilterElements_SimpleAttribute(TypeId: UANodeId; SimpleRelativeBrowsePathString: string): UASimpleAttributeOperand;
  var
    Operand: UASimpleAttributeOperand;
    BrowsePathParser: UABrowsePathParser;
  begin
    BrowsePathParser := CoUABrowsePathParser.Create;
    Operand := CoUASimpleAttributeOperand.Create;
    Operand.TypeId.NodeId := TypeId;
    Operand.QualifiedNames := BrowsePathParser.ParseRelative(SimpleRelativeBrowsePathString).ToUAQualifiedNameCollection;
    UAFilterElements_SimpleAttribute := Operand;
  end;

  function UABaseEventObject_Operands_NodeId: UASimpleAttributeOperand;
  var
    Operand: UASimpleAttributeOperand;
  begin
    Operand := CoUASimpleAttributeOperand.Create;
    Operand.TypeId.NodeId.StandardName := 'BaseEventType';
    Operand.AttributeId := UAAttributeId_NodeId;
    UABaseEventObject_Operands_NodeId := Operand;
  end;

  function UABaseEventObject_Operands_EventId: UASimpleAttributeOperand;
  begin
    UABaseEventObject_Operands_EventId := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/EventId');
  end;

  function UABaseEventObject_Operands_EventType: UASimpleAttributeOperand;
  begin
    UABaseEventObject_Operands_EventType := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/EventType');
  end;

  function UABaseEventObject_Operands_SourceNode: UASimpleAttributeOperand;
  begin
    UABaseEventObject_Operands_SourceNode := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/SourceNode');
  end;

  function UABaseEventObject_Operands_SourceName: UASimpleAttributeOperand;
  begin
    UABaseEventObject_Operands_SourceName := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/SourceName');
  end;

  function UABaseEventObject_Operands_Time: UASimpleAttributeOperand;
  begin
    UABaseEventObject_Operands_Time := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Time');
  end;

  function UABaseEventObject_Operands_ReceiveTime: UASimpleAttributeOperand;
  begin
    UABaseEventObject_Operands_ReceiveTime := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/ReceiveTime');
  end;

  function UABaseEventObject_Operands_LocalTime: UASimpleAttributeOperand;
  begin
    UABaseEventObject_Operands_LocalTime := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/LocalTime');
  end;

  function UABaseEventObject_Operands_Message: UASimpleAttributeOperand;
  begin
    UABaseEventObject_Operands_Message := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Message');
  end;

  function UABaseEventObject_Operands_Severity: UASimpleAttributeOperand;
  begin
    UABaseEventObject_Operands_Severity := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Severity');
  end;

  function UABaseEventObject_AllFields: UAAttributeFieldCollection;
  var
    Fields: UAAttributeFieldCollection;
  begin
    Fields := CoUAAttributeFieldCollection.Create;

    Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_NodeId));

    Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_EventId));
    Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_EventType));
    Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_SourceNode));
    Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_SourceName));
    Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_Time));
    Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_ReceiveTime));
    Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_LocalTime));
    Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_Message));
    Fields.Add(ToUAAttributeField(UABaseEventObject_Operands_Severity));

    UABaseEventObject_AllFields := Fields;
  end;

var
  Arguments: OleVariant;
  EvsClient: TEvsEasyUAClient;
  Client: EasyUAClient;
  ClientEventHandlers: TClientEventHandlers3;
  Handle: Cardinal;
  HandleArray: OleVariant;
  MonitoredItemArguments: EasyUAMonitoredItemArguments;
  MonitoringParameters: UAMonitoringParameters;
  EventFilter: UAEventFilter;
  WhereClause: UAContentFilterElement;
  Operand1: UASimpleAttributeOperand;
  Operand2: UALiteralOperand;
  Operand3: UASimpleAttributeOperand;
  Operand4: UALiteralOperand;
  SourceNodeId: UANodeId;
  Element1, Element2: UAContentFilterElement;
  BaseEventType: UANodeId;
begin
  // Instantiate the client object and hook events
  EvsClient := TEvsEasyUAClient.Create(nil);
  Client := EvsClient.ComServer;
  ClientEventHandlers := TClientEventHandlers3.Create;
  EvsClient.OnEventNotification := @ClientEventHandlers.OnEventNotification;

  WriteLn('Subscribing...');

  WhereClause := CoUAContentFilterElement.Create;
  BaseEventType := CoUaNodeId.Create;
  BaseEventType.StandardName := 'BaseEventType';

  // Either the severity is >= 500, or the event comes from a specified source node
  Operand1 := UABaseEventObject_Operands_Severity;
  Operand2 := CoUALiteralOperand.Create;
  Operand2.Value := 500;
  Element1 := CoUAContentFilterElement.Create;
  Element1.FilterOperator := UAFilterOperator_GreaterThanOrEqual;
  Element1.FilterOperands.Add(Operand1);
  Element1.FilterOperands.Add(Operand2);
  Operand3 := UABaseEventObject_Operands_SourceNode;
  SourceNodeId := CoUANodeId.Create;
  SourceNodeId.ExpandedText := 'nsu=http://opcfoundation.org/Quickstarts/AlarmCondition;ns=2;s=1:Metals/SouthMotor';
  Operand4 := CoUALiteralOperand.Create;
  Operand4.Value := SourceNodeId;
  Element2 := CoUAContentFilterElement.Create;
  Element2.FilterOperator := UAFilterOperator_Equals;
  Element2.FilterOperands.Add(Operand3);
  Element2.FilterOperands.Add(Operand4);
  WhereClause.FilterOperator := UAFilterOperator_Or;
  WhereClause.FilterOperands.Add(Element1);
  WhereClause.FilterOperands.Add(Element2);

  EventFilter := CoUAEventFilter.Create;
  EventFilter.SelectClauses := UABaseEventObject_AllFields;
  EventFilter.WhereClause := WhereClause;

  MonitoringParameters := CoUAMonitoringParameters.Create;
  MonitoringParameters.SamplingInterval := 1000;
  MonitoringParameters.EventFilter := EventFilter;
  MonitoringParameters.QueueSize := 1000;

  MonitoredItemArguments := CoEasyUAMonitoredItemArguments.Create;
  MonitoredItemArguments.EndpointDescriptor.UrlString := 'opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer';
  MonitoredItemArguments.NodeDescriptor.NodeId.StandardName := 'Server';
  MonitoredItemArguments.MonitoringParameters := MonitoringParameters;
  //MonitoredItemArguments.SubscriptionParameters.PublishingInterval := 0;
  MonitoredItemArguments.AttributeId := UAAttributeId_EventNotifier;

  Arguments := VarArrayCreate([0, 0], varVariant);
  Arguments[0] := MonitoredItemArguments;

  TVarData(HandleArray).VType := varArray or varVariant;
  TVarData(HandleArray).VArray := PVarArray(
    Client.SubscribeMultipleMonitoredItems(PSafeArray(TVarData(Arguments).VArray)));

  WriteLn('Processing event notifications for 30 seconds...');
  PumpSleep(30*1000);

  WriteLn('Unsubscribing...');
  Client.UnsubscribeAllMonitoredItems;

  WriteLn('Waiting for 5 seconds...');
  PumpSleep(5*1000);

  WriteLn('Finished...');
end;
// This example shows how to specify criteria for event notifications.
//
// Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

type
  THelperMethods10 = class
    class function ObjectTypeIds_BaseEventType: _UANodeId; static;
    class function UABaseEventObject_Operands_EventId: _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_EventType: _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_NodeId: _UASimpleAttributeOperand; static;
    class function UAFilterElements_SimpleAttribute(TypeId: _UANodeId; simpleRelativeBrowsePathString: string): _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_SourceName: _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_Time: _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_ReceiveTime: _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_LocalTime: _UASimpleAttributeOperand;
    class function UABaseEventObject_Operands_SourceNode: _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_Message: _UASimpleAttributeOperand; static;
    class function UABaseEventObject_Operands_Severity: _UASimpleAttributeOperand; static;
    class function UABaseEventObject_AllFields: _UAAttributeFieldCollection; static;
  end;

type
  TClientEventHandlers10 = class
    procedure Client_EventNotification(
      ASender: TObject;
      sender: OleVariant;
      const eventArgs: _EasyUAEventNotificationEventArgs);
  end;

procedure TClientEventHandlers10.Client_EventNotification(
  ASender: TObject;
  sender: OleVariant;
  const eventArgs: _EasyUAEventNotificationEventArgs);
begin
  // Display the event
  WriteLn(eventArgs.ToString);
end;

class procedure WhereClause.Main;
const
  UAObjectIds_Server = 'nsu=http://opcfoundation.org/UA/;i=2253';
var
  Arguments: OleVariant;
  Client: TEasyUAClient;
  ClientEventHandlers: TClientEventHandlers10;
  Element1, Element2: _UAContentFilterElement;
  EndpointDescriptor: string;
  EventFilter: _UAEventFilter;
  MonitoredItemArguments: _EasyUAMonitoredItemArguments;
  MonitoringParameters: _UAMonitoringParameters;
  Operand1, Operand3: _UASimpleAttributeOperand;
  Operand2, Operand4: _UALiteralOperand;
  SourceNodeId: _UANodeId;
  WhereClause: _UAContentFilterElement;
begin
  EndpointDescriptor := 'opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer';

  // Instantiate the client object and hook events
  Client := TEasyUAClient.Create(nil);
  ClientEventHandlers := TClientEventHandlers10.Create;
  Client.OnEventNotification := ClientEventHandlers.Client_EventNotification;

  WriteLn('Subscribing...');

  WhereClause := CoUAContentFilterElement.Create;

  // Either the severity is >= 500, or the event comes from a specified source node
  Operand1 := THelperMethods10.UABaseEventObject_Operands_Severity;
  Operand2 := CoUALiteralOperand.Create;
  Operand2.Value := 500;
  Element1 := CoUAContentFilterElement.Create;
  Element1.FilterOperator := UAFilterOperator_GreaterThanOrEqual;
  Element1.FilterOperands.Add(Operand1);
  Element1.FilterOperands.Add(Operand2);
  Operand3 := THelperMethods10.UABaseEventObject_Operands_SourceNode;
  SourceNodeId := CoUANodeId.Create;
  SourceNodeId.ExpandedText := 'nsu=http://opcfoundation.org/Quickstarts/AlarmCondition;ns=2;s=1:Metals/SouthMotor';
  Operand4 := CoUALiteralOperand.Create;
  Operand4.Value := SourceNodeId;
  Element2 := CoUAContentFilterElement.Create;
  Element2.FilterOperator := UAFilterOperator_Equals;
  Element2.FilterOperands.Add(Operand3);
  Element2.FilterOperands.Add(Operand4);
  WhereClause.FilterOperator := UAFilterOperator_Or;
  WhereClause.FilterOperands.Add(Element1);
  WhereClause.FilterOperands.Add(Element2);

  EventFilter := CoUAEventFilter.Create;
  EventFilter.SelectClauses := THelperMethods10.UABaseEventObject_AllFields;
  EventFilter.WhereClause := WhereClause;

  MonitoringParameters := CoUAMonitoringParameters.Create;
  MonitoringParameters.SamplingInterval := 1000;
  MonitoringParameters.EventFilter := EventFilter;
  MonitoringParameters.QueueSize := 1000;

  MonitoredItemArguments := CoEasyUAMonitoredItemArguments.Create;
  MonitoredItemArguments.EndpointDescriptor.UrlString := 'opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer';
  MonitoredItemArguments.NodeDescriptor.NodeId.StandardName := 'Server';
  MonitoredItemArguments.MonitoringParameters := MonitoringParameters;
  //MonitoredItemArguments.SubscriptionParameters.PublishingInterval := 0;
  MonitoredItemArguments.AttributeId := UAAttributeId_EventNotifier;

  Arguments := VarArrayCreate([0, 0], varVariant);
  Arguments[0] := MonitoredItemArguments;

  Client.SubscribeMultipleMonitoredItems(Arguments);

  WriteLn('Processing event notifications for 30 seconds...');
  PumpSleep(30*1000);

  WriteLn('Unsubscribing...');
  Client.UnsubscribeAllMonitoredItems;

  WriteLn('Waiting for 5 seconds...');
  Sleep(5*1000);

  WriteLn('Finished.');
  VarClear(Arguments);
  FreeAndNil(Client);
  FreeAndNil(ClientEventHandlers);
end;


class function THelperMethods10.ObjectTypeIds_BaseEventType: _UANodeId;
  var NodeId: _UANodeId;
  begin
    NodeId := CoUANodeId.Create;
    NodeId.StandardName := 'BaseEventType';
    Result := NodeId;
  end;

class function THelperMethods10.UAFilterElements_SimpleAttribute(TypeId: _UANodeId; simpleRelativeBrowsePathString: string): _UASimpleAttributeOperand;
var
  BrowsePathParser: _UABrowsePathParser;
  Operand: _UASimpleAttributeOperand;
begin
  BrowsePathParser := CoUABrowsePathParser.Create;
  Operand := CoUASimpleAttributeOperand.Create;
  Operand.TypeId.NodeId := TypeId;
  Operand.QualifiedNames := BrowsePathParser.ParseRelative(simpleRelativeBrowsePathString).ToUAQualifiedNameCollection;
  Result := Operand;
end;

class function THelperMethods10.UABaseEventObject_Operands_EventId: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/EventId');
end;

class function THelperMethods10.UABaseEventObject_Operands_EventType: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/EventType');
end;

class function THelperMethods10.UABaseEventObject_Operands_NodeId: _UASimpleAttributeOperand;
var
  Operand: _UASimpleAttributeOperand;
begin
  Operand := CoUASimpleAttributeOperand.Create;
  Operand.TypeId.NodeId.StandardName := 'BaseEventType';
  Operand.AttributeId := UAAttributeId_NodeId;
  Result := Operand;
end;

class function THelperMethods10.UABaseEventObject_Operands_SourceNode: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/SourceNode');
end;

class function THelperMethods10.UABaseEventObject_Operands_SourceName: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/SourceName');
end;

class function THelperMethods10.UABaseEventObject_Operands_Time: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Time');
end;

class function THelperMethods10.UABaseEventObject_Operands_ReceiveTime: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/ReceiveTime');
end;

class function THelperMethods10.UABaseEventObject_Operands_LocalTime: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/LocalTime');
end;

class function THelperMethods10.UABaseEventObject_Operands_Message: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Message');
end;

class function THelperMethods10.UABaseEventObject_Operands_Severity: _UASimpleAttributeOperand;
begin
  Result := UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType, '/Severity');
end;

class function THelperMethods10.UABaseEventObject_AllFields: _UAAttributeFieldCollection;
var
  Fields: _UAAttributeFieldCollection;
begin
  Fields := CoUAAttributeFieldCollection.Create;
  Fields.Add(UABaseEventObject_Operands_NodeId.ToUAAttributeField);
  Fields.Add(UABaseEventObject_Operands_EventId.ToUAAttributeField);
  Fields.Add(UABaseEventObject_Operands_EventType.ToUAAttributeField);
  Fields.Add(UABaseEventObject_Operands_SourceNode.ToUAAttributeField);
  Fields.Add(UABaseEventObject_Operands_SourceName.ToUAAttributeField);
  Fields.Add(UABaseEventObject_Operands_Time.ToUAAttributeField);
  Fields.Add(UABaseEventObject_Operands_ReceiveTime.ToUAAttributeField);
  Fields.Add(UABaseEventObject_Operands_LocalTime.ToUAAttributeField);
  Fields.Add(UABaseEventObject_Operands_Message.ToUAAttributeField);
  Fields.Add(UABaseEventObject_Operands_Severity.ToUAAttributeField);

  Result := Fields;
end;
// This example shows how to specify criteria for event notifications.
//
// Find all latest examples here : https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

const UAAttributeId_NodeId = 1;
const UAAttributeId_EventNotifier = 12;

const UAFilterOperator_Equals = 1;
const UAFilterOperator_GreaterThanOrEqual = 5;
const UAFilterOperator_Or = 12;

const UAObjectIds_Server = 'nsu=http://opcfoundation.org/UA/;i=2253';

class ClientEvents {
    function EventNotification($Sender, $E)
    {
        // Display the event
        printf("%s\n", $E);
    }
}

$EndpointDescriptor = "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer";

// Instantiate the client object and hook events
$Client = new COM("OpcLabs.EasyOpc.UA.EasyUAClient");
$ClientEvents = new ClientEvents();
com_event_sink($Client, $ClientEvents, "DEasyUAClientEvents");

$WhereClause = new COM("OpcLabs.EasyOpc.UA.Filtering.UAContentFilterElement");

// Either the severity is >= 500, or the event comes from a specified source node
$Operand1 = UABaseEventObject_Operands_Severity();
$Operand2 = new COM("OpcLabs.EasyOpc.UA.Filtering.UALiteralOperand");
$Operand2->Value = 500;
$Element1 = new COM("OpcLabs.EasyOpc.UA.Filtering.UAContentFilterElement");
$Element1->FilterOperator = UAFilterOperator_GreaterThanOrEqual;
$Element1->FilterOperands->Add($Operand1);
$Element1->FilterOperands->Add($Operand2);
$Operand3 = UABaseEventObject_Operands_SourceNode();
$SourceNodeId = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
$SourceNodeId->ExpandedText = "nsu=http://opcfoundation.org/Quickstarts/AlarmCondition;ns=2;s=1:Metals/SouthMotor";
$Operand4 = new COM("OpcLabs.EasyOpc.UA.Filtering.UALiteralOperand");
$Operand4->Value = $SourceNodeId;
$Element2 = new COM("OpcLabs.EasyOpc.UA.Filtering.UAContentFilterElement");
$Element2->FilterOperator = UAFilterOperator_Equals;
$Element2->FilterOperands->Add($Operand3);
$Element2->FilterOperands->Add($Operand4);
$WhereClause->FilterOperator = UAFilterOperator_Or;
$WhereClause->FilterOperands->Add($Element1);
$WhereClause->FilterOperands->Add($Element2);

$EventFilter = new COM("OpcLabs.EasyOpc.UA.UAEventFilter");
$EventFilter->SelectClauses = UABaseEventObject_AllFields();
$EventFilter->WhereClause = $WhereClause;

$MonitoringParameters = new COM("OpcLabs.EasyOpc.UA.UAMonitoringParameters");
$MonitoringParameters->SamplingInterval = 1000;
$MonitoringParameters->EventFilter = $EventFilter;
$MonitoringParameters->QueueSize = 1000;

$MonitoredItemArguments = new COM("OpcLabs.EasyOpc.UA.OperationModel.EasyUAMonitoredItemArguments");
$MonitoredItemArguments->EndpointDescriptor->UrlString = $EndpointDescriptor;
$MonitoredItemArguments->NodeDescriptor->NodeId->StandardName = "Server";
$MonitoredItemArguments->MonitoringParameters = $MonitoringParameters;
$MonitoredItemArguments->SubscriptionParameters->PublishingInterval = 0;
$MonitoredItemArguments->AttributeId = UAAttributeId_EventNotifier;

$arguments[0] = $MonitoredItemArguments;

printf("Subscribing...\n");
$Client->SubscribeMultipleMonitoredItems($arguments);

printf("Processing monitored item changed events for 30 seconds...\n");
$startTime = time(); do { com_message_pump(1000); } while (time() < $startTime + 30);

printf("Unsubscribing...\n");
$Client->UnsubscribeAllMonitoredItems;

printf("Waiting for 5 seconds...\n");
$startTime = time(); do { com_message_pump(1000); } while (time() < $startTime + 5);


function ObjectTypeIds_BaseEventType() {
    $NodeId = new COM("OpcLabs.EasyOpc.UA.AddressSpace.UANodeId");
    $NodeId->StandardName = "BaseEventType";
    return $NodeId;
}

function UAFilterElements_SimpleAttribute($TypeId, $simpleRelativeBrowsePathString) {
  $BrowsePathParser = new COM("OpcLabs.EasyOpc.UA.Navigation.Parsing.UABrowsePathParser");
  $Operand = new COM("OpcLabs.EasyOpc.UA.Filtering.UASimpleAttributeOperand");
  $Operand->TypeId->NodeId = $TypeId;
  $Operand->QualifiedNames = $BrowsePathParser->ParseRelative($simpleRelativeBrowsePathString)->ToUAQualifiedNameCollection;
  return $Operand;
}

function UABaseEventObject_Operands_NodeId() {
    $Operand = new COM("OpcLabs.EasyOpc.UA.Filtering.UASimpleAttributeOperand");
    $Operand->TypeId->NodeId->StandardName = "BaseEventType";
    $Operand->AttributeId = UAAttributeId_NodeId;
    return $Operand;
}

function UABaseEventObject_Operands_EventId() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/EventId");
}

function UABaseEventObject_Operands_EventType() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/EventType");
}

function UABaseEventObject_Operands_SourceNode() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/SourceNode");
}

function UABaseEventObject_Operands_SourceName() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/SourceName");
}

function UABaseEventObject_Operands_Time() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/Time");
}

function UABaseEventObject_Operands_ReceiveTime() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/ReceiveTime");
}

function UABaseEventObject_Operands_LocalTime() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/LocalTime");
}

function UABaseEventObject_Operands_Message() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/Message");
}

function UABaseEventObject_Operands_Severity() {
  return UAFilterElements_SimpleAttribute(ObjectTypeIds_BaseEventType(), "/Severity");
}

function UABaseEventObject_AllFields() {
    $Fields = new COM("OpcLabs.EasyOpc.UA.UAAttributeFieldCollection");
    $Fields->Add(UABaseEventObject_Operands_NodeId()->ToUAAttributeField);
    $Fields->Add(UABaseEventObject_Operands_EventId()->ToUAAttributeField);
    $Fields->Add(UABaseEventObject_Operands_EventType()->ToUAAttributeField);
    $Fields->Add(UABaseEventObject_Operands_SourceNode()->ToUAAttributeField);
    $Fields->Add(UABaseEventObject_Operands_SourceName()->ToUAAttributeField);
    $Fields->Add(UABaseEventObject_Operands_Time()->ToUAAttributeField);
    $Fields->Add(UABaseEventObject_Operands_ReceiveTime()->ToUAAttributeField);
    $Fields->Add(UABaseEventObject_Operands_LocalTime()->ToUAAttributeField);
    $Fields->Add(UABaseEventObject_Operands_Message()->ToUAAttributeField);
    $Fields->Add(UABaseEventObject_Operands_Severity()->ToUAAttributeField);

    return $Fields;
}
// This example shows how to obtain acknowledged state of events, and acknowledge an event that is not acknowledged yet.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

using System;
using System.Diagnostics;
using System.Threading;
using OpcLabs.BaseLib.OperationModel;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.AddressSpace;
using OpcLabs.EasyOpc.UA.AddressSpace.Standard;
using OpcLabs.EasyOpc.UA.AlarmsAndConditions;
using OpcLabs.EasyOpc.UA.Filtering;
using OpcLabs.EasyOpc.UA.OperationModel;

namespace UADocExamples.AlarmsAndConditions
{
    partial class Acknowledge
    {
        public static void AckedState()
        {
            // Define which server we will work with.
            UAEndpointDescriptor endpointDescriptor =
                "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer";

            // Instantiate the client objects.
            var client = new EasyUAClient();
            IEasyUAAlarmsAndConditionsClient alarmsAndConditionsClient = client.AsAlarmsAndConditionsClient();

            UANodeId nodeId = null;
            byte[] eventId = null;
            var anEvent = new ManualResetEvent(initialState: false);

            // Prepare the Select clauses.
            UAAttributeFieldCollection selectClauses = UABaseEventObject.AllFields;
            UASimpleAttributeOperand ackedStateIdOperand = UAFilterElements.SimpleAttribute(UAObjectTypeIds.BaseEventType, "/AckedState/Id");
            selectClauses.Add(ackedStateIdOperand);

            Console.WriteLine("Subscribing...");
            client.SubscribeEvent(
                endpointDescriptor,
                UAObjectIds.Server,
                1000,
                new UAEventFilterBuilder(
                    // We will auto-acknowledge an event with severity less than 200.
                    UAFilterElements.LessThan(UABaseEventObject.Operands.Severity, 200),
                    selectClauses),
                (sender, eventArgs) =>
                {
                    if (!eventArgs.Succeeded)
                    {
                        Console.WriteLine($"*** Failure: {eventArgs.ErrorMessageBrief}");
                        return;
                    }

                    UAEventData eventData = eventArgs.EventData;
                    if (!(eventData is null))
                    {
                        UABaseEventObject baseEventObject = eventData.BaseEvent;
                        Console.WriteLine(baseEventObject);

                        // Obtain the acknowledge state of the event.
                        ValueResult ackedStateIdResult = eventData.FieldResults[ackedStateIdOperand];
                        Debug.Assert(!(ackedStateIdResult is null));
                        if (!ackedStateIdResult.Succeeded)
                            return;
                        bool? ackedStateId = (ackedStateIdResult.Value is bool) ? (bool?)ackedStateIdResult.Value : null;
                        Console.WriteLine($"AckedState/Id: {ackedStateId}");

                        // Only attempt to acknowledge when not acknowledged yet.
                        if (ackedStateId != false)
                            return;

                        // Make sure we do not catch the event more than once.
                        if (anEvent.WaitOne(0))
                            return;

                        nodeId = baseEventObject.NodeId;
                        eventId = baseEventObject.EventId;

                        anEvent.Set();
                    }
                },
                state:null);

            Console.WriteLine("Waiting for an acknowledgeable event for 10 minutes...");
            if (!anEvent.WaitOne(10*60*1000))
            {
                Console.WriteLine("Event not received.");
                return;
            }

            Console.WriteLine();
            Console.WriteLine("Acknowledging an event...");
            try
            {
                alarmsAndConditionsClient.Acknowledge(
                    endpointDescriptor,
                    nodeId,
                    eventId,
                    "Acknowledged by an automated example code.");
            }
            catch (UAException uaException)
            {
                Console.WriteLine($"*** Failure: {uaException.GetBaseException().Message}");
            }

            Console.WriteLine("Waiting for 5 seconds...");
            Thread.Sleep(5 * 1000);

            Console.WriteLine("Unsubscribing...");
            client.UnsubscribeAllMonitoredItems();

            Console.WriteLine("Waiting for 5 seconds...");
            Thread.Sleep(5 * 1000);

            Console.WriteLine("Finished.");
        }
    }
}
# This example shows how to obtain acknowledged state of events, and acknowledge an event that is not acknowledged yet.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python .
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc
import time

# Import .NET namespaces.
from System.Threading import *
from OpcLabs.EasyOpc.UA import *
from OpcLabs.EasyOpc.UA.AddressSpace.Standard import *
from OpcLabs.EasyOpc.UA.AlarmsAndConditions import *
from OpcLabs.EasyOpc.UA.Filtering import *
from OpcLabs.EasyOpc.UA.OperationModel import *


def eventNotification(sender, eventArgs):
    global ackedStateIdOperand
    global anEvent
    global eventId
    global nodeId

    if not eventArgs.Succeeded:
        print('*** Failure: ', eventArgs.ErrorMessageBrief, sep='')
        return

    eventData = eventArgs.EventData
    if not eventData is None:
        baseEventObject = eventData.BaseEvent
        print(baseEventObject)

        # Obtain the acknowledge state of the event.
        ackedStateIdResult = eventData.FieldResults.get_Item(UAAttributeField(ackedStateIdOperand))
        assert ackedStateIdResult is not None
        if not ackedStateIdResult.Succeeded:
            return
        ackedStateId = ackedStateIdResult.Value
        print('AckedState/Id: ', ackedStateId, sep='')

        # Only attempt to acknowledge when not acknowledged yet.
        if ackedStateId != False:
            return

        # Make sure we do not catch the event more than once.
        if anEvent.WaitOne(0):
            return

        nodeId = baseEventObject.NodeId
        eventId = baseEventObject.EventId

        anEvent.Set()


# Define which server we will work with.
endpointDescriptor = UAEndpointDescriptor('opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer')

# Instantiate the client objects.
client = EasyUAClient()
alarmsAndConditionsClient = IEasyUAClientExtension.AsAlarmsAndConditionsClient(client)

nodeId = None
eventId = None
anEvent = ManualResetEvent(False)   # initialState

# Prepare the Select clauses.
selectClauses = UABaseEventObject.AllFields
ackedStateIdOperand = UAFilterElements.SimpleAttribute(
    UANodeDescriptor(UAObjectTypeIds.BaseEventType),
    '/AckedState/Id')
selectClauses.Add(UAAttributeField(ackedStateIdOperand))

print('Subscribing...')
eventFilterBuilder = UAEventFilterBuilder(
    # We will auto-acknowledge an event with severity less than 200.
    UAFilterElements.LessThan(UABaseEventObject.Operands.Severity, 200),
    selectClauses)
IEasyUAClientExtension.SubscribeEvent(
    client,
    endpointDescriptor,
    UANodeDescriptor(UAObjectIds.Server),
    1000,
    UAEventFilterBuilder.ToUAEventFilter(eventFilterBuilder),
    EasyUAEventNotificationEventHandler(eventNotification),
    None)   # state

print('Waiting for an acknowledgeable event for 10 minutes...')
if not anEvent.WaitOne(10*60*1000):
    print('Event not received.')
    exit()

print()
print('Acknowledging an event...')
try:
    alarmsAndConditionsClient.Acknowledge(
        endpointDescriptor,
        UANodeDescriptor(nodeId),
        eventId,
        'Acknowledged by an automated example code.')
except UAException as uaException:
    print('*** Failure: ' + uaException.GetBaseException().Message)
print('Event successfully acknowledged.')

print()
print('Waiting for 5 seconds...')
time.sleep(5)

print('Unsubscribing...')
client.UnsubscribeAllMonitoredItems()

print('Waiting for 5 seconds...')
time.sleep(5)

print('Finished.')
' This example shows how to obtain acknowledged state of events, and acknowledge an event that is not acknowledged yet.
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .

Imports System
Imports System.Threading
Imports OpcLabs.BaseLib
Imports OpcLabs.BaseLib.OperationModel
Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.AddressSpace
Imports OpcLabs.EasyOpc.UA.AddressSpace.Standard
Imports OpcLabs.EasyOpc.UA.AlarmsAndConditions
Imports OpcLabs.EasyOpc.UA.Filtering
Imports OpcLabs.EasyOpc.UA.OperationModel

Namespace AlarmsAndConditions
    Partial Friend Class Acknowledge
        Public Shared Sub AckedState()
            ' Define which server we will work with.
            Dim endpointDescriptor As UAEndpointDescriptor =
                "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer"

            ' Instantiate the client object
            Dim client = New EasyUAClient()
            Dim alarmsAndConditionsClient As IEasyUAAlarmsAndConditionsClient = client.AsAlarmsAndConditionsClient()

            Dim nodeId As UANodeId = Nothing
            Dim eventId As Byte() = Nothing
            Dim anEvent = New ManualResetEvent(initialState:=False)

            ' Prepare the Select clauses.
            Dim selectClauses As UAAttributeFieldCollection = UABaseEventObject.AllFields
            Dim ackedStateIdOperand As UASimpleAttributeOperand = UAFilterElements.SimpleAttribute(UAObjectTypeIds.BaseEventType, "/AckedState/Id")
            selectClauses.Add(ackedStateIdOperand)

            Console.WriteLine("Subscribing...")
            client.SubscribeEvent(
                endpointDescriptor,
                UAObjectIds.Server,
                1000,
                New UAEventFilterBuilder(UAFilterElements.LessThan(UABaseEventObject.Operands.Severity, 200),
                    selectClauses), ' We will auto-acknowledge an event with severity less than 200.
                Sub(sender, eventArgs)
                    If Not eventArgs.Succeeded Then
                        Console.WriteLine($"*** Failure: {eventArgs.ErrorMessageBrief}")
                        Return
                    End If

                    Dim eventData As UAEventData = eventArgs.EventData
                    If eventData IsNot Nothing Then
                        Dim baseEventObject = eventArgs.EventData.BaseEvent
                        Console.WriteLine(baseEventObject)

                        ' Obtain the acknowledge state of the event.
                        Dim ackedStateIdResult As ValueResult = eventData.FieldResults(ackedStateIdOperand)
                        Debug.Assert(ackedStateIdResult IsNot Nothing)
                        If Not ackedStateIdResult.Succeeded Then
                            Return
                        End If
                        Dim ackedStateId As Boolean? = If((TypeOf ackedStateIdResult.Value Is Boolean), CType(ackedStateIdResult.Value, Boolean?), Nothing)
                        Console.WriteLine($"AckedState/Id: {ackedStateId}")

                        ' Only attempt to acknowledge when Not acknowledged yet.
                        If Not ackedStateId = False Then
                            Return
                        End If


                        ' Make sure we do not catch the event more than once
                        If anEvent.WaitOne(0) Then
                            Return
                        End If

                        nodeId = baseEventObject.NodeId
                        eventId = baseEventObject.EventId

                        anEvent.Set()
                    End If
                End Sub,
                state:=Nothing)

            Console.WriteLine("Waiting for an acknowledgeable event for 10 minutes...")
            If Not anEvent.WaitOne(10 * 60 * 1000) Then
                Console.WriteLine("Event not received")
                Return
            End If

            Console.WriteLine()
            Console.WriteLine("Acknowledging an event...")
            Try
                alarmsAndConditionsClient.Acknowledge(
                    endpointDescriptor,
                    nodeId,
                    eventId,
                    "Acknowledged by an automated example code.")
            Catch uaException As UAException
                Console.WriteLine($"*** Failure: {uaException.GetBaseException().Message}")
            End Try

            Console.WriteLine("Waiting for 5 seconds...")
            Thread.Sleep(5 * 1000)

            Console.WriteLine("Unsubscribing...")
            client.UnsubscribeAllMonitoredItems()

            Console.WriteLine("Waiting for 5 seconds...")
            Thread.Sleep(5 * 1000)

            Console.WriteLine("Finished.")
        End Sub
    End Class
End Namespace
Inheritance Hierarchy

System.Object
   OpcLabs.EasyOpc.UA.Filtering.UAFilterElements

Requirements

Target Platforms: .NET Framework: Windows 10 (selected versions), Windows 11 (selected versions), Windows Server 2016, Windows Server 2022; .NET: Linux, macOS, Microsoft Windows

See Also