docs(phase4b): Modbus driver-type canonical + Galaxy nesting + FOCAS auto-scale (managed-backend caveat)
v2-ci / build (push) Failing after 37s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
v2-ci / build (push) Failing after 37s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
This commit is contained in:
@@ -164,9 +164,11 @@ before publishing, so a CNC that reports millimetres × 1000 is corrected by set
|
||||
]
|
||||
```
|
||||
|
||||
Auto-fetching the decimal-place count via `cnc_getfigure` is deferred (wire-gated). Until
|
||||
that lands, the config field is the authoritative source — consult the MTB / machine
|
||||
parameter sheets for the correct value. Negative values are clamped to `0`.
|
||||
The driver now attempts to auto-scale each axis position using the CNC's `cnc_getfigure` figure when available; `PositionDecimalPlaces` is the **per-axis fallback** used only when the CNC reports no figure for that axis. **Caveat:** the managed `WireFocasClient` (FOCAS/2 Ethernet wire protocol) does not issue `cnc_getfigure` today, so on real hardware all axes still fall back to the manual `PositionDecimalPlaces` config field. Live auto-fetch is a follow-up requiring a `cnc_getfigure` command in `FocasWireClient`. Negative values from `PositionDecimalPlaces` are clamped to `0`.
|
||||
|
||||
**Follow-ups (known gaps, non-blocking):**
|
||||
- No upper-bound clamp on the figure magnitude returned by the CNC — a misbehaving figure could overflow `Math.Pow`; a max-figure guard should be added.
|
||||
- The negative-figure branch (falls back to manual `PositionDecimalPlaces`) is handled but not explicitly unit-tested.
|
||||
|
||||
**Still user-authored**: `PARAM:6711`, `MACRO:500`, `R100` etc. — specific
|
||||
numbers whose meaning is MTB-specific. Those go under the device folder
|
||||
|
||||
@@ -100,6 +100,10 @@ The session-less alarm feed (`GatewayGalaxyAlarmFeed`) and alarm acknowledger (`
|
||||
- **Parity rig + dev-rig walkthrough**: see [docs/v2/Galaxy.ParityRig.md](../v2/Galaxy.ParityRig.md). The rig stands up a real `mxaccessgw` against a live Galaxy and exercises the full read / write / subscribe / rediscover path.
|
||||
- **Performance + soak**: see [docs/v2/Galaxy.Performance.md](../v2/Galaxy.Performance.md).
|
||||
|
||||
## Browse Tree Shape
|
||||
|
||||
`GalaxyDiscoverer` builds the OPC UA address space as a **true nested tree** by `parent_gobject_id`: each gobject folder is parented under its Galaxy parent folder rather than being emitted flat under the driver root. Parentage falls back gracefully — a gobject with `parent_gobject_id` of 0, a parent not present in the returned set, a self-referencing parent, or a cycle attaches directly to the driver root. This matches the Galaxy `ArchestrA` object hierarchy as seen in the IDE.
|
||||
|
||||
## Operational Notes
|
||||
|
||||
- **MXAccess `ClientName` collisions**: two OtOpcUa instances sharing a `ClientName` cause the older Wonderware session to lose subscription state. Redundancy pairs (decision #149) enforce uniqueness via install scripts.
|
||||
|
||||
@@ -111,6 +111,10 @@ is reproduced in [docs/v2/driver-specs.md §2](../v2/driver-specs.md).
|
||||
- **Integration tests** — `tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Modbus.IntegrationTests/` run against the Docker Modbus simulator fixture. See [Modbus-Test-Fixture.md](Modbus-Test-Fixture.md) for the coverage map and the `MODBUS_SIM_ENDPOINT` wiring.
|
||||
- **Manual client** — [Driver.Modbus.Cli.md](../Driver.Modbus.Cli.md).
|
||||
|
||||
## Driver-Type String
|
||||
|
||||
The canonical stored/dispatched `DriverType` value is **`"Modbus"`** — this is what the runtime factory key, docker-dev seed, AdminUI editor-map, tag-config validator, and probe all use. The AdminUI displays the friendly label **"Modbus TCP"** and the new-driver route slug is `modbustcp`, but neither the slug nor the label is stored in the database. Any pre-existing `DriverInstance` rows that carry the legacy value `"ModbusTcp"` must be updated to `"Modbus"` to receive typed-editor dispatch and factory instantiation.
|
||||
|
||||
## Operational Notes
|
||||
|
||||
- **Wrong-endian readings are silently plausible.** A byte-order misconfiguration produces a wrong number, not a Bad quality code — surface byte-order mismatches as data-validation alerts, not status codes (see [docs/v2/driver-specs.md §2](../v2/driver-specs.md)).
|
||||
|
||||
@@ -241,7 +241,7 @@ CREATE TABLE dbo.DriverInstance (
|
||||
ClusterId nvarchar(64) NOT NULL FOREIGN KEY REFERENCES dbo.ServerCluster(ClusterId),
|
||||
NamespaceId nvarchar(64) NOT NULL FOREIGN KEY REFERENCES dbo.Namespace(NamespaceId),
|
||||
Name nvarchar(128) NOT NULL,
|
||||
DriverType nvarchar(32) NOT NULL, -- Galaxy | ModbusTcp | AbCip | AbLegacy | S7 | TwinCat | Focas | OpcUaClient
|
||||
DriverType nvarchar(32) NOT NULL, -- Galaxy | Modbus | AbCip | AbLegacy | S7 | TwinCat | Focas | OpcUaClient
|
||||
Enabled bit NOT NULL DEFAULT 1,
|
||||
DriverConfig nvarchar(max) NOT NULL CHECK (ISJSON(DriverConfig) = 1)
|
||||
);
|
||||
@@ -259,7 +259,7 @@ CREATE UNIQUE INDEX UX_DriverInstance_Generation_LogicalId
|
||||
| `DriverType` | Allowed `Namespace.Kind` |
|
||||
|--------------|--------------------------|
|
||||
| Galaxy | SystemPlatform |
|
||||
| ModbusTcp / AbCip / AbLegacy / S7 / TwinCat / Focas | Equipment |
|
||||
| Modbus / AbCip / AbLegacy / S7 / TwinCat / Focas | Equipment |
|
||||
| OpcUaClient | Equipment OR SystemPlatform (per-instance config decides) |
|
||||
|
||||
**Same-cluster invariant** (revised after adversarial review 2026-04-17 finding #1): the `Namespace` referenced by `DriverInstance.NamespaceId` MUST belong to the same `ClusterId`. This is a cross-cluster trust boundary — without enforcement, a draft for cluster A could bind to a namespace owned by cluster B, leaking that cluster's URI into A's endpoint and breaking tenant isolation. Three layers of enforcement:
|
||||
@@ -801,7 +801,7 @@ Examples of the per-driver shapes — full specs in `driver-specs.md`:
|
||||
"Historian": { "Enabled": false }
|
||||
}
|
||||
|
||||
// DeviceConfig for DriverType=ModbusTcp
|
||||
// DeviceConfig for DriverType=Modbus
|
||||
{
|
||||
"Host": "10.0.3.42",
|
||||
"Port": 502,
|
||||
@@ -810,7 +810,7 @@ Examples of the per-driver shapes — full specs in `driver-specs.md`:
|
||||
"AddressFormat": "Standard" // or "DL205"
|
||||
}
|
||||
|
||||
// TagConfig for DriverType=ModbusTcp
|
||||
// TagConfig for DriverType=Modbus
|
||||
{
|
||||
"RegisterType": "HoldingRegister",
|
||||
"Address": 100,
|
||||
|
||||
Reference in New Issue
Block a user