OPC UA Client

This page describes how the Connectware can act as an OPC UA client. The Connectware can also act as a OPC UA server.

OPC UA Subscriptions

OPC UA distinguishes between session, subscriptions and monitored items.

  • Each Connectware connection creates exactly one session in the OPC UA terminology, where the Connectware acts as a client towards the server.

  • Within one session, the set of data endpoints are grouped in subscriptions. A subscription carries parameters like publishInterval and maxNotificationsPerPublish so that it controls the data flow between server and client.

  • Within each subscription, the actual data endpoints (also called nodes) are subscribed as monitored items. The monitored items are configured by parameters like nodeId, attributeId, samplingInterval, so monitored items control the collection of the data by the server. Each network request for creating these can create one or multiple monitored items per request.

Connectware Subscriptions

The Connectware tries to abstract this complexity away, combining as many endpoints as possible into the same subscription, and also monitored items creation into the same request. This is done according to the following criteria:

  • Each OPC UA Cybus::Connection resource creates exactly one session

  • Within this session, all OPC UA Cybus::Endpoint resources with the same publishInterval property are combined into one subscription. This holds even across different service commissioning files using inter-service referencing, see here. Hence, enabling/disabling additional services with additional endpoints will add or remove those endpoints from the currently available subscription.

  • Every OPC UA Cybus::Endpoint resource corresponds to one monitored item

  • Within one subscription and within the same service commissioning file, all endpoints (= monitored items) with the same samplingInterval property are combined into one common creation request. This “create monitored items request” is working very efficiently also for thousands of monitored items.

Due to its importance, the relation of the OPC UA terminology to Connectware resources is listed once more:

Session

One Cybus::Connection is exactly one session. (OPC UA reference: 5.6.1 Session)

Subscription

All Cybus::Endpoints with the same publishInterval in the same connection, regardless of service commissioning file. (OPC UA reference: 5.13.1 Subscription)

Monitored items

All Cybus::Endpoints. (OPC UA reference: 5.12.1 MonitoredItem)

Create Monitored Items Request

The monitored items within one service, one connection, and with the same samplingInterval are combined into a single “create monitored items request” (OPC UA reference: 5.12.2 CreateMonitoredItems)

Subscription Limitations

Some OPC UA servers are known for imposing certain limits on the number of monitored items, either in total, or per subscription, or per request.

In particular, an embedded OPC UA server on a Siemens S7-1500 or S7-1200 PLC is known for certain restrictions, see System limits of OPC UA Server.

  • For example, the maximum number of monitored items within one “create monitored items request” might limited to e.g. 1000 nodes. This limit can even be looked up in the OPC UA node with nodeId ns=0;i=11714. On the Connectware side this limit must be taken into account by setting the property maxMonitoredItemsPerCall in the Cybus::Connection resource to the respective value. This will ensure to split larger requests so that all requests stay within this limit.

  • Also, some maximum number of monitored items in total might be configured in the TIAPortal project. Unfortunately it is not known how to look up this value except directly in TIAPortal. If such a value is set, it is not possible for the Connectware to create any larger number of endpoints than this value.

Regarding the created subscriptions: As of today, subscriptions are combined only by the publishInterval parameter. The remaining properties related to subscriptions are currently taken only from the first endpoint to be subscribed, while differing settings at subsequent endpoints are currently ignored. This concerns the following endpoint properties: requestedLifetimeCount, requestedMaxKeepAliveCount, maxNotificationsPerPublish, priority.

Example

This is an example configuration snippet with three endpoints (without the connection configuration):

 1resources:
 2  spindleSpeed:
 3    type: Cybus::Endpoint
 4    properties:
 5      protocol: Opcua
 6      connection: !ref opcuaConnection
 7      subscribe:
 8        nodeId: "ns=1;s=spindleSpeed"
 9        publishInterval: 1000
10        samplingInterval: 100
11        maxNotificationsPerPublish: 100
12  powerConsumption:
13    type: Cybus::Endpoint
14    properties:
15      protocol: Opcua
16      connection: !ref opcuaConnection
17      subscribe:
18        nodeId: "ns=1;s=powerConsumption"
19        publishInterval: 1000
20        maxNotificationsPerPublish: 50
21        samplingInterval: 1000
22  temperature:
23    type: Cybus::Endpoint
24    properties:
25      protocol: Opcua
26      connection: !ref opcuaConnection
27      subscribe:
28        nodeId: "ns=1;s=temperature"
29        publishInterval: 15000
30        samplingInterval: 15000

