feat(lmxproxy): add MxAccess status detail mapping for richer error messages
- MxStatusMapper: maps all 40+ MxStatusDetail codes, MxStatusCategory, and MxStatusSource to human-readable names and client messages - OnDataChange: checks MXSTATUS_PROXY.success and overrides quality with specific OPC UA code when MxAccess reports a failure (e.g., CommFailure, ConfigError, WaitingForInitialData) - OnWriteComplete: uses MxStatusMapper.FormatStatus for structured logging - Write errors: catches COMException separately with HRESULT in message - Read errors: distinguishes COM, timeout, and generic failures in logging Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using ArchestrA.MxAccess;
|
||||
using Serilog;
|
||||
using ZB.MOM.WW.LmxProxy.Host.Domain;
|
||||
@@ -31,6 +29,17 @@ namespace ZB.MOM.WW.LmxProxy.Host.MxAccess
|
||||
{
|
||||
var quality = MapQuality(pwItemQuality);
|
||||
var timestamp = ConvertTimestamp(pftItemTimeStamp);
|
||||
|
||||
// Check MXSTATUS_PROXY — if success is false, override quality
|
||||
// with a more specific code derived from the MxAccess status fields
|
||||
if (ItemStatus != null && ItemStatus.Length > 0 && ItemStatus[0].success == 0)
|
||||
{
|
||||
var status = ItemStatus[0];
|
||||
quality = MxStatusMapper.CategoryToQuality((int)status.category, status.detail);
|
||||
Log.Debug("OnDataChange status failure for handle {Handle}: {Status}",
|
||||
phItemHandle, MxStatusMapper.FormatStatus(status.detail, (int)status.category, (int)status.detectedBy));
|
||||
}
|
||||
|
||||
var vtq = new Vtq(pvItemValue, timestamp, quality);
|
||||
|
||||
// Resolve address from handle map
|
||||
@@ -84,9 +93,8 @@ namespace ZB.MOM.WW.LmxProxy.Host.MxAccess
|
||||
var status = ItemStatus[0];
|
||||
if (status.success == 0)
|
||||
{
|
||||
string errorMsg = GetWriteErrorMessage(status.detail);
|
||||
Log.Warning("OnWriteComplete callback: write failed for handle {Handle}: {Error} (Category={Category}, Detail={Detail})",
|
||||
phItemHandle, errorMsg, status.category, status.detail);
|
||||
Log.Warning("OnWriteComplete callback: write failed for handle {Handle}: {Status}",
|
||||
phItemHandle, MxStatusMapper.FormatStatus(status.detail, (int)status.category, (int)status.detectedBy));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -104,20 +112,6 @@ namespace ZB.MOM.WW.LmxProxy.Host.MxAccess
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a human-readable error message for a write error code.
|
||||
/// </summary>
|
||||
private static string GetWriteErrorMessage(int errorCode)
|
||||
{
|
||||
switch (errorCode)
|
||||
{
|
||||
case 1008: return "User lacks proper security for write operation";
|
||||
case 1012: return "Secured write required";
|
||||
case 1013: return "Verified write required";
|
||||
default: return string.Format("Unknown error code: {0}", errorCode);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a timestamp object to DateTime in UTC.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user