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>
82 lines
3.2 KiB
C#
82 lines
3.2 KiB
C#
using Opc.Ua;
|
|
using Opc.Ua.Client;
|
|
using Opc.Ua.Configuration;
|
|
|
|
namespace OpcUaCli;
|
|
|
|
public static class OpcUaHelper
|
|
{
|
|
public static async Task<Session> ConnectAsync(string endpointUrl)
|
|
{
|
|
var config = new ApplicationConfiguration
|
|
{
|
|
ApplicationName = "OpcUaCli",
|
|
ApplicationUri = "urn:localhost:OpcUaCli",
|
|
ApplicationType = ApplicationType.Client,
|
|
SecurityConfiguration = new SecurityConfiguration
|
|
{
|
|
ApplicationCertificate = new CertificateIdentifier
|
|
{
|
|
StoreType = CertificateStoreType.Directory,
|
|
StorePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "OpcUaCli", "pki", "own")
|
|
},
|
|
TrustedIssuerCertificates = new CertificateTrustList
|
|
{
|
|
StoreType = CertificateStoreType.Directory,
|
|
StorePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "OpcUaCli", "pki", "issuer")
|
|
},
|
|
TrustedPeerCertificates = new CertificateTrustList
|
|
{
|
|
StoreType = CertificateStoreType.Directory,
|
|
StorePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "OpcUaCli", "pki", "trusted")
|
|
},
|
|
RejectedCertificateStore = new CertificateTrustList
|
|
{
|
|
StoreType = CertificateStoreType.Directory,
|
|
StorePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "OpcUaCli", "pki", "rejected")
|
|
},
|
|
AutoAcceptUntrustedCertificates = true
|
|
},
|
|
ClientConfiguration = new ClientConfiguration { DefaultSessionTimeout = 60000 }
|
|
};
|
|
|
|
#pragma warning disable CS0618 // Sync/obsolete API is fine for a CLI tool
|
|
await config.Validate(ApplicationType.Client);
|
|
config.CertificateValidator.CertificateValidation += (_, e) => e.Accept = true;
|
|
|
|
var endpoint = CoreClientUtils.SelectEndpoint(config, endpointUrl, false);
|
|
var endpointConfig = EndpointConfiguration.Create(config);
|
|
var configuredEndpoint = new ConfiguredEndpoint(null, endpoint, endpointConfig);
|
|
|
|
var session = await Session.Create(
|
|
config,
|
|
configuredEndpoint,
|
|
false,
|
|
"OpcUaCli",
|
|
60000,
|
|
null,
|
|
null);
|
|
|
|
return session;
|
|
#pragma warning restore CS0618
|
|
}
|
|
|
|
public static object ConvertValue(string rawValue, object? currentValue)
|
|
{
|
|
return currentValue switch
|
|
{
|
|
bool => bool.Parse(rawValue),
|
|
byte => byte.Parse(rawValue),
|
|
short => short.Parse(rawValue),
|
|
ushort => ushort.Parse(rawValue),
|
|
int => int.Parse(rawValue),
|
|
uint => uint.Parse(rawValue),
|
|
long => long.Parse(rawValue),
|
|
ulong => ulong.Parse(rawValue),
|
|
float => float.Parse(rawValue),
|
|
double => double.Parse(rawValue),
|
|
_ => rawValue
|
|
};
|
|
}
|
|
}
|