OPC Studio User's Guide and Reference
Examples - OPC UA PubSub - Use Packet capture file
View with Navigation Tools

.NET

// This example shows how to feed the packet capture file into the PubSub subscriber, instead of connecting to the message
// oriented middleware (receiving the messages from the network).
//
// The OpcLabs.Pcap assembly needs to be referenced in your project (or otherwise made available, together with its
// dependencies) for the capture files to work. Refer to the documentation for more information.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

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

namespace UASubscriberDocExamples.PubSub._EasyUASubscriber
{
    partial class SubscribeDataSet
    {
        public static void CaptureFile()
        {
            // Define the PubSub connection we will work with. Uses implicit conversion from a string.
            UAPubSubConnectionDescriptor pubSubConnectionDescriptor = "opc.eth://FF-FF-FF-FF-FF-FF";
            // Use packets from the specified Ethernet capture file. The file itself is at the root of the project, and we
            // have specified that it has to be copied to the project's output directory.
            // Note that .pcap is the default file name extension, and can thus be omitted.
            pubSubConnectionDescriptor.UseEthernetCaptureFile("UADemoPublisher-Ethernet.pcap");

            // Alternative setup for Ethernet with VLAN tagging:
            //UAPubSubConnectionDescriptor pubSubConnectionDescriptor = "opc.eth://FF-FF-FF-FF-FF-FF:2";
            //pubSubConnectionDescriptor.UseEthernetCaptureFile("UADemoPublisher-EthernetVlan.pcap");

            // Alternative setup for UDP over IPv4:
            //UAPubSubConnectionDescriptor pubSubConnectionDescriptor = "opc.udp://239.0.0.1";
            //pubSubConnectionDescriptor.UseUdpCaptureFile("UADemoPublisher-UDP.pcap");

            // Alternative setup for UDP over IPv6:
            //UAPubSubConnectionDescriptor pubSubConnectionDescriptor = "opc.udp://[ff02::1]";
            //pubSubConnectionDescriptor.UseUdpCaptureFile("UADemoPublisher-UDP6.pcap");

            // Instantiate the subscriber object.
            var subscriber = new EasyUASubscriber();

            // Define the arguments for subscribing to the dataset, where the filter is (unsigned 64-bit) publisher Id 31.
            var subscribeDataSetArguments = new UASubscribeDataSetArguments(
                pubSubConnectionDescriptor, UAPublisherId.CreateUInt64(31));

            Console.WriteLine("Subscribing...");
            subscriber.SubscribeDataSet(subscribeDataSetArguments, (sender, args) =>
            {
                // Display the dataset.
                if (args.Succeeded)
                {
                    // An event with null DataSetData just indicates a successful connection.
                    if (!(args.DataSetData is null))
                    {
                        Console.WriteLine();
                        Console.WriteLine($"Dataset data: {args.DataSetData}");
                        foreach (KeyValuePair<string, UADataSetFieldData> pair in args.DataSetData.FieldDataDictionary)
                            Console.WriteLine(pair);
                    }
                }
                else
                {
                    Console.WriteLine();
                    Console.WriteLine($"*** Failure: {args.ErrorMessageBrief}");
                }
            });

            Console.WriteLine("Processing dataset message events for 20 seconds...");
            Thread.Sleep(20 * 1000);

            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: 2019-10-31T16:04:59.145,266,700,00; Good; Data; publisher=(UInt64)31, writer=1, fields: 4
        //[#0, True {System.Boolean} @2019-10-31T16:04:59.145,266,700,00; Good]
        //[#1, 0 {System.Int32} @2019-10-31T16:04:59.145,266,700,00; Good]
        //[#2, 767 {System.Int32} @2019-10-31T16:04:59.145,266,700,00; Good]
        //[#3, 10/31/2019 4:04:59 PM {System.DateTime} @2019-10-31T16:04:59.145,266,700,00; Good]
        //
        //Dataset data: 2019-10-31T16:04:59.170,047,500,00; Good; Data; publisher=(UInt64)31, writer=3, fields: 100
        //[#0, 0 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
        //[#1, 100 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
        //[#2, 200 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
        //[#3, 300 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
        //[#4, 400 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
        //[#5, 500 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
        //[#6, 600 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
        //[#7, 700 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
        //[#8, 800 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
        //[#9, 900 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
        //[#10, 1000 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
        //...
    }
}

COM

// This example shows how to feed the packet capture file into the PubSub subscriber, instead of connecting to the message
// oriented middleware (receiving the messages from the network).
//
// In order to produce network messages for this example, run the UADemoPublisher tool. For documentation, see
// https://kb.opclabs.com/UADemoPublisher_Basics . In some cases, you may have to specify the interface name to be used.
//
// The OpcLabs.Pcap assembly needs to be referenced in your project (or otherwise made available, together with its
// dependencies) for the capture files to work. Refer to the documentation for more information.
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client and subscriber examples in Object Pascal (Delphi) on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-OP .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

type
  TSubscriberEventHandlers72 = class
    procedure OnDataSetMessage(
      ASender: TObject;
      sender: OleVariant;
      const eventArgs: _EasyUADataSetMessageEventArgs);
  end;

class procedure SubscribeDataSet.CaptureFile;
var
  ConnectionDescriptor: _UAPubSubConnectionDescriptor;
  SubscribeDataSetArguments: _EasyUASubscribeDataSetArguments;
  Subscriber: TEasyUASubscriber;
  SubscriberEventHandlers: TSubscriberEventHandlers72;
begin
  // Define the PubSub connection we will work with.
  SubscribeDataSetArguments := CoEasyUASubscribeDataSetArguments.Create;
  ConnectionDescriptor := SubscribeDataSetArguments.DataSetSubscriptionDescriptor.ConnectionDescriptor;
  ConnectionDescriptor.ResourceAddress.ResourceDescriptor.UrlString := 'opc.eth://FF-FF-FF-FF-FF-FF';
  // Use packets from the specified Ethernet capture file. The file itself is at the root of the project, and we
  // have specified that it has to be copied to the project's output directory.
  // Note that .pcap is the default file name extension, and can thus be omitted.
  ConnectionDescriptor.UseEthernetCaptureFile('UADemoPublisher-Ethernet.pcap');

