OPC UA

Connection String Options

Array selection uses the shared notation - a single index, an inclusive range, and optionally the array’s declared lower bound, placed before the type. See Addressing arrays.

Name

Type

Default Value

Required

Description

Name

Opcua

Code

opcua

Maven Dependency

<dependency>
  <groupId>org.apache.plc4x</groupId>
  <artifactId>plc4j-driver-opcua</artifactId>
  <version>1.0.0</version>
</dependency>

Default Transport

tcp

Supported Transports

  • tcp

Config options:

protocol-code

STRING

transport-code

STRING

transport-config

STRING

discovery

BOOLEAN

true

Controls the feature of the discovery endpoint of an OPC UA server which every server
will propagate over an '<address>/discovery' endpoint. The most common issue here is that most servers are not correctly
configured and propagate the wrong external IP or URL address. If that is the case you can disable the discovery by
configuring it with a false value.

The discovery phase is always conducted using NONE security policy.

username

STRING

A username to authenticate to the OPCUA server with.

password

STRING

A password to authenticate to the OPCUA server with.

security-policy

STRING

Basic256Sha256

The security policy applied to communication channel between driver and OPC UA server.
Possible options are NONE, Basic128Rsa15, Basic256, Basic256Sha256, Aes128_Sha256_RsaOaep, Aes256_Sha256_RsaPss.
NONE means the channel is neither signed nor encrypted, so anything on the path can read and
change what is exchanged; it also leaves the server unauthenticated. A policy that signs and
encrypts needs a trust anchor for the server’s certificate - see tls.trust-store and
server-certificate-file.

message-security

STRING

SIGN_ENCRYPT

The security policy applied to messages exchanged after handshake phase.
Possible options are NONE, SIGN, SIGN_ENCRYPT.
This option is effective only when securityPolicy turns encryption (anything beyond NONE).

tls.keystore

STRING

The Keystore file used to lookup client certificate and its private key.

tls.keystore-type

STRING

pkcs12

Keystore type used to access keystore and private key, defaults to PKCS (for Java 11+).
Possible values are between others jks, pkcs11, dks, jceks.

tls.keystore-password

STRING

Java keystore password used to access keystore and private key.

generated-key-size

INT

2048

Size in bits of the RSA key of the certificate the driver generates when no tls.keystore is configured. It is ignored when a key store is supplied, as the key then comes from that store. Some servers require a minimum size; 4096 is a common requirement.

server-certificate-file

STRING

Filesystem location where server certificate is located, supported formats are DER and PEM.

tls.trust-store

STRING

The trust store file used to verify server certificates and its chain.

tls.trust-store-type

STRING

pkcs12

Keystore type used to access keystore and private key, defaults to PKCS (for Java 11+).
Possible values are between others jks, pkcs11, dks, jceks.

tls.trust-store-password

STRING

Password used to open trust store.

allow-insecure-credentials

BOOLEAN

false

Allows a username and password to be sent over a channel that neither signs nor encrypts.
Without this, a connection configured with credentials over an unprotected channel fails rather
than putting the password on the wire where anything on the path can read it. Setting it warns.

browse-max-references-per-node

INT

65536

Largest number of references the driver will collect for a single node while browsing.
A Browse is answered in batches, each batch handing back a continuation point for the next, and
the driver follows them until the server stops. A server that never stops would otherwise grow
the collected list without limit. The same number is asked of the server as its per-node maximum,
so it can stop before the driver has to. Set to 0 for no limit.

browse-max-total-nodes

INT

1000000

Largest number of nodes a single browse will expand. A browse walks whatever tree the
server describes, and the driver has no way to know how large that is before walking it, so this
bounds a tree that turns out to be unreasonable - or endless, if the server keeps naming nodes it
has not named before. Set to 0 for no limit.

browse-max-depth

INT

64

How deep a browse will recurse into the node tree. Already-visited nodes are never
expanded twice, so a reference cycle terminates on its own, but a server naming a fresh node at
every level describes a tree with no bottom. Set to 0 for no limit.

tls.verify

BOOLEAN

true

Verifies the OPC UA server’s certificate. Set to false to trust any certificate the server presents.
Turning it off is UNSAFE: it leaves the connection open to man-in-the-middle attacks and defeats the
integrity/authenticity guarantees of a signed secure channel. Only do so for local testing. In production,
establish trust with tls.trust-store (chain validation) or server-certificate-file (certificate
pinning) instead.

channel-lifetime-ms

LONG

3600000

Time for which negotiated secure channel, its keys and session remains open. Value in milliseconds, by default 60 minutes.

min-channel-lifetime-ms

LONG

