f179829ca6
- IMPORTANT: a successful probe records the PLC's ADS state; a PLC not in Run
keeps the driver Degraded with 'PLC in {state}' while LastSuccessfulRead
still advances (the device answered). RecordDeviceAnswered never restores
Healthy while any device is out of Run.
- Health is per device, rolled up worst-of: a comms fault is remembered on the
device it was seen on and only that device answering clears it (device A
answering no longer clears device B's fault).
- Refused (non-comms) dead registrations back off 30 s doubling to 10 min and
are re-armed by a symbol-version change or retried by the reconnect replay;
comms-class failures keep the every-tick retry. A retry whose failure class
changes republishes the tag's status, once.
- Bit-RMW gates are kept across generations and teardowns (never cleared).
- ShutdownAsync honours its CancellationToken: it stops waiting, finishes the
bookkeeping and throws OperationCanceledException.
- Remarks on why a superseded InitializeAsync throws OperationCanceledException.
- REAL / LREAL values (scalar or array element) outside the target range are
OverflowException -> BadOutOfRange instead of being written as Infinity.
- String / array write encoding factored into AdsTwinCATClient.PlanStringWrite
/ PlanArrayWrite; the fake runs them so a driver-level test covers the real
encode path against a fake resolved symbol.
- Timing-fragile tests use condition waits / measured probe-tick windows; the
dispose-during-shutdown test asserts ordering with a 1 s bound.
Refs #739
Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT