Files
lmxopcua/docs/drivers/AbLegacy-Diagnostics.md
2026-04-26 03:50:47 -04:00

5.3 KiB
Raw Blame History

AB Legacy diagnostic counters

Per-device diagnostic counters surface as auto-generated read-only OPC UA variables under each device's synthetic _Diagnostics/ folder. HMIs can bind directly without going through a separate diagnostics RPC. Mirrors the AB CIP _System/ pattern from PR abcip-4.3.

Closes #253 (PR ablegacy-10).

The seven counters

Each device managed by the AbLegacyDriver exposes seven read-only nodes under AbLegacy/<host>/_Diagnostics/<name>:

Name Type Semantics
RequestCount Int64 Total ReadAsync requests issued against this device. One increment per non-diagnostic reference per call, success or failure.
ResponseCount Int64 Successful read responses.
ErrorCount Int64 Failed read responses (any non-Good status).
RetryCount Int64 Retry attempts beyond the first per the PR 9 retry loop. A single read with two retries adds two.
LastErrorCode Int32 Most recent libplctag status code on a failed read; 0 when no error has been seen since the last reset.
LastErrorMessage String Most recent libplctag error message on a failed read; empty when no error has been seen since the last reset.
CommFailures Int64 Count of read failures mapped to BadCommunicationError. Spans transient libplctag throws + retried-out chains so operators see a single "wire fell off" counter.

Address shape: _Diagnostics/<deviceHostAddress>/<name> — e.g. _Diagnostics/ab://10.0.0.5/1,0/RequestCount.

The <deviceHostAddress> segment is the canonical ab://host[:port]/cip-path string from AbLegacyDeviceOptions.HostAddress. The browse path looks like AbLegacy/<deviceHostAddress>/_Diagnostics/<name> — the same shape as a user-config tag node, just under a reserved sibling folder.

Reset behaviour

Trigger Effect
ReinitializeAsync Every counter for every device resets to zero, plus LastErrorMessage clears to empty.
ShutdownAsync Same as Reinitialize — counters drop with the device map.
Driver process restart Counters start at zero.
Probe transition Stopped→Running No automatic reset — counters are cumulative across reconnect events so operators can spot intermittent links by watching CommFailures keep climbing.

There is no in-process "reset" RPC at the time of writing. If you need to clear counters without a redeploy, kick a ReinitializeAsync from the Admin RPC surface — the driver re-EnsureDevice's each host so the freshly registered counters start at zero.

What does not increment counters

Reads against _Diagnostics/<host>/<name> are driver-local observability, not field traffic — they short-circuit before the libplctag dispatch and do NOT increment RequestCount or any other counter. Otherwise a 1 Hz HMI poll of RequestCount would make the counter chase its own tail.

Writes against _Diagnostics/* are rejected with BadNotWritable because every diagnostic node is SecurityClassification.ViewOnly — a misbehaving SCADA template can't accidentally clobber the diagnostic surface.

Collision with user tags

User-config tags must not shadow the seven reserved diagnostic names and must not live under the synthetic _Diagnostics/ folder. Both shapes are rejected at InitializeAsync time with a clear InvalidOperationException:

  • A tag named RequestCount (or any of the other six reserved names) is rejected because it would silently never resolve at read time — the diagnostics short-circuit wins.
  • A tag whose Address starts with _Diagnostics/ is rejected because the whole prefix is owned by the auto-emitted counters.

Pick a different name (SiteRequestCount, MachineRequestCount) or a different address path (real PCCC files like N7:0).

HMI binding examples

OPC UA Client CLI

dotnet run --project src/ZB.MOM.WW.OtOpcUa.Client.CLI -- read `
  -u opc.tcp://localhost:4840 `
  -n "ns=2;s=AbLegacy/ab://10.0.0.5/1,0/_Diagnostics/RequestCount"

AB Legacy CLI (driver-direct, no OPC UA layer)

dotnet run --project src/ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.Cli -- read `
  -g "ab://10.0.0.5/1,0" -P Slc500 `
  --address "_Diagnostics/RequestCount"

The driver-direct path lets you sanity-check the counter without standing up an OPC UA server — useful when triaging a wire-level issue on the bench.

Subscription pattern

Subscribe to all seven counters at a slow rate (e.g. 510 s) on a long-lived overview dashboard, plus a faster rate (1 s) on LastErrorMessage / LastErrorCode when actively debugging a flapping link. The diagnostics short-circuit makes every read O(1) — there's no penalty for fast polling of the counter itself, only the OPC UA subscription bookkeeping.

Cross-references