using System; using Crestron.SimplSharp; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DM; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using PepperDash.Core; using PepperDash.Essentials.Core.Config; using Serilog.Events; namespace PepperDash.Essentials.Core { /// /// /// public class CommFactory { public static EssentialsControlPropertiesConfig GetControlPropertiesConfig(DeviceConfig deviceConfig) { try { return JsonConvert.DeserializeObject (deviceConfig.Properties["control"].ToString()); //Debug.LogMessage(LogEventLevel.Verbose, "Control TEST: {0}", JsonConvert.SerializeObject(controlConfig)); } catch (Exception e) { Debug.LogMessage(LogEventLevel.Information, "ERROR: [{0}] Control properties deserialize failed:\r{1}", deviceConfig.Key, e); return null; } } /// /// Returns a comm method of either com port, TCP, SSH, and puts this into the DeviceManager /// /// The Device config object /// /// CreateCommForDevice method /// public static IBasicCommunication CreateCommForDevice(DeviceConfig deviceConfig) { EssentialsControlPropertiesConfig controlConfig = GetControlPropertiesConfig(deviceConfig); if (controlConfig == null) return null; IBasicCommunication comm = null; try { var c = controlConfig.TcpSshProperties; switch (controlConfig.Method) { case eControlMethod.Com: comm = new ComPortController(deviceConfig.Key + "-com", GetComPort, controlConfig.ComParams.Value, controlConfig); break; case eControlMethod.Cec: comm = new CecPortController(deviceConfig.Key + "-cec", GetCecPort, controlConfig); break; case eControlMethod.IR: break; case eControlMethod.Ssh: { var ssh = new GenericSshClient(deviceConfig.Key + "-ssh", c.Address, c.Port, c.Username, c.Password); ssh.AutoReconnect = c.AutoReconnect; if(ssh.AutoReconnect) ssh.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs; comm = ssh; break; } case eControlMethod.Tcpip: { var tcp = new GenericTcpIpClient(deviceConfig.Key + "-tcp", c.Address, c.Port, c.BufferSize); tcp.AutoReconnect = c.AutoReconnect; if (tcp.AutoReconnect) tcp.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs; comm = tcp; break; } case eControlMethod.Udp: { var udp = new GenericUdpServer(deviceConfig.Key + "-udp", c.Address, c.Port, c.BufferSize); comm = udp; break; } case eControlMethod.Telnet: break; case eControlMethod.SecureTcpIp: { var secureTcp = new GenericSecureTcpIpClient(deviceConfig.Key + "-secureTcp", c.Address, c.Port, c.BufferSize); secureTcp.AutoReconnect = c.AutoReconnect; if (secureTcp.AutoReconnect) secureTcp.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs; comm = secureTcp; break; } default: break; } } catch (Exception e) { Debug.LogMessage(LogEventLevel.Information, "Cannot create communication from JSON:\r{0}\r\rException:\r{1}", deviceConfig.Properties.ToString(), e); } // put it in the device manager if it's the right flavor var comDev = comm as Device; if (comDev != null) DeviceManager.AddDevice(comDev); return comm; } /// /// GetComPort method /// public static ComPort GetComPort(EssentialsControlPropertiesConfig config) { var comPar = config.ComParams; var dev = GetIComPortsDeviceFromManagedDevice(config.ControlPortDevKey); if (dev != null && config.ControlPortNumber <= dev.NumberOfComPorts) return dev.ComPorts[config.ControlPortNumber.Value]; Debug.LogMessage(LogEventLevel.Information, "GetComPort: Device '{0}' does not have com port {1}", config.ControlPortDevKey, config.ControlPortNumber); return null; } /// /// Gets an ICec port from a RoutingInput or RoutingOutput on a device /// /// /// /// /// GetCecPort method /// public static ICec GetCecPort(ControlPropertiesConfig config) { try { var dev = DeviceManager.GetDeviceForKey(config.ControlPortDevKey); Debug.LogMessage(LogEventLevel.Information, "GetCecPort: device '{0}' {1}", config.ControlPortDevKey, dev == null ? "is not valid, failed to get cec port" : "found in device manager, attempting to get cec port"); if (dev == null) return null; if (String.IsNullOrEmpty(config.ControlPortName)) { Debug.LogMessage(LogEventLevel.Information, "GetCecPort: '{0}' - Configuration missing 'ControlPortName'", config.ControlPortDevKey); return null; } var inputsOutputs = dev as IRoutingInputsOutputs; if (inputsOutputs == null) { Debug.LogMessage(LogEventLevel.Information, "GetCecPort: Device '{0}' does not support IRoutingInputsOutputs, failed to get CEC port called '{1}'", config.ControlPortDevKey, config.ControlPortName); return null; } var inputPort = inputsOutputs.InputPorts[config.ControlPortName]; if (inputPort != null && inputPort.Port is ICec) return inputPort.Port as ICec; var outputPort = inputsOutputs.OutputPorts[config.ControlPortName]; if (outputPort != null && outputPort.Port is ICec) return outputPort.Port as ICec; } catch (Exception ex) { Debug.LogMessage(LogEventLevel.Debug, "GetCecPort Exception Message: {0}", ex.Message); Debug.LogMessage(LogEventLevel.Verbose, "GetCecPort Exception StackTrace: {0}", ex.StackTrace); if (ex.InnerException != null) Debug.LogMessage(LogEventLevel.Information, "GetCecPort Exception InnerException: {0}", ex.InnerException); } Debug.LogMessage(LogEventLevel.Information, "GetCecPort: Device '{0}' does not have a CEC port called '{1}'", config.ControlPortDevKey, config.ControlPortName); return null; } /// /// Helper to grab the IComPorts device for this PortDeviceKey. Key "controlSystem" will /// return the ControlSystem object from the Global class. /// /// IComPorts device or null if the device is not found or does not implement IComPorts /// /// GetIComPortsDeviceFromManagedDevice method /// public static IComPorts GetIComPortsDeviceFromManagedDevice(string ComPortDevKey) { if ((ComPortDevKey.Equals("controlSystem", System.StringComparison.OrdinalIgnoreCase) || ComPortDevKey.Equals("processor", System.StringComparison.OrdinalIgnoreCase)) && Global.ControlSystem is IComPorts) return Global.ControlSystem; else { var dev = DeviceManager.GetDeviceForKey(ComPortDevKey) as IComPorts; if (dev == null) Debug.LogMessage(LogEventLevel.Information, "ComPortConfig: Cannot find com port device '{0}'", ComPortDevKey); return dev; } } } /// /// Represents a EssentialsControlPropertiesConfig /// public class EssentialsControlPropertiesConfig : ControlPropertiesConfig { [JsonProperty("comParams", NullValueHandling = NullValueHandling.Ignore)] [JsonConverter(typeof(ComSpecJsonConverter))] public ComPort.ComPortSpec? ComParams { get; set; } [JsonProperty("cresnetId", NullValueHandling = NullValueHandling.Ignore)] public string CresnetId { get; set; } /// /// Attempts to provide uint conversion of string CresnetId /// [JsonIgnore] public uint CresnetIdInt { get { try { return Convert.ToUInt32(CresnetId, 16); } catch (Exception) { throw new FormatException(string.Format("ERROR:Unable to convert Cresnet ID: {0} to hex. Error:\n{1}", CresnetId)); } } } [JsonProperty("infinetId", NullValueHandling = NullValueHandling.Ignore)] /// /// Gets or sets the InfinetId /// public string InfinetId { get; set; } /// /// Attepmts to provide uiont conversion of string InifinetId /// [JsonIgnore] public uint InfinetIdInt { get { try { return Convert.ToUInt32(InfinetId, 16); } catch (Exception) { throw new FormatException(string.Format("ERROR:Unable to conver Infinet ID: {0} to hex. Error:\n{1}", InfinetId)); } } } } /// /// Represents a IrControlSpec /// public class IrControlSpec { /// /// Gets or sets the PortDeviceKey /// public string PortDeviceKey { get; set; } /// /// Gets or sets the PortNumber /// public uint PortNumber { get; set; } /// /// Gets or sets the File /// public string File { get; set; } } }