fix(historian): map Boolean historization to Int2, not degenerate Int1 (#441)
The historian's Int1 analog-tag creation path is server-degenerate: EnsureTags(Int1) stores an unusable stub (live-probed on the deployed 2023 R2 historian; root-caused + documented gateway-side in HistorianGateway #11 / PR #16). HistorianTypeMapper mapped DriverDataType.Boolean -> HistorianDataType.Int1, so Boolean historized tags failed auto-provisioning. Map Boolean -> Int2 instead (store 0/1). Int2 is a proven-creatable analog type, and the value-write path already sends every value as a double on WriteLiveValues regardless of tag type, so Boolean 0.0/1.0 round-trips cleanly. Both Float and Int2 are supported, so a pre-existing Float Boolean tag retypes cleanly on its next deploy. - HistorianTypeMapper: Boolean => Int2 (+ remarks) - Unit pins: HistorianTypeMapperTests, GatewayTagProvisionerTests (Boolean_definition_carries_explicit_Int2_presence) - Live gate: EnsureTags_boolean_sandbox_provisions_as_Int2 (was _Int1); retype probe reframed Float->Int2 (drops the dead Int1 leg) - Docs: docs/Historian.md 'Boolean historization maps to Int2', CLAUDE.md, archreview STATUS.md (R2-06 live gate -> 6/6) Resolves #441.
This commit is contained in:
+10
-6
@@ -9,11 +9,14 @@ namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway.Mapping;
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Only the nine numeric types are historizable on the gateway's analog write path. Two of them
|
||||
/// fall back to a wider historian type because the narrower one's write path is deferred upstream:
|
||||
/// <see cref="DriverDataType.UInt16"/> maps to <see cref="HistorianDataType.Uint4"/> (the historian's
|
||||
/// <c>UInt2</c> write path is not proven). String / DateTime / Reference are not historized in v1
|
||||
/// and throw <see cref="NotSupportedException"/>; callers that want to skip them without catching an
|
||||
/// exception should consult <see cref="IsHistorizable(DriverDataType)"/> first.
|
||||
/// fall back to a wider/adjacent historian type because the exact one's write path is not usable
|
||||
/// upstream: <see cref="DriverDataType.UInt16"/> maps to <see cref="HistorianDataType.Uint4"/> (the
|
||||
/// historian's <c>UInt2</c> write path is not proven), and <see cref="DriverDataType.Boolean"/> maps
|
||||
/// to <see cref="HistorianDataType.Int2"/> — the historian's <c>Int1</c> analog-tag creation path is
|
||||
/// server-degenerate (issue #441 / HistorianGateway #11: <c>EnsureTags(Int1)</c> stores an unusable
|
||||
/// stub), so Boolean historizes as a small 0/1 integer instead. String / DateTime / Reference are not
|
||||
/// historized in v1 and throw <see cref="NotSupportedException"/>; callers that want to skip them
|
||||
/// without catching an exception should consult <see cref="IsHistorizable(DriverDataType)"/> first.
|
||||
/// </remarks>
|
||||
internal static class HistorianTypeMapper
|
||||
{
|
||||
@@ -25,7 +28,8 @@ internal static class HistorianTypeMapper
|
||||
/// </exception>
|
||||
public static HistorianDataType ToHistorianDataType(DriverDataType dataType) => dataType switch
|
||||
{
|
||||
DriverDataType.Boolean => HistorianDataType.Int1,
|
||||
DriverDataType.Boolean => HistorianDataType.Int2, // Int1 analog-tag creation is server-degenerate (issue #441) → store 0/1
|
||||
|
||||
DriverDataType.Int16 => HistorianDataType.Int2,
|
||||
DriverDataType.Int32 => HistorianDataType.Int4,
|
||||
DriverDataType.Int64 => HistorianDataType.Int8,
|
||||
|
||||
Reference in New Issue
Block a user