In the above example, two subscriptions will be created. One with publishInterval set to 1000ms and maxNotificationsPerPublish set to 100, the other one with publishInterval set to 15.000ms. The sampling of the individual source values will be set as expected by the specified samplingInterval property, but remember that OPC UA does not offer a fixed data sampling but rather applies a change-of-value filter to each particular data point automatically.

Security Settings

For production use, the connection to the OPC UA server should only be established using the security profile SignAndEncrypt. Any other security profile bears the risk that the communication between client and server can easily get manipulated or compromised. Per default, the built-in OPC UA server only allows connections with SignAndEncrypt security setting enabled (in the property securityModes). Please use your Connectware credentials when authenticating to the OPC UA server by Connectware username and password user token.

Connection Properties

host (string, required)

Hostname or IP of the OPC UA device

Example: "192.168.2.60"

port (integer, required)

Port of the OPC UA device

Default: 4840

Example: 4840

resourcePath (string)

Resource Path of the OPC UA server. Please note that this should be set to a valid value as some OPC-UA servers experience issues when connecting without one

Default: ""

Example: ""

username (string)

Username for OPC UA server

Example: "user"

password (string)

Password for OPC UA server

Example: "user"

timeout (integer)

Timeout, in milliseconds

Default: 1000

Examples: 1000, 2000

certificateFile (string)

Absolute path to the client certificate file

Example: "/connectware_certs/cybus_client.crt"

privateKeyFile (string)

Absolute path to the client private key file

Example: "/connectware_certs/cybus_client.key"

checkHostReachable (boolean)

Checks if a low level TCP connection can be made to the configured host and port

Default: false

maxMonitoredItemsPerCall (integer)

If non-zero, multiple monitoredItems (i.e. multiple endpoints/nodes) will be registered in groups of maximum size of this given number. This is a server configuration property that can be queried on the server at nodeId: ns=0;i=11714. If this value is zero, no maximum value is assumed and all endpoints will be registered in one call.

Default: 0

options (object)

Properties of the options object:

defaultSecureTokenLifetime (integer)

Lifetime of the secure token. Specified in milliseconds.

Default: 3600000

requestedSessionTimeout (integer)

OPC UA sessions may survive TCP connection breaks and are only deleted if no message from a client is received within the timeout period. Specified in milliseconds.

Default: 3600000

transportTimeout (integer)

Secure channel creating timeout, used before connecting or reconnecting to an OPC UA host. Has an impact on when a deviation is thrown as reconnect is first trying to connect to the host.

Default: 60000

endpointMustExist (boolean)

Specifies if the connection is strictly meant for the given endpoint. If false and the endpoint doesn’t exist, a reasonable default endpoint is automatically chosen.

Default: false

messageSecurityMode (string, enum)

This element must be one of the following enum values:

  • None

  • Sign

  • SignAndEncrypt

Default: "None"

securityPolicy (string, enum)

This element must be one of the following enum values:

  • Aes128_Sha256_RsaOaep

  • Basic128

  • Basic128Rsa15

  • Basic192

  • Basic192Rsa15

  • Basic256

  • Basic256Rsa15

  • Basic256Sha256

  • None

  • PubSub_Aes128_CTR

  • PubSub_Aes256_CTR

Default: "None"

watchInterval (integer)

For observing connection breaks, a connection watchdog runs regularly. Short intervals guarantee short notice on break but lead to higher load. Specified in milliseconds

Default: 30000

connectionStrategy (object)

If a connection attempt fails, retries will be performed with increasing delay (waiting time) in between. The following parameters control how these delays behave.

Properties of the connectionStrategy object:

maxRetry (integer)

Maximum number of connection retries in case of failure.

Default: 1000000000

initialDelay (integer)

Delay (waiting time) of the first connection retry (in milliseconds). For subsequent retries, the delay will be increased by a factor of 2, and also by a potential random increase according to the parameter randomisationFactor.

Default: 1000

maxDelay (integer)

Maximum delay (waiting time) to wait until the next retry (in milliseconds). The delay (waiting time) for any subsequent connection retry will not be larger than this value. Must be strictly greater than initialDelay.

Default: 30000

randomisationFactor (number)

This parameter controls added randomisation to the retry attempts. Must be a number between 0 and 1. If set to 0, retries will be performed with exponentially growing delay until maxDelay. If set to 1, a maximum noise will be added to the retry delays.

