Merge remote-tracking branch 'origin/feature/PDC-9_ReceivedDataAsyncCallbackFixes' into maintenance/PR-1

# Conflicts:
#	Pepperdash Core/Pepperdash Core/Properties/AssemblyInfo.cs
This commit is contained in:
Neil Dorin
2019-05-23 14:08:37 -06:00
6 changed files with 487 additions and 475 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -669,6 +669,8 @@ namespace PepperDash.Core
} }
if (ClientReadyAfterKeyExchange.Contains(clientIndex)) if (ClientReadyAfterKeyExchange.Contains(clientIndex))
ClientReadyAfterKeyExchange.Remove(clientIndex); ClientReadyAfterKeyExchange.Remove(clientIndex);
if (WaitingForSharedKey.Contains(clientIndex))
WaitingForSharedKey.Remove(clientIndex);
} }
} }
catch (Exception ex) 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); 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.SendData(clientIndex, b, b.Length);
mySecureTCPServer.Disconnect(clientIndex); mySecureTCPServer.Disconnect(clientIndex);
WaitingForSharedKey.Remove(clientIndex);
return; return;
} }
if (mySecureTCPServer.NumberOfClientsConnected > 0)
mySecureTCPServer.ReceiveDataAsync(clientIndex, SecureReceivedDataAsyncCallback);
WaitingForSharedKey.Remove(clientIndex); WaitingForSharedKey.Remove(clientIndex);
byte[] success = Encoding.GetEncoding(28591).GetBytes("Shared Key Match"); byte[] success = Encoding.GetEncoding(28591).GetBytes("Shared Key Match");
mySecureTCPServer.SendDataAsync(clientIndex, success, success.Length, null); mySecureTCPServer.SendDataAsync(clientIndex, success, success.Length, null);
OnServerClientReadyForCommunications(clientIndex); OnServerClientReadyForCommunications(clientIndex);
Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Client with index {0} provided the shared key and successfully connected to the server", 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); else if (!string.IsNullOrEmpty(checkHeartbeat(clientIndex, received)))
//Debug.Console(1, this, "Secure Server Listening on Port: {0}, client IP: {1}, Client Index: {4}, NumberOfBytesReceived: {2}, Received: {3}\r\n", onTextReceived(received, clientIndex);
// mySecureTCPServer.PortNumber.ToString(), address , numberOfBytesReceived.ToString(), received, clientIndex.ToString());
if (!string.IsNullOrEmpty(checkHeartbeat(clientIndex, received)))
onTextReceived(received, clientIndex);
} }
catch (Exception ex) catch (Exception ex)
{ {
Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Error Receiving data: {0}. Error: {1}", received, 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) else
mySecureTCPServer.ReceiveDataAsync(clientIndex, SecureReceivedDataAsyncCallback); {
// If numberOfBytesReceived <= 0
mySecureTCPServer.Disconnect(clientIndex);
}
} }
#endregion #endregion

View File

@@ -174,8 +174,8 @@ namespace PepperDash.Core
if (Client != null) if (Client != null)
{ {
Debug.Console(1, this, "Program stopping. Closing connection"); Debug.Console(1, this, "Program stopping. Closing connection");
Client.Disconnect(); Disconnect();
Client.Dispose(); //Client.Dispose();
} }
} }
} }

View File

