Scope alarm tracking to selected templates and surface endpoint/security state on the dashboard so operators can deploy in large galaxies without drowning clients in irrelevant alarms or guessing what the server is advertising

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joseph Doherty
2026-04-13 09:48:57 -04:00
parent c5ed5312a9
commit 517d92c76f
25 changed files with 1511 additions and 12 deletions
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
@@ -18,6 +19,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Host.OpcUa
public class OpcUaServerHost : IDisposable
{
private static readonly ILogger Log = Serilog.Log.ForContext<OpcUaServerHost>();
private readonly AlarmObjectFilter? _alarmObjectFilter;
private readonly AuthenticationConfiguration _authConfig;
private readonly IUserAuthenticationProvider? _authProvider;
@@ -42,7 +44,8 @@ namespace ZB.MOM.WW.LmxOpcUa.Host.OpcUa
AuthenticationConfiguration? authConfig = null,
IUserAuthenticationProvider? authProvider = null,
SecurityProfileConfiguration? securityConfig = null,
RedundancyConfiguration? redundancyConfig = null)
RedundancyConfiguration? redundancyConfig = null,
AlarmObjectFilter? alarmObjectFilter = null)
{
_config = config;
_mxAccessClient = mxAccessClient;
@@ -52,6 +55,7 @@ namespace ZB.MOM.WW.LmxOpcUa.Host.OpcUa
_authProvider = authProvider;
_securityConfig = securityConfig ?? new SecurityProfileConfiguration();
_redundancyConfig = redundancyConfig ?? new RedundancyConfiguration();
_alarmObjectFilter = alarmObjectFilter;
}
/// <summary>
@@ -69,6 +73,45 @@ namespace ZB.MOM.WW.LmxOpcUa.Host.OpcUa
/// </summary>
public bool IsRunning => _server != null;
/// <summary>
/// Gets the list of opc.tcp base addresses the server is currently listening on.
/// Returns an empty list when the server has not started.
/// </summary>
public IReadOnlyList<string> BaseAddresses
{
get
{
var addrs = _application?.ApplicationConfiguration?.ServerConfiguration?.BaseAddresses;
return addrs != null ? addrs.ToList() : Array.Empty<string>();
}
}
/// <summary>
/// Gets the list of active security policies advertised to clients (SecurityMode + PolicyUri).
/// Returns an empty list when the server has not started.
/// </summary>
public IReadOnlyList<ServerSecurityPolicy> SecurityPolicies
{
get
{
var policies = _application?.ApplicationConfiguration?.ServerConfiguration?.SecurityPolicies;
return policies != null ? policies.ToList() : Array.Empty<ServerSecurityPolicy>();
}
}
/// <summary>
/// Gets the list of user token policy names advertised to clients (Anonymous, UserName, Certificate).
/// Returns an empty list when the server has not started.
/// </summary>
public IReadOnlyList<string> UserTokenPolicies
{
get
{
var policies = _application?.ApplicationConfiguration?.ServerConfiguration?.UserTokenPolicies;
return policies != null ? policies.Select(p => p.TokenType.ToString()).ToList() : Array.Empty<string>();
}
}
/// <summary>
/// Stops the host and releases server resources.
/// </summary>
@@ -195,7 +238,8 @@ namespace ZB.MOM.WW.LmxOpcUa.Host.OpcUa
}
_server = new LmxOpcUaServer(_config.GalaxyName, _mxAccessClient, _metrics, _historianDataSource,
_config.AlarmTrackingEnabled, _authConfig, _authProvider, _redundancyConfig, applicationUri);
_config.AlarmTrackingEnabled, _authConfig, _authProvider, _redundancyConfig, applicationUri,
_alarmObjectFilter);
await _application.Start(_server);
Log.Information(