diff --git a/src/PepperDash.Core/ComTextHelper.cs b/src/PepperDash.Core/ComTextHelper.cs new file mode 100644 index 00000000..06b996be --- /dev/null +++ b/src/PepperDash.Core/ComTextHelper.cs @@ -0,0 +1,43 @@ +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + +namespace PepperDash.Core +{ + /// + /// + /// + public class ComTextHelper + { + /// + /// Gets escaped text for a byte array + /// + /// + /// string with all bytes escaped + public static string GetEscapedText(byte[] bytes) + { + return string.Concat(bytes.Select(b => string.Format(@"[{0:X2}]", (int)b)).ToArray()); + } + + /// + /// Gets escaped text for a string + /// + /// + /// string with all bytes escaped + public static string GetEscapedText(string text) + { + var bytes = Encoding.GetEncoding(28591).GetBytes(text); + return string.Concat(bytes.Select(b => string.Format(@"[{0:X2}]", (int)b)).ToArray()); + } + + /// + /// Gets debug text for a string + /// + /// + /// string with all non-printable characters escaped + public static string GetDebugText(string text) + { + return Regex.Replace(text, @"[^\u0020-\u007E]", a => GetEscapedText(a.Value)); + } + } +} \ No newline at end of file diff --git a/src/PepperDash.Core/Comm/CommunicationStreamDebugging.cs b/src/PepperDash.Core/Comm/CommunicationStreamDebugging.cs index 33141f0c..780e65d0 100644 --- a/src/PepperDash.Core/Comm/CommunicationStreamDebugging.cs +++ b/src/PepperDash.Core/Comm/CommunicationStreamDebugging.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Text; using Crestron.SimplSharp; @@ -37,14 +36,14 @@ namespace PepperDash.Core { get { - return _DebugTimeoutInMs/60000; + return _DebugTimeoutInMs / 60000; } } /// /// Gets or sets the RxStreamDebuggingIsEnabled /// - public bool RxStreamDebuggingIsEnabled{ get; private set; } + public bool RxStreamDebuggingIsEnabled { get; private set; } /// /// Indicates that transmit stream debugging is enabled @@ -108,7 +107,7 @@ namespace PepperDash.Core TxStreamDebuggingIsEnabled = true; Debug.SetDeviceDebugSettings(ParentDeviceKey, setting); - + } /// @@ -136,51 +135,4 @@ namespace PepperDash.Core DebugExpiryPeriod = null; } } - - /// - /// The available settings for stream debugging - /// - [Flags] - /// - /// Enumeration of eStreamDebuggingSetting values - /// - public enum eStreamDebuggingSetting - { - /// - /// Debug off - /// - Off = 0, - /// - /// Debug received data - /// - Rx = 1, - /// - /// Debug transmitted data - /// - Tx = 2, - /// - /// Debug both received and transmitted data - /// - Both = Rx | Tx - } - - /// - /// The available settings for stream debugging response types - /// - [Flags] - public enum eStreamDebuggingDataTypeSettings - { - /// - /// Debug data in byte format - /// - Bytes = 0, - /// - /// Debug data in text format - /// - Text = 1, - /// - /// Debug data in both byte and text formats - /// - Both = Bytes | Text, - } } diff --git a/src/PepperDash.Core/Comm/GenericSshClient.cs b/src/PepperDash.Core/Comm/GenericSshClient.cs index 13192ed5..8ea5138e 100644 --- a/src/PepperDash.Core/Comm/GenericSshClient.cs +++ b/src/PepperDash.Core/Comm/GenericSshClient.cs @@ -416,18 +416,14 @@ namespace PepperDash.Core if (bytesHandler != null) { var bytes = Encoding.UTF8.GetBytes(response); - if (StreamDebugging.RxStreamDebuggingIsEnabled) - { - this.LogInformation("Received {1} bytes: '{0}'", ComTextHelper.GetEscapedText(bytes), bytes.Length); - } + this.PrintReceivedBytes(bytes); bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); } var textHandler = TextReceived; if (textHandler != null) { - if (StreamDebugging.RxStreamDebuggingIsEnabled) - this.LogInformation("Received: '{0}'", ComTextHelper.GetDebugText(response)); + this.PrintReceivedText(response); textHandler(this, new GenericCommMethodReceiveTextArgs(response)); } @@ -484,11 +480,7 @@ namespace PepperDash.Core { if (Client != null && TheStream != null && IsConnected) { - if (StreamDebugging.TxStreamDebuggingIsEnabled) - this.LogInformation( - "Sending {length} characters of text: '{text}'", - text.Length, - ComTextHelper.GetDebugText(text)); + this.PrintSentText(text); TheStream.Write(text); TheStream.Flush(); @@ -521,8 +513,7 @@ namespace PepperDash.Core { if (Client != null && TheStream != null && IsConnected) { - if (StreamDebugging.TxStreamDebuggingIsEnabled) - this.LogInformation("Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes)); + this.PrintSentBytes(bytes); TheStream.Write(bytes, 0, bytes.Length); TheStream.Flush(); diff --git a/src/PepperDash.Core/Comm/GenericTcpIpClient.cs b/src/PepperDash.Core/Comm/GenericTcpIpClient.cs index c9235411..17507851 100644 --- a/src/PepperDash.Core/Comm/GenericTcpIpClient.cs +++ b/src/PepperDash.Core/Comm/GenericTcpIpClient.cs @@ -19,44 +19,44 @@ namespace PepperDash.Core /// public CommunicationStreamDebugging StreamDebugging { get; private set; } - /// - /// Fires when data is received from the server and returns it as a Byte array - /// - public event EventHandler BytesReceived; + /// + /// Fires when data is received from the server and returns it as a Byte array + /// + public event EventHandler BytesReceived; - /// - /// Fires when data is received from the server and returns it as text - /// - public event EventHandler TextReceived; + /// + /// Fires when data is received from the server and returns it as text + /// + public event EventHandler TextReceived; - /// - /// - /// - //public event GenericSocketStatusChangeEventDelegate SocketStatusChange; - public event EventHandler ConnectionChange; + /// + /// + /// + //public event GenericSocketStatusChangeEventDelegate SocketStatusChange; + public event EventHandler ConnectionChange; - private string _hostname; + private string _hostname; /// /// Address of server /// public string Hostname { - get - { - return _hostname; - } + get + { + return _hostname; + } - set - { - _hostname = value; - if (_client != null) - { - _client.AddressClientConnectedTo = _hostname; - } - } - } + set + { + _hostname = value; + if (_client != null) + { + _client.AddressClientConnectedTo = _hostname; + } + } + } /// /// Gets or sets the Port @@ -78,19 +78,19 @@ namespace PepperDash.Core /// public int BufferSize { get; set; } - /// - /// The actual client class - /// - private TCPClient _client; + /// + /// The actual client class + /// + private TCPClient _client; - /// - /// Bool showing if socket is connected - /// - public bool IsConnected - { - get { return _client != null && _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; } + /// + /// Bool showing if socket is connected + /// + public bool IsConnected + { + get { return _client != null && _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; } } - + /// /// S+ helper for IsConnected /// @@ -99,15 +99,15 @@ namespace PepperDash.Core get { return (ushort)(IsConnected ? 1 : 0); } } - /// - /// _client socket status Read only - /// - public SocketStatus ClientStatus - { - get + /// + /// _client socket status Read only + /// + public SocketStatus ClientStatus + { + get { - return _client == null ? SocketStatus.SOCKET_STATUS_NO_CONNECT : _client.ClientStatus; - } + return _client == null ? SocketStatus.SOCKET_STATUS_NO_CONNECT : _client.ClientStatus; + } } /// @@ -119,26 +119,26 @@ namespace PepperDash.Core get { return (ushort)ClientStatus; } } - /// + /// /// Status text shows the message associated with socket status - /// - public string ClientStatusText { get { return ClientStatus.ToString(); } } + /// + public string ClientStatusText { get { return ClientStatus.ToString(); } } - /// - /// Ushort representation of client status - /// + /// + /// Ushort representation of client status + /// [Obsolete] - public ushort UClientStatus { get { return (ushort)ClientStatus; } } + public ushort UClientStatus { get { return (ushort)ClientStatus; } } - /// - /// Connection failure reason - /// - public string ConnectionFailure { get { return ClientStatus.ToString(); } } + /// + /// Connection failure reason + /// + public string ConnectionFailure { get { return ClientStatus.ToString(); } } - /// - /// Gets or sets the AutoReconnect - /// - public bool AutoReconnect { get; set; } + /// + /// Gets or sets the AutoReconnect + /// + public bool AutoReconnect { get; set; } /// /// S+ helper for AutoReconnect @@ -149,29 +149,29 @@ namespace PepperDash.Core set { AutoReconnect = value == 1; } } - /// - /// Milliseconds to wait before attempting to reconnect. Defaults to 5000 - /// - public int AutoReconnectIntervalMs { get; set; } + /// + /// Milliseconds to wait before attempting to reconnect. Defaults to 5000 + /// + public int AutoReconnectIntervalMs { get; set; } - /// - /// Set only when the disconnect method is called - /// - bool DisconnectCalledByUser; + /// + /// Set only when the disconnect method is called + /// + bool DisconnectCalledByUser; - /// - /// - /// - public bool Connected - { - get { return _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; } - } + /// + /// + /// + public bool Connected + { + get { return _client.ClientStatus == SocketStatus.SOCKET_STATUS_CONNECTED; } + } //Lock object to prevent simulatneous connect/disconnect operations private CCriticalSection connectLock = new CCriticalSection(); // private Timer for auto reconnect - private CTimer RetryTimer; + private CTimer RetryTimer; /// /// Constructor @@ -181,8 +181,8 @@ namespace PepperDash.Core /// /// public GenericTcpIpClient(string key, string address, int port, int bufferSize) - : base(key) - { + : base(key) + { StreamDebugging = new CommunicationStreamDebugging(key); CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); AutoReconnectIntervalMs = 5000; @@ -218,18 +218,18 @@ namespace PepperDash.Core /// Default constructor for S+ /// public GenericTcpIpClient() - : base(SplusKey) + : base(SplusKey) { StreamDebugging = new CommunicationStreamDebugging(SplusKey); - CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); - AutoReconnectIntervalMs = 5000; + CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); + AutoReconnectIntervalMs = 5000; BufferSize = 2000; RetryTimer = new CTimer(o => { Reconnect(); }, Timeout.Infinite); - } + } /// /// Initialize method @@ -255,26 +255,26 @@ namespace PepperDash.Core /// /// /// - /// - /// Deactivate method - /// - public override bool Deactivate() - { + /// + /// Deactivate method + /// + public override bool Deactivate() + { RetryTimer.Stop(); RetryTimer.Dispose(); if (_client != null) { - _client.SocketStatusChange -= this.Client_SocketStatusChange; + _client.SocketStatusChange -= this.Client_SocketStatusChange; DisconnectClient(); } - return true; - } + return true; + } - /// - /// Connect method - /// - public void Connect() - { + /// + /// Connect method + /// + public void Connect() + { if (string.IsNullOrEmpty(Hostname)) { Debug.Console(1, Debug.ErrorLogLevel.Warning, "GenericTcpIpClient '{0}': No address set", Key); @@ -310,7 +310,7 @@ namespace PepperDash.Core { connectLock.Leave(); } - } + } private void Reconnect() { @@ -337,11 +337,11 @@ namespace PepperDash.Core } } - /// - /// Disconnect method - /// - public void Disconnect() - { + /// + /// Disconnect method + /// + public void Disconnect() + { try { connectLock.Enter(); @@ -355,7 +355,7 @@ namespace PepperDash.Core { connectLock.Leave(); } - } + } /// /// DisconnectClient method @@ -375,7 +375,7 @@ namespace PepperDash.Core /// /// void ConnectToServerCallback(TCPClient c) - { + { if (c.ClientStatus != SocketStatus.SOCKET_STATUS_CONNECTED) { Debug.Console(0, this, "Server connection result: {0}", c.ClientStatus); @@ -385,13 +385,13 @@ namespace PepperDash.Core { Debug.Console(1, this, "Server connection result: {0}", c.ClientStatus); } - } + } /// /// Disconnects, waits and attemtps to connect again /// void WaitAndTryReconnect() - { + { CrestronInvoke.BeginInvoke(o => { try @@ -409,7 +409,7 @@ namespace PepperDash.Core connectLock.Leave(); } }); - } + } /// /// Recieves incoming data @@ -417,7 +417,7 @@ namespace PepperDash.Core /// /// void Receive(TCPClient client, int numBytes) - { + { if (client != null) { if (numBytes > 0) @@ -426,10 +426,7 @@ namespace PepperDash.Core var bytesHandler = BytesReceived; if (bytesHandler != null) { - if (StreamDebugging.RxStreamDebuggingIsEnabled) - { - Debug.Console(0, this, "Received {1} bytes: '{0}'", ComTextHelper.GetEscapedText(bytes), bytes.Length); - } + this.PrintReceivedBytes(bytes); bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); } var textHandler = TextReceived; @@ -437,58 +434,54 @@ namespace PepperDash.Core { var str = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); - if (StreamDebugging.RxStreamDebuggingIsEnabled) - { - Debug.Console(0, this, "Received {1} characters of text: '{0}'", ComTextHelper.GetDebugText(str), str.Length); - } + this.PrintReceivedText(str); textHandler(this, new GenericCommMethodReceiveTextArgs(str)); - } + } } client.ReceiveDataAsync(Receive); } - } + } - /// - /// SendText method - /// - public void SendText(string text) - { - var bytes = Encoding.GetEncoding(28591).GetBytes(text); - // Check debug level before processing byte array - if (StreamDebugging.TxStreamDebuggingIsEnabled) - Debug.Console(0, this, "Sending {0} characters of text: '{1}'", text.Length, ComTextHelper.GetDebugText(text)); + /// + /// SendText method + /// + public void SendText(string text) + { + var bytes = Encoding.GetEncoding(28591).GetBytes(text); + // Check debug level before processing byte array + this.PrintSentText(text); if (_client != null) - _client.SendData(bytes, bytes.Length); - } + _client.SendData(bytes, bytes.Length); + } - /// - /// SendEscapedText method - /// - public void SendEscapedText(string text) - { - var unescapedText = Regex.Replace(text, @"\\x([0-9a-fA-F][0-9a-fA-F])", s => - { - var hex = s.Groups[1].Value; - return ((char)Convert.ToByte(hex, 16)).ToString(); - }); - SendText(unescapedText); - } + /// + /// SendEscapedText method + /// + public void SendEscapedText(string text) + { + var unescapedText = Regex.Replace(text, @"\\x([0-9a-fA-F][0-9a-fA-F])", s => + { + var hex = s.Groups[1].Value; + return ((char)Convert.ToByte(hex, 16)).ToString(); + }); + SendText(unescapedText); + } /// /// Sends Bytes to the server /// /// - /// - /// SendBytes method - /// - public void SendBytes(byte[] bytes) - { + /// + /// SendBytes method + /// + public void SendBytes(byte[] bytes) + { if (StreamDebugging.TxStreamDebuggingIsEnabled) Debug.Console(0, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes)); if (_client != null) - _client.SendData(bytes, bytes.Length); - } + _client.SendData(bytes, bytes.Length); + } /// /// Socket Status Change Handler @@ -496,7 +489,7 @@ namespace PepperDash.Core /// /// void Client_SocketStatusChange(TCPClient client, SocketStatus clientSocketStatus) - { + { if (clientSocketStatus != SocketStatus.SOCKET_STATUS_CONNECTED) { Debug.Console(0, this, "Socket status change {0} ({1})", clientSocketStatus, ClientStatusText); @@ -505,68 +498,68 @@ namespace PepperDash.Core else { Debug.Console(1, this, "Socket status change {0} ({1})", clientSocketStatus, ClientStatusText); - _client.ReceiveDataAsync(Receive); + _client.ReceiveDataAsync(Receive); } - var handler = ConnectionChange; - if (handler != null) - ConnectionChange(this, new GenericSocketStatusChageEventArgs(this)); - } - } + var handler = ConnectionChange; + if (handler != null) + ConnectionChange(this, new GenericSocketStatusChageEventArgs(this)); + } + } - /// - /// Represents a TcpSshPropertiesConfig - /// - public class TcpSshPropertiesConfig - { + /// + /// Represents a TcpSshPropertiesConfig + /// + public class TcpSshPropertiesConfig + { /// /// Address to connect to /// [JsonProperty(Required = Required.Always)] - public string Address { get; set; } - + public string Address { get; set; } + /// /// Port to connect to /// - [JsonProperty(Required = Required.Always)] - public int Port { get; set; } - + [JsonProperty(Required = Required.Always)] + public int Port { get; set; } + /// /// Username credential /// - public string Username { get; set; } - /// - /// Gets or sets the Password - /// - public string Password { get; set; } + public string Username { get; set; } + /// + /// Gets or sets the Password + /// + public string Password { get; set; } - /// - /// Defaults to 32768 - /// - public int BufferSize { get; set; } + /// + /// Defaults to 32768 + /// + public int BufferSize { get; set; } - /// - /// Gets or sets the AutoReconnect - /// - public bool AutoReconnect { get; set; } + /// + /// Gets or sets the AutoReconnect + /// + public bool AutoReconnect { get; set; } - /// - /// Gets or sets the AutoReconnectIntervalMs - /// - public int AutoReconnectIntervalMs { get; set; } + /// + /// Gets or sets the AutoReconnectIntervalMs + /// + public int AutoReconnectIntervalMs { get; set; } /// /// Default constructor /// public TcpSshPropertiesConfig() - { - BufferSize = 32768; - AutoReconnect = true; - AutoReconnectIntervalMs = 5000; + { + BufferSize = 32768; + AutoReconnect = true; + AutoReconnectIntervalMs = 5000; Username = ""; Password = ""; - } + } - } + } } diff --git a/src/PepperDash.Core/Comm/GenericUdpServer.cs b/src/PepperDash.Core/Comm/GenericUdpServer.cs index 52ac627a..a713872a 100644 --- a/src/PepperDash.Core/Comm/GenericUdpServer.cs +++ b/src/PepperDash.Core/Comm/GenericUdpServer.cs @@ -124,7 +124,7 @@ namespace PepperDash.Core CrestronEnvironment.ProgramStatusEventHandler += new ProgramStatusEventHandler(CrestronEnvironment_ProgramStatusEventHandler); CrestronEnvironment.EthernetEventHandler += new EthernetEventHandler(CrestronEnvironment_EthernetEventHandler); } - + /// /// /// @@ -135,7 +135,7 @@ namespace PepperDash.Core public GenericUdpServer(string key, string address, int port, int bufferSize) : base(key) { - StreamDebugging = new CommunicationStreamDebugging(key); + StreamDebugging = new CommunicationStreamDebugging(key); Hostname = address; Port = port; BufferSize = bufferSize; @@ -180,7 +180,7 @@ namespace PepperDash.Core /// void CrestronEnvironment_ProgramStatusEventHandler(eProgramStatusEventType programEventType) { - if (programEventType != eProgramStatusEventType.Stopping) + if (programEventType != eProgramStatusEventType.Stopping) return; Debug.Console(1, this, "Program stopping. Disabling Server"); @@ -243,7 +243,7 @@ namespace PepperDash.Core /// public void Disconnect() { - if(Server != null) + if (Server != null) Server.DisableUDPServer(); IsConnected = false; @@ -265,7 +265,7 @@ namespace PepperDash.Core try { - if (numBytes <= 0) + if (numBytes <= 0) return; var sourceIp = Server.IPAddressLastMessageReceivedFrom; @@ -281,17 +281,13 @@ namespace PepperDash.Core var bytesHandler = BytesReceived; if (bytesHandler != null) { - if (StreamDebugging.RxStreamDebuggingIsEnabled) - { - Debug.Console(0, this, "Received {1} bytes: '{0}'", ComTextHelper.GetEscapedText(bytes), bytes.Length); - } + this.PrintReceivedBytes(bytes); bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); } var textHandler = TextReceived; if (textHandler != null) { - if (StreamDebugging.RxStreamDebuggingIsEnabled) - Debug.Console(0, this, "Received {1} characters of text: '{0}'", ComTextHelper.GetDebugText(str), str.Length); + this.PrintReceivedText(str); textHandler(this, new GenericCommMethodReceiveTextArgs(str)); } } @@ -318,8 +314,7 @@ namespace PepperDash.Core if (IsConnected && Server != null) { - if (StreamDebugging.TxStreamDebuggingIsEnabled) - Debug.Console(0, this, "Sending {0} characters of text: '{1}'", text.Length, ComTextHelper.GetDebugText(text)); + this.PrintSentText(text); Server.SendData(bytes, bytes.Length); } @@ -334,8 +329,7 @@ namespace PepperDash.Core /// public void SendBytes(byte[] bytes) { - if (StreamDebugging.TxStreamDebuggingIsEnabled) - Debug.Console(0, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes)); + this.PrintSentBytes(bytes); if (IsConnected && Server != null) Server.SendData(bytes, bytes.Length); @@ -343,11 +337,11 @@ namespace PepperDash.Core } - /// - /// Represents a GenericUdpReceiveTextExtraArgs - /// - public class GenericUdpReceiveTextExtraArgs : EventArgs - { + /// + /// Represents a GenericUdpReceiveTextExtraArgs + /// + public class GenericUdpReceiveTextExtraArgs : EventArgs + { /// /// /// @@ -359,7 +353,7 @@ namespace PepperDash.Core /// /// /// - public int Port { get; private set; } + public int Port { get; private set; } /// /// /// @@ -373,18 +367,18 @@ namespace PepperDash.Core /// /// public GenericUdpReceiveTextExtraArgs(string text, string ipAddress, int port, byte[] bytes) - { - Text = text; - IpAddress = ipAddress; - Port = port; - Bytes = bytes; - } + { + Text = text; + IpAddress = ipAddress; + Port = port; + Bytes = bytes; + } - /// - /// Stupid S+ Constructor - /// - public GenericUdpReceiveTextExtraArgs() { } - } + /// + /// Stupid S+ Constructor + /// + public GenericUdpReceiveTextExtraArgs() { } + } /// /// diff --git a/src/PepperDash.Core/Comm/StreamDebuggingExtensionMethods.cs b/src/PepperDash.Core/Comm/StreamDebuggingExtensionMethods.cs new file mode 100644 index 00000000..9fd7544d --- /dev/null +++ b/src/PepperDash.Core/Comm/StreamDebuggingExtensionMethods.cs @@ -0,0 +1,69 @@ +using System; +using Crestron.SimplSharp; + +namespace PepperDash.Core +{ + /// + /// Extension methods for stream debugging + /// + public static class StreamDebuggingExtensions + { + private static readonly string app = CrestronEnvironment.DevicePlatform == eDevicePlatform.Appliance ? $"App {InitialParametersClass.ApplicationNumber}" : $"{InitialParametersClass.RoomId}"; + + /// + /// Print the sent bytes to the console + /// + /// comms device + /// bytes to print + public static void PrintSentBytes(this IStreamDebugging comms, byte[] bytes) + { + if (!comms.StreamDebugging.TxStreamDebuggingIsEnabled) return; + + var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); + + CrestronConsole.PrintLine($"[{timestamp}][{app}][{comms.Key}] Sending {bytes.Length} bytes: '{ComTextHelper.GetEscapedText(bytes)}'"); + } + + /// + /// Print the received bytes to the console + /// + /// comms device + /// bytes to print + public static void PrintReceivedBytes(this IStreamDebugging comms, byte[] bytes) + { + if (!comms.StreamDebugging.RxStreamDebuggingIsEnabled) return; + + var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); + + CrestronConsole.PrintLine($"[{timestamp}][{app}][{comms.Key}] Received {bytes.Length} bytes: '{ComTextHelper.GetEscapedText(bytes)}'"); + } + + /// + /// Print the sent text to the console + /// + /// comms device + /// text to print + public static void PrintSentText(this IStreamDebugging comms, string text) + { + if (!comms.StreamDebugging.TxStreamDebuggingIsEnabled) return; + + var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); + + CrestronConsole.PrintLine($"[{timestamp}][{app}][{comms.Key}] Sending Text: '{ComTextHelper.GetDebugText(text)}'"); + } + + /// + /// Print the received text to the console + /// + /// comms device + /// text to print + public static void PrintReceivedText(this IStreamDebugging comms, string text) + { + if (!comms.StreamDebugging.RxStreamDebuggingIsEnabled) return; + + var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); + + CrestronConsole.PrintLine($"[{timestamp}][{app}][{comms.Key}] Received Text: '{ComTextHelper.GetDebugText(text)}'"); + } + } +} diff --git a/src/PepperDash.Core/Comm/eStreamDebuggingDataTypeSettings.cs b/src/PepperDash.Core/Comm/eStreamDebuggingDataTypeSettings.cs new file mode 100644 index 00000000..24bd18d5 --- /dev/null +++ b/src/PepperDash.Core/Comm/eStreamDebuggingDataTypeSettings.cs @@ -0,0 +1,24 @@ +using System; + +namespace PepperDash.Core +{ + /// + /// The available settings for stream debugging response types + /// + [Flags] + public enum eStreamDebuggingDataTypeSettings + { + /// + /// Debug data in byte format + /// + Bytes = 0, + /// + /// Debug data in text format + /// + Text = 1, + /// + /// Debug data in both byte and text formats + /// + Both = Bytes | Text, + } +} diff --git a/src/PepperDash.Core/Comm/eStreamDebuggingSetting.cs b/src/PepperDash.Core/Comm/eStreamDebuggingSetting.cs new file mode 100644 index 00000000..f9f7eb3f --- /dev/null +++ b/src/PepperDash.Core/Comm/eStreamDebuggingSetting.cs @@ -0,0 +1,28 @@ +using System; + +namespace PepperDash.Core +{ + /// + /// The available settings for stream debugging + /// + [Flags] + public enum eStreamDebuggingSetting + { + /// + /// Debug off + /// + Off = 0, + /// + /// Debug received data + /// + Rx = 1, + /// + /// Debug transmitted data + /// + Tx = 2, + /// + /// Debug both received and transmitted data + /// + Both = Rx | Tx + } +} diff --git a/src/PepperDash.Core/CommunicationExtras.cs b/src/PepperDash.Core/CommunicationExtras.cs index d16ea761..a8bc57d3 100644 --- a/src/PepperDash.Core/CommunicationExtras.cs +++ b/src/PepperDash.Core/CommunicationExtras.cs @@ -1,10 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using Crestron.SimplSharp; using Crestron.SimplSharp.CrestronSockets; -using System.Text.RegularExpressions; using Newtonsoft.Json; namespace PepperDash.Core @@ -42,7 +39,7 @@ namespace PepperDash.Core /// Defines the contract for IBasicCommunication /// public interface IBasicCommunication : ICommunicationReceiver - { + { /// /// Send text to the device /// @@ -54,7 +51,7 @@ namespace PepperDash.Core /// /// void SendBytes(byte[] bytes); - } + } /// /// Represents a device that implements IBasicCommunication and IStreamDebugging @@ -67,7 +64,7 @@ namespace PepperDash.Core /// /// Represents a device with stream debugging capablities /// - public interface IStreamDebugging + public interface IStreamDebugging : IKeyed { /// /// Object to enable stream debugging @@ -76,12 +73,12 @@ namespace PepperDash.Core CommunicationStreamDebugging StreamDebugging { get; } } - /// - /// For IBasicCommunication classes that have SocketStatus. GenericSshClient, - /// GenericTcpIpClient - /// - public interface ISocketStatus : IBasicCommunication - { + /// + /// For IBasicCommunication classes that have SocketStatus. GenericSshClient, + /// GenericTcpIpClient + /// + public interface ISocketStatus : IBasicCommunication + { /// /// Notifies of socket status changes /// @@ -93,7 +90,7 @@ namespace PepperDash.Core [JsonProperty("clientStatus")] [JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] SocketStatus ClientStatus { get; } - } + } /// /// Describes a device that implements ISocketStatus and IStreamDebugging @@ -107,24 +104,24 @@ namespace PepperDash.Core /// Describes a device that can automatically attempt to reconnect /// public interface IAutoReconnect - { + { /// /// Enable automatic recconnect /// [JsonProperty("autoReconnect")] - bool AutoReconnect { get; set; } + bool AutoReconnect { get; set; } /// /// Interval in ms to attempt automatic recconnections /// [JsonProperty("autoReconnectIntervalMs")] - int AutoReconnectIntervalMs { get; set; } - } + int AutoReconnectIntervalMs { get; set; } + } - /// - /// - /// - public enum eGenericCommMethodStatusChangeType - { + /// + /// + /// + public enum eGenericCommMethodStatusChangeType + { /// /// Connected /// @@ -133,45 +130,45 @@ namespace PepperDash.Core /// Disconnected /// Disconnected - } + } - /// - /// This delegate defines handler for IBasicCommunication status changes - /// - /// Device firing the status change - /// - public delegate void GenericCommMethodStatusHandler(IBasicCommunication comm, eGenericCommMethodStatusChangeType status); + /// + /// This delegate defines handler for IBasicCommunication status changes + /// + /// Device firing the status change + /// + public delegate void GenericCommMethodStatusHandler(IBasicCommunication comm, eGenericCommMethodStatusChangeType status); - /// - /// - /// - public class GenericCommMethodReceiveBytesArgs : EventArgs - { - /// - /// Gets or sets the Bytes - /// - public byte[] Bytes { get; private set; } + /// + /// + /// + public class GenericCommMethodReceiveBytesArgs : EventArgs + { + /// + /// Gets or sets the Bytes + /// + public byte[] Bytes { get; private set; } /// /// /// /// public GenericCommMethodReceiveBytesArgs(byte[] bytes) - { - Bytes = bytes; - } + { + Bytes = bytes; + } - /// - /// S+ Constructor - /// - public GenericCommMethodReceiveBytesArgs() { } - } + /// + /// S+ Constructor + /// + public GenericCommMethodReceiveBytesArgs() { } + } - /// - /// - /// - public class GenericCommMethodReceiveTextArgs : EventArgs - { + /// + /// + /// + public class GenericCommMethodReceiveTextArgs : EventArgs + { /// /// /// @@ -185,9 +182,9 @@ namespace PepperDash.Core /// /// public GenericCommMethodReceiveTextArgs(string text) - { - Text = text; - } + { + Text = text; + } /// /// @@ -195,59 +192,14 @@ namespace PepperDash.Core /// /// public GenericCommMethodReceiveTextArgs(string text, string delimiter) - :this(text) + : this(text) { Delimiter = delimiter; } - /// - /// S+ Constructor - /// - public GenericCommMethodReceiveTextArgs() { } - } - - - - /// - /// - /// - public class ComTextHelper - { /// - /// Gets escaped text for a byte array + /// S+ Constructor /// - /// - /// - public static string GetEscapedText(byte[] bytes) - { - return String.Concat(bytes.Select(b => string.Format(@"[{0:X2}]", (int)b)).ToArray()); - } - - /// - /// Gets escaped text for a string - /// - /// - /// - /// - /// GetEscapedText method - /// - public static string GetEscapedText(string text) - { - var bytes = Encoding.GetEncoding(28591).GetBytes(text); - return String.Concat(bytes.Select(b => string.Format(@"[{0:X2}]", (int)b)).ToArray()); - } - - /// - /// Gets debug text for a string - /// - /// - /// - /// - /// GetDebugText method - /// - public static string GetDebugText(string text) - { - return Regex.Replace(text, @"[^\u0020-\u007E]", a => GetEscapedText(a.Value)); - } - } + public GenericCommMethodReceiveTextArgs() { } + } } \ No newline at end of file diff --git a/src/PepperDash.Essentials.Core/Comm and IR/CecPortController.cs b/src/PepperDash.Essentials.Core/Comm and IR/CecPortController.cs index 7dacce5c..2dd4f2ba 100644 --- a/src/PepperDash.Essentials.Core/Comm and IR/CecPortController.cs +++ b/src/PepperDash.Essentials.Core/Comm and IR/CecPortController.cs @@ -12,15 +12,15 @@ using Serilog.Events; namespace PepperDash.Essentials.Core { - /// - /// Represents a CecPortController - /// - public class CecPortController : Device, IBasicCommunicationWithStreamDebugging + /// + /// Represents a CecPortController + /// + public class CecPortController : Device, IBasicCommunicationWithStreamDebugging { - /// - /// Gets or sets the StreamDebugging - /// - public CommunicationStreamDebugging StreamDebugging { get; private set; } + /// + /// Gets or sets the StreamDebugging + /// + public CommunicationStreamDebugging StreamDebugging { get; private set; } public event EventHandler BytesReceived; public event EventHandler TextReceived; @@ -33,16 +33,16 @@ namespace PepperDash.Essentials.Core ICec Port; public CecPortController(string key, Func postActivationFunc, - EssentialsControlPropertiesConfig config):base(key) + EssentialsControlPropertiesConfig config) : base(key) { - StreamDebugging = new CommunicationStreamDebugging(key); + StreamDebugging = new CommunicationStreamDebugging(key); AddPostActivationAction(() => { Port = postActivationFunc(config); Port.StreamCec.CecChange += StreamCec_CecChange; - }); + }); } public CecPortController(string key, ICec port) @@ -58,27 +58,25 @@ namespace PepperDash.Essentials.Core if (args.EventId == CecEventIds.CecMessageReceivedEventId) OnDataReceived(cecDevice.Received.StringValue); else if (args.EventId == CecEventIds.ErrorFeedbackEventId) - if(cecDevice.ErrorFeedback.BoolValue) + if (cecDevice.ErrorFeedback.BoolValue) Debug.LogMessage(LogEventLevel.Verbose, this, "CEC NAK Error"); } void OnDataReceived(string s) { - var bytesHandler = BytesReceived; + var bytesHandler = BytesReceived; if (bytesHandler != null) { var bytes = Encoding.GetEncoding(28591).GetBytes(s); - if (StreamDebugging.RxStreamDebuggingIsEnabled) - Debug.LogMessage(LogEventLevel.Information, this, "Received: '{0}'", ComTextHelper.GetEscapedText(bytes)); + this.PrintReceivedBytes(bytes); bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); } var textHandler = TextReceived; - if (textHandler != null) - { - if (StreamDebugging.RxStreamDebuggingIsEnabled) - Debug.LogMessage(LogEventLevel.Information, this, "Received: '{0}'", s); - textHandler(this, new GenericCommMethodReceiveTextArgs(s)); - } + if (textHandler != null) + { + this.PrintReceivedText(s); + textHandler(this, new GenericCommMethodReceiveTextArgs(s)); + } } #region IBasicCommunication Members @@ -90,8 +88,7 @@ namespace PepperDash.Essentials.Core { if (Port == null) return; - if (StreamDebugging.TxStreamDebuggingIsEnabled) - Debug.LogMessage(LogEventLevel.Information, this, "Sending {0} characters of text: '{1}'", text.Length, text); + this.PrintSentText(text); Port.StreamCec.Send.StringValue = text; } @@ -103,8 +100,8 @@ namespace PepperDash.Essentials.Core if (Port == null) return; var text = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); - if (StreamDebugging.TxStreamDebuggingIsEnabled) - Debug.LogMessage(LogEventLevel.Information, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes)); + this.PrintSentBytes(bytes); + Debug.LogMessage(LogEventLevel.Information, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes)); Port.StreamCec.Send.StringValue = text; } diff --git a/src/PepperDash.Essentials.Core/Comm and IR/ComPortController.cs b/src/PepperDash.Essentials.Core/Comm and IR/ComPortController.cs index ba599ead..d3c46196 100644 --- a/src/PepperDash.Essentials.Core/Comm and IR/ComPortController.cs +++ b/src/PepperDash.Essentials.Core/Comm and IR/ComPortController.cs @@ -23,10 +23,10 @@ namespace PepperDash.Essentials.Core /// Event fired when bytes are received /// public event EventHandler BytesReceived; - + /// - /// Event fired when text is received - /// + /// Event fired when text is received + /// public event EventHandler TextReceived; /// @@ -38,12 +38,12 @@ namespace PepperDash.Essentials.Core ComPort.ComPortSpec Spec; /// - /// Constructor - /// - /// - /// - /// - /// + /// Constructor + /// + /// + /// + /// + /// public ComPortController(string key, Func postActivationFunc, ComPort.ComPortSpec spec, EssentialsControlPropertiesConfig config) : base(key) { @@ -100,7 +100,7 @@ namespace PepperDash.Essentials.Core return; // false } } - + var specResult = Port.SetComPortSpec(Spec); if (specResult != 0) { @@ -165,16 +165,14 @@ namespace PepperDash.Essentials.Core if (bytesHandler != null) { var bytes = Encoding.GetEncoding(28591).GetBytes(s); - if (StreamDebugging.RxStreamDebuggingIsEnabled) - Debug.LogMessage(LogEventLevel.Information, this, "Received: '{0}'", ComTextHelper.GetEscapedText(bytes)); + this.PrintReceivedBytes(bytes); bytesHandler(this, new GenericCommMethodReceiveBytesArgs(bytes)); eventSubscribed = true; } var textHandler = TextReceived; if (textHandler != null) { - if (StreamDebugging.RxStreamDebuggingIsEnabled) - Debug.LogMessage(LogEventLevel.Information, this, "Received: '{0}'", s); + this.PrintReceivedText(s); textHandler(this, new GenericCommMethodReceiveTextArgs(s)); eventSubscribed = true; } @@ -201,8 +199,7 @@ namespace PepperDash.Essentials.Core if (Port == null) return; - if (StreamDebugging.TxStreamDebuggingIsEnabled) - Debug.LogMessage(LogEventLevel.Information, this, "Sending {0} characters of text: '{1}'", text.Length, text); + this.PrintSentText(text); Port.Send(text); } @@ -214,8 +211,7 @@ namespace PepperDash.Essentials.Core if (Port == null) return; var text = Encoding.GetEncoding(28591).GetString(bytes, 0, bytes.Length); - if (StreamDebugging.TxStreamDebuggingIsEnabled) - Debug.LogMessage(LogEventLevel.Information, this, "Sending {0} bytes: '{1}'", bytes.Length, ComTextHelper.GetEscapedText(bytes)); + this.PrintSentBytes(bytes); Port.Send(text); } diff --git a/src/PepperDash.Essentials.Core/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs b/src/PepperDash.Essentials.Core/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs index 72758b0e..7c6aea26 100644 --- a/src/PepperDash.Essentials.Core/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs +++ b/src/PepperDash.Essentials.Core/Web/RequestHandlers/SetDeviceStreamDebugRequestHandler.cs @@ -6,9 +6,9 @@ using PepperDash.Core.Web.RequestHandlers; namespace PepperDash.Essentials.Core.Web.RequestHandlers { - /// - /// Represents a SetDeviceStreamDebugRequestHandler - /// + /// + /// Represents a SetDeviceStreamDebugRequestHandler + /// public class SetDeviceStreamDebugRequestHandler : WebApiBaseRequestHandler { /// @@ -122,23 +122,23 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers return; } - if (!(DeviceManager.GetDeviceForKey(body.DeviceKey) is IStreamDebugging device)) - { - context.Response.StatusCode = 404; - context.Response.StatusDescription = "Not Found"; - context.Response.End(); + if (!(DeviceManager.GetDeviceForKey(body.DeviceKey) is IStreamDebugging device)) + { + context.Response.StatusCode = 404; + context.Response.StatusDescription = "Not Found"; + context.Response.End(); - return; - } + return; + } - eStreamDebuggingSetting debugSetting; + eStreamDebuggingSetting debugSetting; try { - debugSetting = (eStreamDebuggingSetting) Enum.Parse(typeof (eStreamDebuggingSetting), body.Setting, true); + debugSetting = (eStreamDebuggingSetting)Enum.Parse(typeof(eStreamDebuggingSetting), body.Setting, true); } catch (Exception ex) { - Debug.LogMessage(ex, "Exception handling set debug request"); + Debug.LogMessage(ex, "Exception handling set debug request"); context.Response.StatusCode = 500; context.Response.StatusDescription = "Internal Server Error"; context.Response.End(); @@ -164,7 +164,7 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers } catch (Exception ex) { - Debug.LogMessage(ex, "Exception handling set debug request"); + Debug.LogMessage(ex, "Exception handling set debug request"); context.Response.StatusCode = 500; context.Response.StatusDescription = "Internal Server Error"; context.Response.End(); @@ -198,21 +198,21 @@ namespace PepperDash.Essentials.Core.Web.RequestHandlers public class SetDeviceStreamDebugConfig { [JsonProperty("deviceKey", NullValueHandling = NullValueHandling.Include)] - /// - /// Gets or sets the DeviceKey - /// + /// + /// Gets or sets the DeviceKey + /// public string DeviceKey { get; set; } [JsonProperty("setting", NullValueHandling = NullValueHandling.Include)] - /// - /// Gets or sets the Setting - /// + /// + /// Gets or sets the Setting + /// public string Setting { get; set; } [JsonProperty("timeout")] - /// - /// Gets or sets the Timeout - /// + /// + /// Gets or sets the Timeout + /// public int Timeout { get; set; } public SetDeviceStreamDebugConfig()