Files
lmxopcua/docs/v1/DataTypeMapping.md
Joseph Doherty 006af51768 docs: post-PR-7.2 cleanup — audit + three-track scrub
Audit (three parallel agent passes) found 43 markdown files carrying
stale references to the deleted Galaxy.Host/Proxy/Shared projects
after the v2-mxgw merge. This commit lands the prioritized fixes.

Track 1 — high-traffic in-place rewrites (3 files, ~454 lines deleted)
- README.md (202 → 91 lines): drops .NET 4.8 / x86 / TopShelf install
  text; leads with the multi-driver .NET 10 server identity and points
  at scripts/install/Install-Services.ps1 and the parity rig.
- docs/v2/driver-specs.md §1 Galaxy (~289 → ~66 lines): replaces the
  Tier-C out-of-process spec with a Tier-A in-process description
  matching the current GalaxyDriver code, with the four-section
  GalaxyDriverOptions JSON shape pulled verbatim from
  Config/GalaxyDriverOptions.cs.
- docs/drivers/Galaxy.md (211 → 92 lines): full rewrite around the
  current Browse/Runtime/Health/Config sub-folders.

Track 2 — historical banners (5 files)
- lmx_mxgw.md, lmx_mxgw_impl.md, lmx_backend.md,
  docs/v2/Galaxy.ParityMatrix.md,
  docs/v2/implementation/phase-2-galaxy-out-of-process.md each get a
  " Completed 2026-04-30 — historical record" banner block. lmx_mxgw.md
  also fixes two dead links (`docs/Galaxy.Driver.md` and
  `docs/v2/Galaxy.Driver.md`) → `docs/drivers/Galaxy.md`.

Track 3 — v1 archive sweep (10 git mv + 1 new index + 2 in-place scrubs)
- Moved 10 v1 docs under docs/v1/ preserving subpath structure:
  AlarmTracking, Configuration, DataTypeMapping, HistoricalDataAccess,
  Subscriptions (top-level); drivers/Galaxy-Repository,
  drivers/Galaxy-Test-Fixture; reqs/GalaxyRepositoryReqs,
  reqs/MxAccessClientReqs, reqs/ServiceHostReqs.
- New docs/v1/README.md is the shared archive banner + per-file table.
- docs/README.md repointed to the v1 paths and updated to reflect the
  v2 two-process deploy shape (Server + Admin + optional
  OtOpcUaWonderwareHistorian).
- docs/v2/Galaxy.ParityRig.md got a historical banner + four inline
  scrubs marking the OtOpcUaGalaxyHost service / Driver.Galaxy.Host
  EXE / Driver.Galaxy.ParityTests project as deleted-in-PR-7.2.

The repo's live-reading surface (README + CLAUDE.md + docs/v2/) now
describes only the post-PR-7.2 architecture. v1 docs are preserved as
a labelled archive under docs/v1/.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 08:59:59 -04:00

5.1 KiB

Data Type Mapping

Data-type mapping is driver-defined. Each driver translates its native attribute metadata into two driver-agnostic enums from Core.AbstractionsDriverDataType (src/ZB.MOM.WW.OtOpcUa.Core.Abstractions/DriverDataType.cs) and SecurityClassification (src/ZB.MOM.WW.OtOpcUa.Core.Abstractions/SecurityClassification.cs) — and populates the DriverAttributeInfo record it hands to IAddressSpaceBuilder.Variable(...). Core doesn't interpret the native types; it trusts the driver's translation.

DriverDataType → OPC UA built-in type

DriverNodeManager.MapDataType (src/ZB.MOM.WW.OtOpcUa.Server/OpcUa/DriverNodeManager.cs) is the single translation table for every driver:

DriverDataType OPC UA NodeId
Boolean DataTypeIds.Boolean (i=1)
Int32 DataTypeIds.Int32 (i=6)
Float32 DataTypeIds.Float (i=10)
Float64 DataTypeIds.Double (i=11)
String DataTypeIds.String (i=12)
DateTime DataTypeIds.DateTime (i=13)
anything else DataTypeIds.BaseDataType

