feat(historian): GatewayHistorianProvider; status→DA quality reverse mapping

Claude-Session: https://claude.ai/code/session_01Ef2ozxS7QPanGT8uoATbTe
This commit is contained in:
Joseph Doherty
2026-10-09 12:47:09 -04:00
parent ff7c6c531a
commit 8c8e243de6
6 changed files with 198 additions and 5 deletions
@@ -43,4 +43,36 @@ internal static class GatewayQualityMapper
_ when q >= 64 => HistorianStatusCodes.Uncertain,
_ => HistorianStatusCodes.Bad,
};
/// <summary>
/// Reverse of <see cref="Map"/>: maps an OPC UA StatusCode to the OPC DA quality byte the gateway
/// expects. Every explicit <see cref="Map"/> entry round-trips; an unknown status falls back to its
/// severity bucket (Good 192, Uncertain 64, Bad 0).
/// </summary>
/// <param name="statusCode">The OPC UA StatusCode.</param>
/// <returns>The OPC DA quality byte.</returns>
public static byte ToDaQuality(uint statusCode) => statusCode switch
{
HistorianStatusCodes.Good => 192,
HistorianStatusCodes.GoodLocalOverride => 216,
HistorianStatusCodes.Uncertain => 64,
HistorianStatusCodes.UncertainLastUsableValue => 68,
HistorianStatusCodes.UncertainSensorNotAccurate => 80,
HistorianStatusCodes.UncertainEngineeringUnitsExceeded => 84,
HistorianStatusCodes.UncertainSubNormal => 88,
HistorianStatusCodes.Bad => 0,
HistorianStatusCodes.BadConfigurationError => 4,
HistorianStatusCodes.BadNotConnected => 8,
HistorianStatusCodes.BadDeviceFailure => 12,
HistorianStatusCodes.BadSensorFailure => 16,
HistorianStatusCodes.BadCommunicationError => 20,
HistorianStatusCodes.BadOutOfService => 24,
HistorianStatusCodes.BadWaitingForInitialData => 32,
_ => (statusCode >> 30) switch
{
0 => (byte)192,
1 => (byte)64,
_ => (byte)0,
},
};
}