mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-01-22 08:55:21 +00:00
Compare commits
46 Commits
v2.12.3-be
...
v2.15.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0f708294c | ||
|
|
a00d186c62 | ||
|
|
51da668dfd | ||
|
|
d2b7400039 | ||
|
|
2424838b7f | ||
|
|
9556edc064 | ||
|
|
f9088691fd | ||
|
|
e40b6a8b4c | ||
|
|
c3b39a87da | ||
|
|
06dc0e947e | ||
|
|
147997f460 | ||
|
|
49abec5eea | ||
|
|
6830efe42a | ||
|
|
d013068a0c | ||
|
|
52916d29f4 | ||
|
|
19e8489166 | ||
|
|
fe33443b25 | ||
|
|
8cf195b262 | ||
|
|
40406b797d | ||
|
|
65bc408ebf | ||
|
|
9d49fb8357 | ||
|
|
fb7797dac7 | ||
|
|
574f5f6dc9 | ||
|
|
e49c69a12f | ||
|
|
7889cba196 | ||
|
|
033aa1f3dd | ||
|
|
9b6c2d80ea | ||
|
|
a0fc731701 | ||
|
|
f2d0dca7b8 | ||
|
|
ab4e85d081 | ||
|
|
47017da527 | ||
|
|
4f0d464ba4 | ||
|
|
0107422507 | ||
|
|
1a366790e7 | ||
|
|
97448f4f0f | ||
|
|
cf3ece4237 | ||
|
|
808e8042a7 | ||
|
|
0bc4388bfd | ||
|
|
dbc132c0da | ||
|
|
5bb0ab2626 | ||
|
|
27bf36c58c | ||
|
|
ce886aea63 | ||
|
|
ef920bf54c | ||
|
|
a031424752 | ||
|
|
fd1ba345aa | ||
|
|
e03874a7a9 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -395,3 +395,4 @@ essentials-framework/Essentials Interfaces/PepperDash_Essentials_Interfaces/Pepp
|
||||
_site/
|
||||
api/
|
||||
*.DS_Store
|
||||
/._PepperDash.Essentials.4Series.sln
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<Version>2.4.0-local</Version>
|
||||
<Version>2.15.1-local</Version>
|
||||
<InformationalVersion>$(Version)</InformationalVersion>
|
||||
<Authors>PepperDash Technology</Authors>
|
||||
<Company>PepperDash Technology</Company>
|
||||
|
||||
@@ -74,6 +74,10 @@ namespace PepperDash.Core
|
||||
/// <summary>
|
||||
/// Secure TCP/IP
|
||||
/// </summary>
|
||||
SecureTcpIp
|
||||
SecureTcpIp,
|
||||
/// <summary>
|
||||
/// Used when comms needs to be handled in SIMPL and bridged opposite the normal direction
|
||||
/// </summary>
|
||||
ComBridge
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using Crestron.SimplSharp;
|
||||
@@ -19,7 +20,6 @@ using Serilog.Templates;
|
||||
namespace PepperDash.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains debug commands for use in various situations
|
||||
/// </summary>
|
||||
public static class Debug
|
||||
{
|
||||
@@ -272,6 +272,9 @@ namespace PepperDash.Core
|
||||
if (result != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
|
||||
{
|
||||
CrestronConsole.Print($"Unable to retrieve stored log level for {levelStoreKey}.\r\nError: {result}.\r\nSetting level to {LogEventLevel.Information}\r\n");
|
||||
|
||||
CrestronDataStoreStatic.SetLocalIntValue(levelStoreKey, (int)LogEventLevel.Information);
|
||||
|
||||
return LogEventLevel.Information;
|
||||
}
|
||||
|
||||
@@ -346,13 +349,13 @@ namespace PepperDash.Core
|
||||
if (levelString.Trim() == "?")
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse(
|
||||
$@"Used to set the minimum level of debug messages to be printed to the console:
|
||||
{_logLevels[0]} = 0
|
||||
{_logLevels[1]} = 1
|
||||
{_logLevels[2]} = 2
|
||||
{_logLevels[3]} = 3
|
||||
{_logLevels[4]} = 4
|
||||
{_logLevels[5]} = 5");
|
||||
"Used to set the minimum level of debug messages to be printed to the console:\r\n" +
|
||||
$"{_logLevels[0]} = 0\r\n" +
|
||||
$"{_logLevels[1]} = 1\r\n" +
|
||||
$"{_logLevels[2]} = 2\r\n" +
|
||||
$"{_logLevels[3]} = 3\r\n" +
|
||||
$"{_logLevels[4]} = 4\r\n" +
|
||||
$"{_logLevels[5]} = 5");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -373,7 +376,7 @@ namespace PepperDash.Core
|
||||
return;
|
||||
}
|
||||
|
||||
if (Enum.TryParse<LogEventLevel>(levelString, out var levelEnum))
|
||||
if (Enum.TryParse<LogEventLevel>(levelString, true, out var levelEnum))
|
||||
{
|
||||
SetDebugLevel(levelEnum);
|
||||
return;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Serilog.Events;
|
||||
using System;
|
||||
using System;
|
||||
using Serilog.Events;
|
||||
using Log = PepperDash.Core.Debug;
|
||||
|
||||
namespace PepperDash.Core.Logging
|
||||
@@ -11,7 +11,7 @@ namespace PepperDash.Core.Logging
|
||||
/// </summary>
|
||||
public static void LogException(this IKeyed device, Exception ex, string message, params object[] args)
|
||||
{
|
||||
Log.LogMessage(ex, message, device, args);
|
||||
Log.LogMessage(ex, message, device: device, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -19,7 +19,7 @@ namespace PepperDash.Core.Logging
|
||||
/// </summary>
|
||||
public static void LogVerbose(this IKeyed device, Exception ex, string message, params object[] args)
|
||||
{
|
||||
Log.LogMessage(LogEventLevel.Verbose, ex, message, device, args);
|
||||
Log.LogVerbose(ex, device, message, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -27,7 +27,7 @@ namespace PepperDash.Core.Logging
|
||||
/// </summary>
|
||||
public static void LogVerbose(this IKeyed device, string message, params object[] args)
|
||||
{
|
||||
Log.LogMessage(LogEventLevel.Verbose, device, message, args);
|
||||
Log.LogVerbose(device, message, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -35,7 +35,7 @@ namespace PepperDash.Core.Logging
|
||||
/// </summary>
|
||||
public static void LogDebug(this IKeyed device, Exception ex, string message, params object[] args)
|
||||
{
|
||||
Log.LogMessage(LogEventLevel.Debug, ex, message, device, args);
|
||||
Log.LogDebug(ex, device, message, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -43,7 +43,7 @@ namespace PepperDash.Core.Logging
|
||||
/// </summary>
|
||||
public static void LogDebug(this IKeyed device, string message, params object[] args)
|
||||
{
|
||||
Log.LogMessage(LogEventLevel.Debug, device, message, args);
|
||||
Log.LogDebug(device, message, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -51,7 +51,7 @@ namespace PepperDash.Core.Logging
|
||||
/// </summary>
|
||||
public static void LogInformation(this IKeyed device, Exception ex, string message, params object[] args)
|
||||
{
|
||||
Log.LogMessage(LogEventLevel.Information, ex, message, device, args);
|
||||
Log.LogInformation(ex, device, message, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -59,7 +59,7 @@ namespace PepperDash.Core.Logging
|
||||
/// </summary>
|
||||
public static void LogInformation(this IKeyed device, string message, params object[] args)
|
||||
{
|
||||
Log.LogMessage(LogEventLevel.Information, device, message, args);
|
||||
Log.LogInformation(device, message, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -67,7 +67,7 @@ namespace PepperDash.Core.Logging
|
||||
/// </summary>
|
||||
public static void LogWarning(this IKeyed device, Exception ex, string message, params object[] args)
|
||||
{
|
||||
Log.LogMessage(LogEventLevel.Warning, ex, message, device, args);
|
||||
Log.LogWarning(ex, device, message, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -75,7 +75,7 @@ namespace PepperDash.Core.Logging
|
||||
/// </summary>
|
||||
public static void LogWarning(this IKeyed device, string message, params object[] args)
|
||||
{
|
||||
Log.LogMessage(LogEventLevel.Warning, device, message, args);
|
||||
Log.LogWarning(device, message, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -83,7 +83,7 @@ namespace PepperDash.Core.Logging
|
||||
/// </summary>
|
||||
public static void LogError(this IKeyed device, Exception ex, string message, params object[] args)
|
||||
{
|
||||
Log.LogMessage(LogEventLevel.Error, ex, message, device, args);
|
||||
Log.LogError(ex, device, message, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -91,7 +91,7 @@ namespace PepperDash.Core.Logging
|
||||
/// </summary>
|
||||
public static void LogError(this IKeyed device, string message, params object[] args)
|
||||
{
|
||||
Log.LogMessage(LogEventLevel.Error, device, message, args);
|
||||
Log.LogError(device, message, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -99,7 +99,7 @@ namespace PepperDash.Core.Logging
|
||||
/// </summary>
|
||||
public static void LogFatal(this IKeyed device, Exception ex, string message, params object[] args)
|
||||
{
|
||||
Log.LogMessage(LogEventLevel.Fatal, ex, message, device, args);
|
||||
Log.LogFatal(ex, device, message, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -107,7 +107,7 @@ namespace PepperDash.Core.Logging
|
||||
/// </summary>
|
||||
public static void LogFatal(this IKeyed device, string message, params object[] args)
|
||||
{
|
||||
Log.LogMessage(LogEventLevel.Fatal, device, message, args);
|
||||
Log.LogFatal(device, message, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,13 @@ namespace PepperDash.Essentials.Core.Bridges
|
||||
/// </summary>
|
||||
public interface IBridgeAdvanced
|
||||
{
|
||||
/// <summary>
|
||||
/// Links the bridge to the API using the provided trilist, join start, join map key, and bridge.
|
||||
/// </summary>
|
||||
/// <param name="trilist">The trilist to link to.</param>
|
||||
/// <param name="joinStart">The starting join number.</param>
|
||||
/// <param name="joinMapKey">The key for the join map.</param>
|
||||
/// <param name="bridge">The EISC API bridge.</param>
|
||||
void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge);
|
||||
}
|
||||
}
|
||||
138
src/PepperDash.Essentials.Core/Comm and IR/CommBridge.cs
Normal file
138
src/PepperDash.Essentials.Core/Comm and IR/CommBridge.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Crestron.SimplSharp.CrestronSockets;
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
using Newtonsoft.Json;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Core.Logging;
|
||||
using PepperDash.Essentials.Core.Bridges;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
using PepperDash.Essentials.Core.Devices;
|
||||
|
||||
|
||||
namespace PepperDash.Essentials.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements IBasicCommunication and sends all communication through an EISC
|
||||
/// </summary>
|
||||
[Description("Generic communication wrapper class for any IBasicCommunication type")]
|
||||
public class CommBridge : EssentialsBridgeableDevice, IBasicCommunication
|
||||
{
|
||||
private EiscApiAdvanced eisc;
|
||||
|
||||
private IBasicCommunicationJoinMap joinMap;
|
||||
|
||||
/// <summary>
|
||||
/// Event triggered when text is received through the communication bridge.
|
||||
/// </summary>
|
||||
public event EventHandler<GenericCommMethodReceiveTextArgs> TextReceived;
|
||||
|
||||
/// <summary>
|
||||
/// Event triggered when bytes are received through the communication bridge.
|
||||
/// </summary>
|
||||
public event EventHandler<GenericCommMethodReceiveBytesArgs> BytesReceived;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the communication bridge is currently connected.
|
||||
/// </summary>
|
||||
public bool IsConnected { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CommBridge"/> class.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for the communication bridge.</param>
|
||||
/// <param name="name">The display name for the communication bridge.</param>
|
||||
public CommBridge(string key, string name)
|
||||
: base(key, name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a byte array through the communication bridge.
|
||||
/// </summary>
|
||||
/// <param name="bytes">The byte array to send.</param>
|
||||
public void SendBytes(byte[] bytes)
|
||||
{
|
||||
if (eisc == null)
|
||||
{
|
||||
this.LogWarning("EISC is null, cannot send bytes.");
|
||||
return;
|
||||
}
|
||||
eisc.Eisc.SetString(joinMap.SendText.JoinNumber, Encoding.ASCII.GetString(bytes, 0, bytes.Length));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a text string through the communication bridge.
|
||||
/// </summary>
|
||||
/// <param name="text">The text string to send.</param>
|
||||
public void SendText(string text)
|
||||
{
|
||||
if (eisc == null)
|
||||
{
|
||||
this.LogWarning("EISC is null, cannot send text.");
|
||||
return;
|
||||
}
|
||||
eisc.Eisc.SetString(joinMap.SendText.JoinNumber, text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initiates a connection through the communication bridge.
|
||||
/// </summary>
|
||||
public void Connect()
|
||||
{
|
||||
if (eisc == null)
|
||||
{
|
||||
this.LogWarning("EISC is null, cannot connect.");
|
||||
return;
|
||||
}
|
||||
eisc.Eisc.SetBool(joinMap.Connect.JoinNumber, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Terminates the connection through the communication bridge.
|
||||
/// </summary>
|
||||
public void Disconnect()
|
||||
{
|
||||
if (eisc == null)
|
||||
{
|
||||
this.LogWarning("EISC is null, cannot disconnect.");
|
||||
return;
|
||||
}
|
||||
eisc.Eisc.SetBool(joinMap.Connect.JoinNumber, false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
|
||||
{
|
||||
joinMap = new IBasicCommunicationJoinMap(joinStart);
|
||||
|
||||
var joinMapSerialized = JoinMapHelper.GetSerializedJoinMapForDevice(joinMapKey);
|
||||
|
||||
if (!string.IsNullOrEmpty(joinMapSerialized))
|
||||
joinMap = JsonConvert.DeserializeObject<IBasicCommunicationJoinMap>(joinMapSerialized);
|
||||
|
||||
if (bridge != null)
|
||||
{
|
||||
bridge.AddJoinMap(Key, joinMap);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.LogWarning("Please update config to use 'eiscapiadvanced' to get all join map features for this device.");
|
||||
}
|
||||
|
||||
this.LogDebug("Linking to Trilist '{0}'", trilist.ID.ToString("X"));
|
||||
|
||||
eisc = bridge;
|
||||
|
||||
trilist.SetBoolSigAction(joinMap.Connected.JoinNumber, (b) => IsConnected = b);
|
||||
|
||||
trilist.SetStringSigAction(joinMap.TextReceived.JoinNumber, (s) =>
|
||||
{
|
||||
TextReceived?.Invoke(this, new GenericCommMethodReceiveTextArgs(s));
|
||||
BytesReceived?.Invoke(this, new GenericCommMethodReceiveBytesArgs(Encoding.ASCII.GetBytes(s)));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
|
||||
|
||||
using System;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.DM;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core.Config;
|
||||
using Serilog.Events;
|
||||
@@ -38,9 +36,9 @@ namespace PepperDash.Essentials.Core
|
||||
/// Returns a comm method of either com port, TCP, SSH, and puts this into the DeviceManager
|
||||
/// </summary>
|
||||
/// <param name="deviceConfig">The Device config object</param>
|
||||
/// <summary>
|
||||
/// CreateCommForDevice method
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// CreateCommForDevice method
|
||||
/// </summary>
|
||||
public static IBasicCommunication CreateCommForDevice(DeviceConfig deviceConfig)
|
||||
{
|
||||
EssentialsControlPropertiesConfig controlConfig = GetControlPropertiesConfig(deviceConfig);
|
||||
@@ -56,35 +54,38 @@ namespace PepperDash.Essentials.Core
|
||||
case eControlMethod.Com:
|
||||
comm = new ComPortController(deviceConfig.Key + "-com", GetComPort, controlConfig.ComParams.Value, controlConfig);
|
||||
break;
|
||||
case eControlMethod.Cec:
|
||||
comm = new CecPortController(deviceConfig.Key + "-cec", GetCecPort, controlConfig);
|
||||
break;
|
||||
case eControlMethod.ComBridge:
|
||||
comm = new CommBridge(deviceConfig.Key + "-simpl", deviceConfig.Name + " Simpl");
|
||||
break;
|
||||
case eControlMethod.Cec:
|
||||
comm = new CecPortController(deviceConfig.Key + "-cec", GetCecPort, controlConfig);
|
||||
break;
|
||||
case eControlMethod.IR:
|
||||
break;
|
||||
case eControlMethod.Ssh:
|
||||
{
|
||||
var ssh = new GenericSshClient(deviceConfig.Key + "-ssh", c.Address, c.Port, c.Username, c.Password);
|
||||
ssh.AutoReconnect = c.AutoReconnect;
|
||||
if(ssh.AutoReconnect)
|
||||
ssh.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs;
|
||||
comm = ssh;
|
||||
break;
|
||||
}
|
||||
case eControlMethod.Tcpip:
|
||||
{
|
||||
var tcp = new GenericTcpIpClient(deviceConfig.Key + "-tcp", c.Address, c.Port, c.BufferSize);
|
||||
tcp.AutoReconnect = c.AutoReconnect;
|
||||
if (tcp.AutoReconnect)
|
||||
tcp.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs;
|
||||
comm = tcp;
|
||||
break;
|
||||
}
|
||||
case eControlMethod.Udp:
|
||||
{
|
||||
var udp = new GenericUdpServer(deviceConfig.Key + "-udp", c.Address, c.Port, c.BufferSize);
|
||||
comm = udp;
|
||||
break;
|
||||
}
|
||||
case eControlMethod.Ssh:
|
||||
{
|
||||
var ssh = new GenericSshClient(deviceConfig.Key + "-ssh", c.Address, c.Port, c.Username, c.Password);
|
||||
ssh.AutoReconnect = c.AutoReconnect;
|
||||
if (ssh.AutoReconnect)
|
||||
ssh.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs;
|
||||
comm = ssh;
|
||||
break;
|
||||
}
|
||||
case eControlMethod.Tcpip:
|
||||
{
|
||||
var tcp = new GenericTcpIpClient(deviceConfig.Key + "-tcp", c.Address, c.Port, c.BufferSize);
|
||||
tcp.AutoReconnect = c.AutoReconnect;
|
||||
if (tcp.AutoReconnect)
|
||||
tcp.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs;
|
||||
comm = tcp;
|
||||
break;
|
||||
}
|
||||
case eControlMethod.Udp:
|
||||
{
|
||||
var udp = new GenericUdpServer(deviceConfig.Key + "-udp", c.Address, c.Port, c.BufferSize);
|
||||
comm = udp;
|
||||
break;
|
||||
}
|
||||
case eControlMethod.Telnet:
|
||||
break;
|
||||
case eControlMethod.SecureTcpIp:
|
||||
@@ -98,7 +99,7 @@ namespace PepperDash.Essentials.Core
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -107,15 +108,14 @@ namespace PepperDash.Essentials.Core
|
||||
}
|
||||
|
||||
// put it in the device manager if it's the right flavor
|
||||
var comDev = comm as Device;
|
||||
if (comDev != null)
|
||||
if (comm is Device comDev)
|
||||
DeviceManager.AddDevice(comDev);
|
||||
return comm;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GetComPort method
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// GetComPort method
|
||||
/// </summary>
|
||||
public static ComPort GetComPort(EssentialsControlPropertiesConfig config)
|
||||
{
|
||||
var comPar = config.ComParams;
|
||||
@@ -126,74 +126,74 @@ namespace PepperDash.Essentials.Core
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an ICec port from a RoutingInput or RoutingOutput on a device
|
||||
/// </summary>
|
||||
/// <param name="config"></param>
|
||||
/// <returns></returns>
|
||||
/// <summary>
|
||||
/// GetCecPort method
|
||||
/// </summary>
|
||||
public static ICec GetCecPort(ControlPropertiesConfig config)
|
||||
{
|
||||
try
|
||||
{
|
||||
var dev = DeviceManager.GetDeviceForKey(config.ControlPortDevKey);
|
||||
/// <summary>
|
||||
/// Gets an ICec port from a RoutingInput or RoutingOutput on a device
|
||||
/// </summary>
|
||||
/// <param name="config"></param>
|
||||
/// <returns></returns>
|
||||
/// <summary>
|
||||
/// GetCecPort method
|
||||
/// </summary>
|
||||
public static ICec GetCecPort(ControlPropertiesConfig config)
|
||||
{
|
||||
try
|
||||
{
|
||||
var dev = DeviceManager.GetDeviceForKey(config.ControlPortDevKey);
|
||||
|
||||
Debug.LogMessage(LogEventLevel.Information, "GetCecPort: device '{0}' {1}", config.ControlPortDevKey, dev == null
|
||||
? "is not valid, failed to get cec port"
|
||||
: "found in device manager, attempting to get cec port");
|
||||
Debug.LogMessage(LogEventLevel.Information, "GetCecPort: device '{0}' {1}", config.ControlPortDevKey, dev == null
|
||||
? "is not valid, failed to get cec port"
|
||||
: "found in device manager, attempting to get cec port");
|
||||
|
||||
if (dev == null)
|
||||
return null;
|
||||
if (dev == null)
|
||||
return null;
|
||||
|
||||
if (String.IsNullOrEmpty(config.ControlPortName))
|
||||
{
|
||||
Debug.LogMessage(LogEventLevel.Information, "GetCecPort: '{0}' - Configuration missing 'ControlPortName'", config.ControlPortDevKey);
|
||||
return null;
|
||||
}
|
||||
if (String.IsNullOrEmpty(config.ControlPortName))
|
||||
{
|
||||
Debug.LogMessage(LogEventLevel.Information, "GetCecPort: '{0}' - Configuration missing 'ControlPortName'", config.ControlPortDevKey);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
var inputsOutputs = dev as IRoutingInputsOutputs;
|
||||
if (inputsOutputs == null)
|
||||
{
|
||||
var inputsOutputs = dev as IRoutingInputsOutputs;
|
||||
if (inputsOutputs == null)
|
||||
{
|
||||
Debug.LogMessage(LogEventLevel.Information, "GetCecPort: Device '{0}' does not support IRoutingInputsOutputs, failed to get CEC port called '{1}'",
|
||||
config.ControlPortDevKey, config.ControlPortName);
|
||||
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
var inputPort = inputsOutputs.InputPorts[config.ControlPortName];
|
||||
if (inputPort != null && inputPort.Port is ICec)
|
||||
if (inputPort != null && inputPort.Port is ICec)
|
||||
return inputPort.Port as ICec;
|
||||
|
||||
|
||||
var outputPort = inputsOutputs.OutputPorts[config.ControlPortName];
|
||||
if (outputPort != null && outputPort.Port is ICec)
|
||||
return outputPort.Port as ICec;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogMessage(LogEventLevel.Debug, "GetCecPort Exception Message: {0}", ex.Message);
|
||||
Debug.LogMessage(LogEventLevel.Verbose, "GetCecPort Exception StackTrace: {0}", ex.StackTrace);
|
||||
if (ex.InnerException != null)
|
||||
Debug.LogMessage(LogEventLevel.Information, "GetCecPort Exception InnerException: {0}", ex.InnerException);
|
||||
}
|
||||
|
||||
var outputPort = inputsOutputs.OutputPorts[config.ControlPortName];
|
||||
if (outputPort != null && outputPort.Port is ICec)
|
||||
return outputPort.Port as ICec;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogMessage(LogEventLevel.Debug, "GetCecPort Exception Message: {0}", ex.Message);
|
||||
Debug.LogMessage(LogEventLevel.Verbose, "GetCecPort Exception StackTrace: {0}", ex.StackTrace);
|
||||
if (ex.InnerException != null)
|
||||
Debug.LogMessage(LogEventLevel.Information, "GetCecPort Exception InnerException: {0}", ex.InnerException);
|
||||
}
|
||||
|
||||
Debug.LogMessage(LogEventLevel.Information, "GetCecPort: Device '{0}' does not have a CEC port called '{1}'",
|
||||
config.ControlPortDevKey, config.ControlPortName);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper to grab the IComPorts device for this PortDeviceKey. Key "controlSystem" will
|
||||
/// return the ControlSystem object from the Global class.
|
||||
/// </summary>
|
||||
/// <returns>IComPorts device or null if the device is not found or does not implement IComPorts</returns>
|
||||
/// <summary>
|
||||
/// GetIComPortsDeviceFromManagedDevice method
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// GetIComPortsDeviceFromManagedDevice method
|
||||
/// </summary>
|
||||
public static IComPorts GetIComPortsDeviceFromManagedDevice(string ComPortDevKey)
|
||||
{
|
||||
if ((ComPortDevKey.Equals("controlSystem", System.StringComparison.OrdinalIgnoreCase)
|
||||
@@ -210,81 +210,81 @@ namespace PepperDash.Essentials.Core
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a EssentialsControlPropertiesConfig
|
||||
/// </summary>
|
||||
public class EssentialsControlPropertiesConfig :
|
||||
ControlPropertiesConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a EssentialsControlPropertiesConfig
|
||||
/// </summary>
|
||||
public class EssentialsControlPropertiesConfig :
|
||||
ControlPropertiesConfig
|
||||
{
|
||||
|
||||
[JsonProperty("comParams", NullValueHandling = NullValueHandling.Ignore)]
|
||||
[JsonConverter(typeof(ComSpecJsonConverter))]
|
||||
public ComPort.ComPortSpec? ComParams { get; set; }
|
||||
[JsonProperty("comParams", NullValueHandling = NullValueHandling.Ignore)]
|
||||
[JsonConverter(typeof(ComSpecJsonConverter))]
|
||||
public ComPort.ComPortSpec? ComParams { get; set; }
|
||||
|
||||
[JsonProperty("cresnetId", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string CresnetId { get; set; }
|
||||
[JsonProperty("cresnetId", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string CresnetId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to provide uint conversion of string CresnetId
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public uint CresnetIdInt
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return Convert.ToUInt32(CresnetId, 16);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new FormatException(string.Format("ERROR:Unable to convert Cresnet ID: {0} to hex. Error:\n{1}", CresnetId));
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Attempts to provide uint conversion of string CresnetId
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public uint CresnetIdInt
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return Convert.ToUInt32(CresnetId, 16);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new FormatException(string.Format("ERROR:Unable to convert Cresnet ID: {0} to hex. Error:\n{1}", CresnetId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[JsonProperty("infinetId", NullValueHandling = NullValueHandling.Ignore)]
|
||||
/// <summary>
|
||||
/// Gets or sets the InfinetId
|
||||
/// </summary>
|
||||
public string InfinetId { get; set; }
|
||||
[JsonProperty("infinetId", NullValueHandling = NullValueHandling.Ignore)]
|
||||
/// <summary>
|
||||
/// Gets or sets the InfinetId
|
||||
/// </summary>
|
||||
public string InfinetId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Attepmts to provide uiont conversion of string InifinetId
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public uint InfinetIdInt
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return Convert.ToUInt32(InfinetId, 16);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new FormatException(string.Format("ERROR:Unable to conver Infinet ID: {0} to hex. Error:\n{1}", InfinetId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Attepmts to provide uiont conversion of string InifinetId
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public uint InfinetIdInt
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return Convert.ToUInt32(InfinetId, 16);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new FormatException(string.Format("ERROR:Unable to conver Infinet ID: {0} to hex. Error:\n{1}", InfinetId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a IrControlSpec
|
||||
/// </summary>
|
||||
public class IrControlSpec
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the PortDeviceKey
|
||||
/// </summary>
|
||||
public string PortDeviceKey { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the PortNumber
|
||||
/// </summary>
|
||||
public uint PortNumber { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the File
|
||||
/// </summary>
|
||||
public string File { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Represents a IrControlSpec
|
||||
/// </summary>
|
||||
public class IrControlSpec
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the PortDeviceKey
|
||||
/// </summary>
|
||||
public string PortDeviceKey { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the PortNumber
|
||||
/// </summary>
|
||||
public uint PortNumber { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the File
|
||||
/// </summary>
|
||||
public string File { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Config
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the base properties for a streaming device.
|
||||
/// </summary>
|
||||
public class BaseStreamingDeviceProperties
|
||||
{
|
||||
/// <summary>
|
||||
/// The multicast video address for the streaming device.
|
||||
/// </summary>
|
||||
[JsonProperty("multicastVideoAddress", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string MulticastVideoAddress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The multicast audio address for the streaming device.
|
||||
/// </summary>
|
||||
[JsonProperty("multicastAudioAddress", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string MulticastAudioAddress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The URL for the streaming device's media stream.
|
||||
/// </summary>
|
||||
[JsonProperty("streamUrl", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string StreamUrl { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -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 <see
|
||||
/// cref="PortInformationChanged"/> event is raised whenever the <see cref="NetworkPorts"/> collection
|
||||
/// changes.</remarks>
|
||||
public interface INvxNetworkPortInformation
|
||||
public interface INvxNetworkPortInformation : IKeyed
|
||||
{
|
||||
/// <summary>
|
||||
/// Occurs when the port information changes.
|
||||
|
||||
@@ -202,14 +202,15 @@ namespace PepperDash.Essentials.Core
|
||||
|
||||
private static void ListDevices(string s)
|
||||
{
|
||||
Debug.LogMessage(LogEventLevel.Information, "{0} Devices registered with Device Manager:", Devices.Count);
|
||||
CrestronConsole.ConsoleCommandResponse($"{Devices.Count} Devices registered with Device Manager:");
|
||||
|
||||
var sorted = Devices.Values.ToList();
|
||||
sorted.Sort((a, b) => a.Key.CompareTo(b.Key));
|
||||
|
||||
foreach (var d in sorted)
|
||||
{
|
||||
var name = d is IKeyName ? (d as IKeyName).Name : "---";
|
||||
Debug.LogMessage(LogEventLevel.Information, " [{0}] {1}", d.Key, name);
|
||||
CrestronConsole.ConsoleCommandResponse($" [{d.Key}] {name}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -475,9 +476,9 @@ namespace PepperDash.Essentials.Core
|
||||
if (String.IsNullOrEmpty(s) || s.Contains("?"))
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse(
|
||||
@"SETDEVICESTREAMDEBUG [{deviceKey}] [OFF |TX | RX | BOTH] [timeOutInMinutes]
|
||||
{deviceKey} [OFF | TX | RX | BOTH] - Device to set stream debugging on, and which setting to use
|
||||
timeOutInMinutes - Set timeout for stream debugging. Default is 30 minutes");
|
||||
"SETDEVICESTREAMDEBUG [{deviceKey}] [OFF |TX | RX | BOTH] [timeOutInMinutes]\r\n" +
|
||||
" {deviceKey} [OFF | TX | RX | BOTH] - Device to set stream debugging on, and which setting to use\r\n" +
|
||||
" timeOutInMinutes - Set timeout for stream debugging. Default is 30 minutes");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,16 +3,29 @@ using PepperDash.Essentials.Core.Bridges;
|
||||
|
||||
namespace PepperDash.Essentials.Core
|
||||
{
|
||||
public abstract class EssentialsBridgeableDevice:EssentialsDevice, IBridgeAdvanced
|
||||
/// <summary>
|
||||
/// Base class for devices that can be bridged to an EISC API.
|
||||
/// </summary>
|
||||
public abstract class EssentialsBridgeableDevice : EssentialsDevice, IBridgeAdvanced
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EssentialsBridgeableDevice"/> class with the specified key.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for the device.</param>
|
||||
protected EssentialsBridgeableDevice(string key) : base(key)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EssentialsBridgeableDevice"/> class with the specified key and name.
|
||||
/// </summary>
|
||||
/// <param name="key">The unique key for the device.</param>
|
||||
/// <param name="name">The display name for the device.</param>
|
||||
protected EssentialsBridgeableDevice(string key, string name) : base(key, name)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge);
|
||||
}
|
||||
}
|
||||
@@ -244,6 +244,20 @@ namespace PepperDash.Essentials.Core
|
||||
/// </summary>
|
||||
[JsonProperty("type")]
|
||||
public eRoutingSignalType Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Key for a destination list item. If BOTH SourceListItemKey AND DestinationListItemKey are defined,
|
||||
/// then the direct route method should be used.
|
||||
/// </summary>
|
||||
[JsonProperty("destinationListItemKey", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string DestinationListItemKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Key for a source list item. If BOTH SourceListItemKey AND DestinationListItemKey are defined,
|
||||
/// then the direct route method should be used.
|
||||
/// </summary>
|
||||
[JsonProperty("sourceListItemKey", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string SourceListItemKey { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -135,7 +135,7 @@ namespace PepperDash.Essentials.Core
|
||||
{
|
||||
if (FactoryMethods.ContainsKey(typeName))
|
||||
{
|
||||
Debug.LogInformation("Unable to add type: '{typeName}'. Already exists in DeviceFactory", typeName);
|
||||
Debug.LogInformation("Unable to add type: '{typeName}'. Already exists in DeviceFactory", typeName);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -217,7 +217,8 @@ namespace PepperDash.Essentials.Core
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError(ex, "Exception occurred while creating device {0}: {1}", null, dc.Key, ex.Message);
|
||||
Debug.LogError(ex, "Exception occurred while creating device {key}: {message}", dc.Key, ex.Message);
|
||||
Debug.LogDebug(ex, "Exception details: {stackTrace}", ex.StackTrace);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -249,9 +250,9 @@ namespace PepperDash.Essentials.Core
|
||||
}
|
||||
|
||||
CrestronConsole.ConsoleCommandResponse(
|
||||
@"Type: '{0}'
|
||||
Type: '{1}'
|
||||
Description: {2}{3}", type.Key, Type, description, CrestronEnvironment.NewLine);
|
||||
"Type: '{0}'\r\n" +
|
||||
" Type: '{1}'\r\n" +
|
||||
" Description: {2}{3}", type.Key, Type, description, CrestronEnvironment.NewLine);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using PepperDash.Essentials.Core;
|
||||
|
||||
namespace PepperDash.Essentials.Core.Routing
|
||||
{
|
||||
@@ -25,5 +25,19 @@ namespace PepperDash.Essentials.Core.Routing
|
||||
/// </summary>
|
||||
Dictionary<eRoutingSignalType, string> CurrentSourceKeys { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when the current sources change.
|
||||
/// </summary>
|
||||
event EventHandler CurrentSourcesChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current source for a specific signal type.
|
||||
/// This method updates the current source for the specified signal type and notifies any subscribers of the change.
|
||||
/// </summary>
|
||||
/// <param name="signalType">The signal type to update.</param>
|
||||
/// <param name="sourceListKey">The key for the source list.</param>
|
||||
/// <param name="sourceListItem">The source list item to set as the current source.</param>
|
||||
void SetCurrentSource(eRoutingSignalType signalType, string sourceListKey, SourceListItem sourceListItem);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,38 +22,38 @@ namespace PepperDash.Essentials.Core.Config
|
||||
/// The key of the source device.
|
||||
/// </summary>
|
||||
public string SourceKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The key of the source card (if applicable, e.g., in a modular chassis).
|
||||
/// </summary>
|
||||
|
||||
/// <summary>
|
||||
/// The key of the source card (if applicable, e.g., in a modular chassis).
|
||||
/// </summary>
|
||||
public string SourceCard { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The key of the source output port, used for routing configurations.
|
||||
/// </summary>
|
||||
|
||||
/// <summary>
|
||||
/// The key of the source output port, used for routing configurations.
|
||||
/// </summary>
|
||||
public string SourcePort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DestinationKey
|
||||
/// </summary>
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DestinationKey
|
||||
/// </summary>
|
||||
public string DestinationKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DestinationCard
|
||||
/// </summary>
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DestinationCard
|
||||
/// </summary>
|
||||
public string DestinationCard { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DestinationPort
|
||||
/// </summary>
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DestinationPort
|
||||
/// </summary>
|
||||
public string DestinationPort { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional override for the signal type of the tie line. If set, this overrides the destination port's type for routing calculations.
|
||||
/// </summary>
|
||||
[JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public eRoutingSignalType? OverrideType { get; set; }
|
||||
/// <summary>
|
||||
/// Optional override for the signal type of the tie line. If set, this overrides the destination port's type for routing calculations.
|
||||
/// </summary>
|
||||
[JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public eRoutingSignalType? OverrideType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the appropriate tie line for either a card-based device or
|
||||
@@ -62,40 +62,39 @@ namespace PepperDash.Essentials.Core.Config
|
||||
/// <returns>null if config data does not match ports, cards or devices</returns>
|
||||
public TieLine GetTieLine()
|
||||
{
|
||||
Debug.LogMessage(LogEventLevel.Information, "Build TieLine: {0}",null, this);
|
||||
Debug.LogInformation("Build TieLine: {config}", ToString());
|
||||
|
||||
// Get the source device
|
||||
var sourceDev = DeviceManager.GetDeviceForKey(SourceKey) as IRoutingOutputs;
|
||||
if (sourceDev == null)
|
||||
if (!(DeviceManager.GetDeviceForKey(SourceKey) is IRoutingOutputs sourceDev))
|
||||
{
|
||||
LogError("Routable source not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the destination device
|
||||
var destDev = DeviceManager.GetDeviceForKey(DestinationKey) as IRoutingInputs;
|
||||
if (destDev == null)
|
||||
if (!(DeviceManager.GetDeviceForKey(DestinationKey) is IRoutingInputs destDev))
|
||||
{
|
||||
LogError("Routable destination not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
//Get the source port
|
||||
var sourceOutputPort = sourceDev.OutputPorts[SourcePort];
|
||||
//Get the source port
|
||||
var sourceOutputPort = sourceDev.OutputPorts[SourcePort];
|
||||
|
||||
if (sourceOutputPort == null)
|
||||
if (sourceOutputPort == null)
|
||||
{
|
||||
LogError("Source does not contain port");
|
||||
return null;
|
||||
}
|
||||
|
||||
//Get the Destination port
|
||||
var destinationInputPort = destDev.InputPorts[DestinationPort];
|
||||
//Get the Destination port
|
||||
var destinationInputPort = destDev.InputPorts[DestinationPort];
|
||||
|
||||
if (destinationInputPort == null)
|
||||
{
|
||||
LogError("Destination does not contain port");
|
||||
return null;
|
||||
}
|
||||
if (destinationInputPort == null)
|
||||
{
|
||||
LogError("Destination does not contain port");
|
||||
return null;
|
||||
}
|
||||
|
||||
return new TieLine(sourceOutputPort, destinationInputPort, OverrideType);
|
||||
}
|
||||
@@ -104,9 +103,9 @@ namespace PepperDash.Essentials.Core.Config
|
||||
/// Logs an error message related to creating this tie line configuration.
|
||||
/// </summary>
|
||||
/// <param name="msg">The specific error message.</param>
|
||||
void LogError(string msg)
|
||||
private void LogError(string msg)
|
||||
{
|
||||
Debug.LogMessage(LogEventLevel.Error, "WARNING: Cannot create tie line: {message}:\r {tieLineConfig}",null, msg, this);
|
||||
Debug.LogError("Cannot create tie line: {message}", msg);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -115,8 +114,7 @@ namespace PepperDash.Essentials.Core.Config
|
||||
/// <returns>A string describing the source and destination of the configured tie line.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0}.{1}.{2} --> {3}.{4}.{5}", SourceKey, SourceCard, SourcePort,
|
||||
DestinationKey, DestinationCard, DestinationPort);
|
||||
return $"{SourceKey}.{SourceCard}.{SourcePort} --> {DestinationKey}.{DestinationCard}.{DestinationPort}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
using Newtonsoft.Json;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Core.Logging;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Bridges;
|
||||
using PepperDash.Essentials.Core.DeviceTypeInterfaces;
|
||||
@@ -52,9 +53,9 @@ namespace PepperDash.Essentials.Devices.Common.Displays
|
||||
/// </summary>
|
||||
public event SourceInfoChangeHandler CurrentSourceChange;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the CurrentSourceInfoKey
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// Gets or sets the CurrentSourceInfoKey
|
||||
/// </summary>
|
||||
public string CurrentSourceInfoKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -89,29 +90,32 @@ namespace PepperDash.Essentials.Devices.Common.Displays
|
||||
/// <inheritdoc/>
|
||||
public Dictionary<eRoutingSignalType, string> CurrentSourceKeys { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler CurrentSourcesChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Gets feedback indicating whether the display is currently cooling down after being powered off.
|
||||
/// </summary>
|
||||
public BoolFeedback IsCoolingDownFeedback { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the IsWarmingUpFeedback
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// Gets or sets the IsWarmingUpFeedback
|
||||
/// </summary>
|
||||
public BoolFeedback IsWarmingUpFeedback { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the UsageTracker
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// Gets or sets the UsageTracker
|
||||
/// </summary>
|
||||
public UsageTracking UsageTracker { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the WarmupTime
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// Gets or sets the WarmupTime
|
||||
/// </summary>
|
||||
public uint WarmupTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the CooldownTime
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// Gets or sets the CooldownTime
|
||||
/// </summary>
|
||||
public uint CooldownTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -189,7 +193,7 @@ namespace PepperDash.Essentials.Devices.Common.Displays
|
||||
/// <summary>
|
||||
/// Gets the collection of feedback objects for this display device.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
/// <inheritdoc />
|
||||
public virtual FeedbackCollection<Feedback> Feedbacks
|
||||
{
|
||||
get
|
||||
@@ -378,6 +382,53 @@ namespace PepperDash.Essentials.Devices.Common.Displays
|
||||
volumeDisplayWithFeedback.MuteFeedback.LinkComplementInputSig(trilist.BooleanInput[joinMap.VolumeMuteOff.JoinNumber]);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void SetCurrentSource(eRoutingSignalType signalType, string sourceListKey, SourceListItem sourceListItem)
|
||||
{
|
||||
foreach (eRoutingSignalType type in Enum.GetValues(typeof(eRoutingSignalType)))
|
||||
{
|
||||
var flagValue = Convert.ToInt32(type);
|
||||
// Skip if flagValue is 0 or not a power of two (i.e., not a single-bit flag).
|
||||
// (flagValue & (flagValue - 1)) != 0 checks if more than one bit is set.
|
||||
if (flagValue == 0 || (flagValue & (flagValue - 1)) != 0)
|
||||
{
|
||||
this.LogDebug("Skipping {type}", type);
|
||||
continue;
|
||||
}
|
||||
|
||||
this.LogDebug("setting {type}", type);
|
||||
|
||||
if (signalType.HasFlag(type))
|
||||
{
|
||||
UpdateCurrentSources(type, sourceListKey, sourceListItem);
|
||||
}
|
||||
}
|
||||
// Raise the CurrentSourcesChanged event
|
||||
CurrentSourcesChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
private void UpdateCurrentSources(eRoutingSignalType signalType, string sourceListKey, SourceListItem sourceListItem)
|
||||
{
|
||||
if (CurrentSources.ContainsKey(signalType))
|
||||
{
|
||||
CurrentSources[signalType] = sourceListItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentSources.Add(signalType, sourceListItem);
|
||||
}
|
||||
|
||||
// Update the current source key for the specified signal type
|
||||
if (CurrentSourceKeys.ContainsKey(signalType))
|
||||
{
|
||||
CurrentSourceKeys[signalType] = sourceListKey;
|
||||
}
|
||||
else
|
||||
{
|
||||
CurrentSourceKeys.Add(signalType, sourceListKey);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -140,17 +140,19 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
||||
|
||||
if (Camera is IHasCameraPresets presetsCamera)
|
||||
{
|
||||
for (int i = 1; i <= 6; i++)
|
||||
AddAction("/recallPreset", (id, content) =>
|
||||
{
|
||||
var preset = i;
|
||||
AddAction("/cameraPreset" + i, (id, content) =>
|
||||
{
|
||||
var msg = content.ToObject<MobileControlSimpleContent<int>>();
|
||||
var msg = content.ToObject<MobileControlSimpleContent<int>>();
|
||||
|
||||
presetsCamera.PresetSelect(msg.Value);
|
||||
});
|
||||
presetsCamera.PresetSelect(msg.Value);
|
||||
});
|
||||
|
||||
}
|
||||
AddAction("/storePreset", (id, content) =>
|
||||
{
|
||||
var msg = content.ToObject<MobileControlSimpleContent<int>>();
|
||||
|
||||
presetsCamera.PresetStore(msg.Value, string.Empty);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,9 +166,8 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
||||
return;
|
||||
}
|
||||
|
||||
timerHandler(state.Value, cameraAction);
|
||||
timerHandler(Camera.Key, cameraAction);
|
||||
|
||||
cameraAction(state.Value.Equals("true", StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using PepperDash.Essentials.Core.Routing;
|
||||
|
||||
namespace PepperDash.Essentials.AppServer.Messengers
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a IHasCurrentSourceInfoMessenger
|
||||
/// </summary>
|
||||
public class CurrentSourcesMessenger : MessengerBase
|
||||
{
|
||||
private readonly ICurrentSources sourceDevice;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CurrentSourcesMessenger"/> class.
|
||||
/// </summary>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="messagePath">The message path.</param>
|
||||
/// <param name="device">The device.</param>
|
||||
public CurrentSourcesMessenger(string key, string messagePath, ICurrentSources device) : base(key, messagePath, device as IKeyName)
|
||||
{
|
||||
sourceDevice = device;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers the actions for the messenger.
|
||||
/// </summary>
|
||||
protected override void RegisterActions()
|
||||
{
|
||||
base.RegisterActions();
|
||||
|
||||
AddAction("/fullStatus", (id, content) =>
|
||||
{
|
||||
var message = new CurrentSourcesStateMessage
|
||||
{
|
||||
CurrentSourceKeys = sourceDevice.CurrentSourceKeys,
|
||||
CurrentSources = sourceDevice.CurrentSources
|
||||
};
|
||||
|
||||
PostStatusMessage(message);
|
||||
});
|
||||
|
||||
sourceDevice.CurrentSourcesChanged += (sender, e) =>
|
||||
{
|
||||
PostStatusMessage(JToken.FromObject(new
|
||||
{
|
||||
currentSourceKeys = sourceDevice.CurrentSourceKeys,
|
||||
currentSources = sourceDevice.CurrentSources
|
||||
}));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a CurrentSourcesStateMessage
|
||||
/// </summary>
|
||||
public class CurrentSourcesStateMessage : DeviceStateMessageBase
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the CurrentSourceKey
|
||||
/// </summary>
|
||||
[JsonProperty("currentSourceKeys", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public Dictionary<eRoutingSignalType, string> CurrentSourceKeys { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the CurrentSource
|
||||
/// </summary>
|
||||
[JsonProperty("currentSources")]
|
||||
public Dictionary<eRoutingSignalType, SourceListItem> CurrentSources { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PepperDash.Core;
|
||||
using PepperDash.Essentials.Core;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PepperDash.Essentials.AppServer.Messengers
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a IBasicVideoMuteWithFeedbackMessenger
|
||||
/// </summary>
|
||||
public class IBasicVideoMuteWithFeedbackMessenger : MessengerBase
|
||||
{
|
||||
private readonly IBasicVideoMuteWithFeedback device;
|
||||
|
||||
public IBasicVideoMuteWithFeedbackMessenger(string key, string messagePath, IBasicVideoMuteWithFeedback device)
|
||||
: base(key, messagePath, device as IKeyName)
|
||||
{
|
||||
this.device = device;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SendFullStatus method
|
||||
/// </summary>
|
||||
public void SendFullStatus()
|
||||
{
|
||||
var messageObj = new IBasicVideoMuteWithFeedbackMessage
|
||||
{
|
||||
VideoMuteState = device.VideoMuteIsOn.BoolValue
|
||||
};
|
||||
|
||||
PostStatusMessage(messageObj);
|
||||
}
|
||||
|
||||
protected override void RegisterActions()
|
||||
{
|
||||
base.RegisterActions();
|
||||
|
||||
AddAction("/fullStatus", (id, content) => SendFullStatus());
|
||||
|
||||
AddAction("/videoMuteToggle", (id, content) =>
|
||||
{
|
||||
device.VideoMuteToggle();
|
||||
});
|
||||
|
||||
AddAction("/videoMuteOn", (id, content) =>
|
||||
{
|
||||
device.VideoMuteOn();
|
||||
});
|
||||
|
||||
AddAction("/videoMuteOff", (id, content) =>
|
||||
{
|
||||
device.VideoMuteOff();
|
||||
});
|
||||
|
||||
device.VideoMuteIsOn.OutputChange += VideoMuteIsOnFeedback_OutputChange;
|
||||
}
|
||||
|
||||
private void VideoMuteIsOnFeedback_OutputChange(object sender, FeedbackEventArgs args)
|
||||
{
|
||||
PostStatusMessage(JToken.FromObject(new
|
||||
{
|
||||
videoMuteState = args.BoolValue
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a IBasicVideoMuteWithFeedbackMessage
|
||||
/// </summary>
|
||||
public class IBasicVideoMuteWithFeedbackMessage : DeviceStateMessageBase
|
||||
{
|
||||
[JsonProperty("videoMuteState")]
|
||||
public bool VideoMuteState { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -54,16 +54,18 @@ namespace PepperDash.Essentials.AppServer.Messengers
|
||||
/// </summary>
|
||||
public class CurrentSourceStateMessage : DeviceStateMessageBase
|
||||
{
|
||||
[JsonProperty("currentSourceKey", NullValueHandling = NullValueHandling.Ignore)]
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the CurrentSourceKey
|
||||
/// </summary>
|
||||
[JsonProperty("currentSourceKey", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string CurrentSourceKey { get; set; }
|
||||
|
||||
[JsonProperty("currentSource")]
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the CurrentSource
|
||||
/// </summary>
|
||||
[JsonProperty("currentSource")]
|
||||
public SourceListItem CurrentSource { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
/// </summary>
|
||||
public class MobileControlConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the ServerUrl
|
||||
/// </summary>
|
||||
[JsonProperty("serverUrl")]
|
||||
public string ServerUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ClientAppUrl
|
||||
/// </summary>
|
||||
[JsonProperty("clientAppUrl")]
|
||||
public string ClientAppUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DirectServer
|
||||
/// </summary>
|
||||
[JsonProperty("directServer")]
|
||||
public MobileControlDirectServerPropertiesConfig DirectServer { get; set; }
|
||||
|
||||
[JsonProperty("applicationConfig")]
|
||||
/// <summary>
|
||||
/// Gets or sets the ApplicationConfig
|
||||
/// </summary>
|
||||
[JsonProperty("applicationConfig")]
|
||||
public MobileControlApplicationConfig ApplicationConfig { get; set; } = null;
|
||||
|
||||
[JsonProperty("enableApiServer")]
|
||||
/// <summary>
|
||||
/// Gets or sets the EnableApiServer
|
||||
/// </summary>
|
||||
[JsonProperty("enableApiServer")]
|
||||
public bool EnableApiServer { get; set; } = true;
|
||||
}
|
||||
|
||||
@@ -36,27 +45,42 @@ namespace PepperDash.Essentials
|
||||
/// </summary>
|
||||
public class MobileControlDirectServerPropertiesConfig
|
||||
{
|
||||
[JsonProperty("enableDirectServer")]
|
||||
/// <summary>
|
||||
/// Gets or sets the EnableDirectServer
|
||||
/// </summary>
|
||||
[JsonProperty("enableDirectServer")]
|
||||
public bool EnableDirectServer { get; set; }
|
||||
|
||||
[JsonProperty("port")]
|
||||
/// <summary>
|
||||
/// Gets or sets the Port
|
||||
/// </summary>
|
||||
[JsonProperty("port")]
|
||||
public int Port { get; set; }
|
||||
|
||||
[JsonProperty("logging")]
|
||||
/// <summary>
|
||||
/// Gets or sets the Logging
|
||||
/// </summary>
|
||||
[JsonProperty("logging")]
|
||||
public MobileControlLoggingConfig Logging { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the AutomaticallyForwardPortToCSLAN
|
||||
/// </summary>
|
||||
[JsonProperty("automaticallyForwardPortToCSLAN")]
|
||||
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()
|
||||
{
|
||||
Logging = new MobileControlLoggingConfig();
|
||||
@@ -68,26 +92,26 @@ namespace PepperDash.Essentials
|
||||
/// </summary>
|
||||
public class MobileControlLoggingConfig
|
||||
{
|
||||
[JsonProperty("enableRemoteLogging")]
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the EnableRemoteLogging
|
||||
/// </summary>
|
||||
[JsonProperty("enableRemoteLogging")]
|
||||
public bool EnableRemoteLogging { get; set; }
|
||||
|
||||
[JsonProperty("host")]
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Host
|
||||
/// </summary>
|
||||
[JsonProperty("host")]
|
||||
public string Host { get; set; }
|
||||
|
||||
[JsonProperty("port")]
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Port
|
||||
/// </summary>
|
||||
[JsonProperty("port")]
|
||||
public int Port { get; set; }
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -95,16 +119,16 @@ namespace PepperDash.Essentials
|
||||
/// </summary>
|
||||
public class MobileControlRoomBridgePropertiesConfig
|
||||
{
|
||||
[JsonProperty("key")]
|
||||
/// <summary>
|
||||
/// Gets or sets the Key
|
||||
/// </summary>
|
||||
[JsonProperty("key")]
|
||||
public string Key { get; set; }
|
||||
|
||||
[JsonProperty("roomKey")]
|
||||
/// <summary>
|
||||
/// Gets or sets the RoomKey
|
||||
/// </summary>
|
||||
[JsonProperty("roomKey")]
|
||||
public string RoomKey { get; set; }
|
||||
}
|
||||
|
||||
@@ -113,53 +137,71 @@ namespace PepperDash.Essentials
|
||||
/// </summary>
|
||||
public class MobileControlSimplRoomBridgePropertiesConfig
|
||||
{
|
||||
[JsonProperty("eiscId")]
|
||||
/// <summary>
|
||||
/// Gets or sets the EiscId
|
||||
/// </summary>
|
||||
[JsonProperty("eiscId")]
|
||||
public string EiscId { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a MobileControlApplicationConfig
|
||||
/// </summary>
|
||||
public class MobileControlApplicationConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the ApiPath
|
||||
/// </summary>
|
||||
[JsonProperty("apiPath")]
|
||||
public string ApiPath { get; set; }
|
||||
|
||||
[JsonProperty("gatewayAppPath")]
|
||||
/// <summary>
|
||||
/// Gets or sets the GatewayAppPath
|
||||
/// </summary>
|
||||
[JsonProperty("gatewayAppPath")]
|
||||
public string GatewayAppPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the EnableDev
|
||||
/// </summary>
|
||||
[JsonProperty("enableDev")]
|
||||
public bool? EnableDev { get; set; }
|
||||
|
||||
[JsonProperty("logoPath")]
|
||||
/// <summary>
|
||||
/// Gets or sets the LogoPath
|
||||
/// </summary>
|
||||
[JsonProperty("logoPath")]
|
||||
public string LogoPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the IconSet
|
||||
/// </summary>
|
||||
[JsonProperty("iconSet")]
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public MCIconSet? IconSet { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LoginMode
|
||||
/// </summary>
|
||||
[JsonProperty("loginMode")]
|
||||
public string LoginMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Modes
|
||||
/// </summary>
|
||||
[JsonProperty("modes")]
|
||||
public Dictionary<string, McMode> Modes { get; set; }
|
||||
|
||||
[JsonProperty("enableRemoteLogging")]
|
||||
/// <summary>
|
||||
/// Gets or sets the Logging
|
||||
/// </summary>
|
||||
[JsonProperty("enableRemoteLogging")]
|
||||
public bool Logging { get; set; }
|
||||
|
||||
[JsonProperty("partnerMetadata", NullValueHandling = NullValueHandling.Ignore)]
|
||||
/// <summary>
|
||||
/// Gets or sets the PartnerMetadata
|
||||
/// </summary>
|
||||
[JsonProperty("partnerMetadata", NullValueHandling = NullValueHandling.Ignore)]
|
||||
public List<MobileControlPartnerMetadata> PartnerMetadata { get; set; }
|
||||
}
|
||||
|
||||
@@ -168,22 +210,22 @@ namespace PepperDash.Essentials
|
||||
/// </summary>
|
||||
public class MobileControlPartnerMetadata
|
||||
{
|
||||
[JsonProperty("role")]
|
||||
/// <summary>
|
||||
/// Gets or sets the Role
|
||||
/// </summary>
|
||||
[JsonProperty("role")]
|
||||
public string Role { get; set; }
|
||||
|
||||
[JsonProperty("description")]
|
||||
/// <summary>
|
||||
/// Gets or sets the Description
|
||||
/// </summary>
|
||||
[JsonProperty("description")]
|
||||
public string Description { get; set; }
|
||||
|
||||
[JsonProperty("logoPath")]
|
||||
/// <summary>
|
||||
/// Gets or sets the LogoPath
|
||||
/// </summary>
|
||||
[JsonProperty("logoPath")]
|
||||
public string LogoPath { get; set; }
|
||||
}
|
||||
|
||||
@@ -192,21 +234,22 @@ namespace PepperDash.Essentials
|
||||
/// </summary>
|
||||
public class McMode
|
||||
{
|
||||
[JsonProperty("listPageText")]
|
||||
/// <summary>
|
||||
/// Gets or sets the ListPageText
|
||||
/// </summary>
|
||||
[JsonProperty("listPageText")]
|
||||
public string ListPageText { get; set; }
|
||||
[JsonProperty("loginHelpText")]
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the LoginHelpText
|
||||
/// </summary>
|
||||
[JsonProperty("loginHelpText")]
|
||||
public string LoginHelpText { get; set; }
|
||||
|
||||
[JsonProperty("passcodePageText")]
|
||||
/// <summary>
|
||||
/// Gets or sets the PasscodePageText
|
||||
/// </summary>
|
||||
[JsonProperty("passcodePageText")]
|
||||
public string PasscodePageText { get; set; }
|
||||
}
|
||||
|
||||
@@ -215,8 +258,19 @@ namespace PepperDash.Essentials
|
||||
/// </summary>
|
||||
public enum MCIconSet
|
||||
{
|
||||
/// <summary>
|
||||
/// Google icon set
|
||||
/// </summary>
|
||||
GOOGLE,
|
||||
|
||||
/// <summary>
|
||||
/// Habanero icon set
|
||||
/// </summary>
|
||||
HABANERO,
|
||||
|
||||
/// <summary>
|
||||
/// Neo icon set
|
||||
/// </summary>
|
||||
NEO
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,10 @@
|
||||
using Crestron.SimplSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharp.CrestronIO;
|
||||
using Crestron.SimplSharp.Net.Http;
|
||||
using Crestron.SimplSharp.WebScripting;
|
||||
@@ -30,12 +36,6 @@ using PepperDash.Essentials.RoomBridges;
|
||||
using PepperDash.Essentials.Services;
|
||||
using PepperDash.Essentials.WebApiHandlers;
|
||||
using PepperDash.Essentials.WebSocketServer;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using WebSocketSharp;
|
||||
|
||||
namespace PepperDash.Essentials
|
||||
@@ -505,6 +505,25 @@ namespace PepperDash.Essentials
|
||||
messengerAdded = true;
|
||||
}
|
||||
|
||||
if (device is IBasicVideoMuteWithFeedback)
|
||||
{
|
||||
var deviceKey = device.Key;
|
||||
this.LogVerbose(
|
||||
"Adding IBasicVideoMuteWithFeedback for {deviceKey}",
|
||||
deviceKey
|
||||
);
|
||||
|
||||
var videoMuteControlDevice = device as IBasicVideoMuteWithFeedback;
|
||||
var messenger = new IBasicVideoMuteWithFeedbackMessenger(
|
||||
$"{device.Key}-videoMute-{Key}",
|
||||
string.Format("/device/{0}", deviceKey),
|
||||
videoMuteControlDevice
|
||||
);
|
||||
AddDefaultDeviceMessenger(messenger);
|
||||
|
||||
messengerAdded = true;
|
||||
}
|
||||
|
||||
if (device is ILightingScenes || device is LightingBase)
|
||||
{
|
||||
var deviceKey = device.Key;
|
||||
@@ -582,7 +601,7 @@ namespace PepperDash.Essentials
|
||||
{
|
||||
this.LogVerbose(
|
||||
"Adding ISetTopBoxControlMessenger for {deviceKey}"
|
||||
);
|
||||
);
|
||||
|
||||
var messenger = new ISetTopBoxControlsMessenger(
|
||||
$"{device.Key}-stb-{Key}",
|
||||
@@ -599,7 +618,7 @@ namespace PepperDash.Essentials
|
||||
{
|
||||
this.LogVerbose(
|
||||
"Adding IChannelMessenger for {deviceKey}", device.Key
|
||||
);
|
||||
);
|
||||
|
||||
var messenger = new IChannelMessenger(
|
||||
$"{device.Key}-channel-{Key}",
|
||||
@@ -614,7 +633,7 @@ namespace PepperDash.Essentials
|
||||
|
||||
if (device is IColor colorDevice)
|
||||
{
|
||||
this.LogVerbose("Adding IColorMessenger for {deviceKey}", device.Key);
|
||||
this.LogVerbose("Adding IColorMessenger for {deviceKey}", device.Key);
|
||||
|
||||
var messenger = new IColorMessenger(
|
||||
$"{device.Key}-color-{Key}",
|
||||
@@ -629,7 +648,7 @@ namespace PepperDash.Essentials
|
||||
|
||||
if (device is IDPad dPadDevice)
|
||||
{
|
||||
this.LogVerbose("Adding IDPadMessenger for {deviceKey}", device.Key);
|
||||
this.LogVerbose("Adding IDPadMessenger for {deviceKey}", device.Key);
|
||||
|
||||
var messenger = new IDPadMessenger(
|
||||
$"{device.Key}-dPad-{Key}",
|
||||
@@ -644,7 +663,7 @@ namespace PepperDash.Essentials
|
||||
|
||||
if (device is INumericKeypad nkDevice)
|
||||
{
|
||||
this.LogVerbose("Adding INumericKeyapdMessenger for {deviceKey}", device.Key);
|
||||
this.LogVerbose("Adding INumericKeyapdMessenger for {deviceKey}", device.Key);
|
||||
|
||||
var messenger = new INumericKeypadMessenger(
|
||||
$"{device.Key}-numericKeypad-{Key}",
|
||||
@@ -659,7 +678,7 @@ namespace PepperDash.Essentials
|
||||
|
||||
if (device is IHasPowerControl pcDevice)
|
||||
{
|
||||
this.LogVerbose("Adding IHasPowerControlMessenger for {deviceKey}", device.Key);
|
||||
this.LogVerbose("Adding IHasPowerControlMessenger for {deviceKey}", device.Key);
|
||||
|
||||
var messenger = new IHasPowerMessenger(
|
||||
$"{device.Key}-powerControl-{Key}",
|
||||
@@ -693,7 +712,7 @@ namespace PepperDash.Essentials
|
||||
{
|
||||
this.LogVerbose(
|
||||
"Adding ITransportMessenger for {deviceKey}", device.Key
|
||||
);
|
||||
);
|
||||
|
||||
var messenger = new ITransportMessenger(
|
||||
$"{device.Key}-transport-{Key}",
|
||||
@@ -721,6 +740,17 @@ namespace PepperDash.Essentials
|
||||
messengerAdded = true;
|
||||
}
|
||||
|
||||
if (device is ICurrentSources currentSources)
|
||||
{
|
||||
this.LogVerbose("Adding CurrentSourcesMessenger for {deviceKey}", device.Key);
|
||||
|
||||
var messenger = new CurrentSourcesMessenger($"{device.Key}-currentSources-{Key}", $"/device/{device.Key}", currentSources);
|
||||
|
||||
AddDefaultDeviceMessenger(messenger);
|
||||
|
||||
messengerAdded = true;
|
||||
}
|
||||
|
||||
if (device is ISwitchedOutput switchedDevice)
|
||||
{
|
||||
this.LogVerbose(
|
||||
@@ -1625,15 +1655,14 @@ namespace PepperDash.Essentials
|
||||
if (Config.EnableApiServer)
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse(
|
||||
@"Mobile Control Edge Server API Information:
|
||||
|
||||
Server address: {0}
|
||||
System Name: {1}
|
||||
System URL: {2}
|
||||
System UUID: {3}
|
||||
System User code: {4}
|
||||
Connected?: {5}
|
||||
Seconds Since Last Ack: {6}",
|
||||
"Mobile Control Edge Server API Information:\r\n\r\n" +
|
||||
"\tServer address: {0}\r\n" +
|
||||
"\tSystem Name: {1}\r\n" +
|
||||
"\tSystem URL: {2}\r\n" +
|
||||
"\tSystem UUID: {3}\r\n" +
|
||||
"\tSystem User code: {4}\r\n" +
|
||||
"\tConnected?: {5}\r\n" +
|
||||
"\tSeconds Since Last Ack: {6}\r\n",
|
||||
url,
|
||||
name,
|
||||
ConfigReader.ConfigObject.SystemUrl,
|
||||
@@ -1646,10 +1675,8 @@ namespace PepperDash.Essentials
|
||||
else
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse(
|
||||
@"
|
||||
Mobile Control Edge Server API Information:
|
||||
Not Enabled in Config.
|
||||
"
|
||||
"\r\nMobile Control Edge Server API Information:\r\n" +
|
||||
" Not Enabled in Config.\r\n"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1660,21 +1687,17 @@ Mobile Control Edge Server API Information:
|
||||
)
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse(
|
||||
@"
|
||||
Mobile Control Direct Server Information:
|
||||
User App URL: {0}
|
||||
Server port: {1}
|
||||
",
|
||||
"\r\nMobile Control Direct Server Information:\r\n" +
|
||||
" User App URL: {0}\r\n" +
|
||||
" Server port: {1}\r\n",
|
||||
string.Format("{0}[insert_client_token]", _directServer.UserAppUrlPrefix),
|
||||
_directServer.Port
|
||||
);
|
||||
|
||||
CrestronConsole.ConsoleCommandResponse(
|
||||
@"
|
||||
UI Client Info:
|
||||
Tokens Defined: {0}
|
||||
Clients Connected: {1}
|
||||
",
|
||||
"\r\n UI Client Info:\r\n" +
|
||||
" Tokens Defined: {0}\r\n" +
|
||||
" Clients Connected: {1}\r\n",
|
||||
_directServer.UiClients.Count,
|
||||
_directServer.ConnectedUiClientsCount
|
||||
);
|
||||
@@ -1692,15 +1715,13 @@ Mobile Control Direct Server Information:
|
||||
}
|
||||
|
||||
CrestronConsole.ConsoleCommandResponse(
|
||||
@"
|
||||
Client {0}:
|
||||
Room Key: {1}
|
||||
Touchpanel Key: {6}
|
||||
Token: {2}
|
||||
Client URL: {3}
|
||||
Connected: {4}
|
||||
Duration: {5}
|
||||
",
|
||||
"\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,
|
||||
@@ -1715,9 +1736,8 @@ Duration: {5}
|
||||
else
|
||||
{
|
||||
CrestronConsole.ConsoleCommandResponse(
|
||||
@"
|
||||
Mobile Control Direct Server Infromation:
|
||||
Not Enabled in Config."
|
||||
"\r\nMobile Control Direct Server Information:\r\n" +
|
||||
" Not Enabled in Config.\r\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -2309,7 +2329,7 @@ Mobile Control Direct Server Infromation:
|
||||
{
|
||||
this.LogInformation("-- Warning: Incoming message has no registered handler {type}", message.Type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var handler in handlers)
|
||||
{
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Crestron.SimplSharp;
|
||||
using Crestron.SimplSharpPro;
|
||||
using Crestron.SimplSharpPro.DeviceSupport;
|
||||
using Crestron.SimplSharpPro.UI;
|
||||
@@ -106,6 +108,11 @@ namespace PepperDash.Essentials.Touchpanel
|
||||
|
||||
public ReadOnlyCollection<ConnectedIpInformation> ConnectedIps => Panel.ConnectedIpList;
|
||||
|
||||
private System.Net.IPAddress csIpAddress;
|
||||
|
||||
private System.Net.IPAddress csSubnetMask;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the MobileControlTouchpanelController class.
|
||||
/// </summary>
|
||||
@@ -182,6 +189,13 @@ namespace PepperDash.Essentials.Touchpanel
|
||||
};
|
||||
|
||||
RegisterForExtenders();
|
||||
|
||||
var csAdapterId = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetCSAdapter);
|
||||
var csSubnetMask = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, csAdapterId);
|
||||
var csIpAddress = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, csAdapterId);
|
||||
|
||||
this.csSubnetMask = System.Net.IPAddress.Parse(csSubnetMask);
|
||||
this.csIpAddress = System.Net.IPAddress.Parse(csIpAddress);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -381,19 +395,81 @@ namespace PepperDash.Essentials.Touchpanel
|
||||
McServerUrlFeedback.LinkInputSig(Panel.StringInput[3]);
|
||||
UserCodeFeedback.LinkInputSig(Panel.StringInput[4]);
|
||||
|
||||
Panel.IpInformationChange += (sender, args) =>
|
||||
{
|
||||
if (args.Connected)
|
||||
{
|
||||
this.LogVerbose("Connection from IP: {ip}", args.DeviceIpAddress);
|
||||
this.LogInformation("Sending {appUrl} on join 1", AppUrlFeedback.StringValue);
|
||||
|
||||
var appUrl = GetUrlWithCorrectIp(_appUrl);
|
||||
Panel.StringInput[1].StringValue = appUrl;
|
||||
|
||||
SetAppUrl(appUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.LogVerbose("Disconnection from IP: {ip}", args.DeviceIpAddress);
|
||||
}
|
||||
};
|
||||
|
||||
Panel.OnlineStatusChange += (sender, args) =>
|
||||
{
|
||||
UpdateFeedbacks();
|
||||
|
||||
this.LogInformation("Sending {appUrl} on join 1", AppUrlFeedback.StringValue);
|
||||
|
||||
Panel.StringInput[1].StringValue = AppUrlFeedback.StringValue;
|
||||
UpdateFeedbacks();
|
||||
Panel.StringInput[1].StringValue = _appUrl;
|
||||
Panel.StringInput[2].StringValue = QrCodeUrlFeedback.StringValue;
|
||||
Panel.StringInput[3].StringValue = McServerUrlFeedback.StringValue;
|
||||
Panel.StringInput[4].StringValue = UserCodeFeedback.StringValue;
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the URL with the correct IP address based on the connected devices and the Crestron processor's IP address.
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <returns></returns>
|
||||
private string GetUrlWithCorrectIp(string url)
|
||||
{
|
||||
var lanAdapterId = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetLANAdapter);
|
||||
|
||||
var processorIp = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, lanAdapterId);
|
||||
|
||||
if(csIpAddress == null || csSubnetMask == null || url == null)
|
||||
{
|
||||
this.LogWarning("CS IP Address Subnet Mask or url is null, cannot determine correct IP for URL");
|
||||
return url;
|
||||
}
|
||||
|
||||
this.LogVerbose("Processor IP: {processorIp}, CS IP: {csIpAddress}, CS Subnet Mask: {csSubnetMask}", processorIp, csIpAddress, csSubnetMask);
|
||||
this.LogVerbose("Connected IP Count: {connectedIps}", ConnectedIps.Count);
|
||||
|
||||
var ip = ConnectedIps.Any(ipInfo =>
|
||||
{
|
||||
if (System.Net.IPAddress.TryParse(ipInfo.DeviceIpAddress, out var parsedIp))
|
||||
{
|
||||
return csIpAddress.IsInSameSubnet(parsedIp, csSubnetMask);
|
||||
}
|
||||
this.LogWarning("Invalid IP address: {deviceIpAddress}", ipInfo.DeviceIpAddress);
|
||||
return false;
|
||||
}) ? csIpAddress.ToString() : processorIp;
|
||||
|
||||
var match = Regex.Match(url, @"^http://([^:/]+):\d+/mc/app\?token=.+$");
|
||||
if (match.Success)
|
||||
{
|
||||
string ipa = match.Groups[1].Value;
|
||||
// ip will be "192.168.1.100"
|
||||
}
|
||||
|
||||
// replace ipa with ip but leave the rest of the string intact
|
||||
var updatedUrl = Regex.Replace(url, @"^http://[^:/]+", $"http://{ip}");
|
||||
|
||||
this.LogVerbose("Updated URL: {updatedUrl}", updatedUrl);
|
||||
|
||||
return updatedUrl;
|
||||
}
|
||||
|
||||
private void SubscribeForMobileControlUpdates()
|
||||
{
|
||||
foreach (var dev in DeviceManager.AllDevices)
|
||||
@@ -443,7 +519,8 @@ namespace PepperDash.Essentials.Touchpanel
|
||||
/// </summary>
|
||||
public void SetAppUrl(string url)
|
||||
{
|
||||
_appUrl = url;
|
||||
_appUrl = GetUrlWithCorrectIp(url);
|
||||
|
||||
AppUrlFeedback.FireUpdate();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
@@ -41,8 +42,14 @@ namespace PepperDash.Essentials.WebSocketServer
|
||||
|
||||
private HttpServer _server;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the HttpServer instance
|
||||
/// </summary>
|
||||
public HttpServer Server => _server;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of UI client contexts
|
||||
/// </summary>
|
||||
public Dictionary<string, UiClientContext> UiClients { get; private set; }
|
||||
|
||||
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>
|
||||
/// The path for the WebSocket messaging
|
||||
/// </summary>
|
||||
private readonly string _wsPath = "/mc/api/ui/join/";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the WebSocket path
|
||||
/// </summary>
|
||||
public string WsPath => _wsPath;
|
||||
|
||||
/// <summary>
|
||||
@@ -89,6 +99,9 @@ namespace PepperDash.Essentials.WebSocketServer
|
||||
/// </summary>
|
||||
public int Port { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user app URL prefix
|
||||
/// </summary>
|
||||
public string UserAppUrlPrefix
|
||||
{
|
||||
get
|
||||
@@ -101,6 +114,9 @@ namespace PepperDash.Essentials.WebSocketServer
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the count of connected UI clients
|
||||
/// </summary>
|
||||
public int ConnectedUiClientsCount
|
||||
{
|
||||
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)
|
||||
: base(key)
|
||||
{
|
||||
@@ -327,17 +346,26 @@ namespace PepperDash.Essentials.WebSocketServer
|
||||
}
|
||||
|
||||
string ip = processorIp;
|
||||
if (touchpanel.Touchpanel is IMobileControlCrestronTouchpanelController crestronTouchpanel && csIpAddress != null)
|
||||
|
||||
// Moved to the MobileControlTouchpanelController class in the GetUrlWithCorrectIp method
|
||||
// triggered by the Panel.IpInformationChange event so that we know we have the necessary info
|
||||
// to make the determination of which IP to use.
|
||||
//if (touchpanel.Touchpanel is IMobileControlCrestronTouchpanelController crestronTouchpanel && csIpAddress != null)
|
||||
//{
|
||||
// ip = crestronTouchpanel.ConnectedIps.Any(ipInfo =>
|
||||
// {
|
||||
// if (System.Net.IPAddress.TryParse(ipInfo.DeviceIpAddress, out var parsedIp))
|
||||
// {
|
||||
// return csIpAddress.IsInSameSubnet(parsedIp, csSubnetMask);
|
||||
// }
|
||||
// this.LogWarning("Invalid IP address: {deviceIpAddress}", ipInfo.DeviceIpAddress);
|
||||
// return false;
|
||||
// }) ? 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 = crestronTouchpanel.ConnectedIps.Any(ipInfo =>
|
||||
{
|
||||
if (System.Net.IPAddress.TryParse(ipInfo.DeviceIpAddress, out var parsedIp))
|
||||
{
|
||||
return csIpAddress.IsInSameSubnet(parsedIp, csSubnetMask);
|
||||
}
|
||||
this.LogWarning("Invalid IP address: {deviceIpAddress}", ipInfo.DeviceIpAddress);
|
||||
return false;
|
||||
}) ? csIpAddress.ToString() : processorIp;
|
||||
ip = csIpAddress.ToString();
|
||||
}
|
||||
|
||||
var appUrl = $"http://{ip}:{_parent.Config.DirectServer.Port}/mc/app?token={touchpanel.Key}";
|
||||
@@ -621,6 +649,9 @@ namespace PepperDash.Essentials.WebSocketServer
|
||||
CrestronConsole.ConsoleCommandResponse($"Token: {token}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the grant code against the room key
|
||||
/// </summary>
|
||||
public (string, string) ValidateGrantCode(string grantCode, string roomKey)
|
||||
{
|
||||
var bridge = _parent.GetRoomBridge(roomKey);
|
||||
@@ -634,6 +665,9 @@ namespace PepperDash.Essentials.WebSocketServer
|
||||
return ValidateGrantCode(grantCode, bridge);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the grant code against the room key
|
||||
/// </summary>
|
||||
public (string, string) ValidateGrantCode(string grantCode, MobileControlBridgeBase bridge)
|
||||
{
|
||||
// TODO: Authenticate grant code passed in
|
||||
@@ -655,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 = "")
|
||||
{
|
||||
var key = Guid.NewGuid().ToString();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
using System;
|
||||
using System;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Crestron.SimplSharp;
|
||||
@@ -41,29 +41,6 @@ namespace PepperDash.Essentials
|
||||
SystemMonitor.ProgramInitialization.ProgramInitializationUnderUserControl = true;
|
||||
|
||||
Debug.SetErrorLogMinimumDebugLevel(CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? LogEventLevel.Warning : LogEventLevel.Verbose);
|
||||
|
||||
// AppDomain.CurrentDomain.AssemblyResolve += CurrentDomainOnAssemblyResolve;
|
||||
}
|
||||
|
||||
private Assembly CurrentDomainOnAssemblyResolve(object sender, ResolveEventArgs args)
|
||||
{
|
||||
var assemblyName = new AssemblyName(args.Name).Name;
|
||||
if (assemblyName == "PepperDash_Core")
|
||||
{
|
||||
return Assembly.LoadFrom("PepperDashCore.dll");
|
||||
}
|
||||
|
||||
if (assemblyName == "PepperDash_Essentials_Core")
|
||||
{
|
||||
return Assembly.LoadFrom("PepperDash.Essentials.Core.dll");
|
||||
}
|
||||
|
||||
if (assemblyName == "Essentials Devices Common")
|
||||
{
|
||||
return Assembly.LoadFrom("PepperDash.Essentials.Devices.Common.dll");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -267,6 +244,8 @@ namespace PepperDash.Essentials
|
||||
// _ = new ProcessorExtensionDeviceFactory();
|
||||
// _ = new MobileControlFactory();
|
||||
|
||||
LoadAssets();
|
||||
|
||||
Debug.LogMessage(LogEventLevel.Information, "Starting Essentials load from configuration");
|
||||
|
||||
var filesReady = SetupFilesystem();
|
||||
@@ -568,5 +547,142 @@ namespace PepperDash.Essentials
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void LoadAssets()
|
||||
{
|
||||
var applicationDirectory = new DirectoryInfo(Global.ApplicationDirectoryPathPrefix);
|
||||
Debug.LogMessage(LogEventLevel.Information, "Searching: {applicationDirectory:l} for embedded assets - {Destination}", applicationDirectory.FullName, Global.FilePathPrefix);
|
||||
|
||||
var zipFiles = applicationDirectory.GetFiles("assets*.zip");
|
||||
|
||||
if (zipFiles.Length > 1)
|
||||
{
|
||||
throw new Exception("Multiple assets zip files found. Cannot continue.");
|
||||
}
|
||||
|
||||
if (zipFiles.Length == 1)
|
||||
{
|
||||
var zipFile = zipFiles[0];
|
||||
var assetsRoot = System.IO.Path.GetFullPath(Global.FilePathPrefix);
|
||||
if (!assetsRoot.EndsWith(Path.DirectorySeparatorChar.ToString()) && !assetsRoot.EndsWith(Path.AltDirectorySeparatorChar.ToString()))
|
||||
{
|
||||
assetsRoot += Path.DirectorySeparatorChar;
|
||||
}
|
||||
Debug.LogMessage(LogEventLevel.Information, "Found assets zip file: {zipFile:l}... Unzipping...", zipFile.FullName);
|
||||
using (var archive = ZipFile.OpenRead(zipFile.FullName))
|
||||
{
|
||||
foreach (var entry in archive.Entries)
|
||||
{
|
||||
var destinationPath = Path.Combine(Global.FilePathPrefix, entry.FullName);
|
||||
var fullDest = System.IO.Path.GetFullPath(destinationPath);
|
||||
if (!fullDest.StartsWith(assetsRoot, StringComparison.OrdinalIgnoreCase))
|
||||
throw new InvalidOperationException($"Entry '{entry.FullName}' is trying to extract outside of the target directory.");
|
||||
|
||||
if (string.IsNullOrEmpty(entry.Name))
|
||||
{
|
||||
Directory.CreateDirectory(destinationPath);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If a directory exists where a file should go, delete it
|
||||
if (Directory.Exists(destinationPath))
|
||||
Directory.Delete(destinationPath, true);
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(destinationPath));
|
||||
entry.ExtractToFile(destinationPath, true);
|
||||
Debug.LogMessage(LogEventLevel.Information, "Extracted: {entry:l} to {Destination}", entry.FullName, destinationPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cleaning up zip files
|
||||
foreach (var file in zipFiles)
|
||||
{
|
||||
File.Delete(file.FullName);
|
||||
}
|
||||
|
||||
var htmlZipFiles = applicationDirectory.GetFiles("htmlassets*.zip");
|
||||
|
||||
if (htmlZipFiles.Length > 1)
|
||||
{
|
||||
throw new Exception("Multiple htmlassets zip files found in application directory. Please ensure only one htmlassets*.zip file is present and retry.");
|
||||
}
|
||||
|
||||
|
||||
if (htmlZipFiles.Length == 1)
|
||||
{
|
||||
var htmlZipFile = htmlZipFiles[0];
|
||||
var programDir = new DirectoryInfo(Global.FilePathPrefix.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar));
|
||||
var userOrNvramDir = programDir.Parent;
|
||||
var rootDir = userOrNvramDir?.Parent;
|
||||
if (rootDir == null)
|
||||
{
|
||||
throw new Exception($"Unable to determine root directory for html extraction. Current path: {Global.FilePathPrefix}");
|
||||
}
|
||||
var htmlDir = Path.Combine(rootDir.FullName, "html");
|
||||
var htmlRoot = System.IO.Path.GetFullPath(htmlDir);
|
||||
if (!htmlRoot.EndsWith(Path.DirectorySeparatorChar.ToString()) &&
|
||||
!htmlRoot.EndsWith(Path.AltDirectorySeparatorChar.ToString()))
|
||||
{
|
||||
htmlRoot += Path.DirectorySeparatorChar;
|
||||
}
|
||||
Debug.LogMessage(LogEventLevel.Information, "Found htmlassets zip file: {zipFile:l}... Unzipping...", htmlZipFile.FullName);
|
||||
using (var archive = ZipFile.OpenRead(htmlZipFile.FullName))
|
||||
{
|
||||
foreach (var entry in archive.Entries)
|
||||
{
|
||||
var destinationPath = Path.Combine(htmlDir, entry.FullName);
|
||||
var fullDest = System.IO.Path.GetFullPath(destinationPath);
|
||||
if (!fullDest.StartsWith(htmlRoot, StringComparison.OrdinalIgnoreCase))
|
||||
throw new InvalidOperationException($"Entry '{entry.FullName}' is trying to extract outside of the target directory.");
|
||||
|
||||
if (string.IsNullOrEmpty(entry.Name))
|
||||
{
|
||||
Directory.CreateDirectory(destinationPath);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only delete the file if it exists and is a file, not a directory
|
||||
if (File.Exists(destinationPath))
|
||||
File.Delete(destinationPath);
|
||||
|
||||
var parentDir = Path.GetDirectoryName(destinationPath);
|
||||
if (!string.IsNullOrEmpty(parentDir))
|
||||
Directory.CreateDirectory(parentDir);
|
||||
|
||||
entry.ExtractToFile(destinationPath, true);
|
||||
Debug.LogMessage(LogEventLevel.Information, "Extracted: {entry:l} to {Destination}", entry.FullName, destinationPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cleaning up html zip files
|
||||
foreach (var file in htmlZipFiles)
|
||||
{
|
||||
File.Delete(file.FullName);
|
||||
}
|
||||
|
||||
var jsonFiles = applicationDirectory.GetFiles("*configurationFile*.json");
|
||||
|
||||
if (jsonFiles.Length > 1)
|
||||
{
|
||||
throw new Exception("Multiple configuration files found. Cannot continue.");
|
||||
}
|
||||
|
||||
if (jsonFiles.Length == 1)
|
||||
{
|
||||
var jsonFile = jsonFiles[0];
|
||||
var finalPath = Path.Combine(Global.FilePathPrefix, jsonFile.Name);
|
||||
Debug.LogMessage(LogEventLevel.Information, "Found configuration file: {jsonFile:l}... Moving to: {Destination}", jsonFile.FullName, finalPath);
|
||||
|
||||
if (File.Exists(finalPath))
|
||||
{
|
||||
Debug.LogMessage(LogEventLevel.Information, "Removing existing configuration file: {Destination}", finalPath);
|
||||
File.Delete(finalPath);
|
||||
}
|
||||
|
||||
jsonFile.MoveTo(finalPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 4.7.2|AnyCPU'">
|
||||
<DebugType>full</DebugType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<DocumentationFile>bin\$(Configuration)\PepperDashEssentials.xml</DocumentationFile>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<DocumentationFile>bin\$(Configuration)\PepperDashEssentials.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Example Configuration\EssentialsHuddleSpaceRoom\configurationFile-HuddleSpace-2-Source.json">
|
||||
@@ -49,6 +49,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Crestron.SimplSharp.SDK.Program" Version="2.21.90" />
|
||||
<PackageReference Include="System.IO.Compression" Version="4.0.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\PepperDash.Core\PepperDash.Core.csproj" />
|
||||
|
||||
Reference in New Issue
Block a user