diff --git a/Pepperdash Core/Pepperdash Core/Comm/EventArgs.cs b/Pepperdash Core/Pepperdash Core/Comm/EventArgs.cs index e9e9f1f..ecf6db8 100644 --- a/Pepperdash Core/Pepperdash Core/Comm/EventArgs.cs +++ b/Pepperdash Core/Pepperdash Core/Comm/EventArgs.cs @@ -76,6 +76,14 @@ namespace PepperDash.Core public class GenericTcpServerCommMethodReceiveTextArgs : EventArgs { public uint ReceivedFromClientIndex { get; private set; } + public ushort ReceivedFromClientIndexShort + { + get + { + return (ushort)ReceivedFromClientIndex; + } + } + public string Text { get; private set; } public GenericTcpServerCommMethodReceiveTextArgs(string text) diff --git a/Pepperdash Core/Pepperdash Core/Comm/GenericSshClient.cs b/Pepperdash Core/Pepperdash Core/Comm/GenericSshClient.cs index 6af5d7b..8a6e9fd 100644 --- a/Pepperdash Core/Pepperdash Core/Comm/GenericSshClient.cs +++ b/Pepperdash Core/Pepperdash Core/Comm/GenericSshClient.cs @@ -221,7 +221,12 @@ namespace PepperDash.Core Debug.Console(1, this, "Creating new SshClient"); ConnectionInfo connectionInfo = new ConnectionInfo(Hostname, Port, Username, pauth, kauth); - Client = new SshClient(connectionInfo); + + if (Client == null) + { + Client = new SshClient(connectionInfo); + } + Client.ErrorOccurred -= Client_ErrorOccurred; Client.ErrorOccurred += Client_ErrorOccurred; //You can do it! diff --git a/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpClient.cs b/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpClient.cs index 1abdb25..b8b715f 100644 --- a/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpClient.cs +++ b/Pepperdash Core/Pepperdash Core/Comm/GenericTcpIpClient.cs @@ -273,8 +273,6 @@ namespace PepperDash.Core if (Client == null) { - - Client = new TCPClient(Hostname, Port, BufferSize); Client.SocketStatusChange += Client_SocketStatusChange; } diff --git a/Pepperdash Core/Pepperdash Core/EventArgs.cs b/Pepperdash Core/Pepperdash Core/EventArgs.cs new file mode 100644 index 0000000..6def673 --- /dev/null +++ b/Pepperdash Core/Pepperdash Core/EventArgs.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash.Core +{ + /// + /// Bool change event args + /// + public class BoolChangeEventArgs : EventArgs + { + /// + /// Boolean state property + /// + public bool State { get; set; } + + /// + /// Boolean ushort value property + /// + public ushort IntValue { get { return (ushort)(State ? 1 : 0); } } + + /// + /// Boolean change event args type + /// + public ushort Type { get; set; } + + /// + /// Boolean change event args index + /// + public ushort Index { get; set; } + + /// + /// Constructor + /// + public BoolChangeEventArgs() + { + + } + + /// + /// Constructor overload + /// + /// + /// + public BoolChangeEventArgs(bool state, ushort type) + { + State = state; + Type = type; + } + + /// + /// Constructor overload + /// + /// + /// + /// + public BoolChangeEventArgs(bool state, ushort type, ushort index) + { + State = state; + Type = type; + Index = index; + } + } + + /// + /// Ushort change event args + /// + public class UshrtChangeEventArgs : EventArgs + { + /// + /// Ushort change event args integer value + /// + public ushort IntValue { get; set; } + + /// + /// Ushort change event args type + /// + public ushort Type { get; set; } + + /// + /// Ushort change event args index + /// + public ushort Index { get; set; } + + /// + /// Constructor + /// + public UshrtChangeEventArgs() + { + + } + + /// + /// Constructor overload + /// + /// + /// + public UshrtChangeEventArgs(ushort intValue, ushort type) + { + IntValue = intValue; + Type = type; + } + + /// + /// Constructor overload + /// + /// + /// + /// + public UshrtChangeEventArgs(ushort intValue, ushort type, ushort index) + { + IntValue = intValue; + Type = type; + Index = index; + } + } + + /// + /// String change event args + /// + public class StringChangeEventArgs : EventArgs + { + /// + /// String change event args value + /// + public string StringValue { get; set; } + + /// + /// String change event args type + /// + public ushort Type { get; set; } + + /// + /// string change event args index + /// + public ushort Index { get; set; } + + /// + /// Constructor + /// + public StringChangeEventArgs() + { + + } + + /// + /// Constructor overload + /// + /// + /// + public StringChangeEventArgs(string stringValue, ushort type) + { + StringValue = stringValue; + Type = type; + } + + /// + /// Constructor overload + /// + /// + /// + /// + public StringChangeEventArgs(string stringValue, ushort type, ushort index) + { + StringValue = stringValue; + Type = type; + Index = index; + } + } +} \ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/GenericRESTfulCommunications/Constants.cs b/Pepperdash Core/Pepperdash Core/GenericRESTfulCommunications/Constants.cs new file mode 100644 index 0000000..9df43f0 --- /dev/null +++ b/Pepperdash Core/Pepperdash Core/GenericRESTfulCommunications/Constants.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash.Core.GenericRESTfulCommunications +{ + /// + /// Constants + /// + public class GenericRESTfulConstants + { + /// + /// Generic boolean change + /// + public const ushort BoolValueChange = 1; + /// + /// Generic Ushort change + /// + public const ushort UshrtValueChange = 101; + /// + /// Response Code Ushort change + /// + public const ushort ResponseCodeChange = 102; + /// + /// Generic String chagne + /// + public const ushort StringValueChange = 201; + /// + /// Response string change + /// + public const ushort ResponseStringChange = 202; + /// + /// Error string change + /// + public const ushort ErrorStringChange = 203; + } +} \ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/GenericRESTfulCommunications/GenericRESTfulClient.cs b/Pepperdash Core/Pepperdash Core/GenericRESTfulCommunications/GenericRESTfulClient.cs new file mode 100644 index 0000000..7d8df61 --- /dev/null +++ b/Pepperdash Core/Pepperdash Core/GenericRESTfulCommunications/GenericRESTfulClient.cs @@ -0,0 +1,253 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharp.Net.Http; +using Crestron.SimplSharp.Net.Https; + +namespace PepperDash.Core.GenericRESTfulCommunications +{ + /// + /// Generic RESTful communication class + /// + public class GenericRESTfulClient + { + /// + /// Boolean event handler + /// + public event EventHandler BoolChange; + /// + /// Ushort event handler + /// + public event EventHandler UshrtChange; + /// + /// String event handler + /// + public event EventHandler StringChange; + + /// + /// Constructor + /// + public GenericRESTfulClient() + { + + } + + /// + /// Generic RESTful submit request + /// + /// + /// + /// + /// + /// + public void SubmitRequest(string url, ushort port, ushort requestType, string contentType, string username, string password) + { + if (url.StartsWith("https:", StringComparison.OrdinalIgnoreCase)) + { + SubmitRequestHttps(url, port, requestType, contentType, username, password); + } + else if (url.StartsWith("http:", StringComparison.OrdinalIgnoreCase)) + { + SubmitRequestHttp(url, port, requestType, contentType, username, password); + } + else + { + OnStringChange(string.Format("Invalid URL {0}", url), 0, GenericRESTfulConstants.ErrorStringChange); + } + } + + /// + /// Private HTTP submit request + /// + /// + /// + /// + /// + /// + private void SubmitRequestHttp(string url, ushort port, ushort requestType, string contentType, string username, string password) + { + try + { + HttpClient client = new HttpClient(); + HttpClientRequest request = new HttpClientRequest(); + HttpClientResponse response; + + client.KeepAlive = false; + + if(port >= 1 || port <= 65535) + client.Port = port; + else + client.Port = 80; + + var authorization = ""; + if (!string.IsNullOrEmpty(username)) + authorization = EncodeBase64(username, password); + + if (!string.IsNullOrEmpty(authorization)) + request.Header.SetHeaderValue("Authorization", authorization); + + if (!string.IsNullOrEmpty(contentType)) + request.Header.ContentType = contentType; + + request.Url.Parse(url); + request.RequestType = (Crestron.SimplSharp.Net.Http.RequestType)requestType; + + response = client.Dispatch(request); + + CrestronConsole.PrintLine(string.Format("SubmitRequestHttp Response[{0}]: {1}", response.Code, response.ContentString.ToString())); + + if (!string.IsNullOrEmpty(response.ContentString.ToString())) + OnStringChange(response.ContentString.ToString(), 0, GenericRESTfulConstants.ResponseStringChange); + + if (response.Code > 0) + OnUshrtChange((ushort)response.Code, 0, GenericRESTfulConstants.ResponseCodeChange); + } + catch (Exception e) + { + //var msg = string.Format("SubmitRequestHttp({0}, {1}, {2}) failed:{3}", url, port, requestType, e.Message); + //CrestronConsole.PrintLine(msg); + //ErrorLog.Error(msg); + + CrestronConsole.PrintLine(e.Message); + OnStringChange(e.Message, 0, GenericRESTfulConstants.ErrorStringChange); + } + } + + /// + /// Private HTTPS submit request + /// + /// + /// + /// + /// + /// + private void SubmitRequestHttps(string url, ushort port, ushort requestType, string contentType, string username, string password) + { + try + { + HttpsClient client = new HttpsClient(); + HttpsClientRequest request = new HttpsClientRequest(); + HttpsClientResponse response; + + client.KeepAlive = false; + client.HostVerification = false; + client.PeerVerification = false; + + var authorization = ""; + if (!string.IsNullOrEmpty(username)) + authorization = EncodeBase64(username, password); + + if (!string.IsNullOrEmpty(authorization)) + request.Header.SetHeaderValue("Authorization", authorization); + + if (!string.IsNullOrEmpty(contentType)) + request.Header.ContentType = contentType; + + request.Url.Parse(url); + request.RequestType = (Crestron.SimplSharp.Net.Https.RequestType)requestType; + + response = client.Dispatch(request); + + CrestronConsole.PrintLine(string.Format("SubmitRequestHttp Response[{0}]: {1}", response.Code, response.ContentString.ToString())); + + if(!string.IsNullOrEmpty(response.ContentString.ToString())) + OnStringChange(response.ContentString.ToString(), 0, GenericRESTfulConstants.ResponseStringChange); + + if(response.Code > 0) + OnUshrtChange((ushort)response.Code, 0, GenericRESTfulConstants.ResponseCodeChange); + + } + catch (Exception e) + { + //var msg = string.Format("SubmitRequestHttps({0}, {1}, {2}, {3}, {4}) failed:{5}", url, port, requestType, username, password, e.Message); + //CrestronConsole.PrintLine(msg); + //ErrorLog.Error(msg); + + CrestronConsole.PrintLine(e.Message); + OnStringChange(e.Message, 0, GenericRESTfulConstants.ErrorStringChange); + } + } + + /// + /// Private method to encode username and password to Base64 string + /// + /// + /// + /// authorization + private string EncodeBase64(string username, string password) + { + var authorization = ""; + + try + { + if (!string.IsNullOrEmpty(username)) + { + string base64String = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(string.Format("{0}:{1}", username, password))); + authorization = string.Format("Basic {0}", base64String); + } + } + catch (Exception e) + { + var msg = string.Format("EncodeBase64({0}, {1}) failed:\r{2}", username, password, e); + CrestronConsole.PrintLine(msg); + ErrorLog.Error(msg); + return "" ; + } + + return authorization; + } + + /// + /// Protected method to handle boolean change events + /// + /// + /// + /// + protected void OnBoolChange(bool state, ushort index, ushort type) + { + var handler = BoolChange; + if (handler != null) + { + var args = new BoolChangeEventArgs(state, type); + args.Index = index; + BoolChange(this, args); + } + } + + /// + /// Protected mehtod to handle ushort change events + /// + /// + /// + /// + protected void OnUshrtChange(ushort value, ushort index, ushort type) + { + var handler = UshrtChange; + if (handler != null) + { + var args = new UshrtChangeEventArgs(value, type); + args.Index = index; + UshrtChange(this, args); + } + } + + /// + /// Protected method to handle string change events + /// + /// + /// + /// + protected void OnStringChange(string value, ushort index, ushort type) + { + var handler = StringChange; + if (handler != null) + { + var args = new StringChangeEventArgs(value, type); + args.Index = index; + StringChange(this, args); + } + } + } +} \ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/JsonStandardObjects/EventArgs and Constants.cs b/Pepperdash Core/Pepperdash Core/JsonStandardObjects/EventArgs and Constants.cs new file mode 100644 index 0000000..2bac226 --- /dev/null +++ b/Pepperdash Core/Pepperdash Core/JsonStandardObjects/EventArgs and Constants.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash.Core.JsonStandardObjects +{ + /// + /// Constants for simpl modules + /// + public class JsonStandardDeviceConstants + { + /// + /// Json object evaluated constant + /// + public const ushort JsonObjectEvaluated = 2; + + /// + /// Json object changed constant + /// + public const ushort JsonObjectChanged = 104; + } + + /// + /// + /// + public class DeviceChangeEventArgs : EventArgs + { + /// + /// Device change event args object + /// + public DeviceConfig Device { get; set; } + + /// + /// Device change event args type + /// + public ushort Type { get; set; } + + /// + /// Device change event args index + /// + public ushort Index { get; set; } + + /// + /// Default constructor + /// + public DeviceChangeEventArgs() + { + + } + + /// + /// Constructor overload + /// + /// + /// + public DeviceChangeEventArgs(DeviceConfig device, ushort type) + { + Device = device; + Type = type; + } + + /// + /// Constructor overload + /// + /// + /// + /// + public DeviceChangeEventArgs(DeviceConfig device, ushort type, ushort index) + { + Device = device; + Type = type; + Index = index; + } + } +} \ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/JsonStandardObjects/JsonToSimplDevice.cs b/Pepperdash Core/Pepperdash Core/JsonStandardObjects/JsonToSimplDevice.cs new file mode 100644 index 0000000..eef68f2 --- /dev/null +++ b/Pepperdash Core/Pepperdash Core/JsonStandardObjects/JsonToSimplDevice.cs @@ -0,0 +1,186 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using PepperDash.Core.JsonToSimpl; + +namespace PepperDash.Core.JsonStandardObjects +{ + /// + /// Device class + /// + public class DeviceConfig + { + /// + /// JSON config key property + /// + public string key { get; set; } + /// + /// JSON config name property + /// + public string name { get; set; } + /// + /// JSON config type property + /// + public string type { get; set; } + /// + /// JSON config properties + /// + public PropertiesConfig properties { get; set; } + + /// + /// Bool change event handler + /// + public event EventHandler BoolChange; + /// + /// Ushort change event handler + /// + public event EventHandler UshrtChange; + /// + /// String change event handler + /// + public event EventHandler StringChange; + /// + /// Object change event handler + /// + public event EventHandler DeviceChange; + + /// + /// Constructor + /// + public DeviceConfig() + { + properties = new PropertiesConfig(); + } + + /// + /// Initialize method + /// + /// + /// + public void Initialize(string uniqueID, string deviceKey) + { + // S+ set EvaluateFb low + OnBoolChange(false, 0, JsonStandardDeviceConstants.JsonObjectEvaluated); + // validate parameters + if (string.IsNullOrEmpty(uniqueID) || string.IsNullOrEmpty(deviceKey)) + { + Debug.Console(1, "UniqueID ({0} or key ({1} is null or empty", uniqueID, deviceKey); + // S+ set EvaluteFb high + OnBoolChange(true, 0, JsonStandardDeviceConstants.JsonObjectEvaluated); + return; + } + + key = deviceKey; + + try + { + // get the file using the unique ID + JsonToSimplMaster jsonMaster = J2SGlobal.GetMasterByFile(uniqueID); + if (jsonMaster == null) + { + Debug.Console(1, "Could not find JSON file with uniqueID {0}", uniqueID); + return; + } + + // get the device configuration using the key + var devices = jsonMaster.JsonObject.ToObject().devices; + var device = devices.FirstOrDefault(d => d.key.Equals(key)); + if (device == null) + { + Debug.Console(1, "Could not find device with key {0}", key); + return; + } + OnObjectChange(device, 0, JsonStandardDeviceConstants.JsonObjectChanged); + + var index = devices.IndexOf(device); + OnStringChange(string.Format("devices[{0}]", index), 0, JsonToSimplConstants.FullPathToArrayChange); + } + catch (Exception e) + { + var msg = string.Format("Device {0} lookup failed:\r{1}", key, e); + CrestronConsole.PrintLine(msg); + ErrorLog.Error(msg); + } + finally + { + // S+ set EvaluteFb high + OnBoolChange(true, 0, JsonStandardDeviceConstants.JsonObjectEvaluated); + } + } + + #region EventHandler Helpers + + /// + /// BoolChange event handler helper + /// + /// + /// + /// + protected void OnBoolChange(bool state, ushort index, ushort type) + { + var handler = BoolChange; + if (handler != null) + { + var args = new BoolChangeEventArgs(state, type); + args.Index = index; + BoolChange(this, args); + } + } + + /// + /// UshrtChange event handler helper + /// + /// + /// + /// + protected void OnUshrtChange(ushort state, ushort index, ushort type) + { + var handler = UshrtChange; + if (handler != null) + { + var args = new UshrtChangeEventArgs(state, type); + args.Index = index; + UshrtChange(this, args); + } + } + + /// + /// StringChange event handler helper + /// + /// + /// + /// + protected void OnStringChange(string value, ushort index, ushort type) + { + var handler = StringChange; + if (handler != null) + { + var args = new StringChangeEventArgs(value, type); + args.Index = index; + StringChange(this, args); + } + } + + /// + /// ObjectChange event handler helper + /// + /// + /// + /// + protected void OnObjectChange(DeviceConfig device, ushort index, ushort type) + { + if (DeviceChange != null) + { + var args = new DeviceChangeEventArgs(device, type); + args.Index = index; + DeviceChange(this, args); + } + } + + #endregion EventHandler Helpers + } +} \ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/JsonStandardObjects/JsonToSimplDeviceConfig.cs b/Pepperdash Core/Pepperdash Core/JsonStandardObjects/JsonToSimplDeviceConfig.cs new file mode 100644 index 0000000..92e9f03 --- /dev/null +++ b/Pepperdash Core/Pepperdash Core/JsonStandardObjects/JsonToSimplDeviceConfig.cs @@ -0,0 +1,158 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash.Core.JsonStandardObjects +{ + /* + Convert JSON snippt to C#: http://json2csharp.com/# + + JSON Snippet: + { + "devices": [ + { + "key": "deviceKey", + "name": "deviceName", + "type": "deviceType", + "properties": { + "deviceId": 1, + "enabled": true, + "control": { + "method": "methodName", + "controlPortDevKey": "deviceControlPortDevKey", + "controlPortNumber": 1, + "comParams": { + "baudRate": 9600, + "dataBits": 8, + "stopBits": 1, + "parity": "None", + "protocol": "RS232", + "hardwareHandshake": "None", + "softwareHandshake": "None", + "pacing": 0 + }, + "tcpSshProperties": { + "address": "172.22.1.101", + "port": 23, + "username": "user01", + "password": "password01", + "autoReconnect": false, + "autoReconnectIntervalMs": 10000 + } + } + } + } + ] + } + */ + /// + /// Device communication parameter class + /// + public class ComParamsConfig + { + public int baudRate { get; set; } + public int dataBits { get; set; } + public int stopBits { get; set; } + public string parity { get; set; } + public string protocol { get; set; } + public string hardwareHandshake { get; set; } + public string softwareHandshake { get; set; } + public int pacing { get; set; } + + // convert properties for simpl + public ushort simplBaudRate { get { return Convert.ToUInt16(baudRate); } } + public ushort simplDataBits { get { return Convert.ToUInt16(dataBits); } } + public ushort simplStopBits { get { return Convert.ToUInt16(stopBits); } } + public ushort simplPacing { get { return Convert.ToUInt16(pacing); } } + + /// + /// Constructor + /// + public ComParamsConfig() + { + + } + } + + /// + /// Device TCP/SSH properties class + /// + public class TcpSshPropertiesConfig + { + public string address { get; set; } + public int port { get; set; } + public string username { get; set; } + public string password { get; set; } + public bool autoReconnect { get; set; } + public int autoReconnectIntervalMs { get; set; } + + // convert properties for simpl + public ushort simplPort { get { return Convert.ToUInt16(port); } } + public ushort simplAutoReconnect { get { return (ushort)(autoReconnect ? 1 : 0); } } + public ushort simplAutoReconnectIntervalMs { get { return Convert.ToUInt16(autoReconnectIntervalMs); } } + + /// + /// Constructor + /// + public TcpSshPropertiesConfig() + { + + } + } + + /// + /// Device control class + /// + public class ControlConfig + { + public string method { get; set; } + public string controlPortDevKey { get; set; } + public int controlPortNumber { get; set; } + public ComParamsConfig comParams { get; set; } + public TcpSshPropertiesConfig tcpSshProperties { get; set; } + + // convert properties for simpl + public ushort simplControlPortNumber { get { return Convert.ToUInt16(controlPortNumber); } } + + /// + /// Constructor + /// + public ControlConfig() + { + comParams = new ComParamsConfig(); + tcpSshProperties = new TcpSshPropertiesConfig(); + } + } + + /// + /// Device properties class + /// + public class PropertiesConfig + { + public int deviceId { get; set; } + public bool enabled { get; set; } + public ControlConfig control { get; set; } + + // convert properties for simpl + public ushort simplDeviceId { get { return Convert.ToUInt16(deviceId); } } + public ushort simplEnabled { get { return (ushort)(enabled ? 1 : 0); } } + + /// + /// Constructor + /// + public PropertiesConfig() + { + control = new ControlConfig(); + } + } + + /// + /// Root device class + /// + public class RootObject + { + public List devices { get; set; } + } +} \ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/JsonToSimpl/Constants.cs b/Pepperdash Core/Pepperdash Core/JsonToSimpl/Constants.cs new file mode 100644 index 0000000..0838d56 --- /dev/null +++ b/Pepperdash Core/Pepperdash Core/JsonToSimpl/Constants.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash.Core.JsonToSimpl +{ + /// + /// Constants for Simpl modules + /// + public class JsonToSimplConstants + { + public const ushort BoolValueChange = 1; + public const ushort JsonIsValidBoolChange = 2; + + public const ushort UshortValueChange = 101; + + public const ushort StringValueChange = 201; + public const ushort FullPathToArrayChange = 202; + public const ushort ActualFilePathChange = 203; + + // TODO: pdc-20: Added below constants for passing file path and filename back to S+ + public const ushort FilenameResolvedChange = 204; + public const ushort FilePathResolvedChange = 205; + } + + /// + /// S+ values delegate + /// + public delegate void SPlusValuesDelegate(); + + /// + /// S+ values wrapper + /// + public class SPlusValueWrapper + { + public SPlusType ValueType { get; private set; } + public ushort Index { get; private set; } + public ushort BoolUShortValue { get; set; } + public string StringValue { get; set; } + + public SPlusValueWrapper() { } + + public SPlusValueWrapper(SPlusType type, ushort index) + { + ValueType = type; + Index = index; + } + } + + /// + /// S+ types enum + /// + public enum SPlusType + { + Digital, Analog, String + } +} \ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/JsonToSimpl/EventArgs and Constants.cs b/Pepperdash Core/Pepperdash Core/JsonToSimpl/EventArgs and Constants.cs deleted file mode 100644 index bbbf7e2..0000000 --- a/Pepperdash Core/Pepperdash Core/JsonToSimpl/EventArgs and Constants.cs +++ /dev/null @@ -1,125 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; - -namespace PepperDash.Core.JsonToSimpl -{ - /// - /// Constants for Simpl modules - /// - public class JsonToSimplConstants - { - public const ushort JsonIsValidBoolChange = 2; - - - public const ushort BoolValueChange = 1; - public const ushort UshortValueChange = 101; - public const ushort StringValueChange = 201; - public const ushort FullPathToArrayChange = 202; - public const ushort ActualFilePathChange = 203; - } - - //**************************************************************************************************// - public delegate void SPlusValuesDelegate(); - - public class SPlusValueWrapper - { - public SPlusType ValueType { get; private set; } - public ushort Index { get; private set; } - public ushort BoolUShortValue { get; set; } - public string StringValue { get; set; } - - public SPlusValueWrapper() { } - - public SPlusValueWrapper(SPlusType type, ushort index) - { - ValueType = type; - Index = index; - } - } - - public enum SPlusType - { - Digital, Analog, String - } - - - //**************************************************************************************************// - public class BoolChangeEventArgs : EventArgs - { - public bool State { get; set; } - public ushort IntValue { get { return (ushort)(State ? 1 : 0); } } - public ushort Type { get; set; } - public ushort Index { get; set; } - - public BoolChangeEventArgs() - { - } - - public BoolChangeEventArgs(bool state, ushort type) - { - State = state; - Type = type; - } - - public BoolChangeEventArgs(bool state, ushort type, ushort index) - { - State = state; - Type = type; - Index = index; - } - } - - //**************************************************************************************************// - public class UshrtChangeEventArgs : EventArgs - { - public ushort IntValue { get; set; } - public ushort Type { get; set; } - public ushort Index { get; set; } - - public UshrtChangeEventArgs() - { - } - - public UshrtChangeEventArgs(ushort intValue, ushort type) - { - IntValue = intValue; - Type = type; - } - - public UshrtChangeEventArgs(ushort intValue, ushort type, ushort index) - { - IntValue = intValue; - Type = type; - Index = index; - } - } - - //**************************************************************************************************// - public class StringChangeEventArgs : EventArgs - { - public string StringValue { get; set; } - public ushort Type { get; set; } - public ushort Index { get; set; } - - public StringChangeEventArgs() - { - } - - public StringChangeEventArgs(string stringValue, ushort type) - { - StringValue = stringValue; - Type = type; - } - - public StringChangeEventArgs(string stringValue, ushort type, ushort index) - { - StringValue = stringValue; - Type = type; - Index = index; - } - - } -} \ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/JsonToSimpl/JsonToSimplArrayLookupChild.cs b/Pepperdash Core/Pepperdash Core/JsonToSimpl/JsonToSimplArrayLookupChild.cs index 56ef04a..0ac1bbf 100644 --- a/Pepperdash Core/Pepperdash Core/JsonToSimpl/JsonToSimplArrayLookupChild.cs +++ b/Pepperdash Core/Pepperdash Core/JsonToSimpl/JsonToSimplArrayLookupChild.cs @@ -1,116 +1,116 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace PepperDash.Core.JsonToSimpl -{ - public class JsonToSimplArrayLookupChild : JsonToSimplChildObjectBase - { - public string SearchPropertyName { get; set; } - public string SearchPropertyValue { get; set; } - - int ArrayIndex; - - /// - /// For <2.4.1 array lookups - /// - /// - /// - /// - /// - /// - /// - public void Initialize(string file, string key, string pathPrefix, string pathSuffix, - string searchPropertyName, string searchPropertyValue) - { - base.Initialize(file, key, pathPrefix, pathSuffix); - SearchPropertyName = searchPropertyName; - SearchPropertyValue = searchPropertyValue; - } - - - /// - /// For newer >=2.4.1 array lookups. - /// - /// - /// - /// - /// - /// - /// - /// - public void InitializeWithAppend(string file, string key, string pathPrefix, string pathAppend, - string pathSuffix, string searchPropertyName, string searchPropertyValue) +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace PepperDash.Core.JsonToSimpl +{ + public class JsonToSimplArrayLookupChild : JsonToSimplChildObjectBase + { + public string SearchPropertyName { get; set; } + public string SearchPropertyValue { get; set; } + + int ArrayIndex; + + /// + /// For <2.4.1 array lookups + /// + /// + /// + /// + /// + /// + /// + public void Initialize(string file, string key, string pathPrefix, string pathSuffix, + string searchPropertyName, string searchPropertyValue) + { + base.Initialize(file, key, pathPrefix, pathSuffix); + SearchPropertyName = searchPropertyName; + SearchPropertyValue = searchPropertyValue; + } + + + /// + /// For newer >=2.4.1 array lookups. + /// + /// + /// + /// + /// + /// + /// + /// + public void InitializeWithAppend(string file, string key, string pathPrefix, string pathAppend, + string pathSuffix, string searchPropertyName, string searchPropertyValue) + { + string pathPrefixWithAppend = (pathPrefix != null ? pathPrefix : "") + GetPathAppend(pathAppend); + base.Initialize(file, key, pathPrefixWithAppend, pathSuffix); + + SearchPropertyName = searchPropertyName; + SearchPropertyValue = searchPropertyValue; + } + + + + //PathPrefix+ArrayName+[x]+path+PathSuffix + /// + /// + /// + /// + /// + protected override string GetFullPath(string path) { - string pathPrefixWithAppend = (pathPrefix != null ? pathPrefix : "") + GetPathAppend(pathAppend); - base.Initialize(file, key, pathPrefixWithAppend, pathSuffix); - - SearchPropertyName = searchPropertyName; - SearchPropertyValue = searchPropertyValue; - } - - - - //PathPrefix+ArrayName+[x]+path+PathSuffix - /// - /// - /// - /// - /// - protected override string GetFullPath(string path) - { return string.Format("{0}[{1}].{2}{3}", PathPrefix == null ? "" : PathPrefix, - ArrayIndex, + ArrayIndex, path, - PathSuffix == null ? "" : PathSuffix); - } - - public override void ProcessAll() - { - if(FindInArray()) - base.ProcessAll(); - } - - /// - /// Provides the path append for GetFullPath - /// - /// - string GetPathAppend(string a) - { - if (string.IsNullOrEmpty(a)) - { - return ""; - } - if (a.StartsWith(".")) - { - return a; - } - else - { - return "." + a; - } - } - - /// - /// - /// - /// - bool FindInArray() - { - if (Master == null) - throw new InvalidOperationException("Cannot do operations before master is linked"); - if (Master.JsonObject == null) - throw new InvalidOperationException("Cannot do operations before master JSON has read"); - if (PathPrefix == null) + PathSuffix == null ? "" : PathSuffix); + } + + public override void ProcessAll() + { + if (FindInArray()) + base.ProcessAll(); + } + + /// + /// Provides the path append for GetFullPath + /// + /// + string GetPathAppend(string a) + { + if (string.IsNullOrEmpty(a)) + { + return ""; + } + if (a.StartsWith(".")) + { + return a; + } + else + { + return "." + a; + } + } + + /// + /// + /// + /// + bool FindInArray() + { + if (Master == null) + throw new InvalidOperationException("Cannot do operations before master is linked"); + if (Master.JsonObject == null) + throw new InvalidOperationException("Cannot do operations before master JSON has read"); + if (PathPrefix == null) throw new InvalidOperationException("Cannot do operations before PathPrefix is set"); - var token = Master.JsonObject.SelectToken(PathPrefix); + var token = Master.JsonObject.SelectToken(PathPrefix); if (token is JArray) { var array = token as JArray; @@ -139,15 +139,15 @@ namespace PepperDash.Core.JsonToSimpl catch (Exception e) { Debug.Console(1, "JSON Child[{0}] Array '{1}' lookup error: '{2}={3}'\r{4}", Key, - PathPrefix, SearchPropertyName, SearchPropertyValue, e); + PathPrefix, SearchPropertyName, SearchPropertyValue, e); } } else { - Debug.Console(1, "JSON Child[{0}] Path '{1}' is not an array", Key, PathPrefix); - } - - return false; - } - } + Debug.Console(1, "JSON Child[{0}] Path '{1}' is not an array", Key, PathPrefix); + } + + return false; + } + } } \ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/JsonToSimpl/JsonToSimplChildObjectBase.cs b/Pepperdash Core/Pepperdash Core/JsonToSimpl/JsonToSimplChildObjectBase.cs index ec855f9..93c5ee5 100644 --- a/Pepperdash Core/Pepperdash Core/JsonToSimpl/JsonToSimplChildObjectBase.cs +++ b/Pepperdash Core/Pepperdash Core/JsonToSimpl/JsonToSimplChildObjectBase.cs @@ -1,327 +1,327 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace PepperDash.Core.JsonToSimpl -{ - public abstract class JsonToSimplChildObjectBase: IKeyed - { - - public event EventHandler BoolChange; - public event EventHandler UShortChange; - public event EventHandler StringChange; - - public SPlusValuesDelegate GetAllValuesDelegate { get; set; } - - /// - /// Use a callback to reduce task switch/threading - /// - public SPlusValuesDelegate SetAllPathsDelegate { get; set; } - - public string Key { get; protected set; } - - /// - /// This will be prepended to all paths to allow path swapping or for more organized - /// sub-paths - /// +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace PepperDash.Core.JsonToSimpl +{ + public abstract class JsonToSimplChildObjectBase: IKeyed + { + + public event EventHandler BoolChange; + public event EventHandler UShortChange; + public event EventHandler StringChange; + + public SPlusValuesDelegate GetAllValuesDelegate { get; set; } + + /// + /// Use a callback to reduce task switch/threading + /// + public SPlusValuesDelegate SetAllPathsDelegate { get; set; } + + public string Key { get; protected set; } + + /// + /// This will be prepended to all paths to allow path swapping or for more organized + /// sub-paths + /// public string PathPrefix { get; protected set; } - - /// - /// This is added to the end of all paths - /// - public string PathSuffix { get; protected set; } - - public bool LinkedToObject { get; protected set; } - - protected JsonToSimplMaster Master; - - // The sent-in JPaths for the various types - protected Dictionary BoolPaths = new Dictionary(); - protected Dictionary UshortPaths = new Dictionary(); - protected Dictionary StringPaths = new Dictionary(); - - /// - /// Call this before doing anything else - /// - /// - /// - /// - /// - public void Initialize(string masterUniqueId, string key, string pathPrefix, string pathSuffix) - { - Key = key; - PathPrefix = pathPrefix; - PathSuffix = pathSuffix; - - Master = J2SGlobal.GetMasterByFile(masterUniqueId); - if (Master != null) - Master.AddChild(this); - else - Debug.Console(1, "JSON Child [{0}] cannot link to master {1}", key, masterUniqueId); - } - - public void SetPathPrefix(string pathPrefix) { - PathPrefix = pathPrefix; - } - /// - /// Set the JPath to evaluate for a given bool out index. - /// - public void SetBoolPath(ushort index, string path) - { - Debug.Console(1, "JSON Child[{0}] SetBoolPath {1}={2}", Key, index, path); - if (path == null || path.Trim() == string.Empty) return; - BoolPaths[index] = path; - } - - /// - /// Set the JPath for a ushort out index. - /// - public void SetUshortPath(ushort index, string path) - { - Debug.Console(1, "JSON Child[{0}] SetUshortPath {1}={2}", Key, index, path); - if (path == null || path.Trim() == string.Empty) return; - UshortPaths[index] = path; - } - - /// - /// Set the JPath for a string output index. - /// - public void SetStringPath(ushort index, string path) - { - Debug.Console(1, "JSON Child[{0}] SetStringPath {1}={2}", Key, index, path); - if (path == null || path.Trim() == string.Empty) return; - StringPaths[index] = path; - } - - /// - /// Evalutates all outputs with defined paths. called by S+ when paths are ready to process - /// and by Master when file is read. - /// - public virtual void ProcessAll() - { - if (!LinkedToObject) - { - Debug.Console(1, this, "Not linked to object in file. Skipping"); - return; - } - - if (SetAllPathsDelegate == null) - { - Debug.Console(1, this, "No SetAllPathsDelegate set. Ignoring ProcessAll"); - return; - } - SetAllPathsDelegate(); - foreach (var kvp in BoolPaths) - ProcessBoolPath(kvp.Key); - foreach (var kvp in UshortPaths) - ProcessUshortPath(kvp.Key); - foreach (var kvp in StringPaths) - ProcessStringPath(kvp.Key); - } - - /// - /// Processes a bool property, converting to bool, firing off a BoolChange event - /// - void ProcessBoolPath(ushort index) - { - string response; - if (Process(BoolPaths[index], out response)) - OnBoolChange(response.Equals("true", StringComparison.OrdinalIgnoreCase), - index, JsonToSimplConstants.BoolValueChange); - else { } - // OnBoolChange(false, index, JsonToSimplConstants.BoolValueChange); - } - - // Processes the path to a ushort, converting to ushort if able, firing off UshrtChange event - void ProcessUshortPath(ushort index) - { - string response; - if (Process(UshortPaths[index], out response)) { - ushort val; - try { val = Convert.ToUInt16(response); } catch { val = 0; } - OnUShortChange(val, index, JsonToSimplConstants.UshortValueChange); - } - else { } - // OnUShortChange(0, index, JsonToSimplConstants.UshortValueChange); - } - - // Processes the path to a string property and fires of a StringChange event. - void ProcessStringPath(ushort index) - { - string response; - if (Process(StringPaths[index], out response)) - OnStringChange(response, index, JsonToSimplConstants.StringValueChange); - else { } - // OnStringChange("", index, JsonToSimplConstants.StringValueChange); - } - - /// - /// Processes the given path. - /// - /// JPath formatted path to the desired property - /// The string value of the property, or a default value if it - /// doesn't exist - /// This will return false in the case that EvaulateAllOnJsonChange - /// is false and the path does not evaluate to a property in the incoming JSON. - bool Process(string path, out string response) - { - path = GetFullPath(path); - Debug.Console(1, "JSON Child[{0}] Processing {1}", Key, path); - response = ""; - if (Master == null) - { - Debug.Console(1, "JSONChild[{0}] cannot process without Master attached", Key); - return false; - } - - if (Master.JsonObject != null && path != string.Empty) - { - bool isCount = false; - path = path.Trim(); - if (path.EndsWith(".Count")) - { - path = path.Remove(path.Length - 6, 6); - isCount = true; - } - try // Catch a strange cast error on a bad path - { - var t = Master.JsonObject.SelectToken(path); - if (t != null) - { - // return the count of children objects - if any - if (isCount) - response = (t.HasValues ? t.Children().Count() : 0).ToString(); - else - response = t.Value(); - Debug.Console(1, " ='{0}'", response); - return true; - } - } - catch - { - response = ""; - } - } - // If the path isn't found, return this to determine whether to pass out the non-value or not. - return false; - } - - - //************************************************************************************************ - // Save-related functions - - - /// - /// Called from Master to read inputs and update their values in master JObject - /// Callback should hit one of the following four methods - /// - public void UpdateInputsForMaster() - { - if (!LinkedToObject) - { - Debug.Console(1, this, "Not linked to object in file. Skipping"); - return; - } - - if (SetAllPathsDelegate == null) - { - Debug.Console(1, this, "No SetAllPathsDelegate set. Ignoring UpdateInputsForMaster"); - return; - } - SetAllPathsDelegate(); - var del = GetAllValuesDelegate; - if (del != null) - GetAllValuesDelegate(); - } - - public void USetBoolValue(ushort key, ushort theValue) - { - SetBoolValue(key, theValue == 1); - } - - public void SetBoolValue(ushort key, bool theValue) - { - if (BoolPaths.ContainsKey(key)) - SetValueOnMaster(BoolPaths[key], new JValue(theValue)); - } - - public void SetUShortValue(ushort key, ushort theValue) - { - if (UshortPaths.ContainsKey(key)) - SetValueOnMaster(UshortPaths[key], new JValue(theValue)); - } - - public void SetStringValue(ushort key, string theValue) - { - if (StringPaths.ContainsKey(key)) - SetValueOnMaster(StringPaths[key], new JValue(theValue)); - } - - public void SetValueOnMaster(string keyPath, JValue valueToSave) - { - var path = GetFullPath(keyPath); - try - { - Debug.Console(1, "JSON Child[{0}] Queueing value on master {1}='{2}'", Key, path, valueToSave); - - //var token = Master.JsonObject.SelectToken(path); - //if (token != null) // The path exists in the file - Master.AddUnsavedValue(path, valueToSave); - } - catch (Exception e) - { - Debug.Console(1, "JSON Child[{0}] Failed setting value for path '{1}'\r{2}", Key, path, e); - } - } - - /// - /// Called during Process(...) to get the path to a given property. By default, - /// returns PathPrefix+path+PathSuffix. Override to change the way path is built. - /// - protected virtual string GetFullPath(string path) - { - return (PathPrefix != null ? PathPrefix : "") + - path + (PathSuffix != null ? PathSuffix : ""); - } - - // Helpers for events - //****************************************************************************************** - protected void OnBoolChange(bool state, ushort index, ushort type) - { - var handler = BoolChange; - if (handler != null) - { - var args = new BoolChangeEventArgs(state, type); - args.Index = index; - BoolChange(this, args); - } - } - - //****************************************************************************************** - protected void OnUShortChange(ushort state, ushort index, ushort type) - { - var handler = UShortChange; - if (handler != null) - { - var args = new UshrtChangeEventArgs(state, type); - args.Index = index; - UShortChange(this, args); - } - } - - protected void OnStringChange(string value, ushort index, ushort type) - { - var handler = StringChange; - if (handler != null) - { - var args = new StringChangeEventArgs(value, type); - args.Index = index; - StringChange(this, args); - } - } - } + + /// + /// This is added to the end of all paths + /// + public string PathSuffix { get; protected set; } + + public bool LinkedToObject { get; protected set; } + + protected JsonToSimplMaster Master; + + // The sent-in JPaths for the various types + protected Dictionary BoolPaths = new Dictionary(); + protected Dictionary UshortPaths = new Dictionary(); + protected Dictionary StringPaths = new Dictionary(); + + /// + /// Call this before doing anything else + /// + /// + /// + /// + /// + public void Initialize(string masterUniqueId, string key, string pathPrefix, string pathSuffix) + { + Key = key; + PathPrefix = pathPrefix; + PathSuffix = pathSuffix; + + Master = J2SGlobal.GetMasterByFile(masterUniqueId); + if (Master != null) + Master.AddChild(this); + else + Debug.Console(1, "JSON Child [{0}] cannot link to master {1}", key, masterUniqueId); + } + + public void SetPathPrefix(string pathPrefix) { + PathPrefix = pathPrefix; + } + /// + /// Set the JPath to evaluate for a given bool out index. + /// + public void SetBoolPath(ushort index, string path) + { + Debug.Console(1, "JSON Child[{0}] SetBoolPath {1}={2}", Key, index, path); + if (path == null || path.Trim() == string.Empty) return; + BoolPaths[index] = path; + } + + /// + /// Set the JPath for a ushort out index. + /// + public void SetUshortPath(ushort index, string path) + { + Debug.Console(1, "JSON Child[{0}] SetUshortPath {1}={2}", Key, index, path); + if (path == null || path.Trim() == string.Empty) return; + UshortPaths[index] = path; + } + + /// + /// Set the JPath for a string output index. + /// + public void SetStringPath(ushort index, string path) + { + Debug.Console(1, "JSON Child[{0}] SetStringPath {1}={2}", Key, index, path); + if (path == null || path.Trim() == string.Empty) return; + StringPaths[index] = path; + } + + /// + /// Evalutates all outputs with defined paths. called by S+ when paths are ready to process + /// and by Master when file is read. + /// + public virtual void ProcessAll() + { + if (!LinkedToObject) + { + Debug.Console(1, this, "Not linked to object in file. Skipping"); + return; + } + + if (SetAllPathsDelegate == null) + { + Debug.Console(1, this, "No SetAllPathsDelegate set. Ignoring ProcessAll"); + return; + } + SetAllPathsDelegate(); + foreach (var kvp in BoolPaths) + ProcessBoolPath(kvp.Key); + foreach (var kvp in UshortPaths) + ProcessUshortPath(kvp.Key); + foreach (var kvp in StringPaths) + ProcessStringPath(kvp.Key); + } + + /// + /// Processes a bool property, converting to bool, firing off a BoolChange event + /// + void ProcessBoolPath(ushort index) + { + string response; + if (Process(BoolPaths[index], out response)) + OnBoolChange(response.Equals("true", StringComparison.OrdinalIgnoreCase), + index, JsonToSimplConstants.BoolValueChange); + else { } + // OnBoolChange(false, index, JsonToSimplConstants.BoolValueChange); + } + + // Processes the path to a ushort, converting to ushort if able, firing off UshrtChange event + void ProcessUshortPath(ushort index) + { + string response; + if (Process(UshortPaths[index], out response)) { + ushort val; + try { val = Convert.ToUInt16(response); } catch { val = 0; } + OnUShortChange(val, index, JsonToSimplConstants.UshortValueChange); + } + else { } + // OnUShortChange(0, index, JsonToSimplConstants.UshortValueChange); + } + + // Processes the path to a string property and fires of a StringChange event. + void ProcessStringPath(ushort index) + { + string response; + if (Process(StringPaths[index], out response)) + OnStringChange(response, index, JsonToSimplConstants.StringValueChange); + else { } + // OnStringChange("", index, JsonToSimplConstants.StringValueChange); + } + + /// + /// Processes the given path. + /// + /// JPath formatted path to the desired property + /// The string value of the property, or a default value if it + /// doesn't exist + /// This will return false in the case that EvaulateAllOnJsonChange + /// is false and the path does not evaluate to a property in the incoming JSON. + bool Process(string path, out string response) + { + path = GetFullPath(path); + Debug.Console(1, "JSON Child[{0}] Processing {1}", Key, path); + response = ""; + if (Master == null) + { + Debug.Console(1, "JSONChild[{0}] cannot process without Master attached", Key); + return false; + } + + if (Master.JsonObject != null && path != string.Empty) + { + bool isCount = false; + path = path.Trim(); + if (path.EndsWith(".Count")) + { + path = path.Remove(path.Length - 6, 6); + isCount = true; + } + try // Catch a strange cast error on a bad path + { + var t = Master.JsonObject.SelectToken(path); + if (t != null) + { + // return the count of children objects - if any + if (isCount) + response = (t.HasValues ? t.Children().Count() : 0).ToString(); + else + response = t.Value(); + Debug.Console(1, " ='{0}'", response); + return true; + } + } + catch + { + response = ""; + } + } + // If the path isn't found, return this to determine whether to pass out the non-value or not. + return false; + } + + + //************************************************************************************************ + // Save-related functions + + + /// + /// Called from Master to read inputs and update their values in master JObject + /// Callback should hit one of the following four methods + /// + public void UpdateInputsForMaster() + { + if (!LinkedToObject) + { + Debug.Console(1, this, "Not linked to object in file. Skipping"); + return; + } + + if (SetAllPathsDelegate == null) + { + Debug.Console(1, this, "No SetAllPathsDelegate set. Ignoring UpdateInputsForMaster"); + return; + } + SetAllPathsDelegate(); + var del = GetAllValuesDelegate; + if (del != null) + GetAllValuesDelegate(); + } + + public void USetBoolValue(ushort key, ushort theValue) + { + SetBoolValue(key, theValue == 1); + } + + public void SetBoolValue(ushort key, bool theValue) + { + if (BoolPaths.ContainsKey(key)) + SetValueOnMaster(BoolPaths[key], new JValue(theValue)); + } + + public void SetUShortValue(ushort key, ushort theValue) + { + if (UshortPaths.ContainsKey(key)) + SetValueOnMaster(UshortPaths[key], new JValue(theValue)); + } + + public void SetStringValue(ushort key, string theValue) + { + if (StringPaths.ContainsKey(key)) + SetValueOnMaster(StringPaths[key], new JValue(theValue)); + } + + public void SetValueOnMaster(string keyPath, JValue valueToSave) + { + var path = GetFullPath(keyPath); + try + { + Debug.Console(1, "JSON Child[{0}] Queueing value on master {1}='{2}'", Key, path, valueToSave); + + //var token = Master.JsonObject.SelectToken(path); + //if (token != null) // The path exists in the file + Master.AddUnsavedValue(path, valueToSave); + } + catch (Exception e) + { + Debug.Console(1, "JSON Child[{0}] Failed setting value for path '{1}'\r{2}", Key, path, e); + } + } + + /// + /// Called during Process(...) to get the path to a given property. By default, + /// returns PathPrefix+path+PathSuffix. Override to change the way path is built. + /// + protected virtual string GetFullPath(string path) + { + return (PathPrefix != null ? PathPrefix : "") + + path + (PathSuffix != null ? PathSuffix : ""); + } + + // Helpers for events + //****************************************************************************************** + protected void OnBoolChange(bool state, ushort index, ushort type) + { + var handler = BoolChange; + if (handler != null) + { + var args = new BoolChangeEventArgs(state, type); + args.Index = index; + BoolChange(this, args); + } + } + + //****************************************************************************************** + protected void OnUShortChange(ushort state, ushort index, ushort type) + { + var handler = UShortChange; + if (handler != null) + { + var args = new UshrtChangeEventArgs(state, type); + args.Index = index; + UShortChange(this, args); + } + } + + protected void OnStringChange(string value, ushort index, ushort type) + { + var handler = StringChange; + if (handler != null) + { + var args = new StringChangeEventArgs(value, type); + args.Index = index; + StringChange(this, args); + } + } + } } \ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/JsonToSimpl/JsonToSimplFileMaster.cs b/Pepperdash Core/Pepperdash Core/JsonToSimpl/JsonToSimplFileMaster.cs index 1e4c506..8fce304 100644 --- a/Pepperdash Core/Pepperdash Core/JsonToSimpl/JsonToSimplFileMaster.cs +++ b/Pepperdash Core/Pepperdash Core/JsonToSimpl/JsonToSimplFileMaster.cs @@ -10,8 +10,8 @@ using Newtonsoft.Json.Linq; namespace PepperDash.Core.JsonToSimpl { - public class JsonToSimplFileMaster : JsonToSimplMaster - { + public class JsonToSimplFileMaster : JsonToSimplMaster + { /// /// Sets the filepath as well as registers this with the Global.Masters list /// @@ -19,10 +19,14 @@ namespace PepperDash.Core.JsonToSimpl public string ActualFilePath { get; private set; } + // TODO: pdc-20: added to return filename back to SIMPL + public string Filename { get; private set; } + public string FilePathName { get; private set; } + /*****************************************************************************************/ /** Privates **/ - + // The JSON file in JObject form // For gathering the incoming data object StringBuilderLock = new object(); @@ -32,10 +36,10 @@ namespace PepperDash.Core.JsonToSimpl /*****************************************************************************************/ /// - /// SIMPL+ default constructor. - /// + /// SIMPL+ default constructor. + /// public JsonToSimplFileMaster() - { + { } /// @@ -49,7 +53,7 @@ namespace PepperDash.Core.JsonToSimpl if (string.IsNullOrEmpty(Filepath)) { CrestronConsole.PrintLine("Cannot evaluate file. JSON file path not set"); - return; + return; } // Resolve wildcard @@ -59,18 +63,28 @@ namespace PepperDash.Core.JsonToSimpl var directory = new DirectoryInfo(dir); var actualFile = directory.GetFiles(fileName).FirstOrDefault(); - if(actualFile == null) + if (actualFile == null) { var msg = string.Format("JSON file not found: {0}", Filepath); CrestronConsole.PrintLine(msg); ErrorLog.Error(msg); return; } - //var actualFileName = actualFile.FullName; + + // \xSE\xR\PDT000-Template_Main_Config-Combined_DSP_v00.02.json + // \USER\PDT000-Template_Main_Config-Combined_DSP_v00.02.json ActualFilePath = actualFile.FullName; - OnStringChange(ActualFilePath, 0, JsonToSimplConstants.ActualFilePathChange); + OnStringChange(ActualFilePath, 0, JsonToSimplConstants.ActualFilePathChange); Debug.Console(1, "Actual JSON file is {0}", ActualFilePath); + Filename = actualFile.Name; + OnStringChange(Filename, 0, JsonToSimplConstants.FilenameResolvedChange); + Debug.Console(1, "JSON Filename is {0}", Filename); + + FilePathName = string.Format(@"{0}\", actualFile.DirectoryName); + OnStringChange(FilePathName, 0, JsonToSimplConstants.FilePathResolvedChange); + Debug.Console(1, "JSON File Path is {0}", FilePathName); + string json = File.ReadToEnd(ActualFilePath, System.Text.Encoding.ASCII); try @@ -87,10 +101,11 @@ namespace PepperDash.Core.JsonToSimpl ErrorLog.Error(msg); return; } - } - public void setDebugLevel(int level) { - Debug.SetDebugLevel(level); - } + } + public void setDebugLevel(int level) + { + Debug.SetDebugLevel(level); + } public override void Save() { // this code is duplicated in the other masters!!!!!!!!!!!!! @@ -122,39 +137,39 @@ namespace PepperDash.Core.JsonToSimpl { //http://stackoverflow.com/questions/17455052/how-to-set-the-value-of-a-json-path-using-json-net Debug.Console(1, "JSON Master[{0}] Cannot write value onto missing property: '{1}'", UniqueID, path); - -// JContainer jpart = JsonObject; -// // walk down the path and find where it goes -//#warning Does not handle arrays. -// foreach (var part in path.Split('.')) -// { -// var openPos = part.IndexOf('['); -// if (openPos > -1) -// { -// openPos++; // move to number -// var closePos = part.IndexOf(']'); -// var arrayName = part.Substring(0, openPos - 1); // get the name -// var index = Convert.ToInt32(part.Substring(openPos, closePos - openPos)); + // JContainer jpart = JsonObject; + // // walk down the path and find where it goes + //#warning Does not handle arrays. + // foreach (var part in path.Split('.')) + // { -// // Check if the array itself exists and add the item if so -// if (jpart[arrayName] != null) -// { -// var arrayObj = jpart[arrayName] as JArray; -// var item = arrayObj[index]; -// if (item == null) -// arrayObj.Add(new JObject()); -// } - -// Debug.Console(0, "IGNORING MISSING ARRAY VALUE FOR NOW"); -// continue; -// } -// // Build the -// if (jpart[part] == null) -// jpart.Add(new JProperty(part, new JObject())); -// jpart = jpart[part] as JContainer; -// } -// jpart.Replace(UnsavedValues[path]); + // var openPos = part.IndexOf('['); + // if (openPos > -1) + // { + // openPos++; // move to number + // var closePos = part.IndexOf(']'); + // var arrayName = part.Substring(0, openPos - 1); // get the name + // var index = Convert.ToInt32(part.Substring(openPos, closePos - openPos)); + + // // Check if the array itself exists and add the item if so + // if (jpart[arrayName] != null) + // { + // var arrayObj = jpart[arrayName] as JArray; + // var item = arrayObj[index]; + // if (item == null) + // arrayObj.Add(new JObject()); + // } + + // Debug.Console(0, "IGNORING MISSING ARRAY VALUE FOR NOW"); + // continue; + // } + // // Build the + // if (jpart[part] == null) + // jpart.Add(new JProperty(part, new JObject())); + // jpart = jpart[part] as JContainer; + // } + // jpart.Replace(UnsavedValues[path]); } } using (StreamWriter sw = new StreamWriter(ActualFilePath)) diff --git a/Pepperdash Core/Pepperdash Core/PepperDash_Core.csproj b/Pepperdash Core/Pepperdash Core/PepperDash_Core.csproj index 6c7960d..e0fef86 100644 --- a/Pepperdash Core/Pepperdash Core/PepperDash_Core.csproj +++ b/Pepperdash Core/Pepperdash Core/PepperDash_Core.csproj @@ -86,6 +86,12 @@ + + + + + + @@ -94,7 +100,7 @@ - + @@ -104,7 +110,10 @@ + + + @@ -117,5 +126,7 @@ rem S# preparation will execute after these operations + del "$(TargetDir)PepperDash_Core.*" /q + \ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/Properties/UpdateAssemblyVersion.ps1 b/Pepperdash Core/Pepperdash Core/Properties/UpdateAssemblyVersion.ps1 index 46392b3..f1c6c38 100644 --- a/Pepperdash Core/Pepperdash Core/Properties/UpdateAssemblyVersion.ps1 +++ b/Pepperdash Core/Pepperdash Core/Properties/UpdateAssemblyVersion.ps1 @@ -24,6 +24,7 @@ function Update-AllAssemblyInfoFiles ( $version ) $r= [System.Text.RegularExpressions.Regex]::Match($args[0], "^\d+\.\d+\.\d+$"); if ($r.Success) { + echo "Updating Assembly Version..."; Update-AllAssemblyInfoFiles $args[0]; } else diff --git a/Pepperdash Core/Pepperdash Core/SystemInfo/EventArgs and Constants.cs b/Pepperdash Core/Pepperdash Core/SystemInfo/EventArgs and Constants.cs new file mode 100644 index 0000000..4e6b500 --- /dev/null +++ b/Pepperdash Core/Pepperdash Core/SystemInfo/EventArgs and Constants.cs @@ -0,0 +1,187 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash.Core.SystemInfo +{ + /// + /// Constants + /// + public class SystemInfoConstants + { + public const ushort BoolValueChange = 1; + public const ushort CompleteBoolChange = 2; + public const ushort BusyBoolChange = 3; + + public const ushort UshortValueChange = 101; + + public const ushort StringValueChange = 201; + public const ushort ConsoleResponseChange = 202; + public const ushort ProcessorUptimeChange = 203; + public const ushort ProgramUptimeChange = 204; + + public const ushort ObjectChange = 301; + public const ushort ProcessorConfigChange = 302; + public const ushort EthernetConfigChange = 303; + public const ushort ControlSubnetConfigChange = 304; + public const ushort ProgramConfigChange = 305; + } + + /// + /// Processor Change Event Args Class + /// + public class ProcessorChangeEventArgs : EventArgs + { + public ProcessorInfo Processor { get; set; } + public ushort Type { get; set; } + public ushort Index { get; set; } + + /// + /// Constructor + /// + public ProcessorChangeEventArgs() + { + + } + + /// + /// Constructor overload + /// + public ProcessorChangeEventArgs(ProcessorInfo processor, ushort type) + { + Processor = processor; + Type = type; + } + + /// + /// Constructor + /// + public ProcessorChangeEventArgs(ProcessorInfo processor, ushort type, ushort index) + { + Processor = processor; + Type = type; + Index = index; + } + } + + /// + /// Ethernet Change Event Args Class + /// + public class EthernetChangeEventArgs : EventArgs + { + public EthernetInfo Adapter { get; set; } + public ushort Type { get; set; } + public ushort Index { get; set; } + + /// + /// Constructor + /// + public EthernetChangeEventArgs() + { + + } + + /// + /// Constructor overload + /// + /// + /// + public EthernetChangeEventArgs(EthernetInfo ethernet, ushort type) + { + Adapter = ethernet; + Type = type; + } + + /// + /// Constructor overload + /// + /// + /// + public EthernetChangeEventArgs(EthernetInfo ethernet, ushort type, ushort index) + { + Adapter = ethernet; + Type = type; + Index = index; + } + } + + /// + /// Control Subnet Chage Event Args Class + /// + public class ControlSubnetChangeEventArgs : EventArgs + { + public ControlSubnetInfo Adapter { get; set; } + public ushort Type { get; set; } + public ushort Index { get; set; } + + /// + /// Constructor + /// + public ControlSubnetChangeEventArgs() + { + + } + + /// + /// Constructor overload + /// + public ControlSubnetChangeEventArgs(ControlSubnetInfo controlSubnet, ushort type) + { + Adapter = controlSubnet; + Type = type; + } + + /// + /// Constructor overload + /// + public ControlSubnetChangeEventArgs(ControlSubnetInfo controlSubnet, ushort type, ushort index) + { + Adapter = controlSubnet; + Type = type; + Index = index; + } + } + + /// + /// Program Change Event Args Class + /// + public class ProgramChangeEventArgs : EventArgs + { + public ProgramInfo Program { get; set; } + public ushort Type { get; set; } + public ushort Index { get; set; } + + /// + /// Constructor + /// + public ProgramChangeEventArgs() + { + + } + + /// + /// Constructor overload + /// + /// + /// + public ProgramChangeEventArgs(ProgramInfo program, ushort type) + { + Program = program; + Type = type; + } + + /// + /// Constructor overload + /// + /// + /// + public ProgramChangeEventArgs(ProgramInfo program, ushort type, ushort index) + { + Program = program; + Type = type; + Index = index; + } + } +} \ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/SystemInfo/SystemInfoConfig.cs b/Pepperdash Core/Pepperdash Core/SystemInfo/SystemInfoConfig.cs new file mode 100644 index 0000000..cbf5f4b --- /dev/null +++ b/Pepperdash Core/Pepperdash Core/SystemInfo/SystemInfoConfig.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash.Core.SystemInfo +{ + /// + /// Processor info class + /// + public class ProcessorInfo + { + public string Model { get; set; } + public string SerialNumber { get; set; } + public string Firmware { get; set; } + public string FirmwareDate { get; set; } + public string OsVersion { get; set; } + public string RuntimeEnvironment { get; set; } + public string DevicePlatform { get; set; } + public string ModuleDirectory { get; set; } + public string LocalTimeZone { get; set; } + public string ProgramIdTag { get; set; } + + /// + /// Constructor + /// + public ProcessorInfo() + { + + } + } + + /// + /// Ethernet info class + /// + public class EthernetInfo + { + public ushort DhcpIsOn { get; set; } + public string Hostname { get; set; } + public string MacAddress { get; set; } + public string IpAddress { get; set; } + public string Subnet { get; set; } + public string Gateway { get; set; } + public string Dns1 { get; set; } + public string Dns2 { get; set; } + public string Dns3 { get; set; } + public string Domain { get; set; } + + /// + /// Constructor + /// + public EthernetInfo() + { + + } + } + + /// + /// Control subnet info class + /// + public class ControlSubnetInfo + { + public ushort Enabled { get; set; } + public ushort IsInAutomaticMode { get; set; } + public string MacAddress { get; set; } + public string IpAddress { get; set; } + public string Subnet { get; set; } + public string RouterPrefix { get; set; } + + /// + /// Constructor + /// + public ControlSubnetInfo() + { + + } + } + + /// + /// Program info class + /// + public class ProgramInfo + { + public string Name { get; set; } + public string Header { get; set; } + public string System { get; set; } + public string ProgramIdTag { get; set; } + public string CompileTime { get; set; } + public string Database { get; set; } + public string Environment { get; set; } + public string Programmer { get; set; } + + /// + /// Constructor + /// + public ProgramInfo() + { + + } + } +} \ No newline at end of file diff --git a/Pepperdash Core/Pepperdash Core/SystemInfo/SystemInfoToSimpl.cs b/Pepperdash Core/Pepperdash Core/SystemInfo/SystemInfoToSimpl.cs new file mode 100644 index 0000000..80c8246 --- /dev/null +++ b/Pepperdash Core/Pepperdash Core/SystemInfo/SystemInfoToSimpl.cs @@ -0,0 +1,443 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; + +namespace PepperDash.Core.SystemInfo +{ + /// + /// System Info class + /// + public class SystemInfoToSimpl + { + public event EventHandler BoolChange; + public event EventHandler StringChange; + + public event EventHandler ProcessorChange; + public event EventHandler EthernetChange; + public event EventHandler ControlSubnetChange; + public event EventHandler ProgramChange; + + /// + /// Constructor + /// + public SystemInfoToSimpl() + { + + } + + /// + /// Gets the current processor info + /// + public void GetProcessorInfo() + { + OnBoolChange(true, 0, SystemInfoConstants.BusyBoolChange); + + try + { + var processor = new ProcessorInfo(); + processor.Model = InitialParametersClass.ControllerPromptName; + processor.SerialNumber = CrestronEnvironment.SystemInfo.SerialNumber; + processor.ModuleDirectory = InitialParametersClass.ProgramDirectory.ToString(); + processor.ProgramIdTag = InitialParametersClass.ProgramIDTag; + processor.DevicePlatform = CrestronEnvironment.DevicePlatform.ToString(); + processor.OsVersion = CrestronEnvironment.OSVersion.Version.ToString(); + processor.RuntimeEnvironment = CrestronEnvironment.RuntimeEnvironment.ToString(); + processor.LocalTimeZone = CrestronEnvironment.GetTimeZone().Offset; + + // Does not return firmware version matching a "ver" command + // returns the "ver -v" 'CAB' version + // example return ver -v: + // RMC3 Cntrl Eng [v1.503.3568.25373 (Oct 09 2018), #4001E302] @E-00107f4420f0 + // Build: 14:05:46 Oct 09 2018 (3568.25373) + // Cab: 1.503.0070 + // Applications: 1.0.6855.21351 + // Updater: 1.4.24 + // Bootloader: 1.22.00 + // RMC3-SetupProgram: 1.003.0011 + // IOPVersion: FPGA [v09] slot:7 + // PUF: Unknown + //Firmware = CrestronEnvironment.OSVersion.Firmware; + //Firmware = InitialParametersClass.FirmwareVersion; + + // Use below logic to get actual firmware ver, not the 'CAB' returned by the above + // matches console return of a "ver" and on SystemInfo page + // example return ver: + // RMC3 Cntrl Eng [v1.503.3568.25373 (Oct 09 2018), #4001E302] @E-00107f4420f0 + var response = ""; + CrestronConsole.SendControlSystemCommand("ver", ref response); + processor.Firmware = ParseConsoleResponse(response, "Cntrl Eng", "[", "("); + processor.FirmwareDate = ParseConsoleResponse(response, "Cntrl Eng", "(", ")"); + + OnProcessorChange(processor, 0, SystemInfoConstants.ProcessorConfigChange); + } + catch (Exception e) + { + var msg = string.Format("GetProcessorInfo failed: {0}", e.Message); + CrestronConsole.PrintLine(msg); + //ErrorLog.Error(msg); + } + + OnBoolChange(false, 0, SystemInfoConstants.BusyBoolChange); + } + + /// + /// Gets the current ethernet info + /// + public void GetEthernetInfo() + { + OnBoolChange(true, 0, SystemInfoConstants.BusyBoolChange); + + var adapter = new EthernetInfo(); + + try + { + // get lan adapter id + var adapterId = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetLANAdapter); + + // get lan adapter info + var dhcpState = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_DHCP_STATE, adapterId); + if (!string.IsNullOrEmpty(dhcpState)) + adapter.DhcpIsOn = (ushort)(dhcpState.ToLower().Contains("on") ? 1 : 0); + + adapter.Hostname = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_HOSTNAME, adapterId); + adapter.MacAddress = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, adapterId); + adapter.IpAddress = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, adapterId); + adapter.Subnet = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, adapterId); + adapter.Gateway = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_ROUTER, adapterId); + adapter.Domain = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DOMAIN_NAME, adapterId); + + // returns comma seperate list of dns servers with trailing comma + // example return: "8.8.8.8 (DHCP),8.8.4.4 (DHCP)," + string dns = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_DNS_SERVER, adapterId); + if (dns.Contains(",")) + { + string[] dnsList = dns.Split(','); + for (var i = 0; i < dnsList.Length; i++) + { + if(i == 0) + adapter.Dns1 = !string.IsNullOrEmpty(dnsList[0]) ? dnsList[0] : "0.0.0.0"; + if(i == 1) + adapter.Dns2 = !string.IsNullOrEmpty(dnsList[1]) ? dnsList[1] : "0.0.0.0"; + if(i == 2) + adapter.Dns3 = !string.IsNullOrEmpty(dnsList[2]) ? dnsList[2] : "0.0.0.0"; + } + } + else + { + adapter.Dns1 = !string.IsNullOrEmpty(dns) ? dns : "0.0.0.0"; + adapter.Dns2 = "0.0.0.0"; + adapter.Dns3 = "0.0.0.0"; + } + + OnEthernetInfoChange(adapter, 0, SystemInfoConstants.EthernetConfigChange); + } + catch (Exception e) + { + var msg = string.Format("GetEthernetInfo failed: {0}", e.Message); + CrestronConsole.PrintLine(msg); + //ErrorLog.Error(msg); + } + + OnBoolChange(false, 0, SystemInfoConstants.BusyBoolChange); + } + + /// + /// Gets the current control subnet info + /// + public void GetControlSubnetInfo() + { + OnBoolChange(true, 0, SystemInfoConstants.BusyBoolChange); + + var adapter = new ControlSubnetInfo(); + + try + { + // get cs adapter id + var adapterId = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(EthernetAdapterType.EthernetCSAdapter); + if (!adapterId.Equals(EthernetAdapterType.EthernetUnknownAdapter)) + { + adapter.Enabled = 1; + adapter.IsInAutomaticMode = (ushort)(CrestronEthernetHelper.IsControlSubnetInAutomaticMode ? 1 : 0); + adapter.MacAddress = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS, adapterId); + adapter.IpAddress = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS, adapterId); + adapter.Subnet = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_MASK, adapterId); + adapter.RouterPrefix = CrestronEthernetHelper.GetEthernetParameter(CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CONTROL_SUBNET_ROUTER_PREFIX, adapterId); + } + } + catch (Exception e) + { + adapter.Enabled = 0; + adapter.IsInAutomaticMode = 0; + adapter.MacAddress = "NA"; + adapter.IpAddress = "NA"; + adapter.Subnet = "NA"; + adapter.RouterPrefix = "NA"; + + var msg = string.Format("GetControlSubnetInfo failed: {0}", e.Message); + CrestronConsole.PrintLine(msg); + //ErrorLog.Error(msg); + } + + OnControlSubnetInfoChange(adapter, 0, SystemInfoConstants.ControlSubnetConfigChange); + OnBoolChange(false, 0, SystemInfoConstants.BusyBoolChange); + } + + /// + /// Gets the program info by index + /// + /// + public void GetProgramInfoByIndex(ushort index) + { + if (index < 1 || index > 10) + return; + + OnBoolChange(true, 0, SystemInfoConstants.BusyBoolChange); + + var program = new ProgramInfo(); + + try + { + var response = ""; + CrestronConsole.SendControlSystemCommand(string.Format("progcomments:{0}", index), ref response); + + // no program loaded or running + if (response.Contains("Bad or Incomplete Command")) + { + program.Name = ""; + program.System = ""; + program.Programmer = ""; + program.CompileTime = ""; + program.Database = ""; + program.Environment = ""; + } + else + { + // SIMPL returns + program.Name = ParseConsoleResponse(response, "Program File", ":", "\x0D"); + program.System = ParseConsoleResponse(response, "System Name", ":", "\x0D"); + program.ProgramIdTag = ParseConsoleResponse(response, "Friendly Name", ":", "\x0D"); + program.Programmer = ParseConsoleResponse(response, "Programmer", ":", "\x0D"); + program.CompileTime = ParseConsoleResponse(response, "Compiled On", ":", "\x0D"); + program.Database = ParseConsoleResponse(response, "CrestronDB", ":", "\x0D"); + program.Environment = ParseConsoleResponse(response, "Source Env", ":", "\x0D"); + + // S# returns + if (program.System.Length == 0) + program.System = ParseConsoleResponse(response, "Application Name", ":", "\x0D"); + if (program.Database.Length == 0) + program.Database = ParseConsoleResponse(response, "PlugInVersion", ":", "\x0D"); + if (program.Environment.Length == 0) + program.Environment = ParseConsoleResponse(response, "Program Tool", ":", "\x0D"); + + } + + OnProgramChange(program, index, SystemInfoConstants.ProgramConfigChange); + } + catch (Exception e) + { + var msg = string.Format("GetProgramInfoByIndex failed: {0}", e.Message); + CrestronConsole.PrintLine(msg); + //ErrorLog.Error(msg); + } + + OnBoolChange(false, 0, SystemInfoConstants.BusyBoolChange); + } + + /// + /// Gets the processor uptime and passes it to S+ + /// + public void RefreshProcessorUptime() + { + try + { + string response = ""; + CrestronConsole.SendControlSystemCommand("uptime", ref response); + var uptime = ParseConsoleResponse(response, "running for", "running for", "\x0D"); + OnStringChange(uptime, 0, SystemInfoConstants.ProcessorUptimeChange); + } + catch (Exception e) + { + var msg = string.Format("RefreshProcessorUptime failed:\r{0}", e.Message); + CrestronConsole.PrintLine(msg); + //ErrorLog.Error(msg); + } + } + + /// + /// Gets the program uptime, by index, and passes it to S+ + /// + /// + public void RefreshProgramUptimeByIndex(int index) + { + try + { + string response = ""; + CrestronConsole.SendControlSystemCommand(string.Format("proguptime:{0}", index), ref response); + string uptime = ParseConsoleResponse(response, "running for", "running for", "\x0D"); + OnStringChange(uptime, (ushort)index, SystemInfoConstants.ProgramUptimeChange); + } + catch (Exception e) + { + var msg = string.Format("RefreshProgramUptimebyIndex({0}) failed:\r{1}", index, e.Message); + CrestronConsole.PrintLine(msg); + //ErrorLog.Error(msg); + } + } + + /// + /// Sends command to console, passes response back using string change event + /// + /// + public void SendConsoleCommand(string cmd) + { + if (string.IsNullOrEmpty(cmd)) + return; + + string response = ""; + CrestronConsole.SendControlSystemCommand(cmd, ref response); + if (!string.IsNullOrEmpty(response)) + { + if (response.EndsWith("\x0D\\x0A")) + response.Trim('\n'); + + OnStringChange(response, 0, SystemInfoConstants.ConsoleResponseChange); + } + } + + /// + /// private method to parse console messages + /// + /// + /// + /// + /// + /// + private string ParseConsoleResponse(string data, string line, string dataStart, string dataEnd) + { + var response = ""; + + if (string.IsNullOrEmpty(data) || string.IsNullOrEmpty(line) || string.IsNullOrEmpty(dataStart) || string.IsNullOrEmpty(dataEnd)) + return response; + + try + { + var linePos = data.IndexOf(line); + var startPos = data.IndexOf(dataStart, linePos) + dataStart.Length; + var endPos = data.IndexOf(dataEnd, startPos); + response = data.Substring(startPos, endPos - startPos).Trim(); + } + catch (Exception e) + { + var msg = string.Format("ParseConsoleResponse failed: {0}", e.Message); + CrestronConsole.PrintLine(msg); + //ErrorLog.Error(msg); + } + + return response; + } + + /// + /// Protected boolean change event handler + /// + /// + /// + /// + protected void OnBoolChange(bool state, ushort index, ushort type) + { + var handler = BoolChange; + if (handler != null) + { + var args = new BoolChangeEventArgs(state, type); + args.Index = index; + BoolChange(this, args); + } + } + + /// + /// Protected string change event handler + /// + /// + /// + /// + protected void OnStringChange(string value, ushort index, ushort type) + { + var handler = StringChange; + if (handler != null) + { + var args = new StringChangeEventArgs(value, type); + args.Index = index; + StringChange(this, args); + } + } + + /// + /// Protected processor config change event handler + /// + /// + /// + /// + protected void OnProcessorChange(ProcessorInfo processor, ushort index, ushort type) + { + var handler = ProcessorChange; + if (handler != null) + { + var args = new ProcessorChangeEventArgs(processor, type); + args.Index = index; + ProcessorChange(this, args); + } + } + + /// + /// Ethernet change event handler + /// + /// + /// + /// + protected void OnEthernetInfoChange(EthernetInfo ethernet, ushort index, ushort type) + { + var handler = EthernetChange; + if (handler != null) + { + var args = new EthernetChangeEventArgs(ethernet, type); + args.Index = index; + EthernetChange(this, args); + } + } + + /// + /// Control Subnet change event handler + /// + /// + /// + /// + protected void OnControlSubnetInfoChange(ControlSubnetInfo ethernet, ushort index, ushort type) + { + var handler = ControlSubnetChange; + if (handler != null) + { + var args = new ControlSubnetChangeEventArgs(ethernet, type); + args.Index = index; + ControlSubnetChange(this, args); + } + } + + /// + /// Program change event handler + /// + /// + /// + /// + protected void OnProgramChange(ProgramInfo program, ushort index, ushort type) + { + var handler = ProgramChange; + if (handler != null) + { + var args = new ProgramChangeEventArgs(program, type); + args.Index = index; + ProgramChange(this, args); + } + } + } +} \ No newline at end of file