OPC UA Client
This page describes how Connectware can act as an OPC UA client. Connectware can also act as an 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 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
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.
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 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 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):
resources:
spindleSpeed:
type: Cybus::Endpoint
properties:
protocol: Opcua
connection: !ref opcuaConnection
subscribe:
nodeId: 'ns=1;s=spindleSpeed'
publishInterval: 1000
samplingInterval: 100
maxNotificationsPerPublish: 100
powerConsumption:
type: Cybus::Endpoint
properties:
protocol: Opcua
connection: !ref opcuaConnection
subscribe:
nodeId: 'ns=1;s=powerConsumption'
publishInterval: 1000
maxNotificationsPerPublish: 50
samplingInterval: 1000
temperature:
type: Cybus::Endpoint
properties:
protocol: Opcua
connection: !ref opcuaConnection
subscribe:
nodeId: 'ns=1;s=temperature'
publishInterval: 15000
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.
Service Commissioning File Example
Basic 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:
---
description: >
Simple OPC UA connectivity example
metadata:
name: Simple OPC UA connectivity
version: 1.0.0
icon: https://www.cybus.io/wp-content/uploads/2019/03/Cybus-logo-Claim-lang.svg
provider: cybus
homepage: https://www.cybus.io
parameters:
opcuaHost:
type: string
description: OPC-UA Host
default: 172.17.0.1
opcuaPort:
type: integer
default: 4840
opcuaUser:
type: string
default: ''
opcuaPass:
type: string
default: ''
resources:
opcuaConnection:
type: Cybus::Connection
properties:
protocol: Opcua
connection:
host: !ref opcuaHost
port: !ref opcuaPort
username: !ref opcuaUser
password: !ref opcuaPass
serverStatusEndpoint:
type: Cybus::Endpoint
properties:
protocol: Opcua
connection: !ref opcuaConnection
subscribe:
nodeId: ns=0;i=2259
samplingInterval: 2000
Advanced Example
More complex example including an OPC UA server container from public docker hub:
---
description: >
Simulated OPC UA server
metadata:
name: Simulated OPC UA
version: 1.0.1
icon: https://www.cybus.io/wp-content/uploads/2019/03/Cybus-logo-Claim-lang.svg
provider: cybus
homepage: https://www.cybus.io
parameters:
opcuaHost:
type: string
description: OPC-UA Host
default: 172.17.0.1
opcuaPort:
type: integer
default: 50000
opcuaUser:
type: string
default: user
opcuaPass:
type: string
default: user
definitions:
CYBUS_MQTT_ROOT: cybus-factory/opcua
resources:
machineSimulatorContainer:
type: Cybus::Container
properties:
image: mcr.microsoft.com/iotedge/opc-plc
ports:
- !sub '${opcuaPort}:50000/tcp'
command:
- --unsecuretransport
- --autoaccept
- --defaultuser=user
- --defaultpassword=user
opcuaConnection:
type: Cybus::Connection
properties:
protocol: Opcua
connection:
host: !ref opcuaHost
port: !ref opcuaPort
username: !ref opcuaUser
password: !ref opcuaPass
currentTime:
type: Cybus::Endpoint
properties:
protocol: Opcua
connection: !ref opcuaConnection
topic: server/status/currenttime
subscribe:
nodeId: i=2258
dipData:
type: Cybus::Endpoint
properties:
protocol: Opcua
connection: !ref opcuaConnection
topic: dip-data
subscribe:
nodeId: ns=2;s=DipData
alternatingBool:
type: Cybus::Endpoint
properties:
protocol: Opcua
connection: !ref opcuaConnection
topic: alternating-bool
subscribe:
nodeId: ns=2;s=AlternatingBoolean
negativeTrendData:
type: Cybus::Endpoint
properties:
protocol: Opcua
connection: !ref opcuaConnection
topic: negative-trend-data
subscribe:
nodeId: ns=2;s=NegativeTrendData
positiveTrendData:
type: Cybus::Endpoint
properties:
protocol: Opcua
connection: !ref opcuaConnection
topic: positive-trend-data
subscribe:
nodeId: ns=2;s=PositiveTrendData
randomSignedInt:
type: Cybus::Endpoint
properties:
protocol: Opcua
connection: !ref opcuaConnection
topic: random-signed-int32
subscribe:
nodeId: ns=2;s=RandomSignedInt32
randomUnsignedInt:
type: Cybus::Endpoint
properties:
protocol: Opcua
connection: !ref opcuaConnection
topic: random-unsigned-int32
subscribe:
nodeId: ns=2;s=RandomUnsignedInt32
spikeData:
type: Cybus::Endpoint
properties:
protocol: Opcua
connection: !ref opcuaConnection
topic: spike-data
subscribe:
nodeId: ns=2;s=SpikeData
stepUp:
type: Cybus::Endpoint
properties:
protocol: Opcua
connection: !ref opcuaConnection
topic: step-up
subscribe:
nodeId: ns=2;s=StepUp
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:
resources:
myConnection:
type: Cybus::Connection
properties:
protocol: Opcua
connection:
host: !ref opcuaHost
port: !ref opcuaPort
options:
connectionStrategy:
initialDelay: 500
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.
---
description: >
Simple OPC UA connectivity example
metadata:
name: example for opcua connectivity
version: 1.0.0
icon: https://www.cybus.io/wp-content/uploads/2019/03/Cybus-logo-Claim-lang.svg
provider: cybus
homepage: https://www.cybus.io
parameters:
opcuaHost:
type: string
description: OPC-UA Host
default: 172.17.0.1
opcuaPort:
type: integer
default: 4840
opcuaUser:
type: string
default: ''
opcuaPass:
type: string
default: ''
resources:
opcuaConnection:
type: Cybus::Connection
properties:
protocol: Opcua
connection:
host: !ref opcuaHost
port: !ref opcuaPort
username: !ref opcuaUser
password: !ref opcuaPass
# Listen to all events from the server node
# A list of eventTypes can be selected
serverEventsEndpoint:
type: Cybus::Endpoint
properties:
protocol: Opcua
connection: !ref opcuaConnection
subscribe:
nodeId: i=2253
eventTypes:
- 'i=85'
fields:
- 'EventType'
- 'ReceiveTime'
- 'Message'
- 'SourceName'
- 'Severity'
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.
description: OPC UA Status Code Example
metadata:
name: OPC UA Status Code Example
version: 1.0.0
parameters:
ipAddress:
type: string
port:
type: integer
default: 4334
samplingIntervalMs:
type: number
default: 1000
publishIntervalMs:
type: number
default: 1000
resources:
opcuaConnection:
type: Cybus::Connection
properties:
protocol: Opcua
connection:
host: !ref ipAddress
port: !ref port
A_000:
type: Cybus::Endpoint
properties:
protocol: Opcua
connection: !ref opcuaConnection
subscribe:
nodeId: ns=1;s=0
samplingInterval: !ref samplingIntervalMs
publishInterval: !ref publishIntervalMs
rules:
- transform:
expression: |
{
"statusCode": {
"name": $context.raw.statusCode.name,
"value": $context.raw.statusCode.value,
"description": $context.raw.statusCode.description
},
"value": $.value,
"timestamp": $.timestamp
}
topic: A/000
Last updated
Was this helpful?