From 9556edc064f730eb5735a9ee2e81e75e17bbdd7e Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 2 Sep 2025 12:54:51 -0500 Subject: [PATCH 1/3] fix: add config property for devices on CS LAN --- src/Directory.Build.props | 2 +- .../MobileControlConfig.cs | 106 +++++++++++++----- .../MobileControlWebsocketServer.cs | 40 ++++++- 3 files changed, 118 insertions(+), 30 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index b47efdc9..af743a53 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,6 +1,6 @@ - 2.12.1-local + 2.15.1-local $(Version) PepperDash Technology PepperDash Technology diff --git a/src/PepperDash.Essentials.MobileControl/MobileControlConfig.cs b/src/PepperDash.Essentials.MobileControl/MobileControlConfig.cs index 80d90d1e..6c130f6d 100644 --- a/src/PepperDash.Essentials.MobileControl/MobileControlConfig.cs +++ b/src/PepperDash.Essentials.MobileControl/MobileControlConfig.cs @@ -1,6 +1,6 @@ -using Newtonsoft.Json; +using System.Collections.Generic; +using Newtonsoft.Json; using Newtonsoft.Json.Converters; -using System.Collections.Generic; namespace PepperDash.Essentials { @@ -9,25 +9,34 @@ namespace PepperDash.Essentials /// public class MobileControlConfig { + /// + /// Gets or sets the ServerUrl + /// [JsonProperty("serverUrl")] public string ServerUrl { get; set; } + /// + /// Gets or sets the ClientAppUrl + /// [JsonProperty("clientAppUrl")] public string ClientAppUrl { get; set; } + /// + /// Gets or sets the DirectServer + /// [JsonProperty("directServer")] public MobileControlDirectServerPropertiesConfig DirectServer { get; set; } - [JsonProperty("applicationConfig")] /// /// Gets or sets the ApplicationConfig /// + [JsonProperty("applicationConfig")] public MobileControlApplicationConfig ApplicationConfig { get; set; } = null; - [JsonProperty("enableApiServer")] /// /// Gets or sets the EnableApiServer /// + [JsonProperty("enableApiServer")] public bool EnableApiServer { get; set; } = true; } @@ -36,27 +45,42 @@ namespace PepperDash.Essentials /// public class MobileControlDirectServerPropertiesConfig { - [JsonProperty("enableDirectServer")] /// /// Gets or sets the EnableDirectServer /// + [JsonProperty("enableDirectServer")] public bool EnableDirectServer { get; set; } - [JsonProperty("port")] /// /// Gets or sets the Port /// + [JsonProperty("port")] public int Port { get; set; } - [JsonProperty("logging")] /// /// Gets or sets the Logging /// + [JsonProperty("logging")] public MobileControlLoggingConfig Logging { get; set; } + /// + /// Gets or sets the AutomaticallyForwardPortToCSLAN + /// [JsonProperty("automaticallyForwardPortToCSLAN")] public bool? AutomaticallyForwardPortToCSLAN { get; set; } + /// + /// Gets or sets the CSLanUiDeviceKeys + /// + /// + /// A list of device keys for the CS LAN UI. These devices will get the CS LAN IP address instead of the LAN IP Address + /// + [JsonProperty("csLanUiDeviceKeys")] + public List CSLanUiDeviceKeys { get; set; } + + /// + /// Initializes a new instance of the MobileControlDirectServerPropertiesConfig class. + /// public MobileControlDirectServerPropertiesConfig() { Logging = new MobileControlLoggingConfig(); @@ -68,26 +92,26 @@ namespace PepperDash.Essentials /// public class MobileControlLoggingConfig { - [JsonProperty("enableRemoteLogging")] + /// /// Gets or sets the EnableRemoteLogging /// + [JsonProperty("enableRemoteLogging")] public bool EnableRemoteLogging { get; set; } - [JsonProperty("host")] + /// /// Gets or sets the Host /// + [JsonProperty("host")] public string Host { get; set; } - [JsonProperty("port")] + /// /// Gets or sets the Port /// + [JsonProperty("port")] public int Port { get; set; } - - - } /// @@ -95,16 +119,16 @@ namespace PepperDash.Essentials /// public class MobileControlRoomBridgePropertiesConfig { - [JsonProperty("key")] /// /// Gets or sets the Key /// + [JsonProperty("key")] public string Key { get; set; } - [JsonProperty("roomKey")] /// /// Gets or sets the RoomKey /// + [JsonProperty("roomKey")] public string RoomKey { get; set; } } @@ -113,53 +137,71 @@ namespace PepperDash.Essentials /// public class MobileControlSimplRoomBridgePropertiesConfig { - [JsonProperty("eiscId")] /// /// Gets or sets the EiscId /// + [JsonProperty("eiscId")] public string EiscId { get; set; } } + /// + /// Represents a MobileControlApplicationConfig + /// public class MobileControlApplicationConfig { + /// + /// Gets or sets the ApiPath + /// [JsonProperty("apiPath")] public string ApiPath { get; set; } - [JsonProperty("gatewayAppPath")] /// /// Gets or sets the GatewayAppPath /// + [JsonProperty("gatewayAppPath")] public string GatewayAppPath { get; set; } + /// + /// Gets or sets the EnableDev + /// [JsonProperty("enableDev")] public bool? EnableDev { get; set; } - [JsonProperty("logoPath")] /// /// Gets or sets the LogoPath /// + [JsonProperty("logoPath")] public string LogoPath { get; set; } + /// + /// Gets or sets the IconSet + /// [JsonProperty("iconSet")] [JsonConverter(typeof(StringEnumConverter))] public MCIconSet? IconSet { get; set; } + /// + /// Gets or sets the LoginMode + /// [JsonProperty("loginMode")] public string LoginMode { get; set; } + /// + /// Gets or sets the Modes + /// [JsonProperty("modes")] public Dictionary Modes { get; set; } - [JsonProperty("enableRemoteLogging")] /// /// Gets or sets the Logging /// + [JsonProperty("enableRemoteLogging")] public bool Logging { get; set; } - [JsonProperty("partnerMetadata", NullValueHandling = NullValueHandling.Ignore)] /// /// Gets or sets the PartnerMetadata /// + [JsonProperty("partnerMetadata", NullValueHandling = NullValueHandling.Ignore)] public List PartnerMetadata { get; set; } } @@ -168,22 +210,22 @@ namespace PepperDash.Essentials /// public class MobileControlPartnerMetadata { - [JsonProperty("role")] /// /// Gets or sets the Role /// + [JsonProperty("role")] public string Role { get; set; } - [JsonProperty("description")] /// /// Gets or sets the Description /// + [JsonProperty("description")] public string Description { get; set; } - [JsonProperty("logoPath")] /// /// Gets or sets the LogoPath /// + [JsonProperty("logoPath")] public string LogoPath { get; set; } } @@ -192,21 +234,22 @@ namespace PepperDash.Essentials /// public class McMode { - [JsonProperty("listPageText")] /// /// Gets or sets the ListPageText /// + [JsonProperty("listPageText")] public string ListPageText { get; set; } - [JsonProperty("loginHelpText")] + /// /// Gets or sets the LoginHelpText /// + [JsonProperty("loginHelpText")] public string LoginHelpText { get; set; } - [JsonProperty("passcodePageText")] /// /// Gets or sets the PasscodePageText /// + [JsonProperty("passcodePageText")] public string PasscodePageText { get; set; } } @@ -215,8 +258,19 @@ namespace PepperDash.Essentials /// public enum MCIconSet { + /// + /// Google icon set + /// GOOGLE, + + /// + /// Habanero icon set + /// HABANERO, + + /// + /// Neo icon set + /// NEO } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.MobileControl/WebSocketServer/MobileControlWebsocketServer.cs b/src/PepperDash.Essentials.MobileControl/WebSocketServer/MobileControlWebsocketServer.cs index 8fcfd11f..384509ca 100644 --- a/src/PepperDash.Essentials.MobileControl/WebSocketServer/MobileControlWebsocketServer.cs +++ b/src/PepperDash.Essentials.MobileControl/WebSocketServer/MobileControlWebsocketServer.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.IO; using System.Linq; using System.Net.Http; using System.Text; using Crestron.SimplSharp; using Crestron.SimplSharp.WebScripting; +using Microsoft.SqlServer.Server; using Newtonsoft.Json; using PepperDash.Core; using PepperDash.Core.Logging; @@ -41,8 +43,14 @@ namespace PepperDash.Essentials.WebSocketServer private HttpServer _server; + /// + /// Gets the HttpServer instance + /// public HttpServer Server => _server; + /// + /// Gets the collection of UI client contexts + /// public Dictionary UiClients { get; private set; } private readonly MobileControlSystemController _parent; @@ -61,17 +69,20 @@ namespace PepperDash.Essentials.WebSocketServer } } - private string lanIpAddress => CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetLANAdapter)); + private string LanIpAddress => CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetLANAdapter)); - private System.Net.IPAddress csIpAddress; + private readonly System.Net.IPAddress csIpAddress; - private System.Net.IPAddress csSubnetMask; + private readonly System.Net.IPAddress csSubnetMask; /// /// The path for the WebSocket messaging /// private readonly string _wsPath = "/mc/api/ui/join/"; + /// + /// Gets the WebSocket path + /// public string WsPath => _wsPath; /// @@ -89,6 +100,9 @@ namespace PepperDash.Essentials.WebSocketServer /// public int Port { get; private set; } + /// + /// Gets the user app URL prefix + /// public string UserAppUrlPrefix { get @@ -101,6 +115,9 @@ namespace PepperDash.Essentials.WebSocketServer } } + /// + /// Gets the count of connected UI clients + /// public int ConnectedUiClientsCount { get @@ -119,6 +136,9 @@ namespace PepperDash.Essentials.WebSocketServer } } + /// + /// Initializes a new instance of the MobileControlWebsocketServer class. + /// public MobileControlWebsocketServer(string key, int customPort, MobileControlSystemController parent) : base(key) { @@ -344,6 +364,11 @@ namespace PepperDash.Essentials.WebSocketServer // }) ? csIpAddress.ToString() : processorIp; //} + if (_parent.Config.DirectServer.CSLanUiDeviceKeys != null && _parent.Config.DirectServer.CSLanUiDeviceKeys.Any(k => k.Equals(touchpanel.Touchpanel.Key, StringComparison.InvariantCultureIgnoreCase)) && csIpAddress != null) + { + ip = csIpAddress.ToString(); + } + var appUrl = $"http://{ip}:{_parent.Config.DirectServer.Port}/mc/app?token={touchpanel.Key}"; this.LogVerbose("Sending URL {appUrl}", appUrl); @@ -625,6 +650,9 @@ namespace PepperDash.Essentials.WebSocketServer CrestronConsole.ConsoleCommandResponse($"Token: {token}"); } + /// + /// Validates the grant code against the room key + /// public (string, string) ValidateGrantCode(string grantCode, string roomKey) { var bridge = _parent.GetRoomBridge(roomKey); @@ -638,6 +666,9 @@ namespace PepperDash.Essentials.WebSocketServer return ValidateGrantCode(grantCode, bridge); } + /// + /// Validates the grant code against the room key + /// public (string, string) ValidateGrantCode(string grantCode, MobileControlBridgeBase bridge) { // TODO: Authenticate grant code passed in @@ -659,6 +690,9 @@ namespace PepperDash.Essentials.WebSocketServer } } + /// + /// Generates a new client token for the specified bridge + /// public (string, string) GenerateClientToken(MobileControlBridgeBase bridge, string touchPanelKey = "") { var key = Guid.NewGuid().ToString(); From 2424838b7fa10328953b37e98ea111ff173c9052 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 2 Sep 2025 12:56:14 -0500 Subject: [PATCH 2/3] chore: remove unused using Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../WebSocketServer/MobileControlWebsocketServer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/PepperDash.Essentials.MobileControl/WebSocketServer/MobileControlWebsocketServer.cs b/src/PepperDash.Essentials.MobileControl/WebSocketServer/MobileControlWebsocketServer.cs index 384509ca..ba241a04 100644 --- a/src/PepperDash.Essentials.MobileControl/WebSocketServer/MobileControlWebsocketServer.cs +++ b/src/PepperDash.Essentials.MobileControl/WebSocketServer/MobileControlWebsocketServer.cs @@ -7,7 +7,6 @@ using System.Net.Http; using System.Text; using Crestron.SimplSharp; using Crestron.SimplSharp.WebScripting; -using Microsoft.SqlServer.Server; using Newtonsoft.Json; using PepperDash.Core; using PepperDash.Core.Logging; From d2b7400039dc33ade1f5ebad4b0ab4bcd5a13a8f Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Fri, 5 Sep 2025 15:55:20 -0500 Subject: [PATCH 3/3] fix: INvxNetworkPortInformation inherits from IKeyed --- .../DeviceTypeInterfaces/INvxNetworkPortInformation.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/INvxNetworkPortInformation.cs b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/INvxNetworkPortInformation.cs index c1592c94..842c1aac 100644 --- a/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/INvxNetworkPortInformation.cs +++ b/src/PepperDash.Essentials.Core/DeviceTypeInterfaces/INvxNetworkPortInformation.cs @@ -1,6 +1,7 @@ -using Crestron.SimplSharpPro.DM.Streaming; using System; using System.Collections.Generic; +using Crestron.SimplSharpPro.DM.Streaming; +using PepperDash.Core; namespace PepperDash.Essentials.Core { @@ -11,7 +12,7 @@ namespace PepperDash.Essentials.Core /// subscribers when the port information is updated. Implementations of this interface should ensure that the event is raised whenever the collection /// changes. - public interface INvxNetworkPortInformation + public interface INvxNetworkPortInformation : IKeyed { /// /// Occurs when the port information changes.