Compare commits

...

11 Commits

Author SHA1 Message Date
Andrew Welker
cf3ece4237 fix: use cr-lf for line endings 2025-08-06 09:00:45 -05:00
Andrew Welker
0bc4388bfd Merge branch 'default-debug-levels' into current-sources 2025-08-04 13:31:26 -05:00
Andrew Welker
dbc132c0da fix: set default debug levels if not found 2025-08-04 13:31:17 -05:00
Andrew Welker
5bb0ab2626 fix: base config properties for use with streaming devices 2025-08-01 21:17:35 -05:00
Andrew Welker
27bf36c58c fix: modify how current sources dictionary gets updated 2025-08-01 09:22:31 -05:00
Andrew Welker
ce886aea63 chore: update local build version 2025-08-01 09:22:31 -05:00
Andrew Welker
ef920bf54c Merge branch 'main' into current-sources 2025-07-31 13:27:43 -05:00
Andrew Welker
88466818ce Merge pull request #1303 from PepperDash/debug-fixes
fix: use correct overload for logging at levels
2025-07-31 13:03:14 -05:00
Andrew Welker
0871a902e1 fix: use correct overload for logging at levels
Some overloads that had the first argument as an Exception were calling the _logger.Write method with a null where the message template should have been, causing messages logged with that overload to be swallowed and not logged.
2025-07-31 12:50:41 -05:00
Andrew Welker
a031424752 fix: add destination & source keys to routelist 2025-07-30 11:20:54 -05:00
Andrew Welker
fd1ba345aa fix: remove StringEnumConverter 2025-07-29 23:01:13 -05:00
10 changed files with 310 additions and 233 deletions

View File

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

View File

