QuickOPC User's Guide and Reference
IEasyUASubscriberEnqueuing Interface
Members 



OpcLabs.EasyOpcUA Assembly > OpcLabs.EasyOpc.UA.PubSub Namespace : IEasyUASubscriberEnqueuing Interface
Provides access to enqueuing for IEasyUASubscriber objects.
Syntax
'Declaration
 
<ComVisibleAttribute(False)>
Public Interface IEasyUASubscriberEnqueuing 
'Usage
 
Dim instance As IEasyUASubscriberEnqueuing
[ComVisible(false)]
public interface IEasyUASubscriberEnqueuing 
[ComVisible(false)]
public interface class IEasyUASubscriberEnqueuing 
Remarks

 

In This Topic

Event pull mechanism is an alternative to the traditional delivery mechanism of notifications through event handlers. Setting up event handlers, and properly handling events, is difficult or impossible in some (especially COM-based) tools (e.g. Python) or in some environments (e.g. applications running under Web server). In COM, unless taken care of already by the tool, the developer must also assure that (in an STA model) Windows messages are being pumped by the application.

Note: This feature should only be used when the traditional event delivery approach is not feasible. It is unlikely that you will need to use the event pull mechanism in C# or VB.NET (except maybe for server-side of certain Web apps and Web services).

Event pull mechanism replaces the event handlers by methods that allow the developer to obtain a next available notification from an internally provided queue. Events can then be handled by a loop that calls the “pull” method and processes the notifications. In order to maintain reasonable performance, a so-called long poll approach is used: The method only returns after a notification becomes available, or a specified timeout elapses. Note that the event pull concept is strictly confined to how the QuickOPC exchanges notifications with the enclosing application, and is not related to how QuickOPC communicates with OPC servers.

For each event XXXX, by convention, two methods for event pull mechanism are provided: A PullXXXX method, which allows to retrieve a single notification, and a PullMultipleXXXX method, which allows to retrieve multiple notifications, if they are available. Although currently is no significant performance difference between the two methods, it is recommended that your code uses the PullMultipleXXXX methods, because it may bring performance benefits in the future.

The following table shows the traditional events, and their corresponding methods for event pull:

Type Event Pull method PullMultiple method
EasyDAClient ItemChanged PullItemChanged PullMultipleItemChanges
EasyAEClient Notification PullNotification PullMultipleNotifications
EasyUAClient DataChangeNotification PullDataChangeNotification PullMultipleDataChangeNotifications
EventNotification PullEventNotification PullMultipleEventNotifications
ServerConditionChanged PullServerConditionChanged PullMultipleServerConditionChanges
EasyUASubscriber Class DataSetMessage Event PullDataSetMessage Method PullMultipleDataSetMessages Method
ResolverAccess Event PullResolverAccess Method PullMultipleResolverAccesses Method

Each PullXXXX or PullMultipleXXXX method takes an argument that specifies a timeout (in milliseconds). When a notification is available, the methods returns it immediately, and return a non-null object containing the event arguments (or an array of such event arguments, for PullMultipleXXXX). If no notifications are available during the specified period (timeout), the methods returns after the period elapses, but the return value is a null reference.

After your code receives a non-null event arguments object, it can process it as it would do in a traditional event handler.

You will probably be calling the PullXXXX or PullMultipleXXXX method in a loop with some termination condition. Specify a timeout that will allow the loop to react to the termination condition quickly enough. You should not, however, use very low (or zero) timeouts in such a loop, because that would lead to unnecessary high CPU consumption.

In order to use the event pull mechanism, your code needs to set up a queue with a fixed capacity upfront. This is done by setting a corresponding property in the EasyXXClient object. By convention, for an event named XXXX, the property name is PullXXXXQueueCapacity. For example, set the EasyUAClient.PullDataChangeNotificationQueueCapacity property to allocate a queue for OPC UA data change notifications.

If you do not set the queue capacity to a positive (non-zero) value, and attempt to use the event pull mechanism, the PullXXXX or PullMultipleXXXX method will throw an InvalidOperationException.

Examples

Examples for OPC Data Access:

With single item:

// This example shows how to subscribe to item changes and obtain the events by pulling them.

using System;
using OpcLabs.EasyOpc.DataAccess;
using OpcLabs.EasyOpc.DataAccess.OperationModel;

namespace DocExamples.DataAccess._EasyDAClient
{
    class PullItemChanged
    {
        public static void Main1()
        {
            // Instantiate the client object.
            // In order to use event pull, you must set a non-zero queue capacity upfront.
            var client = new EasyDAClient { PullItemChangedQueueCapacity = 1000 };

            Console.WriteLine("Subscribing item changes...");
            client.SubscribeItem("", "OPCLabs.KitServer.2", "Simulation.Random", 1000);

            Console.WriteLine("Processing item changes for 1 minute...");
            int endTick = Environment.TickCount + 60 * 1000;
            do
            {
                EasyDAItemChangedEventArgs eventArgs = client.PullItemChanged(2 * 1000);
                if (!(eventArgs is null))
                    // Handle the notification event
                    Console.WriteLine(eventArgs);
            } while (Environment.TickCount < endTick);

            Console.WriteLine("Unsubscribing item changes...");
            client.UnsubscribeAllItems();

            Console.WriteLine("Finished.");
        }
    }
}
# This example shows how to subscribe to item changes and obtain the events by pulling them.

#requires -Version 5.1
using namespace OpcLabs.EasyOpc.DataAccess

# The path below assumes that the current directory is [ProductDir]/Examples-NET/PowerShell/Windows .
Add-Type -Path "../../../Assemblies/net47/OpcLabs.EasyOpcClassic.dll"

# Instantiate the client object.
$client = New-Object EasyDAClient
# In order to use event pull, you must set a non-zero queue capacity upfront.
$client.PullItemChangedQueueCapacity = 1000

Write-Host "Subscribing item..."
[IEasyDAClientExtension]::SubscribeItem($client, "", "OPCLabs.KitServer.2", "Simulation.Random", 1000)

Write-Host "Processing item changes for 1 minute..."
$stopwatch =  [System.Diagnostics.Stopwatch]::StartNew() 
while ($stopwatch.Elapsed.TotalSeconds -lt 60) {    
    $eventArgs = [IEasyDAClientExtension]::PullItemChanged($client, 2*1000)
    if ($eventArgs -ne $null) {
        # Handle the notification event
        Write-Host $eventArgs
    }
}

Write-Host "Unsubscribing items..."
$client.UnsubscribeAllItems()

Write-Host "Finished."
' This example shows how to subscribe to item changes and obtain the events by pulling them.

Imports OpcLabs.EasyOpc.DataAccess
Imports OpcLabs.EasyOpc.DataAccess.OperationModel

Namespace DocExamples.DataAccess._EasyDAClient
    Partial Friend Class PullItemChanged
        Public Shared Sub Main1()
            Dim client = New EasyDAClient()
            ' In order to use event pull, you must set a non-zero queue capacity upfront.
            client.PullItemChangedQueueCapacity = 1000

            Console.WriteLine("Subscribing item changes...")
            client.SubscribeItem("", "OPCLabs.KitServer.2", "Simulation.Random", 1000)

            Console.WriteLine("Processing item changes for 1 minute...")
            Dim endTick As Integer = Environment.TickCount + 60 * 1000
            Do
                Dim eventArgs As EasyDAItemChangedEventArgs = client.PullItemChanged(2 * 1000)
                If Not eventArgs Is Nothing Then
                    ' Handle the notification event
                    Console.WriteLine(eventArgs)
                End If
            Loop While Environment.TickCount < endTick

            Console.WriteLine("Unsubscribing item changes...")
            client.UnsubscribeAllItems()

            Console.WriteLine("Finished.")
        End Sub
    End Class
End Namespace
// This example shows how to subscribe to item changes and obtain the events by pulling them.

var Client = new ActiveXObject("OpcLabs.EasyOpc.DataAccess.EasyDAClient");
// In order to use event pull, you must set a non-zero queue capacity upfront.
Client.PullItemChangedQueueCapacity = 1000;

WScript.Echo("Subscribing item changes...");
Client.SubscribeItem("", "OPCLabs.KitServer.2", "Simulation.Random", 1000);

WScript.Echo("Processing item changes for 1 minute...");
var endTime = new Date().getTime() + 60*1000
do {
    var EventArgs = Client.PullItemChanged(2*1000);
    if (EventArgs !== null) {
        //  Handle the notification event
        WScript.Echo(EventArgs);
    }
} while(new Date().getTime() < endTime);

WScript.Echo("Unsubscribing item changes...");
Client.UnsubscribeAllItems();

WScript.Echo("Finished.");
// This example shows how to subscribe to item changes and obtain the events by pulling them.

class procedure PullItemChanged.Main;
var
  Client: OpcLabs_EasyOpcClassic_TLB._EasyDAClient;
  EndTick: Cardinal;
  EventArgs: _EasyDAItemChangedEventArgs;
begin
  // Instantiate the client object
  Client := CoEasyDAClient.Create;
  // In order to use event pull, you must set a non-zero queue capacity upfront.
  Client.PullItemChangedQueueCapacity := 1000;

  WriteLn('Subscribing item changes...');
  Client.SubscribeItem('', 'OPCLabs.KitServer.2', 'Simulation.Random', 1000);

  WriteLn('Processing item changes for 1 minute...');
  EndTick := Ticks + 60*1000;
  while Ticks < EndTick do
  begin
    EventArgs := Client.PullItemChanged(2*1000);
    if EventArgs <> nil then
      // Handle the notification event
      WriteLn(EventArgs.ToString);
  end;

  WriteLn('Unsubscribing item changes...');
  Client.UnsubscribeAllItems;

  WriteLn('Finished.');
end;
// This example shows how to subscribe to item changes and obtain the events by pulling them.

$Client = new COM("OpcLabs.EasyOpc.DataAccess.EasyDAClient");
// In order to use event pull, you must set a non-zero queue capacity upfront.
$Client->PullItemChangedQueueCapacity = 1000;

print "Subscribing item changes...\n";
$Client->SubscribeItem("", "OPCLabs.KitServer.2", "Simulation.Random", 1000);

print "Processing item changed events for 1 minute...\n";
$endTime = time() + 60;
do {
    $EventArgs = $Client->PullItemChanged(2*1000);
    if (!is_null($EventArgs)) {
        // Handle the notification event
        print $EventArgs->ToString();
        print "\n";
    }
} while (time() < $endTime);
// This example shows how to subscribe to item changes and obtain the events by pulling them.

mle_outputtext.Text = ""

// Instantiate the client object
OLEObject client
client = CREATE OLEObject
client.ConnectToNewObject("OpcLabs.EasyOpc.DataAccess.EasyDAClient")
// In order to use event pull, you must set a non-zero queue capacity upfront.
client.PullItemChangedQueueCapacity = 1000

mle_outputtext.Text = mle_outputtext.Text + "Subscribing item changes..." + "~r~n"
client.SubscribeItem("", "OPCLabs.KitServer.2", "Simulation.Random", 1000)

mle_outputtext.Text = mle_outputtext.Text + "Processing item changes for 1 minute..." + "~r~n"

Time endTime = RelativeTime(Now(), 60)
DO
    OLEObject eventArgs
    eventArgs = client.PullItemChanged(2*1000)
    IF NOT IsNull(eventArgs) THEN
        // Handle the notification event
        mle_outputtext.Text = mle_outputtext.Text + eventArgs.DisplayString + "~r~n"
    END IF
LOOP WHILE Now() < endTime

mle_outputtext.Text = mle_outputtext.Text + "Unsubscribing item changes..." + "~r~n"
client.UnsubscribeAllItems()

