v3(s7): apply Modbus RawTags exemplar to the S7 driver

Rename S7EquipmentTagParser -> S7TagDefinitionFactory; TryParse(reference)
-> FromTagConfig(tagConfig, rawPath, out def) (drops the leading-{ heuristic,
keys the def by RawPath, adds inverse ToTagConfig). Replace S7DriverOptions.Tags
(pre-declared S7TagDefinition list) with RawTags (IReadOnlyList<RawTagEntry>);
the driver builds its RawPath->def table from RawTags at Initialize via the
factory (skip+log on miss), resolver is byName-only, DiscoverAsync + init guards
+ address pre-parse now run off that table. Factory retires the pre-declared DTO
tag path (RawTags binding only). Cli BuildOptions serialises typed defs to
RawTagEntry. Tests migrated to a S7RawTags helper + FromTagConfig; parser test
files renamed. Coordinator's EquipmentTagConfigInspector S7 rename left to Wave-B
coordinator; Driver.S7.IntegrationTests (Docker-gated) left red per scope.

Driver.S7 + Cli build green; Driver.S7.Tests 264/264, S7.Cli.Tests 49/49.
This commit is contained in:
Joseph Doherty
2026-07-15 20:11:04 -04:00
parent c379e246d0
commit 1e26b9ab58
21 changed files with 425 additions and 251 deletions
@@ -22,14 +22,16 @@ public sealed class S7DiscoveryAndSubscribeTests
var opts = new S7DriverOptions
{
Host = "192.0.2.1",
Tags =
[
new("TempSetpoint", "DB1.DBW0", S7DataType.Int16, Writable: true),
new("FaultBit", "M0.0", S7DataType.Bool, Writable: false),
new("PIDOutput", "DB5.DBD12", S7DataType.Float32, Writable: true),
],
Probe = new S7ProbeOptions { Enabled = false },
RawTags = S7RawTags.Entries(
new S7TagDefinition("TempSetpoint", "DB1.DBW0", S7DataType.Int16, Writable: true),
new S7TagDefinition("FaultBit", "M0.0", S7DataType.Bool, Writable: false),
new S7TagDefinition("PIDOutput", "DB5.DBD12", S7DataType.Float32, Writable: true)),
};
using var drv = new S7Driver(opts, "s7-disco");
// v3: DiscoverAsync projects the RawPath → definition table, which is built at Initialize —
// so the driver must be initialized (with a connecting fake PLC) before Discover.
using var drv = new S7Driver(opts, "s7-disco", new ConnectingFakeS7PlcFactory());
await drv.InitializeAsync("{}", TestContext.Current.CancellationToken);
var builder = new RecordingAddressSpaceBuilder();
await drv.DiscoverAsync(builder, TestContext.Current.CancellationToken);
@@ -49,13 +51,14 @@ public sealed class S7DiscoveryAndSubscribeTests
var opts = new S7DriverOptions
{
Host = "192.0.2.1",
Tags =
[
new("SetPoint", "DB1.DBW0", S7DataType.Int16, WriteIdempotent: true),
new("StartBit", "M0.0", S7DataType.Bool),
],
Probe = new S7ProbeOptions { Enabled = false },
RawTags = S7RawTags.Entries(
new S7TagDefinition("SetPoint", "DB1.DBW0", S7DataType.Int16, WriteIdempotent: true),
new S7TagDefinition("StartBit", "M0.0", S7DataType.Bool)),
};
using var drv = new S7Driver(opts, "s7-idem");
// v3: DiscoverAsync projects the table built at Initialize — initialize with a fake PLC first.
using var drv = new S7Driver(opts, "s7-idem", new ConnectingFakeS7PlcFactory());
await drv.InitializeAsync("{}", TestContext.Current.CancellationToken);
var builder = new RecordingAddressSpaceBuilder();
await drv.DiscoverAsync(builder, TestContext.Current.CancellationToken);