@@ -1,4 +1,9 @@
using Crestron.SimplSharp;
using System;
using System.Collections.Generic;
using System.Net;
using System.Reflection;
using System.Text.RegularExpressions;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronDataStore;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharp.CrestronLogger;
@@ -11,15 +16,10 @@ using Serilog.Events;
using Serilog.Formatting.Compact;
using Serilog.Formatting.Json;
using Serilog.Templates;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text.RegularExpressions;
namespace PepperDash.Core
{
/// <summary>
/// Contains debug commands for use in various situations
/// </summary>
public static class Debug
{
@@ -48,6 +48,9 @@ namespace PepperDash.Core
private static readonly LoggingLevelSwitch _fileLevelSwitch;
/// <summary>
/// Gets the minimum log level for the websocket sink.
/// </summary>
public static LogEventLevel WebsocketMinimumLogLevel
{
get { return _websocketLoggingLevelSwitch.MinimumLevel; }
@@ -55,6 +58,9 @@ namespace PepperDash.Core
private static readonly DebugWebsocketSink _websocketSink;
/// <summary>
/// Gets the websocket sink for debug logging.
/// </summary>
public static DebugWebsocketSink WebsocketSink
{
get { return _websocketSink; }
@@ -91,29 +97,33 @@ namespace PepperDash.Core
private const int SaveTimeoutMs = 30000;
/// <summary>
/// Indicates whether the system is running on an appliance.
/// </summary>
public static bool IsRunningOnAppliance = CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance;
/// <summary>
/// Gets or sets the PepperDashCoreVersion
/// </summary>
public static string PepperDashCoreVersion { get; private set; }
public static string PepperDashCoreVersion { get; private set; }
private static CTimer _saveTimer;
/// <summary>
/// When true, the IncludedExcludedKeys dict will contain keys to include.
/// When false (default), IncludedExcludedKeys will contain keys to exclude.
/// </summary>
private static bool _excludeAllMode;
/// <summary>
/// When true, the IncludedExcludedKeys dict will contain keys to include.
/// When false (default), IncludedExcludedKeys will contain keys to exclude.
/// </summary>
private static bool _excludeAllMode;
//static bool ExcludeNoKeyMessages;
private static readonly Dictionary<string, object> IncludedExcludedKeys;
private static readonly Dictionary<string, object> IncludedExcludedKeys;
private static readonly LoggerConfiguration _defaultLoggerConfiguration;
private static LoggerConfiguration _loggerConfiguration;
/// <summary>
/// Gets the logger configuration for the debug logging.
/// </summary>
public static LoggerConfiguration LoggerConfiguration => _loggerConfiguration;
static Debug()
@@ -128,7 +138,7 @@ namespace PepperDash.Core
var defaultFileLogLevel = GetStoredLogEventLevel(FileLevelStoreKey);
_consoleLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultConsoleLevel);
_consoleLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultConsoleLevel);
_websocketLoggingLevelSwitch = new LoggingLevelSwitch(initialMinimumLevel: defaultWebsocketLevel);
@@ -144,7 +154,7 @@ namespace PepperDash.Core
CrestronConsole.PrintLine($"Saving log files to {logFilePath}");
var errorLogTemplate = CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance
var errorLogTemplate = CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance
? "{@t:fff}ms [{@l:u4}]{#if Key is not null}[{Key}]{#end} {@m}{#if @x is not null}\r\n{@x}{#end}"
: "[{@t:yyyy-MM-dd HH:mm:ss.fff}][{@l:u4}][{App}]{#if Key is not null}[{Key}]{#end} {@m}{#if @x is not null}\r\n{@x}{#end}";
@@ -155,7 +165,7 @@ namespace PepperDash.Core
.WriteTo.Sink(new DebugConsoleSink(new ExpressionTemplate("[{@t:yyyy-MM-dd HH:mm:ss.fff}][{@l:u4}][{App}]{#if Key is not null}[{Key}]{#end} {@m}{#if @x is not null}\r\n{@x}{#end}")), levelSwitch: _consoleLoggingLevelSwitch)
.WriteTo.Sink(_websocketSink, levelSwitch: _websocketLoggingLevelSwitch)
.WriteTo.Sink(new DebugErrorLogSink(new ExpressionTemplate(errorLogTemplate)), levelSwitch: _errorLogLevelSwitch)
.WriteTo.File(new RenderedCompactJsonFormatter(), logFilePath,
.WriteTo.File(new RenderedCompactJsonFormatter(), logFilePath,
rollingInterval: RollingInterval.Day,
restrictedToMinimumLevel: LogEventLevel.Debug,
retainedFileCountLimit: CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? 30 : 60,
@@ -193,27 +203,27 @@ namespace PepperDash.Core
CrestronConsole.PrintLine(msg);
LogMessage(LogEventLevel.Information,msg);
LogMessage(LogEventLevel.Information, msg);
IncludedExcludedKeys = new Dictionary<string, object>();
IncludedExcludedKeys = new Dictionary<string, object>();
if (CrestronEnvironment.RuntimeEnvironment == eRuntimeEnvironment.SimplSharpPro)
{
// Add command to console
CrestronConsole.AddNewConsoleCommand(SetDoNotLoadOnNextBootFromConsole, "donotloadonnextboot",
CrestronConsole.AddNewConsoleCommand(SetDoNotLoadOnNextBootFromConsole, "donotloadonnextboot",
"donotloadonnextboot:P [true/false]: Should the application load on next boot", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(SetDebugFromConsole, "appdebug",
"appdebug:P [0-5]: Sets the application's console debug message level",
ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(ShowDebugLog, "appdebuglog",
"appdebuglog:P [all] Use \"all\" for full log.",
"appdebuglog:P [all] Use \"all\" for full log.",
ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(s => CrestronLogger.Clear(false), "appdebugclear",
"appdebugclear:P Clears the current custom log",
"appdebugclear:P Clears the current custom log",
ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(SetDebugFilterFromConsole, "appdebugfilter",
"appdebugfilter [params]", ConsoleAccessLevelEnum.AccessOperator);
CrestronConsole.AddNewConsoleCommand(SetDebugFilterFromConsole, "appdebugfilter",
"appdebugfilter [params]", ConsoleAccessLevelEnum.AccessOperator);
}
CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler;
@@ -224,7 +234,7 @@ namespace PepperDash.Core
Level = context.Level;
DoNotLoadConfigOnNextBoot = context.DoNotLoadOnNextBoot;
if(DoNotLoadConfigOnNextBoot)
if (DoNotLoadConfigOnNextBoot)
CrestronConsole.PrintLine(string.Format("Program {0} will not load config after next boot. Use console command go:{0} to load the config manually", InitialParametersClass.ApplicationNumber));
_consoleLoggingLevelSwitch.MinimumLevelChanged += (sender, args) =>
@@ -257,22 +267,26 @@ namespace PepperDash.Core
{
try
{
var result = CrestronDataStoreStatic.GetLocalIntValue(levelStoreKey, out int logLevel);
var result = CrestronDataStoreStatic.GetLocalIntValue(levelStoreKey, out int logLevel);
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;
}
if(logLevel < 0 || logLevel > 5)
if (logLevel < 0 || logLevel > 5)
{
CrestronConsole.PrintLine($"Stored Log level not valid for {levelStoreKey}: {logLevel}. Setting level to {LogEventLevel.Information}");
return LogEventLevel.Information;
}
return (LogEventLevel)logLevel;
} catch (Exception ex)
}
catch (Exception ex)
{
CrestronConsole.PrintLine($"Exception retrieving log level for {levelStoreKey}: {ex.Message}");
return LogEventLevel.Information;
@@ -284,7 +298,7 @@ namespace PepperDash.Core
var assembly = Assembly.GetExecutingAssembly();
var ver =
assembly
.GetCustomAttributes(typeof (AssemblyInformationalVersionAttribute), false);
.GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false);
if (ver != null && ver.Length > 0)
{
@@ -335,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;
}
@@ -351,25 +365,25 @@ namespace PepperDash.Core
return;
}
if(int.TryParse(levelString, out var levelInt))
if (int.TryParse(levelString, out var levelInt))
{
if(levelInt < 0 || levelInt > 5)
if (levelInt < 0 || levelInt > 5)
{
CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelString} to valid log level. If using a number, value must be between 0-5");
return;
}
SetDebugLevel((uint) levelInt);
SetDebugLevel((uint)levelInt);
return;
}
if(Enum.TryParse<LogEventLevel>(levelString, out var levelEnum))
if (Enum.TryParse<LogEventLevel>(levelString, out var levelEnum))
{
SetDebugLevel(levelEnum);
return;
}
CrestronConsole.ConsoleCommandResponse($"Error: Unable to parse {levelString} to valid log level");
}
}
catch
{
CrestronConsole.ConsoleCommandResponse("Usage: appdebug:P [0-5]");
@@ -385,7 +399,7 @@ namespace PepperDash.Core
/// </summary>
public static void SetDebugLevel(uint level)
{
if(!_logLevels.TryGetValue(level, out var logLevel))
if (!_logLevels.TryGetValue(level, out var logLevel))
{
logLevel = LogEventLevel.Information;
@@ -407,9 +421,9 @@ namespace PepperDash.Core
CrestronConsole.ConsoleCommandResponse("[Application {0}], Debug level set to {1}\r\n",
InitialParametersClass.ApplicationNumber, _consoleLoggingLevelSwitch.MinimumLevel);
CrestronConsole.ConsoleCommandResponse($"Storing level {level}:{(int) level}");
CrestronConsole.ConsoleCommandResponse($"Storing level {level}:{(int)level}");
var err = CrestronDataStoreStatic.SetLocalIntValue(LevelStoreKey, (int) level);
var err = CrestronDataStoreStatic.SetLocalIntValue(LevelStoreKey, (int)level);
CrestronConsole.ConsoleCommandResponse($"Store result: {err}:{(int)level}");
@@ -422,9 +436,9 @@ namespace PepperDash.Core
/// </summary>
public static void SetWebSocketMinimumDebugLevel(LogEventLevel level)
{
_websocketLoggingLevelSwitch.MinimumLevel = level;
_websocketLoggingLevelSwitch.MinimumLevel = level;
var err = CrestronDataStoreStatic.SetLocalUintValue(WebSocketLevelStoreKey, (uint) level);
var err = CrestronDataStoreStatic.SetLocalUintValue(WebSocketLevelStoreKey, (uint)level);
if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
LogMessage(LogEventLevel.Information, "Error saving websocket debug level setting: {erro}", err);
@@ -491,83 +505,83 @@ namespace PepperDash.Core
/// Callback for console command
/// </summary>
/// <param name="items"></param>
/// <summary>
/// SetDebugFilterFromConsole method
/// </summary>
public static void SetDebugFilterFromConsole(string items)
{
var str = items.Trim();
if (str == "?")
{
CrestronConsole.ConsoleCommandResponse("Usage:\r APPDEBUGFILTER key1 key2 key3....\r " +
"+all: at beginning puts filter into 'default include' mode\r" +
" All keys that follow will be excluded from output.\r" +
"-all: at beginning puts filter into 'default exclude all' mode.\r" +
" All keys that follow will be the only keys that are shown\r" +
"+nokey: Enables messages with no key (default)\r" +
"-nokey: Disables messages with no key.\r" +
"(nokey settings are independent of all other settings)");
return;
}
var keys = Regex.Split(str, @"\s*");
foreach (var keyToken in keys)
{
var lkey = keyToken.ToLower();
if (lkey == "+all")
{
IncludedExcludedKeys.Clear();
_excludeAllMode = false;
}
else if (lkey == "-all")
{
IncludedExcludedKeys.Clear();
_excludeAllMode = true;
}
//else if (lkey == "+nokey")
//{
// ExcludeNoKeyMessages = false;
//}
//else if (lkey == "-nokey")
//{
// ExcludeNoKeyMessages = true;
//}
else
{
string key;
if (lkey.StartsWith("-"))
{
key = lkey.Substring(1);
// if in exclude all mode, we need to remove this from the inclusions
if (_excludeAllMode)
{
if (IncludedExcludedKeys.ContainsKey(key))
IncludedExcludedKeys.Remove(key);
}
// otherwise include all mode, add to the exclusions
else
{
IncludedExcludedKeys[key] = new object();
}
}
else if (lkey.StartsWith("+"))
{
key = lkey.Substring(1);
// if in exclude all mode, we need to add this as inclusion
if (_excludeAllMode)
{
/// <summary>
/// SetDebugFilterFromConsole method
/// </summary>
public static void SetDebugFilterFromConsole(string items)
{
var str = items.Trim();
if (str == "?")
{
CrestronConsole.ConsoleCommandResponse("Usage:\r APPDEBUGFILTER key1 key2 key3....\r " +
"+all: at beginning puts filter into 'default include' mode\r" +
" All keys that follow will be excluded from output.\r" +
"-all: at beginning puts filter into 'default exclude all' mode.\r" +
" All keys that follow will be the only keys that are shown\r" +
"+nokey: Enables messages with no key (default)\r" +
"-nokey: Disables messages with no key.\r" +
"(nokey settings are independent of all other settings)");
return;
}
var keys = Regex.Split(str, @"\s*");
foreach (var keyToken in keys)
{
var lkey = keyToken.ToLower();
if (lkey == "+all")
{
IncludedExcludedKeys.Clear();
_excludeAllMode = false;
}
else if (lkey == "-all")
{
IncludedExcludedKeys.Clear();
_excludeAllMode = true;
}
//else if (lkey == "+nokey")
//{
// ExcludeNoKeyMessages = false;
//}
//else if (lkey == "-nokey")
//{
// ExcludeNoKeyMessages = true;
//}
else
{
string key;
if (lkey.StartsWith("-"))
{
key = lkey.Substring(1);
// if in exclude all mode, we need to remove this from the inclusions
if (_excludeAllMode)
{
if (IncludedExcludedKeys.ContainsKey(key))
IncludedExcludedKeys.Remove(key);
}
// otherwise include all mode, add to the exclusions
else
{
IncludedExcludedKeys[key] = new object();
}
}
else if (lkey.StartsWith("+"))
{
key = lkey.Substring(1);
// if in exclude all mode, we need to add this as inclusion
if (_excludeAllMode)
{
IncludedExcludedKeys[key] = new object();
}
// otherwise include all mode, remove this from exclusions
else
{
if (IncludedExcludedKeys.ContainsKey(key))
IncludedExcludedKeys.Remove(key);
}
}
}
}
}
IncludedExcludedKeys[key] = new object();
}
// otherwise include all mode, remove this from exclusions
else
{
if (IncludedExcludedKeys.ContainsKey(key))
IncludedExcludedKeys.Remove(key);
}
}
}
}
}
@@ -595,7 +609,7 @@ namespace PepperDash.Core
public static object GetDeviceDebugSettingsForKey(string deviceKey)
{
return _contexts.GetDebugSettingsForKey(deviceKey);
}
}
/// <summary>
/// Sets the flag to prevent application starting on next boot
@@ -654,9 +668,15 @@ namespace PepperDash.Core
}
}
/// <summary>
/// Logs a message at the specified log level.
/// </summary>
/// <param name="level">Level to log at</param>
/// <param name="message">Message template</param>
/// <param name="args">Args to put into message template</param>
public static void LogMessage(LogEventLevel level, string message, params object[] args)
{
_logger.Write(level, message, args);
_logger.Write(level, message, args);
}
/// <summary>
@@ -692,7 +712,7 @@ namespace PepperDash.Core
/// </summary>
public static void LogVerbose(IKeyed keyed, string message, params object[] args)
{
using(LogContext.PushProperty("Key", keyed?.Key))
using (LogContext.PushProperty("Key", keyed?.Key))
{
_logger.Write(LogEventLevel.Verbose, message, args);
}
@@ -703,7 +723,7 @@ namespace PepperDash.Core
/// </summary>
public static void LogVerbose(Exception ex, IKeyed keyed, string message, params object[] args)
{
using(LogContext.PushProperty("Key", keyed?.Key))
using (LogContext.PushProperty("Key", keyed?.Key))
{
_logger.Write(LogEventLevel.Verbose, ex, message, args);
}
@@ -722,7 +742,7 @@ namespace PepperDash.Core
/// </summary>
public static void LogVerbose(Exception ex, string message, params object[] args)
{
_logger.Write(LogEventLevel.Verbose, ex, null, message, args);
_logger.Write(LogEventLevel.Verbose, ex, message, args);
}
/// <summary>
@@ -798,7 +818,7 @@ namespace PepperDash.Core
/// </summary>
public static void LogInformation(Exception ex, string message, params object[] args)
{
_logger.Write(LogEventLevel.Information, ex, null, message, args);
_logger.Write(LogEventLevel.Information, ex, message, args);
}
/// <summary>
@@ -836,7 +856,7 @@ namespace PepperDash.Core
/// </summary>
public static void LogWarning(Exception ex, string message, params object[] args)
{
_logger.Write(LogEventLevel.Warning, ex, null, message, args);
_logger.Write(LogEventLevel.Warning, ex, message, args);
}
/// <summary>
@@ -874,7 +894,7 @@ namespace PepperDash.Core
/// </summary>
public static void LogError(Exception ex, string message, params object[] args)
{
_logger.Write(LogEventLevel.Error, ex, null, message, args);
_logger.Write(LogEventLevel.Error, ex, message, args);
}
/// <summary>
@@ -912,7 +932,7 @@ namespace PepperDash.Core
/// </summary>
public static void LogFatal(Exception ex, string message, params object[] args)
{
_logger.Write(LogEventLevel.Fatal, ex, null, message, args);
_logger.Write(LogEventLevel.Fatal, ex, message, args);
}
#endregion
@@ -923,7 +943,7 @@ namespace PepperDash.Core
if (!_logLevels.ContainsKey(level)) return;
var logLevel = _logLevels[level];
LogMessage(logLevel, format, items);
}
@@ -978,7 +998,7 @@ namespace PepperDash.Core
[Obsolete("Use LogMessage methods, Will be removed in 2.2.0 and later versions")]
public static void Console(uint level, IKeyed dev, ErrorLogLevel errorLogLevel,
string format, params object[] items)
{
{
LogMessage(level, dev, format, items);
}
@@ -1122,7 +1142,7 @@ namespace PepperDash.Core
return string.Format(@"\user\debugSettings\program{0}", InitialParametersClass.ApplicationNumber);
}
return string.Format("{0}{1}user{1}debugSettings{1}{2}.json",Directory.GetApplicationRootDirectory(), Path.DirectorySeparatorChar, InitialParametersClass.RoomId);
return string.Format("{0}{1}user{1}debugSettings{1}{2}.json", Directory.GetApplicationRootDirectory(), Path.DirectorySeparatorChar, InitialParametersClass.RoomId);
}
/// <summary>
@@ -1133,15 +1153,15 @@ namespace PepperDash.Core
/// <summary>
/// Error
/// </summary>
Error,
Error,
/// <summary>
/// Warning
/// </summary>
Warning,
Warning,
/// <summary>
/// Notice
/// </summary>
Notice,
Notice,
/// <summary>
/// None
/// </summary>

View File

@@ -0,0 +1,23 @@
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; }
}
}

View File

@@ -475,9 +475,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;
}

View File

@@ -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>

View File

@@ -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);
}
}