5000

Shortest secure-channel lifetime this client will work with, in milliseconds. A server may revise the requested channel-lifetime-ms downwards, and the renewal schedule is derived from whatever it returns - so a very short lifetime means very frequent renewals, on an executor shared by every OPC UA connection in this JVM. A server-supplied lifetime below this value is raised to it and a warning is logged. If a server genuinely needs faster renewal, lower this value to accept it; the default is far below any lifetime a conforming server negotiates.

session-timeout-ms

LONG

120000

Expiry time for opened secure session, value in milliseconds. Defaults to 2 minutes.

handshake-timeout-ms

LONG

60000

Timeout for all negotiation steps prior acceptance of application level operations - this timeout applies to open secure channel, create session and close calls. Defaults to 60 seconds.

request-timeout-ms

LONG

30000

Timeout for read/write/subscribe calls. Value in milliseconds.

endpoint-host

STRING

Endpoint host used to establish secure channel connection. Used when client made connection to server which advertises different hostname than one used for network connection.

endpoint-port

INT

Endpoint port used to establish secure channel. Used when client made connection to server which advertises different port number than one used for network connection.

subscription-queue-size

LONG

1

Server-side queue depth per monitored item for subscriptions. 1 (default) keeps only
the latest value between publishes; higher values retain intermediate changes for fast
change-of-state tags, whose sampling rate can exceed the publishing (cycle) interval.

Transport config options:

tcp

tcp.connect-timeout-ms

INT

5000

tcp.read-timeout-ms

INT

0

tcp.write-timeout-ms

INT

0

tcp.no-delay

BOOLEAN

true

tcp.keep-alive

BOOLEAN

false

tcp.send-buffer-size

INT

81920

tcp.receive-buffer-size

INT

81920

tcp.local-address

STRING

tcp.local-port

INT

0

Name

Value

Description

Supported Operations

read

The read interface allows for reading the full range of supported PLC4X data types in single and bulk requests

write

The write interface allows for writing the full range of supported PLC4X data types in single and bulk requests

subscribe

Subscriptions are possible with events on event- and cyclic-basis

Connection String

The OPC UA drivers uses the connection string

opcua:{transport}://{ip-address}:{port}?{options}

An example of this connection string would be:-

opcua:tcp://127.0.0.1:12686?discovery=true&username=admin&password=password

Note the transport, port and options fields are optional.

Secure communication

The secure channel implementation within Apache PLC4X project have been tested against existing open source server implementations. This includes Eclipse Milo (all modes) as well as OPC Foundation .NET server (except Basic128Rsa15). Manual tests proven that driver is able to communicate with OPC UA server launched on PLCs as well as commercial simulators.

Depending on actual configuration of remote end there might be necessity to prepare client certificate. Preparation of certificate is beyond driver, however in case when no client certificate is provided, it will be auto-generated to establish a session. Please follow our tutorial on provisioning of client private key and certificate. By following it you will be able to create self-signed certificate for use with both hardware and software based OPC-UA servers. Please note that there are multiple appearances of certificates within specification. There is the application instance certificate securing the communication channel, which is provided through the keystore options described below, and there is a X509 certificate identifying the user, which is supplied separately - see User authentication.

The security modes differ between themselves by strength of applied signature and encryption algorithms. Driver is able to communicate with single security mode at the time. Additionally, to security policy it is possible to specify message-security option which indicates expected security settings after initial handshake. By default, this option is set to SIGN_ENCRYPT which imposes high security settings and full encryption of exchanged message payloads. In case when additional diagnostics is needed payloads has to be traced through TRACE level log entries. The SIGN mode gives possibility o browse packets in tools such wireshark.

Certificate verification

The OPC UA specification defines its own procedures for certificate validation.

The driver verifies the server certificate by default and fails closed: if no trust anchor is configured, the server certificate is rejected and the connection fails. Configure one of:

  • tls.trust-store - validate the certificate chain against the given trust store. The acceptance relies on regular TLS checks (expiry date, certificate path etc.); it does not validate OPC UA specific parts such as the application URI.

  • server-certificate-file - pin trust to exactly that certificate. Only the certificate read from the configured file is trusted; a certificate learned over the unauthenticated discovery channel is never used as a trust anchor.

tls.verify=false disables server certificate verification altogether. This makes the connection vulnerable to man-in-the-middle attacks and is intended for local testing only.

Client certificate

If no tls.keystore is configured, the driver generates a self-signed application instance certificate for the session. It is a 2048 bit RSA key signed with SHA-256; use generated-key-size to ask for a larger key when the server demands one:

