mirror of
https://github.com/PepperDash/Essentials.git
synced 2026-02-14 20:24:57 +00:00
feat: removed DSP, Lutron, Analog Way, TVOne
This commit is contained in:
@@ -1,396 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
using PepperDash.Core;
|
|
||||||
using PepperDash.Essentials.Core;
|
|
||||||
using PepperDash.Essentials.Core.Config;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
|
||||||
{
|
|
||||||
|
|
||||||
// QUESTIONS:
|
|
||||||
//
|
|
||||||
// When subscribing, just use the Instance ID for Custom Name?
|
|
||||||
|
|
||||||
// Verbose on subscriptions?
|
|
||||||
|
|
||||||
// Example subscription feedback responses
|
|
||||||
// ! "publishToken":"name" "value":-77.0
|
|
||||||
// ! "myLevelName" -77
|
|
||||||
|
|
||||||
public class BiampTesiraForteDsp : DspBase
|
|
||||||
{
|
|
||||||
public IBasicCommunication Communication { get; private set; }
|
|
||||||
public CommunicationGather PortGather { get; private set; }
|
|
||||||
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
|
||||||
|
|
||||||
public new Dictionary<string, TesiraForteLevelControl> LevelControlPoints { get; private set; }
|
|
||||||
|
|
||||||
public bool isSubscribed;
|
|
||||||
|
|
||||||
private CTimer SubscriptionTimer;
|
|
||||||
|
|
||||||
private CrestronQueue CommandQueue;
|
|
||||||
|
|
||||||
private bool CommandQueueInProgress = false;
|
|
||||||
|
|
||||||
//new public Dictionary<string, DspControlPoint> DialerControlPoints { get; private set; }
|
|
||||||
|
|
||||||
//new public Dictionary<string, DspControlPoint> SwitcherControlPoints { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Shows received lines as hex
|
|
||||||
/// </summary>
|
|
||||||
public bool ShowHexResponse { get; set; }
|
|
||||||
|
|
||||||
public BiampTesiraForteDsp(string key, string name, IBasicCommunication comm,
|
|
||||||
BiampTesiraFortePropertiesConfig props) :
|
|
||||||
base(key, name)
|
|
||||||
{
|
|
||||||
CommandQueue = new CrestronQueue(100);
|
|
||||||
|
|
||||||
Communication = comm;
|
|
||||||
var socket = comm as ISocketStatus;
|
|
||||||
if (socket != null)
|
|
||||||
{
|
|
||||||
// This instance uses IP control
|
|
||||||
|
|
||||||
socket.ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// This instance uses RS-232 control
|
|
||||||
}
|
|
||||||
PortGather = new CommunicationGather(Communication, "\x0d\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,
|
|
||||||
"SESSION get aliases\x0d\x0a");
|
|
||||||
}
|
|
||||||
|
|
||||||
LevelControlPoints = new Dictionary<string, TesiraForteLevelControl>();
|
|
||||||
|
|
||||||
foreach (KeyValuePair<string, BiampTesiraForteLevelControlBlockConfig> block in props.LevelControlBlocks)
|
|
||||||
{
|
|
||||||
this.LevelControlPoints.Add(block.Key, new TesiraForteLevelControl(block.Key, block.Value, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CustomActivate()
|
|
||||||
{
|
|
||||||
Communication.Connect();
|
|
||||||
CommunicationMonitor.StatusChange +=
|
|
||||||
(o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
|
||||||
CommunicationMonitor.Start();
|
|
||||||
|
|
||||||
CrestronConsole.AddNewConsoleCommand(SendLine, "send" + Key, "", ConsoleAccessLevelEnum.AccessOperator);
|
|
||||||
CrestronConsole.AddNewConsoleCommand(s => Communication.Connect(), "con" + Key, "",
|
|
||||||
ConsoleAccessLevelEnum.AccessOperator);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
|
|
||||||
{
|
|
||||||
Debug.Console(2, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
|
|
||||||
|
|
||||||
if (e.Client.IsConnected)
|
|
||||||
{
|
|
||||||
// Tasks on connect
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Cleanup items from this session
|
|
||||||
|
|
||||||
if (SubscriptionTimer != null)
|
|
||||||
{
|
|
||||||
SubscriptionTimer.Stop();
|
|
||||||
SubscriptionTimer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
isSubscribed = false;
|
|
||||||
CommandQueue.Clear();
|
|
||||||
CommandQueueInProgress = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initiates the subscription process to the DSP
|
|
||||||
/// </summary>
|
|
||||||
private void SubscribeToAttributes()
|
|
||||||
{
|
|
||||||
SendLine("SESSION set verbose true");
|
|
||||||
|
|
||||||
foreach (KeyValuePair<string, TesiraForteLevelControl> level in LevelControlPoints)
|
|
||||||
{
|
|
||||||
level.Value.Subscribe();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!CommandQueueInProgress)
|
|
||||||
SendNextQueuedCommand();
|
|
||||||
|
|
||||||
ResetSubscriptionTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Resets or Sets the subscription timer
|
|
||||||
/// </summary>
|
|
||||||
private void ResetSubscriptionTimer()
|
|
||||||
{
|
|
||||||
isSubscribed = true;
|
|
||||||
|
|
||||||
if (SubscriptionTimer != null)
|
|
||||||
{
|
|
||||||
SubscriptionTimer = new CTimer(o => SubscribeToAttributes(), 30000);
|
|
||||||
SubscriptionTimer.Reset();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles a response message from the DSP
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="dev"></param>
|
|
||||||
/// <param name="args"></param>
|
|
||||||
private void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (args.Text.IndexOf("Welcome to the Tesira Text Protocol Server...") > -1)
|
|
||||||
{
|
|
||||||
// Indicates a new TTP session
|
|
||||||
|
|
||||||
SubscribeToAttributes();
|
|
||||||
}
|
|
||||||
else if (args.Text.IndexOf("publishToken") > -1)
|
|
||||||
{
|
|
||||||
// response is from a subscribed attribute
|
|
||||||
|
|
||||||
string pattern = "! \"publishToken\":[\"](.*)[\"] \"value\":(.*)";
|
|
||||||
|
|
||||||
Match match = Regex.Match(args.Text, pattern);
|
|
||||||
|
|
||||||
if (match.Success)
|
|
||||||
{
|
|
||||||
|
|
||||||
string key;
|
|
||||||
|
|
||||||
string customName;
|
|
||||||
|
|
||||||
string value;
|
|
||||||
|
|
||||||
customName = match.Groups[1].Value;
|
|
||||||
|
|
||||||
// Finds the key (everything before the '~' character
|
|
||||||
key = customName.Substring(0, customName.IndexOf("~", 0) - 1);
|
|
||||||
|
|
||||||
value = match.Groups[2].Value;
|
|
||||||
|
|
||||||
foreach (KeyValuePair<string, TesiraForteLevelControl> controlPoint in LevelControlPoints)
|
|
||||||
{
|
|
||||||
if (customName == controlPoint.Value.LevelCustomName ||
|
|
||||||
customName == controlPoint.Value.MuteCustomName)
|
|
||||||
{
|
|
||||||
controlPoint.Value.ParseSubscriptionMessage(customName, value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// same for dialers
|
|
||||||
/// same for switchers
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (args.Text.IndexOf("+OK") > -1)
|
|
||||||
{
|
|
||||||
if (args.Text == "+OK" || args.Text.IndexOf("list\":") > -1)
|
|
||||||
// Check for a simple "+OK" only 'ack' repsonse or a list response and ignore
|
|
||||||
return;
|
|
||||||
|
|
||||||
// response is not from a subscribed attribute. From a get/set/toggle/increment/decrement command
|
|
||||||
|
|
||||||
if (!CommandQueue.IsEmpty)
|
|
||||||
{
|
|
||||||
if (CommandQueue.Peek() is QueuedCommand)
|
|
||||||
{
|
|
||||||
// Expected response belongs to a child class
|
|
||||||
QueuedCommand tempCommand = (QueuedCommand) CommandQueue.TryToDequeue();
|
|
||||||
//Debug.Console(1, this, "Command Dequeued. CommandQueue Size: {0}", CommandQueue.Count);
|
|
||||||
|
|
||||||
tempCommand.ControlPoint.ParseGetMessage(tempCommand.AttributeCode, args.Text);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Expected response belongs to this class
|
|
||||||
string temp = (string) CommandQueue.TryToDequeue();
|
|
||||||
//Debug.Console(1, this, "Command Dequeued. CommandQueue Size: {0}", CommandQueue.Count);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CommandQueue.IsEmpty)
|
|
||||||
CommandQueueInProgress = false;
|
|
||||||
else
|
|
||||||
SendNextQueuedCommand();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (args.Text.IndexOf("-ERR") > -1)
|
|
||||||
{
|
|
||||||
// Error response
|
|
||||||
|
|
||||||
switch (args.Text)
|
|
||||||
{
|
|
||||||
case "-ERR ALREADY_SUBSCRIBED":
|
|
||||||
{
|
|
||||||
ResetSubscriptionTimer();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
Debug.Console(0, this, "Error From DSP: '{0}'", args.Text);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
if (Debug.Level == 2)
|
|
||||||
Debug.Console(2, this, "Error parsing response: '{0}'\n{1}", args.Text, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sends a command to the DSP (with delimiter appended)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="s">Command to send</param>
|
|
||||||
public void SendLine(string s)
|
|
||||||
{
|
|
||||||
Communication.SendText(s + "\x0a");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a command from a child module to the queue
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="command">Command object from child module</param>
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a raw string command to the queue
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="command"></param>
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sends the next queued command to the DSP
|
|
||||||
/// </summary>
|
|
||||||
private void SendNextQueuedCommand()
|
|
||||||
{
|
|
||||||
//Debug.Console(2, this, "Attempting to send next queued command. CommandQueueInProgress: {0} Communication isConnected: {1}", CommandQueueInProgress, Communication.IsConnected);
|
|
||||||
|
|
||||||
//if (CommandQueue.IsEmpty)
|
|
||||||
// CommandQueueInProgress = false;
|
|
||||||
|
|
||||||
//Debug.Console(1, this, "CommandQueue has {0} Elements:\n", CommandQueue.Count);
|
|
||||||
|
|
||||||
//foreach (object o in CommandQueue)
|
|
||||||
//{
|
|
||||||
// if (o is string)
|
|
||||||
// Debug.Console(1, this, "{0}", o);
|
|
||||||
// else if(o is QueuedCommand)
|
|
||||||
// {
|
|
||||||
// var item = (QueuedCommand)o;
|
|
||||||
// Debug.Console(1, this, "{0}", item.Command);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//Debug.Console(1, this, "End of CommandQueue");
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sends a command to execute a preset
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="name">Preset Name</param>
|
|
||||||
public void RunPreset(string name)
|
|
||||||
{
|
|
||||||
SendLine(string.Format("DEVICE recallPreset {0}", name));
|
|
||||||
}
|
|
||||||
|
|
||||||
public class QueuedCommand
|
|
||||||
{
|
|
||||||
public string Command { get; set; }
|
|
||||||
public string AttributeCode { get; set; }
|
|
||||||
public TesiraForteControlPoint ControlPoint { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class BiampTesiraForteDspFactory : EssentialsDeviceFactory<BiampTesiraForteDsp>
|
|
||||||
{
|
|
||||||
public BiampTesiraForteDspFactory()
|
|
||||||
{
|
|
||||||
TypeNames = new List<string>() {"biamptesira"};
|
|
||||||
}
|
|
||||||
|
|
||||||
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
|
||||||
{
|
|
||||||
Debug.Console(1, "Factory Attempting to create new BiampTesira Device");
|
|
||||||
var comm = CommFactory.CreateCommForDevice(dc);
|
|
||||||
var props = Newtonsoft.Json.JsonConvert.DeserializeObject<BiampTesiraFortePropertiesConfig>(
|
|
||||||
dc.Properties.ToString());
|
|
||||||
return new BiampTesiraForteDsp(dc.Key, dc.Name, comm, props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,379 +0,0 @@
|
|||||||
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.DSP
|
|
||||||
{
|
|
||||||
public interface IBiampTesiraDspLevelControl : IBasicVolumeWithFeedback
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// In BiAmp: Instance Tag, QSC: Named Control, Polycom:
|
|
||||||
/// </summary>
|
|
||||||
string ControlPointTag { get; }
|
|
||||||
int Index1 { get; }
|
|
||||||
int Index2 { get; }
|
|
||||||
bool HasMute { get; }
|
|
||||||
bool HasLevel { get; }
|
|
||||||
bool AutomaticUnmuteOnVolumeUp { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class TesiraForteLevelControl : TesiraForteControlPoint, IBiampTesiraDspLevelControl, IKeyed
|
|
||||||
{
|
|
||||||
bool _IsMuted;
|
|
||||||
ushort _VolumeLevel;
|
|
||||||
|
|
||||||
public BoolFeedback MuteFeedback { get; private set; }
|
|
||||||
|
|
||||||
public IntFeedback VolumeLevelFeedback { get; private set; }
|
|
||||||
|
|
||||||
|
|
||||||
public bool Enabled { get; set; }
|
|
||||||
public string ControlPointTag { get { return base.InstanceTag; } }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Used for to identify level subscription values
|
|
||||||
/// </summary>
|
|
||||||
public string LevelCustomName { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Used for to identify mute subscription values
|
|
||||||
/// </summary>
|
|
||||||
public string MuteCustomName { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Minimum fader level
|
|
||||||
/// </summary>
|
|
||||||
double MinLevel;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Maximum fader level
|
|
||||||
/// </summary>
|
|
||||||
double MaxLevel;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks if a valid subscription string has been recieved for all subscriptions
|
|
||||||
/// </summary>
|
|
||||||
public bool IsSubsribed
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
bool isSubscribed = false;
|
|
||||||
|
|
||||||
if (HasMute && MuteIsSubscribed)
|
|
||||||
isSubscribed = true;
|
|
||||||
|
|
||||||
if (HasLevel && LevelIsSubscribed)
|
|
||||||
isSubscribed = true;
|
|
||||||
|
|
||||||
return isSubscribed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool AutomaticUnmuteOnVolumeUp { get; private set; }
|
|
||||||
|
|
||||||
public bool HasMute { get; private set; }
|
|
||||||
|
|
||||||
public bool HasLevel { get; private set; }
|
|
||||||
|
|
||||||
bool MuteIsSubscribed;
|
|
||||||
|
|
||||||
bool LevelIsSubscribed;
|
|
||||||
|
|
||||||
//public TesiraForteLevelControl(string label, string id, int index1, int index2, bool hasMute, bool hasLevel, BiampTesiraForteDsp parent)
|
|
||||||
// : base(id, index1, index2, parent)
|
|
||||||
//{
|
|
||||||
// Initialize(label, hasMute, hasLevel);
|
|
||||||
//}
|
|
||||||
|
|
||||||
public TesiraForteLevelControl(string key, BiampTesiraForteLevelControlBlockConfig config, BiampTesiraForteDsp parent)
|
|
||||||
: base(config.InstanceTag, config.Index1, config.Index2, parent)
|
|
||||||
{
|
|
||||||
Initialize(key, config.Label, config.HasMute, config.HasLevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes this attribute based on config values and generates subscriptions commands and adds commands to the parent's queue.
|
|
||||||
/// </summary>
|
|
||||||
public void Initialize(string key, string label, bool hasMute, bool hasLevel)
|
|
||||||
{
|
|
||||||
Key = string.Format("{0}--{1}", Parent.Key, key);
|
|
||||||
|
|
||||||
DeviceManager.AddDevice(this);
|
|
||||||
|
|
||||||
Debug.Console(2, this, "Adding LevelControl '{0}'", Key);
|
|
||||||
|
|
||||||
this.IsSubscribed = false;
|
|
||||||
|
|
||||||
MuteFeedback = new BoolFeedback(() => _IsMuted);
|
|
||||||
|
|
||||||
VolumeLevelFeedback = new IntFeedback(() => _VolumeLevel);
|
|
||||||
|
|
||||||
HasMute = hasMute;
|
|
||||||
HasLevel = hasLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Subscribe()
|
|
||||||
{
|
|
||||||
// Do subscriptions and blah blah
|
|
||||||
|
|
||||||
// Subscribe to mute
|
|
||||||
if (this.HasMute)
|
|
||||||
{
|
|
||||||
MuteCustomName = string.Format("{0}~mute{1}", this.InstanceTag, this.Index1);
|
|
||||||
|
|
||||||
SendSubscriptionCommand(MuteCustomName, "mute", 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Subscribe to level
|
|
||||||
if (this.HasLevel)
|
|
||||||
{
|
|
||||||
LevelCustomName = string.Format("{0}~level{1}", this.InstanceTag, this.Index1);
|
|
||||||
|
|
||||||
SendSubscriptionCommand(LevelCustomName, "level", 250);
|
|
||||||
|
|
||||||
SendFullCommand("get", "minLevel", null);
|
|
||||||
|
|
||||||
SendFullCommand("get", "maxLevel", null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses the response from the DspBase
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="customName"></param>
|
|
||||||
/// <param name="value"></param>
|
|
||||||
public void ParseSubscriptionMessage(string customName, string value)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Check for valid subscription response
|
|
||||||
|
|
||||||
if (this.HasMute && customName == MuteCustomName)
|
|
||||||
{
|
|
||||||
//if (value.IndexOf("+OK") > -1)
|
|
||||||
//{
|
|
||||||
// int pointer = value.IndexOf(" +OK");
|
|
||||||
|
|
||||||
// MuteIsSubscribed = true;
|
|
||||||
|
|
||||||
// // Removes the +OK
|
|
||||||
// value = value.Substring(0, value.Length - (value.Length - (pointer - 1)));
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (value.IndexOf("true") > -1)
|
|
||||||
{
|
|
||||||
_IsMuted = true;
|
|
||||||
MuteIsSubscribed = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (value.IndexOf("false") > -1)
|
|
||||||
{
|
|
||||||
_IsMuted = false;
|
|
||||||
MuteIsSubscribed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MuteFeedback.FireUpdate();
|
|
||||||
}
|
|
||||||
else if (this.HasLevel && customName == LevelCustomName)
|
|
||||||
{
|
|
||||||
//if (value.IndexOf("+OK") > -1)
|
|
||||||
//{
|
|
||||||
// int pointer = value.IndexOf(" +OK");
|
|
||||||
|
|
||||||
// LevelIsSubscribed = true;
|
|
||||||
|
|
||||||
//}
|
|
||||||
|
|
||||||
var _value = Double.Parse(value);
|
|
||||||
|
|
||||||
_VolumeLevel = (ushort)Scale(_value, MinLevel, MaxLevel, 0, 65535);
|
|
||||||
|
|
||||||
LevelIsSubscribed = true;
|
|
||||||
|
|
||||||
VolumeLevelFeedback.FireUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Parses a non subscription response
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="attributeCode">The attribute code of the command</param>
|
|
||||||
/// <param name="message">The message to parse</param>
|
|
||||||
public override void ParseGetMessage(string attributeCode, string message)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Parse an "+OK" message
|
|
||||||
string pattern = @"\+OK ""value"":(.*)";
|
|
||||||
|
|
||||||
Match match = Regex.Match(message, pattern);
|
|
||||||
|
|
||||||
if (match.Success)
|
|
||||||
{
|
|
||||||
|
|
||||||
string value = match.Groups[1].Value;
|
|
||||||
|
|
||||||
Debug.Console(1, this, "Response: '{0}' Value: '{1}'", attributeCode, value);
|
|
||||||
|
|
||||||
if (message.IndexOf("\"value\":") > -1)
|
|
||||||
{
|
|
||||||
switch (attributeCode)
|
|
||||||
{
|
|
||||||
case "minLevel":
|
|
||||||
{
|
|
||||||
MinLevel = Double.Parse(value);
|
|
||||||
|
|
||||||
Debug.Console(1, this, "MinLevel is '{0}'", MinLevel);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "maxLevel":
|
|
||||||
{
|
|
||||||
MaxLevel = Double.Parse(value);
|
|
||||||
|
|
||||||
Debug.Console(1, this, "MaxLevel is '{0}'", MaxLevel);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
Debug.Console(2, "Response does not match expected attribute codes: '{0}'", message);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Debug.Console(2, "Unable to parse message: '{0}'\n{1}", message, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Turns the mute off
|
|
||||||
/// </summary>
|
|
||||||
public void MuteOff()
|
|
||||||
{
|
|
||||||
SendFullCommand("set", "mute", "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Turns the mute on
|
|
||||||
/// </summary>
|
|
||||||
public void MuteOn()
|
|
||||||
{
|
|
||||||
SendFullCommand("set", "mute", "true");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the volume to a specified level
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="level"></param>
|
|
||||||
public void SetVolume(ushort level)
|
|
||||||
{
|
|
||||||
Debug.Console(1, this, "volume: {0}", level);
|
|
||||||
// Unmute volume if new level is higher than existing
|
|
||||||
if (level > _VolumeLevel && AutomaticUnmuteOnVolumeUp)
|
|
||||||
if(_IsMuted)
|
|
||||||
MuteOff();
|
|
||||||
|
|
||||||
double volumeLevel = Scale(level, 0, 65535, MinLevel, MaxLevel);
|
|
||||||
|
|
||||||
SendFullCommand("set", "level", string.Format("{0:0.000000}", volumeLevel));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Toggles mute status
|
|
||||||
/// </summary>
|
|
||||||
public void MuteToggle()
|
|
||||||
{
|
|
||||||
SendFullCommand("toggle", "mute", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Decrements volume level
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pressRelease"></param>
|
|
||||||
public void VolumeDown(bool pressRelease)
|
|
||||||
{
|
|
||||||
SendFullCommand("decrement", "level", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Increments volume level
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="pressRelease"></param>
|
|
||||||
public void VolumeUp(bool pressRelease)
|
|
||||||
{
|
|
||||||
SendFullCommand("increment", "level", "");
|
|
||||||
|
|
||||||
if (AutomaticUnmuteOnVolumeUp)
|
|
||||||
if (!_IsMuted)
|
|
||||||
MuteOff();
|
|
||||||
}
|
|
||||||
|
|
||||||
///// <summary>
|
|
||||||
///// Scales the input from the input range to the output range
|
|
||||||
///// </summary>
|
|
||||||
///// <param name="input"></param>
|
|
||||||
///// <param name="inMin"></param>
|
|
||||||
///// <param name="inMax"></param>
|
|
||||||
///// <param name="outMin"></param>
|
|
||||||
///// <param name="outMax"></param>
|
|
||||||
///// <returns></returns>
|
|
||||||
//int Scale(int input, int inMin, int inMax, int outMin, int outMax)
|
|
||||||
//{
|
|
||||||
// Debug.Console(1, this, "Scaling (int) input '{0}' with min '{1}'/max '{2}' to output range min '{3}'/max '{4}'", input, inMin, inMax, outMin, outMax);
|
|
||||||
|
|
||||||
// int inputRange = inMax - inMin;
|
|
||||||
|
|
||||||
// int outputRange = outMax - outMin;
|
|
||||||
|
|
||||||
// var output = (((input-inMin) * outputRange) / inputRange ) - outMin;
|
|
||||||
|
|
||||||
// Debug.Console(1, this, "Scaled output '{0}'", output);
|
|
||||||
|
|
||||||
// return output;
|
|
||||||
//}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Scales the input from the input range to the output range
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="input"></param>
|
|
||||||
/// <param name="inMin"></param>
|
|
||||||
/// <param name="inMax"></param>
|
|
||||||
/// <param name="outMin"></param>
|
|
||||||
/// <param name="outMax"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
double Scale(double input, double inMin, double inMax, double outMin, double outMax)
|
|
||||||
{
|
|
||||||
Debug.Console(1, this, "Scaling (double) input '{0}' with min '{1}'/max '{2}' to output range min '{3}'/max '{4}'",input ,inMin ,inMax ,outMin, outMax);
|
|
||||||
|
|
||||||
double inputRange = inMax - inMin;
|
|
||||||
|
|
||||||
if (inputRange <= 0)
|
|
||||||
{
|
|
||||||
throw new ArithmeticException(string.Format("Invalid Input Range '{0}' for Scaling. Min '{1}' Max '{2}'.", inputRange, inMin, inMax));
|
|
||||||
}
|
|
||||||
|
|
||||||
double outputRange = outMax - outMin;
|
|
||||||
|
|
||||||
var output = (((input - inMin) * outputRange) / inputRange) + outMin;
|
|
||||||
|
|
||||||
Debug.Console(1, this, "Scaled output '{0}'", output);
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
|
|
||||||
using PepperDash.Core;
|
|
||||||
using PepperDash.Essentials.Core;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class BiampTesiraFortePropertiesConfig
|
|
||||||
{
|
|
||||||
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
|
|
||||||
|
|
||||||
public ControlPropertiesConfig Control { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// These are key-value pairs, string id, string type.
|
|
||||||
/// Valid types are level and mute.
|
|
||||||
/// Need to include the index values somehow
|
|
||||||
/// </summary>
|
|
||||||
public Dictionary<string, BiampTesiraForteLevelControlBlockConfig> LevelControlBlocks { get; set; }
|
|
||||||
// public Dictionary<string, BiampTesiraForteDialerControlBlockConfig> DialerControlBlocks {get; set;}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class BiampTesiraForteLevelControlBlockConfig
|
|
||||||
{
|
|
||||||
public bool Enabled { get; set; }
|
|
||||||
public string Label { get; set; }
|
|
||||||
public string InstanceTag { get; set; }
|
|
||||||
public int Index1 { get; set; }
|
|
||||||
public int Index2 { get; set; }
|
|
||||||
public bool HasMute { get; set; }
|
|
||||||
public bool HasLevel { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
|
||||||
{
|
|
||||||
public abstract class TesiraForteControlPoint : DspControlPoint
|
|
||||||
{
|
|
||||||
public string Key { get; protected set; }
|
|
||||||
|
|
||||||
public string InstanceTag { get; set; }
|
|
||||||
public int Index1 { get; private set; }
|
|
||||||
public int Index2 { get; private set; }
|
|
||||||
public BiampTesiraForteDsp Parent { get; private set; }
|
|
||||||
|
|
||||||
public bool IsSubscribed { get; protected set; }
|
|
||||||
|
|
||||||
protected TesiraForteControlPoint(string id, int index1, int index2, BiampTesiraForteDsp parent)
|
|
||||||
{
|
|
||||||
InstanceTag = id;
|
|
||||||
Index1 = index1;
|
|
||||||
Index2 = index2;
|
|
||||||
Parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual public void Initialize()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sends a command to the DSP
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="command">command</param>
|
|
||||||
/// <param name="attribute">attribute code</param>
|
|
||||||
/// <param name="value">value (use "" if not applicable)</param>
|
|
||||||
public virtual void SendFullCommand(string command, string attributeCode, string value)
|
|
||||||
{
|
|
||||||
// Command Format: InstanceTag get/set/toggle/increment/decrement/subscribe/unsubscribe attributeCode [index] [value]
|
|
||||||
// Ex: "RoomLevel set level 1.00"
|
|
||||||
|
|
||||||
string cmd;
|
|
||||||
|
|
||||||
if (attributeCode == "level" || attributeCode == "mute" || attributeCode == "minLevel" || attributeCode == "maxLevel" || attributeCode == "label" || attributeCode == "rampInterval" || attributeCode == "rampStep")
|
|
||||||
{
|
|
||||||
//Command requires Index
|
|
||||||
|
|
||||||
if (String.IsNullOrEmpty(value))
|
|
||||||
{
|
|
||||||
// format command without value
|
|
||||||
cmd = string.Format("{0} {1} {2} {3}", InstanceTag, command, attributeCode, Index1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// format commadn with value
|
|
||||||
cmd = string.Format("{0} {1} {2} {3} {4}", InstanceTag, command, attributeCode, Index1, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Command does not require Index
|
|
||||||
|
|
||||||
if (String.IsNullOrEmpty(value))
|
|
||||||
{
|
|
||||||
cmd = string.Format("{0} {1} {2} {3}", InstanceTag, command, attributeCode, value);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cmd = string.Format("{0} {1} {2}", InstanceTag, command, attributeCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command == "get")
|
|
||||||
{
|
|
||||||
// This command will generate a return value response so it needs to be queued
|
|
||||||
Parent.EnqueueCommand(new BiampTesiraForteDsp.QueuedCommand{ Command = cmd, AttributeCode = attributeCode, ControlPoint = this });
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// This command will generate a simple "+OK" response and doesn't need to be queued
|
|
||||||
Parent.SendLine(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual public void ParseGetMessage(string attributeCode, string message)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public virtual void SendSubscriptionCommand(string customName, string attributeCode, int responseRate)
|
|
||||||
{
|
|
||||||
// Subscription string format: InstanceTag subscribe attributeCode Index1 customName responseRate
|
|
||||||
// Ex: "RoomLevel subscribe level 1 MyRoomLevel 500"
|
|
||||||
|
|
||||||
string cmd;
|
|
||||||
|
|
||||||
if (responseRate > 0)
|
|
||||||
{
|
|
||||||
cmd = string.Format("{0} subscribe {1} {2} {3} {4}", InstanceTag, attributeCode, Index1, customName, responseRate);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cmd = string.Format("{0} subscribe {1} {2} {3}", InstanceTag, attributeCode, Index1, customName);
|
|
||||||
}
|
|
||||||
|
|
||||||
Parent.SendLine(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
|
|
||||||
using PepperDash.Core;
|
|
||||||
using PepperDash.Essentials.Core;
|
|
||||||
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
|
||||||
{
|
|
||||||
|
|
||||||
//QUESTIONS:
|
|
||||||
|
|
||||||
//When subscribing, just use the Instance ID for Custom Name?
|
|
||||||
|
|
||||||
//Verbose on subscriptions?
|
|
||||||
|
|
||||||
//! "publishToken":"name" "value":-77.0
|
|
||||||
//! "myLevelName" -77
|
|
||||||
|
|
||||||
//public class TesiraForteMuteControl : IDspLevelControl
|
|
||||||
//{
|
|
||||||
// BiampTesiraForteDsp Parent;
|
|
||||||
// bool _IsMuted;
|
|
||||||
// ushort _VolumeLevel;
|
|
||||||
|
|
||||||
// public TesiraForteMuteControl(string id, BiampTesiraForteDsp parent)
|
|
||||||
// : base(id)
|
|
||||||
// {
|
|
||||||
// Parent = parent;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public void Initialize()
|
|
||||||
// {
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// protected override Func<bool> MuteFeedbackFunc
|
|
||||||
// {
|
|
||||||
// get { return () => _IsMuted; }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// protected override Func<int> VolumeLevelFeedbackFunc
|
|
||||||
// {
|
|
||||||
// get { return () => _VolumeLevel; }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override void MuteOff()
|
|
||||||
// {
|
|
||||||
// throw new NotImplementedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override void MuteOn()
|
|
||||||
// {
|
|
||||||
// throw new NotImplementedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override void SetVolume(ushort level)
|
|
||||||
// {
|
|
||||||
// throw new NotImplementedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override void MuteToggle()
|
|
||||||
// {
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override void VolumeDown(bool pressRelease)
|
|
||||||
// {
|
|
||||||
// throw new NotImplementedException();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// public override void VolumeUp(bool pressRelease)
|
|
||||||
// {
|
|
||||||
// throw new NotImplementedException();
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
|
|
||||||
using PepperDash.Essentials.Core;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.DSP
|
|
||||||
{
|
|
||||||
public class SoundStructureBasics
|
|
||||||
{
|
|
||||||
// public Dictionary<string, IBiampTesiraDspLevelControl> Levels { get; private set; }
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
using Crestron.SimplSharpPro;
|
|
||||||
using Crestron.SimplSharpPro.DeviceSupport;
|
|
||||||
using Crestron.SimplSharpPro.Lighting;
|
|
||||||
|
|
||||||
using PepperDash.Core;
|
|
||||||
using PepperDash.Essentials.Core;
|
|
||||||
using PepperDash.Essentials.Core.Config;
|
|
||||||
using PepperDash.Essentials.Core.CrestronIO;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.Environment.Lighting
|
|
||||||
{
|
|
||||||
public class Din8sw8Controller : EssentialsDevice, ISwitchedOutputCollection
|
|
||||||
{
|
|
||||||
// Need to figure out some sort of interface to make these switched outputs behave like processor relays so they can be used interchangably
|
|
||||||
|
|
||||||
public Din8Sw8 SwitchModule { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Collection of generic switched outputs
|
|
||||||
/// </summary>
|
|
||||||
public Dictionary<uint, ISwitchedOutput> SwitchedOutputs { get; private set; }
|
|
||||||
|
|
||||||
public Din8sw8Controller(string key, uint cresnetId)
|
|
||||||
: base(key)
|
|
||||||
{
|
|
||||||
SwitchedOutputs = new Dictionary<uint, ISwitchedOutput>();
|
|
||||||
|
|
||||||
SwitchModule = new Din8Sw8(cresnetId, Global.ControlSystem);
|
|
||||||
|
|
||||||
if (SwitchModule.Register() != eDeviceRegistrationUnRegistrationResponse.Success)
|
|
||||||
{
|
|
||||||
Debug.Console(2, this, "Error registering Din8sw8. Reason: {0}", SwitchModule.RegistrationFailureReason);
|
|
||||||
}
|
|
||||||
|
|
||||||
PopulateDictionary();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CustomActivate()
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
return base.CustomActivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Populates the generic collection with the loads from the Crestron collection
|
|
||||||
/// </summary>
|
|
||||||
void PopulateDictionary()
|
|
||||||
{
|
|
||||||
foreach (var item in SwitchModule.SwitchedLoads)
|
|
||||||
{
|
|
||||||
SwitchedOutputs.Add(item.Number, new Din8sw8Output(item));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Wrapper class to
|
|
||||||
/// </summary>
|
|
||||||
public class Din8sw8Output : ISwitchedOutput
|
|
||||||
{
|
|
||||||
SwitchedLoadWithOverrideParameter SwitchedOutput;
|
|
||||||
|
|
||||||
public BoolFeedback OutputIsOnFeedback { get; protected set; }
|
|
||||||
|
|
||||||
public Din8sw8Output(SwitchedLoadWithOverrideParameter switchedOutput)
|
|
||||||
{
|
|
||||||
SwitchedOutput = switchedOutput;
|
|
||||||
|
|
||||||
OutputIsOnFeedback = new BoolFeedback(new Func<bool>(() => SwitchedOutput.IsOn));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void On()
|
|
||||||
{
|
|
||||||
SwitchedOutput.FullOn();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Off()
|
|
||||||
{
|
|
||||||
SwitchedOutput.FullOff();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Din8sw8ControllerFactory : EssentialsDeviceFactory<Din8sw8Controller>
|
|
||||||
{
|
|
||||||
public Din8sw8ControllerFactory()
|
|
||||||
{
|
|
||||||
TypeNames = new List<string>() { "din8sw8" };
|
|
||||||
}
|
|
||||||
|
|
||||||
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
|
||||||
{
|
|
||||||
Debug.Console(1, "Factory Attempting to create new Din8sw8Controller Device");
|
|
||||||
var comm = CommFactory.GetControlPropertiesConfig(dc);
|
|
||||||
|
|
||||||
return new Din8sw8Controller(dc.Key, comm.CresnetIdInt);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,286 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
using Crestron.SimplSharpPro.DeviceSupport;
|
|
||||||
using PepperDash.Core;
|
|
||||||
using PepperDash.Essentials.Core;
|
|
||||||
using PepperDash.Essentials.Core.Config;
|
|
||||||
using PepperDash.Essentials.Core.Bridges;
|
|
||||||
using PepperDash.Essentials.Core.Lighting;
|
|
||||||
using LightingBase = PepperDash.Essentials.Core.Lighting.LightingBase;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common.Environment.Lutron
|
|
||||||
{
|
|
||||||
public class LutronQuantumArea : LightingBase, ILightingMasterRaiseLower, ICommunicationMonitor
|
|
||||||
{
|
|
||||||
public IBasicCommunication Communication { get; private set; }
|
|
||||||
public CommunicationGather PortGather { get; private set; }
|
|
||||||
public StatusMonitorBase CommunicationMonitor { get; private set; }
|
|
||||||
|
|
||||||
CTimer SubscribeAfterLogin;
|
|
||||||
|
|
||||||
public string IntegrationId;
|
|
||||||
string Username;
|
|
||||||
string Password;
|
|
||||||
|
|
||||||
const string Delimiter = "\x0d\x0a";
|
|
||||||
const string Set = "#";
|
|
||||||
const string Get = "?";
|
|
||||||
|
|
||||||
public LutronQuantumArea(string key, string name, IBasicCommunication comm, LutronQuantumPropertiesConfig props)
|
|
||||||
: base(key, name)
|
|
||||||
{
|
|
||||||
Communication = comm;
|
|
||||||
|
|
||||||
IntegrationId = props.IntegrationId;
|
|
||||||
|
|
||||||
if (props.Control.Method != eControlMethod.Com)
|
|
||||||
{
|
|
||||||
|
|
||||||
Username = props.Control.TcpSshProperties.Username;
|
|
||||||
Password = props.Control.TcpSshProperties.Password;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LightingScenes = props.Scenes;
|
|
||||||
|
|
||||||
var socket = comm as ISocketStatus;
|
|
||||||
if (socket != null)
|
|
||||||
{
|
|
||||||
// IP Control
|
|
||||||
socket.ConnectionChange += new EventHandler<GenericSocketStatusChageEventArgs>(socket_ConnectionChange);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// RS-232 Control
|
|
||||||
}
|
|
||||||
|
|
||||||
Communication.TextReceived += new EventHandler<GenericCommMethodReceiveTextArgs>(Communication_TextReceived);
|
|
||||||
|
|
||||||
PortGather = new CommunicationGather(Communication, Delimiter);
|
|
||||||
PortGather.LineReceived += new EventHandler<GenericCommMethodReceiveTextArgs>(PortGather_LineReceived);
|
|
||||||
|
|
||||||
if (props.CommunicationMonitorProperties != null)
|
|
||||||
{
|
|
||||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, props.CommunicationMonitorProperties);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 120000, 120000, 300000, "?ETHERNET,0\x0d\x0a");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool CustomActivate()
|
|
||||||
{
|
|
||||||
Communication.Connect();
|
|
||||||
CommunicationMonitor.StatusChange += (o, a) => { Debug.Console(2, this, "Communication monitor state: {0}", CommunicationMonitor.Status); };
|
|
||||||
CommunicationMonitor.Start();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge)
|
|
||||||
{
|
|
||||||
var joinMap = LinkLightingToApi(this, trilist, joinStart, joinMapKey, bridge);
|
|
||||||
|
|
||||||
CommunicationMonitor.IsOnlineFeedback.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]);
|
|
||||||
trilist.SetStringSigAction(joinMap.IntegrationIdSet.JoinNumber , s => IntegrationId = s);
|
|
||||||
}
|
|
||||||
|
|
||||||
void socket_ConnectionChange(object sender, GenericSocketStatusChageEventArgs e)
|
|
||||||
{
|
|
||||||
Debug.Console(2, this, "Socket Status Change: {0}", e.Client.ClientStatus.ToString());
|
|
||||||
|
|
||||||
if (e.Client.IsConnected)
|
|
||||||
{
|
|
||||||
// Tasks on connect
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Checks for responses that do not contain the delimiter
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender"></param>
|
|
||||||
/// <param name="args"></param>
|
|
||||||
void Communication_TextReceived(object sender, GenericCommMethodReceiveTextArgs args)
|
|
||||||
{
|
|
||||||
Debug.Console(2, this, "Text Received: '{0}'", args.Text);
|
|
||||||
|
|
||||||
if (args.Text.Contains("login:"))
|
|
||||||
{
|
|
||||||
// Login
|
|
||||||
SendLine(Username);
|
|
||||||
}
|
|
||||||
else if (args.Text.Contains("password:"))
|
|
||||||
{
|
|
||||||
// Login
|
|
||||||
SendLine(Password);
|
|
||||||
SubscribeAfterLogin = new CTimer(x => SubscribeToFeedback(), null, 5000);
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (args.Text.Contains("Access Granted"))
|
|
||||||
{
|
|
||||||
if (SubscribeAfterLogin != null)
|
|
||||||
{
|
|
||||||
SubscribeAfterLogin.Stop();
|
|
||||||
}
|
|
||||||
SubscribeToFeedback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles all responses that contain the delimiter
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender"></param>
|
|
||||||
/// <param name="args"></param>
|
|
||||||
void PortGather_LineReceived(object sender, GenericCommMethodReceiveTextArgs args)
|
|
||||||
{
|
|
||||||
Debug.Console(2, this, "Line Received: '{0}'", args.Text);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (args.Text.Contains("~AREA"))
|
|
||||||
{
|
|
||||||
var response = args.Text.Split(',');
|
|
||||||
|
|
||||||
var integrationId = response[1];
|
|
||||||
|
|
||||||
if (integrationId != IntegrationId)
|
|
||||||
{
|
|
||||||
Debug.Console(2, this, "Response is not for correct Integration ID");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var action = Int32.Parse(response[2]);
|
|
||||||
|
|
||||||
switch (action)
|
|
||||||
{
|
|
||||||
case (int)eAction.Scene:
|
|
||||||
{
|
|
||||||
var scene = response[3];
|
|
||||||
CurrentLightingScene = LightingScenes.FirstOrDefault(s => s.ID.Equals(scene));
|
|
||||||
|
|
||||||
OnLightingSceneChange();
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Debug.Console(2, this, "Error parsing response:\n{0}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Subscribes to feedback
|
|
||||||
/// </summary>
|
|
||||||
public void SubscribeToFeedback()
|
|
||||||
{
|
|
||||||
Debug.Console(1, "Sending Monitoring Subscriptions");
|
|
||||||
SendLine("#MONITORING,6,1");
|
|
||||||
SendLine("#MONITORING,8,1");
|
|
||||||
SendLine("#MONITORING,5,2");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Recalls the specified scene
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="scene"></param>
|
|
||||||
///
|
|
||||||
|
|
||||||
public override void SelectScene(LightingScene scene)
|
|
||||||
{
|
|
||||||
Debug.Console(1, this, "Selecting Scene: '{0}'", scene.Name);
|
|
||||||
SendLine(string.Format("{0}AREA,{1},{2},{3}", Set, IntegrationId, (int)eAction.Scene, scene.ID));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Begins raising the lights in the area
|
|
||||||
/// </summary>
|
|
||||||
public void MasterRaise()
|
|
||||||
{
|
|
||||||
SendLine(string.Format("{0}AREA,{1},{2}", Set, IntegrationId, (int)eAction.Raise));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Begins lowering the lights in the area
|
|
||||||
/// </summary>
|
|
||||||
public void MasterLower()
|
|
||||||
{
|
|
||||||
SendLine(string.Format("{0}AREA,{1},{2}", Set, IntegrationId, (int)eAction.Lower));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Stops the current raise/lower action
|
|
||||||
/// </summary>
|
|
||||||
public void MasterRaiseLowerStop()
|
|
||||||
{
|
|
||||||
SendLine(string.Format("{0}AREA,{1},{2}", Set, IntegrationId, (int)eAction.Stop));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Appends the delimiter and sends the string
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="s"></param>
|
|
||||||
public void SendLine(string s)
|
|
||||||
{
|
|
||||||
Communication.SendText(s + Delimiter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum eAction : int
|
|
||||||
{
|
|
||||||
SetLevel = 1,
|
|
||||||
Raise = 2,
|
|
||||||
Lower = 3,
|
|
||||||
Stop = 4,
|
|
||||||
Scene = 6,
|
|
||||||
DaylightMode = 7,
|
|
||||||
OccupancyState = 8,
|
|
||||||
OccupancyMode = 9,
|
|
||||||
OccupiedLevelOrScene = 12,
|
|
||||||
UnoccupiedLevelOrScene = 13,
|
|
||||||
HyperionShaddowSensorOverrideState = 26,
|
|
||||||
HyperionBrightnessSensorOverrideStatue = 27
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LutronQuantumPropertiesConfig
|
|
||||||
{
|
|
||||||
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
|
|
||||||
public ControlPropertiesConfig Control { get; set; }
|
|
||||||
|
|
||||||
public string IntegrationId { get; set; }
|
|
||||||
public List<LightingScene> Scenes { get; set; }
|
|
||||||
|
|
||||||
// Moved to use existing properties in Control object
|
|
||||||
// public string Username { get; set; }
|
|
||||||
// public string Password { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class LutronQuantumAreaFactory : EssentialsDeviceFactory<LutronQuantumArea>
|
|
||||||
{
|
|
||||||
public LutronQuantumAreaFactory()
|
|
||||||
{
|
|
||||||
TypeNames = new List<string>() { "lutronqs" };
|
|
||||||
}
|
|
||||||
|
|
||||||
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
|
||||||
{
|
|
||||||
Debug.Console(1, "Factory Attempting to create new LutronQuantumArea Device");
|
|
||||||
var comm = CommFactory.CreateCommForDevice(dc);
|
|
||||||
|
|
||||||
var props = Newtonsoft.Json.JsonConvert.DeserializeObject<Environment.Lutron.LutronQuantumPropertiesConfig>(dc.Properties.ToString());
|
|
||||||
|
|
||||||
return new LutronQuantumArea(dc.Key, dc.Name, comm, props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
|
|
||||||
using PepperDash.Core;
|
|
||||||
using PepperDash.Essentials.Core;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class AnalogWayLiveCorePropertiesConfig
|
|
||||||
{
|
|
||||||
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
|
|
||||||
|
|
||||||
public ControlPropertiesConfig Control { get; set; }
|
|
||||||
public string userName { get; set; }
|
|
||||||
public string password { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,252 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
using PepperDash.Core;
|
|
||||||
using PepperDash.Essentials.Core;
|
|
||||||
using PepperDash.Essentials.Core.Config;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common
|
|
||||||
{
|
|
||||||
|
|
||||||
public class AnalogWayLiveCore : EssentialsDevice
|
|
||||||
{
|
|
||||||
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<string, QscDspLevelControl> LevelControlPoints { get; private set; }
|
|
||||||
// public List<QscDspPresets> PresetList = new List<QscDspPresets>();
|
|
||||||
|
|
||||||
public bool isSubscribed;
|
|
||||||
|
|
||||||
private CTimer SubscriptionTimer;
|
|
||||||
|
|
||||||
CrestronQueue CommandQueue;
|
|
||||||
|
|
||||||
bool CommandQueueInProgress = false;
|
|
||||||
|
|
||||||
//new public Dictionary<string, DspControlPoint> DialerControlPoints { get; private set; }
|
|
||||||
|
|
||||||
//new public Dictionary<string, DspControlPoint> SwitcherControlPoints { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Shows received lines as hex
|
|
||||||
/// </summary>
|
|
||||||
public bool ShowHexResponse { get; set; }
|
|
||||||
|
|
||||||
public AnalogWayLiveCore(string key, string name, IBasicCommunication comm, AnalogWayLiveCorePropertiesConfig 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<GenericSocketStatusChageEventArgs>(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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initiates the subscription process to the DSP
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles a response message from the DSP
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="dev"></param>
|
|
||||||
/// <param name="args"></param>
|
|
||||||
void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sends a command to the DSP (with delimiter appended)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="s">Command to send</param>
|
|
||||||
public void SendLine(string s)
|
|
||||||
{
|
|
||||||
Communication.SendText(s + "\x0d\x0a");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a command from a child module to the queue
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="command">Command object from child module</param>
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a raw string command to the queue
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="command"></param>
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sends the next queued command to the DSP
|
|
||||||
/// </summary>
|
|
||||||
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; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AnalogWayLiveCoreFactory : EssentialsDeviceFactory<AnalogWayLiveCore>
|
|
||||||
{
|
|
||||||
public AnalogWayLiveCoreFactory()
|
|
||||||
{
|
|
||||||
TypeNames = new List<string>() { "analogwaylivecore" };
|
|
||||||
}
|
|
||||||
|
|
||||||
public override EssentialsDevice BuildDevice(DeviceConfig dc)
|
|
||||||
{
|
|
||||||
Debug.Console(1, "Factory Attempting to create new AnalogWayLiveCore Device");
|
|
||||||
var comm = CommFactory.CreateCommForDevice(dc);
|
|
||||||
var props = Newtonsoft.Json.JsonConvert.DeserializeObject<AnalogWayLiveCorePropertiesConfig>(
|
|
||||||
dc.Properties.ToString());
|
|
||||||
return new AnalogWayLiveCore(dc.Key, dc.Name, comm, props);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,241 +0,0 @@
|
|||||||
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<string, QscDspLevelControl> LevelControlPoints { get; private set; }
|
|
||||||
// public List<QscDspPresets> PresetList = new List<QscDspPresets>();
|
|
||||||
|
|
||||||
public bool isSubscribed;
|
|
||||||
|
|
||||||
private CTimer SubscriptionTimer;
|
|
||||||
|
|
||||||
CrestronQueue CommandQueue;
|
|
||||||
|
|
||||||
bool CommandQueueInProgress = false;
|
|
||||||
|
|
||||||
//new public Dictionary<string, DspControlPoint> DialerControlPoints { get; private set; }
|
|
||||||
|
|
||||||
//new public Dictionary<string, DspControlPoint> SwitcherControlPoints { get; private set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Shows received lines as hex
|
|
||||||
/// </summary>
|
|
||||||
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<GenericSocketStatusChageEventArgs>(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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initiates the subscription process to the DSP
|
|
||||||
/// </summary>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles a response message from the DSP
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="dev"></param>
|
|
||||||
/// <param name="args"></param>
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sends a command to the DSP (with delimiter appended)
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="s">Command to send</param>
|
|
||||||
public void SendLine(string s)
|
|
||||||
{
|
|
||||||
Debug.Console(1, this, "TVOne Cusio TX: '{0}'", s);
|
|
||||||
Communication.SendText(s + "\x0d\x0a");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a command from a child module to the queue
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="command">Command object from child module</param>
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a raw string command to the queue
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="command"></param>
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sends the next queued command to the DSP
|
|
||||||
/// </summary>
|
|
||||||
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; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Crestron.SimplSharp;
|
|
||||||
|
|
||||||
using PepperDash.Core;
|
|
||||||
using PepperDash.Essentials.Core;
|
|
||||||
|
|
||||||
namespace PepperDash.Essentials.Devices.Common
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
///
|
|
||||||
/// </summary>
|
|
||||||
public class TVOneCorioPropertiesConfig
|
|
||||||
{
|
|
||||||
public CommunicationMonitorConfig CommunicationMonitorProperties { get; set; }
|
|
||||||
|
|
||||||
public ControlPropertiesConfig Control { get; set; }
|
|
||||||
public string userName { get; set; }
|
|
||||||
public string password { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user