merge: Modbus RTU-over-TCP transport (#495)
Wave 1 of the driver-expansion program. The branch was complete and live-gated but had never been merged; it sat 15 commits ahead and 50 behind master. Purely additive behind the existing IModbusTransport seam — the application protocol (function codes, codecs, planner, coalescing, write path, probe, materialisation, HistoryRead) is identical across TCP and RTU; only the wire framing differs ([addr][PDU][CRC-16], no MBAP, no TxId). Zero changes to codecs/planner/health. Selected by a new Transport config field (ModbusTransportMode: Tcp | RtuOverTcp), routed through ModbusTransportFactory (throws on unknown mode), with the string-enum guard on options/DTO/factory and a Transport selector on the AdminUI Modbus form. ModbusSocketLifecycle was extracted from ModbusTcpTransport (behaviour-preserving) and is composed by both transports. Descoped by design: direct-serial (System.IO.Ports) and Modbus ASCII — RTU buses are reached exclusively via a serial->Ethernet gateway. No per-tag config changes; the existing per-tag UnitId already makes a multi-drop bus work. Re-validated against current master at merge time (the branch's own gate predates 50 commits of master): no overlapping files, clean merge, solution builds 0 errors, and Modbus 344/344, Modbus.Addressing 161/161, AdminUI 740/740, Runtime 507/507, Configuration 131/131 all pass. Confirmed the Transport selector is still reachable through master's current authoring path (DriverConfigModal -> ModbusDriverForm), so the branch's live /run gate result still applies.
This commit is contained in:
@@ -61,4 +61,15 @@ public sealed class ModbusDriverFormModelTests
|
||||
json.ShouldContain("\"family\":\"MELSEC\""); // enum-as-name (not a number), camelCase key
|
||||
json.ShouldNotContain("\"family\":0", Case.Sensitive); // never the numeric enum form
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Round_trip_preserves_Transport_mode()
|
||||
{
|
||||
var form = new ModbusDriverForm.FormModel { Transport = ModbusTransportMode.RtuOverTcp };
|
||||
var json = JsonSerializer.Serialize(form.ToOptions(), JsonOpts);
|
||||
var back = ModbusDriverForm.FormModel.FromOptions(
|
||||
JsonSerializer.Deserialize<ModbusDriverOptions>(json, JsonOpts)!);
|
||||
back.Transport.ShouldBe(ModbusTransportMode.RtuOverTcp);
|
||||
json.ShouldContain("\"transport\":\"RtuOverTcp\""); // name string, never a number
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user