opcua:tcp://127.0.0.1:12686?security-policy=Basic256Sha256&message-security=SIGN_ENCRYPT&generated-key-size=4096

A generated certificate is fresh for every connection, so a server that keeps a trust list will reject it until it is trusted there. For anything beyond a first connection attempt, supply your own certificate through tls.keystore instead - see the client certificate tutorial.

User authentication

Beside securing the channel, OPC UA authenticates the user of a session. The driver supports all three token types the specification defines: anonymous, username/password and a X509 user certificate.

Anonymous access is what you get when no credentials are supplied. A username and password can come from the connection string:

opcua:tcp://127.0.0.1:12686?username=admin&password=password

or, together with the certificate variant, from a PlcAuthentication handed to the driver manager. The object passed to getConnection decides which token type the driver asks the server for, and credentials given this way take precedence over those in the connection string:

PlcConnection connection = driverManager.getConnection(
    "opcua:tcp://127.0.0.1:12686?security-policy=Basic256Sha256",
    new PlcUsernamePasswordAuthentication("admin", "password"));

User certificate

To authenticate as a user with a X509 certificate, pass a PlcCertificateAuthentication carrying the key store that holds the user certificate and its private key:

KeyStore keyStore = KeyStore.getInstance("PKCS12");
try (InputStream in = new FileInputStream("user.p12")) {
    keyStore.load(in, "changeit".toCharArray());
}

PlcConnection connection = driverManager.getConnection(
    "opcua:tcp://127.0.0.1:12686?security-policy=Basic256Sha256",
    new PlcCertificateAuthentication(keyStore, "changeit".toCharArray()));

The driver takes the first key store entry holding a private key. When the store holds more than one identity, name the one to use:

new PlcCertificateAuthentication(keyStore, "changeit".toCharArray(), "operator");

The certificate has to use an RSA key, and the server has to trust it - servers usually keep a separate trust list for user certificates, distinct from the one for application instance certificates.

This is not the same certificate as the one configured through tls.keystore. That one is the application instance certificate: it secures the channel and says which installation is talking, whereas the user certificate says who is talking. Nothing stops you from using the same certificate for both, provided the server trusts it for both purposes.

The driver proves possession of the private key by signing the server certificate and server nonce, using the security policy the server declares for its certificate user token policy. A server that offers certificate authentication with a security policy of None leaves no algorithm to sign with; the driver refuses such an endpoint rather than sending an unverifiable token.

Negotiation procedure

Depending on settings driver might or might not attempt to discover endpoints from remote server. In case when discovery option is set to true driver will look up server certificate through connection attempt. The discovery option also enables checks of server endpoints for matching security settings.

Once initial discovery is completed and driver finds endpoint matching its security settings it will launch second connection attempt which will switch to configured security mode.

Each connection attempt made by driver attempt to use limits described in table above. Role of these options is declaration of values accepted and expected by client. Once server returns its limits (Acknowledge for supplied Hello call) driver picks values from these. The only one note is that driver takes minimum of local receive and remote send buffer size. It does same with local send and remote receive buffer.

Usual values of encoding.send-buffer-size and encoding.receive-buffer-size PLC devices remain at 8196 bytes.

Due to lack of complete implementation of negotiation and chunking logic the OPC UA driver prior Apache PLC4X 0.11 release could supply calls exceeding server limits.

Address Format

To read, write and subscribe to data, the OPC UA driver uses the variable declaration string of the OPC UA server it is connecting to. It includes the namespace(ns) of the hierarchy tree followed by the type of identifier string(s), numeric(i), binary(b) or guid(g) and its address. The Data Type is an optional field, if it is not included a default data type is selected based on the datatype of the returned value. For Unsigned data types it needs to be included otherwise.

ns={namespace-index};[s|i|g|b]={Identifier};a=attributeId;{Data Type}

The a parameter which stands for attributeId of an object is optional, and by default it is assumed to be Value 13 (0x0d). Value of this parameter can be specified using numeric value or OPC-UA attribute name (case-sensitive).

Data Types

The following data types are supported

  • BOOL (boolean)

  • SINT (int 8)

  • USINT (uint 8)

  • BYTE (uint 8)

  • INT (int 16)

  • UINT (uint 16)

  • DINT (int 32)

  • UDINT (uint 32)

  • LINT (int 64)

  • ULINT (uint 64)

  • REAL (float)

  • LREAL (double)

  • CHAR (char)

  • WCHAR (2 byte char)

  • STRING (utf-8)

  • TIME (duration, milliseconds)

  • LTIME (duration, nanoseconds)

  • DATE (date)

  • LDATE (date)

  • TIME_OF_DAY (time of day)

  • LTIME_OF_DAY (time of day)

  • DATE_AND_TIME (date and time)

  • LDATE_AND_TIME (date and time)

