feat(lmxproxy): add Connected Since and Reconnect Count to status page

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joseph Doherty
2026-03-24 13:32:46 -04:00
parent 73fe618953
commit 488a7b534b
8 changed files with 29 additions and 2 deletions

View File

@@ -16,6 +16,12 @@ namespace ZB.MOM.WW.LmxProxy.Host.Domain
/// <summary>Gets the current connection state.</summary>
ConnectionState ConnectionState { get; }
/// <summary>Gets the UTC time when the current connection was established.</summary>
DateTime ConnectedSince { get; }
/// <summary>Gets the number of times the client has reconnected since startup.</summary>
int ReconnectCount { get; }
/// <summary>Occurs when the connection state changes.</summary>
event EventHandler<ConnectionStateChangedEventArgs> ConnectionStateChanged;

View File

@@ -97,6 +97,9 @@ namespace ZB.MOM.WW.LmxProxy.Host.MxAccess
get { lock (_lock) { return _connectedSince; } }
}
/// <summary>Gets the number of times the client has reconnected since startup.</summary>
public int ReconnectCount => _reconnectCount;
// ── Internal synchronous methods ──────────
private void ConnectInternal()
@@ -278,7 +281,8 @@ namespace ZB.MOM.WW.LmxProxy.Host.MxAccess
try
{
await ConnectAsync(ct);
Log.Information("Reconnected to MxAccess successfully");
Interlocked.Increment(ref _reconnectCount);
Log.Information("Reconnected to MxAccess successfully (reconnect #{Count})", _reconnectCount);
}
catch (OperationCanceledException)
{

View File

@@ -53,6 +53,9 @@ namespace ZB.MOM.WW.LmxProxy.Host.MxAccess
// Probe state — updated by OnDataChange callback, read by monitor loop
private DateTime _lastProbeValueTime;
// Reconnect counter
private int _reconnectCount;
// Stored subscriptions for reconnect replay
private readonly Dictionary<string, Action<string, Vtq>> _storedSubscriptions
= new Dictionary<string, Action<string, Vtq>>(StringComparer.OrdinalIgnoreCase);

View File

@@ -20,6 +20,8 @@ namespace ZB.MOM.WW.LmxProxy.Host.Status
public string State { get; set; } = "";
public string NodeName { get; set; } = "";
public string GalaxyName { get; set; } = "";
public DateTime? ConnectedSince { get; set; }
public int ReconnectCount { get; set; }
}
public class SubscriptionStatus

View File

@@ -83,7 +83,9 @@ namespace ZB.MOM.WW.LmxProxy.Host.Status
statusData.Connection = new ConnectionStatus
{
IsConnected = _scadaClient.IsConnected,
State = _scadaClient.ConnectionState.ToString()
State = _scadaClient.ConnectionState.ToString(),
ConnectedSince = _scadaClient.IsConnected ? _scadaClient.ConnectedSince : (DateTime?)null,
ReconnectCount = _scadaClient.ReconnectCount
};
// Subscription stats
@@ -180,6 +182,10 @@ namespace ZB.MOM.WW.LmxProxy.Host.Status
sb.AppendLine(" <h3>Connection</h3>");
sb.AppendLine($" <p><strong>Connected:</strong> {statusData.Connection.IsConnected}</p>");
sb.AppendLine($" <p><strong>State:</strong> {statusData.Connection.State}</p>");
if (statusData.Connection.ConnectedSince.HasValue)
sb.AppendLine($" <p><strong>Connected Since:</strong> {statusData.Connection.ConnectedSince.Value:yyyy-MM-dd HH:mm:ss} UTC</p>");
if (statusData.Connection.ReconnectCount > 0)
sb.AppendLine($" <p><strong>Reconnects:</strong> {statusData.Connection.ReconnectCount}</p>");
if (!string.IsNullOrEmpty(statusData.Connection.NodeName))
sb.AppendLine($" <p><strong>Node:</strong> {statusData.Connection.NodeName}</p>");
if (!string.IsNullOrEmpty(statusData.Connection.GalaxyName))