mle_outputtext.Text = mle_outputtext.Text + "~r~n" 
mle_outputtext.Text = mle_outputtext.Text + "Finished." + "~r~n" 
# This example shows how to subscribe to item changes and obtain the events by pulling them.

import time
import win32com.client

# Instantiate the client object
client = win32com.client.Dispatch('OpcLabs.EasyOpc.DataAccess.EasyDAClient') 
# In order to use event pull, you must set a non-zero queue capacity upfront.
client.PullItemChangedQueueCapacity = 1000

print('Subscribing item changes...')
client.SubscribeItem('', 'OPCLabs.KitServer.2', 'Simulation.Random', 1000)

print('Processing item changes for 1 minute...')
endTime = time.time() + 60
while time.time() < endTime:
    eventArgs = client.PullItemChanged(2*1000)
    if eventArgs is not None:
        # Handle the notification event
        print(eventArgs)

print('Unsubscribing item changes...')
client.UnsubscribeAllItems()

print('Finished.')
Rem This example shows how to subscribe to item changes and obtain the events by pulling them.

Option Explicit

Dim Client: Set Client = CreateObject("OpcLabs.EasyOpc.DataAccess.EasyDAClient")
' In order to use event pull, you must set a non-zero queue capacity upfront.
Client.PullItemChangedQueueCapacity = 1000

WScript.Echo "Subscribing item changes..."
Client.SubscribeItem "", "OPCLabs.KitServer.2", "Simulation.Random", 1000

WScript.Echo "Processing item changes for 1 minute..."
Dim endTime: endTime = Now() + 60*(1/24/60/60)
Do
    Dim EventArgs: Set EventArgs = Client.PullItemChanged(2*1000)
    If Not (EventArgs Is Nothing) Then
        ' Handle the notification event
        WScript.Echo EventArgs
    End If    
Loop While Now() < endTime

WScript.Echo "Unsubscribing item changes..."
Client.UnsubscribeAllItems

WScript.Echo "Finished."

With multiple items:

# This example shows how to subscribe to changes of multiple items and obtain the item changed events by pulling them.

#requires -Version 5.1
using namespace OpcLabs.EasyOpc.DataAccess
using namespace OpcLabs.EasyOpc.DataAccess.OperationModel

# The path below assumes that the current directory is [ProductDir]/Examples-NET/PowerShell/Windows .
Add-Type -Path "../../../Assemblies/net47/OpcLabs.EasyOpcClassic.dll"

# Instantiate the client object.
$client = New-Object EasyDAClient
# In order to use event pull, you must set a non-zero queue capacity upfront.
$client.PullItemChangedQueueCapacity = 1000