Example of a valid OPC UA address:

The following are examples of valid addresses

String address:

ns=2;s=HelloWorld/ScalarTypes/Boolean
ns=2;s=HelloWorld/ScalarTypes/Boolean;BOOL
ns=2;s=HelloWorld/ScalarTypes/Boolean;a=Value;BOOL

Numeric address

ns=1;i=1337
ns=1;i=1337;DINT
ns=1;i=1337;a=Value;DINT

GUID address:

ns=2;g=09087e75-8e5e-499b-954f-f2a8624db28a
ns=2;g=09087e75-8e5e-499b-954f-f2a8624db28a;REAL
ns=2;g=09087e75-8e5e-499b-954f-f2a8624db28a;a=Value;REAL

Event Subscription:

ns=0;i=2253;a=EventNotifier;BOOL|EventId=x,EventType=x,Severity=x,Time=x,Message=x

Note the Identifiers s,i,b and g specify the format of the address not the data type of the returned value. The a attribute is required only for event subscriptions which additionally makes use of tag config. Tag config is appended after a | as a comma-separated key=value list naming the event fields to request. The values are placeholders and are ignored, but they must be non-empty and alphanumeric, and a ;{Data Type} segment has to precede the | - otherwise the config is silently dropped.

Some useful tips

The namespace (e.g. ns=2) within the address is specific to the server you are connecting to. Objects appearing in namespaces can, and will vary, as namespaces are used to separate scope of objects.

OPC-UA servers support subscriptions which allow to reduce amount of data exchanged between client and server. There are three primary subscription modes: Data Change Notification, Status Change Notification and Event Notification. Currently, Apache PLC4X client supports Data Change Notification and Event Notification.

Under the hood subscriptions still require client to request data though PublishRequest.

OPC UA Data Change Notification

Data change notifications are created with list of tags, after which client need to send publish requests. Upon each publish request server will send response which will include values of all tag for which subscription was created. While OPC-UA specification permits mutation of subscription contents, PLC4X API does not allow that.

By default, Cyclic and Change of State subscriptions operations defined in PLC4X client API result in data change notifications.

OPC UA Event Notification

Third mode of subscription defined by PLC4X API is Event Subscription. This kind of subscription is available since PLC4X 0.13 and have slightly different syntax, which brings more complex data. OPC-UA events can be used to receive notifications of various kinds which appear when specific situation happens. In other protocols this kind of behavior can function as alarms or alerts.

In order to create OPC-UA event subscription you need to:

  • define a=EventNotifier or a=12

  • specify event fields to retrieve through a tag config

The tag config key must match OPC-UA event field. The tag config value is not used, thus it can not be used to specify filter criteria for field value. Fields which are supported are defined in OPC UA BaseEventType:

  • EventId

  • EventType

  • SourceNode

  • SourceName

  • Time

  • ReceiveTime

  • LocalTime

  • Message

  • Severity

Example syntax: ns=0;i=2253;a=EventNotifier;BOOL|EventId=x,EventType=x,Severity=x,Time=x,Message=x.

Subscription event generated by client upon receiving notification will contain an object (PlcSTRUCT/Map) which will contain all requested fields. Please note that Apache PLC4X does only basic normalization of data, thus your application need to take care of actual processing of event data.

Tag metadata

This driver supports tag metadata. Beyond standard metadata fields such timestamp and timestamp_source it can provide following keys:

  • opcua_quality

  • opcua_server_timestamp

  • opcua_source_timestamp

Appearance of these fields is conditional, they are provided only when it can be sourced from packets exchanged between client and server. This means that depending on operation conducted by client (read/write/subscribe) metadata will vary.

Compatibility with OPC-UA Servers

There are multiple OPC-UA server implementations. Each of it have its own specifics, sometimes showing up more detailed security handling or further edge case buried in specification. So far Apache PLC4X OPC-UA client have been confirmed to be working with below servers (order in chronology of passed tests/confirmed compatibility):

More details on OPC UA

OPC UA The OPC Unified Architecture (UA), released in 2008, is a platform independent service-oriented architecture that integrates all the functionality of the individual OPC Classic specifications into one extensible framework.

This multi-layered approach accomplishes the original design specification goals of:

  • Functional equivalence: all COM OPC Classic specifications are mapped to UA

  • Platform independence: from an embedded micro-controller to cloud-based infrastructure

  • Secure: encryption, authentication, and auditing

  • Extensible: ability to add new features without affecting existing applications

  • Comprehensive information modeling: for defining complex information