@@ -387,13 +387,16 @@ namespace PepperDash.Core
myTcpServer.SocketSendOrReceiveTimeOutInMs = (this.HeartbeatRequiredIntervalMs * 5); myTcpServer.SocketSendOrReceiveTimeOutInMs = (this.HeartbeatRequiredIntervalMs * 5);
// myTcpServer.HandshakeTimeout = 30; // myTcpServer.HandshakeTimeout = 30;
myTcpServer.SocketStatusChange += new TCPServerSocketStatusChangeEventHandler(TcpServer_SocketStatusChange);
} }
else else
{ {
KillServer(); KillServer();
myTcpServer.PortNumber = Port; myTcpServer.PortNumber = Port;
} }
myTcpServer.SocketStatusChange -= TcpServer_SocketStatusChange;
myTcpServer.SocketStatusChange += TcpServer_SocketStatusChange;
ServerStopped = false; ServerStopped = false;
myTcpServer.WaitForConnectionAsync(IPAddress.Any, TcpConnectCallback); myTcpServer.WaitForConnectionAsync(IPAddress.Any, TcpConnectCallback);
OnServerStateChange(myTcpServer.State); OnServerStateChange(myTcpServer.State);
@@ -670,6 +673,8 @@ namespace PepperDash.Core
} }
if (ClientReadyAfterKeyExchange.Contains(clientIndex)) if (ClientReadyAfterKeyExchange.Contains(clientIndex))
ClientReadyAfterKeyExchange.Remove(clientIndex); ClientReadyAfterKeyExchange.Remove(clientIndex);
if (WaitingForSharedKey.Contains(clientIndex))
WaitingForSharedKey.Remove(clientIndex);
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -763,50 +768,51 @@ namespace PepperDash.Core
/// <param name="mySecureTCPServer"></param> /// <param name="mySecureTCPServer"></param>
/// <param name="clientIndex"></param> /// <param name="clientIndex"></param>
/// <param name="numberOfBytesReceived"></param> /// <param name="numberOfBytesReceived"></param>
void TcpServerReceivedDataAsyncCallback(TCPServer mySecureTCPServer, uint clientIndex, int numberOfBytesReceived) void TcpServerReceivedDataAsyncCallback(TCPServer myTCPServer, uint clientIndex, int numberOfBytesReceived)
{ {
if (numberOfBytesReceived > 0) if (numberOfBytesReceived > 0)
{ {
string received = "Nothing"; string received = "Nothing";
try try
{ {
byte[] bytes = mySecureTCPServer.GetIncomingDataBufferForSpecificClient(clientIndex); byte[] bytes = myTCPServer.GetIncomingDataBufferForSpecificClient(clientIndex);
received = System.Text.Encoding.GetEncoding(28591).GetString(bytes, 0, numberOfBytesReceived); received = System.Text.Encoding.GetEncoding(28591).GetString(bytes, 0, numberOfBytesReceived);
if (WaitingForSharedKey.Contains(clientIndex)) if (WaitingForSharedKey.Contains(clientIndex))
{ {
received = received.Replace("\r", ""); received = received.Replace("\r", "");
received = received.Replace("\n", ""); received = received.Replace("\n", "");
if (received != SharedKey) if (received != SharedKey)
{ {
byte[] b = Encoding.GetEncoding(28591).GetBytes("Shared key did not match server. Disconnecting"); 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); 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); myTCPServer.SendData(clientIndex, b, b.Length);
mySecureTCPServer.Disconnect(clientIndex); myTCPServer.Disconnect(clientIndex);
WaitingForSharedKey.Remove(clientIndex); return;
return; }
}
if (mySecureTCPServer.NumberOfClientsConnected > 0) WaitingForSharedKey.Remove(clientIndex);
mySecureTCPServer.ReceiveDataAsync(clientIndex, TcpServerReceivedDataAsyncCallback); byte[] success = Encoding.GetEncoding(28591).GetBytes("Shared Key Match");
WaitingForSharedKey.Remove(clientIndex); myTCPServer.SendDataAsync(clientIndex, success, success.Length, null);
byte[] success = Encoding.GetEncoding(28591).GetBytes("Shared Key Match"); OnServerClientReadyForCommunications(clientIndex);
mySecureTCPServer.SendDataAsync(clientIndex, success, success.Length, null); Debug.Console(1, this, Debug.ErrorLogLevel.Notice, "Client with index {0} provided the shared key and successfully connected to the server", clientIndex);
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; else if (!string.IsNullOrEmpty(checkHeartbeat(clientIndex, received)))
} onTextReceived(received, clientIndex);
//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", catch (Exception ex)
// mySecureTCPServer.PortNumber.ToString(), address , numberOfBytesReceived.ToString(), received, clientIndex.ToString()); {
if (!string.IsNullOrEmpty(checkHeartbeat(clientIndex, received))) Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Error Receiving data: {0}. Error: {1}", received, ex);
onTextReceived(received, clientIndex); }
} if (myTCPServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED)
catch (Exception ex) myTCPServer.ReceiveDataAsync(clientIndex, TcpServerReceivedDataAsyncCallback);
{ }
Debug.Console(0, this, Debug.ErrorLogLevel.Error, "Error Receiving data: {0}. Error: {1}", received, ex); else
} {
} // If numberOfBytesReceived <= 0
if (mySecureTCPServer.GetServerSocketStatusForSpecificClient(clientIndex) == SocketStatus.SOCKET_STATUS_CONNECTED) myTCPServer.Disconnect();
mySecureTCPServer.ReceiveDataAsync(clientIndex, TcpServerReceivedDataAsyncCallback); }
} }
#endregion #endregion

