Boolean historization broken: EnsureTags(Int1) is server-degenerate — remap Boolean off Int1 #441
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
The Gateway historian driver maps
DriverDataType.Boolean → HistorianDataType.Int1(
HistorianTypeMapper, pinned byHistorianTypeMapperTests[InlineData(Boolean, Int1)]and the0.2.0 proto3-presence tests). But
EnsureTags(Int1)cannot provision a usable tag against a realAVEVA Historian —
Int1is a Discrete/Boolean type and the gateway's analog tag-creation path storesa degenerate tag, so the historian rejects/degrades it. Boolean historized tags therefore fail
auto-provisioning.
Surfaced by the live gate
EnsureTags_boolean_sandbox_provisions_as_Int1(
tests/Drivers/.../Live/GatewayLiveIntegrationTests.cs) — the one red case in the R2-06Category=LiveIntegrationrun (5/6).Upstream root cause (now confirmed + closed on the gateway side)
HistorianGateway issue #11 investigated this with a live probe against the 2023 R2 historian
(2026-07-14) and proved
Int1is server-degenerate on the analog path, identical toUInt1:EnsureTags.BSuccess0x02(Discrete)false0x81(Boolean)true0x29trueThe
0x81case even reportssuccess=truebut stores an unusable stub → a subsequent historical/livewrite fails on the
GetTagInfoGUID lookup. Creating an Int1/Boolean tag needs a discrete-tag paththat was never reverse-engineered.
HistorianGateway has (PR #16) documented Int1 as an explicit, evidence-based exclusion
(
ProtocolEvidenceMissingException→ gRPCUnimplemented) and reconciled its docs. The gatewaybehaviour OtOpcUa sees is unchanged —
EnsureTags(Int1)surfaces as per-tagsuccess=false/error="ProtocolEvidenceMissingException"; the batch is not aborted, deploy is not blocked, and apre-existing Float Boolean tag is neither retyped nor data-lost.
What OtOpcUa should decide
Boolean historization against this historian is not possible via Int1. Options:
Int2) inHistorianTypeMapperand store 0/1.Boolean values round-trip as a small int; simplest path to a green live gate. Update
HistorianTypeMapperTests+GatewayTagProvisionerTests+ the live gate expectation.explicit "Boolean historization unsupported" assertion, matching the fire-and-forget
failed=Nreality.
Recommendation: option 1 (Boolean → Int2) unless a caller specifically needs the historian tag
typed as discrete/boolean.
Refs
histsdk/docs/reverse-engineering/int1-write-degenerate-capture.md(live probe record)src/Drivers/ZB.MOM.WW.OtOpcUa.Driver.Historian.Gateway/(HistorianTypeMapper,GatewayTagProvisioner); live gateGatewayLiveIntegrationTests.EnsureTags_boolean_sandbox_provisions_as_Int1Implemented option 1 (Boolean → Int2) in PR #442.
HistorianTypeMappernow mapsDriverDataType.Boolean → HistorianDataType.Int2and Boolean historizes as a small 0/1 integer. Int2 is a proven-creatable analog type (the #11 sweep: Int2/UInt2/Int4/UInt4/Float/Double all provision; only Int1 fails), and the value-write path already sends every value as adoubleonWriteLiveValuesregardless of tag type, so a Boolean0.0/1.0round-trips cleanly. Both Float and Int2 are supported analog types, so a pre-existing Float Boolean tag retypes cleanly on its next deploy — no Int1 gap.Unit pins updated (
HistorianTypeMapperTests,GatewayTagProvisionerTests.Boolean_definition_carries_explicit_Int2_presence), the live gate renamedEnsureTags_boolean_sandbox_provisions_as_Int2(retype probe reframed Float→Int2), docs updated (docs/Historian.md,CLAUDE.md, archreviewSTATUS.md→ R2-06 live gate 6/6). Gateway driver unit 103/103, full build clean. Closes on merge of #442.