Files

6.3 KiB

OPC UA Client (Gateway) Driver

Getting-started guide for the OPC UA Client driver. This is the short path — for the full per-field spec read docs/v2/driver-specs.md §8, and for the test-harness map read OpcUaClient-Test-Fixture.md.

What it talks to

A remote OPC UA server. This driver runs the opposite direction from the usual "server exposes PLC data" flow: it acts as an OPC UA client, opens a Session against an upstream server, and re-exposes that server's address space through the local OtOpcUa server. Browse, read, write, subscribe, alarm, and history calls are passed through to the upstream endpoint.

It is built on the OPC Foundation UA .NET Standard reference SDK and runs in-process in the OtOpcUa server's .NET 10 AnyCPU host — pure managed, no out-of-process isolation.

There is no standalone driver CLI for the OPC UA Client driver. To exercise a remote OPC UA endpoint by hand, point the general-purpose Client CLI at it directly.

Project split

Project Target Role
src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient/ net10.0 In-process driver — session lifetime, read / write / subscribe / alarm / history passthrough
src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser/ net10.0 IDriverBrowser — live address-picker browse used by the AdminUI
src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Contracts/ net10.0 Config records + enums bound from DriverConfig JSON

Minimum deployment

"Drivers": {
  "upstream-1": {
    "Type": "OpcUaClient",
    "Config": {
      "EndpointUrl": "opc.tcp://plc.internal:4840",
      "SecurityPolicy": "None",
      "SecurityMode": "None",
      "AuthType": "Anonymous",
      "TargetNamespaceKind": "Equipment"
    }
  }
}

EndpointUrls (a list) takes precedence over the single-URL EndpointUrl and provides ordered failover — the driver tries each candidate in turn at init and on session drop, and the first to connect wins (e.g. a hot-standby pair on 4840 / 4841). See src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Contracts/OpcUaClientDriverOptions.cs for every field (security policy/mode, auth type, session timeout, keep-alive, reconnect period, browse root, node/depth caps).

Session lifetime

A single Session per driver instance; subscriptions multiplex onto it. The SDK reconnect handler takes the session down and brings it back on remote-server restart, re-sending subscriptions on reconnect so monitored-item handles don't dangle. Stored NodeIds embed the server-stable namespace URI (not the session-relative ns=N index) so a remote namespace-table reorder across a restart doesn't silently re-point references at the wrong namespace.

Namespace assignment

This is the only driver that gateways into either namespace kind, decided per instance via TargetNamespaceKind:

  • Equipment — the remote server exposes raw equipment data; remote browse paths are remapped to UNS via a required UnsMappingTable.
  • SystemPlatform — the remote server exposes processed/derived data; the remote hierarchy is preserved with no UNS conversion (and the mapping table must be empty).

The choice is enforced at startup so a misconfiguration fails draft validation rather than surfacing as a runtime surprise.

Capability surface

OpcUaClientDriver : IDriver, ITagDiscovery, IReadable, IWritable, ISubscribable, IHostConnectivityProbe, IAlarmSource, IHistoryProvider (src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient/OpcUaClientDriver.cs:31).

Capability Path Notes
ITagDiscovery DiscoverAsync (recursive browse) Mirrors the upstream tree from BrowseRoot (default ObjectsFolder i=85), bounded by MaxDiscoveredNodes / MaxBrowseDepth
IReadable ReadAsyncSession.ReadAsync Upstream StatusCodes pass through verbatim (cascading-quality rule)
IWritable WriteAsyncSession.WriteAsync Passthrough write
ISubscribable native OPC UA subscriptions / monitored items The remote server pushes data changes
IHostConnectivityProbe session keep-alive Host key is the endpoint URL actually connected to after the failover sweep
IAlarmSource SubscribeAlarmsAsync (EventFilter) + AcknowledgeAsync Subscribes to upstream alarm/condition events and forwards acks
IHistoryProvider ReadRawAsync / ReadProcessedAsync / ReadAtTimeAsyncSession.HistoryReadAsync Unique to this driver — passthrough history read against the upstream server

This driver does not implement IRediscoverable — there is no push-driven rediscovery signal from a remote OPC UA server in this driver. IHistoryProvider is implemented by no other driver; history reads for every other source route server-side through IHistoryRouter.

History passthrough

IHistoryProvider forwards HistoryRead to the upstream server's own historian. Raw, processed (Average / Minimum / Maximum / Total / Count aggregates mapped to OPC UA Part 13 standard aggregate NodeIds), and at-time reads are supported; each returned DataValue keeps its upstream StatusCode and timestamps verbatim. Event-history (ReadEventsAsync) is left at the interface default — the interface doesn't yet carry the EventFilter surface needed to forward it.

Certificate trust

AutoAcceptCertificates accepts any self-signed / untrusted server certificate. It is dev-only — leave it false in production so a MITM against the opc.tcp channel fails closed.

Testing

  • Unit teststests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Tests/ cover the session lifecycle, namespace remapping, alarm/history passthrough, and config binding against a faked SDK session.
  • Integration fixture — exercises the driver against a reference OPC UA server (opc-plc) on the shared docker host; see OpcUaClient-Test-Fixture.md for the coverage map.

Further reading