Default: 0

Additional restrictions:

  • Maximum: 1

Endpoint Properties

nodeId (string)

String of the exact location of the endpoint. Either nodeId or browsePath are required. A nodeId value is encoded as an xs:string with the syntax ns=<namespaceIndex>;<type>=<value>. The fields have the following meaning: <namespaceIndex> is an integer number such as 0 or 10, denoting the namespace. <type> is a flag that specifies the identifier type and can be: i for numeric (integer), s for string, g for guid, or b for opaque (byte string). <value> is the identifier itself, encoded as a string and in the format according to the identifierType. Examples of nodeIds: i=13 , ns=10;i=-1 , ns=10;s=Hello:World . See also https://reference.opcfoundation.org/v104/Core/docs/Part6/5.3.1 section 5.3.1.10

Examples: "i=2258", "ns=2;s=StepUp"

browsePath (string)

String containing the relative path to the endpoint. Either nodeId or browsePath are required.

Examples: "0:CurrentTime", "2:StepUp"

fields (array)

array of browsenames to variables defined in the Eventtype

The object is an array with all elements of the type string.

Additional restrictions:

  • Unique items: true

eventTypes (array)

lists node ids of OPC UA defined eventtypes in the server namespace as nodeId definition strings

The object is an array with all elements of the type string.

Additional restrictions:

  • Unique items: true

browsePathPrefix (string)

Optional, can be used to set a prefix for the browsePath. Both strings will be concatenated using a forward slash /.

publishInterval (integer)

Time interval (in milliseconds) in which the server should publish its node values within the subscription (but in any case the actual value updates are published usually only on change of values).

Default: 1000

samplingInterval (integer)

Time interval (in milliseconds) in which the published values from the server should be sampled for a particular node subscription. All nodes (=monitored items) with the same samplingInterval will be combined into one monitored item group.

Default: 1000

maxNotificationsPerPublish (integer)

Sets the maximum number of monitor notifications that are in a single publish message of the OPC UA subscription. Setting this to a lower value will lead to more network traffic.

Default: 100

priority (integer)

Default: 10

requestedLifetimeCount (integer)

Default: 30

requestedMaxKeepAliveCount (integer)

Default: 10

retryMonitorTimeout (integer)

Default: 300000

Additional restrictions:

  • Minimum: 10000

Example Commissioning Files

Simple example

This is a simple OPC UA connectivity example that only subscribes to the “Server Status” node of an OPC UA server. The proposed node (endpoint) can also be used if the server would otherwise close the connection, which has been observed for some specific versions of OPC UA servers on a S7 PLC.

The example will need some OPC UA server available in your network:

 1---
 2description: >
 3
 4  Simple OPC UA connectivity example
 5
 6metadata:
 7
 8  name: Simple OPC UA connectivity
 9  version: 1.0.0
10  icon: https://www.cybus.io/wp-content/uploads/2019/03/Cybus-logo-Claim-lang.svg
11  provider: cybus
12  homepage: https://www.cybus.io
13
14parameters:
15
16  opcuaHost:
17    type: string
18    description: OPC-UA Host
19    default: 172.17.0.1
20
21  opcuaPort:
22    type: integer
23    default: 4840
24
25  opcuaUser:
26    type: string
27    default: ''
28
29  opcuaPass:
30    type: string
31    default: ''
32
33resources:
34
35  opcuaConnection:
36    type: Cybus::Connection
37    properties:
38      protocol: Opcua
39      connection:
40        host: !ref opcuaHost
41        port: !ref opcuaPort
42        username: !ref opcuaUser
43        password: !ref opcuaPass
44
45  serverStatusEndpoint:
46    type: Cybus::Endpoint
47    properties:
48      protocol: Opcua
49      connection: !ref opcuaConnection
50      subscribe:
51        nodeId: ns=0;i=2259
52        samplingInterval: 2000

Download: opcua-simple-example.yml

More complex example

