Merge pull request #1327 from PepperDash/cs-lan-mc-panel

fix: add config property for devices on CS LAN
This commit is contained in:
Neil Dorin
2025-09-05 16:20:42 -06:00
committed by GitHub
4 changed files with 120 additions and 32 deletions

View File

@@ -1,6 +1,6 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<Version>2.12.1-local</Version> <Version>2.15.1-local</Version>
<InformationalVersion>$(Version)</InformationalVersion> <InformationalVersion>$(Version)</InformationalVersion>
<Authors>PepperDash Technology</Authors> <Authors>PepperDash Technology</Authors>
<Company>PepperDash Technology</Company> <Company>PepperDash Technology</Company>

View File

@@ -1,6 +1,7 @@
using Crestron.SimplSharpPro.DM.Streaming;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Crestron.SimplSharpPro.DM.Streaming;
using PepperDash.Core;
namespace PepperDash.Essentials.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 <see /// subscribers when the port information is updated. Implementations of this interface should ensure that the <see
/// cref="PortInformationChanged"/> event is raised whenever the <see cref="NetworkPorts"/> collection /// cref="PortInformationChanged"/> event is raised whenever the <see cref="NetworkPorts"/> collection
/// changes.</remarks> /// changes.</remarks>
public interface INvxNetworkPortInformation public interface INvxNetworkPortInformation : IKeyed
{ {
/// <summary> /// <summary>
/// Occurs when the port information changes. /// Occurs when the port information changes.

View File

@@ -1,6 +1,6 @@
using Newtonsoft.Json; using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters; using Newtonsoft.Json.Converters;
using System.Collections.Generic;
namespace PepperDash.Essentials namespace PepperDash.Essentials
{ {
@@ -9,25 +9,34 @@ namespace PepperDash.Essentials
/// </summary> /// </summary>
public class MobileControlConfig public class MobileControlConfig
{ {
/// <summary>
/// Gets or sets the ServerUrl
/// </summary>
[JsonProperty("serverUrl")] [JsonProperty("serverUrl")]
public string ServerUrl { get; set; } public string ServerUrl { get; set; }
/// <summary>
/// Gets or sets the ClientAppUrl
/// </summary>
[JsonProperty("clientAppUrl")] [JsonProperty("clientAppUrl")]
public string ClientAppUrl { get; set; } public string ClientAppUrl { get; set; }
/// <summary>
/// Gets or sets the DirectServer
/// </summary>
[JsonProperty("directServer")] [JsonProperty("directServer")]
public MobileControlDirectServerPropertiesConfig DirectServer { get; set; } public MobileControlDirectServerPropertiesConfig DirectServer { get; set; }
[JsonProperty("applicationConfig")]
/// <summary> /// <summary>
/// Gets or sets the ApplicationConfig /// Gets or sets the ApplicationConfig
/// </summary> /// </summary>
[JsonProperty("applicationConfig")]
public MobileControlApplicationConfig ApplicationConfig { get; set; } = null; public MobileControlApplicationConfig ApplicationConfig { get; set; } = null;
[JsonProperty("enableApiServer")]
/// <summary> /// <summary>
/// Gets or sets the EnableApiServer /// Gets or sets the EnableApiServer
/// </summary> /// </summary>
[JsonProperty("enableApiServer")]
public bool EnableApiServer { get; set; } = true; public bool EnableApiServer { get; set; } = true;
} }
@@ -36,27 +45,42 @@ namespace PepperDash.Essentials
/// </summary> /// </summary>
public class MobileControlDirectServerPropertiesConfig public class MobileControlDirectServerPropertiesConfig
{ {
[JsonProperty("enableDirectServer")]
/// <summary> /// <summary>
/// Gets or sets the EnableDirectServer /// Gets or sets the EnableDirectServer
/// </summary> /// </summary>
[JsonProperty("enableDirectServer")]
public bool EnableDirectServer { get; set; } public bool EnableDirectServer { get; set; }
[JsonProperty("port")]
/// <summary> /// <summary>
/// Gets or sets the Port /// Gets or sets the Port
/// </summary> /// </summary>
[JsonProperty("port")]
public int Port { get; set; } public int Port { get; set; }
[JsonProperty("logging")]
/// <summary> /// <summary>
/// Gets or sets the Logging /// Gets or sets the Logging
/// </summary> /// </summary>
[JsonProperty("logging")]
public MobileControlLoggingConfig Logging { get; set; } public MobileControlLoggingConfig Logging { get; set; }
/// <summary>
/// Gets or sets the AutomaticallyForwardPortToCSLAN
/// </summary>
[JsonProperty("automaticallyForwardPortToCSLAN")] [JsonProperty("automaticallyForwardPortToCSLAN")]
public bool? AutomaticallyForwardPortToCSLAN { get; set; } public bool? AutomaticallyForwardPortToCSLAN { get; set; }
/// <summary>
/// Gets or sets the CSLanUiDeviceKeys
/// </summary>
/// <remarks>
/// 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
/// </remarks>
[JsonProperty("csLanUiDeviceKeys")]
public List<string> CSLanUiDeviceKeys { get; set; }
/// <summary>
/// Initializes a new instance of the MobileControlDirectServerPropertiesConfig class.
/// </summary>
public MobileControlDirectServerPropertiesConfig() public MobileControlDirectServerPropertiesConfig()
{ {
Logging = new MobileControlLoggingConfig(); Logging = new MobileControlLoggingConfig();
@@ -68,26 +92,26 @@ namespace PepperDash.Essentials
/// </summary> /// </summary>
public class MobileControlLoggingConfig public class MobileControlLoggingConfig
{ {
[JsonProperty("enableRemoteLogging")]
/// <summary> /// <summary>
/// Gets or sets the EnableRemoteLogging /// Gets or sets the EnableRemoteLogging
/// </summary> /// </summary>
[JsonProperty("enableRemoteLogging")]
public bool EnableRemoteLogging { get; set; } public bool EnableRemoteLogging { get; set; }
[JsonProperty("host")]
/// <summary> /// <summary>
/// Gets or sets the Host /// Gets or sets the Host
/// </summary> /// </summary>
[JsonProperty("host")]
public string Host { get; set; } public string Host { get; set; }
[JsonProperty("port")]
/// <summary> /// <summary>
/// Gets or sets the Port /// Gets or sets the Port
/// </summary> /// </summary>
[JsonProperty("port")]
public int Port { get; set; } public int Port { get; set; }
} }
/// <summary> /// <summary>
@@ -95,16 +119,16 @@ namespace PepperDash.Essentials
/// </summary> /// </summary>
public class MobileControlRoomBridgePropertiesConfig public class MobileControlRoomBridgePropertiesConfig
{ {
[JsonProperty("key")]
/// <summary> /// <summary>
/// Gets or sets the Key /// Gets or sets the Key
/// </summary> /// </summary>
[JsonProperty("key")]
public string Key { get; set; } public string Key { get; set; }
[JsonProperty("roomKey")]
/// <summary> /// <summary>
/// Gets or sets the RoomKey /// Gets or sets the RoomKey
/// </summary> /// </summary>
[JsonProperty("roomKey")]
public string RoomKey { get; set; } public string RoomKey { get; set; }
} }
@@ -113,53 +137,71 @@ namespace PepperDash.Essentials
/// </summary> /// </summary>
public class MobileControlSimplRoomBridgePropertiesConfig public class MobileControlSimplRoomBridgePropertiesConfig
{ {
[JsonProperty("eiscId")]
/// <summary> /// <summary>
/// Gets or sets the EiscId /// Gets or sets the EiscId
/// </summary> /// </summary>
[JsonProperty("eiscId")]
public string EiscId { get; set; } public string EiscId { get; set; }
} }
/// <summary>
/// Represents a MobileControlApplicationConfig
/// </summary>
public class MobileControlApplicationConfig public class MobileControlApplicationConfig
{ {
/// <summary>
/// Gets or sets the ApiPath
/// </summary>
[JsonProperty("apiPath")] [JsonProperty("apiPath")]
public string ApiPath { get; set; } public string ApiPath { get; set; }
[JsonProperty("gatewayAppPath")]
/// <summary> /// <summary>
/// Gets or sets the GatewayAppPath /// Gets or sets the GatewayAppPath
/// </summary> /// </summary>
[JsonProperty("gatewayAppPath")]
public string GatewayAppPath { get; set; } public string GatewayAppPath { get; set; }
/// <summary>
/// Gets or sets the EnableDev
/// </summary>
[JsonProperty("enableDev")] [JsonProperty("enableDev")]
public bool? EnableDev { get; set; } public bool? EnableDev { get; set; }
[JsonProperty("logoPath")]
/// <summary> /// <summary>
/// Gets or sets the LogoPath /// Gets or sets the LogoPath
/// </summary> /// </summary>
[JsonProperty("logoPath")]
public string LogoPath { get; set; } public string LogoPath { get; set; }
/// <summary>
/// Gets or sets the IconSet
/// </summary>
[JsonProperty("iconSet")] [JsonProperty("iconSet")]
[JsonConverter(typeof(StringEnumConverter))] [JsonConverter(typeof(StringEnumConverter))]
public MCIconSet? IconSet { get; set; } public MCIconSet? IconSet { get; set; }
/// <summary>
/// Gets or sets the LoginMode
/// </summary>
[JsonProperty("loginMode")] [JsonProperty("loginMode")]
public string LoginMode { get; set; } public string LoginMode { get; set; }
/// <summary>
/// Gets or sets the Modes
/// </summary>
[JsonProperty("modes")] [JsonProperty("modes")]
public Dictionary<string, McMode> Modes { get; set; } public Dictionary<string, McMode> Modes { get; set; }
[JsonProperty("enableRemoteLogging")]
/// <summary> /// <summary>
/// Gets or sets the Logging /// Gets or sets the Logging
/// </summary> /// </summary>
[JsonProperty("enableRemoteLogging")]
public bool Logging { get; set; } public bool Logging { get; set; }
[JsonProperty("partnerMetadata", NullValueHandling = NullValueHandling.Ignore)]
/// <summary> /// <summary>
/// Gets or sets the PartnerMetadata /// Gets or sets the PartnerMetadata
/// </summary> /// </summary>
[JsonProperty("partnerMetadata", NullValueHandling = NullValueHandling.Ignore)]
public List<MobileControlPartnerMetadata> PartnerMetadata { get; set; } public List<MobileControlPartnerMetadata> PartnerMetadata { get; set; }
} }
@@ -168,22 +210,22 @@ namespace PepperDash.Essentials
/// </summary> /// </summary>
public class MobileControlPartnerMetadata public class MobileControlPartnerMetadata
{ {
[JsonProperty("role")]
/// <summary> /// <summary>
/// Gets or sets the Role /// Gets or sets the Role
/// </summary> /// </summary>
[JsonProperty("role")]
public string Role { get; set; } public string Role { get; set; }
[JsonProperty("description")]
/// <summary> /// <summary>
/// Gets or sets the Description /// Gets or sets the Description
/// </summary> /// </summary>
[JsonProperty("description")]
public string Description { get; set; } public string Description { get; set; }
[JsonProperty("logoPath")]
/// <summary> /// <summary>
/// Gets or sets the LogoPath /// Gets or sets the LogoPath
/// </summary> /// </summary>
[JsonProperty("logoPath")]
public string LogoPath { get; set; } public string LogoPath { get; set; }
} }
@@ -192,21 +234,22 @@ namespace PepperDash.Essentials
/// </summary> /// </summary>
public class McMode public class McMode
{ {
[JsonProperty("listPageText")]
/// <summary> /// <summary>
/// Gets or sets the ListPageText /// Gets or sets the ListPageText
/// </summary> /// </summary>
[JsonProperty("listPageText")]
public string ListPageText { get; set; } public string ListPageText { get; set; }
[JsonProperty("loginHelpText")]
/// <summary> /// <summary>
/// Gets or sets the LoginHelpText /// Gets or sets the LoginHelpText
/// </summary> /// </summary>
[JsonProperty("loginHelpText")]
public string LoginHelpText { get; set; } public string LoginHelpText { get; set; }
[JsonProperty("passcodePageText")]
/// <summary> /// <summary>
/// Gets or sets the PasscodePageText /// Gets or sets the PasscodePageText
/// </summary> /// </summary>
[JsonProperty("passcodePageText")]
public string PasscodePageText { get; set; } public string PasscodePageText { get; set; }
} }
@@ -215,8 +258,19 @@ namespace PepperDash.Essentials
/// </summary> /// </summary>
public enum MCIconSet public enum MCIconSet
{ {
/// <summary>
/// Google icon set
/// </summary>
GOOGLE, GOOGLE,
/// <summary>
/// Habanero icon set
/// </summary>
HABANERO, HABANERO,
/// <summary>
/// Neo icon set
/// </summary>
NEO NEO
} }
} }

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
@@ -41,8 +42,14 @@ namespace PepperDash.Essentials.WebSocketServer
private HttpServer _server; private HttpServer _server;
/// <summary>
/// Gets the HttpServer instance
/// </summary>
public HttpServer Server => _server; public HttpServer Server => _server;
/// <summary>
/// Gets the collection of UI client contexts
/// </summary>
public Dictionary<string, UiClientContext> UiClients { get; private set; } public Dictionary<string, UiClientContext> UiClients { get; private set; }
private readonly MobileControlSystemController _parent; private readonly MobileControlSystemController _parent;
@@ -61,17 +68,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;
/// <summary> /// <summary>
/// The path for the WebSocket messaging /// The path for the WebSocket messaging
/// </summary> /// </summary>
private readonly string _wsPath = "/mc/api/ui/join/"; private readonly string _wsPath = "/mc/api/ui/join/";
/// <summary>
/// Gets the WebSocket path
/// </summary>
public string WsPath => _wsPath; public string WsPath => _wsPath;
/// <summary> /// <summary>
@@ -89,6 +99,9 @@ namespace PepperDash.Essentials.WebSocketServer
/// </summary> /// </summary>
public int Port { get; private set; } public int Port { get; private set; }
/// <summary>
/// Gets the user app URL prefix
/// </summary>
public string UserAppUrlPrefix public string UserAppUrlPrefix
{ {
get get
@@ -101,6 +114,9 @@ namespace PepperDash.Essentials.WebSocketServer
} }
} }
/// <summary>
/// Gets the count of connected UI clients
/// </summary>
public int ConnectedUiClientsCount public int ConnectedUiClientsCount
{ {
get get
@@ -119,6 +135,9 @@ namespace PepperDash.Essentials.WebSocketServer
} }
} }
/// <summary>
/// Initializes a new instance of the MobileControlWebsocketServer class.
/// </summary>
public MobileControlWebsocketServer(string key, int customPort, MobileControlSystemController parent) public MobileControlWebsocketServer(string key, int customPort, MobileControlSystemController parent)
: base(key) : base(key)
{ {
@@ -344,6 +363,11 @@ namespace PepperDash.Essentials.WebSocketServer
// }) ? csIpAddress.ToString() : processorIp; // }) ? 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}"; var appUrl = $"http://{ip}:{_parent.Config.DirectServer.Port}/mc/app?token={touchpanel.Key}";
this.LogVerbose("Sending URL {appUrl}", appUrl); this.LogVerbose("Sending URL {appUrl}", appUrl);
@@ -625,6 +649,9 @@ namespace PepperDash.Essentials.WebSocketServer
CrestronConsole.ConsoleCommandResponse($"Token: {token}"); CrestronConsole.ConsoleCommandResponse($"Token: {token}");
} }
/// <summary>
/// Validates the grant code against the room key
/// </summary>
public (string, string) ValidateGrantCode(string grantCode, string roomKey) public (string, string) ValidateGrantCode(string grantCode, string roomKey)
{ {
var bridge = _parent.GetRoomBridge(roomKey); var bridge = _parent.GetRoomBridge(roomKey);
@@ -638,6 +665,9 @@ namespace PepperDash.Essentials.WebSocketServer
return ValidateGrantCode(grantCode, bridge); return ValidateGrantCode(grantCode, bridge);
} }
/// <summary>
/// Validates the grant code against the room key
/// </summary>
public (string, string) ValidateGrantCode(string grantCode, MobileControlBridgeBase bridge) public (string, string) ValidateGrantCode(string grantCode, MobileControlBridgeBase bridge)
{ {
// TODO: Authenticate grant code passed in // TODO: Authenticate grant code passed in
@@ -659,6 +689,9 @@ namespace PepperDash.Essentials.WebSocketServer
} }
} }
/// <summary>
/// Generates a new client token for the specified bridge
/// </summary>
public (string, string) GenerateClientToken(MobileControlBridgeBase bridge, string touchPanelKey = "") public (string, string) GenerateClientToken(MobileControlBridgeBase bridge, string touchPanelKey = "")
{ {
var key = Guid.NewGuid().ToString(); var key = Guid.NewGuid().ToString();