View File

@@ -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}";
}
}
}

View File

@@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
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;
@@ -384,7 +386,28 @@ namespace PepperDash.Essentials.Devices.Common.Displays
/// <inheritdoc />
public virtual void SetCurrentSource(eRoutingSignalType signalType, string sourceListKey, SourceListItem sourceListItem)
{
// Update the current source for the specified signal type
foreach (eRoutingSignalType type in Enum.GetValues(typeof(eRoutingSignalType)))
{
var flagValue = Convert.ToInt32(type);
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;
@@ -403,9 +426,6 @@ namespace PepperDash.Essentials.Devices.Common.Displays
{
CurrentSourceKeys.Add(signalType, sourceListKey);
}
// Raise the CurrentSourcesChanged event
CurrentSourcesChanged?.Invoke(this, EventArgs.Empty);
}
}

View File

@@ -14,11 +14,21 @@ namespace PepperDash.Essentials.AppServer.Messengers
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();
@@ -55,7 +65,6 @@ namespace PepperDash.Essentials.AppServer.Messengers
/// Gets or sets the CurrentSourceKey
/// </summary>
[JsonProperty("currentSourceKey", NullValueHandling = NullValueHandling.Ignore)]
[JsonConverter(typeof(StringEnumConverter))]
public Dictionary<eRoutingSignalType, string> CurrentSourceKeys { get; set; }

View File

@@ -728,6 +728,8 @@ namespace PepperDash.Essentials
var messenger = new CurrentSourcesMessenger($"{device.Key}-currentSources-{Key}", $"/device/{device.Key}", currentSources);
AddDefaultDeviceMessenger(messenger);
messengerAdded = true;
}
if (device is ISwitchedOutput switchedDevice)
@@ -1634,15 +1636,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,
@@ -1655,10 +1656,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"
);
}
@@ -1669,21 +1668,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
);
@@ -1701,15 +1696,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,
@@ -1724,9 +1717,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"
);
}
}