More complex example including an OPC UA server container from public docker hub:

  1---
  2description: >
  3
  4  Simulated OPC UA server
  5
  6metadata:
  7
  8  name: Simulated OPC UA
  9  version: 1.0.1
 10  icon: https://www.cybus.io/wp-content/uploads/2019/03/Cybus-logo-Claim-lang.svg
 11  provider: cybus
 12  homepage: https://www.cybus.io
 13
 14parameters:
 15
 16  opcuaHost:
 17    type: string
 18    description: OPC-UA Host
 19    default: 172.17.0.1
 20
 21  opcuaPort:
 22    type: integer
 23    default: 50000
 24
 25  opcuaUser:
 26    type: string
 27    default: user
 28
 29  opcuaPass:
 30    type: string
 31    default: user
 32
 33definitions:
 34  CYBUS_MQTT_ROOT: cybus-factory/opcua
 35
 36resources:
 37
 38  machineSimulatorContainer:
 39    type: Cybus::Container
 40    properties:
 41      image: mcr.microsoft.com/iotedge/opc-plc
 42      ports:
 43        - !sub '${opcuaPort}:50000/tcp'
 44      command:
 45        - --unsecuretransport
 46        - --autoaccept
 47        - --defaultuser=user
 48        - --defaultpassword=user
 49
 50
 51  opcuaConnection:
 52    type: Cybus::Connection
 53    properties:
 54      protocol: Opcua
 55      connection:
 56        host: !ref opcuaHost
 57        port: !ref opcuaPort
 58        username: !ref opcuaUser
 59        password: !ref opcuaPass
 60
 61  currentTime:
 62    type: Cybus::Endpoint
 63    properties:
 64      protocol: Opcua
 65      connection: !ref opcuaConnection
 66      topic: server/status/currenttime
 67      subscribe:
 68        nodeId: i=2258
 69
 70  dipData:
 71    type: Cybus::Endpoint
 72    properties:
 73      protocol: Opcua
 74      connection: !ref opcuaConnection
 75      topic: dip-data
 76      subscribe:
 77        nodeId: ns=2;s=DipData
 78
 79  alternatingBool:
 80    type: Cybus::Endpoint
 81    properties:
 82      protocol: Opcua
 83      connection: !ref opcuaConnection
 84      topic: alternating-bool
 85      subscribe:
 86        nodeId: ns=2;s=AlternatingBoolean
 87
 88  negativeTrendData:
 89    type: Cybus::Endpoint
 90    properties:
 91      protocol: Opcua
 92      connection: !ref opcuaConnection
 93      topic: negative-trend-data
 94      subscribe:
 95        nodeId: ns=2;s=NegativeTrendData
 96
 97  positiveTrendData:
 98    type: Cybus::Endpoint
 99    properties:
100      protocol: Opcua
101      connection: !ref opcuaConnection
102      topic: positive-trend-data
103      subscribe:
104        nodeId: ns=2;s=PositiveTrendData
105
106  randomSignedInt:
107    type: Cybus::Endpoint
108    properties:
109      protocol: Opcua
110      connection: !ref opcuaConnection
111      topic: random-signed-int32
112      subscribe:
113        nodeId: ns=2;s=RandomSignedInt32
114
115  randomUnsignedInt:
116    type: Cybus::Endpoint
117    properties:
118      protocol: Opcua
119      connection: !ref opcuaConnection
120      topic: random-unsigned-int32
121      subscribe:
122        nodeId: ns=2;s=RandomUnsignedInt32
123
124  spikeData:
125    type: Cybus::Endpoint
126    properties:
127      protocol: Opcua
128      connection: !ref opcuaConnection
129      topic: spike-data
130      subscribe:
131        nodeId: ns=2;s=SpikeData
132
133  stepUp:
134    type: Cybus::Endpoint
135    properties:
136      protocol: Opcua
137      connection: !ref opcuaConnection
138      topic: step-up
139      subscribe:
140        nodeId: ns=2;s=StepUp

Download: opcua-example.yml

Output Format On Reading

If data is read from OPC UA the output will be provided as JSON object with value and timestamp.

The given timestamp is the OPC UA “Source Timestamp” which was set on the data source side, see https://reference.opcfoundation.org/v104/Core/docs/Part4/7.7.3/

{
  "timestamp": "<unix timestamp in ms>",
  "value": "value"
}

Note: If 64-bit integers are being used (which are unsupported in JSON, but are supported in Javascript by the BigInt class), the value is returned as a string that contains the decimal number.

Output Format On Writing

When data is written to an OPC-UA endpoint, you will get the result of the operation over the /res topic like this:

{
  "id": 29194,
  "timestamp":1629351968526,
  "result": {
    "value":0
  }
}

Input Format

If data is written to OPC UA it must be provided as JSON object

