diff --git a/CLZ Builds/PepperDash_Core.clz b/CLZ Builds/PepperDash_Core.clz
index f3a2ec2..0ef4596 100644
Binary files a/CLZ Builds/PepperDash_Core.clz and b/CLZ Builds/PepperDash_Core.clz differ
diff --git a/CLZ Builds/PepperDash_Core.dll b/CLZ Builds/PepperDash_Core.dll
index 43d7667..9ec42f6 100644
Binary files a/CLZ Builds/PepperDash_Core.dll and b/CLZ Builds/PepperDash_Core.dll differ
diff --git a/Pepperdash Core/Pepperdash Core/Comm/GenericSecureTcpIpServer.cs b/Pepperdash Core/Pepperdash Core/Comm/GenericSecureTcpIpServer.cs
index 58f46c8..3047a60 100644
--- a/Pepperdash Core/Pepperdash Core/Comm/GenericSecureTcpIpServer.cs
+++ b/Pepperdash Core/Pepperdash Core/Comm/GenericSecureTcpIpServer.cs
@@ -669,6 +669,8 @@ namespace PepperDash.Core
}
if (ClientReadyAfterKeyExchange.Contains(clientIndex))
ClientReadyAfterKeyExchange.Remove(clientIndex);
+ if (WaitingForSharedKey.Contains(clientIndex))
+ WaitingForSharedKey.Remove(clientIndex);
}
}
catch (Exception ex)
@@ -781,31 +783,33 @@ namespace PepperDash.Core
Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Client at index {0} Shared key did not match the server, disconnecting client. Key: {1}", clientIndex, received);
mySecureTCPServer.SendData(clientIndex, b, b.Length);
mySecureTCPServer.Disconnect(clientIndex);
- WaitingForSharedKey.Remove(clientIndex);
+
return;
}
- if (mySecureTCPServer.NumberOfClientsConnected > 0)
- mySecureTCPServer.ReceiveDataAsync(clientIndex, SecureReceivedDataAsyncCallback);
+
WaitingForSharedKey.Remove(clientIndex);
byte[] success = Encoding.GetEncoding(28591).GetBytes("Shared Key Match");
mySecureTCPServer.SendDataAsync(clientIndex, success, success.Length, null);
OnServerClientReadyForCommunications(clientIndex);
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Client with index {0} provided the shared key and successfully connected to the server", clientIndex);
- return;
+
}
- //var address = mySecureTCPServer.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex);
- //Debug.Console(1, this, "Secure Server Listening on Port: {0}, client IP: {1}, Client Index: {4}, NumberOfBytesReceived: {2}, Received: {3}\r\n",
- // mySecureTCPServer.PortNumber.ToString(), address , numberOfBytesReceived.ToString(), received, clientIndex.ToString());
- if (!string.IsNullOrEmpty(checkHeartbeat(clientIndex, received)))
- onTextReceived(received, clientIndex);
+ else if (!string.IsNullOrEmpty(checkHeartbeat(clientIndex, received)))
+ onTextReceived(received, clientIndex);
}
catch (Exception ex)
{
Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Error Receiving data: {0}. Error: {1}", received, ex);
}
+ if (mySecureTCPServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED)
+ mySecureTCPServer.ReceiveDataAsync(clientIndex, SecureReceivedDataAsyncCallback);
}
- if (mySecureTCPServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED)
- mySecureTCPServer.ReceiveDataAsync(clientIndex, SecureReceivedDataAsyncCallback);
+ else
+ {
+ // If numberOfBytesReceived <= 0
+ mySecureTCPServer.Disconnect(clientIndex);
+ }
+
}
#endregion
diff --git a/Pepperdash Core/Pepperdash Core/Comm/GenericSshClient.cs b/Pepperdash Core/Pepperdash Core/Comm/GenericSshClient.cs
index 3d1101a..6af5d7b 100644
--- a/Pepperdash Core/Pepperdash Core/Comm/GenericSshClient.cs
+++ b/Pepperdash Core/Pepperdash Core/Comm/GenericSshClient.cs
@@ -174,8 +174,8 @@ namespace PepperDash.Core
if (Client != null)
{
Debug.Console(1, this, "Program stopping. Closing connection");
- Client.Disconnect();
- Client.Dispose();
+ Disconnect();
+ //Client.Dispose();
}
}
}
diff --git a/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpServer.cs b/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpServer.cs
index 2ef2845..7dfb682 100644
--- a/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpServer.cs
+++ b/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpServer.cs
@@ -387,13 +387,16 @@ namespace PepperDash.Core
myTcpServer.SocketSendOrReceiveTimeOutInMs = (this.HeartbeatRequiredIntervalMs * 5);
// myTcpServer.HandshakeTimeout = 30;
- myTcpServer.SocketStatusChange += new TCPServerSocketStatusChangeEventHandler(TcpServer_SocketStatusChange);
}
else
{
KillServer();
myTcpServer.PortNumber = Port;
}
+
+ myTcpServer.SocketStatusChange -= TcpServer_SocketStatusChange;
+ myTcpServer.SocketStatusChange += TcpServer_SocketStatusChange;
+
ServerStopped = false;
myTcpServer.WaitForConnectionAsync(IPAddress.Any, TcpConnectCallback);
OnServerStateChange(myTcpServer.State);
@@ -670,6 +673,8 @@ namespace PepperDash.Core
}
if (ClientReadyAfterKeyExchange.Contains(clientIndex))
ClientReadyAfterKeyExchange.Remove(clientIndex);
+ if (WaitingForSharedKey.Contains(clientIndex))
+ WaitingForSharedKey.Remove(clientIndex);
}
}
catch (Exception ex)
@@ -763,50 +768,51 @@ namespace PepperDash.Core
///
///
///
- void TcpServerReceivedDataAsyncCallback(TCPServer mySecureTCPServer, uint clientIndex, int numberOfBytesReceived)
+ void TcpServerReceivedDataAsyncCallback(TCPServer myTCPServer, uint clientIndex, int numberOfBytesReceived)
{
- if (numberOfBytesReceived > 0)
- {
- string received = "Nothing";
- try
- {
- byte[] bytes = mySecureTCPServer.GetIncomingDataBufferForSpecificClient(clientIndex);
- received = System.Text.Encoding.GetEncoding(28591).GetString(bytes, 0, numberOfBytesReceived);
- if (WaitingForSharedKey.Contains(clientIndex))
- {
- received = received.Replace("\r", "");
- received = received.Replace("\n", "");
- if (received != SharedKey)
- {
- byte[] b = Encoding.GetEncoding(28591).GetBytes("Shared key did not match server. Disconnecting");
- Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Client at index {0} Shared key did not match the server, disconnecting client. Key: {1}", clientIndex, received);
- mySecureTCPServer.SendData(clientIndex, b, b.Length);
- mySecureTCPServer.Disconnect(clientIndex);
- WaitingForSharedKey.Remove(clientIndex);
- return;
- }
- if (mySecureTCPServer.NumberOfClientsConnected > 0)
- mySecureTCPServer.ReceiveDataAsync(clientIndex, TcpServerReceivedDataAsyncCallback);
- WaitingForSharedKey.Remove(clientIndex);
- byte[] success = Encoding.GetEncoding(28591).GetBytes("Shared Key Match");
- mySecureTCPServer.SendDataAsync(clientIndex, success, success.Length, null);
- OnServerClientReadyForCommunications(clientIndex);
- Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Client with index {0} provided the shared key and successfully connected to the server", clientIndex);
- return;
- }
- //var address = mySecureTCPServer.GetAddressServerAcceptedConnectionFromForSpecificClient(clientIndex);
- //Debug.Console(1, this, "Secure Server Listening on Port: {0}, client IP: {1}, Client Index: {4}, NumberOfBytesReceived: {2}, Received: {3}\r\n",
- // mySecureTCPServer.PortNumber.ToString(), address , numberOfBytesReceived.ToString(), received, clientIndex.ToString());
- if (!string.IsNullOrEmpty(checkHeartbeat(clientIndex, received)))
- onTextReceived(received, clientIndex);
- }
- catch (Exception ex)
- {
- Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Error Receiving data: {0}. Error: {1}", received, ex);
- }
- }
- if (mySecureTCPServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED)
- mySecureTCPServer.ReceiveDataAsync(clientIndex, TcpServerReceivedDataAsyncCallback);
+ if (numberOfBytesReceived > 0)
+ {
+ string received = "Nothing";
+ try
+ {
+ byte[] bytes = myTCPServer.GetIncomingDataBufferForSpecificClient(clientIndex);
+ received = System.Text.Encoding.GetEncoding(28591).GetString(bytes, 0, numberOfBytesReceived);
+ if (WaitingForSharedKey.Contains(clientIndex))
+ {
+ received = received.Replace("\r", "");
+ received = received.Replace("\n", "");
+ if (received != SharedKey)
+ {
+ byte[] b = Encoding.GetEncoding(28591).GetBytes("Shared key did not match server. Disconnecting");
+ Debug.Console(1, this, Debug.ErrorLogLevel.Warning, "Client at index {0} Shared key did not match the server, disconnecting client. Key: {1}", clientIndex, received);
+ myTCPServer.SendData(clientIndex, b, b.Length);
+ myTCPServer.Disconnect(clientIndex);
+ return;
+ }
+
+ WaitingForSharedKey.Remove(clientIndex);
+ byte[] success = Encoding.GetEncoding(28591).GetBytes("Shared Key Match");
+ myTCPServer.SendDataAsync(clientIndex, success, success.Length, null);
+ OnServerClientReadyForCommunications(clientIndex);
+ Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Client with index {0} provided the shared key and successfully connected to the server", clientIndex);
+ }
+
+ else if (!string.IsNullOrEmpty(checkHeartbeat(clientIndex, received)))
+ onTextReceived(received, clientIndex);
+ }
+ catch (Exception ex)
+ {
+ Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Error Receiving data: {0}. Error: {1}", received, ex);
+ }
+ if (myTCPServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED)
+ myTCPServer.ReceiveDataAsync(clientIndex, TcpServerReceivedDataAsyncCallback);
+ }
+ else
+ {
+ // If numberOfBytesReceived <= 0
+ myTCPServer.Disconnect();
+ }
+
}
#endregion
diff --git a/Pepperdash Core/Pepperdash Core/Logging/Debug.cs b/Pepperdash Core/Pepperdash Core/Logging/Debug.cs
index cf92ff0..21f0121 100644
--- a/Pepperdash Core/Pepperdash Core/Logging/Debug.cs
+++ b/Pepperdash Core/Pepperdash Core/Logging/Debug.cs
@@ -1,419 +1,421 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Text.RegularExpressions;
-using Crestron.SimplSharp;
-using Crestron.SimplSharp.Reflection;
-using Crestron.SimplSharp.CrestronLogger;
-using Crestron.SimplSharp.CrestronIO;
-using Newtonsoft.Json;
-using PepperDash.Core.DebugThings;
-
-
-namespace PepperDash.Core
-{
- public static class Debug
- {
- ///
- /// Describes the folder location where a given program stores it's debug level memory. By default, the
- /// file written will be named appNdebug where N is 1-10.
- ///
- public static string FilePathPrefix = @"\nvram\debug\";
-
- ///
- /// The name of the file containing the current debug settings.
- ///
- public static string FileName = string.Format(@"app{0}Debug.json", InitialParametersClass.ApplicationNumber);
-
- public static int Level { get; private set; }
-
- static DebugContextCollection Contexts;
-
- static int SaveTimeoutMs = 30000;
-
- static CTimer SaveTimer;
-
- ///
- /// When true, the IncludedExcludedKeys dict will contain keys to include.
- /// When false (default), IncludedExcludedKeys will contain keys to exclude.
- ///
- static bool ExcludeAllMode;
-
- //static bool ExcludeNoKeyMessages;
-
- static Dictionary IncludedExcludedKeys;
-
- static Debug()
- {
- // Get the assembly version and print it to console and the log
- var version = Assembly.GetExecutingAssembly().GetName().Version;
-
- var versionString = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build);
-
- var msg = string.Format("[App {0}] Using PepperDash_Core v{1}", InitialParametersClass.ApplicationNumber, versionString);
-
- CrestronConsole.PrintLine(msg);
-
- LogError(ErrorLogLevel.Notice, msg);
-
- IncludedExcludedKeys = new Dictionary();
-
- //CrestronDataStoreStatic.InitCrestronDataStore();
- if (CrestronEnvironment.RuntimeEnvironment == eRuntimeEnvironment.SimplSharpPro)
- {
- // Add command to console
- CrestronConsole.AddNewConsoleCommand(SetDebugFromConsole, "appdebug",
- "appdebug:P [0-2]: Sets the application's console debug message level",
- ConsoleAccessLevelEnum.AccessOperator);
- CrestronConsole.AddNewConsoleCommand(ShowDebugLog, "appdebuglog",
- "appdebuglog:P [all] Use \"all\" for full log.",
- ConsoleAccessLevelEnum.AccessOperator);
- CrestronConsole.AddNewConsoleCommand(s => CrestronLogger.Clear(false), "appdebugclear",
- "appdebugclear:P Clears the current custom log",
- ConsoleAccessLevelEnum.AccessOperator);
- CrestronConsole.AddNewConsoleCommand(SetDebugFilterFromConsole, "appdebugfilter",
- "appdebugfilter [params]", ConsoleAccessLevelEnum.AccessOperator);
- }
-
- CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler;
-
- LoadMemory();
- Level = Contexts.GetOrCreateItem("DEFAULT").Level;
-
- try
- {
- if (InitialParametersClass.NumberOfRemovableDrives > 0)
- {
- CrestronConsole.PrintLine("{0} RM Drive(s) Present.", InitialParametersClass.NumberOfRemovableDrives);
- CrestronLogger.Initialize(2, LoggerModeEnum.DEFAULT); // Use RM instead of DEFAULT as not to double-up console messages.
- }
- else
- CrestronConsole.PrintLine("No RM Drive(s) Present.");
- }
- catch (Exception e)
- {
-
- CrestronConsole.PrintLine("Initializing of CrestronLogger failed: {0}", e);
- }
- }
-
- ///
- /// Used to save memory when shutting down
- ///
- ///
- static void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType)
- {
- if (programEventType == eProgramStatusEventType.Stopping)
- {
- if (SaveTimer != null)
- {
- SaveTimer.Stop();
- SaveTimer = null;
- }
- Console(0, "Saving debug settings");
- SaveMemory();
- }
- }
-
- ///
- /// Callback for console command
- ///
- ///
- public static void SetDebugFromConsole(string levelString)
- {
- try
- {
- if (string.IsNullOrEmpty(levelString.Trim()))
- {
- CrestronConsole.PrintLine("AppDebug level = {0}", Level);
- return;
- }
-
- SetDebugLevel(Convert.ToInt32(levelString));
- }
- catch
- {
- CrestronConsole.PrintLine("Usage: appdebug:P [0-2]");
- }
- }
-
- 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 excluse 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 = null; ;
- 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);
- }
- }
- }
- }
- }
-
-
- ///
- /// Sets the debug level
- ///
- /// Valid values 0 (no debug), 1 (critical), 2 (all messages)
- public static void SetDebugLevel(int level)
- {
- if (level <= 2)
- {
- Level = level;
- Contexts.GetOrCreateItem("DEFAULT").Level = level;
- SaveMemoryOnTimeout();
-
- CrestronConsole.PrintLine("[Application {0}], Debug level set to {1}",
- InitialParametersClass.ApplicationNumber, Level);
-
- //var err = CrestronDataStoreStatic.SetLocalUintValue("DebugLevel", level);
- //if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
- // CrestronConsole.PrintLine("Error saving console debug level setting: {0}", err);
- }
- }
-
- ///
- ///
- ///
- public static void ShowDebugLog(string s)
- {
- var loglist = CrestronLogger.PrintTheLog(s.ToLower() == "all");
- foreach (var l in loglist)
- CrestronConsole.ConsoleCommandResponse(l + CrestronEnvironment.NewLine);
- }
-
- ///
- /// Prints message to console if current debug level is equal to or higher than the level of this message.
- /// Uses CrestronConsole.PrintLine.
- ///
- ///
- /// Console format string
- /// Object parameters
- public static void Console(uint level, string format, params object[] items)
- {
- if (Level >= level)
- CrestronConsole.PrintLine("[{0}]App {1}:{2}", DateTime.Now.ToString("HH:mm:ss.fff"), InitialParametersClass.ApplicationNumber,
- string.Format(format, items));
- }
-
- ///
- /// Logs to Console when at-level, and all messages to error log, including device key
- ///
- public static void Console(uint level, IKeyed dev, string format, params object[] items)
- {
- if (Level >= level)
- Console(level, "[{0}] {1}", dev.Key, string.Format(format, items));
- }
-
- public static void Console(uint level, IKeyed dev, ErrorLogLevel errorLogLevel,
- string format, params object[] items)
- {
- var str = string.Format("[{0}] {1}", dev.Key, string.Format(format, items));
- LogError(errorLogLevel, str);
- if (Level >= level)
- {
- Console(level, str);
- }
- }
-
- ///
- /// Logs to Console when at-level, and all messages to error log
- ///
- public static void Console(uint level, ErrorLogLevel errorLogLevel,
- string format, params object[] items)
- {
- var str = string.Format(format, items);
- LogError(errorLogLevel, str);
- if (Level >= level)
- {
- Console(level, str);
- }
- }
-
- ///
- /// Logs to both console and the custom user log (not the built-in error log). If appdebug level is set at
- /// or above the level provided, then the output will be written to both console and the log. Otherwise
- /// it will only be written to the log.
- ///
- ///
- ///
- ///
- public static void ConsoleWithLog(uint level, string format, params object[] items)
- {
- var str = string.Format(format, items);
- if (Level >= level)
- CrestronConsole.PrintLine("App {0}:{1}", InitialParametersClass.ApplicationNumber, str);
- CrestronLogger.WriteToLog(str, level);
- }
-
- ///
- /// Logs to both console and the custom user log (not the built-in error log). If appdebug level is set at
- /// or above the level provided, then the output will be written to both console and the log. Otherwise
- /// it will only be written to the log.
- ///
- ///
- ///
- /// String.format string
- /// Parameters for substitution in the format string.
- public static void ConsoleWithLog(uint level, IKeyed dev, string format, params object[] items)
- {
- var str = string.Format(format, items);
- if (Level >= level)
- ConsoleWithLog(level, "[{0}] {1}", dev.Key, str);
- }
-
- ///
- /// Prints to log and error log
- ///
- ///
- ///
- public static void LogError(ErrorLogLevel errorLogLevel, string str)
- {
- string msg = string.Format("App {0}:{1}", InitialParametersClass.ApplicationNumber, str);
- switch (errorLogLevel)
- {
- case ErrorLogLevel.Error:
- ErrorLog.Error(msg);
- break;
- case ErrorLogLevel.Warning:
- ErrorLog.Warn(msg);
- break;
- case ErrorLogLevel.Notice:
- ErrorLog.Notice(msg);
- break;
- }
- }
-
- ///
- /// Writes the memory object after timeout
- ///
- static void SaveMemoryOnTimeout()
- {
- if (SaveTimer == null)
- SaveTimer = new CTimer(o =>
- {
- SaveTimer = null;
- SaveMemory();
- }, SaveTimeoutMs);
- else
- SaveTimer.Reset(SaveTimeoutMs);
- }
-
- ///
- /// Writes the memory - use SaveMemoryOnTimeout
- ///
- static void SaveMemory()
- {
- //var dir = @"\NVRAM\debug";
- //if (!Directory.Exists(dir))
- // Directory.Create(dir);
-
- using (StreamWriter sw = new StreamWriter(GetMemoryFileName()))
- {
- var json = JsonConvert.SerializeObject(Contexts);
- sw.Write(json);
- sw.Flush();
- }
- }
-
- ///
- ///
- ///
- static void LoadMemory()
- {
- var file = GetMemoryFileName();
- if (File.Exists(file))
- {
- using (StreamReader sr = new StreamReader(file))
- {
- var json = sr.ReadToEnd();
- Contexts = JsonConvert.DeserializeObject(json);
-
- if (Contexts != null)
- {
- Debug.Console(1, "Debug memory restored from file");
- return;
- }
- }
- }
-
- Contexts = new DebugContextCollection();
- }
-
- ///
- /// Helper to get the file path for this app's debug memory
- ///
- static string GetMemoryFileName()
- {
- return string.Format(@"\NVRAM\debugSettings\program{0}", InitialParametersClass.ApplicationNumber);
- }
-
- public enum ErrorLogLevel
- {
- Error, Warning, Notice, None
- }
- }
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using Crestron.SimplSharp;
+using Crestron.SimplSharp.Reflection;
+using Crestron.SimplSharp.CrestronLogger;
+using Crestron.SimplSharp.CrestronIO;
+using Newtonsoft.Json;
+using PepperDash.Core.DebugThings;
+
+
+namespace PepperDash.Core
+{
+ public static class Debug
+ {
+ ///
+ /// Describes the folder location where a given program stores it's debug level memory. By default, the
+ /// file written will be named appNdebug where N is 1-10.
+ ///
+ public static string FilePathPrefix = @"\nvram\debug\";
+
+ ///
+ /// The name of the file containing the current debug settings.
+ ///
+ public static string FileName = string.Format(@"app{0}Debug.json", InitialParametersClass.ApplicationNumber);
+
+ public static int Level { get; private set; }
+
+ static DebugContextCollection Contexts;
+
+ static int SaveTimeoutMs = 30000;
+
+ public static string PepperDashCoreVersion { get; private set; }
+
+ static CTimer SaveTimer;
+
+ ///
+ /// When true, the IncludedExcludedKeys dict will contain keys to include.
+ /// When false (default), IncludedExcludedKeys will contain keys to exclude.
+ ///
+ static bool ExcludeAllMode;
+
+ //static bool ExcludeNoKeyMessages;
+
+ static Dictionary IncludedExcludedKeys;
+
+ static Debug()
+ {
+ // Get the assembly version and print it to console and the log
+ var version = Assembly.GetExecutingAssembly().GetName().Version;
+
+ PepperDashCoreVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build);
+
+ var msg = string.Format("[App {0}] Using PepperDash_Core v{1}", InitialParametersClass.ApplicationNumber, PepperDashCoreVersion);
+
+ CrestronConsole.PrintLine(msg);
+
+ LogError(ErrorLogLevel.Notice, msg);
+
+ IncludedExcludedKeys = new Dictionary();
+
+ //CrestronDataStoreStatic.InitCrestronDataStore();
+ if (CrestronEnvironment.RuntimeEnvironment == eRuntimeEnvironment.SimplSharpPro)
+ {
+ // Add command to console
+ CrestronConsole.AddNewConsoleCommand(SetDebugFromConsole, "appdebug",
+ "appdebug:P [0-2]: Sets the application's console debug message level",
+ ConsoleAccessLevelEnum.AccessOperator);
+ CrestronConsole.AddNewConsoleCommand(ShowDebugLog, "appdebuglog",
+ "appdebuglog:P [all] Use \"all\" for full log.",
+ ConsoleAccessLevelEnum.AccessOperator);
+ CrestronConsole.AddNewConsoleCommand(s => CrestronLogger.Clear(false), "appdebugclear",
+ "appdebugclear:P Clears the current custom log",
+ ConsoleAccessLevelEnum.AccessOperator);
+ CrestronConsole.AddNewConsoleCommand(SetDebugFilterFromConsole, "appdebugfilter",
+ "appdebugfilter [params]", ConsoleAccessLevelEnum.AccessOperator);
+ }
+
+ CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler;
+
+ LoadMemory();
+ Level = Contexts.GetOrCreateItem("DEFAULT").Level;
+
+ try
+ {
+ if (InitialParametersClass.NumberOfRemovableDrives > 0)
+ {
+ CrestronConsole.PrintLine("{0} RM Drive(s) Present.", InitialParametersClass.NumberOfRemovableDrives);
+ CrestronLogger.Initialize(2, LoggerModeEnum.DEFAULT); // Use RM instead of DEFAULT as not to double-up console messages.
+ }
+ else
+ CrestronConsole.PrintLine("No RM Drive(s) Present.");
+ }
+ catch (Exception e)
+ {
+
+ CrestronConsole.PrintLine("Initializing of CrestronLogger failed: {0}", e);
+ }
+ }
+
+ ///
+ /// Used to save memory when shutting down
+ ///
+ ///
+ static void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType)
+ {
+ if (programEventType == eProgramStatusEventType.Stopping)
+ {
+ if (SaveTimer != null)
+ {
+ SaveTimer.Stop();
+ SaveTimer = null;
+ }
+ Console(0, "Saving debug settings");
+ SaveMemory();
+ }
+ }
+
+ ///
+ /// Callback for console command
+ ///
+ ///
+ public static void SetDebugFromConsole(string levelString)
+ {
+ try
+ {
+ if (string.IsNullOrEmpty(levelString.Trim()))
+ {
+ CrestronConsole.PrintLine("AppDebug level = {0}", Level);
+ return;
+ }
+
+ SetDebugLevel(Convert.ToInt32(levelString));
+ }
+ catch
+ {
+ CrestronConsole.PrintLine("Usage: appdebug:P [0-2]");
+ }
+ }
+
+ 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 excluse 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 = null; ;
+ 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);
+ }
+ }
+ }
+ }
+ }
+
+
+ ///
+ /// Sets the debug level
+ ///
+ /// Valid values 0 (no debug), 1 (critical), 2 (all messages)
+ public static void SetDebugLevel(int level)
+ {
+ if (level <= 2)
+ {
+ Level = level;
+ Contexts.GetOrCreateItem("DEFAULT").Level = level;
+ SaveMemoryOnTimeout();
+
+ CrestronConsole.PrintLine("[Application {0}], Debug level set to {1}",
+ InitialParametersClass.ApplicationNumber, Level);
+
+ //var err = CrestronDataStoreStatic.SetLocalUintValue("DebugLevel", level);
+ //if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
+ // CrestronConsole.PrintLine("Error saving console debug level setting: {0}", err);
+ }
+ }
+
+ ///
+ ///
+ ///
+ public static void ShowDebugLog(string s)
+ {
+ var loglist = CrestronLogger.PrintTheLog(s.ToLower() == "all");
+ foreach (var l in loglist)
+ CrestronConsole.ConsoleCommandResponse(l + CrestronEnvironment.NewLine);
+ }
+
+ ///
+ /// Prints message to console if current debug level is equal to or higher than the level of this message.
+ /// Uses CrestronConsole.PrintLine.
+ ///
+ ///
+ /// Console format string
+ /// Object parameters
+ public static void Console(uint level, string format, params object[] items)
+ {
+ if (Level >= level)
+ CrestronConsole.PrintLine("[{0}]App {1}:{2}", DateTime.Now.ToString("HH:mm:ss.fff"), InitialParametersClass.ApplicationNumber,
+ string.Format(format, items));
+ }
+
+ ///
+ /// Logs to Console when at-level, and all messages to error log, including device key
+ ///
+ public static void Console(uint level, IKeyed dev, string format, params object[] items)
+ {
+ if (Level >= level)
+ Console(level, "[{0}] {1}", dev.Key, string.Format(format, items));
+ }
+
+ public static void Console(uint level, IKeyed dev, ErrorLogLevel errorLogLevel,
+ string format, params object[] items)
+ {
+ var str = string.Format("[{0}] {1}", dev.Key, string.Format(format, items));
+ LogError(errorLogLevel, str);
+ if (Level >= level)
+ {
+ Console(level, str);
+ }
+ }
+
+ ///
+ /// Logs to Console when at-level, and all messages to error log
+ ///
+ public static void Console(uint level, ErrorLogLevel errorLogLevel,
+ string format, params object[] items)
+ {
+ var str = string.Format(format, items);
+ LogError(errorLogLevel, str);
+ if (Level >= level)
+ {
+ Console(level, str);
+ }
+ }
+
+ ///
+ /// Logs to both console and the custom user log (not the built-in error log). If appdebug level is set at
+ /// or above the level provided, then the output will be written to both console and the log. Otherwise
+ /// it will only be written to the log.
+ ///
+ ///
+ ///
+ ///
+ public static void ConsoleWithLog(uint level, string format, params object[] items)
+ {
+ var str = string.Format(format, items);
+ if (Level >= level)
+ CrestronConsole.PrintLine("App {0}:{1}", InitialParametersClass.ApplicationNumber, str);
+ CrestronLogger.WriteToLog(str, level);
+ }
+
+ ///
+ /// Logs to both console and the custom user log (not the built-in error log). If appdebug level is set at
+ /// or above the level provided, then the output will be written to both console and the log. Otherwise
+ /// it will only be written to the log.
+ ///
+ ///
+ ///
+ /// String.format string
+ /// Parameters for substitution in the format string.
+ public static void ConsoleWithLog(uint level, IKeyed dev, string format, params object[] items)
+ {
+ var str = string.Format(format, items);
+ if (Level >= level)
+ ConsoleWithLog(level, "[{0}] {1}", dev.Key, str);
+ }
+
+ ///
+ /// Prints to log and error log
+ ///
+ ///
+ ///
+ public static void LogError(ErrorLogLevel errorLogLevel, string str)
+ {
+ string msg = string.Format("App {0}:{1}", InitialParametersClass.ApplicationNumber, str);
+ switch (errorLogLevel)
+ {
+ case ErrorLogLevel.Error:
+ ErrorLog.Error(msg);
+ break;
+ case ErrorLogLevel.Warning:
+ ErrorLog.Warn(msg);
+ break;
+ case ErrorLogLevel.Notice:
+ ErrorLog.Notice(msg);
+ break;
+ }
+ }
+
+ ///
+ /// Writes the memory object after timeout
+ ///
+ static void SaveMemoryOnTimeout()
+ {
+ if (SaveTimer == null)
+ SaveTimer = new CTimer(o =>
+ {
+ SaveTimer = null;
+ SaveMemory();
+ }, SaveTimeoutMs);
+ else
+ SaveTimer.Reset(SaveTimeoutMs);
+ }
+
+ ///
+ /// Writes the memory - use SaveMemoryOnTimeout
+ ///
+ static void SaveMemory()
+ {
+ //var dir = @"\NVRAM\debug";
+ //if (!Directory.Exists(dir))
+ // Directory.Create(dir);
+
+ using (StreamWriter sw = new StreamWriter(GetMemoryFileName()))
+ {
+ var json = JsonConvert.SerializeObject(Contexts);
+ sw.Write(json);
+ sw.Flush();
+ }
+ }
+
+ ///
+ ///
+ ///
+ static void LoadMemory()
+ {
+ var file = GetMemoryFileName();
+ if (File.Exists(file))
+ {
+ using (StreamReader sr = new StreamReader(file))
+ {
+ var json = sr.ReadToEnd();
+ Contexts = JsonConvert.DeserializeObject(json);
+
+ if (Contexts != null)
+ {
+ Debug.Console(1, "Debug memory restored from file");
+ return;
+ }
+ }
+ }
+
+ Contexts = new DebugContextCollection();
+ }
+
+ ///
+ /// Helper to get the file path for this app's debug memory
+ ///
+ static string GetMemoryFileName()
+ {
+ return string.Format(@"\NVRAM\debugSettings\program{0}", InitialParametersClass.ApplicationNumber);
+ }
+
+ public enum ErrorLogLevel
+ {
+ Error, Warning, Notice, None
+ }
+ }
}
\ No newline at end of file