View File

@@ -1,419 +1,421 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Crestron.SimplSharp; using Crestron.SimplSharp;
using Crestron.SimplSharp.Reflection; using Crestron.SimplSharp.Reflection;
using Crestron.SimplSharp.CrestronLogger; using Crestron.SimplSharp.CrestronLogger;
using Crestron.SimplSharp.CrestronIO; using Crestron.SimplSharp.CrestronIO;
using Newtonsoft.Json; using Newtonsoft.Json;
using PepperDash.Core.DebugThings; using PepperDash.Core.DebugThings;
namespace PepperDash.Core namespace PepperDash.Core
{ {
public static class Debug public static class Debug
{ {
/// <summary> /// <summary>
/// Describes the folder location where a given program stores it's debug level memory. By default, the /// 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. /// file written will be named appNdebug where N is 1-10.
/// </summary> /// </summary>
public static string FilePathPrefix = @"\nvram\debug\"; public static string FilePathPrefix = @"\nvram\debug\";
/// <summary> /// <summary>
/// The name of the file containing the current debug settings. /// The name of the file containing the current debug settings.
/// </summary> /// </summary>
public static string FileName = string.Format(@"app{0}Debug.json", InitialParametersClass.ApplicationNumber); public static string FileName = string.Format(@"app{0}Debug.json", InitialParametersClass.ApplicationNumber);
public static int Level { get; private set; } public static int Level { get; private set; }
static DebugContextCollection Contexts; static DebugContextCollection Contexts;
static int SaveTimeoutMs = 30000; static int SaveTimeoutMs = 30000;
static CTimer SaveTimer; public static string PepperDashCoreVersion { get; private set; }
/// <summary> static CTimer SaveTimer;
/// When true, the IncludedExcludedKeys dict will contain keys to include.
/// When false (default), IncludedExcludedKeys will contain keys to exclude. /// <summary>
/// </summary> /// When true, the IncludedExcludedKeys dict will contain keys to include.
static bool ExcludeAllMode; /// When false (default), IncludedExcludedKeys will contain keys to exclude.
/// </summary>
//static bool ExcludeNoKeyMessages; static bool ExcludeAllMode;
static Dictionary<string, object> IncludedExcludedKeys; //static bool ExcludeNoKeyMessages;
static Debug() static Dictionary<string, object> IncludedExcludedKeys;
{
// Get the assembly version and print it to console and the log static Debug()
var version = Assembly.GetExecutingAssembly().GetName().Version; {
// Get the assembly version and print it to console and the log
var versionString = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build); var version = Assembly.GetExecutingAssembly().GetName().Version;
var msg = string.Format("[App {0}] Using PepperDash_Core v{1}", InitialParametersClass.ApplicationNumber, versionString); PepperDashCoreVersion = string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build);
CrestronConsole.PrintLine(msg); var msg = string.Format("[App {0}] Using PepperDash_Core v{1}", InitialParametersClass.ApplicationNumber, PepperDashCoreVersion);
LogError(ErrorLogLevel.Notice, msg); CrestronConsole.PrintLine(msg);
IncludedExcludedKeys = new Dictionary<string, object>(); LogError(ErrorLogLevel.Notice, msg);
//CrestronDataStoreStatic.InitCrestronDataStore(); IncludedExcludedKeys = new Dictionary<string, object>();
if (CrestronEnvironment.RuntimeEnvironment == eRuntimeEnvironment.SimplSharpPro)
{ //CrestronDataStoreStatic.InitCrestronDataStore();
// Add command to console if (CrestronEnvironment.RuntimeEnvironment == eRuntimeEnvironment.SimplSharpPro)
CrestronConsole.AddNewConsoleCommand(SetDebugFromConsole, "appdebug", {
"appdebug:P [0-2]: Sets the application's console debug message level", // Add command to console
ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(SetDebugFromConsole, "appdebug",
CrestronConsole.AddNewConsoleCommand(ShowDebugLog, "appdebuglog", "appdebug:P [0-2]: Sets the application's console debug message level",
"appdebuglog:P [all] Use \"all\" for full log.", ConsoleAccessLevelEnum.AccessOperator);
ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(ShowDebugLog, "appdebuglog",
CrestronConsole.AddNewConsoleCommand(s => CrestronLogger.Clear(false), "appdebugclear", "appdebuglog:P [all] Use \"all\" for full log.",
"appdebugclear:P Clears the current custom log", ConsoleAccessLevelEnum.AccessOperator);
ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(s => CrestronLogger.Clear(false), "appdebugclear",
CrestronConsole.AddNewConsoleCommand(SetDebugFilterFromConsole, "appdebugfilter", "appdebugclear:P Clears the current custom log",
"appdebugfilter [params]", ConsoleAccessLevelEnum.AccessOperator); ConsoleAccessLevelEnum.AccessOperator);
} CrestronConsole.AddNewConsoleCommand(SetDebugFilterFromConsole, "appdebugfilter",
"appdebugfilter [params]", ConsoleAccessLevelEnum.AccessOperator);
CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler; }
LoadMemory(); CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironment_ProgramStatusEventHandler;
Level = Contexts.GetOrCreateItem("DEFAULT").Level;
LoadMemory();
try Level = Contexts.GetOrCreateItem("DEFAULT").Level;
{
if (InitialParametersClass.NumberOfRemovableDrives > 0) try
{ {
CrestronConsole.PrintLine("{0} RM Drive(s) Present.", InitialParametersClass.NumberOfRemovableDrives); if (InitialParametersClass.NumberOfRemovableDrives > 0)
CrestronLogger.Initialize(2, LoggerModeEnum.DEFAULT); // Use RM instead of DEFAULT as not to double-up console messages. {
} CrestronConsole.PrintLine("{0} RM Drive(s) Present.", InitialParametersClass.NumberOfRemovableDrives);
else CrestronLogger.Initialize(2, LoggerModeEnum.DEFAULT); // Use RM instead of DEFAULT as not to double-up console messages.
CrestronConsole.PrintLine("No RM Drive(s) Present."); }
} else
catch (Exception e) CrestronConsole.PrintLine("No RM Drive(s) Present.");
{ }
catch (Exception e)
CrestronConsole.PrintLine("Initializing of CrestronLogger failed: {0}", e); {
}
} CrestronConsole.PrintLine("Initializing of CrestronLogger failed: {0}", e);
}
/// <summary> }
/// Used to save memory when shutting down
/// </summary> /// <summary>
/// <param name="programEventType"></param> /// Used to save memory when shutting down
static void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) /// </summary>
{ /// <param name="programEventType"></param>
if (programEventType == eProgramStatusEventType.Stopping) static void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType)
{ {
if (SaveTimer != null) if (programEventType == eProgramStatusEventType.Stopping)
{ {
SaveTimer.Stop(); if (SaveTimer != null)
SaveTimer = null; {
} SaveTimer.Stop();
Console(0, "Saving debug settings"); SaveTimer = null;
SaveMemory(); }
} Console(0, "Saving debug settings");
} SaveMemory();
}
/// <summary> }
/// Callback for console command
/// </summary> /// <summary>
/// <param name="levelString"></param> /// Callback for console command
public static void SetDebugFromConsole(string levelString) /// </summary>
{ /// <param name="levelString"></param>
try public static void SetDebugFromConsole(string levelString)
{ {
if (string.IsNullOrEmpty(levelString.Trim())) try
{ {
CrestronConsole.PrintLine("AppDebug level = {0}", Level); if (string.IsNullOrEmpty(levelString.Trim()))
return; {
} CrestronConsole.PrintLine("AppDebug level = {0}", Level);
return;
SetDebugLevel(Convert.ToInt32(levelString)); }
}
catch SetDebugLevel(Convert.ToInt32(levelString));
{ }
CrestronConsole.PrintLine("Usage: appdebug:P [0-2]"); catch
} {
} CrestronConsole.PrintLine("Usage: appdebug:P [0-2]");
}
public static void SetDebugFilterFromConsole(string items) }
{
var str = items.Trim(); public static void SetDebugFilterFromConsole(string items)
if (str == "?") {
{ var str = items.Trim();
CrestronConsole.ConsoleCommandResponse("Usage:\r APPDEBUGFILTER key1 key2 key3....\r " + if (str == "?")
"+all: at beginning puts filter into 'default include' mode\r" + {
" All keys that follow will be excluded from output.\r" + CrestronConsole.ConsoleCommandResponse("Usage:\r APPDEBUGFILTER key1 key2 key3....\r " +
"-all: at beginning puts filter into 'default excluse all' mode.\r" + "+all: at beginning puts filter into 'default include' mode\r" +
" All keys that follow will be the only keys that are shown\r" + " All keys that follow will be excluded from output.\r" +
"+nokey: Enables messages with no key (default)\r" + "-all: at beginning puts filter into 'default excluse all' mode.\r" +
"-nokey: Disables messages with no key.\r" + " All keys that follow will be the only keys that are shown\r" +
"(nokey settings are independent of all other settings)"); "+nokey: Enables messages with no key (default)\r" +
return; "-nokey: Disables messages with no key.\r" +
} "(nokey settings are independent of all other settings)");
var keys = Regex.Split(str, @"\s*"); return;
foreach (var keyToken in keys) }
{ var keys = Regex.Split(str, @"\s*");
var lkey = keyToken.ToLower(); foreach (var keyToken in keys)
if (lkey == "+all") {
{ var lkey = keyToken.ToLower();
IncludedExcludedKeys.Clear(); if (lkey == "+all")
ExcludeAllMode = false; {
} IncludedExcludedKeys.Clear();
else if (lkey == "-all") ExcludeAllMode = false;
{ }
IncludedExcludedKeys.Clear(); else if (lkey == "-all")
ExcludeAllMode = true; {
} IncludedExcludedKeys.Clear();
//else if (lkey == "+nokey") ExcludeAllMode = true;
//{ }
// ExcludeNoKeyMessages = false; //else if (lkey == "+nokey")
//} //{
//else if (lkey == "-nokey") // ExcludeNoKeyMessages = false;
//{ //}
// ExcludeNoKeyMessages = true; //else if (lkey == "-nokey")
//} //{
else // ExcludeNoKeyMessages = true;
{ //}
string key = null; ; else
if (lkey.StartsWith("-")) {
{ string key = null; ;
key = lkey.Substring(1); if (lkey.StartsWith("-"))
// if in exclude all mode, we need to remove this from the inclusions {
if (ExcludeAllMode) key = lkey.Substring(1);
{ // if in exclude all mode, we need to remove this from the inclusions
if (IncludedExcludedKeys.ContainsKey(key)) if (ExcludeAllMode)
IncludedExcludedKeys.Remove(key); {
} if (IncludedExcludedKeys.ContainsKey(key))
// otherwise include all mode, add to the exclusions IncludedExcludedKeys.Remove(key);
else }
{ // otherwise include all mode, add to the exclusions
IncludedExcludedKeys[key] = new object(); else
} {
} IncludedExcludedKeys[key] = new object();
else if (lkey.StartsWith("+")) }
{ }
key = lkey.Substring(1); else if (lkey.StartsWith("+"))
// if in exclude all mode, we need to add this as inclusion {
if (ExcludeAllMode) 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 IncludedExcludedKeys[key] = new object();
else }
{ // otherwise include all mode, remove this from exclusions
if (IncludedExcludedKeys.ContainsKey(key)) else
IncludedExcludedKeys.Remove(key); {
} if (IncludedExcludedKeys.ContainsKey(key))
} IncludedExcludedKeys.Remove(key);
} }
} }
} }
}
}
/// <summary>
/// Sets the debug level
/// </summary> /// <summary>
/// <param name="level"> Valid values 0 (no debug), 1 (critical), 2 (all messages)</param> /// Sets the debug level
public static void SetDebugLevel(int level) /// </summary>
{ /// <param name="level"> Valid values 0 (no debug), 1 (critical), 2 (all messages)</param>
if (level <= 2) public static void SetDebugLevel(int level)
{ {
Level = level; if (level <= 2)
Contexts.GetOrCreateItem("DEFAULT").Level = level; {
SaveMemoryOnTimeout(); Level = level;
Contexts.GetOrCreateItem("DEFAULT").Level = level;
CrestronConsole.PrintLine("[Application {0}], Debug level set to {1}", SaveMemoryOnTimeout();
InitialParametersClass.ApplicationNumber, Level);
CrestronConsole.PrintLine("[Application {0}], Debug level set to {1}",
//var err = CrestronDataStoreStatic.SetLocalUintValue("DebugLevel", level); InitialParametersClass.ApplicationNumber, Level);
//if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
// CrestronConsole.PrintLine("Error saving console debug level setting: {0}", err); //var err = CrestronDataStoreStatic.SetLocalUintValue("DebugLevel", level);
} //if (err != CrestronDataStore.CDS_ERROR.CDS_SUCCESS)
} // CrestronConsole.PrintLine("Error saving console debug level setting: {0}", err);
}
/// <summary> }
///
/// </summary> /// <summary>
public static void ShowDebugLog(string s) ///
{ /// </summary>
var loglist = CrestronLogger.PrintTheLog(s.ToLower() == "all"); public static void ShowDebugLog(string s)
foreach (var l in loglist) {
CrestronConsole.ConsoleCommandResponse(l + CrestronEnvironment.NewLine); var loglist = CrestronLogger.PrintTheLog(s.ToLower() == "all");
} foreach (var l in loglist)
CrestronConsole.ConsoleCommandResponse(l + CrestronEnvironment.NewLine);
/// <summary> }
/// Prints message to console if current debug level is equal to or higher than the level of this message.
/// Uses CrestronConsole.PrintLine. /// <summary>
/// </summary> /// Prints message to console if current debug level is equal to or higher than the level of this message.
/// <param name="level"></param> /// Uses CrestronConsole.PrintLine.
/// <param name="format">Console format string</param> /// </summary>
/// <param name="items">Object parameters</param> /// <param name="level"></param>
public static void Console(uint level, string format, params object[] items) /// <param name="format">Console format string</param>
{ /// <param name="items">Object parameters</param>
if (Level >= level) public static void Console(uint level, string format, params object[] items)
CrestronConsole.PrintLine("[{0}]App {1}:{2}", DateTime.Now.ToString("HH:mm:ss.fff"), InitialParametersClass.ApplicationNumber, {
string.Format(format, items)); if (Level >= level)
} CrestronConsole.PrintLine("[{0}]App {1}:{2}", DateTime.Now.ToString("HH:mm:ss.fff"), InitialParametersClass.ApplicationNumber,
string.Format(format, items));
/// <summary> }
/// Logs to Console when at-level, and all messages to error log, including device key
/// </summary> /// <summary>
public static void Console(uint level, IKeyed dev, string format, params object[] items) /// Logs to Console when at-level, and all messages to error log, including device key
{ /// </summary>
if (Level >= level) public static void Console(uint level, IKeyed dev, string format, params object[] items)
Console(level, "[{0}] {1}", dev.Key, string.Format(format, 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)
{ public static void Console(uint level, IKeyed dev, ErrorLogLevel errorLogLevel,
var str = string.Format("[{0}] {1}", dev.Key, string.Format(format, items)); string format, params object[] items)
LogError(errorLogLevel, str); {
if (Level >= level) var str = string.Format("[{0}] {1}", dev.Key, string.Format(format, items));
{ LogError(errorLogLevel, str);
Console(level, str); if (Level >= level)
} {
} Console(level, str);
}
/// <summary> }
/// Logs to Console when at-level, and all messages to error log
/// </summary> /// <summary>
public static void Console(uint level, ErrorLogLevel errorLogLevel, /// Logs to Console when at-level, and all messages to error log
string format, params object[] items) /// </summary>
{ public static void Console(uint level, ErrorLogLevel errorLogLevel,
var str = string.Format(format, items); string format, params object[] items)
LogError(errorLogLevel, str); {
if (Level >= level) var str = string.Format(format, items);
{ LogError(errorLogLevel, str);
Console(level, str); if (Level >= level)
} {
} Console(level, str);
}
/// <summary> }
/// 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 /// <summary>
/// it will only be written to the log. /// Logs to both console and the custom user log (not the built-in error log). If appdebug level is set at
/// </summary> /// or above the level provided, then the output will be written to both console and the log. Otherwise
/// <param name="level"></param> /// it will only be written to the log.
/// <param name="format"></param> /// </summary>
/// <param name="items"></param> /// <param name="level"></param>
public static void ConsoleWithLog(uint level, string format, params object[] items) /// <param name="format"></param>
{ /// <param name="items"></param>
var str = string.Format(format, items); public static void ConsoleWithLog(uint level, string format, params object[] items)
if (Level >= level) {
CrestronConsole.PrintLine("App {0}:{1}", InitialParametersClass.ApplicationNumber, str); var str = string.Format(format, items);
CrestronLogger.WriteToLog(str, level); if (Level >= level)
} CrestronConsole.PrintLine("App {0}:{1}", InitialParametersClass.ApplicationNumber, str);
CrestronLogger.WriteToLog(str, level);
/// <summary> }
/// 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 /// <summary>
/// it will only be written to the log. /// Logs to both console and the custom user log (not the built-in error log). If appdebug level is set at
/// </summary> /// or above the level provided, then the output will be written to both console and the log. Otherwise
/// <param name="level"></param> /// it will only be written to the log.
/// <param name="dev"></param> /// </summary>
/// <param name="format">String.format string</param> /// <param name="level"></param>
/// <param name="items">Parameters for substitution in the format string.</param> /// <param name="dev"></param>
public static void ConsoleWithLog(uint level, IKeyed dev, string format, params object[] items) /// <param name="format">String.format string</param>
{ /// <param name="items">Parameters for substitution in the format string.</param>
var str = string.Format(format, items); public static void ConsoleWithLog(uint level, IKeyed dev, string format, params object[] items)
if (Level >= level) {
ConsoleWithLog(level, "[{0}] {1}", dev.Key, str); var str = string.Format(format, items);
} if (Level >= level)
ConsoleWithLog(level, "[{0}] {1}", dev.Key, str);
/// <summary> }
/// Prints to log and error log
/// </summary> /// <summary>
/// <param name="errorLogLevel"></param> /// Prints to log and error log
/// <param name="str"></param> /// </summary>
public static void LogError(ErrorLogLevel errorLogLevel, string str) /// <param name="errorLogLevel"></param>
{ /// <param name="str"></param>
string msg = string.Format("App {0}:{1}", InitialParametersClass.ApplicationNumber, str); public static void LogError(ErrorLogLevel errorLogLevel, string str)
switch (errorLogLevel) {
{ string msg = string.Format("App {0}:{1}", InitialParametersClass.ApplicationNumber, str);
case ErrorLogLevel.Error: switch (errorLogLevel)
ErrorLog.Error(msg); {
break; case ErrorLogLevel.Error:
case ErrorLogLevel.Warning: ErrorLog.Error(msg);
ErrorLog.Warn(msg); break;
break; case ErrorLogLevel.Warning:
case ErrorLogLevel.Notice: ErrorLog.Warn(msg);
ErrorLog.Notice(msg); break;
break; case ErrorLogLevel.Notice:
} ErrorLog.Notice(msg);
} break;
}
/// <summary> }
/// Writes the memory object after timeout
/// </summary> /// <summary>
static void SaveMemoryOnTimeout() /// Writes the memory object after timeout
{ /// </summary>
if (SaveTimer == null) static void SaveMemoryOnTimeout()
SaveTimer = new CTimer(o => {
{ if (SaveTimer == null)
SaveTimer = null; SaveTimer = new CTimer(o =>
SaveMemory(); {
}, SaveTimeoutMs); SaveTimer = null;
else SaveMemory();
SaveTimer.Reset(SaveTimeoutMs); }, SaveTimeoutMs);
} else
SaveTimer.Reset(SaveTimeoutMs);
/// <summary> }
/// Writes the memory - use SaveMemoryOnTimeout
/// </summary> /// <summary>
static void SaveMemory() /// Writes the memory - use SaveMemoryOnTimeout
{ /// </summary>
//var dir = @"\NVRAM\debug"; static void SaveMemory()
//if (!Directory.Exists(dir)) {
// Directory.Create(dir); //var dir = @"\NVRAM\debug";
//if (!Directory.Exists(dir))
using (StreamWriter sw = new StreamWriter(GetMemoryFileName())) // Directory.Create(dir);
{
var json = JsonConvert.SerializeObject(Contexts); using (StreamWriter sw = new StreamWriter(GetMemoryFileName()))
sw.Write(json); {
sw.Flush(); var json = JsonConvert.SerializeObject(Contexts);
} sw.Write(json);
} sw.Flush();
}
/// <summary> }
///
/// </summary> /// <summary>
static void LoadMemory() ///
{ /// </summary>
var file = GetMemoryFileName(); static void LoadMemory()
if (File.Exists(file)) {
{ var file = GetMemoryFileName();
using (StreamReader sr = new StreamReader(file)) if (File.Exists(file))
{ {
var json = sr.ReadToEnd(); using (StreamReader sr = new StreamReader(file))
Contexts = JsonConvert.DeserializeObject<DebugContextCollection>(json); {
var json = sr.ReadToEnd();
if (Contexts != null) Contexts = JsonConvert.DeserializeObject<DebugContextCollection>(json);
{
Debug.Console(1, "Debug memory restored from file"); if (Contexts != null)
return; {
} Debug.Console(1, "Debug memory restored from file");
} return;
} }
}
Contexts = new DebugContextCollection(); }
}
Contexts = new DebugContextCollection();
/// <summary> }
/// Helper to get the file path for this app's debug memory
/// </summary> /// <summary>
static string GetMemoryFileName() /// Helper to get the file path for this app's debug memory
{ /// </summary>
return string.Format(@"\NVRAM\debugSettings\program{0}", InitialParametersClass.ApplicationNumber); static string GetMemoryFileName()
} {
return string.Format(@"\NVRAM\debugSettings\program{0}", InitialParametersClass.ApplicationNumber);
public enum ErrorLogLevel }
{
Error, Warning, Notice, None public enum ErrorLogLevel
} {
} Error, Warning, Notice, None
}
}
} }