using System; using System.Collections.Generic; using System.Linq; using Crestron.SimplSharp; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; using Newtonsoft.Json.Linq; using PepperDash.Essentials.Core.Config; using PepperDash.Core; using Serilog.Events; using System.IO; using PepperDash.Core.Logging; namespace PepperDash.Essentials.Core { /// /// IR port wrapper. May act standalone /// public class IrOutputPortController : Device { uint IrPortUid; IROutputPort IrPort; /// /// Gets the DriverLoaded feedback /// public BoolFeedback DriverLoaded { get; private set; } /// /// Gets or sets the StandardIrPulseTime /// public ushort StandardIrPulseTime { get; set; } /// /// Gets or sets the DriverFilepath /// public string DriverFilepath { get; private set; } /// /// Gets or sets the DriverIsLoaded /// public bool DriverIsLoaded { get; private set; } /// /// Gets or sets the IrFileCommands /// public string[] IrFileCommands { get { return IrPort.AvailableStandardIRCmds(IrPortUid); } } /// /// Gets or sets the UseBridgeJoinMap /// public bool UseBridgeJoinMap { get; private set; } /// /// Constructor for IrDevice base class. If a null port is provided, this class will /// still function without trying to talk to a port. /// public IrOutputPortController(string key, IROutputPort port, string irDriverFilepath) : base(key) { //if (port == null) throw new ArgumentNullException("port"); DriverLoaded = new BoolFeedback(() => DriverIsLoaded); IrPort = port; if (port == null) { Debug.LogMessage(LogEventLevel.Information, this, "WARNING No valid IR Port assigned to controller. IR will not function"); return; } LoadDriver(irDriverFilepath); } /// /// Constructor for IrDevice base class using post activation function to get port /// /// key of the device /// function to call post activation /// config of the device public IrOutputPortController(string key, Func postActivationFunc, DeviceConfig config) : base(key) { DriverLoaded = new BoolFeedback(() => DriverIsLoaded); UseBridgeJoinMap = config.Properties["control"].Value("useBridgeJoinMap"); AddPostActivationAction(() => { IrPort = postActivationFunc(config); if (IrPort == null) { Debug.LogMessage(LogEventLevel.Information, this, "WARNING No valid IR Port assigned to controller. IR will not function"); return; } // var filePath = Global.FilePathPrefix + "ir" + Global.DirectorySeparator + config.Properties["control"]["irFile"].Value(); var fileName = config.Properties["control"]["irFile"].Value(); var files = Directory.GetFiles(Global.FilePathPrefix, fileName, SearchOption.AllDirectories); if(files.Length == 0) { this.LogError("IR file {fileName} not found in {path}", fileName, Global.FilePathPrefix); return; } if(files.Length > 1) { this.LogError("IR file {fileName} found in multiple locations: {files}", fileName, files); return; } var filePath = files[0]; Debug.LogMessage(LogEventLevel.Debug, "*************Attempting to load IR file: {0}***************", filePath); LoadDriver(filePath); PrintAvailableCommands(); }); } /// /// PrintAvailableCommands method /// public void PrintAvailableCommands() { Debug.LogMessage(LogEventLevel.Verbose, this, "Available IR Commands in IR File {0}", IrPortUid); foreach (var cmd in IrPort.AvailableIRCmds()) { Debug.LogMessage(LogEventLevel.Verbose, this, "{0}", cmd); } } /// /// Loads the IR driver at path /// /// path of the IR driver file public void LoadDriver(string path) { Debug.LogMessage(LogEventLevel.Verbose, this, "***Loading IR File***"); if (string.IsNullOrEmpty(path)) path = DriverFilepath; try { IrPortUid = IrPort.LoadIRDriver(path); DriverFilepath = path; StandardIrPulseTime = 200; DriverIsLoaded = true; DriverLoaded.FireUpdate(); } catch { DriverIsLoaded = false; var message = string.Format("WARNING IR Driver '{0}' failed to load", path); Debug.LogMessage(LogEventLevel.Information, this, message); DriverLoaded.FireUpdate(); } } /// /// PressRelease method /// /// IR command to send /// true to press, false to release /// public virtual void PressRelease(string command, bool state) { Debug.LogMessage(LogEventLevel.Verbose, this, "IR:'{0}'={1}", command, state); if (IrPort == null) { Debug.LogMessage(LogEventLevel.Verbose, this, "WARNING No IR Port assigned to controller"); return; } if (!DriverIsLoaded) { Debug.LogMessage(LogEventLevel.Verbose, this, "WARNING IR driver is not loaded"); return; } if (state) { if (IrPort.IsIRCommandAvailable(IrPortUid, command)) IrPort.Press(IrPortUid, command); else NoIrCommandError(command); } else IrPort.Release(); } /// /// Pulse method /// /// IR command to send /// time to pulse the command /// public virtual void Pulse(string command, ushort time) { if (IrPort == null) { Debug.LogMessage(LogEventLevel.Verbose, this, "WARNING No IR Port assigned to controller"); return; } if (!DriverIsLoaded) { Debug.LogMessage(LogEventLevel.Verbose, this, "WARNING IR driver is not loaded"); return; } if (IrPort.IsIRCommandAvailable(IrPortUid, command)) IrPort.PressAndRelease(IrPortUid, command, time); else NoIrCommandError(command); } /// /// Notifies the console when a bad command is used. /// /// command that was not found protected void NoIrCommandError(string command) { Debug.LogMessage(LogEventLevel.Verbose, this, "Device {0}: IR Driver {1} does not contain command {2}", Key, IrPort.IRDriverFileNameByIRDriverId(IrPortUid), command); } } }