Write-Host "Subscribing item changes..."
$handleArray = [OpcLabs.EasyOpc.DataAccess.IEasyDAClientExtension]::SubscribeMultipleItems($client, @(
    (New-Object DAItemGroupArguments("", "OPCLabs.KitServer.2", "Simulation.Random", 1000, $null)),
    (New-Object DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Ramp (1 min)", 1000, $null)),
    (New-Object DAItemGroupArguments("", "OPCLabs.KitServer.2", "Trends.Sine (1 min)", 1000, $null)),
    # Intentionally specifying an unknown item here, to demonstrate its behavior.
    (New-Object DAItemGroupArguments("", "OPCLabs.KitServer.2", "SomeUnknownItem", 1000, $null))
    ))

Write-Host "Processing item changes for 1 minute..."
$stopwatch =  [System.Diagnostics.Stopwatch]::StartNew() 
while ($stopwatch.Elapsed.TotalSeconds -lt 60) {    
    $eventArgs = [IEasyDAClientExtension]::PullItemChanged($client, 2*1000)
    if ($eventArgs -ne $null) {
        # Handle the notification event
        if ($eventArgs.Succeeded) {
            Write-Host "$($eventArgs.Arguments.ItemDescriptor.ItemId): $($eventArgs.Vtq)"
        }
        else {
            Write-Host "$($eventArgs.Arguments.ItemDescriptor.ItemId) *** Failure: $($eventArgs.ErrorMessageBrief)"
        }
    }
}

Write-Host "Unsubscribing item changes..."
$client.UnsubscribeAllItems()

Write-Host "Finished."
// This example shows how to subscribe to changes of multiple items and obtain the item changed events by pulling them.

class procedure PullItemChanged.MultipleItems;
var
  Arguments: OleVariant;
  Client: OpcLabs_EasyOpcClassic_TLB._EasyDAClient;
  EndTick: Cardinal;
  EventArgs: _EasyDAItemChangedEventArgs;
  HandleArray: OleVariant;
  ItemSubscriptionArguments1: _EasyDAItemSubscriptionArguments;
  ItemSubscriptionArguments2: _EasyDAItemSubscriptionArguments;
  ItemSubscriptionArguments3: _EasyDAItemSubscriptionArguments;
  ItemSubscriptionArguments4: _EasyDAItemSubscriptionArguments;
begin
  ItemSubscriptionArguments1 := CoEasyDAItemSubscriptionArguments.Create;
  ItemSubscriptionArguments1.ServerDescriptor.ServerClass := 'OPCLabs.KitServer.2';
  ItemSubscriptionArguments1.ItemDescriptor.ItemID := 'Simulation.Random';
  ItemSubscriptionArguments1.GroupParameters.RequestedUpdateRate := 1000;

  ItemSubscriptionArguments2 := CoEasyDAItemSubscriptionArguments.Create;
  ItemSubscriptionArguments2.ServerDescriptor.ServerClass := 'OPCLabs.KitServer.2';
  ItemSubscriptionArguments2.ItemDescriptor.ItemID := 'Trends.Ramp (1 min)';
  ItemSubscriptionArguments2.GroupParameters.RequestedUpdateRate := 1000;

  ItemSubscriptionArguments3 := CoEasyDAItemSubscriptionArguments.Create;
  ItemSubscriptionArguments3.ServerDescriptor.ServerClass := 'OPCLabs.KitServer.2';
  ItemSubscriptionArguments3.ItemDescriptor.ItemID := 'Trends.Sine (1 min)';
  ItemSubscriptionArguments3.GroupParameters.RequestedUpdateRate := 1000;

  // Intentionally specifying an unknown item here, to demonstrate its behavior.
  ItemSubscriptionArguments4 := CoEasyDAItemSubscriptionArguments.Create;
  ItemSubscriptionArguments4.ServerDescriptor.ServerClass := 'OPCLabs.KitServer.2';
  ItemSubscriptionArguments4.ItemDescriptor.ItemID := 'SomeUnknownItem';
  ItemSubscriptionArguments4.GroupParameters.RequestedUpdateRate := 1000;

  Arguments := VarArrayCreate([0, 3], varVariant);
  Arguments[0] := ItemSubscriptionArguments1;
  Arguments[1] := ItemSubscriptionArguments2;
  Arguments[2] := ItemSubscriptionArguments3;
  Arguments[3] := ItemSubscriptionArguments4;

  // Instantiate the client object
  Client := CoEasyDAClient.Create;
  // In order to use event pull, you must set a non-zero queue capacity upfront.
  Client.PullItemChangedQueueCapacity := 1000;

  WriteLn('Subscribing item changes...');
  TVarData(HandleArray).VType := varArray or varVariant;
  TVarData(HandleArray).VArray := PVarArray(
    Client.SubscribeMultipleItems(Arguments));

  WriteLn('Processing item changes for 1 minute...');
  EndTick := Ticks + 60*1000;
  while Ticks < EndTick do
  begin
    EventArgs := Client.PullItemChanged(2*1000);
    if EventArgs <> nil then
      // Handle the notification event
      if eventArgs.Succeeded then
        WriteLn(eventArgs.Arguments.ItemDescriptor.ItemId, ': ', eventArgs.Vtq.ToString)
      else
        WriteLn(eventArgs.Arguments.ItemDescriptor.ItemId, ' *** Failure: ', eventArgs.ErrorMessageBrief);
  end;

  WriteLn('Unsubscribing item changes...');
  Client.UnsubscribeAllItems;

  VarClear(HandleArray);
  VarClear(Arguments);

  WriteLn('Finished.');
end;

Examples for OPC Alarms&Events:

// This example shows how to subscribe to events and obtain the notification events by pulling them.

using System;
using OpcLabs.EasyOpc.AlarmsAndEvents;
using OpcLabs.EasyOpc.AlarmsAndEvents.OperationModel;

namespace DocExamples.AlarmsAndEvents._EasyAEClient
{
    class PullNotification
    {
        public static void Main1()
        {
            // Instantiate the client object.
            // In order to use event pull, you must set a non-zero queue capacity upfront.
            using (var client = new EasyAEClient { PullNotificationQueueCapacity = 1000 })
            {
                Console.WriteLine("Subscribing events...");
                int handle = client.SubscribeEvents("", "OPCLabs.KitEventServer.2", 1000);

                Console.WriteLine("Processing event notifications for 1 minute...");
                int endTick = Environment.TickCount + 60 * 1000;
                do
                {
                    EasyAENotificationEventArgs eventArgs = client.PullNotification(2 * 1000);
                    if (!(eventArgs is null))
                        // Handle the notification event
                        Console.WriteLine(eventArgs);
                } while (Environment.TickCount < endTick);

                Console.WriteLine("Unsubscribing events...");
                client.UnsubscribeEvents(handle);

                Console.WriteLine("Finished.");
            }
        }
    }
}
# This example shows how to subscribe to events and obtain the notification events by pulling them.

#requires -Version 5.1
using namespace OpcLabs.EasyOpc.AlarmsAndEvents

# The path below assumes that the current directory is [ProductDir]/Examples-NET/PowerShell/Windows .
Add-Type -Path "../../../Assemblies/net47/OpcLabs.EasyOpcClassic.dll"

# Instantiate the client object.
$client = New-Object EasyAEClient
# In order to use event pull, you must set a non-zero queue capacity upfront.
$client.PullNotificationQueueCapacity = 1000

Write-Host "Subscribing events..."
$handle = [OpcLabs.EasyOpc.AlarmsAndEvents.IEasyAEClientExtension]::SubscribeEvents($client, 
    "", "OPCLabs.KitEventServer.2", 1000)

Write-Host "Processing event notifications for 1 minute..."
$stopwatch =  [System.Diagnostics.Stopwatch]::StartNew() 
while ($stopwatch.Elapsed.TotalSeconds -lt 60) {    
    $eventArgs = $client.PullNotification(2*1000)
    if ($eventArgs -ne $null) {
        # Handle the notification event
        Write-Host $eventArgs
    }
}

Write-Host "Unsubscribing events..."
$client.UnsubscribeEvents($handle)

Write-Host "Finished."
' This example shows how to subscribe to events and obtain the notification events by pulling them.

Imports OpcLabs.EasyOpc.AlarmsAndEvents
Imports OpcLabs.EasyOpc.AlarmsAndEvents.OperationModel

Namespace DocExamples.AlarmsAndEvents._EasyAEClient
    Partial Friend Class PullNotification
        Public Shared Sub Main1()
            Using client = New EasyAEClient()
                ' In order to use event pull, you must set a non-zero queue capacity upfront.
                client.PullNotificationQueueCapacity = 1000

                Console.WriteLine("Subscribing events...")
                Dim handle As Integer = client.SubscribeEvents("", "OPCLabs.KitEventServer.2", 1000)

                Console.WriteLine("Processing event notifications for 1 minute...")
                Dim endTick As Integer = Environment.TickCount + 60 * 1000
                Do
                    Dim eventArgs As EasyAENotificationEventArgs = client.PullNotification(2 * 1000)
                    If Not eventArgs Is Nothing Then
                        ' Handle the notification event
                        Console.WriteLine(eventArgs)
                    End If
                Loop While Environment.TickCount < endTick

                Console.WriteLine("Unsubscribing events...")
                client.UnsubscribeEvents(handle)
            End Using

            Console.WriteLine("Finished.")
        End Sub
    End Class
End Namespace
// This example shows how to subscribe to events and obtain the notification events by pulling them.

class procedure PullNotification.Main;
var
  Client: OpcLabs_EasyOpcClassic_TLB._EasyAEClient;
  EndTick: Cardinal;
  EventArgs: _EasyAENotificationEventArgs;
  Handle: Integer;
  ServerDescriptor: _ServerDescriptor;
  State: OleVariant;
  SubscriptionParameters: _AESubscriptionParameters;
begin
  ServerDescriptor := CoServerDescriptor.Create;
  ServerDescriptor.ServerClass := 'OPCLabs.KitEventServer.2';

  // Instantiate the client object
  Client := CoEasyAEClient.Create;
  // In order to use event pull, you must set a non-zero queue capacity upfront.
  Client.PullNotificationQueueCapacity := 1000;

  WriteLn('Subscribing events...');
  SubscriptionParameters := CoAESubscriptionParameters.Create;
  SubscriptionParameters.NotificationRate := 1000;
  Handle := Client.SubscribeEvents(ServerDescriptor, SubscriptionParameters, true, State);

  WriteLn('Processing event notifications for 1 minute...');
  EndTick := Ticks + 60*1000;
  while Ticks < EndTick do
  begin
    EventArgs := Client.PullNotification(2*1000);
    if EventArgs <> nil then
      // Handle the notification event
      WriteLn(EventArgs.ToString);
  end;

  WriteLn('Unsubscribing events...');
  Client.UnsubscribeEvents(Handle);

  WriteLn('Finished.');
end;
// This example shows how to subscribe to events and obtain the notification events by pulling them.

$ServerDescriptor = new COM("OpcLabs.EasyOpc.ServerDescriptor");
$ServerDescriptor->ServerClass = "OPCLabs.KitEventServer.2";

$Client = new COM("OpcLabs.EasyOpc.AlarmsAndEvents.EasyAEClient");
// In order to use event pull, you must set a non-zero queue capacity upfront.
$Client->PullNotificationQueueCapacity = 1000;

print "Subscribing events...\n";
$SubscriptionParameters = new COM("OpcLabs.EasyOpc.AlarmsAndEvents.AESubscriptionParameters");
$SubscriptionParameters->NotificationRate = 1000;
$handle = $Client->SubscribeEvents($ServerDescriptor, $SubscriptionParameters, TRUE, NULL);

print "Processing event notifications for 1 minute...\n";
$endTime = time() + 60;
do {
    $EventArgs = $Client->PullNotification(2*1000);
    if (!is_null($EventArgs)) {
        // Handle the notification event
        print $EventArgs->ToString();
        print "\n";
    }
} while (time() < $endTime);

print "Unsubscribing events...\n";
$Client->UnsubscribeEvents($handle);

print "Finished.\n";
# This example shows how to subscribe to events and obtain the notification events by pulling them.

import time
import win32com.client

serverDescriptor = win32com.client.Dispatch('OpcLabs.EasyOpc.ServerDescriptor')
serverDescriptor.UrlString = 'opcae://localhost/OPCLabs.KitEventServer.2'
#serverDescriptor.ServerClass = 'OPCLabs.KitEventServer.2'

# Instantiate the client object
client = win32com.client.Dispatch('OpcLabs.EasyOpc.AlarmsAndEvents.EasyAEClient') 
# In order to use event pull, you must set a non-zero queue capacity upfront.
client.PullNotificationQueueCapacity = 1000

print('Subscribing events...')
subscriptionParameters = win32com.client.Dispatch('OpcLabs.EasyOpc.AlarmsAndEvents.AESubscriptionParameters')
subscriptionParameters.NotificationRate = 1000
handle = client.SubscribeEvents(serverDescriptor, subscriptionParameters, True, None)

print('Processing event notifications for 1 minute...')
endTime = time.time() + 60
while time.time() < endTime:
    eventArgs = client.PullNotification(2*1000)
    if eventArgs is not None:
        # Handle the notification event
        print(eventArgs)

print('Unsubscribing events...')
client.UnsubscribeAllItems()

print('Finished.')
Rem This example shows how to subscribe to events and obtain the notification events by pulling them.

Option Explicit

Dim ServerDescriptor: Set ServerDescriptor = CreateObject("OpcLabs.EasyOpc.ServerDescriptor")
ServerDescriptor.ServerClass = "OPCLabs.KitEventServer.2"

Dim Client: Set Client = CreateObject("OpcLabs.EasyOpc.AlarmsAndEvents.EasyAEClient")
' In order to use event pull, you must set a non-zero queue capacity upfront.
Client.PullNotificationQueueCapacity = 1000

WScript.Echo "Subscribing events..."
Dim SubscriptionParameters: Set SubscriptionParameters = CreateObject("OpcLabs.EasyOpc.AlarmsAndEvents.AESubscriptionParameters")
SubscriptionParameters.NotificationRate = 1000
Dim handle: handle = Client.SubscribeEvents(ServerDescriptor, SubscriptionParameters, True, Nothing)

WScript.Echo "Processing event notifications for 1 minute..."
Dim endTime: endTime = Now() + 60*(1/24/60/60)
Do
    Dim EventArgs: Set EventArgs = Client.PullNotification(2*1000)
    If Not (EventArgs Is Nothing) Then
        ' Handle the notification event
        WScript.Echo EventArgs
    End If    
Loop While Now() < endTime

WScript.Echo "Unsubscribing events..."
Client.UnsubscribeEvents handle

WScript.Echo "Finished."

 

Examples for OPC XML-DA:

// This example shows how to subscribe to OPC XML-DA item changes and obtain the events by pulling them.

using System;
using OpcLabs.EasyOpc.DataAccess;
using OpcLabs.EasyOpc.DataAccess.OperationModel;

namespace DocExamples.DataAccess.Xml
{
    class PullItemChanged
    {
        public static void Main1Xml()
        {
            // Instantiate the client object.
            // In order to use event pull, you must set a non-zero queue capacity upfront.
            var client = new EasyDAClient { PullItemChangedQueueCapacity = 1000 };

            Console.WriteLine("Subscribing item changes...");
            client.SubscribeItem(
                "http://opcxml.demo-this.com/XmlDaSampleServer/Service.asmx",
                "Dynamic/Analog Types/Int",
                1000,
                state: null);

            Console.WriteLine("Processing item changes for 1 minute...");
            int endTick = Environment.TickCount + 60 * 1000;
            do
            {
                EasyDAItemChangedEventArgs eventArgs = client.PullItemChanged(2 * 1000);
                if (!(eventArgs is null))
                    // Handle the notification event
                    Console.WriteLine(eventArgs);
            } while (Environment.TickCount < endTick);

            Console.WriteLine("Unsubscribing item changes...");
            client.UnsubscribeAllItems();

            Console.WriteLine("Finished.");
        }
    }
}
' This example shows how to subscribe to OPC XML-DA item changes and obtain the events by pulling them.

Imports OpcLabs.EasyOpc.DataAccess
Imports OpcLabs.EasyOpc.DataAccess.OperationModel

Namespace DocExamples.DataAccess.Xml
    Partial Friend Class PullItemChanged
        Public Shared Sub Main1Xml()
            ' In order to use event pull, you must set a non-zero queue capacity upfront.
            Dim client = New EasyDAClient() With {.PullItemChangedQueueCapacity = 1000}

            Console.WriteLine("Subscribing item changes...")
            client.SubscribeItem(
                    "http://opcxml.demo-this.com/XmlDaSampleServer/Service.asmx",
                    "Dynamic/Analog Types/Int",
                    1000,
                    state:=Nothing)

            Console.WriteLine("Processing item changes for 1 minute...")
            Dim endTick As Integer = Environment.TickCount + 60 * 1000
            Do
                Dim eventArgs As EasyDAItemChangedEventArgs = client.PullItemChanged(2 * 1000)
                If Not eventArgs Is Nothing Then
                    ' Handle the notification event
                    Console.WriteLine(eventArgs)
                End If
            Loop While Environment.TickCount < endTick

            Console.WriteLine("Unsubscribing item changes...")
            client.UnsubscribeAllItems()

            Console.WriteLine("Finished.")
        End Sub
    End Class
End Namespace
QuickOPC supports OPC XML-DA also on Linux and macOS.

Examples for OPC UA (Data):

// This example shows how to subscribe to changes of a single monitored item, pull events, and display each change.

using System;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.OperationModel;

namespace UADocExamples._EasyUAClient
{
    class PullDataChangeNotification
    {
        public static void Main1()
        {
            UAEndpointDescriptor endpointDescriptor =
                "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer";
            // or "http://opcua.demo-this.com:51211/UA/SampleServer" (not in .NET Standard)
            // or "https://opcua.demo-this.com:51212/UA/SampleServer/"

            // Instantiate the client object
            // In order to use event pull, you must set a non-zero queue capacity upfront.
            var client = new EasyUAClient { PullDataChangeNotificationQueueCapacity = 1000 };

            Console.WriteLine("Subscribing...");
            client.SubscribeDataChange(endpointDescriptor, "nsu=http://test.org/UA/Data/ ;i=10853", 1000);

            Console.WriteLine("Processing data change events for 1 minute...");
            int endTick = Environment.TickCount + 60 * 1000;
            do
            {
                EasyUADataChangeNotificationEventArgs eventArgs = client.PullDataChangeNotification(2 * 1000);
                if (!(eventArgs is null))
                    // Handle the notification event
                    Console.WriteLine(eventArgs);
            } while (Environment.TickCount < endTick);

            Console.WriteLine("Unsubscribing...");
            client.UnsubscribeAllMonitoredItems();
        }
    }
}
# This example shows how to subscribe to changes of a single monitored item, pull events, and display each change.

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

# The path below assumes that the current directory is [ProductDir]/Examples-NET/PowerShell/Windows .
Add-Type -Path "../../../Assemblies/net47/OpcLabs.EasyOpcUA.dll"

[UAEndpointDescriptor]$endpointDescriptor =
    "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
# or "http://opcua.demo-this.com:51211/UA/SampleServer" (not in .NET Standard)
# or "https://opcua.demo-this.com:51212/UA/SampleServer/"

# Instantiate the client object.
$client = New-Object EasyUAClient
# In order to use event pull, you must set a non-zero queue capacity upfront.
$client.PullDataChangeNotificationQueueCapacity = 1000

Write-Host "Subscribing..."
$client.SubscribeDataChange($endpointDescriptor, "nsu=http://test.org/UA/Data/ ;i=10853", 1000)

Write-Host "Processing data change events for 1 minute..."
$stopwatch =  [System.Diagnostics.Stopwatch]::StartNew() 
while ($stopwatch.Elapsed.TotalSeconds -lt 60) {    
    $eventArgs = $client.PullDataChangeNotification(2*1000)
    if ($eventArgs -ne $null) {
        # Handle the notification event
        Write-Host $eventArgs
    }
}

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

Write-Host "Finished."
' This example shows how to subscribe to changes of a single monitored item, pull events, and display each change.

Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.OperationModel

Namespace UADocExamples._EasyUAClient
    Friend Class PullDataChangeNotification
        Public Shared Sub Main1()

            ' Define which server we will work with.
            Dim endpointDescriptor As UAEndpointDescriptor =
                    "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"
            ' or "http://opcua.demo-this.com:51211/UA/SampleServer" (not in .NET Standard)
            ' or "https://opcua.demo-this.com:51212/UA/SampleServer/"

            ' Instantiate the client object
            Dim client = New EasyUAClient()
            ' In order to use event pull, you must set a non-zero queue capacity upfront.
            client.PullDataChangeNotificationQueueCapacity = 1000

            Console.WriteLine("Subscribing...")
            client.SubscribeDataChange(
                endpointDescriptor,
                "nsu=http://test.org/UA/Data/ ;i=10853",
                1000)   ' or "opc.tcp://opcua.demo-this.com:51210/UA/SampleServer"

            Console.WriteLine("Processing data change events for 1 minute...")
            Dim endTick As Integer = Environment.TickCount + 60 * 1000
            Do
                Dim eventArgs As EasyUADataChangeNotificationEventArgs = client.PullDataChangeNotification(2 * 1000)
                If Not eventArgs Is Nothing Then
                    ' Handle the notification event
                    Console.WriteLine(eventArgs)
                End If
            Loop While Environment.TickCount < endTick
        End Sub
    End Class
End Namespace
// This example shows how to subscribe to changes of a single monitored item, pull events, and display each change.

class procedure PullDataChangeNotification.Main;
var
  Client: EasyUAClient;
  EndTick: Cardinal;
  EventArgs: _EasyUADataChangeNotificationEventArgs;
begin
  // Instantiate the client object
  Client := CoEasyUAClient.Create;
  // In order to use event pull, you must set a non-zero queue capacity upfront.
  Client.PullDataChangeNotificationQueueCapacity := 1000;

  WriteLn('Subscribing...');
  Client.SubscribeDataChange(
    'http://opcua.demo-this.com:51211/UA/SampleServer',
    'nsu=http://test.org/UA/Data/ ;i=10853',
    1000);

  WriteLn('Processing data change events for 1 minute...');
  EndTick := GetTickCount + 60*1000;
  while GetTickCount < EndTick do
  begin
    EventArgs := Client.PullDataChangeNotification(2*1000);
    if EventArgs <> nil then
      // Handle the notification event
      WriteLn(EventArgs.ToString);
  end;

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

  WriteLn('Finished.');
end;
// This example shows how to subscribe to changes of a single monitored item, pull events, and display each change.

var Client = new ActiveXObject("OpcLabs.EasyOpc.UA.EasyUAClient");
// In order to use event pull, you must set a non-zero queue capacity upfront.
Client.PullDataChangeNotificationQueueCapacity = 1000;

WScript.Echo("Subscribing...");
Client.SubscribeDataChange("http://opcua.demo-this.com:51211/UA/SampleServer", "nsu=http://test.org/UA/Data/ ;i=10853", 1000);

WScript.Echo("Processing data change events for 1 minute...");
var endTime = new Date().getTime() + 60*1000
do {
    var EventArgs = Client.PullDataChangeNotification(2*1000);
    if (EventArgs !== null) {
        //  Handle the notification event
        WScript.Echo(EventArgs);
    }
} while(new Date().getTime() < endTime);
// This example shows how to subscribe to changes of a single monitored item, pull events, and display each change.

class procedure PullDataChangeNotification.Main;
var
  Client: OpcLabs_EasyOpcUA_TLB._EasyUAClient;
  EndTick: Cardinal;
  EventArgs: _EasyUADataChangeNotificationEventArgs;
begin
  // Instantiate the client object
  Client := CoEasyUAClient.Create;
  // In order to use event pull, you must set a non-zero queue capacity upfront.
  Client.PullDataChangeNotificationQueueCapacity := 1000;

  WriteLn('Subscribing...');
  Client.SubscribeDataChange(
    'http://opcua.demo-this.com:51211/UA/SampleServer',
    'nsu=http://test.org/UA/Data/ ;i=10853',
    1000);

  WriteLn('Processing data change events for 1 minute...');
  EndTick := Ticks + 60*1000;
  while Ticks < EndTick do
  begin
    EventArgs := Client.PullDataChangeNotification(2*1000);
    if EventArgs <> nil then
      // Handle the notification event
      WriteLn(EventArgs.ToString);
  end;

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

  WriteLn('Finished.');
end;
// This example shows how to subscribe to changes of a single monitored item, pull events, and display each change.

$Client = new COM("OpcLabs.EasyOpc.UA.EasyUAClient");
// In order to use event pull, you must set a non-zero queue capacity upfront.
$Client->PullDataChangeNotificationQueueCapacity = 1000;

print "Subscribing...\n";
$Client->SubscribeDataChange("http://opcua.demo-this.com:51211/UA/SampleServer", "nsu=http://test.org/UA/Data/ ;i=10853", 1000);

print "Processing data change events for 1 minute...\n";
$endTime = time() + 60;
do {
    $EventArgs = $Client->PullDataChangeNotification(2*1000);
    if (!is_null($EventArgs)) {
        // Handle the notification event
        print $EventArgs->ToString();
        print "\n";
    }
} while (time() < $endTime);
// This example shows how to subscribe to changes of a single monitored item, pull events, and display each change.

mle_outputtext.Text = ""

// Instantiate the client object
OLEObject client
client = CREATE OLEObject
client.ConnectToNewObject("OpcLabs.EasyOpc.UA.EasyUAClient")
// In order to use event pull, you must set a non-zero queue capacity upfront.
client.PullDataChangeNotificationQueueCapacity = 1000

mle_outputtext.Text = mle_outputtext.Text + "Subscribing data changes..." + "~r~n"
client.SubscribeDataChange("http://opcua.demo-this.com:51211/UA/SampleServer", "nsu=http://test.org/UA/Data/ ;i=10853", 1000)

mle_outputtext.Text = mle_outputtext.Text + "Processing data change events for 1 minute..." + "~r~n"

Time endTime = RelativeTime(Now(), 60)
DO
    OLEObject eventArgs
    eventArgs = client.PullDataChangeNotification(2*1000)
    IF NOT IsNull(eventArgs) THEN
        // Handle the notification event
        mle_outputtext.Text = mle_outputtext.Text + eventArgs.DisplayString + "~r~n"
    END IF
LOOP WHILE Now() < endTime

mle_outputtext.Text = mle_outputtext.Text + "~r~n" 
mle_outputtext.Text = mle_outputtext.Text + "Finished." + "~r~n" 
# This example shows how to subscribe to changes of a single monitored item, pull events, and display each change.

import time
import win32com.client

# Instantiate the client object
client = win32com.client.Dispatch('OpcLabs.EasyOpc.UA.EasyUAClient') 
# In order to use event pull, you must set a non-zero queue capacity upfront.
client.PullDataChangeNotificationQueueCapacity = 1000

print('Subscribing...')
client.SubscribeDataChange('http://opcua.demo-this.com:51211/UA/SampleServer', 'nsu=http://test.org/UA/Data/ ;i=10853', 1000)

print('Processing data change events for 1 minute...')
endTime = time.time() + 60
while time.time() < endTime:
    eventArgs = client.PullDataChangeNotification(2*1000)
    if eventArgs is not None:
        # Handle the notification event
        print(eventArgs)
Rem This example shows how to subscribe to changes of a single monitored item, pull events, and display each change.

Public Sub PullDataChangeNotification_Main_Command_Click()
    OutputText = ""
    
    Dim eventArgs As EasyUADataChangeNotificationEventArgs
    
    ' Instantiate the client object
    Dim Client As New EasyUAClient
    
    ' In order to use event pull, you must set a non-zero queue capacity upfront.
    Client.PullDataChangeNotificationQueueCapacity = 1000
    
    OutputText = OutputText & "Subscribing..." & vbCrLf
    Call Client.SubscribeDataChange("http://opcua.demo-this.com:51211/UA/SampleServer", "nsu=http://test.org/UA/Data/ ;i=10853", 1000)

    OutputText = OutputText & "Processing data changed notification events for 1 minute..." & vbCrLf
    
    Dim EndTick As Long
    EndTick = GetTickCount + 60000
    While GetTickCount < EndTick
        Set eventArgs = Client.PullDataChangeNotification(2 * 1000)
        If Not eventArgs Is Nothing Then
            ' Handle the notification event
            OutputText = OutputText & eventArgs & vbCrLf
        End If
    Wend
    
    OutputText = OutputText & "Unsubscribing..." & vbCrLf
    Client.UnsubscribeAllMonitoredItems

    OutputText = OutputText & "Finished." & vbCrLf
End Sub
Rem This example shows how to subscribe to changes of a single monitored item, pull events, and display each change.

Option Explicit

' Instantiate the client object
Dim Client: Set Client = CreateObject("OpcLabs.EasyOpc.UA.EasyUAClient")
' In order to use event pull, you must set a non-zero queue capacity upfront.
Client.PullDataChangeNotificationQueueCapacity = 1000

WScript.Echo "Subscribing..."
Client.SubscribeDataChange "http://opcua.demo-this.com:51211/UA/SampleServer", "nsu=http://test.org/UA/Data/ ;i=10853", 1000

WScript.Echo "Processing data change events for 1 minute..."
Dim endTime: endTime = Now() + 60*(1/24/60/60)
Do
    Dim EventArgs: Set EventArgs = Client.PullDataChangeNotification(2*1000)
    If Not (EventArgs Is Nothing) Then
        ' Handle the notification event
        WScript.Echo EventArgs
    End If    
Loop While Now() < endTime
* This example shows how to subscribe to changes of a single monitored item, pull events, and display each change.

DECLARE INTEGER GetTickCount IN kernel32 

THISFORM.OutputEdit.Value = ""

* Instantiate the client object.
oClient = CREATEOBJECT("OpcLabs.EasyOpc.UA.EasyUAClient")

* In order to use event pull, you must set a non-zero queue capacity upfront.
oClient.PullDataChangeNotificationQueueCapacity = 1000

THISFORM.OutputEdit.Value = THISFORM.OutputEdit.Value + "Subscribing..." + CHR(13) + CHR(10)
oClient.SubscribeDataChange("http://opcua.demo-this.com:51211/UA/SampleServer", "nsu=http://test.org/UA/Data/ ;i=10853", 1000)

THISFORM.OutputEdit.Value = THISFORM.OutputEdit.Value + "Processing data change notification events for 1 minute..." + CHR(13) + CHR(10)

EndTick = GetTickCount() + 60000
DO WHILE GetTickCount() < EndTick
    oEventArgs = oClient.PullDataChangeNotification(2*1000)
    IF NOT ISNULL(oEventArgs)
        THISFORM.OutputEdit.Value = THISFORM.OutputEdit.Value + oEventArgs.DisplayString + CHR(13) + CHR(10)
    ENDIF
ENDDO

THISFORM.OutputEdit.Value = THISFORM.OutputEdit.Value + "Unsubscribing..." + CHR(13) + CHR(10)
oClient.UnsubscribeAllMonitoredItems()

THISFORM.OutputEdit.Value = THISFORM.OutputEdit.Value + "Finished." + CHR(13) + CHR(10)

Examples for OPC UA (Alarms & Conditions):

// This example shows how to subscribe to event notifications, pull events, and display each incoming event.

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

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

            // Instantiate the client object.
            // In order to use event pull, you must set a non-zero queue capacity upfront.
            var client = new EasyUAClient { PullEventNotificationQueueCapacity = 1000 };

            Console.WriteLine("Subscribing...");
            client.SubscribeEvent(endpointDescriptor, UAObjectIds.Server, 1000);

            Console.WriteLine("Processing event notifications for 30 seconds...");
            int endTick = Environment.TickCount + 30 * 1000;
            do
            {
                EasyUAEventNotificationEventArgs eventArgs = client.PullEventNotification(2 * 1000);
                if (!(eventArgs is null))
                    // Handle the notification event.
                    Console.WriteLine(eventArgs);
            } while (Environment.TickCount < endTick);

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

            Console.WriteLine("Finished.");
        }

        // Example output (truncated):
        //Subscribing...
        //Processing event notifications for 30 seconds...
        //[] Success
        //[] Success; Refresh; RefreshInitiated
        //[] Success; Refresh; (10 field results) [EastTank] 100! "The dialog was activated" @9/10/2019 8:08:23 PM
        //[] Success; Refresh; (10 field results) [EastTank] 500! "The alarm was acknoweledged." @10/14/2019 4:00:13 PM
        //[] Success; Refresh; (10 field results) [EastTank] 100! "The alarm was acknoweledged." @11/9/2019 9:56:23 AM
        //[] Success; Refresh; (10 field results) [EastTank] 500! "The alarm was acknoweledged." @10/14/2019 4:00:17 PM
        //[] Success; Refresh; (10 field results) [EastTank] 100! "The alarm severity has increased." @9/10/2019 8:09:07 PM
        //[] Success; Refresh; (10 field results) [EastTank] 100! "The alarm severity has increased." @9/10/2019 8:10:09 PM
        //[] Success; Refresh; (10 field results) [NorthMotor] 100! "The dialog was activated" @9/10/2019 8:08:25 PM
        //[] Success; Refresh; (10 field results) [NorthMotor] 500! "The alarm was acknoweledged." @10/14/2019 4:00:02 PM
        //[] Success; Refresh; (10 field results) [NorthMotor] 500! "The alarm was acknoweledged." @10/14/2019 4:00:16 PM
        //[] Success; Refresh; (10 field results) [NorthMotor] 300! "The alarm severity has increased." @11/9/2019 10:29:42 AM
        //[] Success; Refresh; (10 field results) [NorthMotor] 100! "The alarm severity has increased." @9/10/2019 8:09:11 PM
        //[] Success; Refresh; (10 field results) [NorthMotor] 100! "The alarm severity has increased." @9/10/2019 8:10:19 PM
        //[] Success; Refresh; (10 field results) [WestTank] 100! "The dialog was activated" @9/10/2019 8:08:25 PM
        //[] Success; Refresh; (10 field results) [WestTank] 300! "The alarm was acknoweledged." @10/14/2019 4:00:12 PM
        //[] Success; Refresh; (10 field results) [WestTank] 300! "The alarm severity has increased." @11/9/2019 10:29:42 AM
        //[] Success; Refresh; (10 field results) [WestTank] 300! "The alarm was acknoweledged." @10/14/2019 4:00:04 PM
        //[] Success; Refresh; (10 field results) [WestTank] 100! "The alarm severity has increased." @9/10/2019 8:08:58 PM
        //[] Success; Refresh; (10 field results) [WestTank] 100! "The alarm severity has increased." @9/10/2019 8:09:48 PM
        //[] Success; Refresh; (10 field results) [SouthMotor] 100! "The dialog was activated" @9/10/2019 8:08:25 PM
        //[] Success; Refresh; (10 field results) [SouthMotor] 300! "The alarm severity has increased." @11/9/2019 10:29:42 AM
        //[] Success; Refresh; (10 field results) [SouthMotor] 700! "The alarm was acknoweledged." @10/14/2019 4:00:21 PM
        //[] Success; Refresh; (10 field results) [SouthMotor] 500! "The alarm was acknoweledged." @10/14/2019 4:00:03 PM
        //[] Success; Refresh; (10 field results) [SouthMotor] 100! "The alarm severity has increased." @9/10/2019 8:09:02 PM
        //[] Success; Refresh; (10 field results) [SouthMotor] 100! "The alarm severity has increased." @9/10/2019 8:09:59 PM
        //[] Success; Refresh; RefreshComplete
        //[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:43 AM
        //[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:43 AM
        //[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:44 AM
        //[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:44 AM
        //[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:45 AM
        //[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:45 AM
        //[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:46 AM
        //[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:46 AM
        //[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:47 AM
        //[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:47 AM
        //[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:48 AM
        //[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:48 AM
        //[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:49 AM
        //[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:49 AM
        //[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:50 AM
        //[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:50 AM
        //[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:51 AM
        //[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:51 AM
        //[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:52 AM
        //[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:52 AM
        //[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:53 AM
        //[] Success; (10 field results) [NorthMotor] 500! "The alarm severity has increased." @11/9/2019 10:29:53 AM
        //[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:53 AM
        //[] Success; (10 field results) [WestTank] 500! "The alarm severity has increased." @11/9/2019 10:29:53 AM
        //[] Success; (10 field results) [SouthMotor] 500! "The alarm severity has increased." @11/9/2019 10:29:53 AM
        //[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:54 AM
        //[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:54 AM
        //[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:55 AM
        //...
    }
}
# This example shows how to subscribe to event notifications, pull events, and display each incoming event.

