Using OpcCmd Utility as OPC UA PubSub Subscriber: Difference between revisions

From OPC Labs Knowledge Base
 
(94 intermediate revisions by the same user not shown)
Line 1: Line 1:
[[Category:OPC UA PubSub]] [[Category:OpcCmd]] [[Category:Tools]]
[[Category:OPC UA PubSub]] [[Category:OpcCmd Utility]] [[Category:Tools and Online Services]]  
For general information about the OpcCmd tool, see [[:Category:OpcCmd Utility]].


= Introduction =
= Introduction =


The OpcCmd utility is a program that allows performing various OPC operations from the command line. It can act as a generic OPC UA PubSub subscriber, and be used for evaluation, experiments, and testing.
This version supports following transport protocol mappings:
* OPC UA UDP (UADP over UDP; IPv4 or IPv6)
* OPC UA Ethernet (UADP over Ethernet; with or without VLAN tagging)
* OPC UA MQTT (UADP or JSON over MQTT; supports [[OPC UA PubSub Automatic Message Mapping Recognition|automatic message mapping recognition]] )
OPC UA PubSub security is not supported.  


OpcCmd is a console application, running on .NET. It is available for .NET Framework (Windows only), or .NET Core (Windows or Linux). It is available free of charge, but without an appropriate QuickOPC commercial or evaluation license made available to it, it provides valid data only for 30 minutes (it needs to be started over then).
{{Note|OpcCmd also supports other OPC-related functionality, for Client-Server or PubSub, and for OPC Classic. This page, however, is only for the UA PubSub subscriber aspect of the OpcCmd tool.}}


