using System; using System.Collections.Generic; using System.Linq; using System.Text; using Crestron.SimplSharp; using PepperDash.Core; using PepperDash.Essentials.Core; using System.Text.RegularExpressions; namespace PepperDash.Essentials.Devices.Common { public class TVOneCorio : Device { public IBasicCommunication Communication { get; private set; } public CommunicationGather PortGather { get; private set; } public StatusMonitorBase CommunicationMonitor { get; private set; } public string userName; public string password; private bool OnlineStatus; public BoolFeedback OnlineFeedback; private ushort CurrentPreset; public IntFeedback PresetFeedback; // new public Dictionary LevelControlPoints { get; private set; } // public List PresetList = new List(); public bool isSubscribed; private CTimer SubscriptionTimer; CrestronQueue CommandQueue; bool CommandQueueInProgress = false; //new public Dictionary DialerControlPoints { get; private set; } //new public Dictionary SwitcherControlPoints { get; private set; } /// /// Shows received lines as hex /// public bool ShowHexResponse { get; set; } public TVOneCorio(string key, string name, IBasicCommunication comm, TVOneCorioPropertiesConfig props) : base(key, name) { this.userName = props.userName; this.password = props.password; CommandQueue = new CrestronQueue(100); Communication = comm; var socket = comm as ISocketStatus; if (socket != null) { // This instance uses IP control socket.ConnectionChange += new EventHandler(socket_ConnectionChange); } else { // This instance uses RS-232 control } PortGather = new CommunicationGather(Communication, "\x0a"); PortGather.LineReceived += this.Port_LineReceived; if (props.CommunicationMonitorProperties != null) { CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, props.CommunicationMonitorProperties); } else { //#warning Need to deal with this poll string CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 120000, 120000, 300000, "System.Status\x0A\x0D"); } } public override bool CustomActivate() { Communication.Connect(); CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); }; CommunicationMonitor.Start(); OnlineFeedback = new BoolFeedback(() => { return OnlineStatus; }); PresetFeedback = new IntFeedback(() => { return CurrentPreset; }); CrestronConsole.AddNewConsoleCommand(SendLine, "send" + Key, "", ConsoleAccessLevelEnum.AccessOperator); CrestronConsole.AddNewConsoleCommand(s => Communication.Connect(), "con" + Key, "", ConsoleAccessLevelEnum.AccessOperator); return true; } void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e) { Debug.Console(2, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString()); if (e.Client.IsConnected) { OnlineStatus = true; OnlineFeedback.FireUpdate(); } else { OnlineStatus = false; OnlineFeedback.FireUpdate(); if (SubscriptionTimer != null) { SubscriptionTimer.Stop(); SubscriptionTimer = null; } isSubscribed = false; CommandQueue.Clear(); CommandQueueInProgress = false; } } /// /// Initiates the subscription process to the DSP /// /// /// Handles a response message from the DSP /// /// /// void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args) { Debug.Console(2, this, "TVOneCurio RX: '{0}'", args.Text); try { if (args.Text.IndexOf("login") > -1) { SendLine(string.Format("Login({0},{1})", this.userName, this.password)); } else if (args.Text.IndexOf("!Done Preset.Take =") > -1) { string presetNumberParse = args.Text.Remove(0, args.Text.IndexOf("=") + 2); Debug.Console(1, this, "Preset Parse: {0}", presetNumberParse); CurrentPreset = ushort.Parse(presetNumberParse); PresetFeedback.FireUpdate(); } } catch (Exception e) { if (Debug.Level == 2) Debug.Console(2, this, "Error parsing response: '{0}'\n{1}", args.Text, e); } } /// /// Sends a command to the DSP (with delimiter appended) /// /// Command to send public void SendLine(string s) { Debug.Console(1, this, "TVOne Cusio TX: '{0}'", s); Communication.SendText(s + "\x0d\x0a"); } /// /// Adds a command from a child module to the queue /// /// Command object from child module public void EnqueueCommand(QueuedCommand commandToEnqueue) { CommandQueue.Enqueue(commandToEnqueue); //Debug.Console(1, this, "Command (QueuedCommand) Enqueued '{0}'. CommandQueue has '{1}' Elements.", commandToEnqueue.Command, CommandQueue.Count); if(!CommandQueueInProgress) SendNextQueuedCommand(); } /// /// Adds a raw string command to the queue /// /// public void EnqueueCommand(string command) { CommandQueue.Enqueue(command); //Debug.Console(1, this, "Command (string) Enqueued '{0}'. CommandQueue has '{1}' Elements.", command, CommandQueue.Count); if (!CommandQueueInProgress) SendNextQueuedCommand(); } /// /// Sends the next queued command to the DSP /// void SendNextQueuedCommand() { if (Communication.IsConnected && !CommandQueue.IsEmpty) { CommandQueueInProgress = true; if (CommandQueue.Peek() is QueuedCommand) { QueuedCommand nextCommand = new QueuedCommand(); nextCommand = (QueuedCommand)CommandQueue.Peek(); SendLine(nextCommand.Command); } else { string nextCommand = (string)CommandQueue.Peek(); SendLine(nextCommand); } } } public void CallPreset(ushort presetNumber) { SendLine(string.Format("Preset.Take = {0}", presetNumber)); // SendLine("cgp 1"); } public class QueuedCommand { public string Command { get; set; } public string AttributeCode { get; set; } // public QscDspControlPoint ControlPoint { get; set; } } } }