#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 "../../../Assemblies/net47/OpcLabs.EasyOpcUA.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
# In order to use event pull, you must set a non-zero queue capacity upfront.
$client.PullEventNotificationQueueCapacity = 1000

Write-Host "Subscribing..."
[IEasyUAClientExtension]::SubscribeEvent($client, $endpointDescriptor, [UAObjectIds]::Server, 1000)

Write-Host "Processing event notifications for 30 seconds..."
$stopwatch =  [System.Diagnostics.Stopwatch]::StartNew() 
while ($stopwatch.Elapsed.TotalSeconds -lt 60) {    
    $eventArgs = $client.PullEventNotification(2*1000)
    if ($eventArgs -ne $null) {
        # Handle the notification event.
        Write-Host $eventArgs
    }
}

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

Write-Host "Finished."


# Example output (truncated):
#Subscribing...
#Processing event notifications for 30 seconds...
#[] Success
#[] Success; Refresh; RefreshInitiated
#[] Success; Refresh; (10 field results) [EastTank] 100! "The dialog was activated" @9/10/2019 8:08:23 PM
#[] Success; Refresh; (10 field results) [EastTank] 500! "The alarm was acknoweledged." @10/14/2019 4:00:13 PM
#[] Success; Refresh; (10 field results) [EastTank] 100! "The alarm was acknoweledged." @11/9/2019 9:56:23 AM
#[] Success; Refresh; (10 field results) [EastTank] 500! "The alarm was acknoweledged." @10/14/2019 4:00:17 PM
#[] Success; Refresh; (10 field results) [EastTank] 100! "The alarm severity has increased." @9/10/2019 8:09:07 PM
#[] Success; Refresh; (10 field results) [EastTank] 100! "The alarm severity has increased." @9/10/2019 8:10:09 PM
#[] Success; Refresh; (10 field results) [NorthMotor] 100! "The dialog was activated" @9/10/2019 8:08:25 PM
#[] Success; Refresh; (10 field results) [NorthMotor] 500! "The alarm was acknoweledged." @10/14/2019 4:00:02 PM
#[] Success; Refresh; (10 field results) [NorthMotor] 500! "The alarm was acknoweledged." @10/14/2019 4:00:16 PM
#[] Success; Refresh; (10 field results) [NorthMotor] 300! "The alarm severity has increased." @11/9/2019 10:29:42 AM
#[] Success; Refresh; (10 field results) [NorthMotor] 100! "The alarm severity has increased." @9/10/2019 8:09:11 PM
#[] Success; Refresh; (10 field results) [NorthMotor] 100! "The alarm severity has increased." @9/10/2019 8:10:19 PM
#[] Success; Refresh; (10 field results) [WestTank] 100! "The dialog was activated" @9/10/2019 8:08:25 PM
#[] Success; Refresh; (10 field results) [WestTank] 300! "The alarm was acknoweledged." @10/14/2019 4:00:12 PM
#[] Success; Refresh; (10 field results) [WestTank] 300! "The alarm severity has increased." @11/9/2019 10:29:42 AM
#[] Success; Refresh; (10 field results) [WestTank] 300! "The alarm was acknoweledged." @10/14/2019 4:00:04 PM
#[] Success; Refresh; (10 field results) [WestTank] 100! "The alarm severity has increased." @9/10/2019 8:08:58 PM
#[] Success; Refresh; (10 field results) [WestTank] 100! "The alarm severity has increased." @9/10/2019 8:09:48 PM
#[] Success; Refresh; (10 field results) [SouthMotor] 100! "The dialog was activated" @9/10/2019 8:08:25 PM
#[] Success; Refresh; (10 field results) [SouthMotor] 300! "The alarm severity has increased." @11/9/2019 10:29:42 AM
#[] Success; Refresh; (10 field results) [SouthMotor] 700! "The alarm was acknoweledged." @10/14/2019 4:00:21 PM
#[] Success; Refresh; (10 field results) [SouthMotor] 500! "The alarm was acknoweledged." @10/14/2019 4:00:03 PM
#[] Success; Refresh; (10 field results) [SouthMotor] 100! "The alarm severity has increased." @9/10/2019 8:09:02 PM
#[] Success; Refresh; (10 field results) [SouthMotor] 100! "The alarm severity has increased." @9/10/2019 8:09:59 PM
#[] Success; Refresh; RefreshComplete
#[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:43 AM
#[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:43 AM
#[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:44 AM
#[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:44 AM
#[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:45 AM
#[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:45 AM
#[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:46 AM
#[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:46 AM
#[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:47 AM
#[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:47 AM
#[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:48 AM
#[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:48 AM
#[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:49 AM
#[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:49 AM
#[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:50 AM
#[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:50 AM
#[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:51 AM
#[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:51 AM
#[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:52 AM
#[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:52 AM
#[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:53 AM
#[] Success; (10 field results) [NorthMotor] 500! "The alarm severity has increased." @11/9/2019 10:29:53 AM
#[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:53 AM
#[] Success; (10 field results) [WestTank] 500! "The alarm severity has increased." @11/9/2019 10:29:53 AM
#[] Success; (10 field results) [SouthMotor] 500! "The alarm severity has increased." @11/9/2019 10:29:53 AM
#[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:54 AM
#[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:54 AM
#[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:55 AM
#...

