OPC UA
OPC UA (OPC Unified Architecture) is a platform independent, service-oriented protocol for industrial communication, released in 2008 as the successor to the COM-based OPC Classic specifications. It is spoken by a wide range of industrial automation devices, PLCs and SCADA systems - see Compatibility with OPC-UA Servers for the server implementations this driver has been tested against.
Supported Operations
| Name | Value | Description |
|---|---|---|
|
Java only. Reads the full range of supported PLC4X data types, in single and bulk requests. |
|
|
Java only. Writes the full range of supported PLC4X data types, in single and bulk requests. |
|
|
Java only. Subscriptions are possible on both an event and a cyclic basis - see OPC UA Data Change Notification and OPC UA Event Notification. |
|
|
Java only. Browses the nodes exposed by the connected server, starting from the standard
|
The Go driver works over an unencrypted channel only (security-policy=None), does not browse,
and does not chunk messages - a request or response that exceeds one chunk fails.
Connection String
The OPC UA driver 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.
Connection String Options
Name |
Type |
Default Value |
Required |
Description |
Name |
Opcua |
|||
Code |
|
|||
Maven Dependency |
<dependency> <groupId>org.apache.plc4x</groupId> <artifactId>plc4j-driver-opcua</artifactId> <version>1.1.0</version> </dependency> |
|||
Default Transport |
|
|||
Supported Transports |
|
|||
Config options: |
||||
|
STRING |
|||
|
STRING |
|||
|
STRING |
|||
|
BOOLEAN |
true |
Controls the feature of the discovery endpoint of an OPC UA server which every server |
|
|
STRING |
A username to authenticate to the OPCUA server with. |
||
|
STRING |
A password to authenticate to the OPCUA server with. |
||
|
STRING |
Basic256Sha256 |
The security policy applied to communication channel between driver and OPC UA server. |
|
|
STRING |
SIGN_ENCRYPT |
The security policy applied to messages exchanged after handshake phase. |
|
|
STRING |
The Keystore file used to lookup client certificate and its private key. |
||
|
STRING |
pkcs12 |
Keystore type used to access keystore and private key, defaults to PKCS (for Java 11+). |
|
|
STRING |
Java keystore password used to access keystore and private key. |
||
|
INT |
2048 |
Size in bits of the RSA key of the certificate the driver generates when no |
|
|
STRING |
Filesystem location where server certificate is located, supported formats are |
||
|
STRING |
The trust store file used to verify server certificates and its chain. |
||
|
STRING |
pkcs12 |
Keystore type used to access keystore and private key, defaults to PKCS (for Java 11+). |
|
|
STRING |
Password used to open trust store. |
||
|
BOOLEAN |
false |
Allows a username and password to be sent over a channel that neither signs nor encrypts. |
|
|
INT |
65536 |
Largest number of references the driver will collect for a single node while browsing. |
|
|
INT |
1000000 |
Largest number of nodes a single browse will expand. A browse walks whatever tree the |
|
|
INT |
64 |
How deep a browse will recurse into the node tree. Already-visited nodes are never |
|
|
BOOLEAN |
true |
Verifies the OPC UA server’s certificate. Set to false to trust any certificate the server presents. |
|
|
LONG |
3600000 |
Time for which negotiated secure channel, its keys and session remains open. Value in milliseconds, by default 60 minutes. |
|
|
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. |
|
|
LONG |
120000 |
Expiry time for opened secure session, value in milliseconds. Defaults to 2 minutes. |
|
|
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. |
|
|
LONG |
30000 |
Timeout for read/write/subscribe calls. Value in milliseconds. |
|
|
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. |
||
|
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. |
||
|
LONG |
1 |
Server-side queue depth per monitored item for subscriptions. 1 (default) keeps only |
|
Transport config options: |
||||
tcp |
||||
|
INT |
5000 |
Connection timeout in milliseconds. |
|
|
INT |
0 |
Socket read timeout in milliseconds. 0 means no timeout. |
|
|
INT |
0 |
Socket write timeout in milliseconds. 0 means no timeout. |
|
|
BOOLEAN |
true |
Enable TCP_NODELAY (disable Nagle’s algorithm). |
|
|
BOOLEAN |
false |
Enable SO_KEEPALIVE. |
|
|
INT |
81920 |
Send buffer size in bytes. 0 uses system default. |
|
|
INT |
81920 |
Receive buffer size in bytes. 0 uses system default. |
|
|
STRING |
Local address to bind to (optional). If not set, uses default. |
||
|
INT |
0 |
Local port to bind to (optional). 0 uses ephemeral port. |
|
Tag Addresses
Addressing is implemented in Java. The Go driver works over an unencrypted channel only and does not browse. See the protocol support matrix for what each implementation does.
General 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.
ns={namespace-index};[s|i|g|b]={Identifier};a=attributeId;{Data Type}
The a parameter, standing for the attributeId of an object, is optional and defaults to
Value (0x0d, i.e. 13). Its value can be given as either the numeric id or the OPC-UA
attribute name (case-sensitive).
The Data Type is also optional; when omitted, a default data type is selected based on the datatype of the returned value. For unsigned data types it needs to be given explicitly.
An address may end with a selection of an array’s elements - a single index, an inclusive range, and optionally the array’s declared lower bound, placed before the type. See Addressing arrays.
Note the identifiers s, i, b and g specify the format of the address, not the data type of
the returned value.
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)
Examples
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
The a attribute is required only for event subscriptions, which additionally make 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. See OPC UA Event Notification for the supported event fields.
The ;a=<attributeId> suffix is Java-only - the Go driver’s address pattern has no
;a= group (and no trailing |key=val,… tag-config group at all), so an address such as
ns=2;s=Foo;a=13 is accepted by Java but rejected by Go. This page documents the Java syntax;
consult the Go driver’s own source for what it accepts.
|
Notes and 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 the scope
of objects.
OPC-UA servers support subscriptions, which allow the amount of data exchanged between client and
server to be reduced. There are three primary subscription modes: Data Change Notification, Status
Change Notification and Event Notification. Apache PLC4X currently supports Data Change
Notification and Event Notification. Under the hood, subscriptions still require the client to
request data through a PublishRequest.
Protocol Details
Secure communication
The secure channel implementation within the Apache PLC4X project has been tested against
existing open source server implementations. This includes Eclipse Milo (all modes) as well as
the OPC Foundation .NET server (except Basic128Rsa15). Manual tests have proven that the driver
is able to communicate with OPC UA servers launched on PLCs as well as commercial simulators.
Depending on the configuration of the remote end, it may be necessary to prepare a client certificate. Preparation of a certificate is beyond the driver; however, when no client certificate is provided, one is 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 a self-signed certificate for use with both hardware and software based OPC-UA servers. Note that there are multiple appearances of certificates within the 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 from each other by the strength of the applied signature and encryption
algorithms. The driver is able to communicate with a single security mode at a time. In addition
to the security policy, it is possible to specify the message-security option, which indicates
the expected security settings after the initial handshake. By default, this option is set to
SIGN_ENCRYPT, which imposes high security settings and full encryption of exchanged message
payloads. When additional diagnostics are needed, payloads have to be traced through TRACE level
log entries. The SIGN mode makes it possible to browse packets in tools such as 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
Besides 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 the settings, the driver might or might not attempt to discover endpoints from the
remote server. When the discovery option is set to true, the driver looks up the server
certificate through a connection attempt. The discovery option also enables checks of server
endpoints for matching security settings.
Once initial discovery is completed and the driver finds an endpoint matching its security settings, it launches a second connection attempt which switches to the configured security mode.
Each connection attempt made by the driver uses the limits described in the connection string
options above; these declare the values accepted and expected by the client. Once the server
returns its own limits (Acknowledge for the supplied Hello call), the driver picks values from
these - taking the minimum of the local receive and remote send buffer sizes, and likewise the
minimum of the local send and remote receive buffer sizes.
Usual values for encoding.send-buffer-size and encoding.receive-buffer-size on PLC devices
remain at 8196 bytes.
| Due to a lack of complete implementation of negotiation and chunking logic, the OPC UA driver prior to the Apache PLC4X 0.11 release could supply calls exceeding server limits. |
OPC UA Data Change Notification
Data change notifications are created with a list of tags, after which the client needs to send publish requests. Upon each publish request, the server sends a response which includes the values of all tags for which a subscription was created. While the OPC-UA specification permits mutation of subscription contents, the PLC4X API does not allow that.
By default, Cyclic and Change of State subscription operations defined in the PLC4X client API
result in data change notifications.
OPC UA Event Notification
The third mode of subscription defined by the PLC4X API is Event Subscription. This kind of
subscription is available since PLC4X 0.13 and has a slightly different syntax, which brings more
complex data. OPC-UA events can be used to receive notifications of various kinds, which appear
when a specific situation happens. In other protocols this kind of behavior can function as alarms
or alerts.
In order to create an OPC-UA event subscription you need to:
-
define
a=EventNotifierora=12 -
specify event fields to retrieve through a tag config
The tag config key must match an OPC-UA event field. The tag config value is not used, so it
cannot be used to specify filter criteria for a field value. The fields that are supported are
defined in the 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.
A subscription event generated by the client upon receiving a notification contains an object
(PlcSTRUCT/Map) holding all requested fields. Note that Apache PLC4X only does basic
normalization of the data, so your application needs to take care of the actual processing of
event data.
Tag metadata
This driver supports tag metadata. Beyond standard metadata fields such as timestamp and
timestamp_source, it can provide the following keys:
-
opcua_quality -
opcua_server_timestamp -
opcua_source_timestamp
The appearance of these fields is conditional; they are provided only when they can be sourced from packets exchanged between client and server. This means that, depending on the operation conducted by the client (read/write/subscribe), the metadata will vary.
Compatibility with OPC-UA Servers
There are multiple OPC-UA server implementations, each with its own specifics, sometimes showing more detailed security handling or other edge cases buried in the specification. So far the Apache PLC4X OPC-UA client has been confirmed to work with the servers below (in chronological order of passed tests/confirmed compatibility):
-
version 0.13
-
Mitsubishi Electric MX OPC Server UA
-
version 0.12
-
Simatic OPC UA S7-1200 Basic
-
Simocode OPC UA server
-
versions prior to 0.12
More Information
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
See the OPC UA page at the OPC Foundation for more details.