namespace MxAsbClient; public enum AsbErrorCode : ushort { Success = 0, InvalidConnectionId = 1, ApplicationAuthenticationError = 2, UserAuthenticationError = 3, UserAuthorizationError = 4, NotSupportedOperation = 5, MonitoredItemsNotFound = 6, InvalidSubscriptionId = 7, ItemAlreadyRegistered = 8, ItemAlreadyDeletedOrDoesNotExist = 9, InvalidMonitoredItems = 10, OperationFailed = 11, SpecificError = 12, BadNoCommunication = 13, BadNothingToDo = 14, BadTooManyOperations = 15, BadNodeIdInvalid = 16, BrowseFailed = 17, WriteFailedBadOutOfRange = 18, WriteFailedBadTypeMismatch = 19, WriteFailedBadDimensionMismatch = 20, WriteFailedAccessDenied = 21, WriteFailedSecuredWrite = 22, WriteFailedVerifiedWrite = 23, IndexOutOfRange = 24, RequestTimedOut = 25, DataTypeConversionNotSupported = 26, ItemCannotBeRegisteredNoName = 27, ItemCannotBeRegisteredNoId = 28, ItemAlreadyBeingMonitored = 29, SubscriptionIdAlreadyExist = 30, OperationWouldBlock = 31, PublishComplete = 32, WriteFailedUserNotHavingAccessRights = 33, WriteFailedVerifierNotHavingVerifyRights = 34, ObjectNotInitialized = 128, EndPointNotFound = 129, ConnectionClosed = 130, InvalidParameter = 131, MemoryAllocationError = 132, OperationNotComplete = 133, FileOperationFailed = 256, InvalidXmlFile = 272, RecordLookupError = 288, Unknown = ushort.MaxValue, } public enum AsbStatusQuality { Unknown = 0, Bad = 1, Uncertain = 2, Good = 3, } public enum AsbMxStatusCategory { Unknown = -1, Ok = 0, Pending = 1, Warning = 2, CommunicationError = 3, ConfigurationError = 4, OperationalError = 5, SecurityError = 6, SoftwareError = 7, OtherError = 8, } public enum AsbMxStatusDetail { Unknown = -1, None = 0, RequestTimedOut = 16, PlatformCommunicationError = 17, WriteAccessDenied = 33, } public sealed record AsbResultSummary( AsbErrorCode Error, int RawErrorCode, uint Status, uint SpecificErrorCode, bool IsSuccess, bool IsSuccessLike); public sealed record AsbItemStatusSummary( string? ItemName, ulong ItemId, AsbErrorCode Error, ushort RawErrorCode, bool IsSuccess, IReadOnlyList Status) { public AsbStatusSummary StatusSummary { get; init; } = AsbResultMapper.ToStatusSummary(Status); } public sealed record AsbStatusSummary( ushort? RawQuality, AsbStatusQuality Quality, ushort? RawCategory, AsbMxStatusCategory Category, ushort? RawDetail, AsbMxStatusDetail Detail, AsbErrorCode? StatusError, bool IsGoodQuality, bool IsSuccessLike, IReadOnlyList Elements); public static class AsbResultMapper { public static AsbResultSummary ToSummary(ArchestrAResult result) { AsbErrorCode error = result.ErrorCode is >= 0 and <= ushort.MaxValue ? ToErrorCode((ushort)result.ErrorCode) : AsbErrorCode.Unknown; bool isSuccess = error == AsbErrorCode.Success || result.Success; return new AsbResultSummary( error, result.ErrorCode, result.Status, result.SpecificErrorCode, isSuccess, isSuccess || error == AsbErrorCode.PublishComplete); } public static AsbItemStatusSummary ToItemSummary(ItemStatus status) { AsbErrorCode error = ToErrorCode(status.ErrorCode); IReadOnlyList elements = AsbPublishMapper.DecodeStatus(status.Status); return new AsbItemStatusSummary( status.Item.Name, status.Item.Id, error, status.ErrorCode, error == AsbErrorCode.Success, elements); } public static IReadOnlyList ToItemSummaries(ItemStatus[]? statuses) { if (statuses is null || statuses.Length == 0) { return []; } AsbItemStatusSummary[] summaries = new AsbItemStatusSummary[statuses.Length]; for (int i = 0; i < statuses.Length; i++) { summaries[i] = ToItemSummary(statuses[i]); } return summaries; } public static AsbErrorCode ToErrorCode(ushort errorCode) { return Enum.IsDefined(typeof(AsbErrorCode), errorCode) ? (AsbErrorCode)errorCode : AsbErrorCode.Unknown; } public static AsbStatusSummary ToStatusSummary(AsbStatus status) { return ToStatusSummary(AsbPublishMapper.DecodeStatus(status)); } public static AsbStatusSummary ToStatusSummary(IReadOnlyList elements) { ushort? rawQuality = FirstValue(elements, AsbStatusElementType.MxQuality); ushort? rawCategory = FirstValue(elements, AsbStatusElementType.MxStatusCategory); ushort? rawDetail = FirstValue(elements, AsbStatusElementType.MxStatusDetail); AsbStatusQuality quality = ToQuality(rawQuality); AsbMxStatusCategory category = ToMxStatusCategory(rawCategory); AsbMxStatusDetail detail = ToMxStatusDetail(rawDetail); AsbErrorCode? statusError = ToStatusError(category, detail); bool isGoodQuality = quality == AsbStatusQuality.Good; bool isSuccessLike = statusError == AsbErrorCode.Success && (quality == AsbStatusQuality.Good || quality == AsbStatusQuality.Unknown); return new AsbStatusSummary( rawQuality, quality, rawCategory, category, rawDetail, detail, statusError, isGoodQuality, isSuccessLike, elements); } public static AsbStatusQuality ToQuality(ushort? quality) { if (quality is null) { return AsbStatusQuality.Unknown; } return (quality.Value & 0x00C0) switch { 0x00C0 => AsbStatusQuality.Good, 0x0040 => AsbStatusQuality.Uncertain, 0x0000 => AsbStatusQuality.Bad, _ => AsbStatusQuality.Unknown, }; } public static AsbMxStatusCategory ToMxStatusCategory(ushort? category) { return category switch { 0 => AsbMxStatusCategory.Ok, 1 => AsbMxStatusCategory.Pending, 2 => AsbMxStatusCategory.Warning, 3 => AsbMxStatusCategory.CommunicationError, 4 => AsbMxStatusCategory.ConfigurationError, 5 => AsbMxStatusCategory.OperationalError, 6 => AsbMxStatusCategory.SecurityError, 7 => AsbMxStatusCategory.SoftwareError, 8 => AsbMxStatusCategory.OtherError, _ => AsbMxStatusCategory.Unknown, }; } public static AsbMxStatusDetail ToMxStatusDetail(ushort? detail) { return detail switch { 0 => AsbMxStatusDetail.None, 16 => AsbMxStatusDetail.RequestTimedOut, 17 => AsbMxStatusDetail.PlatformCommunicationError, 33 => AsbMxStatusDetail.WriteAccessDenied, _ => AsbMxStatusDetail.Unknown, }; } private static AsbErrorCode? ToStatusError(AsbMxStatusCategory category, AsbMxStatusDetail detail) { if (category == AsbMxStatusCategory.Ok && detail == AsbMxStatusDetail.None) { return AsbErrorCode.Success; } return detail switch { AsbMxStatusDetail.RequestTimedOut => AsbErrorCode.RequestTimedOut, AsbMxStatusDetail.PlatformCommunicationError => AsbErrorCode.BadNoCommunication, AsbMxStatusDetail.WriteAccessDenied => AsbErrorCode.WriteFailedAccessDenied, _ => null, }; } private static ushort? FirstValue(IReadOnlyList elements, AsbStatusElementType type) { foreach (AsbStatusElement element in elements) { if (element.Type == type) { return element.Value; } } return null; } }