3.2 KiB
OPC UA Client driver
Tier-A in-process driver that opens a Session against a remote OPC UA server
and re-exposes its address space through the local OtOpcUa server. The
"gateway / aggregation" direction — opposite to the usual "server exposes PLC
data" flow.
For the test fixture (opc-plc) see OpcUaClient-Test-Fixture.md.
For the configuration surface see OpcUaClientDriverOptions in
src/ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient/OpcUaClientDriverOptions.cs.
Auto re-import on ModelChangeEvent
The driver subscribes to BaseModelChangeEventType (and its subtype
GeneralModelChangeEventType) on the upstream Server node (i=2253) at
the end of InitializeAsync. When the upstream server advertises a
topology change, the driver coalesces events over a debounce window and
runs a single re-import (equivalent to calling ReinitializeAsync —
internally ShutdownAsync + InitializeAsync).
Configuration
| Option | Default | Notes |
|---|---|---|
WatchModelChanges |
true |
Disable to skip the watch entirely (no extra subscription, no re-import on topology change). |
ModelChangeDebounce |
5s |
Coalescing window. The first event starts the timer; further events extend it; when it elapses with no new events, the driver fires one re-import. |
Behaviour
- One model-change subscription per driver instance, separate from the
data + alarm subscriptions. Created best-effort: a server that doesn't
advertise the event types or rejects the
EventFilterfalls through to no-watch —InitializeAsyncstill succeeds. - The
EventFilterselects only theEventTypefield (aWhereClauseconstrains byOfType BaseModelChangeEventType). Payload fields likeChanges[]are intentionally ignored: the driver always re-imports the full upstream root, so per-event delta tracking would just add wire overhead. - Debounce is implemented via a single-shot
Timer; every event callsTimer.Change(window, Infinite)so a burst of N events triggers exactly one re-import after the window elapses with no further events. - The re-import path acquires the same
_gatesemaphore thatReadAsync/WriteAsync/BrowseAsync/SubscribeAsyncuse. Downstream callers see a brief browse-gap (≈ the upstreamDiscoverAsyncduration) while the gate is held — but no torn reads or split-batch writes. - Failure during the re-import is best-effort: the next
ModelChangeEventtriggers another attempt, and the keep-alive watchdog covers permanent upstream loss. Operators see failures throughDriverHealth.LastError- the diagnostics counters.
When to disable
Flip WatchModelChanges to false when:
- The upstream topology is known-static (e.g. firmware-pinned PLC) and the driver should never run a re-import unprompted.
- The brief browse-gap during re-import is unacceptable and a manual
ReinitializeAsynccall from the operator is preferred. - The upstream server fires spurious
ModelChangeEvents that don't reflect real topology changes, causing wasted re-imports. Tighten or disable rather than chasing the noise downstream.