Implement LmxOpcUa server — all 6 phases complete
Full OPC UA server on .NET Framework 4.8 (x86) exposing AVEVA System Platform Galaxy tags via MXAccess. Mirrors Galaxy object hierarchy as OPC UA address space, translating contained-name browse paths to tag-name runtime references. Components implemented: - Configuration: AppConfiguration with 4 sections, validator - Domain: ConnectionState, Quality, Vtq, MxDataTypeMapper, error codes - MxAccess: StaComThread, MxAccessClient (partial classes), MxProxyAdapter using strongly-typed ArchestrA.MxAccess COM interop - Galaxy Repository: SQL queries (hierarchy, attributes, change detection), ChangeDetectionService with auto-rebuild on deploy - OPC UA Server: LmxNodeManager (CustomNodeManager2), LmxOpcUaServer, OpcUaServerHost with programmatic config, SecurityPolicy None - Status Dashboard: HTTP server with HTML/JSON/health endpoints - Integration: Full 14-step startup, graceful shutdown, component wiring 175 tests (174 unit + 1 integration), all passing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
54
src/ZB.MOM.WW.LmxOpcUa.Host/Domain/QualityMapper.cs
Normal file
54
src/ZB.MOM.WW.LmxOpcUa.Host/Domain/QualityMapper.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
namespace ZB.MOM.WW.LmxOpcUa.Host.Domain
|
||||
{
|
||||
/// <summary>
|
||||
/// Maps MXAccess integer quality to domain Quality enum and OPC UA StatusCodes. (MXA-009, OPC-005)
|
||||
/// </summary>
|
||||
public static class QualityMapper
|
||||
{
|
||||
/// <summary>
|
||||
/// Maps an MXAccess quality integer (OPC DA quality byte) to domain Quality.
|
||||
/// Uses category bits: 192+ = Good, 64-191 = Uncertain, 0-63 = Bad.
|
||||
/// </summary>
|
||||
public static Quality MapFromMxAccessQuality(int mxQuality)
|
||||
{
|
||||
var b = (byte)(mxQuality & 0xFF);
|
||||
|
||||
// Try exact match first
|
||||
if (System.Enum.IsDefined(typeof(Quality), b))
|
||||
return (Quality)b;
|
||||
|
||||
// Fall back to category
|
||||
if (b >= 192) return Quality.Good;
|
||||
if (b >= 64) return Quality.Uncertain;
|
||||
return Quality.Bad;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps domain Quality to OPC UA StatusCode uint32.
|
||||
/// </summary>
|
||||
public static uint MapToOpcUaStatusCode(Quality quality)
|
||||
{
|
||||
return quality switch
|
||||
{
|
||||
Quality.Good => 0x00000000u, // Good
|
||||
Quality.GoodLocalOverride => 0x00D80000u, // Good_LocalOverride
|
||||
Quality.Uncertain => 0x40000000u, // Uncertain
|
||||
Quality.UncertainLastUsable => 0x40900000u,
|
||||
Quality.UncertainSensorNotAccurate => 0x40930000u,
|
||||
Quality.UncertainEuExceeded => 0x40940000u,
|
||||
Quality.UncertainSubNormal => 0x40950000u,
|
||||
Quality.Bad => 0x80000000u, // Bad
|
||||
Quality.BadConfigError => 0x80890000u,
|
||||
Quality.BadNotConnected => 0x808A0000u,
|
||||
Quality.BadDeviceFailure => 0x808B0000u,
|
||||
Quality.BadSensorFailure => 0x808C0000u,
|
||||
Quality.BadCommFailure => 0x80050000u,
|
||||
Quality.BadOutOfService => 0x808D0000u,
|
||||
Quality.BadWaitingForInitialData => 0x80320000u,
|
||||
_ => quality.IsGood() ? 0x00000000u :
|
||||
quality.IsUncertain() ? 0x40000000u :
|
||||
0x80000000u
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user