// This example shows how to subscribe to event notifications, pull events, and display each incoming event.

class procedure PullEventNotification.Main;
var
  Client: OpcLabs_EasyOpcUA_TLB._EasyUAClient;
  EndTick: Cardinal;
  EventArgs: _EasyUAEventNotificationEventArgs;
begin
  // Instantiate the client object and hook events
  Client := CoEasyUAClient.Create;
  // In order to use event pull, you must set a non-zero queue capacity upfront.
  Client.PullEventNotificationQueueCapacity := 1000;

  WriteLn('Subscribing...');
  Client.SubscribeEvent(
    'opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer',
    'nsu=http://opcfoundation.org/UA/;i=2253',  // UAObjectIds.Server
    1000);

  WriteLn('Processing event notifications for 30 seconds...');
  EndTick := Ticks + 30*1000;
  while Ticks < EndTick do
  begin
    EventArgs := Client.PullEventNotification(2*1000);
    if EventArgs <> nil then
      // Handle the notification event
      WriteLn(EventArgs.ToString);
  end;

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

  WriteLn('Finished.');
end;

// Example output (truncated):
//Subscribing...
//Processing event notifications for 30 seconds...
//[] Success
//[] Success; Refresh; RefreshInitiated
//[] Success; Refresh; (10 field results) [EastTank] 100! "The dialog was activated" @9/10/2019 8:08:23 PM
//[] Success; Refresh; (10 field results) [EastTank] 500! "The alarm was acknoweledged." @10/14/2019 4:00:13 PM
//[] Success; Refresh; (10 field results) [EastTank] 100! "The alarm was acknoweledged." @11/9/2019 9:56:23 AM
//[] Success; Refresh; (10 field results) [EastTank] 500! "The alarm was acknoweledged." @10/14/2019 4:00:17 PM
//[] Success; Refresh; (10 field results) [EastTank] 100! "The alarm severity has increased." @9/10/2019 8:09:07 PM
//[] Success; Refresh; (10 field results) [EastTank] 100! "The alarm severity has increased." @9/10/2019 8:10:09 PM
//[] Success; Refresh; (10 field results) [NorthMotor] 100! "The dialog was activated" @9/10/2019 8:08:25 PM
//[] Success; Refresh; (10 field results) [NorthMotor] 500! "The alarm was acknoweledged." @10/14/2019 4:00:02 PM
//[] Success; Refresh; (10 field results) [NorthMotor] 500! "The alarm was acknoweledged." @10/14/2019 4:00:16 PM
//[] Success; Refresh; (10 field results) [NorthMotor] 300! "The alarm severity has increased." @11/9/2019 10:29:42 AM
//[] Success; Refresh; (10 field results) [NorthMotor] 100! "The alarm severity has increased." @9/10/2019 8:09:11 PM
//[] Success; Refresh; (10 field results) [NorthMotor] 100! "The alarm severity has increased." @9/10/2019 8:10:19 PM
//[] Success; Refresh; (10 field results) [WestTank] 100! "The dialog was activated" @9/10/2019 8:08:25 PM
//[] Success; Refresh; (10 field results) [WestTank] 300! "The alarm was acknoweledged." @10/14/2019 4:00:12 PM
//[] Success; Refresh; (10 field results) [WestTank] 300! "The alarm severity has increased." @11/9/2019 10:29:42 AM
//[] Success; Refresh; (10 field results) [WestTank] 300! "The alarm was acknoweledged." @10/14/2019 4:00:04 PM
//[] Success; Refresh; (10 field results) [WestTank] 100! "The alarm severity has increased." @9/10/2019 8:08:58 PM
//[] Success; Refresh; (10 field results) [WestTank] 100! "The alarm severity has increased." @9/10/2019 8:09:48 PM
//[] Success; Refresh; (10 field results) [SouthMotor] 100! "The dialog was activated" @9/10/2019 8:08:25 PM
//[] Success; Refresh; (10 field results) [SouthMotor] 300! "The alarm severity has increased." @11/9/2019 10:29:42 AM
//[] Success; Refresh; (10 field results) [SouthMotor] 700! "The alarm was acknoweledged." @10/14/2019 4:00:21 PM
//[] Success; Refresh; (10 field results) [SouthMotor] 500! "The alarm was acknoweledged." @10/14/2019 4:00:03 PM
//[] Success; Refresh; (10 field results) [SouthMotor] 100! "The alarm severity has increased." @9/10/2019 8:09:02 PM
//[] Success; Refresh; (10 field results) [SouthMotor] 100! "The alarm severity has increased." @9/10/2019 8:09:59 PM
//[] Success; Refresh; RefreshComplete
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:43 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:43 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:44 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:44 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:45 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:45 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:46 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:46 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:47 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:47 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:48 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:48 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:49 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:49 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:50 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:50 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:51 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:51 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:52 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:52 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:53 AM
//[] Success; (10 field results) [NorthMotor] 500! "The alarm severity has increased." @11/9/2019 10:29:53 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:53 AM
//[] Success; (10 field results) [WestTank] 500! "The alarm severity has increased." @11/9/2019 10:29:53 AM
//[] Success; (10 field results) [SouthMotor] 500! "The alarm severity has increased." @11/9/2019 10:29:53 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:54 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:54 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:55 AM
//...

