fix(focas): serialize per-device wire I/O + bound reads; tolerate AdminUI config formats
Equipment tags were stuck at Bad_WaitingForInitialData on the deployed driver: the equipment poll, fixed-tree loop, probe and recycle shared one FOCAS/2 socket with no serialization, and the steady-state read had no timeout — concurrent reads collided and a stalled read hung forever, never overwriting the node's initial-data seed.
- SynchronizedFocasClient: per-device SemaphoreSlim gate + per-call timeout around every wire op (Connect/Probe gated, not double-bounded); wired in EnsureConnectedAsync. ReadAsync/WriteAsync map a per-call timeout to BadCommunicationError instead of rethrowing.
- FlexibleStringConverter on FOCAS config Series: the AdminUI persists the enum as a number ("series":6); accept number-or-string instead of throwing -> stub.
- FocasHostAddress.TryParse tolerates a scheme-less {ip}[:{port}] (AdminUI hostAddress form); canonical focas:// unchanged, malformed schemes still rejected.
247 FOCAS tests green; each fix has a regression test. Live-validated on wonder-app-vd03 (tags read Good).
This commit is contained in:
@@ -70,9 +70,10 @@ public sealed class FocasDriverProbeTests
|
||||
[Fact]
|
||||
public async Task MalformedHostAddress_Returns_OkFalse_WithNoHostPortMessage()
|
||||
{
|
||||
// "not-a-focas-url" is not a focas:// URL — TryParse returns null.
|
||||
// A foreign URI scheme ("http://…") is rejected by TryParse → null. (A bare
|
||||
// "{ip}[:{port}]" without a scheme is now tolerated, so it can't be the malformed case.)
|
||||
var result = await Probe.ProbeAsync(
|
||||
"{\"devices\":[{\"hostAddress\":\"not-a-focas-url\"}]}",
|
||||
"{\"devices\":[{\"hostAddress\":\"http://10.0.0.5/\"}]}",
|
||||
TimeSpan.FromSeconds(3),
|
||||
TestContext.Current.CancellationToken);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user