feat(galaxy): per-code OPC UA mapping for the MxStatusDetail vocabulary
Follow-up to 20a816db: mxaccessgw published the full MxStatusDetail enum
(gateway.md @ 75c71ad, "MxStatus Detail Vocabulary", lifted from
Interop.aaMxDataConsumer.MxStatusDetail), confirming the live-captured codes
(1007 = MX_E_NotWriteable, 1008 = MX_E_WriteAccessDenied). FromCategory now
maps the write-relevant band per code before falling back to the category
bucket: 1004 -> BadOutOfRange, 1005 -> BadTypeMismatch, 1006 -> BadNotReadable,
1007 -> BadNotWritable, 1008/1012/1013/1016/1017 -> BadUserAccessDenied,
1010/1011 (initializing, transient) -> BadOutOfService. 8000
(MX_E_AutomationObjectSpecificError) deliberately stays category-level — the
object supplies its own semantics. Codes <= 0xFF are value-ambiguous with the
OPC DA quality-byte space and keep the quality path (still Bad-family).
Four new named constants, all validated by StatusCodeParityTests against the
pinned SDK. Live refusal smoke re-run green (read-only refusal now surfaces
BadNotWritable instead of generic Bad).
This commit is contained in:
@@ -53,6 +53,10 @@ internal static class StatusCodeMap
|
||||
public const uint BadWaitingForInitialData = 0x80320000u;
|
||||
public const uint BadInternalError = 0x80020000u;
|
||||
public const uint BadUserAccessDenied = 0x801F0000u;
|
||||
public const uint BadOutOfRange = 0x803C0000u;
|
||||
public const uint BadTypeMismatch = 0x80740000u;
|
||||
public const uint BadNotReadable = 0x803A0000u;
|
||||
public const uint BadNotWritable = 0x803B0000u;
|
||||
|
||||
/// <summary>
|
||||
/// Fills a still-pending read when the caller's token fires before the gateway answers. Named here
|
||||
@@ -137,13 +141,33 @@ internal static class StatusCodeMap
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Map a failure row by its <see cref="MxStatusCategory"/> — used when the detail field is
|
||||
/// an MxStatus detail code rather than an OPC DA quality byte (or contradicts the failure).
|
||||
/// Category-level only: the MxStatus detail vocabulary (1007, 1008, …) is not mapped
|
||||
/// per-code yet, so the log line carries the raw detail for field capture.
|
||||
/// Map a failure row whose detail field is an MxStatus detail code rather than an OPC DA
|
||||
/// quality byte (or contradicts the failure). Per-code first — the <c>MxStatusDetail</c>
|
||||
/// vocabulary is published in mxaccessgw's gateway.md ("MxStatus Detail Vocabulary",
|
||||
/// <c>75c71ad</c>, lifted from <c>Interop.aaMxDataConsumer.MxStatusDetail</c>) — then the
|
||||
/// category bucket. Codes ≤ 0xFF (e.g. 1 = MX_E_RequestTimedOut) never reach here: they are
|
||||
/// value-ambiguous with the quality-byte space and take the quality path, which still lands
|
||||
/// them in the Bad family.
|
||||
/// </summary>
|
||||
private static uint FromCategory(MxStatusProxy status, ILogger? logger)
|
||||
{
|
||||
switch (status.Detail)
|
||||
{
|
||||
case 1004: return BadOutOfRange; // MX_E_DataOutOfRange
|
||||
case 1005: return BadTypeMismatch; // MX_E_IncorrectDataType
|
||||
case 1006: return BadNotReadable; // MX_E_NotReadable
|
||||
case 1007: return BadNotWritable; // MX_E_NotWriteable (live-captured: read-only attr)
|
||||
case 1008: // MX_E_WriteAccessDenied (live-captured: unadvised no-login write)
|
||||
case 1012: // MX_E_SecuredWrite (attribute requires a secured write)
|
||||
case 1013: // MX_E_VerifiedWrite (attribute requires a verified write)
|
||||
case 1016: // MX_E_UserNotHavingAccessRights
|
||||
case 1017: return BadUserAccessDenied; // MX_E_VerifierNotHavingVerifyRights
|
||||
case 1010: // MX_E_ObjectInitializing (transient)
|
||||
case 1011: return BadOutOfService; // MX_E_EngineInitializing (transient)
|
||||
}
|
||||
|
||||
// Everything else — including 8000 MX_E_AutomationObjectSpecificError, deliberately, since
|
||||
// the object supplies its own semantics — falls back to the category bucket.
|
||||
var code = status.Category switch
|
||||
{
|
||||
MxStatusCategory.SecurityError => BadUserAccessDenied,
|
||||
|
||||
Reference in New Issue
Block a user