M3 R3.2: AddHistoricalValuesAsync supports Double + Int (Int2/Int4/UInt4)

Extended the historical-write serializer from Float-only to all five analog types EnsureTagAsync
supports. Captured each type's "ON" buffer live from the native client (sandbox tag per type,
written + captured + deleted):

- The 4-byte value descriptor (C0 10 01 00) is CONSTANT across types — it does not encode the type.
- The value is u32(0) + native-width value, width by the tag's declared type:
  Float->float32, Double->double64, Int2->int16, Int4->int32, UInt4->uint32.

HistorianHistoricalWriteProtocol.SerializeAddStreamValuesBuffer now takes the HistorianDataType and
encodes accordingly (unsupported types throw ProtocolEvidenceMissingException). The orchestrator
resolves the type from the tag-info NativeDataTypeDescriptor via MapDataType. Harness capture-write
gained --data-type. Golden-tested against all five live captures + the gated write/read-back test
validated each type end-to-end through the pure-managed SDK; 281 unit tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B6mcaT2PjRFKcogzp9UkfC
This commit is contained in:
Joseph Doherty
2026-06-21 21:48:29 -04:00
parent d527784def
commit d1e96f48de
7 changed files with 137 additions and 69 deletions
+5 -3
View File
@@ -249,9 +249,11 @@ over `RemoteGrpc`: `HistorianGrpcHistoricalWriteOrchestrator` opens a write-enab
`GetTagInfosFromName` (resolves the per-tag GUID = the tag-info record's `TypeId`) →
`HistoryService.AddStreamValues` ("ON" buffer from `HistorianHistoricalWriteProtocol`, golden-tested) per
sample. The pure-managed SDK wrote a value and read it back live (gated test
`AddHistoricalValuesAsync_OverGrpc_WritesAndReadsBack`). Float value encoding only (the captured type);
gRPC-only. Capture artifacts (gitignored):
`artifacts/reverse-engineering/grpc-nonstream-capture/captureB4.ndjson`.
`AddHistoricalValuesAsync_OverGrpc_WritesAndReadsBack`). **All five analog types captured + validated**
(Float/Double/Int2/Int4/UInt4): the 4-byte value descriptor `C0 10 01 00` is **constant across types**;
the value is `u32(0) + native-width value` (float32 / double64 / int16 / int32 / uint32) selected by the
tag's declared type (the orchestrator maps it from the tag-info `NativeDataTypeDescriptor`). gRPC-only.
Capture artifacts (gitignored): `artifacts/reverse-engineering/grpc-nonstream-capture/cap-*.ndjson`.
---