Phase 3 PR 23 — Modbus IHostConnectivityProbe #22

Merged
dohertj2 merged 1 commits from phase-3-pr23-modbus-probe into v2 2026-04-18 12:23:05 -04:00
Owner

Per-endpoint probe loop that issues FC03 at ProbeAddress every Interval, drives HostState Unknown→Running→Stopped→Running, raises OnHostStatusChanged on transitions only (no spam on stable PLCs). HostName formatted host:port so Admin UI dashboard shows PLC endpoints uniformly with Galaxy platforms. 7 new tests cover initial Unknown, first-tick Running, transport-fail Stopped, recovery, no-duplicate-Running on repeat success, probe-disabled stays Unknown, shutdown stops loop. 202/202 solution tests pass. ModbusDriver now implements 6 of 8 capability interfaces (adds IHostConnectivityProbe).

Per-endpoint probe loop that issues FC03 at ProbeAddress every Interval, drives HostState Unknown→Running→Stopped→Running, raises OnHostStatusChanged on transitions only (no spam on stable PLCs). HostName formatted host:port so Admin UI dashboard shows PLC endpoints uniformly with Galaxy platforms. 7 new tests cover initial Unknown, first-tick Running, transport-fail Stopped, recovery, no-duplicate-Running on repeat success, probe-disabled stays Unknown, shutdown stops loop. 202/202 solution tests pass. ModbusDriver now implements 6 of 8 capability interfaces (adds IHostConnectivityProbe).
dohertj2 added 1 commit 2026-04-18 12:23:00 -04:00
Phase 3 PR 23 — Modbus IHostConnectivityProbe. ModbusDriver now implements 6 of 8 capability interfaces (adds IHostConnectivityProbe alongside IDriver + ITagDiscovery + IReadable + IWritable + ISubscribable from the earlier PRs). Background probe loop kicks off in InitializeAsync when ModbusProbeOptions.Enabled is true, sends a cheap FC03 read-1-register at ProbeAddress (default 0) every Interval (default 5s) with a per-tick Timeout (default 2s), and tracks the single Modbus endpoint's state in the HostState machine. Initial state = Unknown; first successful probe transitions to Running; any transport/timeout failure transitions to Stopped; recovery transitions back to Running. OnHostStatusChanged fires exactly on transitions (not on repeat successes — prevents event-spam on a healthy connection). HostName format is 'host:port' so the Admin UI can display the endpoint uniformly with Galaxy platforms/engines in the fleet status dashboard. GetHostStatuses returns a single-item list with the current state + last-change timestamp (Modbus driver talks to exactly one endpoint per instance — operators spin up multiple driver instances for multi-PLC deployments). ShutdownAsync cancels the probe CTS before tearing down the transport so the loop can't log a spurious Stopped after intentional shutdown (OperationCanceledException caught separately from the 'real' transport errors). ModbusDriverOptions extended with ModbusProbeOptions sub-record (Enabled default true, Interval 5s, Timeout 2s, ProbeAddress ushort for PLCs that have register-0 policies; most PLCs tolerate an FC03 at 0 but some industrial gateways lock it). Tests (7 new ModbusProbeTests): Initial_state_is_Unknown_before_first_probe_tick (probe disabled, state stays Unknown, HostName formatted); First_successful_probe_transitions_to_Running (enabled, waits for probe count + event queue, asserts Unknown → Running with correct OldState/NewState); Transport_failure_transitions_to_Stopped (flip fake.Reachable = false mid-run, wait for state diff); Recovery_transitions_Stopped_back_to_Running (up → down → up, asserts ≥ 3 transitions); Repeated_successful_probes_do_not_generate_duplicate_Running_events (several hundred ms of stable probes, count stays at 1); Disabled_probe_stays_Unknown_and_fires_no_events (safety guard when operator wants to disable probing); Shutdown_stops_the_probe_loop (probe count captured at shutdown, delay 400ms, assert ≤ 1 extra to tolerate the narrow race where an in-flight tick completes after shutdown — the contract is 'no new ticks scheduled' not 'instantaneous freeze'). FlappyTransport fake exposes a volatile Reachable flag so tests can toggle the PLC availability mid-run, + ProbeCount counter so tests can assert the loop actually issued requests. WaitForStateAsync helper polls GetHostStatuses up to a deadline; tolerates scheduler jitter on slow CI runners. Full solution: 0 errors, 202 unit + integration tests pass (22 Modbus + 180 pre-existing). 268b12edec
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
dohertj2 merged commit 8a692d4ba8 into v2 2026-04-18 12:23:05 -04:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dohertj2/lmxopcua#22