  // Alternative setup for Ethernet with VLAN tagging:
  //ConnectionDescriptor.ResourceAddress.ResourceDescriptor.UrlString = 'opc.eth://FF-FF-FF-FF-FF-FF:2';
  //ConnectionDescriptor.UseEthernetCaptureFile('UADemoPublisher-EthernetVlan.pcap');

  // Alternative setup for UDP over IPv4:
  //ConnectionDescriptor.ResourceAddress.ResourceDescriptor.UrlString = 'opc.udp://239.0.0.1';
  //ConnectionDescriptor.UseUdpCaptureFile('UADemoPublisher-UDP.pcap');

  // Alternative setup for UDP over IPv6:
  //ConnectionDescriptor.ResourceAddress.ResourceDescriptor.UrlString = 'opc.udp://[ff02::1]';
  //ConnectionDescriptor.UseUdpCaptureFile('UADemoPublisher-UDP6.pcap');

  // Define the arguments for subscribing to the dataset, where the filter is (unsigned 64-bit) publisher Id 31.
  SubscribeDataSetArguments.DataSetSubscriptionDescriptor.Filter.PublisherId.SetIdentifier(UAPublisherIdType_UInt64, 31);

  // Instantiate the subscriber object and hook events.
  Subscriber := TEasyUASubscriber.Create(nil);
  SubscriberEventHandlers := TSubscriberEventHandlers72.Create;
  Subscriber.OnDataSetMessage := SubscriberEventHandlers.OnDataSetMessage;

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

  WriteLn('Processing dataset message for 20 seconds...');
  PumpSleep(20*1000);

  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.');
  FreeAndNil(Subscriber);
  FreeAndNil(SubscriberEventHandlers);
end;

procedure TSubscriberEventHandlers72.OnDataSetMessage(
  ASender: TObject;
  sender: OleVariant;
  const eventArgs: _EasyUADataSetMessageEventArgs);
var
  Count: Cardinal;
  DictionaryEntry2: _DictionaryEntry2;
  Element: OleVariant;
  FieldDataDictionaryEnumerator: IEnumVariant;
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);
      FieldDataDictionaryEnumerator := eventArgs.DataSetData.FieldDataDictionary.GetEnumerator;
      while (FieldDataDictionaryEnumerator.Next(1, Element, Count) = S_OK) do
      begin
        DictionaryEntry2 := IUnknown(Element) as _DictionaryEntry2;
        WriteLn(DictionaryEntry2.ToString);
      end;
    end;
  end
  else begin
    WriteLn;
      WriteLn('*** Failure: ', eventArgs.ErrorMessageBrief);
  end;
end;

// Example output:
//
//Subscribing...
//Processing dataset message events for 20 seconds...
//
//Dataset data: 2019-10-31T16:04:59.145,266,700,00; Good; Data; publisher=(UInt64)31, writer=1, fields: 4
//[#0, True {System.Boolean} @2019-10-31T16:04:59.145,266,700,00; Good]
//[#1, 0 {System.Int32} @2019-10-31T16:04:59.145,266,700,00; Good]
//[#2, 767 {System.Int32} @2019-10-31T16:04:59.145,266,700,00; Good]
//[#3, 10/31/2019 4:04:59 PM {System.DateTime} @2019-10-31T16:04:59.145,266,700,00; Good]
//
//Dataset data: 2019-10-31T16:04:59.170,047,500,00; Good; Data; publisher=(UInt64)31, writer=3, fields: 100
//[#0, 0 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
//[#1, 100 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
//[#2, 200 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
//[#3, 300 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
//[#4, 400 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
//[#5, 500 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
//[#6, 600 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
//[#7, 700 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
//[#8, 800 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
//[#9, 900 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
//[#10, 1000 {System.Int64} @2019-10-31T16:04:59.170,047,500,00; Good]
//...

Python

# This example shows how to feed the packet capture file into the PubSub subscriber, instead of connecting to the
# message oriented middleware (receiving the messages from the network).
#
# The OpcLabs.Pcap assembly needs to be referenced in your project (or otherwise made available, together with its
# dependencies) for the capture files to work. Refer to the documentation for more information.
#
# Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
# OPC client and subscriber examples in Python on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-Python .
# Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
# a commercial license in order to use Online Forums, and we reply to every post.
# The QuickOPC package is needed. Install it using "pip install opclabs_quickopc".
import opclabs_quickopc
import opclabs_pcap
import time

# Import .NET namespaces.
from System import *
from OpcLabs.EasyOpc.UA.PubSub import *
from OpcLabs.EasyOpc.UA.PubSub.Extensions import *
from OpcLabs.EasyOpc.UA.PubSub.OperationModel import *


def dataSetMessage(sender, e):
    # Display the dataset.
    if e.Succeeded:
        # An event with null DataSetData just indicates a successful connection.
        if e.DataSetData is not None:
            print('')
            print('Dataset data: ', e.DataSetData, sep='')
            for pair in e.DataSetData.FieldDataDictionary:
                print(pair)
    else:
        print('')
        print('*** Failure: ', e.ErrorMessageBrief, sep='')


# Define the PubSub connection we will work with. Uses implicit conversion from a string.
# "opc.eth" is the scheme for OPC UA Ethernet. "FF-FF-FF-FF-FF-FF" is the Ethernet broadcast address.
pubSubConnectionDescriptor = UAPubSubConnectionDescriptor.op_Implicit('opc.eth://FF-FF-FF-FF-FF-FF')
# Use packets from the specified Ethernet capture file. The file itself is at the root of the project, and we
# have specified that it has to be copied to the project's output directory.
# Note that .pcap is the default file name extension, and can thus be omitted.
UAPubSubConnectionDescriptorExtension.UseEthernetCaptureFile(pubSubConnectionDescriptor,
                                                             'UADemoPublisher-Ethernet.pcap')

# Alternative setup for Ethernet with VLAN tagging:
#pubSubConnectionDescriptor = UAPubSubConnectionDescriptor.op_Implicit('opc.eth://FF-FF-FF-FF-FF-FF:2')
#UAPubSubConnectionDescriptorExtension.UseEthernetCaptureFile(pubSubConnectionDescriptor,
#                                                             'UADemoPublisher-EthernetVlan.pcap')

# Alternative setup for UDP over IPv4:
#pubSubConnectionDescriptor = UAPubSubConnectionDescriptor.op_Implicit('opc.udp://239.0.0.1')
#UAPubSubConnectionDescriptorExtension.UseEthernetCaptureFile(pubSubConnectionDescriptor,
#                                                             'UADemoPublisher-UDP.pcap')

# Alternative setup for UDP over IPv6:
#pubSubConnectionDescriptor = UAPubSubConnectionDescriptor.op_Implicit('opc.udp://[ff02::1]')
#UAPubSubConnectionDescriptorExtension.UseEthernetCaptureFile(pubSubConnectionDescriptor,
#                                                             'UADemoPublisher-UDP6.pcap')

# Instantiate the subscriber object.
subscriber = EasyUASubscriber()

# Define the arguments for subscribing to the dataset, where the filter is (unsigned 64-bit) publisher Id 31.
subscribeDataSetArguments = UASubscribeDataSetArguments(
    pubSubConnectionDescriptor,
    UASubscribeDataSetFilter(UAPublisherId.CreateUInt64(Decimal(31))))

print('Subscribing...')
IEasyUASubscriberExtension.SubscribeDataSet(subscriber,
                                            subscribeDataSetArguments,
                                            EasyUADataSetMessageEventHandler(dataSetMessage))

print('Processing dataset message events for 20 seconds...')
time.sleep(20)

print('Unsubscribing...')
subscriber.UnsubscribeAllDataSets()

print('Waiting for 1 second...')
# Unsubscribe operation is asynchronous, messages may still come for a short while.
time.sleep(1)

print('Finished.')

 

See Also

Fundamentals

Concepts