Files
lmxopcua/docs/v1/DataTypeMapping.md
T
Joseph Doherty 969b0847a1 docs: update path references for module-folder reorganization
Rewrite src/ and tests/ project paths in docs, CLAUDE.md, README.md, and
test-fixture READMEs to the new module-folder layout (Core/Server/Drivers/
Client/Tooling). References to retired v1 projects (Galaxy.Host/Proxy/Shared,
the legacy monolithic test projects) are left untouched.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 02:10:29 -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.Abstractions — DriverDataType (src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/DriverDataType.cs) and SecurityClassification (src/Core/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/Server/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 Proxy — GalaxyProxyDriver.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 — ElapsedTime → Float64, InternationalizedString → String, Reference → Reference, enumerations → Int32.
  • AB CIP — src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.AbCip/AbCipDataType.cs maps CIP tag type codes.
  • Modbus — src/Drivers/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/Server/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/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/DriverDataType.cs — driver-agnostic type enum
  • src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/SecurityClassification.cs — write-authz tier metadata
  • src/Core/ZB.MOM.WW.OtOpcUa.Core.Abstractions/DriverAttributeInfo.cs — per-attribute descriptor
  • src/Server/ZB.MOM.WW.OtOpcUa.Server/OpcUa/DriverNodeManager.cs — MapDataType translation
  • src/Server/ZB.MOM.WW.OtOpcUa.Server/Security/WriteAuthzPolicy.cs — classification-to-role policy
  • Per-driver mappers in each Driver.* project