Prosys_OPC_UA_SDK_for_Java_PubSub_Tutorial
Prosys_OPC_UA_SDK_for_Java_PubSub_Tutorial
0
PubSub Tutorial
Tutorial
PubSub
-
Java
for
SDK
UA
OPC
Prosys
Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1. Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
2. Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
3. Sample Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
3.1. SampleBroker + SSL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
3.1.1. Generating the keystores and certificates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
4. Configuring PubSub . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
4.1. PubSubSystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
4.2. DataSets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
4.2.1. Variable DataSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
4.2.2. Event DataSet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
4.3. Connection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
4.3.1. Discovery functionality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
4.4. Publisher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
4.4.1. Writer Group . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
4.4.2. DataSet Writer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4.5. Subscriber . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.5.1. Reader Group . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
4.5.2. DataSet Reader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
DataSet Metadata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
PubSubSystemEvents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
TargetVariables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1. Introduction
This is the Prosys OPC UA SDK for Java tutorial for using PubSub features. By reading this tutorial you
should be able to implement your own PubSub applications, utilizing the features provided by the SDK.
The functionality is defined in the OPC UA Specification 1.04 Part 14 "PubSub"
The PubSub Edition has been available since the SDK version 4.5.0. There are still
several PubSub features that are not supported. If you are interested in any
specific feature or have other types of inquiries, please contact the Prosys team
and we’ll see how we can help you.
PubSub consists of two parties. A Publisher, that will send data and a Subscriber, that will receive it.
Applications can work both as a Publisher and a Subscriber. Neither one per se has to be specifically an
OPC UA Application, though typically at least one side is.
The basic premise in the OPC UA Specification Part 14 is that the Publisher or Subscriber would be an
OPC UA Server and the address space of the server is the source and/or target of the data. In the
context of our SDK, the same applies to the connected server when the Publisher or Subscriber would
be an OPC UA Client. You can also receive the data via an event-system and ignore defining any target
node.
The OPC UA PubSub transport configuration consists of Transport Protocol and Message Encoding.
• Datagram Transport Protocol, which is mapped to OPC UA UDP and OPC UA Ethernet
• Broker Transport Protocol, which is mapped to MQTT and AMQP
The Prosys OPC UA SDK for Java support currently the following transport facets:
UADP (UA Datagram Protocol) is the binary message mapping for PubSub. JSON is an alternative clear-
text message format.
MQTT transport is mostly targeting communication to cloud systems. The SDK supports both UADP and
JSON messages with MQTT. The supported MQTT versions are MQTT 3.1 and 3.1.1. The MQTT transport
is typically going from the Publisher to a Broker, which then delivers it to the subscribers. OPC UA
defines both a reversible and non-reversible JSON encoding format. The latter is easier to use by
generic MQTT subscribers, whereas the former includes more OPC UA meta data.
1.1. Security
There are 2 different security levels in PubSub. For UDP-UADP and MQTT-UADP there is security defined
1
for UADP in the specification. This is not yet supported by the Prosys OPC UA SDK for Java. There is
separate security for MQTT in the form of SSL connections to the Broker. This is supported by the SDK
(see SampleBroker + SSL).
2. Installation
You should have a PubSub capable edition of the SDK in order to use PubSub. You can use one of the
following distributions:
• prosys-opc-ua-sdk-for-java-VERSION-evaluation.zip/tar.gz
• prosys-opc-ua-sdk-for-java-VERSION-client-server-pubsub-binary.zip/tar.gz
• prosys-opc-ua-sdk-for-java-VERSION-client-server-pubsub-source.zip/tar.gz
Please, contact Prosys OPC support or sales to get one, if you don’t have it yet.
3. Sample Applications
PubSub editions include sample applications that demonstrate how the PubSub SDK is used in practice:
The SamplePublisherServer publishes data changes of the MyLevel variable and MyLevelAlarm events from
MyDevice node of the server. The Subscribers receive these values and you can see on the console how
the value of MyLevel is changing and when events with message "Level exceeded" have been sent.
SampleSubscriberServer is showing how to synchronize data between two servers. It is monitoring data
changes to MyLevel as a Subscriber from the Publisher and updates MyPubSubTargetVariable in its own
address space accordingly. This allows you to connect to the server with an OPC UA client to monitor
these changes as well.
By default the samples use UDP transport with UADP messages. You can use SampleBroker to run the
samples with MQTT. Alternatively to UADP, you can also use JSON messages with MQTT.
The samples are used similar to the other samples in the SDK. You can compile and start them using
the included script files (.bat/.sh) or use the pom.xml files for Maven integration.
Generally it is best to make a project within your IDE, for example, as explained in
2
• To run a basic test with UDP transport and UADP messages, start both the SamplePublisherServer
and SampleSubscriberServer and select a common Network Interface at start.
• To run with MQTT transport, start the SampleBroker first. Then, start both the
SamplePublisherServer and SampleSubscriberServer with the command line option '-a' (or '--
address'): samplepublisherserver.bat -a mqtt://localhost:1883.
• To use JSON messages with MQTT use also the command line option '-e' ('--encoding'):
samplepublisherserver.bat -a mqtt://localhost:1883 -e json.
The following CLI flags can be used to start `SampleBroker`in SSL mode with also requiring client side
authentication:
PATH_TO_KEYSTORE.jks must be a (preferably absolute) path to a java keystore which contais the
certificate of the Broker, it typically is password protected, so the password is given with
KEYSTORE_PASSWORD. The individual private key of the Broker within that store might have a different
password, that is given with BROKER_KEY_PASSWORD.
PATH_TO_TRUSTSTORE.jks must be a (preferably absolute) path to a java keystore which contais the
truststore of the Broker. With client side authentication required, this store must contain the public key
of the client connecting to the Broker. The store is typically password protected, so the password is
given with TRUSTSTORE_PASSWORD.
The SampleBroker is just a sample to show the PubSub with MQTT works. In a real
application passwords should NEVER be passed in via command line (see e.g.
These are instructions that will work with the SampleBroker, please consult the
documentation of your real Broker how these are done there.
3
These instructions assume the 'keytool' (from a JDK installation) and 'openssl'
commands are available on your system. On non-windows platforms 'openssl' is
typically available or easily installed via package managers. On windows one "easy
place" is typically within a git bash terminal, assuming you are doing version
control with 'Git'. Also depending on the version of the tools you have the process
might be slightly different.
The openssl commands listed below have the 'winpty' at the start, since this might
This creates the private (+public) key of the Broker (note that it will ask some questions, see below for
recommended answers for the purpose of this tutorial):
keytool -genkey -keyalg RSA -alias broker -keystore broker-keystore.jks -storepass password-keystore
-validity 360 -keysize 2048 -ext san=dns:HOSTNAME,dns:localhost,ip:127.0.0.1
The san=… information must match the machine on which the SampleBroker will
be run (i.e. what address the clients use to connect to it). Replace the HOSTNAME
with the hostname of your machine.
4
For the client cert (that will connect to the Broker) we will re-use the OPC UA
ApplicationInstanceCertificate of the samplesubscriberserver and samplepublisherserver for the
purposes of this tutorial:
keytool -import -file mqtt-client-cert1.crt -alias client1 -keystore broker-truststore.jks -storepass password-
truststore
keytool -import -file mqtt-client-cert2.crt -alias client2 -keystore broker-truststore.jks -storepass password-
truststore
Answer to the "Trust this certificate? [no]:" with "yes" for both.
Next we will export the public key of the broker certificate, to be used in the client side (so that the
client side trusts the Broker):
This server.pem is used then as a CLI parameter to the PubSub samples that wish to connect to the
Broker via MQTT+SSL via:
--ca-cert "PATH_TO_server.pem"
Note the parameter was named --ca-cert since it most likely would be a CA certificate (which has been
used to sign the keys of the Broker), but in this sample it is the public key directly.
Currently you must give the mqtt url in the format ssl:// instead of mqtt:// when
giving the address to other PubSub samples i.e. MQTT connection Conf objects.
This server.pem is the public key of the broker, the .pem is just a file format, but it
should be noted that for the rest of the SDK a .pem file has typically mean a private
key (as they are store typically as such, while we have used .der for the public keys).
5
4. Configuring PubSub
In this chapter we’ll go through the configuration of the PubSubSystem.
We strongly recommend you to investigate and play with the samples mentioned in Sample
Applications, but most steps are explained also here.
The PubSub configuration is grouped into various methods in the class SamplePubSubConfiguration. It
also enables handling of command line options for the samples. But for most parts, the configuration is
rather fixed. In your own applications, you can prepare the configuration to your needs using the
various configuration objects that are explained in the below sections.
4.1. PubSubSystem
Everything in the PubSub functionality is defined under the main PubSubSystem class.
The PubSubSystem is configured with PubSubSystemConf, which contains separate configuration objects
for the various parts. The configuration objects are immutable and they are created with the respective
Builder objects (so PubSubSystemConf.Builder in this case).
/**
* Creates a PubSubSystem with a sample configuration for a variable and event dataset
* corresponding to variableId and eventNotifierId.
*
* @param application UaServer or UaClient for which the PubSubSystem is created for
* @param pubSubMode {@link PubSubMode#PUBLISHER} or {@link PubSubMode#SUBSCRIBER}
* @param variableId a single variable to use for defining a Variable Dataset
* @param eventNotifierId an object to use for defining an event dataset. Note that event datasets
* are not available for client applications, yet.
* @param targetVariableId a target variable in the address space of an UaServer to which the
* variableId is mapped to
* @return The PubSubSystem to use with the application.
*/
public PubSubSystem createPubSubSystem(UaApplication application, PubSubMode pubSubMode,
UaNodeId variableId,
UaNodeId eventNotifierId, UaNodeId targetVariableId) {
if (application instanceof UaClient) {
// The eventNotifierId and targetVariableId only work for UaServers
if (eventNotifierId != null) {
throw new IllegalArgumentException("Cannot initialize an event dataset for UaClient");
}
if (targetVariableId != null) {
throw new IllegalArgumentException("Cannot initialize targetVariable for UaClient");
}
6
}
/*
* The PubSubSystem is configured with PubSubSystemConf, which contains separate configuration
* objects for the various parts. The configuration objects are immutable and they are created
* with the respective Builder objects.
*/
PubSubSystemConf.Builder builder = PubSubSystemConf.builder();
// MQTT requires special settings, which are currently provided via PubSubSystemOverrides
// Note, for the time being, SDK doesn't have built-in support for persisting these in a file.
PubSubSystemOverrides pubSubSystemOverrides = createMqttOverrides(application);
7
// The PubSubSystem is created in the context of an UaApplication (either UaClient or UaServer)
return PubSubSystem.createFor(application, pubSubSystemConf, pubSubSystemOverrides);
}
The following chapters will describe the different parts of the configuration that needs to be defined,
including the DataSets, which should match in the Publisher and Subscriber applications and
Connections, which must also match regarding the connection parameters, but which vary between the
Publisher and Subscriber, regarding the respective Writer and Reader configurations.
Once the configuration is finished, the PubSubSystem is created for an UaServer (or UaClient) object
with PubSubSystem.createFor as seen above.
4.2. DataSets
The DataSets define what is published in a Publisher. Both data changes and events can be published.
Although at the moment the client applications cannot publish events.
8
private PubSubVariableDataSetConf addPublishedVariableDataSet(PubSubSystemConf.Builder conf,
UaNodeId variableId) {
PubSubVariableDataSetConf.Builder builder = PubSubVariableDataSetConf.builder();
// The Dataset is identified by it's unique name
builder.setName(SAMPLE_VARIABLE_DATASET_NAME);
/*
* By default, the dataset will monitor the Value attribute of the variable. It will by default
* use data from the node for the metadata of the Field and the name part of the BrowseName
* Attribute for the field's name.
*/
builder.addPublishedVariables(variableId);
builder.addPublishedVariables(variableConfBuilder.build());
PubSubVariableDataSetConf r = builder.build();
conf.addOrReplaceDataSet(r);
return r;
}
The variables must be added to the DataSet using UaNodeId. This is a bit different to the NodeId that the
Client/Server parts of the SDK has used. The main difference is that it is always configured with a
NamespaceUri instead of NamespaceIndex. There are conversion methods between them, but in the
samples we can simply create the value corresponding to our MyLevel variable as follows:
By default, the DataSet will monitor changes in the Value attributes of the variables. If you wish to send
notifications for other attributes, you can use the PubSubPublishedVariableConf as seen above.
In addition to the AttributeId, the PubSubPublishedVariableConf can be used to specify other details,
such as the Deadband and SamplingIntervalHint, although these are not yet supported (will be added
9
in a later version).
builder.setEventNotifier(eventNotifierId);
// The SelecteClauses define which event fields are added to the Dataset
builder.addSelectClauses(UaSimpleAttributeOperand
.from(UaBrowseNamePath.from(Ids.BaseEventType, UaQualifiedName.standard("Message")), Attributes
.Value));
builder.addSelectClauses(UaSimpleAttributeOperand
.from(UaBrowseNamePath.from(Ids.BaseEventType, UaQualifiedName.standard("EventId")), Attributes
.Value));
PubSubEventDataSetConf r = builder.build();
conf.addOrReplaceDataSet(r);
return r;
}
The server samples use the Server object as the source events. We can define it’s UaNodeId as follows:
For more information about the concepts of specifying OPC UA Events, see
Prosys_OPC_UA_SDK_for_Java_Client_Tutorial.
4.3. Connection
The PubSub system must define at least one connection, via which the message are sent to the
network. Each connection consists of the transport protocol (UDP or MQTT) and message encoding
(UADP or JSON). There are separate connection configuration classes for each of the three supported
transport facets (i.e. combinations of transport protocol and message encoding):
PubSubMqttJsonConnectionConf, PubSubMqttUadpConnectionConf and PubSubUdpUadpConnectionConf. The
transport protocol and message encoding are combined as a PubSubTransportProfile.
The PubSubTransportProfile can server as a factory for creating Builder(s) of that kind. The samples take
the profile via command line arguments (or uses PubSubTransportProfile.UDP_UADP by default). This is
10
then used to create the Builder for the connection, groups and reader/writer configuration objects.
if (PubSubMode.PUBLISHER == pubSubMode) {
builder.setPublisherId(publisherId);
}
if (PubSubMode.PUBLISHER == pubSubMode) {
addWriterGroup(builder);
}
if (PubSubMode.SUBSCRIBER == pubSubMode) {
addReaderGroup(builder);
}
conf.addOrReplaceConnection(builder.build());
}
The PublisherId is defined only for a Publisher. The Subscribers can define it for the DataSet Reader, if
they wish to use it for filtering incoming messages.
The PublisherId should be unique in the network so that the Subscribers can recognize the Publishers
with them. The value can a String or unsigned number (Byte, UnsignedShort, UnsignedInteger or
UnsignedLong). Null and 0 are not valid values.
11
The samples are actually using a default PublisherId, which includes the actual
hostname of the computer where they are run. This enables identifying several
publishers in the same network. You can also provide a custom ID with the
command line option --publisher-id for the sample applications.
The connections also need to define the NetworkAddress to send or listen to. The default UDP multicast
address that we use is "opc.udp://224.0.5.1:4840". The address is given as InetSocketAddress, see
getInetAddress method for more details. Note that for multicast addresses you must also define which
NetworkInterface is used (as the address doesn’t map uniquely to one). You can check out the method
selectNetworkInterface in the sample code to see how to choose from the available Network Interfaces.
For MQTT, you define the NetworkAddress as String, corresponding to the address of the Broker. For
example, if you run the SampleBroker in the same computer, you would use "mqtt://localhost:1883".
For MQTT+SSL, you must give the mqtt url in the format ssl:// instead of mqtt://.
DataSetMetaData messages contain information about the structure of the DataSet messages, helping
Subscribers to decode the data they receive. For example, in section Variable DataSet we defined that
our variable DataSet contains the Value and DisplayName attributes of ´MyLevel`. The Value is
changing all the time, whereas the DisplayName typically stays constant. Messages sent by Publishers
don’t need to send values if they are not changing. But when a binary mapped message contains only
one value for a DataSet that includes two attributes there needs to be a way to determine which value
it is. For this reason, the variable fields in a DataSet are indexed in the respective DataSetMetaData to
distinguish them from each other.
In UADP the Publisher can be configured to send DataSetMetaData messages when the
DataSetMetaData changes. In MQTT it can also be sent periodically. Subscribers can also request
DataSetMetaData on demand from the Publisher. When using JSON message mapping with MQTT, the
DataSetMetaData messages can be sent to their own queue on a broker. Additionally, as mentioned in
DataSet Reader, a DataSetMetaData can be assigned manually to a Subscriber if the message structure
is known.
By default, Discovery messages are sent to the same NetworkAddress that was specified with
setNetworkAddress and you don’t need to do anything special for the configuration.
4.4. Publisher
The Publisher specific configuration consists of Writer Groups and DataSet Writers.
12
4.4.1. Writer Group
Writer Groups write the Network Messages that are published by the Publisher. A single Network
Message may contain one or more DataSet Messages from one or more DataSet Writers. Thus, for
example, when we send a Network Message, it may contain data from both the VariableDataSet and
EventDataSet that we configured.
Writer Groups are specific to the message encoding, so we have a separate initialization for UADP and
JSON.
builder.setPublishingInterval(Duration.ofMillis(publishingInterval));
builder.setKeepAliveTime(Duration.ofSeconds(120));
if (variableDataSet != null) {
addVariableDataSetWriter(builder);
}
if (eventDataSet != null) {
addEventDataSetWriter(builder);
}
connection.addOrReplaceGroup(builder.build());
}
And the init parts, which define specific settings for transport and message encoding.
13
UadpNetworkMessageContentMask uadpNetworkMessageContentMask =
UadpNetworkMessageContentMask.of(
UadpNetworkMessageContentMask.PayloadHeader, UadpNetworkMessageContentMask
.SequenceNumber,
UadpNetworkMessageContentMask.DataSetClassId, UadpNetworkMessageContentMask.PublisherId,
UadpNetworkMessageContentMask.WriterGroupId, UadpNetworkMessageContentMask.Timestamp,
UadpNetworkMessageContentMask.GroupHeader, UadpNetworkMessageContentMask
.NetworkMessageNumber);
builder.setMessageContentMask(uadpNetworkMessageContentMask);
// Set maximum Network Message size for written Network Messages. If message size exceeds the
// limit, it is chunked into several messages. Note that 65535 is the maximum size allowed for
// UDP connections.
builder.setMaxNetworkMessageSize(UnsignedInteger.valueOf(4096));
}
/*
* JSON messages don't need a limit, though this is mainly since they are only usable with MQTT.
*/
builder.setMaxNetworkMessageSize(UnsignedInteger.MAX_VALUE);
}
/*
* IMPORTANT! For now the queue names are assumed to be non-wildcards.
*/
builder.setQueueName(queueName);
builder.setMetaDataQueueName(metadataQueueName);
builder.setRequestedDeliveryGuarantee(BrokerTransportQualityOfService.AtLeastOnce);
14
}
WriterGroupId identifies the Writer Group within a Publisher and can be used by the Subscribers to
filter the messages (with UADP).
PublishingInterval defines the frequency of message dispatching. In case no DataSet messages have
been available for a time specified by KeepAliveTime, an empty Network Message is sent to notify the
Subscribers that the Publisher is still functional.
A Network Message can be configured to include meta data, which can then be used for filtering or
identification in the Subscribers. For example, SequenceNumber helps Subscribers to follow the correct
order of the messages.
If the size of the UDP Network Message exceeds the configured MaxNetworkMessageSize, it will be split
into several Network Messages that will be sent at specified PublishingOffsets. The maximum
MaxNetworkMessageSize allowed for UDP UADP communication is 65535 bytes.
and although the SDK supports it, make sure that the Subscribers also supports it,
if you need to split messages. For now, we use 4096, which works fine for our
samples.
A single DataSet Writer always writes data from exactly one DataSet. The following example shows how
to define a Variable DataSet Writer for UADP:
15
private void addVariableDataSetWriter(PubSubWriterGroupConf.Builder<?> group) {
PubSubDataSetWriterConf.Builder<?> builder = group.getTransportProfile()
.createDataSetWriterConfBuilder();
builder.setName(SAMPLE_VARIABLE_DATA_SET_WRITER_NAME);
builder.setDataSetWriterId(SAMPLE_VARIABLE_DATASET_WRITER_ID);
/*
* To optimise message sizes, DataSetWriter writes DataSetMessages that contain only the changed
* values of its PublishedDataSet. These messages are Delta Frames. DataSetMessages that contain
* all values of the PublishedDataSet are Key Frames. Parameter KeyFrameCount defines the
* maximum amount of times the PublishingInterval expires before sending a new Key Frame
* Message. If set as 1, every DataSetMessage will be a Key Frame message.
*/
// Note that this parameter only has meaning for writers that write a variable dataset
builder.setKeyFrameCount(UnsignedInteger.valueOf(SAMPLE_KEYFRAME_COUNT));
16
private static void initUadpDataSetWriter(PubSubUadpDataSetWriterConf.Builder<?> builder) {
// Headers to include in the network messages
builder.setMessageContentMask(UadpDataSetMessageContentMask.Timestamp);
When a DataSet message contains all the values of a Published DataSet, it is called a Key Frame
message. When it contains only changes it is called a Delta Frame message. The KeyFrameCount
parameter defines how often a Key Frame message is sent: if it is one, every message is a Key Frame,
which can be optimal in some situations.
The DatsSetFieldContentMask defines the value fields that are included in the messages.
For MQTT connections, QoS parameters and specific queues for DataSet and DataSetMetaData
messages are set in initBrokerTransportSettings.
4.5. Subscriber
The Subscriber specific configuration consists of Reader Groups and DataSet Readers.
17
4.5.1. Reader Group
A Reader Group reads Network Messages from a connection. A basic Reader Group is configured as
follows:
addVariableDataSetReader(builder);
addEventDataSetReader(builder);
connection.addOrReplaceGroup(builder.build());
}
And the init parts for transport and message encoding specifics:
A DataSet Reader that decodes DataSet messages from a specific Publisher and from a specific DataSet
Writer can be defined this way:
18
private void addVariableDataSetReader(PubSubReaderGroupConf.Builder<?> group) {
final PubSubDataSetReaderConf.Builder<?> builder = group.getTransportProfile()
.createDataSetReaderConfBuilder();
builder.setName(SAMPLE_VARIABLE_DATASET_READER_NAME);
// The reader can copy data automatically to target variables in the server's own address
// space if targetVariableId is defined
builder.setSubscribedDataSet(createTargetVariables(targetVariableId));
/*
* IMPORTANT! For now the queue names are assumed to be non-wildcards.
*/
builder.setQueueName(queueName);
builder.setMetaDataQueueName(metadataQueueName);
builder.setRequestedDeliveryGuarantee(BrokerTransportQualityOfService.AtLeastOnce);
In addition, if you’re using MQTT protocol, you need to set up the queues where the messages, both for
data and meta data, are listened to. This corresponds to the respective transport settings for the
DataSet Writer. See initBrokerTransportSettings for details.
DataSet Metadata
By setting DataSetMetaData information for the DataSet Reader, we can decode the received DataSet
message - even if only a subset of the DataSet specified in the Publisher side is included in the
19
message. DataSetMetaData can be retrieved automatically with Discovery mechanisms, as described in
Discovery functionality. However, if Discovery is not available but you know the message structure, you
can also manually construct a PubSubDataSetMetaDataConf object and set it for the DataSet Reader with
builder.setDataSetMetaData(dataSetMetaDataConf);
The samples don’t do this, because they rely on the Publisher samples to support metadata discovery.
PubSubSystemEvents
The DataSet Reader is configured to receive data or events in DataSet messages. You can use
TargetVariables to map data automatically to Nodes in the server’s own address space or you can just
listen to PubSubSystemEvents.
TargetVariables
The OPC UA server applications that are also Subscribers can also copy variable data automatically to
nodes in their own address space. The mapping between the VariableDataSet and Nodes is done via
TargetVariables.
20
public static final UaNodeId SAMPLE_TARGET_VARIABLE_ID = UaNodeId.from(SAMPLE_NAMESPACE,
"MyPubSubTargetVariable");
// The SamplePubSubPublisherServer is sending two Variables. We want to map the first one
// to a MyPubSubTargetVariable Node. For this, a single TargetVariable configuration is created,
// leaving the second received Variable unhandled.
return builder.build();
}
In this code example, only one TargetVariable is configured, meaning that the first variable in a DataSet
is assigned to be written to the Node MyPubSubTargetVarible. When you need to assign all variables of a
DataSet with specific Nodes, add more variables with addTargetVariables.
21