diff --git a/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs b/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs index 0b320185..392b5543 100644 --- a/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs +++ b/src/PepperDash.Essentials.MobileControl/MobileControlSystemController.cs @@ -1746,38 +1746,40 @@ namespace PepperDash.Essentials "\r\n UI Client Info:\r\n" + " Tokens Defined: {0}\r\n" + " Clients Connected: {1}\r\n", - _directServer.UiClients.Count, + _directServer.UiClientContexts.Count, _directServer.ConnectedUiClientsCount ); var clientNo = 1; - foreach (var clientContext in _directServer.UiClients) + foreach (var clientContext in _directServer.UiClientContexts) { var isAlive = false; var duration = "Not Connected"; - if (clientContext.Value.Client != null) - { - isAlive = clientContext.Value.Client.Context.WebSocket.IsAlive; - duration = clientContext.Value.Client.ConnectedDuration.ToString(); - } + var clients = _directServer.UiClients.Values.Where(c => c.Token == clientContext.Value.Token.Token); CrestronConsole.ConsoleCommandResponse( - "\r\nClient {0}:\r\n" + - "Room Key: {1}\r\n" + - "Touchpanel Key: {6}\r\n" + - "Token: {2}\r\n" + - "Client URL: {3}\r\n" + - "Connected: {4}\r\n" + - "Duration: {5}\r\n", - clientNo, - clientContext.Value.Token.RoomKey, - clientContext.Key, - string.Format("{0}{1}", _directServer.UserAppUrlPrefix, clientContext.Key), - isAlive, - duration, - clientContext.Value.Token.TouchpanelKey + $"\r\nClient {clientNo}:\r\n" + + $" Room Key: {clientContext.Value.Token.RoomKey}\r\n" + + $" Touchpanel Key: {clientContext.Value.Token.TouchpanelKey}\r\n" + + $" Token: {clientContext.Key}\r\n" + + $" Client URL: {_directServer.UserAppUrlPrefix}{clientContext.Key}\r\n" + + $" Clients:\r\n" ); + + if (!clients.Any()) + { + CrestronConsole.ConsoleCommandResponse(" No clients connected"); + } + foreach (var client in clients) + { + CrestronConsole.ConsoleCommandResponse( + $" ID: {client.Id}\r\n" + + $" Connected: {client.Context.WebSocket.IsAlive}\r\n" + + $" Duration: {(client.Context.WebSocket.IsAlive ? client.ConnectedDuration.TotalSeconds.ToString() : "Not Connected")}\r\n" + ); + } + clientNo++; } } diff --git a/src/PepperDash.Essentials.MobileControl/WebApiHandlers/MobileInfoHandler.cs b/src/PepperDash.Essentials.MobileControl/WebApiHandlers/MobileInfoHandler.cs index 588d3861..ddd319e3 100644 --- a/src/PepperDash.Essentials.MobileControl/WebApiHandlers/MobileInfoHandler.cs +++ b/src/PepperDash.Essentials.MobileControl/WebApiHandlers/MobileInfoHandler.cs @@ -117,7 +117,11 @@ namespace PepperDash.Essentials.WebApiHandlers public int ClientsConnected => directServer.ConnectedUiClientsCount; [JsonProperty("clients")] - public List Clients => directServer.UiClientContexts.Select((c, i) => { return new MobileControlDirectClient(c, i, directServer.UserAppUrlPrefix); }).ToList(); + public List Clients => directServer.UiClientContexts + .Select(context => (context, clients: directServer.UiClients.Where(client => client.Value.Token == context.Value.Token.Token).Select(c => c.Value).ToList())) + .Select((clientTuple, i) => new MobileControlDirectClient(clientTuple.clients, clientTuple.context, i, directServer.UserAppUrlPrefix)) + .ToList(); + public MobileControlDirectServer(MobileControlWebsocketServer server) { @@ -157,18 +161,39 @@ namespace PepperDash.Essentials.WebApiHandlers [JsonProperty("token")] public string Token => Key; - [JsonProperty("connected")] - public bool Connected => context.Client != null && context.Client.Context.WebSocket.IsAlive; + private readonly List clients; - [JsonProperty("duration")] - public double Duration => context.Client == null ? 0 : context.Client.ConnectedDuration.TotalSeconds; + [JsonProperty("clientStatus")] + public List ClientStatus => clients.Select(c => new ClientStatus(c)).ToList(); - public MobileControlDirectClient(KeyValuePair clientContext, int index, string urlPrefix) + /// + /// Create an instance of the class. + /// + /// List of Websocket Clients + /// Context for the client + /// Index of the client + /// URL prefix for the client + public MobileControlDirectClient(List clients, KeyValuePair context, int index, string urlPrefix) { - context = clientContext.Value; - Key = clientContext.Key; + this.context = context.Value; + Key = context.Key; clientNumber = index; this.urlPrefix = urlPrefix; + this.clients = clients; + } + } + + public class ClientStatus + { + private readonly UiClient client; + + public bool Connected => client != null && client.Context.WebSocket.IsAlive; + + public double Duration => client == null ? 0 : client.ConnectedDuration.TotalSeconds; + + public ClientStatus(UiClient client) + { + this.client = client; } } } diff --git a/src/PepperDash.Essentials.MobileControl/WebSocketServer/MobileControlWebsocketServer.cs b/src/PepperDash.Essentials.MobileControl/WebSocketServer/MobileControlWebsocketServer.cs index 0b0390aa..f62e136a 100644 --- a/src/PepperDash.Essentials.MobileControl/WebSocketServer/MobileControlWebsocketServer.cs +++ b/src/PepperDash.Essentials.MobileControl/WebSocketServer/MobileControlWebsocketServer.cs @@ -61,6 +61,11 @@ namespace PepperDash.Essentials.WebSocketServer private readonly Dictionary uiClients = new Dictionary(); + /// + /// Gets the collection of UI clients + /// + public ReadOnlyDictionary UiClients => new ReadOnlyDictionary(uiClients); + private readonly MobileControlSystemController _parent; private WebSocketServerSecretProvider _secretProvider; @@ -130,17 +135,7 @@ namespace PepperDash.Essentials.WebSocketServer { get { - var count = 0; - - foreach (var client in UiClientContexts) - { - if (client.Value.Client != null && client.Value.Client.Context.WebSocket.IsAlive) - { - count++; - } - } - - return count; + return uiClients.Values.Where(c => c.Context.WebSocket.IsAlive).Count(); } } @@ -736,7 +731,7 @@ namespace PepperDash.Essentials.WebSocketServer private UiClient BuildUiClient(string roomKey, JoinToken token, string key) { - var c = new UiClient($"uiclient-{key}-{roomKey}-{token.Id}", token.Id); + var c = new UiClient($"uiclient-{key}-{roomKey}-{token.Id}", token.Id, token.Token); this.LogInformation("Constructing UiClient with key {key} and ID {id}", key, token.Id); c.Controller = _parent; c.RoomKey = roomKey; diff --git a/src/PepperDash.Essentials.MobileControl/WebSocketServer/UiClient.cs b/src/PepperDash.Essentials.MobileControl/WebSocketServer/UiClient.cs index 79becd33..21781abc 100644 --- a/src/PepperDash.Essentials.MobileControl/WebSocketServer/UiClient.cs +++ b/src/PepperDash.Essentials.MobileControl/WebSocketServer/UiClient.cs @@ -1,5 +1,4 @@ using System; -using System.Text.RegularExpressions; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using PepperDash.Core; @@ -22,6 +21,16 @@ namespace PepperDash.Essentials.WebSocketServer /// public string Key { get; private set; } + /// + /// Client ID used by client for this connection + /// + public string Id { get; private set; } + + /// + /// Token associated with this client + /// + public string Token { get; private set; } + /// /// Gets or sets the mobile control system controller that handles this client's messages /// @@ -32,11 +41,6 @@ namespace PepperDash.Essentials.WebSocketServer /// public string RoomKey { get; set; } - /// - /// The unique identifier for this client instance - /// - private string _clientId; - /// /// The timestamp when this client connection was established /// @@ -60,15 +64,22 @@ namespace PepperDash.Essentials.WebSocketServer } } + /// + /// Triggered when this client closes it's connection + /// + public event EventHandler ConnectionClosed; + /// /// Initializes a new instance of the UiClient class with the specified key /// /// The unique key to identify this client /// The client ID used by the client for this connection - public UiClient(string key, string id) + /// + public UiClient(string key, string id, string token) { Key = key; Id = id; + Token = token; } /// @@ -76,34 +87,11 @@ namespace PepperDash.Essentials.WebSocketServer { base.OnOpen(); + _connectionTime = DateTime.Now; + Log.Output = (data, message) => Utilities.ConvertWebsocketLog(data, message); Log.Level = LogLevel.Trace; - try - { - this.LogDebug("Current session count on open {count}", Sessions.Count); - this.LogDebug("Current WebsocketServiceCount on open: {count}", Controller.DirectServer.WebsocketServiceCount); - } - catch (Exception ex) - { - this.LogError("Error getting service count: {message}", ex.Message); - this.LogDebug(ex, "Stack Trace: "); - } - - // var url = Context.WebSocket.Url; - // this.LogInformation("New WebSocket Connection from: {url}", url); - - // var match = Regex.Match(url.AbsoluteUri, "(?:ws|wss):\\/\\/.*(?:\\/mc\\/api\\/ui\\/join\\/)(.*)"); - - // if (!match.Success) - // { - // _connectionTime = DateTime.Now; - // return; - // } - - // var clientId = match.Groups[1].Value; - // _clientId = clientId; - if (Controller == null) { Debug.LogMessage(LogEventLevel.Verbose, "WebSocket UiClient Controller is null"); @@ -141,7 +129,7 @@ namespace PepperDash.Essentials.WebSocketServer /// Event arguments private void Bridge_UserCodeChanged(object sender, EventArgs e) { - SendUserCodeToClient((MobileControlEssentialsRoomBridge)sender, _clientId); + SendUserCodeToClient((MobileControlEssentialsRoomBridge)sender, Id); } /// @@ -184,17 +172,6 @@ namespace PepperDash.Essentials.WebSocketServer { base.OnClose(e); - try - { - this.LogDebug("Current session count on close {count}", Sessions.Count); - this.LogDebug("Current WebsocketServiceCount on close: {count}", Controller.DirectServer.WebsocketServiceCount); - } - catch (Exception ex) - { - this.LogError("Error getting service count: {message}", ex.Message); - this.LogDebug(ex, "Stack Trace: "); - } - this.LogInformation("WebSocket UiClient Closing: {code} reason: {reason}", e.Code, e.Reason); foreach (var messenger in Controller.Messengers)