{{Note|This page describes a preliminary version (5.55.0.3) of the program; the behavior is subject to change in future versions. This version only supports the OPC UA UDP transport protocol mapping (UADP over UDP). We plan to add more features and mappings in the future. Once released, the documentation to the OpcCmd (intended to be a superset of this page) will be found in the QuickOPC User's Guide and Reference.}}
= Commands, Arguments and Options =


{{Note|OpcCmd may be enhanced in the future to support other OPC-related functionality, for Client-Server or PubSub. This page, however, is only for the PubSub subscriber aspect of the OpcCmd tool.}}
For the usage as OPC UA PubSub subscriber, you will need one command ('''uaSubscriber''') and most commonly one sub-command ('''subscribeDataSet'''), so they will practically always be present on the command line, and you will just give them additional options as needed. For this reason, most of your commands will start with:


= Usage =
OpcCmd uaSubscriber subscribeDataSet


In order to run the OpcCmd utility, open a command prompt, and switch to the directory that contains the program. You start the program and give it a command and additional parameters (options). If you are using the .NET Framework version, type {{Style=keyboard|OpcCmd}}, followed by the commands and options, and press {{Style=shortcut|Enter}}. If you are using the .NET Core version, type {{Style=keyboard|dotnet OpcCmd.dll}}, followed by the commands and options, and press {{Style=shortcut|Enter}}. In the text that follows, when discussing the command line options, we will be listing the commands simply with the '''OpcCmd''' at the beginning; remember to use '''dotnet OpcCmd.dll''' in .NET Core instead.
{{Note|You can start the OpcCmd utility in ''interactive mode'' using <code>OpcCmd --interactive</code> or (shortened) <code>OpcCmd -i</code>. You can then experiment with various commands without having to restart the utility. OpcCmd commands can be executed directly at the {{Style=label|OpcCmd>}} prompt, or you can invoke the interactive mode for deeper levels by entering the command name without any arguments, such as <code>uaSubscriber</code>. In addition, the interactive mode gives you the ability to review and inspect the events generated by last command, and much more.}}
== Command: '''uaSubscriber subscribeDataSet''' ==


After the program starts, it displays all dataset messages received (according to the criteria given by the command-line options) and their content (data fields). In case of an error, it displays an appropriate error message.
After the command starts, it displays all dataset messages received (according to the criteria given by the command-line options) and their content (data fields). In case of an error, it displays an appropriate error message.


By default, OpcCmd stays subscribed for one minute, or until you interrupt it using the {{Style=shortcut|Ctrl+Break}} key combination. The time period can be configured using the '''--SleepTimeMilliseconds''' ('''-stm''') or '''--SleepTimeSpan''' ('''-sts''') command-line option.
By default, OpcCmd stays subscribed for one minute, or until you interrupt it using the {{Style=shortcut|X}} key. The time period can be configured using the '''!wait''' subcommand, with duration given as time span, number of milliseconds, or 'Infinite'. You can also use {{Style=shortcut|Ctrl+Break}} key combination to terminate the OpcCmd utility at any time, but without giving it a chance to perform any finalization tasks or return to the interactive mode.
 
Parameters of the '''subscribeDataSet''' command can be influenced by various arguments (positional) and options (named) given after it on the command line. The option names are case sensitive, and can be entered using the long form (starts with --) or the short form (starts with -). The options are (obtained through {{Style=keyboard|OpcCmd uaSubscriber subscribeDataSet --help}}):
<nowiki>
Usage: OpcCmd uaSubscriber|uas subscribeDataSet|sds [options] <resourceDescriptor> <brokerQueueName> [command]


= Command-line Options =
Arguments:
  resourceDescriptor                                      PubSub connection resource descriptor
  brokerQueueName                                          Broker queue name


OpcCmd has a concept of (possibly nested) ''commands'' and ''options''. For the usage as OPC UA PubSub subscriber, you will need one command ('''uaSubscriber''') and one sub-command ('''subscribeDataSet'''), so they will practically always be present on the command line, and you will just give them additional options as needed. For this reason, most of your commands will start with:
Options:
  -?|-h|--help                                            Show help information
  -!op|--!option <key-typedValue-pair>                    Execute with given program option value (*)
  -!xe|--!extractElement <index>                          Extract element at given index of the result sequence
  -!xm|--!extractMember <elementPath>                      Extract member of the result object
  -!if|--!inputFile <filePath>                            Read input from a specified file
  -!of|--!outputFile <filePath>                            Write output to a specified file
  -!ao|--!appendOutput                                    Append to the existing content of the output file
  -!to|--!teeOutput                                        Write to the output file in addition to the original output destination
  -!t2s|--!treeToSequence <treeTraversalType>              Define how to convert trees to sequences
  -!ve|--!viewEvent[:<viewValueSpecifier>]                Specify how to view events
  -!vv|--!viewValue[:<viewValueSpecifier>]                Specify to view the result as a value, and how
  -!vs|--!viewSequence[:<viewSequenceSpecifier>]          Specify to view the result as a sequence, and how
  -!vt|--!viewTree[:<viewTreeSpecifier>]                  Specify view the result as a tree, and how
  -!0e|--!clearEvents[:<bool>]                            Determines whether collected events will be clear before execution of the command
  -!ce|--!collectEvents[:<bool>]                          Determines whether events will be collected during execution of the command
  -rpeu|--ResolverPublisherEndpointUri <uri>              Resolver publisher endpoint URI
  -rpeui|--ResolverPublisherEndpointUser <userInfo>        Resolver publisher endpoint user name token - user
  -rpeun|--ResolverPublisherEndpointUserName <string>      Resolver publisher endpoint user name token - user name
  -rpeup|--ResolverPublisherEndpointUserPassword <string>  Resolver publisher endpoint user name token - password
  -rpfru|--ResolverPublisherFileResourceUri <uri>          Resolver publisher file resource URI
  -rk|--ResolverKind <uaResolverKind>                      Resolver kind
  -cni|--ConnectionNetworkInterface <name>                PubSub connection network interface
  -cn|--ConnectionName <name>                              PubSub connection name
  -cru|--ConnectionResourceUri <uri>                      PubSub connection resource URI
  -ctpn|--ConnectionTransportProfileName <uaPubsubTpn>    PubSub connection transport profile name
  -ctpu|--ConnectionTransportProfileUri <uri>              PubSub connection transport profile URI
  -cp|--ConnectionProperty <uaKey-uaValue-pair>            PubSub connection property (*)
  -uecf|--UseEthernetCaptureFile <fileName>                Use Ethernet capture file (requires OpcLabs.Pcap)
  -uucf|--UseUdpCaptureFile <fileName>                    Use UDP capture file (requires OpcLabs.Pcap)
  -cbapu|--ConnectionBrokerAuthenticationProfileUri <uri>  PubSub connection broker authentication profile URI
  -cbru|--ConnectionBrokerResourceUri <uri>                PubSub connection broker resource URI
  -cddu|--ConnectionDatagramDiscoveryUri <uri>            PubSub connection datagram discovery URI
  -mnms|--MaximumNetworkMessageSize <uint32>              Maximum network message size (ignored)
  -mrt|--MessageReceiveTimeout <double>                    Message receive timeout (milliseconds)
  -sgi|--SecurityGroupId <name>                            Security group Id
  -sksu|--SecurityKeyServiceUri <uri>                      Security key service URI (*)
  -sm|--SecurityMode <uaSecurityMode>                      Security mode
  -stms|--SksTemplateMessageSecurity <uaMsml>              SKS template message security modes
  -stu|--SksTemplateUser <userInfo>                        SKS template user name token - user
  -stun|--SksTemplateUserName <string>                    SKS template user name token - user name
  -stup|--SksTemplateUserPassword <string>                SKS template user name token - user password
  -bapu|--BrokerAuthenticationProfileUri <uri>            Broker authentication profile URI
  -bmdqn|--BrokerMetaDataQueueName <name>                  Broker metadata queue name
  -bqn|--BrokerQueueName <name>                            Broker queue name
  -brdg|--BrokerRequestedDeliveryGuarantee <uaGuarantee>  Broker requested delivery guarantee
  -bru|--BrokerResourceUri <uri>                          Broker resource URI
  -dso|--DataSetOffset <uint16>                            Dataset offset
  -gv|--GroupVersion <uint32>                              Group version
  -nmn|--NetworkMessageNumber <uint16>                    Network message number
  -dsci|--DataSetClassId <guid>                            Dataset class Id
  -adm|--AllowDataMessages <bool>                          Allow data messages (default=true)
  -aem|--AllowEventMessages <bool>                        Allow event messages (default=true)
  -dswi|--DataSetWriterId <uint16>                        Dataset writer Id
  -dswn|--DataSetWriterName <name>                        Dataset writer name
  -op|--OriginPattern <pattern>                            Pattern to match the origin
  -pi|--PublisherId <uaPublisherId>                        Publisher Id
  -rfv|--RequiredFieldValue <key-typedValue-pair>          Required field value (uses promoted fields when available) (*)
  -wgi|--WriterGroupId <uint16>                            Writer group Id
  -wgn|--WriterGroupName <name>                            Writer group name
  -pdsn|--PublishedDataSetName <name>                      Published dataset name
  -a|--Aggregates <aggregates>                            List of aggregates to be reported after the capture is completed (default:
                                                          DataSetHeaderStatistics)
  -dho|--DistinctHeadersOnly                              Only output distinct PubSub headers
  -ofbi|--OutputFieldsById                                Output dataset fields by their dataset field Id
  -i|--interactive                                        Enter subcommands in an interactive loop ("exit" to leave)


OpcCmd uaSubscriber subscribeDataSet
Commands:
  !wait                                                    Specify how long will the parent command execute (default 00:01:00)


Parameters of the '''subscribeDataSet''' command can be influenced by various options given after it on the command line. They are (obtained through {{Style=keyboard|OpcCmd uaSubscriber subscribeDataSet --help}}):
Run 'subscribeDataSet|sds [command] --help' for more information about a command.
<nowiki>
(*) Indicates options that can be specified multiple times with multiple values.
Usage: OpcCmd uaSubscriber subscribeDataSet [options]


Options:
Parameter values:
   --SleepTimeMilliseconds|-stm <milliseconds>                         Sleep time (-1 for Infinite, default=1 minute)
   <aggregate>             DataSetHeaderStatistics|DataSetWriterStatistics|OriginStatistics|PublisherStatistics
   --SleepTimeSpan|-sts <timespan>                                     Sleep timespan (e.g. hh:mm, or hh:mm:ss)
   <aggregates>            None|All|<aggregate>[,<aggregate>]...
  --ResolverPublisherEndpointUri|-rpeu <uri>                           Resolver publisher endpoint URI
   <clarkNotation>         [{<url>}]<name>
   --ResolverPublisherFileResourceUri|-rpfru <uri>                     Resolver publisher file resource URI
   <format>                 <string>
  --ResolverKind|-rk <None/Discovery/PublisherEndpoint/PublisherFile> Resolver kind [DISCOVERY NOT IMPLEMENTED]
   <key-typedValue-pair>    <name>=<typedValue>
  --ConnectionNetworkInterface|-cni <name>                             PubSub connection network interface
   <pattern>               <string>
   --ConnectionName|-cn <name>                                         PubSub connection name
   <treeTraversalType>     None|DepthFirst|BreadthFirst
  --ConnectionResourceUri|-cru <uri>                                   PubSub connection resource URI
   <typeCode>               Empty|Object|DBNull|Boolean|Char|SByte|Byte|Int16|UInt16|Int32|UInt32|Int64|UInt64|Single|Double|Decimal|DateTime|String
   --ConnectionTransportProfile|-ctp <uri>                             PubSub connection transport profile
   <typedValue>             [<typeCode>]<value>
  --PcapReaderCaptureFile|-prcf <fileName>                             Pcap reader capture file (requires OpcLabs.Pcap)
   <uaBuiltInType>         Null|Boolean|SByte|Byte|Int16|UInt16|Int32|UInt32|Int64|UInt64|Float|Double|String|DateTime|Guid|ByteString|XmlElement|NodeId|ExpandedNodeId|StatusCode|QualifiedName|LocalizedText|ExtensionObject|DataValue|Variant|DiagnosticInfo|Number|Integer|UInteger|Enumeration
   --ConnectionBrokerAuthenticationProfileUri|-cbapu <uri>             PubSub connection broker authentication profile URI
   <uaGuarantee>           NotSpecified|BestEffort|AtLeastOnce|AtMostOnce|ExactlyOnce
  --ConnectionBrokerResourceUri|-cbru <uri>                           PubSub connection broker resource URI
   <uaKey-uaValue-pair>    <clarkNotation>=<uaValue>
   --ConnectionDatagramDiscoveryUri|-cddu <uri>                         PubSub connection datagram discovery URI
   <uaPublisherId>          [<uaPublisherIdType>]<value>
   --MaximumNetworkMessageSize|-mnms <uint32>                           Maximum network message size (ignored)
   <uaPublisherIdType>     |Byte|UInt16|UInt32|UInt64|String
   --MessageReceiveTimeout|-mrt <double>                               Message receive timeout (milliseconds)
   <uaPubsubTpn>           AmqpJson|AmqpUadp|EthUadp|MqttAutoOrJson|MqttAutoOrUadp|MqttJson|MqttUadp|UdpUadp
  --SecurityGroupId|-sgi <name>                                       Security group Id
   <uaResolverKind>         None|PubSubDiscovery|PublisherEndpoint|PublisherFile [DISCOVERY NOT IMPLEMENTED]
  --SecurityKeyServiceEndpointUris|-skseu <uris>                       Security key service endpoint URIs
   <uaSecurityMode>         None|SecurityNone|SecuritySign|SecuritySignAndEncrypt|Secure|All
   --SecurityMode|-sm <securityMode>                                   Security mode (None/SecurityNone/SecuritySign/SecuritySignAndEncrypt)
   <uaValue>                [<uaBuiltInType>]<value>
  --BrokerAuthenticationProfileUri|-bapu <uri>                        Broker authentication profile URI
   <userInfo>              <string>[:<string>]
  --BrokerMetaDataQueueName|-bmdqn <name>                              Broker metadata queue name
   <viewSequenceSpecifier>  [<viewSequenceType>][:<format>]
  --BrokerQueueName|-bqn <name>                                        Broker queue name
   <viewSequenceType>       Default|None|Simple|Table|Browse
   --BrokerRequestedDeliveryGuarantee|-brdg <guarantee>                 Broker requested delivery guarantee (NotSpecified/BestEffort/AtLeastOnce/AtMostOnce/ExactlyOnce)
   <viewTreeSpecifier>     [<viewTreeType>][:<format>]
   --BrokerResourceUri|-bru <uri>                                       Broker resource URI
   <viewTreeType>           Default|None|Simple|Table
   --DataSetOffset|-dso <uint16>                                       Dataset offset
   <viewValueSpecifier>     [<viewValueType>][:<format>]
   --GroupVersion|-gv <uint32>                                         Group version
   <viewValueType>         Default|None|Simple|Properties|Table|Write|Dump|Save</nowiki>
   --NetworkMessageNumber|-nmn <uint16>                                 Network message number
   --DataSetClassId|-dsci <guid>                                       Dataset class Id
   --AllowDataMessages|-adm <bool>                                     Allow data messages (default=true)
   --AllowEventMessages|-aem <bool>                                     Allow event messages (default=true)
   --DataSetWriterId|-dswi <uint16>                                     Dataset writer Id
   --DataSetWriterName|-dswn <name>                                     Dataset writer name
  --PublisherIdNumeric8|-pin8 <byte>                                   Publisher Id (Byte)
   --PublisherIdNumeric16|-pin16 <uint16>                               Publisher Id (UInt16)
   --PublisherIdNumeric32|-pin32 <uint32>                               Publisher Id (UInt32)
  --PublisherIdNumeric64|-pin64 <uint64>                               Publisher Id (UInt64)
  --PublisherIdString|-pis <string>                                   Publisher Id (String)
   --WriterGroupId|-wgi <uint16>                                       Writer group Id
   --WriterGroupName|-wgn <name>                                       Writer group name
  --MessageOriginFilter|-mof <string>                                 Message origin filter (ipaddress:port for UDP)
   --PublishedDataSetName|-pdsn <name>                                 Published dataset name
  -?|-h|--help                                                        Show help information</nowiki>


Help text for the '''OpcCmd''' utility itself can by displayed using {{Style=keyboard|OpcCmd --help}}. Help text for the '''OpcCmd uaSubscriber''' command can be displayed using {{Style=keyboard|OpcCmd uaSubscriber --help}} (there are some less-frequently options directly on this command, such as resolution timeouts, which are not discussed here).
Help text for the '''OpcCmd''' utility itself can by displayed using {{Style=keyboard|OpcCmd --help}}. Help text for the '''OpcCmd uaSubscriber''' command can be displayed using {{Style=keyboard|OpcCmd uaSubscriber --help}} (there are some less-frequently options directly on this command, such as resolution timeouts, which are not discussed here).


Explanation of all the options is outside the scope of this article. Use the provided examples to work with the tool, and add options to the examples when the need arises. The option generally fall into several categories:
Explanation of all the options is outside the scope of this article. Use the provided examples to work with the tool, and add options to the examples when the need arises. The options generally fall into several categories:


; Execution: The '''--SleepTimeMilliseconds''' ('''-stm''') and '''--SleepTimeSpan''' ('''-sts''') options determine how long the command runs.
; Resolver: Allow the physical parameters be determined from logical parameters by a resolution process, from a configuration file or an OPC UA server with PubSub configuration model. Options in this category start with the word '''Resolver'''.
; Resolver: Allow the physical parameters be determined from logical parameters by a resolution process, from a configuration file or an OPC UA server with PubSub configuration model. Options in this category start with the word '''Resolver'''.
; Connection: Specify how the PubSub connection is made. The main options in this category start with the word '''Connection'''.
; Connection: Specify how the PubSub connection is made. The main options in this category start with the word '''Connection'''. The --ConnectionTransportProfile (-ctp) does not have to specified if it can be inferred from the --ConnectionResourceUri (-cru; for example, '''opc.udp''' and '''opc.eth''' schemes in the --ConnectionResourceUri imply the transport profile unambiguously, and therefore you do not have to specify --ConnectionTransportProfile with them). You can use one of the pre-defined symbolic names (such as '''ip6-allnodes''') in place of the host name in --ConnectionResourceUri (-cru); see [[Enhanced Host Name Resolution]] for more information.
; Communication parameters: E.g. '''--MessageReceiveTimeout''' ('''-mrt'''), or most of the options that start with the word '''Broker'''.
; Communication parameters: E.g. '''--MessageReceiveTimeout''' ('''-mrt'''), or most of the options that start with the word '''Broker'''.
; Filter: Allows filtering of the incoming messages. Main options in this category are the options that specify the publisher ID - they start with words '''PublisherId''', such as '''--PublisherIdNumeric16''' ('''-pin16'''). Other options in this category include '''--WriterGroupId''' ('''-wgi''') and '''--DataSetWriterId''' ('''-dswi''').
; Filter: Allows filtering of the incoming messages. Main option in this category, '''--PublisherId''' ('''-pi'''), allows you to specify the publisher ID (e.g. <code>-pi [UInt64]31</code>). Other options in this category include '''--WriterGroupId''' ('''-wgi''') and '''--DataSetWriterId''' ('''-dswi''').
 
== Command: '''uaSubscriber subscribeDataSetField''' ==
 
The '''subscribeDataSetField''' command is almost identical to the '''subscribeDataSet''' command. The only difference is that it does not display the whole dataset contents, but extracts a single given dataset field, and displays its data only.
 
The name of the field is given using an additional command-line option, '''--FieldName''' ('''-fn'''), followed by the field name. If there is a metadata available, this has to be the field name as it appears in the metadata. In absence of the metadata, you can use the field index instead - an integer (starting from 0), and preceded by'#', e.g. #2 for the 3rd field in the dataset.
 
If a dataset message is received but the specified field is not present in the dataset, the tool will display a corresponding error message.
 
== Physical and Logical Parameters ==
 
The PubSub subscription can be specified using ''physical parameters'', ''logical parameters'', or a mix of them.
 
''Physical parameters'' refer to data that is directly used to open the PubSub connection, and that appears "on the wire", in the PubSub messages. They include (only the most important parameters are listed; the list is not complete):
 
* '''--ConnectionNetworkInterface''' ('''-cni''')
* '''--ConnectionResourceUri''' ('''-cru'''). This is the main parameter that always has to be specified. The scheme part is mandatory, always start the URI with "opc.udp://" in this version. Default port for OPC UA UDP is 4840 and does not have to be specified.
* '''--ConnectionTransportProfile''' ('''-ctp'''). You do not need to specify it, if it can be derived from the scheme, such as in "opc.udp:".
* '''--MessageReceiveTimeout''' ('''-mrt''')
* '''--DataSetOffset''' ('''-dso''')
* '''--GroupVersion''' ('''-gv''')
* '''--NetworkMessageNumber''' ('''-nmn''')
* '''--DataSetClassId''' ('''-dsci''')
* '''--DataSetWriterId''' ('''-dswi''')
* various '''PublisherId''XXXX''''' ('''-pi''XX''''') options
* '''--WriterGroupId''' ('''-wgi''')
 
''Logical parameters'' refer to named objects in the PubSub configuration. They are:
 
* '''--ConnectionName''' ('''-cn''')
* '''--DataSetWriterName''' ('''-dswn''')
* '''--WriterGroupName''' ('''-wgn''')
* '''--PublishedDataSetName''' ('''-pdsn''')
 
When using logical parameters, you typically specify the first three (connection, dataset writer and writer group names), or the last one (published data set name). When published data set name is specified, OpcCmd finds the instances in the PubSub configuration where the dataset is published; the outcome must be unambiguous, otherwise an error occurs. Other logical parameters, and some physical parameters (such as transport profile URI) can be used to narrow down the outcome of this selection process.
 
The PubSub configuration information must somehow be available to OpcCmd, and a so-called ''resolver'' is used to transform the logical parameters to physical ones. There are currently two kinds of resolvers: One takes the PubSub configuration from a file (in a format given by OPC UA specification), the other works with a live PubSub configuration in an information model of a live OPC server that supports it (and is typically part of, of connected with or related to, the actual OPC UA PubSub publisher).
 
Following parameters are used to specify the resolver and its parameters:
 
* '''--ResolverPublisherEndpointUri''' ('''-rpeu'''). Use this option to resolve the logical parameters from an OPC UA server with PubSub configuration model.
* '''--ResolverPublisherFileResourceUri''' ('''-rpfru'''). Use this option to resolve the logical parameters from a PubSub configuration file.
* '''--ResolverKind''' ('''-rk'''). Not necessary unless you want to specify multiple resolvers, and then just switch between them.
 
The information you specify using the parameters must be valid for the subscription to work, but in some cases it does not have to be complete. For example, when using physical or logical parameters, you do not have to specify anything beyond the connection - the OpcCmd will then simply process all messages on that connection, without filtering. Or, you can filter just by publisher ID, but still receive different datasets provided by the given publisher.
 
== Aggregates ==
The '''subscribeDataSet''' command can calculate aggregated information out of the notifications received, and display it at the end of command execution. By default, it displays a statistics of dataset headers (count of each distinct header received, and the rate at which it was received). You can use the '''--Aggregates''' ('''-a''') option to choose the aggregate (or aggregates) that will be calculated and displayed. Available aggregates are currently '''DataSetHeaderStatistics''', '''DataSetWriterStatistics''', '''OriginStatistics''', and '''PublisherStatistics'''.


= Examples =
= Examples =


(TBD)
Following examples show some typical OpcCmd use cases (obtained through {{Style=keyboard|OpcCmd uaSubscriber subscribeDataSet --help}}):
 
  <nowiki>
  <nowiki>
Usage examples:
Usage examples:


Subscribe to a dataset, specifying physical parameters:
Subscribe to an OPC UA PubSub dataset, specifying physical parameters:
OpcCmd uaSubscriber subscribeDataSet -cru opc.udp://239.0.0.1:4840
  uaSubscriber subscribeDataSet opc.udp://239.0.0.1:4840
OpcCmd uaSubscriber subscribeDataSet -cru opc.udp://224.0.0.22 -dswi 62541
  uaSubscriber subscribeDataSet opc.udp://224.0.0.22 -dswi 62541
OpcCmd uaSubscriber subscribeDataSet -sts 01:00 -cru opc.udp://239.0.0.1:4840
  uaSubscriber subscribeDataSet -cru opc.udp://239.0.0.1:4840 !wait 01:00
OpcCmd uaSubscriber subscribeDataSet -cru opc.udp://239.0.0.1:4840 -pin 20
  uaSubscriber subscribeDataSet opc.udp://239.0.0.1:4840 -pi [UInt16]30
  uaSubscriber subscribeDataSet opc.udp://239.0.0.1:4840 --OriginPattern 192.168.*
  uaSubscriber subscribeDataSet opc.eth://FF-FF-FF-FF-FF-FF -pi [UInt16]30
  uaSubscriber subscribeDataSet mqtt://opcua-pubsub.demo-this.com opcuademo/uadp/none
  uaSubscriber subscribeDataSet mqtt://opcua-pubsub.demo-this.com opcuademo/uadp/none -dswi 4 -!op View=[ViewOptions]Cls
  uaSubscriber subscribeDataSet mqtt://opcua-pubsub.demo-this.com opcuademo/json -ctpn MqttJson
  uaSubscriber subscribeDataSet mqtt://opcua-pubsub.demo-this.com #
  uaSubscriber subscribeDataSet mqtt://opcua-pubsub.demo-this.com # --DistinctHeadersOnly !wait Infinite
  uaSubscriber subscribeDataSet mqtt://opcua-pubsub.demo-this.com # -a OriginStatistics,DataSetHeaderStatistics
Subscribe to an OPC UA PubSub dataset, specifying logical parameters (and resolving them first):
  uaSubscriber subscribeDataSet -rpfru http://opcua.demo-this.com/UADemoPublisher/UADemoPublisher-PublicDemo.uabinary -pdsn Simple
  uaSubscriber subscribeDataSet -rpeu opc.tcp://192.168.0.85:4840 -cn UDP1 -wgn WriterGroupStatic -dswn WriterSimple
  uaSubscriber subscribeDataSet -rpeu opc.tcp://192.168.0.50:4842 -pdsn "PublishedDataSet #1"
  uaSubscriber subscribeDataSet -rpfru unified_automation_cpp.bin -cn UDP1 -wgn WriterGroupDynamic -dswn WriterAllTypes</nowiki>
 
More examples:


Subscribe to a dataset, specifying logical parameters (and resolving them first):
Subscribe to all messages generated by a default configuration of the '''UADemoPublisher''' utility (see [[UADemoPublisher Basics]] for more information):
OpcCmd uaSubscriber subscribeDataSet -rpeu opc.tcp://192.168.0.85:4840 -cn UDP1 -wgn WriterGroupStatic -dswn WriterSimple
OpcCmd uaSubscriber subscribeDataSet -rpeu opc.tcp://192.168.0.50:4842 -pdsn "PublishedDataSet #1"
OpcCmd uaSubscriber subscribeDataSet -rfru unified_automation_cpp.bin -cn UDP1 -wgn WriterGroupDynamic -dswn WriterAllTypes</nowiki>


(TBD)
OpcCmd uaSubscriber subscribeDataSet -cru opc.udp://239.0.0.1
 
Subscribe to all messages on an IPv6 multicast address ff02::1 (all nodes on the local network segment):
 
OpcCmd uaSubscriber subscribeDataSet -cru opc.udp://[ff02::1]
 
Subscribe to all messages on an Ethernet broadcast address (FF-FF-FF-FF-FF-FF), tagged with VID (VLAN identifier) 2:
 
OpcCmd uaSubscriber subscribeDataSet -cru opc.eth://eth-broadcast:2


For messages from a default configuration of '''UADemoPublisher''' utility, with specific publisher ID (31, in 64 bits) and dataset writer ID (4):
For messages from a default configuration of '''UADemoPublisher''' utility, with specific publisher ID (31, in 64 bits) and dataset writer ID (4):


  OpcCmd uaSubscriber subscribeDataSet -cru opc.udp://239.0.0.1 -pin64 31 -dswi 4
  OpcCmd uaSubscriber subscribeDataSet -cru opc.udp://239.0.0.1 -pi [UInt64]31 -dswi 4
 
(TBD)


= Sample Output =
= Sample Output =
Line 113: Line 238:


  <nowiki>
  <nowiki>
OPC Labs OpcCmd Utility (.NET Core) 5.55.0.3: OPC Command-line Tool (OPC-UA PubSub Subscriber).
OPC Labs OPC Command-line Tool (.NET Framework) 5.63.115.1
Copyright © 2019 CODE Consulting and Development, s.r.o., Plzen. All rights reserved.


Executing for 00:01:00 (press 'X' to stop)...
Subscribing dataset...
Subscribing dataset...
Subscription handle: 12586001
Dataset handle: 13000001
Sleeping for 00:01:00 (press Ctrl+Break to abort)...


DataSetMessage: Success
IEasyUASubscriber.DataSetMessage: Success


DataSetMessage: Success; 0001-01-01T00:00:00.000,000,000,00; Good; Data; publisher="32", writer=1, class=eae79794-1af7-4f96-8401-4096cd1d8908, fields: 4
IEasyUASubscriber.DataSetMessage: *** Failure {59D1C1E4}\1: The OPC UA PubSub discoverer has no DataSetMetaData information for the dataset. PubSub connection name: 'PubSubConnection1', publisher Id: 30. [...]
[#0, True {System.Boolean} @0001-01-01T00:00:00.000,000,000,00; Good]
[#1, 229 {System.Int32} @0001-01-01T00:00:00.000,000,000,00; Good]
[#2, 1109 {System.Int32} @0001-01-01T00:00:00.000,000,000,00; Good]
[#3, 7/17/2019 3:29:54 PM {System.DateTime} @0001-01-01T00:00:00.000,000,000,00; Good]


DataSetMessage: Success; 0001-01-01T00:00:00.000,000,000,00; Good; Data; publisher="32", writer=3, class=96976b7b-0db7-46c3-a715-0979884b55ae, fields: 100
IEasyUASubscriber.DataSetMessage: Success; Good; Data; publisher=[String]32, writer=1, class=eae79794-1af7-4f96-8401-4096cd1d8908, origin=192.168.1.69:4840, fields: 4
[#0, 29 {System.Int64} @0001-01-01T00:00:00.000,000,000,00; Good]
Field data (sequence): 4 element(s)                                                                                               
[#1, 129 {System.Int64} @0001-01-01T00:00:00.000,000,000,00; Good]
╒══╤════════════════════╤═════════╤═══════════════╤═══════════════╤══════╕                                                         
[#2, 229 {System.Int64} @0001-01-01T00:00:00.000,000,000,00; Good]
[]│Value              │Value    │Source        │Server        │Status│                                                         
[#3, 329 {System.Int64} @0001-01-01T00:00:00.000,000,000,00; Good]
│  │                    │Type Name│Timestamp Local│Timestamp Local│Code  │                                                         
[#4, 429 {System.Int64} @0001-01-01T00:00:00.000,000,000,00; Good]
╞══╪════════════════════╪═════════╪═══════════════╪═══════════════╪══════╡                                                         
[#5, 529 {System.Int64} @0001-01-01T00:00:00.000,000,000,00; Good]
#0│True                │Boolean  │              │              │Good  │                                                         
[#6, 629 {System.Int64} @0001-01-01T00:00:00.000,000,000,00; Good]
#1│19                  │Int32    │              │              │Good  │                                                         
[#7, 729 {System.Int64} @0001-01-01T00:00:00.000,000,000,00; Good]
#2│1371                │Int32    │              │              │Good  │                                                         
[#8, 829 {System.Int64} @0001-01-01T00:00:00.000,000,000,00; Good]
#3│3/23/2022 8:19:46 AM│DateTime │              │              │Good  │                                                         
[#9, 929 {System.Int64} @0001-01-01T00:00:00.000,000,000,00; Good]
╘══╧════════════════════╧═════════╧═══════════════╧═══════════════╧══════╛                                                         
[#10, 1029 {System.Int64} @0001-01-01T00:00:00.000,000,000,00; Good]
[#11, 1129 {System.Int64} @0001-01-01T00:00:00.000,000,000,00; Good]
[#12, 1229 {System.Int64} @0001-01-01T00:00:00.000,000,000,00; Good]
...
 
DataSetMessage: Success; 0001-01-01T00:00:00.000,000,000,00; Good; Data; publisher="32", writer=4, class=cc7cb5f4-4272-45c2-9a4d-f85a8b331f6a, fields: 16
[#0, True {System.Boolean} @0001-01-01T00:00:00.000,000,000,00; Good]
[#1, 230 {System.Byte} @0001-01-01T00:00:00.000,000,000,00; Good]
[#2, 230 {System.Int16} @0001-01-01T00:00:00.000,000,000,00; Good]
[#3, 230 {System.Int32} @0001-01-01T00:00:00.000,000,000,00; Good]
[#4, 230 {System.Int64} @0001-01-01T00:00:00.000,000,000,00; Good]
[#5, 102 {System.Int16} @0001-01-01T00:00:00.000,000,000,00; Good]
[#6, 230 {System.Int32} @0001-01-01T00:00:00.000,000,000,00; Good]
[#7, 230 {System.Int64} @0001-01-01T00:00:00.000,000,000,00; Good]
[#8, 230 {System.Decimal} @0001-01-01T00:00:00.000,000,000,00; Good]
[#9, 230 {System.Single} @0001-01-01T00:00:00.000,000,000,00; Good]
[#10, 230 {System.Double} @0001-01-01T00:00:00.000,000,000,00; Good]
[#11, Whiskey {System.String} @0001-01-01T00:00:00.000,000,000,00; Good]
[#12, [20] {169, 225, 194, 251, 149, ...} {System.Byte[]} @0001-01-01T00:00:00.000,000,000,00; Good]
[#13, d34c50d3-a8e0-4861-b1e7-1868ab97756d {System.Guid} @0001-01-01T00:00:00.000,000,000,00; Good]
[#14, 7/17/2019 3:29:55 PM {System.DateTime} @0001-01-01T00:00:00.000,000,000,00; Good]
[#15, [10] {230, 231, 232, 233, 234, ...} {System.Int64[]} @0001-01-01T00:00:00.000,000,000,00; Good]


IEasyUASubscriber.DataSetMessage: Success; Good; Data; publisher=[String]32, writer=3, class=96976b7b-0db7-46c3-a715-0979884b55ae, origin=192.168.1.69:4840, fields: 100
Field data (sequence): 100 element(s)                                                                                             
╒═══╤═════╤═════════╤═══════════════╤═══════════════╤══════╕                                                                       
│[] │Value│Value    │Source        │Server        │Status│                                                                       
│  │    │Type Name│Timestamp Local│Timestamp Local│Code  │                                                                       
╞═══╪═════╪═════════╪═══════════════╪═══════════════╪══════╡                                                                       
│#0 │19  │Int64    │              │              │Good  │                                                                       
│#1 │119  │Int64    │              │              │Good  │                                                                       
│#2 │219  │Int64    │              │              │Good  │                                                                       
│#3 │319  │Int64    │              │              │Good  │                                                                       
│#4 │419  │Int64    │              │              │Good  │                                                                       
│#5 │519  │Int64    │              │              │Good  │                                                                       
│#6 │619  │Int64    │              │              │Good  │                                                                       
│#7 │719  │Int64    │              │              │Good  │                                                                       
│#8 │819  │Int64    │              │              │Good  │                                                                       
│#9 │919  │Int64    │              │              │Good  │                                                                       
│#10│1019 │Int64    │              │              │Good  │                                                                       
│#11│1119 │Int64    │              │              │Good  │                                                                       
│#12│1219 │Int64    │              │              │Good  │                                                                       
...
...
╘═══╧═════╧═════════╧═══════════════╧═══════════════╧══════╛                                                                       


DataSetMessage: *** Failure -1 (0xFFFFFFFF): The toolkit UADP NetworkMessage processor does not have DataSetMetaData available (publisher ID: 30, writer group ID: 101).
IEasyUASubscriber.DataSetMessage: Success; Good; Data; publisher=[String]32, writer=4, class=cc7cb5f4-4272-45c2-9a4d-f85a8b331f6a, origin=192.168.1.69:4840, fields: 16
Field data (sequence): 16 element(s)                                                                                               
╒═══╤════════════════════════════════════╤═════════╤═══════════════╤═══════════════╤══════╕                                       
│[] │Value                              │Value    │Source        │Server        │Status│                                       
│  │                                    │Type Name│Timestamp Local│Timestamp Local│Code  │                                       
╞═══╪════════════════════════════════════╪═════════╪═══════════════╪═══════════════╪══════╡                                       
│#0 │False                              │Boolean  │              │              │Good  │                                       
│#1 │19                                  │Byte    │              │              │Good  │                                       
│#2 │19                                  │Int16    │              │              │Good  │                                       
│#3 │19                                  │Int32    │              │              │Good  │                                       
│#4 │19                                  │Int64    │              │              │Good  │                                       
│#5 │19                                  │Int16    │              │              │Good  │                                       
│#6 │19                                  │Int32    │              │              │Good  │                                       
│#7 │19                                  │Int64    │              │              │Good  │                                       
│#8 │19                                  │Decimal  │              │              │Good  │                                       
│#9 │19                                  │Single  │              │              │Good  │                                       
│#10│19                                  │Double  │              │              │Good  │                                       
│#11│Tango                              │String  │              │              │Good  │                                       
│#12│20 element(s)                      │Byte[]  │              │              │Good  │                                       
│#13│47fa030c-48d6-427b-b87b-ef8dfb661b63│Guid    │              │              │Good  │                                       
│#14│3/23/2022 8:19:46 AM                │DateTime │              │              │Good  │                                       
│#15│10 element(s)                       │Int64[]  │              │              │Good  │                                       
╘═══╧════════════════════════════════════╧═════════╧═══════════════╧═══════════════╧══════╛                                       


...
...


DataSetMessage: Success; 2019-07-17T15:29:55.329,733,500,00; Good; Event; publisher=(UInt64)31, writer=51, fields: 4
IEasyUASubscriber.DataSetMessage: Success; 2022-03-23 08:19:49.407,711,500,00; Good; Event; publisher=[UInt64]31, writer=51, origin=192.168.1.69:4840, fields: 4
[#0, True {System.Boolean} @2019-07-17T15:29:55.329,733,500,00; Good]
Field data (sequence): 4 element(s)                                                                                               
[#1, 230 {System.Int32} @2019-07-17T15:29:55.329,733,500,00; Good]
╒══╤════════════════════╤═════════╤═══════════════════════╤═══════════════╤══════╕                                                 
[#2, 1219 {System.Int32} @2019-07-17T15:29:55.329,733,500,00; Good]
[]│Value              │Value    │Source                │Server        │Status│                                                 
[#3, 7/17/2019 3:29:55 PM {System.DateTime} @2019-07-17T15:29:55.329,733,500,00; Good]
│  │                    │Type Name│Timestamp Local        │Timestamp Local│Code  │                                                 
╞══╪════════════════════╪═════════╪═══════════════════════╪═══════════════╪══════╡                                                 
#0│False              │Boolean  │2022-03-23T09:19:49.407│              │Good  │                                                 
#1│22                  │Int32    │2022-03-23T09:19:49.407│              │Good  │                                                 
#2│7358                │Int32    │2022-03-23T09:19:49.407│              │Good  │                                                 
#3│3/23/2022 8:19:49 AM│DateTime │2022-03-23T09:19:49.407│              │Good  │                                                 
╘══╧════════════════════╧═════════╧═══════════════════════╧═══════════════╧══════╛                                                 


DataSetMessage: Success; 2019-07-17T15:29:57.333,255,400,00; Good; Event; publisher=(UInt64)31, writer=51, fields: 4
IEasyUASubscriber.DataSetMessage: Success; 2022-03-23 08:19:50.427,087,200,00; Good; Event; publisher=[UInt64]31, writer=51, origin=192.168.1.69:4840, fields: 4
[#0, False {System.Boolean} @2019-07-17T15:29:57.333,255,400,00; Good]
Field data (sequence): 4 element(s)                                                                                               
[#1, 232 {System.Int32} @2019-07-17T15:29:57.333,255,400,00; Good]
╒══╤════════════════════╤═════════╤═══════════════════════╤═══════════════╤══════╕                                                 
[#2, 1571 {System.Int32} @2019-07-17T15:29:57.333,255,400,00; Good]
[]│Value              │Value    │Source                │Server        │Status│                                                 
[#3, 7/17/2019 3:29:57 PM {System.DateTime} @2019-07-17T15:29:57.333,255,400,00; Good]
│  │                    │Type Name│Timestamp Local        │Timestamp Local│Code  │                                                 
╞══╪════════════════════╪═════════╪═══════════════════════╪═══════════════╪══════╡                                                 
#0│False              │Boolean  │2022-03-23T09:19:50.427│              │Good  │                                                 
#1│23                  │Int32    │2022-03-23T09:19:50.427│              │Good  │                                                 
#2│9296                │Int32    │2022-03-23T09:19:50.427│              │Good  │                                                 
#3│3/23/2022 8:19:50 AM│DateTime │2022-03-23T09:19:50.427│              │Good  │                                                 
╘══╧════════════════════╧═════════╧═══════════════════════╧═══════════════╧══════╛                                                 


...
...


Unsubscribing dataset (subscription handle 12586001)...
Unsubscribing dataset (dataset handle 13000001)...
Finished.</nowiki>
Dataset header counts (sequence): 7 element(s)                                                                                     
╒════════════════════════════════════════════════════════════════════════════════════════════════════╤═════╕                       
│[]                                                                                                  │Value│                       
╞════════════════════════════════════════════════════════════════════════════════════════════════════╪═════╡                       
│publisher=[UInt64]31, writer=1, origin=192.168.1.69:4840                                            │6    │                       
│publisher=[UInt64]31, writer=3, origin=192.168.1.69:4840                                            │4    │                       
│publisher=[UInt64]31, writer=4, origin=192.168.1.69:4840                                            │6    │                       
│publisher=[UInt64]31, writer=51, origin=192.168.1.69:4840                                          │38  │                       
│publisher=[String]32, writer=1, class=eae79794-1af7-4f96-8401-4096cd1d8908, origin=192.168.1.69:4840│117  │                       
│publisher=[String]32, writer=3, class=96976b7b-0db7-46c3-a715-0979884b55ae, origin=192.168.1.69:4840│117  │                       
│publisher=[String]32, writer=4, class=cc7cb5f4-4272-45c2-9a4d-f85a8b331f6a, origin=192.168.1.69:4840│117  │                       
╘════════════════════════════════════════════════════════════════════════════════════════════════════╧═════╛                       
Command finished: subscribeDataSet|sds (61.6 seconds).
OpcCmd terminating with exit code 0.</nowiki>


Explanation to some of the output follows.
Explanation to some of the output follows.


  DataSetMessage: Success
  IEasyUASubscriber.DataSetMessage: Success


This line indicates that a PubSub connection has been successfully established (there is no direct connection to the publisher - but, depending on the protocol, an IP socket need to be open, or similar "initiating" operation needs to be made, and the message indicates that the parameters used to specify the connections were OK in principle). If the connection could not have been established, there would be an error message instead.
This line indicates that a PubSub connection has been successfully established (there is no direct connection to the publisher - but, depending on the protocol, an IP socket needs to be open, or similar "initiating" operation needs to be made, and the message indicates that the parameters used to specify the connections were OK in principle). If the connection could not have been established, there would be an error message instead.


  DataSetMessage: Success; 0001-01-01T00:00:00.000,000,000,00; Good; Data; publisher="32", writer=1, class=eae79794-1af7-4f96-8401-4096cd1d8908, fields: 4
  IEasyUASubscriber.DataSetMessage: Success; Good; Data; publisher=[String]32, writer=1, class=eae79794-1af7-4f96-8401-4096cd1d8908, origin=192.168.1.69:4840, fields: 4


Similar lines precede each dataset message received. They contain the timestamp of the message, the status code, an indication whether the message contains Data or Event, and an identification of the dataset (depending on what is actually available).
Similar lines precede each dataset message received. They contain the timestamp of the message, the status code, an indication whether the message contains Data or Event, and an identification of the dataset (depending on what is actually available).


  [#0, True {System.Boolean} @0001-01-01T00:00:00.000,000,000,00; Good]
  ╒══╤════════════════════╤═════════╤═══════════════╤═══════════════╤══════╕                                                         
[]│Value              │Value    │Source        │Server        │Status│                                                         
│  │                    │Type Name│Timestamp Local│Timestamp Local│Code  │                                                         
╞══╪════════════════════╪═════════╪═══════════════╪═══════════════╪══════╡                                                         
#0│True                │Boolean  │              │              │Good  │


Similar lines contain the data fields of the message. '#' followed by a number indicates a field index. If metadata is available, there is a field name instead. Then, the actual data value is listed, followed by its type in '{ }' (this is .NET type; note that the values are converted to so-called CLS types, and therefore the .NET type may not be precisely the same as the type of the field). After that, a source timestamp preceded with '@' follows, and after a semicolon (';'), a status code.
Similar table rows contain the data fields of the message. '#' followed by a number indicates a field index. If metadata is available, there is a field name instead. Then, the actual data value is listed, followed by its type in '{ }' (this is .NET type; note that the values are converted to so-called CLS types, and therefore the .NET type may not be precisely the same as the type of the field). After that, source and server timestamps (if available), and status code, are listed. The rows with data fields are sorted alphabetically by the field name/index.


The timestamps are formatted down to 10-picosecond level.
The timestamps are formatted down to 10-picosecond level.


  DataSetMessage: *** Failure -1 (0xFFFFFFFF): The toolkit UADP NetworkMessage processor does not have DataSetMetaData available (publisher ID: 30, writer group ID: 101).
  IEasyUASubscriber.DataSetMessage: *** Failure {59D1C1E4}\1: The OPC UA PubSub discoverer has no DataSetMetaData information for the dataset. PubSub connection name: 'PubSubConnection1', publisher Id: 30. [...]
 
This message indicates that a dataset message has been received, but because the data uses raw encoding and no metadata is available, it cannot be fully parsed. Metadata can be provided from a configuration file or by an OPC UA server with PubSub configuration model. The related command-line options for that are (among others) '''--ResolverPublisherFileResourceUri''' ('''-rpfru''') and '''--ResolverPublisherEndpointUri''' ('''-rpeu'''). The UADemoPublisher comes with (and/or can generate) a .uabinary file for itself.
 
= Reading Capture Files =
 
OpcCmd can read the network traffic from a file, instead of using live data. This is extremely handy for various kinds of troubleshooting, diagnostics, analysis and similar tasks. It allows you to capture the data generated by the publisher once, and then replay it as many times as you like.
 
The network capture needs to be in the PCAP format. Various tools, including Wireshark, can read and write this format. The current versions of Wireshark, however, store network capture in a newer format (PCAPNG) by default. Using the "Save as type" drop-down in Wireshark's "Save file as" dialog, it is easy to save your network captures in the PCAP format, or even convert existing PCAPNG captures to PCAP.
 
For UDP message mapping, apply the '''--UseUdpCaptureFile''' ('''-uucf''') option, followed by the file name, to the '''subscribeDataSet''' or '''subscribeDataSetField''' command. For Ethernet message mapping, apply the '''--UseEthernetCaptureFile''' ('''-uecf''') option instead.
 
You still need to specify the connection URI as usual. The command to subscribe to a dataset from a network capture file may then look like this (the file used is one of sample files that ship with the UADemoPublisher):
 
<nowiki>
OpcCmd uaSubscriber subscribeDataSet opc.udp://239.0.0.1:4840 -uucf UADemoPublisher-UDP</nowiki>
 
The default file name extension is ".pcap".
 
When reading UDP message captures, there is a built-in IP fragment reassembler (for both IPv4 and IPv6), and thus you can work with messages whose requirements exceed the network's MTU.


This message indicates that a dataset message has been received, but because the data uses raw encoding and no metadata is available, it cannot be fully parsed. Metadata can be provided from a configuration file or by an OPC UA server with PubSub configuration model. The related command-line options for that are (among others) '''--ResolverPublisherFileResourceUri''' ('''-rpfru''') and '''--ResolverPublisherEndpointUri''' ('''-rpeu''').
The packets in the capture file are used to provide "timed" replay of the network communication. This means that when the capture is replayed, the software not only mimics the actual data in the packets, but it also attempts to maintain the same timing of the packets as it appears in the capture. An initial delay of 1000 milliseconds is added before the replay starts, in order to allow for startup tasks on the receiver side to finalize.


= Testing =
= Tips and Tricks =
; Listen on UDP port for unicast messages: You can change the local port to listen on (e.g. to 9999) using the following command option: <code>--ConnectionProperty {http://opclabs.com/OpcUA/PubSub}LocalPort=[Int32]9999</code>.
; Collect information about "who is publishing" on a connection: Specify just the connection parameters, and use the '''--DistinctHeadersOnly''' ('''-dho''') option. The command will print out every new combination of publisher Id, writer group dataset writer Id&name, dataset class Id and origin it receives. For example:
OpcCmd uaSubscriber subscribeDataSet mqtt://opcua-pubsub.demo-this.com # --DistinctHeadersOnly !wait Infinite
or
OpcCmd uaSubscriber subscribeDataSet opc.udp://239.0.0.1:4840 --DistinctHeadersOnly !wait Infinite
Only messages that can be sufficiently parsed to obtain the basic header information are considered. The command works well with the [[OPC UA PubSub Automatic Message Mapping Recognition]] feature, meaning that you do not even have to specify the message mapping (JSON or UADP). For more advanced scenarios, see [[Using OpcCmd Utility as OPC UA PubSub Sniffer]].


(TBD)
= Related reading  =
* [[OPC UA PubSub Common Traps And Pitfalls]]
* [[How to publish or subscribe to secure OPC UA PubSub messages]]
* [[MQTT communication packages]]
* [[Certificate security plugin]]
* [[Using OpcCmd Utility as OPC UA PubSub Sniffer]]

Latest revision as of 19:19, 6 November 2022

For general information about the OpcCmd tool, see Category:OpcCmd Utility.

Introduction

This version supports following transport protocol mappings:

  • OPC UA UDP (UADP over UDP; IPv4 or IPv6)
  • OPC UA Ethernet (UADP over Ethernet; with or without VLAN tagging)
  • OPC UA MQTT (UADP or JSON over MQTT; supports automatic message mapping recognition )

OPC UA PubSub security is not supported.

Note2-icon.png

Note: OpcCmd also supports other OPC-related functionality, for Client-Server or PubSub, and for OPC Classic. This page, however, is only for the UA PubSub subscriber aspect of the OpcCmd tool.

Commands, Arguments and Options

For the usage as OPC UA PubSub subscriber, you will need one command (uaSubscriber) and most commonly one sub-command (subscribeDataSet), so they will practically always be present on the command line, and you will just give them additional options as needed. For this reason, most of your commands will start with:

OpcCmd uaSubscriber subscribeDataSet
Note2-icon.png

Note: You can start the OpcCmd utility in interactive mode using OpcCmd --interactive or (shortened) OpcCmd -i. You can then experiment with various commands without having to restart the utility. OpcCmd commands can be executed directly at the OpcCmd> prompt, or you can invoke the interactive mode for deeper levels by entering the command name without any arguments, such as uaSubscriber. In addition, the interactive mode gives you the ability to review and inspect the events generated by last command, and much more.

Command: uaSubscriber subscribeDataSet

After the command starts, it displays all dataset messages received (according to the criteria given by the command-line options) and their content (data fields). In case of an error, it displays an appropriate error message.

By default, OpcCmd stays subscribed for one minute, or until you interrupt it using the X key. The time period can be configured using the !wait subcommand, with duration given as time span, number of milliseconds, or 'Infinite'. You can also use Ctrl+Break key combination to terminate the OpcCmd utility at any time, but without giving it a chance to perform any finalization tasks or return to the interactive mode.

Parameters of the subscribeDataSet command can be influenced by various arguments (positional) and options (named) given after it on the command line. The option names are case sensitive, and can be entered using the long form (starts with --) or the short form (starts with -). The options are (obtained through OpcCmd uaSubscriber subscribeDataSet --help):

Usage: OpcCmd uaSubscriber|uas subscribeDataSet|sds [options] <resourceDescriptor> <brokerQueueName> [command]

Arguments:
  resourceDescriptor                                       PubSub connection resource descriptor
  brokerQueueName                                          Broker queue name

Options:
  -?|-h|--help                                             Show help information
  -!op|--!option <key-typedValue-pair>                     Execute with given program option value (*)
  -!xe|--!extractElement <index>                           Extract element at given index of the result sequence
  -!xm|--!extractMember <elementPath>                      Extract member of the result object
  -!if|--!inputFile <filePath>                             Read input from a specified file
  -!of|--!outputFile <filePath>                            Write output to a specified file
  -!ao|--!appendOutput                                     Append to the existing content of the output file
  -!to|--!teeOutput                                        Write to the output file in addition to the original output destination
  -!t2s|--!treeToSequence <treeTraversalType>              Define how to convert trees to sequences
  -!ve|--!viewEvent[:<viewValueSpecifier>]                 Specify how to view events
  -!vv|--!viewValue[:<viewValueSpecifier>]                 Specify to view the result as a value, and how
  -!vs|--!viewSequence[:<viewSequenceSpecifier>]           Specify to view the result as a sequence, and how
  -!vt|--!viewTree[:<viewTreeSpecifier>]                   Specify view the result as a tree, and how
  -!0e|--!clearEvents[:<bool>]                             Determines whether collected events will be clear before execution of the command
  -!ce|--!collectEvents[:<bool>]                           Determines whether events will be collected during execution of the command
  -rpeu|--ResolverPublisherEndpointUri <uri>               Resolver publisher endpoint URI
  -rpeui|--ResolverPublisherEndpointUser <userInfo>        Resolver publisher endpoint user name token - user
  -rpeun|--ResolverPublisherEndpointUserName <string>      Resolver publisher endpoint user name token - user name
  -rpeup|--ResolverPublisherEndpointUserPassword <string>  Resolver publisher endpoint user name token - password
  -rpfru|--ResolverPublisherFileResourceUri <uri>          Resolver publisher file resource URI
  -rk|--ResolverKind <uaResolverKind>                      Resolver kind
  -cni|--ConnectionNetworkInterface <name>                 PubSub connection network interface
  -cn|--ConnectionName <name>                              PubSub connection name
  -cru|--ConnectionResourceUri <uri>                       PubSub connection resource URI
  -ctpn|--ConnectionTransportProfileName <uaPubsubTpn>     PubSub connection transport profile name
  -ctpu|--ConnectionTransportProfileUri <uri>              PubSub connection transport profile URI
  -cp|--ConnectionProperty <uaKey-uaValue-pair>            PubSub connection property (*)
  -uecf|--UseEthernetCaptureFile <fileName>                Use Ethernet capture file (requires OpcLabs.Pcap)
  -uucf|--UseUdpCaptureFile <fileName>                     Use UDP capture file (requires OpcLabs.Pcap)
  -cbapu|--ConnectionBrokerAuthenticationProfileUri <uri>  PubSub connection broker authentication profile URI
  -cbru|--ConnectionBrokerResourceUri <uri>                PubSub connection broker resource URI
  -cddu|--ConnectionDatagramDiscoveryUri <uri>             PubSub connection datagram discovery URI
  -mnms|--MaximumNetworkMessageSize <uint32>               Maximum network message size (ignored)
  -mrt|--MessageReceiveTimeout <double>                    Message receive timeout (milliseconds)
  -sgi|--SecurityGroupId <name>                            Security group Id
  -sksu|--SecurityKeyServiceUri <uri>                      Security key service URI (*)
  -sm|--SecurityMode <uaSecurityMode>                      Security mode
  -stms|--SksTemplateMessageSecurity <uaMsml>              SKS template message security modes
  -stu|--SksTemplateUser <userInfo>                        SKS template user name token - user
  -stun|--SksTemplateUserName <string>                     SKS template user name token - user name
  -stup|--SksTemplateUserPassword <string>                 SKS template user name token - user password
  -bapu|--BrokerAuthenticationProfileUri <uri>             Broker authentication profile URI
  -bmdqn|--BrokerMetaDataQueueName <name>                  Broker metadata queue name
  -bqn|--BrokerQueueName <name>                            Broker queue name
  -brdg|--BrokerRequestedDeliveryGuarantee <uaGuarantee>   Broker requested delivery guarantee
  -bru|--BrokerResourceUri <uri>                           Broker resource URI
  -dso|--DataSetOffset <uint16>                            Dataset offset
  -gv|--GroupVersion <uint32>                              Group version
  -nmn|--NetworkMessageNumber <uint16>                     Network message number
  -dsci|--DataSetClassId <guid>                            Dataset class Id
  -adm|--AllowDataMessages <bool>                          Allow data messages (default=true)
  -aem|--AllowEventMessages <bool>                         Allow event messages (default=true)
  -dswi|--DataSetWriterId <uint16>                         Dataset writer Id
  -dswn|--DataSetWriterName <name>                         Dataset writer name
  -op|--OriginPattern <pattern>                            Pattern to match the origin
  -pi|--PublisherId <uaPublisherId>                        Publisher Id
  -rfv|--RequiredFieldValue <key-typedValue-pair>          Required field value (uses promoted fields when available) (*)
  -wgi|--WriterGroupId <uint16>                            Writer group Id
  -wgn|--WriterGroupName <name>                            Writer group name
  -pdsn|--PublishedDataSetName <name>                      Published dataset name
  -a|--Aggregates <aggregates>                             List of aggregates to be reported after the capture is completed (default:
                                                           DataSetHeaderStatistics)
  -dho|--DistinctHeadersOnly                               Only output distinct PubSub headers
  -ofbi|--OutputFieldsById                                 Output dataset fields by their dataset field Id
  -i|--interactive                                         Enter subcommands in an interactive loop ("exit" to leave)

Commands:
  !wait                                                    Specify how long will the parent command execute (default 00:01:00)

Run 'subscribeDataSet|sds [command] --help' for more information about a command.
(*) Indicates options that can be specified multiple times with multiple values.

Parameter values:
  <aggregate>              DataSetHeaderStatistics|DataSetWriterStatistics|OriginStatistics|PublisherStatistics
  <aggregates>             None|All|<aggregate>[,<aggregate>]...
  <clarkNotation>          [{<url>}]<name>
  <format>                 <string>
  <key-typedValue-pair>    <name>=<typedValue>
  <pattern>                <string>
  <treeTraversalType>      None|DepthFirst|BreadthFirst
  <typeCode>               Empty|Object|DBNull|Boolean|Char|SByte|Byte|Int16|UInt16|Int32|UInt32|Int64|UInt64|Single|Double|Decimal|DateTime|String
  <typedValue>             [<typeCode>]<value>
  <uaBuiltInType>          Null|Boolean|SByte|Byte|Int16|UInt16|Int32|UInt32|Int64|UInt64|Float|Double|String|DateTime|Guid|ByteString|XmlElement|NodeId|ExpandedNodeId|StatusCode|QualifiedName|LocalizedText|ExtensionObject|DataValue|Variant|DiagnosticInfo|Number|Integer|UInteger|Enumeration
  <uaGuarantee>            NotSpecified|BestEffort|AtLeastOnce|AtMostOnce|ExactlyOnce
  <uaKey-uaValue-pair>     <clarkNotation>=<uaValue>
  <uaPublisherId>          [<uaPublisherIdType>]<value>
  <uaPublisherIdType>      |Byte|UInt16|UInt32|UInt64|String
  <uaPubsubTpn>            AmqpJson|AmqpUadp|EthUadp|MqttAutoOrJson|MqttAutoOrUadp|MqttJson|MqttUadp|UdpUadp
  <uaResolverKind>         None|PubSubDiscovery|PublisherEndpoint|PublisherFile [DISCOVERY NOT IMPLEMENTED]
  <uaSecurityMode>         None|SecurityNone|SecuritySign|SecuritySignAndEncrypt|Secure|All
  <uaValue>                [<uaBuiltInType>]<value>
  <userInfo>               <string>[:<string>]
  <viewSequenceSpecifier>  [<viewSequenceType>][:<format>]
  <viewSequenceType>       Default|None|Simple|Table|Browse
  <viewTreeSpecifier>      [<viewTreeType>][:<format>]
  <viewTreeType>           Default|None|Simple|Table
  <viewValueSpecifier>     [<viewValueType>][:<format>]
  <viewValueType>          Default|None|Simple|Properties|Table|Write|Dump|Save

Help text for the OpcCmd utility itself can by displayed using OpcCmd --help. Help text for the OpcCmd uaSubscriber command can be displayed using OpcCmd uaSubscriber --help (there are some less-frequently options directly on this command, such as resolution timeouts, which are not discussed here).

Explanation of all the options is outside the scope of this article. Use the provided examples to work with the tool, and add options to the examples when the need arises. The options generally fall into several categories:

Resolver
Allow the physical parameters be determined from logical parameters by a resolution process, from a configuration file or an OPC UA server with PubSub configuration model. Options in this category start with the word Resolver.
Connection
Specify how the PubSub connection is made. The main options in this category start with the word Connection. The --ConnectionTransportProfile (-ctp) does not have to specified if it can be inferred from the --ConnectionResourceUri (-cru; for example, opc.udp and opc.eth schemes in the --ConnectionResourceUri imply the transport profile unambiguously, and therefore you do not have to specify --ConnectionTransportProfile with them). You can use one of the pre-defined symbolic names (such as ip6-allnodes) in place of the host name in --ConnectionResourceUri (-cru); see Enhanced Host Name Resolution for more information.
Communication parameters
E.g. --MessageReceiveTimeout (-mrt), or most of the options that start with the word Broker.
Filter
Allows filtering of the incoming messages. Main option in this category, --PublisherId (-pi), allows you to specify the publisher ID (e.g. -pi [UInt64]31). Other options in this category include --WriterGroupId (-wgi) and --DataSetWriterId (-dswi).

Command: uaSubscriber subscribeDataSetField

The subscribeDataSetField command is almost identical to the subscribeDataSet command. The only difference is that it does not display the whole dataset contents, but extracts a single given dataset field, and displays its data only.

The name of the field is given using an additional command-line option, --FieldName (-fn), followed by the field name. If there is a metadata available, this has to be the field name as it appears in the metadata. In absence of the metadata, you can use the field index instead - an integer (starting from 0), and preceded by'#', e.g. #2 for the 3rd field in the dataset.

If a dataset message is received but the specified field is not present in the dataset, the tool will display a corresponding error message.

Physical and Logical Parameters

The PubSub subscription can be specified using physical parameters, logical parameters, or a mix of them.

Physical parameters refer to data that is directly used to open the PubSub connection, and that appears "on the wire", in the PubSub messages. They include (only the most important parameters are listed; the list is not complete):

  • --ConnectionNetworkInterface (-cni)
  • --ConnectionResourceUri (-cru). This is the main parameter that always has to be specified. The scheme part is mandatory, always start the URI with "opc.udp://" in this version. Default port for OPC UA UDP is 4840 and does not have to be specified.
  • --ConnectionTransportProfile (-ctp). You do not need to specify it, if it can be derived from the scheme, such as in "opc.udp:".
  • --MessageReceiveTimeout (-mrt)
  • --DataSetOffset (-dso)
  • --GroupVersion (-gv)
  • --NetworkMessageNumber (-nmn)
  • --DataSetClassId (-dsci)
  • --DataSetWriterId (-dswi)
  • various PublisherIdXXXX (-piXX) options
  • --WriterGroupId (-wgi)

Logical parameters refer to named objects in the PubSub configuration. They are:

  • --ConnectionName (-cn)
  • --DataSetWriterName (-dswn)
  • --WriterGroupName (-wgn)
  • --PublishedDataSetName (-pdsn)

When using logical parameters, you typically specify the first three (connection, dataset writer and writer group names), or the last one (published data set name). When published data set name is specified, OpcCmd finds the instances in the PubSub configuration where the dataset is published; the outcome must be unambiguous, otherwise an error occurs. Other logical parameters, and some physical parameters (such as transport profile URI) can be used to narrow down the outcome of this selection process.

The PubSub configuration information must somehow be available to OpcCmd, and a so-called resolver is used to transform the logical parameters to physical ones. There are currently two kinds of resolvers: One takes the PubSub configuration from a file (in a format given by OPC UA specification), the other works with a live PubSub configuration in an information model of a live OPC server that supports it (and is typically part of, of connected with or related to, the actual OPC UA PubSub publisher).

Following parameters are used to specify the resolver and its parameters:

  • --ResolverPublisherEndpointUri (-rpeu). Use this option to resolve the logical parameters from an OPC UA server with PubSub configuration model.
  • --ResolverPublisherFileResourceUri (-rpfru). Use this option to resolve the logical parameters from a PubSub configuration file.
  • --ResolverKind (-rk). Not necessary unless you want to specify multiple resolvers, and then just switch between them.

The information you specify using the parameters must be valid for the subscription to work, but in some cases it does not have to be complete. For example, when using physical or logical parameters, you do not have to specify anything beyond the connection - the OpcCmd will then simply process all messages on that connection, without filtering. Or, you can filter just by publisher ID, but still receive different datasets provided by the given publisher.

Aggregates

The subscribeDataSet command can calculate aggregated information out of the notifications received, and display it at the end of command execution. By default, it displays a statistics of dataset headers (count of each distinct header received, and the rate at which it was received). You can use the --Aggregates (-a) option to choose the aggregate (or aggregates) that will be calculated and displayed. Available aggregates are currently DataSetHeaderStatistics, DataSetWriterStatistics, OriginStatistics, and PublisherStatistics.

Examples

Following examples show some typical OpcCmd use cases (obtained through OpcCmd uaSubscriber subscribeDataSet --help):

Usage examples:

Subscribe to an OPC UA PubSub dataset, specifying physical parameters:
  uaSubscriber subscribeDataSet opc.udp://239.0.0.1:4840
  uaSubscriber subscribeDataSet opc.udp://224.0.0.22 -dswi 62541
  uaSubscriber subscribeDataSet -cru opc.udp://239.0.0.1:4840 !wait 01:00
  uaSubscriber subscribeDataSet opc.udp://239.0.0.1:4840 -pi [UInt16]30
  uaSubscriber subscribeDataSet opc.udp://239.0.0.1:4840 --OriginPattern 192.168.*
  uaSubscriber subscribeDataSet opc.eth://FF-FF-FF-FF-FF-FF -pi [UInt16]30
  uaSubscriber subscribeDataSet mqtt://opcua-pubsub.demo-this.com opcuademo/uadp/none
  uaSubscriber subscribeDataSet mqtt://opcua-pubsub.demo-this.com opcuademo/uadp/none -dswi 4 -!op View=[ViewOptions]Cls
  uaSubscriber subscribeDataSet mqtt://opcua-pubsub.demo-this.com opcuademo/json -ctpn MqttJson
  uaSubscriber subscribeDataSet mqtt://opcua-pubsub.demo-this.com #
  uaSubscriber subscribeDataSet mqtt://opcua-pubsub.demo-this.com # --DistinctHeadersOnly !wait Infinite
  uaSubscriber subscribeDataSet mqtt://opcua-pubsub.demo-this.com # -a OriginStatistics,DataSetHeaderStatistics
Subscribe to an OPC UA PubSub dataset, specifying logical parameters (and resolving them first):
  uaSubscriber subscribeDataSet -rpfru http://opcua.demo-this.com/UADemoPublisher/UADemoPublisher-PublicDemo.uabinary -pdsn Simple
  uaSubscriber subscribeDataSet -rpeu opc.tcp://192.168.0.85:4840 -cn UDP1 -wgn WriterGroupStatic -dswn WriterSimple
  uaSubscriber subscribeDataSet -rpeu opc.tcp://192.168.0.50:4842 -pdsn "PublishedDataSet #1"
  uaSubscriber subscribeDataSet -rpfru unified_automation_cpp.bin -cn UDP1 -wgn WriterGroupDynamic -dswn WriterAllTypes

More examples:

Subscribe to all messages generated by a default configuration of the UADemoPublisher utility (see UADemoPublisher Basics for more information):

OpcCmd uaSubscriber subscribeDataSet -cru opc.udp://239.0.0.1

Subscribe to all messages on an IPv6 multicast address ff02::1 (all nodes on the local network segment):

OpcCmd uaSubscriber subscribeDataSet -cru opc.udp://[ff02::1]

Subscribe to all messages on an Ethernet broadcast address (FF-FF-FF-FF-FF-FF), tagged with VID (VLAN identifier) 2:

OpcCmd uaSubscriber subscribeDataSet -cru opc.eth://eth-broadcast:2

For messages from a default configuration of UADemoPublisher utility, with specific publisher ID (31, in 64 bits) and dataset writer ID (4):

OpcCmd uaSubscriber subscribeDataSet -cru opc.udp://239.0.0.1 -pi [UInt64]31 -dswi 4

Sample Output

The following listing shows a sample output of the OpcCmd tool, when subscribed to data coming from the UADemoPublisher (shortened):

OPC Labs OPC Command-line Tool (.NET Framework) 5.63.115.1

Executing for 00:01:00 (press 'X' to stop)...
Subscribing dataset...
Dataset handle: 13000001

IEasyUASubscriber.DataSetMessage: Success

IEasyUASubscriber.DataSetMessage: *** Failure {59D1C1E4}\1: The OPC UA PubSub discoverer has no DataSetMetaData information for the dataset. PubSub connection name: 'PubSubConnection1', publisher Id: 30. [...]

IEasyUASubscriber.DataSetMessage: Success; Good; Data; publisher=[String]32, writer=1, class=eae79794-1af7-4f96-8401-4096cd1d8908, origin=192.168.1.69:4840, fields: 4
Field data (sequence): 4 element(s)                                                                                                 
╒══╤════════════════════╤═════════╤═══════════════╤═══════════════╤══════╕                                                          
│[]│Value               │Value    │Source         │Server         │Status│                                                          
│  │                    │Type Name│Timestamp Local│Timestamp Local│Code  │                                                          
╞══╪════════════════════╪═════════╪═══════════════╪═══════════════╪══════╡                                                          
│#0│True                │Boolean  │               │               │Good  │                                                          
│#1│19                  │Int32    │               │               │Good  │                                                          
│#2│1371                │Int32    │               │               │Good  │                                                          
│#3│3/23/2022 8:19:46 AM│DateTime │               │               │Good  │                                                          
╘══╧════════════════════╧═════════╧═══════════════╧═══════════════╧══════╛                                                          

IEasyUASubscriber.DataSetMessage: Success; Good; Data; publisher=[String]32, writer=3, class=96976b7b-0db7-46c3-a715-0979884b55ae, origin=192.168.1.69:4840, fields: 100
Field data (sequence): 100 element(s)                                                                                               
╒═══╤═════╤═════════╤═══════════════╤═══════════════╤══════╕                                                                        
│[] │Value│Value    │Source         │Server         │Status│                                                                        
│   │     │Type Name│Timestamp Local│Timestamp Local│Code  │                                                                        
╞═══╪═════╪═════════╪═══════════════╪═══════════════╪══════╡                                                                        
│#0 │19   │Int64    │               │               │Good  │                                                                        
│#1 │119  │Int64    │               │               │Good  │                                                                        
│#2 │219  │Int64    │               │               │Good  │                                                                        
│#3 │319  │Int64    │               │               │Good  │                                                                        
│#4 │419  │Int64    │               │               │Good  │                                                                        
│#5 │519  │Int64    │               │               │Good  │                                                                        
│#6 │619  │Int64    │               │               │Good  │                                                                        
│#7 │719  │Int64    │               │               │Good  │                                                                        
│#8 │819  │Int64    │               │               │Good  │                                                                        
│#9 │919  │Int64    │               │               │Good  │                                                                        
│#10│1019 │Int64    │               │               │Good  │                                                                        
│#11│1119 │Int64    │               │               │Good  │                                                                        
│#12│1219 │Int64    │               │               │Good  │                                                                        
...
╘═══╧═════╧═════════╧═══════════════╧═══════════════╧══════╛                                                                        

IEasyUASubscriber.DataSetMessage: Success; Good; Data; publisher=[String]32, writer=4, class=cc7cb5f4-4272-45c2-9a4d-f85a8b331f6a, origin=192.168.1.69:4840, fields: 16
Field data (sequence): 16 element(s)                                                                                                
╒═══╤════════════════════════════════════╤═════════╤═══════════════╤═══════════════╤══════╕                                         
│[] │Value                               │Value    │Source         │Server         │Status│                                         
│   │                                    │Type Name│Timestamp Local│Timestamp Local│Code  │                                         
╞═══╪════════════════════════════════════╪═════════╪═══════════════╪═══════════════╪══════╡                                         
│#0 │False                               │Boolean  │               │               │Good  │                                         
│#1 │19                                  │Byte     │               │               │Good  │                                         
│#2 │19                                  │Int16    │               │               │Good  │                                         
│#3 │19                                  │Int32    │               │               │Good  │                                         
│#4 │19                                  │Int64    │               │               │Good  │                                         
│#5 │19                                  │Int16    │               │               │Good  │                                         
│#6 │19                                  │Int32    │               │               │Good  │                                         
│#7 │19                                  │Int64    │               │               │Good  │                                         
│#8 │19                                  │Decimal  │               │               │Good  │                                         
│#9 │19                                  │Single   │               │               │Good  │                                         
│#10│19                                  │Double   │               │               │Good  │                                         
│#11│Tango                               │String   │               │               │Good  │                                         
│#12│20 element(s)                       │Byte[]   │               │               │Good  │                                         
│#13│47fa030c-48d6-427b-b87b-ef8dfb661b63│Guid     │               │               │Good  │                                         
│#14│3/23/2022 8:19:46 AM                │DateTime │               │               │Good  │                                         
│#15│10 element(s)                       │Int64[]  │               │               │Good  │                                         
╘═══╧════════════════════════════════════╧═════════╧═══════════════╧═══════════════╧══════╛                                         

...

IEasyUASubscriber.DataSetMessage: Success; 2022-03-23 08:19:49.407,711,500,00; Good; Event; publisher=[UInt64]31, writer=51, origin=192.168.1.69:4840, fields: 4
Field data (sequence): 4 element(s)                                                                                                 
╒══╤════════════════════╤═════════╤═══════════════════════╤═══════════════╤══════╕                                                  
│[]│Value               │Value    │Source                 │Server         │Status│                                                  
│  │                    │Type Name│Timestamp Local        │Timestamp Local│Code  │                                                  
╞══╪════════════════════╪═════════╪═══════════════════════╪═══════════════╪══════╡                                                  
│#0│False               │Boolean  │2022-03-23T09:19:49.407│               │Good  │                                                  
│#1│22                  │Int32    │2022-03-23T09:19:49.407│               │Good  │                                                  
│#2│7358                │Int32    │2022-03-23T09:19:49.407│               │Good  │                                                  
│#3│3/23/2022 8:19:49 AM│DateTime │2022-03-23T09:19:49.407│               │Good  │                                                  
╘══╧════════════════════╧═════════╧═══════════════════════╧═══════════════╧══════╛                                                  

IEasyUASubscriber.DataSetMessage: Success; 2022-03-23 08:19:50.427,087,200,00; Good; Event; publisher=[UInt64]31, writer=51, origin=192.168.1.69:4840, fields: 4
Field data (sequence): 4 element(s)                                                                                                 
╒══╤════════════════════╤═════════╤═══════════════════════╤═══════════════╤══════╕                                                  
│[]│Value               │Value    │Source                 │Server         │Status│                                                  
│  │                    │Type Name│Timestamp Local        │Timestamp Local│Code  │                                                  
╞══╪════════════════════╪═════════╪═══════════════════════╪═══════════════╪══════╡                                                  
│#0│False               │Boolean  │2022-03-23T09:19:50.427│               │Good  │                                                  
│#1│23                  │Int32    │2022-03-23T09:19:50.427│               │Good  │                                                  
│#2│9296                │Int32    │2022-03-23T09:19:50.427│               │Good  │                                                  
│#3│3/23/2022 8:19:50 AM│DateTime │2022-03-23T09:19:50.427│               │Good  │                                                  
╘══╧════════════════════╧═════════╧═══════════════════════╧═══════════════╧══════╛                                                  

...

Unsubscribing dataset (dataset handle 13000001)...
Dataset header counts (sequence): 7 element(s)                                                                                      
╒════════════════════════════════════════════════════════════════════════════════════════════════════╤═════╕                        
│[]                                                                                                  │Value│                        
╞════════════════════════════════════════════════════════════════════════════════════════════════════╪═════╡                        
│publisher=[UInt64]31, writer=1, origin=192.168.1.69:4840                                            │6    │                        
│publisher=[UInt64]31, writer=3, origin=192.168.1.69:4840                                            │4    │                        
│publisher=[UInt64]31, writer=4, origin=192.168.1.69:4840                                            │6    │                        
│publisher=[UInt64]31, writer=51, origin=192.168.1.69:4840                                           │38   │                        
│publisher=[String]32, writer=1, class=eae79794-1af7-4f96-8401-4096cd1d8908, origin=192.168.1.69:4840│117  │                        
│publisher=[String]32, writer=3, class=96976b7b-0db7-46c3-a715-0979884b55ae, origin=192.168.1.69:4840│117  │                        
│publisher=[String]32, writer=4, class=cc7cb5f4-4272-45c2-9a4d-f85a8b331f6a, origin=192.168.1.69:4840│117  │                        
╘════════════════════════════════════════════════════════════════════════════════════════════════════╧═════╛                        
Command finished: subscribeDataSet|sds (61.6 seconds).
OpcCmd terminating with exit code 0.

Explanation to some of the output follows.

IEasyUASubscriber.DataSetMessage: Success

This line indicates that a PubSub connection has been successfully established (there is no direct connection to the publisher - but, depending on the protocol, an IP socket needs to be open, or similar "initiating" operation needs to be made, and the message indicates that the parameters used to specify the connections were OK in principle). If the connection could not have been established, there would be an error message instead.

IEasyUASubscriber.DataSetMessage: Success; Good; Data; publisher=[String]32, writer=1, class=eae79794-1af7-4f96-8401-4096cd1d8908, origin=192.168.1.69:4840, fields: 4

Similar lines precede each dataset message received. They contain the timestamp of the message, the status code, an indication whether the message contains Data or Event, and an identification of the dataset (depending on what is actually available).

╒══╤════════════════════╤═════════╤═══════════════╤═══════════════╤══════╕                                                          
│[]│Value               │Value    │Source         │Server         │Status│                                                          
│  │                    │Type Name│Timestamp Local│Timestamp Local│Code  │                                                          
╞══╪════════════════════╪═════════╪═══════════════╪═══════════════╪══════╡                                                          
│#0│True                │Boolean  │               │               │Good  │

Similar table rows contain the data fields of the message. '#' followed by a number indicates a field index. If metadata is available, there is a field name instead. Then, the actual data value is listed, followed by its type in '{ }' (this is .NET type; note that the values are converted to so-called CLS types, and therefore the .NET type may not be precisely the same as the type of the field). After that, source and server timestamps (if available), and status code, are listed. The rows with data fields are sorted alphabetically by the field name/index.

The timestamps are formatted down to 10-picosecond level.

IEasyUASubscriber.DataSetMessage: *** Failure {59D1C1E4}\1: The OPC UA PubSub discoverer has no DataSetMetaData information for the dataset. PubSub connection name: 'PubSubConnection1', publisher Id: 30. [...]

This message indicates that a dataset message has been received, but because the data uses raw encoding and no metadata is available, it cannot be fully parsed. Metadata can be provided from a configuration file or by an OPC UA server with PubSub configuration model. The related command-line options for that are (among others) --ResolverPublisherFileResourceUri (-rpfru) and --ResolverPublisherEndpointUri (-rpeu). The UADemoPublisher comes with (and/or can generate) a .uabinary file for itself.

Reading Capture Files

OpcCmd can read the network traffic from a file, instead of using live data. This is extremely handy for various kinds of troubleshooting, diagnostics, analysis and similar tasks. It allows you to capture the data generated by the publisher once, and then replay it as many times as you like.

The network capture needs to be in the PCAP format. Various tools, including Wireshark, can read and write this format. The current versions of Wireshark, however, store network capture in a newer format (PCAPNG) by default. Using the "Save as type" drop-down in Wireshark's "Save file as" dialog, it is easy to save your network captures in the PCAP format, or even convert existing PCAPNG captures to PCAP.

For UDP message mapping, apply the --UseUdpCaptureFile (-uucf) option, followed by the file name, to the subscribeDataSet or subscribeDataSetField command. For Ethernet message mapping, apply the --UseEthernetCaptureFile (-uecf) option instead.

You still need to specify the connection URI as usual. The command to subscribe to a dataset from a network capture file may then look like this (the file used is one of sample files that ship with the UADemoPublisher):

OpcCmd uaSubscriber subscribeDataSet opc.udp://239.0.0.1:4840 -uucf UADemoPublisher-UDP

The default file name extension is ".pcap".

When reading UDP message captures, there is a built-in IP fragment reassembler (for both IPv4 and IPv6), and thus you can work with messages whose requirements exceed the network's MTU.

The packets in the capture file are used to provide "timed" replay of the network communication. This means that when the capture is replayed, the software not only mimics the actual data in the packets, but it also attempts to maintain the same timing of the packets as it appears in the capture. An initial delay of 1000 milliseconds is added before the replay starts, in order to allow for startup tasks on the receiver side to finalize.

Tips and Tricks

Listen on UDP port for unicast messages
You can change the local port to listen on (e.g. to 9999) using the following command option: --ConnectionProperty {http://opclabs.com/OpcUA/PubSub}LocalPort=[Int32]9999.
Collect information about "who is publishing" on a connection
Specify just the connection parameters, and use the --DistinctHeadersOnly (-dho) option. The command will print out every new combination of publisher Id, writer group dataset writer Id&name, dataset class Id and origin it receives. For example:
OpcCmd uaSubscriber subscribeDataSet mqtt://opcua-pubsub.demo-this.com # --DistinctHeadersOnly !wait Infinite

or

OpcCmd uaSubscriber subscribeDataSet opc.udp://239.0.0.1:4840 --DistinctHeadersOnly !wait Infinite

Only messages that can be sufficiently parsed to obtain the basic header information are considered. The command works well with the OPC UA PubSub Automatic Message Mapping Recognition feature, meaning that you do not even have to specify the message mapping (JSON or UADP). For more advanced scenarios, see Using OpcCmd Utility as OPC UA PubSub Sniffer.

Related reading