// This example shows how to subscribe to event notifications, pull events, and display each incoming event.


// Instantiate the client object and hook events
$Client = new COM("OpcLabs.EasyOpc.UA.EasyUAClient");
$Client->PullEventNotificationQueueCapacity = 1000;

printf("Subscribing...\n");
$Client->SubscribeEvent(
    "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer",
    "nsu=http://opcfoundation.org/UA/;i=2253",  // UAObjectIds_Server
    1000);

printf("Processing event notifications for 30 seconds...\n");
$startTime = time(); 
do {
    $EventArgs = $Client->PullEventNotification(2*1000);
    if (!is_null($EventArgs)) {
        // Handle the notification event
        printf("%s\n", $EventArgs);
    }
} 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);

// Example output (truncated):
//Subscribing...
//Processing event notifications for 30 seconds...
//[] Success
//[] Success; Refresh; RefreshInitiated
//[] Success; Refresh; (10 field results) [EastTank] 100! "The dialog was activated" @9/10/2019 8:08:23 PM
//[] Success; Refresh; (10 field results) [EastTank] 500! "The alarm was acknoweledged." @10/14/2019 4:00:13 PM
//[] Success; Refresh; (10 field results) [EastTank] 100! "The alarm was acknoweledged." @11/9/2019 9:56:23 AM
//[] Success; Refresh; (10 field results) [EastTank] 500! "The alarm was acknoweledged." @10/14/2019 4:00:17 PM
//[] Success; Refresh; (10 field results) [EastTank] 100! "The alarm severity has increased." @9/10/2019 8:09:07 PM
//[] Success; Refresh; (10 field results) [EastTank] 100! "The alarm severity has increased." @9/10/2019 8:10:09 PM
//[] Success; Refresh; (10 field results) [NorthMotor] 100! "The dialog was activated" @9/10/2019 8:08:25 PM
//[] Success; Refresh; (10 field results) [NorthMotor] 500! "The alarm was acknoweledged." @10/14/2019 4:00:02 PM
//[] Success; Refresh; (10 field results) [NorthMotor] 500! "The alarm was acknoweledged." @10/14/2019 4:00:16 PM
//[] Success; Refresh; (10 field results) [NorthMotor] 300! "The alarm severity has increased." @11/9/2019 10:29:42 AM
//[] Success; Refresh; (10 field results) [NorthMotor] 100! "The alarm severity has increased." @9/10/2019 8:09:11 PM
//[] Success; Refresh; (10 field results) [NorthMotor] 100! "The alarm severity has increased." @9/10/2019 8:10:19 PM
//[] Success; Refresh; (10 field results) [WestTank] 100! "The dialog was activated" @9/10/2019 8:08:25 PM
//[] Success; Refresh; (10 field results) [WestTank] 300! "The alarm was acknoweledged." @10/14/2019 4:00:12 PM
//[] Success; Refresh; (10 field results) [WestTank] 300! "The alarm severity has increased." @11/9/2019 10:29:42 AM
//[] Success; Refresh; (10 field results) [WestTank] 300! "The alarm was acknoweledged." @10/14/2019 4:00:04 PM
//[] Success; Refresh; (10 field results) [WestTank] 100! "The alarm severity has increased." @9/10/2019 8:08:58 PM
//[] Success; Refresh; (10 field results) [WestTank] 100! "The alarm severity has increased." @9/10/2019 8:09:48 PM
//[] Success; Refresh; (10 field results) [SouthMotor] 100! "The dialog was activated" @9/10/2019 8:08:25 PM
//[] Success; Refresh; (10 field results) [SouthMotor] 300! "The alarm severity has increased." @11/9/2019 10:29:42 AM
//[] Success; Refresh; (10 field results) [SouthMotor] 700! "The alarm was acknoweledged." @10/14/2019 4:00:21 PM
//[] Success; Refresh; (10 field results) [SouthMotor] 500! "The alarm was acknoweledged." @10/14/2019 4:00:03 PM
//[] Success; Refresh; (10 field results) [SouthMotor] 100! "The alarm severity has increased." @9/10/2019 8:09:02 PM
//[] Success; Refresh; (10 field results) [SouthMotor] 100! "The alarm severity has increased." @9/10/2019 8:09:59 PM
//[] Success; Refresh; RefreshComplete
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:43 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:43 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:44 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:44 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:45 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:45 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:46 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:46 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:47 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:47 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:48 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:48 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:49 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:49 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:50 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:50 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:51 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:51 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:52 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:52 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:53 AM
//[] Success; (10 field results) [NorthMotor] 500! "The alarm severity has increased." @11/9/2019 10:29:53 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:53 AM
//[] Success; (10 field results) [WestTank] 500! "The alarm severity has increased." @11/9/2019 10:29:53 AM
//[] Success; (10 field results) [SouthMotor] 500! "The alarm severity has increased." @11/9/2019 10:29:53 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:54 AM
//[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:54 AM
//[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:55 AM
//...

' This example shows how to subscribe to event notifications, pull events, and display each incoming event.

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

Namespace UADocExamples.AlarmsAndConditions
    Friend Class PullEventNotification
        Public Shared Sub Main1()
            ' Instantiate the client object
            Dim client = New EasyUAClient()
            ' In order to use event pull, you must set a non-zero queue capacity upfront.
            client.PullEventNotificationQueueCapacity = 1000

            Console.WriteLine("Subscribing...")
            client.SubscribeEvent(
                "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer",
                UAObjectIds.Server,
                1000)

            Console.WriteLine("Processing event notifications for 30 seconds...")
            Dim endTick As Integer = Environment.TickCount + 30 * 1000
            Do
                Dim eventArgs As EasyUAEventNotificationEventArgs = client.PullEventNotification(2 * 1000)
                If Not eventArgs Is Nothing Then
                    ' Handle the notification event
                    Console.WriteLine(eventArgs)
                End If
            Loop While Environment.TickCount < endTick
        End Sub
    End Class
End Namespace
// This example shows how to subscribe to event notifications, pull events, and display each incoming event.

class procedure PullEventNotification.Main;
var
  Client: EasyUAClient;
  EndTick: Cardinal;
  EventArgs: _EasyUAEventNotificationEventArgs;
begin
  // Instantiate the client object and hook events
  Client := CoEasyUAClient.Create;
  // In order to use event pull, you must set a non-zero queue capacity upfront.
  Client.PullEventNotificationQueueCapacity := 1000;

  WriteLn('Subscribing...');
  Client.SubscribeEvent(
    'opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer',
    'nsu=http://opcfoundation.org/UA/;i=2253',  // UAObjectIds.Server
    1000);

  WriteLn('Processing event notifications for 30 seconds...');
  EndTick := GetTickCount + 60*1000;
  while GetTickCount < EndTick do
  begin
    EventArgs := Client.PullEventNotification(2*1000);
    if EventArgs <> nil then
      // Handle the notification event
      WriteLn(EventArgs.ToString);
  end;

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

  WriteLn('Finished.');
end;
Rem This example shows how to subscribe to event notifications, pull events, and display each incoming event.

Option Explicit

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

' Instantiate the client object and hook events
Dim Client: Set Client = CreateObject("OpcLabs.EasyOpc.UA.EasyUAClient")
' In order to use event pull, you must set a non-zero queue capacity upfront.
Client.PullEventNotificationQueueCapacity = 1000

WScript.Echo "Subscribing..."
Client.SubscribeEvent "opc.tcp://opcua.demo-this.com:62544/Quickstarts/AlarmConditionServer", UAObjectIds_Server, 1000

WScript.Echo "Processing event notifications for 30 seconds..."
Dim endTime: endTime = Now() + 30*(1/24/60/60)
Do
    Dim EventArgs: Set EventArgs = Client.PullEventNotification(2*1000)
    If Not (EventArgs Is Nothing) Then
        ' Handle the notification event
        WScript.Echo EventArgs
    End If    
Loop While Now() < endTime