{
  "value": "<value>"
}

Reconnection Behaviour

In OPC UA connections – just with any network connections – it can happen that the connection is lost. In that case the Connectware’s OpcuaConnection will automatically switch into reconnecting state and repeatedly try to re-establish the connection. The exact behaviour on how often this is tried can be controlled by the optional connectionStrategy properties, see Connection Properties. The important property is maxDelay which sets the maximum waiting time (delay) between consecutive re-tries, in milliseconds. The waiting time will start with the value initialDelay, then be increased step by step, until the maxDelay value.

Example with initially 500ms waiting time, increasing up to 10 seconds:

 1resources:
 2  myConnection:
 3    type: Cybus::Connection
 4    properties:
 5      protocol: Opcua
 6      connection:
 7        host: !ref opcuaHost
 8        port: !ref opcuaPort
 9        options:
10          connectionStrategy:
11            initialDelay: 500
12            maxDelay: 10000

For further details see also the documentation of the internally used package backoff, https://www.npmjs.com/package/backoff

Events for OPC UA

Event subscriptions can be created in the connectware by adding the properties fields and eventTypes to the Cybus::Endpoint resource as shown in the example below.

The names for the fields should be Qualified Names. Often, this will require the field name to also contain a namespace identifier, for example 4:MyQualifiedName.3:SubitemQualifiedName. Also, the field names often additionally need a sub-type, which can be specified using a dot notation after the name.

 1---
 2description: >
 3
 4  Simple OPC UA connectivity example
 5
 6metadata:
 7
 8  name: example for opcua connectivity
 9  version: 1.0.0
10  icon: https://www.cybus.io/wp-content/uploads/2019/03/Cybus-logo-Claim-lang.svg
11  provider: cybus
12  homepage: https://www.cybus.io
13
14parameters:
15
16  opcuaHost:
17    type: string
18    description: OPC-UA Host
19    default: 172.17.0.1
20
21  opcuaPort:
22    type: integer
23    default: 4840
24
25  opcuaUser:
26    type: string
27    default: ''
28
29  opcuaPass:
30    type: string
31    default: ''
32
33resources:
34
35  opcuaConnection:
36    type: Cybus::Connection
37    properties:
38      protocol: Opcua
39      connection:
40        host: !ref opcuaHost
41        port: !ref opcuaPort
42        username: !ref opcuaUser
43        password: !ref opcuaPass
44
45  # Listen to all events from the server node
46  # A list of eventTypes can be selected
47  serverEventsEndpoint:
48    type: Cybus::Endpoint
49    properties:
50      protocol: Opcua
51      connection: !ref opcuaConnection
52      subscribe:
53        nodeId: i=2253
54        eventTypes:
55          - 'i=85'
56        fields:
57          - "EventType"
58          - "ReceiveTime"
59          - "Message"
60          - "SourceName"
61          - "Severity"

Download: opcua-events-example.yml

Accessing Status Codes for Values

The quality of a data value in OPC UA is represented by predefined status codes. The `statusCode` is transferred to the `$context` object and can be retrieved within the rule engine of a Cybus::Endpoint via `$context.raw.statusCode` as shown in the example below.

 1description: OPC UA Status Code Example
 2metadata:
 3  name: OPC UA Status Code Example
 4  version: 1.0.0
 5parameters:
 6  ipAddress:
 7    type: string
 8  port:
 9    type: integer
10    default: 4334
11  samplingIntervalMs:
12    type: number
13    default: 1000
14  publishIntervalMs:
15    type: number
16    default: 1000
17resources:
18  opcuaConnection:
19    type: Cybus::Connection
20    properties:
21      protocol: Opcua
22      connection:
23        host: !ref ipAddress
24        port: !ref port
25
26  A_000:
27    type: Cybus::Endpoint
28    properties:
29      protocol: Opcua
30      connection: !ref opcuaConnection      
31      subscribe:
32        nodeId: ns=1;s=0
33        samplingInterval: !ref samplingIntervalMs
34        publishInterval: !ref publishIntervalMs
35      rules:
36        - transform: 
37            expression: |
38              { 
39                "statusCode": {
40                  "name": $context.raw.statusCode.name,
41                  "value": $context.raw.statusCode.value,
42                  "description": $context.raw.statusCode.description
43                },
44                "value": $.value,
45                "timestamp": $.timestamp
46              }  
47      topic: A/000

Download: opcua-statusCodes-example.yml