namespace ZB.MOM.WW.OtOpcUa.Driver.Historian.SqlServer; /// /// Every OPC UA status this backend emits, as named constants (inline literals are invisible to /// StatusCodeParityTests). Values mirror Opc.Ua.StatusCodes. /// internal static class SqlHistorianStatusCodes { public const uint Good = 0x00000000u; public const uint GoodEntryInserted = 0x00A20000u; public const uint GoodEntryReplaced = 0x00A30000u; public const uint BadNoData = 0x809B0000u; public const uint BadEntryExists = 0x809F0000u; public const uint BadNoEntryExists = 0x80A00000u; public const uint BadInvalidTimestamp = 0x80230000u; public const uint BadAggregateInvalidInputs = 0x80D60000u; public const uint UncertainDataSubNormal = 0x40A40000u; /// Stored for a non-finite Double (NaN / ±Infinity) that arrived with a non-Bad status. public const uint BadOutOfRange = 0x803C0000u; } /// /// Bit masks over a 32-bit OPC UA status code (Part 4 §7.39). These are masks, not emitted codes, so their /// names deliberately avoid the Good/Bad/Uncertain prefix the status-code parity scan keys on. /// internal static class StatusBits { /// Severity + sub-code (top 16 bits) of a status, i.e. the code without info bits. public const uint CodeBitsMask = 0xFFFF0000u; /// The two severity bits (Good = 00, Uncertain = 01, Bad = 10). public const uint SeverityMask = 0xC0000000u; /// The severity bit set on every Bad code. public const uint SeverityBadBit = 0x80000000u; /// The two historian info bits (Calculated, Interpolated) in the low bits of the info field. public const uint HistorianBitsMask = 0x3u; /// True when has Bad severity. /// A status code. /// Whether the Bad severity bit is set. public static bool IsBad(uint status) => (status & SeverityBadBit) != 0; /// True when has Good severity. /// A status code. /// Whether both severity bits are clear. public static bool IsGood(uint status) => (status & SeverityMask) == 0; } /// Part 4 §7.39 historian info bits OR-ed onto a status code. internal static class HistorianInfoBits { /// InfoType = DataValue. public const uint InfoTypeDataValue = 0x00000400u; /// The value was produced by an aggregate calculation. public const uint HistorianCalculated = 0x1u; /// The value was interpolated. public const uint HistorianInterpolated = 0x2u; /// /// Marks as a Calculated data value. Any historian bits the status already carries /// (e.g. a stored Interpolated sample) are cleared first, so the result is never both. /// /// Base status code. /// Status with InfoType and Calculated bits set. public static uint WithCalculated(uint status) => (status & ~StatusBits.HistorianBitsMask) | InfoTypeDataValue | HistorianCalculated; /// /// Marks as an Interpolated data value. Any historian bits the status already /// carries (e.g. a stored Calculated sample) are cleared first, so the result is never both. /// /// Base status code. /// Status with InfoType and Interpolated bits set. public static uint WithInterpolated(uint status) => (status & ~StatusBits.HistorianBitsMask) | InfoTypeDataValue | HistorianInterpolated; }