' Example output (truncated):
'Subscribing...
'Processing event notifications for 30 seconds...
'[] Success
'[] Success; Refresh; RefreshInitiated
'[] Success; Refresh; (10 field results) [EastTank] 100! "The dialog was activated" @9/10/2019 8:08:23 PM
'[] Success; Refresh; (10 field results) [EastTank] 500! "The alarm was acknoweledged." @10/14/2019 4:00:13 PM
'[] Success; Refresh; (10 field results) [EastTank] 100! "The alarm was acknoweledged." @11/9/2019 9:56:23 AM
'[] Success; Refresh; (10 field results) [EastTank] 500! "The alarm was acknoweledged." @10/14/2019 4:00:17 PM
'[] Success; Refresh; (10 field results) [EastTank] 100! "The alarm severity has increased." @9/10/2019 8:09:07 PM
'[] Success; Refresh; (10 field results) [EastTank] 100! "The alarm severity has increased." @9/10/2019 8:10:09 PM
'[] Success; Refresh; (10 field results) [NorthMotor] 100! "The dialog was activated" @9/10/2019 8:08:25 PM
'[] Success; Refresh; (10 field results) [NorthMotor] 500! "The alarm was acknoweledged." @10/14/2019 4:00:02 PM
'[] Success; Refresh; (10 field results) [NorthMotor] 500! "The alarm was acknoweledged." @10/14/2019 4:00:16 PM
'[] Success; Refresh; (10 field results) [NorthMotor] 300! "The alarm severity has increased." @11/9/2019 10:29:42 AM
'[] Success; Refresh; (10 field results) [NorthMotor] 100! "The alarm severity has increased." @9/10/2019 8:09:11 PM
'[] Success; Refresh; (10 field results) [NorthMotor] 100! "The alarm severity has increased." @9/10/2019 8:10:19 PM
'[] Success; Refresh; (10 field results) [WestTank] 100! "The dialog was activated" @9/10/2019 8:08:25 PM
'[] Success; Refresh; (10 field results) [WestTank] 300! "The alarm was acknoweledged." @10/14/2019 4:00:12 PM
'[] Success; Refresh; (10 field results) [WestTank] 300! "The alarm severity has increased." @11/9/2019 10:29:42 AM
'[] Success; Refresh; (10 field results) [WestTank] 300! "The alarm was acknoweledged." @10/14/2019 4:00:04 PM
'[] Success; Refresh; (10 field results) [WestTank] 100! "The alarm severity has increased." @9/10/2019 8:08:58 PM
'[] Success; Refresh; (10 field results) [WestTank] 100! "The alarm severity has increased." @9/10/2019 8:09:48 PM
'[] Success; Refresh; (10 field results) [SouthMotor] 100! "The dialog was activated" @9/10/2019 8:08:25 PM
'[] Success; Refresh; (10 field results) [SouthMotor] 300! "The alarm severity has increased." @11/9/2019 10:29:42 AM
'[] Success; Refresh; (10 field results) [SouthMotor] 700! "The alarm was acknoweledged." @10/14/2019 4:00:21 PM
'[] Success; Refresh; (10 field results) [SouthMotor] 500! "The alarm was acknoweledged." @10/14/2019 4:00:03 PM
'[] Success; Refresh; (10 field results) [SouthMotor] 100! "The alarm severity has increased." @9/10/2019 8:09:02 PM
'[] Success; Refresh; (10 field results) [SouthMotor] 100! "The alarm severity has increased." @9/10/2019 8:09:59 PM
'[] Success; Refresh; RefreshComplete
'[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:43 AM
'[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:43 AM
'[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:44 AM
'[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:44 AM
'[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:45 AM
'[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:45 AM
'[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:46 AM
'[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:46 AM
'[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:47 AM
'[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:47 AM
'[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:48 AM
'[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:48 AM
'[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:49 AM
'[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:49 AM
'[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:50 AM
'[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:50 AM
'[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:51 AM
'[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:51 AM
'[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:52 AM
'[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:52 AM
'[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:53 AM
'[] Success; (10 field results) [NorthMotor] 500! "The alarm severity has increased." @11/9/2019 10:29:53 AM
'[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:53 AM
'[] Success; (10 field results) [WestTank] 500! "The alarm severity has increased." @11/9/2019 10:29:53 AM
'[] Success; (10 field results) [SouthMotor] 500! "The alarm severity has increased." @11/9/2019 10:29:53 AM
'[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:54 AM
'[] Success; (10 field results) [Internal] 500! "Events Raised" @11/9/2019 10:29:54 AM
'[] Success; (10 field results) [Internal] 500! "Raising Events" @11/9/2019 10:29:55 AM
'...

 

Examples for OPC UA PubSub:

The example below subscribes to all dataset messages on an OPC-UA PubSub connection with UDP UADP mapping. The connection is specified by its physical parameters, using the scheme name "opc.udp" and the IP address of the multicast group to listen on.

// This example shows how to subscribe to all dataset messages on an OPC-UA PubSub connection, and pull events, and display
// the incoming datasets.
//
// In order to produce network messages for this example, run the UADemoPublisher tool. For documentation, see
// http://kb.opclabs.com/UADemoPublisher_Basics . In some cases, you may have to specify the interface name to be used.

using System;
using System.Collections.Generic;
using System.Threading;
using OpcLabs.EasyOpc.UA.PubSub;
using OpcLabs.EasyOpc.UA.PubSub.OperationModel;

namespace UADocExamples.PubSub._EasyUASubscriber
{
    class PullDataSetMessage
    {
        public static void Main1()
        {
            // Define the PubSub connection we will work with. Uses implicit conversion from a string.
            UAPubSubConnectionDescriptor pubSubConnectionDescriptor = "opc.udp://239.0.0.1";
            // In some cases you may have to set the interface (network adapter) name that needs to be used, similarly to
            // the statement below. Your actual interface name may differ, of course.
            //pubSubConnectionDescriptor.ResourceAddress.InterfaceName = "Ethernet";

            // Instantiate the subscriber object.
            // In order to use event pull, you must set a non-zero queue capacity upfront.
            var subscriber = new EasyUASubscriber {PullDataSetMessageQueueCapacity = 1000};

            Console.WriteLine("Subscribing...");
            subscriber.SubscribeDataSet(pubSubConnectionDescriptor);

            Console.WriteLine("Processing dataset message events for 20 seconds...");
            int endTick = Environment.TickCount + 20 * 1000;
            do
            {
                EasyUADataSetMessageEventArgs eventArgs = subscriber.PullDataSetMessage(2 * 1000);
                if (!(eventArgs is null))
                {
                    // Display the dataset.
                    if (eventArgs.Succeeded)
                    {
                        // An event with null DataSetData just indicates a successful connection.
                        if (!(eventArgs.DataSetData is null))
                        {
                            Console.WriteLine();
                            Console.WriteLine($"Dataset data: {eventArgs.DataSetData}");
                            foreach (KeyValuePair<string, UADataSetFieldData> pair in eventArgs.DataSetData.FieldDataDictionary)
                                Console.WriteLine(pair);
                        }
                    }
                    else
                    {
                        Console.WriteLine();
                        Console.WriteLine($"*** Failure: {eventArgs.ErrorMessageBrief}");
                    }
                }
            } while (Environment.TickCount < endTick);

            Console.WriteLine("Unsubscribing...");
            subscriber.UnsubscribeAllDataSets();

            Console.WriteLine("Waiting for 1 second...");
            // Unsubscribe operation is asynchronous, messages may still come for a short while.
            Thread.Sleep(1 * 1000);

            Console.WriteLine("Finished.");
        }

        // Example output:
        //
        //Subscribing...
        //Processing dataset message events for 20 seconds...
        //
        //Dataset data: Good; Data; publisher="32", writer=1, class=eae79794-1af7-4f96-8401-4096cd1d8908, fields: 4
        //[#0, True {System.Boolean} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
        //[#1, 7945 {System.Int32} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
        //[#2, 5246 {System.Int32} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
        //[#3, 9/30/2019 11:19:14 AM {System.DateTime} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
        //
        //Dataset data: Good; Data; publisher="32", writer=3, class=96976b7b-0db7-46c3-a715-0979884b55ae, fields: 100
        //[#0, 45 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
        //[#1, 145 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
        //[#2, 245 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
        //[#3, 345 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
        //[#4, 445 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
        //[#5, 545 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
        //[#6, 645 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
        //[#7, 745 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
        //[#8, 845 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
        //[#9, 945 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
        //[#10, 1045 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
        //...
    }
}
' This example shows how to subscribe to all dataset messages on an OPC-UA PubSub connection, and pull events, and display
' the incoming datasets.
'
' In order to produce network messages for this example, run the UADemoPublisher tool. For documentation, see
' http://kb.opclabs.com/UADemoPublisher_Basics . In some cases, you may have to specify the interface name to be used.

Imports OpcLabs.EasyOpc.UA.PubSub
Imports OpcLabs.EasyOpc.UA.PubSub.OperationModel

Namespace UADocExamples.PubSub._EasyUASubscriber
    Friend Class PullDataSetMessage
        Public Shared Sub Main1()

            ' Define the PubSub connection we will work with. Uses implicit conversion from a string.
            Dim pubSubConnectionDescriptor As UAPubSubConnectionDescriptor = "opc.udp://239.0.0.1"
            ' In some cases you may have to set the interface (network adapter) name that needs to be used, similarly to
            ' the statement below. Your actual interface name may differ, of course.
            ' pubSubConnectionDescriptor.ResourceAddress.InterfaceName = "Ethernet"

            ' Instantiate the subscriber object.
            ' In order to use event pull, you must set a non-zero queue capacity upfront.
            Dim subscriber = New EasyUASubscriber()
            subscriber.PullDataSetMessageQueueCapacity = 1000

            Console.WriteLine("Subscribing...")
            subscriber.SubscribeDataSet(pubSubConnectionDescriptor)

            Console.WriteLine("Processing dataset message events for 20 seconds...")
            Dim endTick As Integer = Environment.TickCount + 20 * 1000
            Do
                Dim eventArgs As EasyUADataSetMessageEventArgs = subscriber.PullDataSetMessage(2 * 1000)
                If Not eventArgs Is Nothing Then
                    ' Display the dataset.
                    If eventArgs.Succeeded Then
                        ' An event with null DataSetData just indicates a successful connection.
                        If Not eventArgs.DataSetData Is Nothing Then
                            Console.WriteLine()
                            Console.WriteLine("Dataset data: {0}", eventArgs.DataSetData)
                            For Each pair As KeyValuePair(Of String, UADataSetFieldData) In eventArgs.DataSetData.FieldDataDictionary
                                Console.WriteLine(pair)
                            Next
                        End If
                    Else
                        Console.WriteLine()
                        Console.WriteLine("*** Failure: {0}", eventArgs.ErrorMessageBrief)
                    End If
                End If
            Loop While Environment.TickCount < endTick

            Console.WriteLine("Unsubscribing...")
            subscriber.UnsubscribeAllDataSets()

            Console.WriteLine("Waiting for 1 second...")
            ' Unsubscribe operation is asynchronous, messages may still come for a short while.
            Threading.Thread.Sleep(1 * 1000)

            Console.WriteLine("Finished...")
        End Sub
    End Class

    ' Example output
    '
    'Subscribing...
    'Processing dataset message events for 20 seconds...
    '
    ''Dataset data: Good; Data; publisher="32", writer=1, class=eae79794-1af7-4f96-8401-4096cd1d8908, fields: 4
    '[#0, True {System.Boolean} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
    '[#1, 7945 {System.Int32} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
    '[#2, 5246 {System.Int32} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
    '[#3, 9/30/2019 11:19:14 AM {System.DateTime} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
    '
    'Dataset data: Good; Data; publisher="32", writer=3, class=96976b7b-0db7-46c3-a715-0979884b55ae, fields: 100
    '[#0, 45 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
    '[#1, 145 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
    '[#2, 245 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
    '[#3, 345 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
    '[#4, 445 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
    '[#5, 545 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
    '[#6, 645 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
    '[#7, 745 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
    '[#8, 845 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
    '[#9, 945 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
    '[#10, 1045 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
    '...

End Namespace
// This example shows how to subscribe to all dataset messages on an OPC-UA PubSub connection, and pull events, and display
// the incoming datasets.
//
// In order to produce network messages for this example, run the UADemoPublisher tool. For documentation, see
// http://kb.opclabs.com/UADemoPublisher_Basics . In some cases, you may have to specify the interface name to be used.


