# Data Type Mapping `MxDataTypeMapper` and `SecurityClassificationMapper` translate Galaxy attribute metadata into OPC UA variable node properties. These mappings determine how Galaxy runtime values are represented to OPC UA clients and whether clients can write to them. ## mx_data_type to OPC UA Type Mapping Each Galaxy attribute carries an `mx_data_type` integer that identifies its data type. `MxDataTypeMapper.MapToOpcUaDataType` maps these to OPC UA built-in type NodeIds: | mx_data_type | Galaxy type | OPC UA type | NodeId | CLR type | |:---:|-------------|-------------|:------:|----------| | 1 | Boolean | Boolean | i=1 | `bool` | | 2 | Integer | Int32 | i=6 | `int` | | 3 | Float | Float | i=10 | `float` | | 4 | Double | Double | i=11 | `double` | | 5 | String | String | i=12 | `string` | | 6 | Time | DateTime | i=13 | `DateTime` | | 7 | ElapsedTime | Double | i=11 | `double` | | 8 | Reference | String | i=12 | `string` | | 13 | Enumeration | Int32 | i=6 | `int` | | 14 | Custom | String | i=12 | `string` | | 15 | InternationalizedString | LocalizedText | i=21 | `string` | | 16 | Custom | String | i=12 | `string` | | other | Unknown | String | i=12 | `string` | Unknown types default to String. This is a safe fallback because MXAccess delivers values as COM `VARIANT` objects, and string serialization preserves any value that does not have a direct OPC UA counterpart. ### Why ElapsedTime maps to Double Galaxy `ElapsedTime` (mx_data_type 7) represents a duration/timespan. OPC UA has no native `TimeSpan` type. The OPC UA specification defines a `Duration` type alias (NodeId i=290) that is semantically a `Double` representing milliseconds, but the simpler approach is to map directly to `Double` (i=11) representing seconds. This avoids ambiguity about whether the value is in seconds or milliseconds and matches how the Galaxy runtime exposes elapsed time values through MXAccess. ## Array Handling Galaxy attributes with `is_array = 1` in the repository are exposed as one-dimensional OPC UA array variables. ### ValueRank The `ValueRank` property on the OPC UA variable node indicates the array dimensionality: | `is_array` | ValueRank | Constant | |:---:|:---------:|----------| | 0 | -1 | `ValueRanks.Scalar` | | 1 | 1 | `ValueRanks.OneDimension` | ### ArrayDimensions When `ValueRank = 1`, the `ArrayDimensions` property is set to a single-element `ReadOnlyList` containing the declared array length from `array_dimension`: ```csharp if (attr.IsArray && attr.ArrayDimension.HasValue) { variable.ArrayDimensions = new ReadOnlyList( new List { (uint)attr.ArrayDimension.Value }); } ``` The `array_dimension` value is extracted from the `mx_value` binary column in the Galaxy database (bytes 13-16, little-endian int32). ### NodeId for array variables Array variables use a NodeId without the `[]` suffix. The `full_tag_reference` stored internally for MXAccess addressing retains the `[]` (e.g., `MESReceiver_001.MoveInPartNumbers[]`), but the OPC UA NodeId strips it to `ns=1;s=MESReceiver_001.MoveInPartNumbers`. ## Security Classification to AccessLevel Mapping Galaxy attributes carry a `security_classification` value that controls write permissions. `SecurityClassificationMapper.IsWritable` determines the OPC UA `AccessLevel`: | security_classification | Galaxy level | OPC UA AccessLevel | Writable | |:---:|--------------|-------------------|:--------:| | 0 | FreeAccess | CurrentReadOrWrite | Yes | | 1 | Operate | CurrentReadOrWrite | Yes | | 2 | SecuredWrite | CurrentRead | No | | 3 | VerifiedWrite | CurrentRead | No | | 4 | Tune | CurrentReadOrWrite | Yes | | 5 | Configure | CurrentReadOrWrite | Yes | | 6 | ViewOnly | CurrentRead | No | Most attributes default to Operate (1). The mapper treats SecuredWrite, VerifiedWrite, and ViewOnly as read-only because the OPC UA server does not implement the Galaxy's multi-level authentication model. Allowing writes to SecuredWrite or VerifiedWrite attributes without proper verification would bypass Galaxy security. For historized attributes, `AccessLevels.HistoryRead` is added to the access level via bitwise OR, enabling OPC UA history read requests when a `HistorianDataSource` is configured. ## Key source files - `src/ZB.MOM.WW.LmxOpcUa.Host/Domain/MxDataTypeMapper.cs` -- Type and CLR mapping - `src/ZB.MOM.WW.LmxOpcUa.Host/Domain/SecurityClassificationMapper.cs` -- Write access mapping - `gr/data_type_mapping.md` -- Reference documentation for the full mapping table