The enum also carries Int16 / Int64 / UInt16 / UInt32 / UInt64 / Reference members for drivers that need them; the mapping table is extended as those types surface in actual drivers. Reference is the Galaxy-style attribute reference — it's encoded as an OPC UA String on the wire.

Per-driver mappers

Each driver owns its native → DriverDataType translation:

  • Galaxy ProxyGalaxyProxyDriver.MapDataType(int mxDataType) and MapSecurity(int mxSec) (inline in src/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Proxy/GalaxyProxyDriver.cs). The Galaxy mx_data_type integer is sent across the Host↔Proxy pipe and mapped on the Proxy side. Galaxy's full classic 16-entry table (Boolean / Integer / Float / Double / String / Time / ElapsedTime / Reference / Enumeration / Custom / InternationalizedString) is preserved but compressed into the seven-entry DriverDataType enum — ElapsedTimeFloat64, InternationalizedStringString, ReferenceReference, enumerations → Int32.
  • AB CIPsrc/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipDataType.cs maps CIP tag type codes.
  • Modbussrc/ZB.MOM.WW.OtOpcUa.Driver.Modbus/ModbusDriver.cs maps register shapes (16-bit signed, 16-bit unsigned, 32-bit float, etc.) including the DirectLogic quirk table in DirectLogicAddress.cs.
  • S7 / AB Legacy / TwinCAT / FOCAS / OPC UA Client — each has its own inline mapper or *DataType.cs file per the same pattern.

The driver's mapping is authoritative — when a field type is ambiguous (a LREAL that could be bit-reinterpreted, a BCD counter, a string of a particular encoding), the driver decides the exposed OPC UA shape.

Array handling

DriverAttributeInfo.IsArray = true flips ValueRank = OneDimension on the generated BaseDataVariableState; scalars stay at ValueRank.Scalar. DriverAttributeInfo.ArrayDim carries the declared length. Writing element-by-element (OPC UA IndexRange) is a driver-level decision — see docs/ReadWriteOperations.md.

SecurityClassification — metadata, not ACL

SecurityClassification is driver-reported metadata only. Drivers never enforce write permissions themselves — the classification flows into the Server project where WriteAuthzPolicy.IsAllowed(classification, userRoles) (src/ZB.MOM.WW.OtOpcUa.Server/Security/WriteAuthzPolicy.cs) gates the write against the session's LDAP-derived roles, and (Phase 6.2) the AuthorizationGate + permission trie apply on top. This is the "ACL at server layer" invariant documented in docs/security.md.

The classification values mirror the v1 Galaxy model so existing Galaxy galaxies keep their published semantics:

SecurityClassification Required role Write-from-OPC-UA
FreeAccess yes (even anonymous)
Operate WriteOperate yes
Tune WriteTune yes
Configure WriteConfigure yes
SecuredWrite WriteOperate yes
VerifiedWrite WriteConfigure yes
ViewOnly no

Drivers whose backend has no notion of classification (Modbus, most PLCs) default every tag to FreeAccess or Operate; drivers whose backend does carry the notion (Galaxy, OPC UA Client relaying UserAccessLevel) translate it directly.

Historization

DriverAttributeInfo.IsHistorized = true flips AccessLevel.HistoryRead and Historizing = true on the variable. The driver must then implement IHistoryProvider for HistoryRead service calls to succeed; otherwise the node manager surfaces BadHistoryOperationUnsupported per request.

Key source files

  • src/ZB.MOM.WW.OtOpcUa.Core.Abstractions/DriverDataType.cs — driver-agnostic type enum
  • src/ZB.MOM.WW.OtOpcUa.Core.Abstractions/SecurityClassification.cs — write-authz tier metadata
  • src/ZB.MOM.WW.OtOpcUa.Core.Abstractions/DriverAttributeInfo.cs — per-attribute descriptor
  • src/ZB.MOM.WW.OtOpcUa.Server/OpcUa/DriverNodeManager.csMapDataType translation
  • src/ZB.MOM.WW.OtOpcUa.Server/Security/WriteAuthzPolicy.cs — classification-to-role policy
  • Per-driver mappers in each Driver.* project