class procedure PullDataSetMessage.Main1;
var
  ConnectionDescriptor: _UAPubSubConnectionDescriptor;
  Count: Cardinal;
  Element: OleVariant;
  EndTick: Cardinal;
  EventArgs: _EasyUADataSetMessageEventArgs;
  PairEnumerator: IEnumVARIANT;
  SubscribeDataSetArguments: _EasyUASubscribeDataSetArguments;
  Subscriber: OpcLabs_EasyOpcUA_TLB._EasyUASubscriber;
begin
  // Define the PubSub connection we will work with.
  SubscribeDataSetArguments := CoEasyUASubscribeDataSetArguments.Create;
  ConnectionDescriptor := SubscribeDataSetArguments.DataSetSubscriptionDescriptor.ConnectionDescriptor;
  ConnectionDescriptor.ResourceAddress.ResourceDescriptor.UrlString := 'opc.udp://239.0.0.1';
  // In some cases you may have to set the interface (network adapter) name that needs to be used, similarly to
  // the statement below. Your actual interface name may differ, of course.
  // ConnectionDescriptor.ResourceAddress.InterfaceName := 'Ethernet';

  // Instantiate the subscriber object.
  Subscriber := CoEasyUASubscriber.Create;
  // In order to use event pull, you must set a non-zero queue capacity upfront.
  Subscriber.PullDataSetMessageQueueCapacity := 1000;

  WriteLn('Subscribing...');
  Subscriber.SubscribeDataSet(SubscribeDataSetArguments);

  WriteLn('Processing dataset message events for 20 seconds...');
  EndTick := Ticks + 20*1000;
  while Ticks < EndTick do
  begin
    EventArgs := Subscriber.PullDataSetMessage(2*1000);
    if EventArgs <> nil then
      begin
        // Display the dataset.
        if EventArgs.Succeeded then
        begin
          // An event with null DataSetData just indicates a successful connection.
          if EventArgs.DatasetData <> nil then
          begin
            WriteLn;
            WriteLn('Dataset data: ', EventArgs.DatasetData.ToString);
            PairEnumerator := EventArgs.DataSetData.FieldDataDictionary.GetEnumerator;
            while (PairEnumerator.Next(1, Element, Count) = S_OK) do
            begin
              WriteLn(Element.ToString);
            end;
          end;
        end
        else
        begin
          WriteLn;
             WriteLn(' *** Failure: ', EventArgs.ErrorMessageBrief);
        end;
      end;
  end;

  WriteLn('Unsubscribing...');
  Subscriber.UnsubscribeAllDataSets;

  WriteLn('Waiting for 1 second...');
  // Unsubscribe operation is asynchronous, messages may still come for a short while.
  PumpSleep(1*1000);

  WriteLn('Finished.');
end;

// Example output:
//
//Subscribing...
//Processing dataset message events for 20 seconds...
//
//Dataset data: Good; Data; publisher="32", writer=1, class=eae79794-1af7-4f96-8401-4096cd1d8908, fields: 4
//[#0, True {System.Boolean} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
//[#1, 7945 {System.Int32} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
//[#2, 5246 {System.Int32} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
//[#3, 9/30/2019 11:19:14 AM {System.DateTime} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
//
//Dataset data: Good; Data; publisher="32", writer=3, class=96976b7b-0db7-46c3-a715-0979884b55ae, fields: 100
//[#0, 45 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
//[#1, 145 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
//[#2, 245 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
//[#3, 345 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
//[#4, 445 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
//[#5, 545 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
//[#6, 645 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
//[#7, 745 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
//[#8, 845 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
//[#9, 945 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
//[#10, 1045 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
//...
Rem This example shows how to subscribe to all dataset messages on an OPC-UA PubSub connection, and pull events, and display
Rem the incoming datasets.
Rem
Rem In order to produce network messages for this example, run the UADemoPublisher tool. For documentation, see
Rem http://kb.opclabs.com/UADemoPublisher_Basics . In some cases, you may have to specify the interface name to be used.

Option Explicit

' Define the PubSub connection we will work with.
Dim SubscribeDataSetArguments: Set SubscribeDataSetArguments = CreateObject("OpcLabs.EasyOpc.UA.PubSub.OperationModel.EasyUASubscribeDataSetArguments")
Dim ConnectionDescriptor: Set ConnectionDescriptor = SubscribeDataSetArguments.DataSetSubscriptionDescriptor.ConnectionDescriptor
ConnectionDescriptor.ResourceAddress.ResourceDescriptor.UrlString = "opc.udp://239.0.0.1"
' In some cases you may have to set the interface (network adapter) name that needs to be used, similarly to
' the statement below. Your actual interface name may differ, of course.
' ConnectionDescriptor.ResourceAddress.InterfaceName = "Ethernet"

' Instantiate the subscriber object.
Dim Subscriber: Set Subscriber = CreateObject("OpcLabs.EasyOpc.UA.PubSub.EasyUASubscriber")
' In order to use event pull, you must set a non-zero queue capacity upfront. 
Subscriber.PullDataSetMessageQueueCapacity = 1000

WScript.Echo "Subscribing..."
Subscriber.SubscribeDataSet SubscribeDataSetArguments

WScript.Echo "Processing dataset message events for 20 seconds..."
Dim endTime: endTime = Now() + 20*(1/24/60/60)
Do
    Dim EventArgs: Set EventArgs = Subscriber.PullDataSetMessage(2*1000)
    If Not (EventArgs Is Nothing) Then
        ' Display the dataset.
        If EventArgs.Succeeded Then
            ' An event with null DataSetData just indicates a successful connection.
            If Not (EventArgs.DataSetData Is Nothing) Then
                WScript.Echo
                WScript.Echo "Dataset data: " & EventArgs.DataSetData
                Dim Pair: For Each Pair in EventArgs.DataSetData.FieldDataDictionary
                    WScript.Echo Pair
                Next
            End If
        Else
            WScript.Echo
            WScript.Echo "*** Failure: " & EventArgs.ErrorMessageBrief
        End If
    End If    
Loop While Now() < endTime

WScript.Echo "Unsubscribing..."
Subscriber.UnsubscribeAllDataSets

WScript.Echo "Waiting for 1 second..."
' Unsubscribe operation is asynchronous, messages may still come for a short while.
WScript.Sleep 1*1000

WScript.Echo "Finished."



' Example output:
'
'Subscribing...
'Processing dataset message events for 20 seconds...
'
''Dataset data: Good; Data; publisher="32", writer=1, class=eae79794-1af7-4f96-8401-4096cd1d8908, fields: 4
'[#0, True {System.Boolean} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#1, 7945 {System.Int32} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#2, 5246 {System.Int32} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#3, 9/30/2019 11:19:14 AM {System.DateTime} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'
'Dataset data: Good; Data; publisher="32", writer=3, class=96976b7b-0db7-46c3-a715-0979884b55ae, fields: 100
'[#0, 45 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#1, 145 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#2, 245 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#3, 345 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#4, 445 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#5, 545 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#6, 645 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#7, 745 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#8, 845 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#9, 945 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#10, 1045 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'...

Rem This example shows how to subscribe to all dataset messages on an OPC-UA PubSub connection, and pull events, and display
Rem the incoming datasets.
Rem
Rem In order to produce network messages for this example, run the UADemoPublisher tool. For documentation, see
Rem http://kb.opclabs.com/UADemoPublisher_Basics . In some cases, you may have to specify the interface name to be used.

Private Sub EasyUASubscriber_PullDataSetMessage_Main1_Command_Click()
    OutputText = ""
    
    ' Define the PubSub connection we will work with.
    Dim subscribeDataSetArguments: Set subscribeDataSetArguments = New EasyUASubscribeDataSetArguments
    Dim ConnectionDescriptor: Set ConnectionDescriptor = subscribeDataSetArguments.dataSetSubscriptionDescriptor.ConnectionDescriptor
    ConnectionDescriptor.ResourceAddress.ResourceDescriptor.UrlString = "opc.udp://239.0.0.1"
    ' In some cases you may have to set the interface (network adapter) name that needs to be used, similarly to
    ' the statement below. Your actual interface name may differ, of course.
    'ConnectionDescriptor.ResourceAddress.InterfaceName = "Ethernet"
    
    ' Instantiate the subscriber object.
    Dim Subscriber: Set Subscriber = New EasyUASubscriber
    ' In order to use event pull, you must set a non-zero queue capacity upfront.
    Subscriber.PullDataSetMessageQueueCapacity = 1000

    OutputText = OutputText & "Subscribing..." & vbCrLf
    Subscriber.SubscribeDataSet subscribeDataSetArguments

    OutputText = OutputText & "Processing dataset message events for 20 seconds..." & vbCrLf
    Dim endTime: endTime = Now() + 20 * (1 / 24 / 60 / 60)
    Do
        Dim eventArgs: Set eventArgs = Subscriber.PullDataSetMessage(2 * 1000)
        If Not (eventArgs Is Nothing) Then
            ' Display the dataset.
            If eventArgs.Succeeded Then
                ' An event with null DataSetData just indicates a successful connection.
                If Not (eventArgs.DataSetData Is Nothing) Then
                    OutputText = OutputText & vbCrLf
                    OutputText = OutputText & "Dataset data: " & eventArgs.DataSetData & vbCrLf
                    Dim Pair: For Each Pair In eventArgs.DataSetData.FieldDataDictionary
                        OutputText = OutputText & Pair & vbCrLf
                    Next
                End If
            Else
                OutputText = OutputText & vbCrLf
                OutputText = OutputText & "*** Failure: " & eventArgs.ErrorMessageBrief & vbCrLf
            End If
        End If
    Loop While Now() < endTime

    OutputText = OutputText & "Unsubscribing..." & vbCrLf
    Subscriber.UnsubscribeAllDataSets

    OutputText = OutputText & "Waiting for 1 second..." & vbCrLf
    ' Unsubscribe operation is asynchronous, messages may still come for a short while.
    Pause 1000

    Set Subscriber = Nothing

    OutputText = OutputText & "Finished." & vbCrLf
End Sub
' Example output:
'
'Subscribing...
'Processing dataset message events for 20 seconds...
'
''Dataset data: Good; Data; publisher="32", writer=1, class=eae79794-1af7-4f96-8401-4096cd1d8908, fields: 4
'[#0, True {System.Boolean} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#1, 7945 {System.Int32} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#2, 5246 {System.Int32} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#3, 9/30/2019 11:19:14 AM {System.DateTime} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'
'Dataset data: Good; Data; publisher="32", writer=3, class=96976b7b-0db7-46c3-a715-0979884b55ae, fields: 100
'[#0, 45 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#1, 145 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#2, 245 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#3, 345 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#4, 445 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#5, 545 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#6, 645 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#7, 745 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#8, 845 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#9, 945 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'[#10, 1045 {System.Int64} @0001-01-01T00:00:00.000 @@0001-01-01T00:00:00.000; Good]
'...

 

More information

Besides the usual ArgumentException (when your code passes in an improper argument), the InvalidOperationException described above (which also indicates a bug in the code), and system exceptions such OutOfMemoryException, the PullXXXX and PullMultipleXXXX methods can only throw one type of exception, and that is ProcedureCallException. The current implementation does not actually throw this exception type, but future implementations may do so, and we recommend that your code is written in such a way that is ready for that. The ProcedureCallException indicates a failure in the event delivery mechanism (and a likely loss of one or more notifications).

Make sure you always specify a queue capacity that will provide a “buffer” of sufficient length for a difference between the rate of incoming notifications, and the rate your code can consume them. Besides an indication through the event log output (currently in OPC UA only), there is no way to detect queue overflows.

 

Requirements

Target Platforms: .NET Framework: Windows 10, Windows Server 2012, Windows Server 2016; .NET Core, .NET 5: Linux, macOS, Microsoft Windows

See Also

Reference

IEasyUASubscriberEnqueuing Members
OpcLabs.EasyOpc.UA.PubSub Namespace