135 lines
4.6 KiB
C#
135 lines
4.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Reflection;
|
|
using MxGateway.Contracts.Proto;
|
|
|
|
namespace MxGateway.Worker.Conversion;
|
|
|
|
/// <summary>Converts MXAccess MXSTATUS_PROXY COM objects to protobuf MxStatusProxy messages.</summary>
|
|
public sealed class MxStatusProxyConverter
|
|
{
|
|
/// <summary>Converts a single status object to a protobuf message, reflecting all fields and diagnostics.</summary>
|
|
/// <param name="status">COM status object to convert.</param>
|
|
public MxStatusProxy Convert(object status)
|
|
{
|
|
if (status is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(status));
|
|
}
|
|
|
|
Type statusType = status.GetType();
|
|
int success = ReadInt32Field(status, statusType, "success");
|
|
int rawCategory = ReadInt32Field(status, statusType, "category");
|
|
int rawDetectedBy = ReadInt32Field(status, statusType, "detectedBy");
|
|
int detail = ReadInt32Field(status, statusType, "detail");
|
|
|
|
return new MxStatusProxy
|
|
{
|
|
Success = success,
|
|
Category = MapCategory(rawCategory),
|
|
DetectedBy = MapSource(rawDetectedBy),
|
|
Detail = detail,
|
|
RawCategory = rawCategory,
|
|
RawDetectedBy = rawDetectedBy,
|
|
DiagnosticText = MxStatusDetailText.Lookup(detail),
|
|
};
|
|
}
|
|
|
|
/// <summary>Converts an array of status objects, handling nulls gracefully.</summary>
|
|
/// <param name="statuses">Array of COM status objects; null returns empty list.</param>
|
|
public IReadOnlyList<MxStatusProxy> ConvertMany(Array? statuses)
|
|
{
|
|
if (statuses is null)
|
|
{
|
|
return Array.Empty<MxStatusProxy>();
|
|
}
|
|
|
|
List<MxStatusProxy> converted = new(statuses.Length);
|
|
foreach (object? status in statuses)
|
|
{
|
|
if (status is null)
|
|
{
|
|
converted.Add(new MxStatusProxy
|
|
{
|
|
Category = MxStatusCategory.Unknown,
|
|
DetectedBy = MxStatusSource.Unknown,
|
|
DiagnosticText = "Null MXSTATUS_PROXY entry.",
|
|
});
|
|
continue;
|
|
}
|
|
|
|
converted.Add(Convert(status));
|
|
}
|
|
|
|
return converted;
|
|
}
|
|
|
|
/// <summary>Preserves completion-only status bytes as a diagnostic hex string since they cannot be unpacked.</summary>
|
|
/// <param name="statusBytes">Status bytes to encode as hex string.</param>
|
|
public string PreserveCompletionOnlyStatusBytes(byte[] statusBytes)
|
|
{
|
|
if (statusBytes is null)
|
|
{
|
|
throw new ArgumentNullException(nameof(statusBytes));
|
|
}
|
|
|
|
return $"completion_only_status_hex={BitConverter.ToString(statusBytes).Replace("-", string.Empty)}";
|
|
}
|
|
|
|
private static int ReadInt32Field(
|
|
object value,
|
|
Type valueType,
|
|
string fieldName)
|
|
{
|
|
FieldInfo? field = valueType.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public);
|
|
if (field is null)
|
|
{
|
|
throw new MxStatusConversionException(
|
|
$"Status object type '{valueType.FullName}' does not expose required field '{fieldName}'.");
|
|
}
|
|
|
|
object? fieldValue = field.GetValue(value);
|
|
if (fieldValue is null)
|
|
{
|
|
throw new MxStatusConversionException(
|
|
$"Status object field '{fieldName}' on type '{valueType.FullName}' is null.");
|
|
}
|
|
|
|
return System.Convert.ToInt32(fieldValue, CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
private static MxStatusCategory MapCategory(int rawCategory)
|
|
{
|
|
return rawCategory switch
|
|
{
|
|
-1 => MxStatusCategory.Unknown,
|
|
0 => MxStatusCategory.Ok,
|
|
1 => MxStatusCategory.Pending,
|
|
2 => MxStatusCategory.Warning,
|
|
3 => MxStatusCategory.CommunicationError,
|
|
4 => MxStatusCategory.ConfigurationError,
|
|
5 => MxStatusCategory.OperationalError,
|
|
6 => MxStatusCategory.SecurityError,
|
|
7 => MxStatusCategory.SoftwareError,
|
|
8 => MxStatusCategory.OtherError,
|
|
_ => MxStatusCategory.Unknown,
|
|
};
|
|
}
|
|
|
|
private static MxStatusSource MapSource(int rawDetectedBy)
|
|
{
|
|
return rawDetectedBy switch
|
|
{
|
|
-1 => MxStatusSource.Unknown,
|
|
0 => MxStatusSource.RequestingLmx,
|
|
1 => MxStatusSource.RespondingLmx,
|
|
2 => MxStatusSource.RequestingNmx,
|
|
3 => MxStatusSource.RespondingNmx,
|
|
4 => MxStatusSource.RequestingAutomationObject,
|
|
5 => MxStatusSource.RespondingAutomationObject,
|
|
_ => MxStatusSource.Unknown,
|
|
};
|
|
}
|
|
}
|