v3(b1-abcip): RawPath read-path for AbCip (multi-device)
Apply the reviewed Modbus exemplar to the AbCip multi-device driver:
- Mapper AbCipEquipmentTagParser -> AbCipTagDefinitionFactory; TryParse -> FromTagConfig(tagConfig, rawPath, out def); drop leading-{ heuristic + the deviceHostAddress key; add inverse ToTagConfig; round-trip arrays/members/safety for coverage.
- Options: Tags (typed) -> RawTags (RawTagEntry list); Devices list kept.
- Driver: byName-only resolver over _tagsByRawPath (Ordinal); table built from RawTags via FromTagConfig, threading entry.DeviceName (device routing key) + entry.WriteIdempotent onto the def. Multi-device routing keys on DeviceName-or-host via a _devicesByRoutingKey index; discovery groups _declaredTags by RoutesToDevice.
- Factory: retire the pre-declared Tags DTO/BuildTag; bind List<RawTagEntry> RawTags.
- Probe: derive probe tag path from RawTags via the mapper.
- Cli BuildOptions projects typed tags -> RawTagEntry (ToTagConfig).
- Tests: AbCipRawTags helper (typed def -> RawTagEntry); parser tests -> FromTagConfig; blob-fallback driver tests rewritten to author via RawTags + read by RawPath. Driver.AbCip.Tests 342/342, Cli.Tests 42/42.
TODO(v3 WaveC): DeviceName becomes a pure logical name once the device connection host moves to the Device row's DeviceConfig.
This commit is contained in:
+16
-23
@@ -18,17 +18,18 @@ public sealed class AbCipDriverCodeReviewRegressionTests
|
||||
|
||||
// ---- Driver.AbCip-001 — ReinitializeAsync must apply a changed config JSON ----
|
||||
|
||||
/// <summary>Tests that InitializeAsync applies devices and tags from the config JSON.</summary>
|
||||
/// <summary>Tests that InitializeAsync applies devices and raw tags from the config JSON.</summary>
|
||||
[Fact]
|
||||
public async Task InitializeAsync_applies_devices_and_tags_from_the_config_json()
|
||||
{
|
||||
// Constructed with NO devices/tags — the JSON is the only source of config.
|
||||
// Constructed with NO devices/tags — the JSON is the only source of config. v3: tags arrive as
|
||||
// RawTags (RawPath + TagConfig blob + DeviceName routing key).
|
||||
var drv = new AbCipDriver(new AbCipDriverOptions(), "drv-1");
|
||||
const string json = """
|
||||
{
|
||||
"Devices": [ { "HostAddress": "ab://10.0.0.9/1,0", "PlcFamily": "ControlLogix" } ],
|
||||
"Tags": [ { "Name": "Speed", "DeviceHostAddress": "ab://10.0.0.9/1,0",
|
||||
"TagPath": "Speed", "DataType": "DInt" } ]
|
||||
"RawTags": [ { "RawPath": "line1/speed", "TagConfig": "{\"tagPath\":\"Speed\",\"dataType\":\"DInt\"}",
|
||||
"WriteIdempotent": false, "DeviceName": "ab://10.0.0.9/1,0" } ]
|
||||
}
|
||||
""";
|
||||
|
||||
@@ -92,14 +93,12 @@ public sealed class AbCipDriverCodeReviewRegressionTests
|
||||
var drv = new AbCipDriver(new AbCipDriverOptions
|
||||
{
|
||||
Devices = [new AbCipDeviceOptions(Device)],
|
||||
Tags =
|
||||
[
|
||||
RawTags = AbCipRawTags.From(
|
||||
new AbCipTagDefinition("Motor", Device, "Motor", AbCipDataType.Structure, Members:
|
||||
[
|
||||
new AbCipStructureMember("Speed", AbCipDataType.DInt),
|
||||
new AbCipStructureMember("Torque", AbCipDataType.Real),
|
||||
]),
|
||||
],
|
||||
])),
|
||||
}, "drv-1", factory);
|
||||
await drv.InitializeAsync("{}", CancellationToken.None);
|
||||
|
||||
@@ -186,7 +185,7 @@ public sealed class AbCipDriverCodeReviewRegressionTests
|
||||
var drv = new AbCipDriver(new AbCipDriverOptions
|
||||
{
|
||||
Devices = [new AbCipDeviceOptions(Device)],
|
||||
Tags = [new AbCipTagDefinition("Speed", Device, "Speed", AbCipDataType.DInt)],
|
||||
RawTags = AbCipRawTags.From(new AbCipTagDefinition("Speed", Device, "Speed", AbCipDataType.DInt)),
|
||||
}, "drv-1", factory);
|
||||
await drv.InitializeAsync("{}", CancellationToken.None);
|
||||
|
||||
@@ -228,7 +227,7 @@ public sealed class AbCipDriverCodeReviewRegressionTests
|
||||
var drv = new AbCipDriver(new AbCipDriverOptions
|
||||
{
|
||||
Devices = [new AbCipDeviceOptions(Device)],
|
||||
Tags = [new AbCipTagDefinition("Counter", Device, "Counter", AbCipDataType.UDInt)],
|
||||
RawTags = AbCipRawTags.From(new AbCipTagDefinition("Counter", Device, "Counter", AbCipDataType.UDInt)),
|
||||
}, "drv-1", factory);
|
||||
await drv.InitializeAsync("{}", CancellationToken.None);
|
||||
|
||||
@@ -254,14 +253,12 @@ public sealed class AbCipDriverCodeReviewRegressionTests
|
||||
var drv = new AbCipDriver(new AbCipDriverOptions
|
||||
{
|
||||
Devices = [new AbCipDeviceOptions(Device)],
|
||||
Tags =
|
||||
[
|
||||
RawTags = AbCipRawTags.From(
|
||||
new AbCipTagDefinition("Motor", Device, "Motor", AbCipDataType.Structure, Members:
|
||||
[
|
||||
new AbCipStructureMember("Speed", AbCipDataType.DInt),
|
||||
new AbCipStructureMember("Torque", AbCipDataType.Real),
|
||||
]),
|
||||
],
|
||||
])),
|
||||
}, "drv-1", factory);
|
||||
await drv.InitializeAsync("{}", CancellationToken.None);
|
||||
|
||||
@@ -281,11 +278,9 @@ public sealed class AbCipDriverCodeReviewRegressionTests
|
||||
var drv = new AbCipDriver(new AbCipDriverOptions
|
||||
{
|
||||
Devices = [new AbCipDeviceOptions(Device)],
|
||||
Tags =
|
||||
[
|
||||
RawTags = AbCipRawTags.From(
|
||||
new AbCipTagDefinition("Speed", Device, "Speed", AbCipDataType.DInt),
|
||||
new AbCipTagDefinition("Speed", Device, "SpeedAlias", AbCipDataType.Real), // same name
|
||||
],
|
||||
new AbCipTagDefinition("Speed", Device, "SpeedAlias", AbCipDataType.Real)), // same name
|
||||
}, "drv-1");
|
||||
|
||||
Should.Throw<InvalidOperationException>(() =>
|
||||
@@ -301,14 +296,12 @@ public sealed class AbCipDriverCodeReviewRegressionTests
|
||||
var drv = new AbCipDriver(new AbCipDriverOptions
|
||||
{
|
||||
Devices = [new AbCipDeviceOptions(Device)],
|
||||
Tags =
|
||||
[
|
||||
RawTags = AbCipRawTags.From(
|
||||
new AbCipTagDefinition("Motor", Device, "Motor", AbCipDataType.Structure, Members:
|
||||
[
|
||||
new AbCipStructureMember("Speed", AbCipDataType.DInt),
|
||||
]),
|
||||
new AbCipTagDefinition("Motor.Speed", Device, "Motor.Speed", AbCipDataType.DInt), // collision
|
||||
],
|
||||
new AbCipTagDefinition("Motor.Speed", Device, "Motor.Speed", AbCipDataType.DInt)), // collision
|
||||
}, "drv-1");
|
||||
|
||||
Should.Throw<InvalidOperationException>(() =>
|
||||
@@ -336,7 +329,7 @@ public sealed class AbCipDriverCodeReviewRegressionTests
|
||||
var drv = new AbCipDriver(new AbCipDriverOptions
|
||||
{
|
||||
Devices = [new AbCipDeviceOptions(Device)],
|
||||
Tags = [new AbCipTagDefinition("Speed", Device, "Speed", AbCipDataType.DInt)],
|
||||
RawTags = AbCipRawTags.From(new AbCipTagDefinition("Speed", Device, "Speed", AbCipDataType.DInt)),
|
||||
}, "drv-1", factory);
|
||||
await drv.InitializeAsync("{}", CancellationToken.None);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user