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:
@@ -227,7 +227,17 @@ namespace AVEVA.Historian.Grpc2023CaptureHarness
|
||||
string tagName = GetOption(args, "--tag") ?? "SdkM3CaptureSandbox";
|
||||
bool create = args.Contains("--create");
|
||||
bool commit = args.Contains("--commit");
|
||||
float sampleValue = float.TryParse(GetOption(args, "--value"), out float fv) ? fv : 123.0f;
|
||||
string dataType = GetOption(args, "--data-type") ?? "Float"; // Float|Double|Int2|Int4|UInt4
|
||||
string rawValue = GetOption(args, "--value") ?? "123";
|
||||
// Box the value as the CLR type the HistorianDataValue expects for this tag type.
|
||||
object sampleValue = dataType switch
|
||||
{
|
||||
"Double" => (object)double.Parse(rawValue),
|
||||
"Int2" => (object)short.Parse(rawValue),
|
||||
"Int4" => (object)int.Parse(rawValue),
|
||||
"UInt4" => (object)uint.Parse(rawValue),
|
||||
_ => (object)float.Parse(rawValue),
|
||||
};
|
||||
string? user = Environment.GetEnvironmentVariable("HISTORIAN_USER");
|
||||
string? password = Environment.GetEnvironmentVariable("HISTORIAN_PASSWORD");
|
||||
if (string.IsNullOrEmpty(user))
|
||||
@@ -278,7 +288,7 @@ namespace AVEVA.Historian.Grpc2023CaptureHarness
|
||||
object tag = Activator.CreateInstance(tagType)!;
|
||||
SetProp(tag, "TagName", tagName);
|
||||
TrySetProp(tag, "TagDescription", "histsdk M3 non-streamed-write capture sandbox");
|
||||
TrySetProp(tag, "TagDataType", Enum.Parse(tagDataTypeEnum, "Float", true));
|
||||
TrySetProp(tag, "TagDataType", Enum.Parse(tagDataTypeEnum, dataType, true));
|
||||
TrySetProp(tag, "TagStorageType", Enum.Parse(tagStorageEnum, "Cyclic", true));
|
||||
object addErr = Activator.CreateInstance(errorType)!;
|
||||
object?[] addArgs = { tag, 0u, addErr };
|
||||
@@ -332,7 +342,7 @@ namespace AVEVA.Historian.Grpc2023CaptureHarness
|
||||
// --- build the historical (backfill) value ---
|
||||
object value = Activator.CreateInstance(valueType)!;
|
||||
SetProp(value, "TagKey", tagKey);
|
||||
TrySetProp(value, "DataValueType", Enum.Parse(valueDataTypeEnum, "Float", true));
|
||||
TrySetProp(value, "DataValueType", Enum.Parse(valueDataTypeEnum, dataType, true));
|
||||
TrySetProp(value, "OpcQuality", (ushort)192);
|
||||
TrySetProp(value, "Value", sampleValue);
|
||||
DateTime ts = DateTime.UtcNow.AddHours(-2); // backfill = past timestamp
|
||||
|
||||
Reference in New Issue
Block a user