Added IPad Extension methods to link actions between Cotija server and devices for proof of concept

This commit is contained in:
Neil Dorin
2017-06-28 16:29:17 -06:00
parent 95dcc48628
commit 3f6b3ffba0
13 changed files with 969 additions and 860 deletions

View File

@@ -45,6 +45,6 @@ namespace PepperDash.Essentials.Core
triList.ClearBoolSigAction(142);
triList.ClearBoolSigAction(130);
triList.ClearBoolSigAction(134);
}
}
}
}

View File

@@ -34,6 +34,8 @@ namespace PepperDash.Essentials.Core
protected override Func<bool> IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } }
protected override Func<bool> IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } }
int VolumeHeldRepeatInterval = 200;
ushort VolumeInterval = 655;
ushort _FakeVolumeLevel = 31768;
bool _IsMuted;
@@ -138,22 +140,30 @@ namespace PepperDash.Essentials.Core
public void VolumeUp(bool pressRelease)
{
Debug.Console(2, this, "Volume Down {0}", pressRelease);
if (pressRelease)
{
var newLevel = _FakeVolumeLevel + 655;
SetVolume((ushort)newLevel);
}
//while (pressRelease)
//{
Debug.Console(2, this, "Volume Down {0}", pressRelease);
if (pressRelease)
{
var newLevel = _FakeVolumeLevel + VolumeInterval;
SetVolume((ushort)newLevel);
CrestronEnvironment.Sleep(VolumeHeldRepeatInterval);
}
//}
}
public void VolumeDown(bool pressRelease)
{
Debug.Console(2, this, "Volume Up {0}", pressRelease);
if (pressRelease)
{
var newLevel = _FakeVolumeLevel - 655;
SetVolume((ushort)newLevel);
}
//while (pressRelease)
//{
Debug.Console(2, this, "Volume Up {0}", pressRelease);
if (pressRelease)
{
var newLevel = _FakeVolumeLevel - VolumeInterval;
SetVolume((ushort)newLevel);
CrestronEnvironment.Sleep(VolumeHeldRepeatInterval);
}
//}
}
public void MuteToggle()

View File

@@ -1,354 +1,354 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Routing;
namespace PepperDash.Essentials.Devices.Displays
{
/// <summary>
///
/// </summary>
public class NecPSXMDisplay : TwoWayDisplayBase, IBasicVolumeWithFeedback, ICommunicationMonitor
{
public IBasicCommunication Communication { get; private set; }
public CommunicationGather PortGather { get; private set; }
public StatusMonitorBase CommunicationMonitor { get; private set; }
#region Command constants
public const string InputGetCmd = "\x01\x30\x41\x30\x43\x30\x36\x02\x30\x30\x36\x30\x03\x03\x0D";
public const string Hdmi1Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x31\x31\x03\x72\x0d";
public const string Hdmi2Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x31\x32\x03\x71\x0D";
public const string Hdmi3Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x38\x32\x03\x78\x0D";
public const string Hdmi4Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x38\x33\x03\x79\x0D";
public const string Dp1Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x30\x46\x03\x04\x0D";
public const string Dp2Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x31\x30\x03\x73\x0D";
public const string Dvi1Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x30\x33\x03\x71\x0d";
public const string Video1Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x30\x35\x03\x77\x0D";
public const string VgaCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x30\x31\x03\x73\x0D";
public const string RgbCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x30\x32\x03\x70\x0D";
public const string PowerOnCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x30\x33\x44\x36\x30\x30\x30\x31\x03\x73\x0D";
public const string PowerOffCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x30\x33\x44\x36\x30\x30\x30\x34\x03\x76\x0D";
public const string PowerToggleIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x30\x33\x30\x33\x03\x02\x0D";
public const string MuteOffCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x38\x44\x30\x30\x30\x30\x03\x08\x0D";
public const string MuteOnCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x38\x44\x30\x30\x30\x31\x03\x09\x0D";
public const string MuteToggleIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x31\x42\x30\x33\x03\x72\x0D";
public const string MuteGetCmd = "\x01\x30\x41\x30\x43\x30\x36\x02\x30\x30\x38\x44\x03\x79\x0D";
public const string VolumeGetCmd = "\x01\x30\x41\x30\x43\x30\x36\x02\x30\x30\x36\x32\x03\x01\x0D";
public const string VolumeLevelPartialCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x32"; //\x46\x46\x46\x46\x03\xNN\x0D
public const string VolumeUpCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x31\x30\x41\x44\x30\x30\x30\x31\x03\x71\x0D";
public const string VolumeDownCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x31\x30\x41\x44\x30\x30\x30\x32\x03\x72\x0D";
public const string MenuIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x32\x30\x30\x33\x03\x03\x0D";
public const string UpIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x31\x35\x30\x33\x03\x05\x0D";
public const string DownIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x31\x34\x30\x33\x03\x04\x0D";
public const string LeftIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x32\x31\x30\x33\x03\x02\x0D";
public const string RightIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x32\x32\x30\x33\x03\x01\x0D";
public const string SelectIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x32\x33\x30\x33\x03\x00\x0D";
public const string ExitIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x31\x46\x30\x33\x03\x76\x0D";
#endregion
bool _PowerIsOn;
bool _IsWarmingUp;
bool _IsCoolingDown;
ushort _VolumeLevel;
bool _IsMuted;
protected override Func<bool> PowerIsOnFeedbackFunc { get { return () => _PowerIsOn; } }
protected override Func<bool> IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } }
protected override Func<bool> IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } }
/// <summary>
/// Constructor for IBasicCommunication
/// </summary>
public NecPSXMDisplay(string key, string name, IBasicCommunication comm)
: base(key, name)
{
Communication = comm;
Init();
}
/// <summary>
/// Constructor for TCP
/// </summary>
public NecPSXMDisplay(string key, string name, string hostname, int port)
: base(key, name)
{
Communication = new GenericTcpIpClient(key + "-tcp", hostname, port, 5000);
Init();
}
/// <summary>
/// Constructor for COM
/// </summary>
public NecPSXMDisplay(string key, string name, ComPort port, ComPort.ComPortSpec spec)
: base(key, name)
{
Communication = new ComPortController(key + "-com", port, spec);
Init();
}
void Init()
{
PortGather = new CommunicationGather(Communication, '\x0d');
PortGather.LineReceived += this.Port_LineReceived;
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, "xx\x0d");
InputPorts.Add(new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi1), this));
InputPorts.Add(new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi2), this));
InputPorts.Add(new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi3), this));
InputPorts.Add(new RoutingInputPort(RoutingPortNames.HdmiIn4, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi4), this));
InputPorts.Add(new RoutingInputPort(RoutingPortNames.DisplayPortIn1, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.DisplayPort, new Action(InputDisplayPort1), this));
InputPorts.Add(new RoutingInputPort(RoutingPortNames.DisplayPortIn2, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.DisplayPort, new Action(InputDisplayPort2), this));
InputPorts.Add(new RoutingInputPort(RoutingPortNames.DviIn, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Dvi, new Action(InputDvi1), this));
InputPorts.Add(new RoutingInputPort(RoutingPortNames.CompositeIn, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Composite, new Action(InputVideo1), this));
InputPorts.Add(new RoutingInputPort(RoutingPortNames.VgaIn, eRoutingSignalType.Video,
eRoutingPortConnectionType.Vga, new Action(InputVga), this));
InputPorts.Add(new RoutingInputPort(RoutingPortNames.RgbIn, eRoutingSignalType.Video,
eRoutingPortConnectionType.Rgb, new Action(new Action(InputRgb)), this));
VolumeLevelFeedback = new IntFeedback(() => { return _VolumeLevel; });
MuteFeedback = new BoolFeedback(() => _IsMuted);
// new BoolCueActionPair(CommonBoolCue.Menu, b => { if(b) Send(MenuIrCmd); }),
// new BoolCueActionPair(CommonBoolCue.Up, b => { if(b) Send(UpIrCmd); }),
// new BoolCueActionPair(CommonBoolCue.Down, b => { if(b) Send(DownIrCmd); }),
// new BoolCueActionPair(CommonBoolCue.Left, b => { if(b) Send(LeftIrCmd); }),
// new BoolCueActionPair(CommonBoolCue.Right, b => { if(b) Send(RightIrCmd); }),
// new BoolCueActionPair(CommonBoolCue.Select, b => { if(b) Send(SelectIrCmd); }),
// new BoolCueActionPair(CommonBoolCue.Exit, b => { if(b) Send(ExitIrCmd); }),
//};
}
~NecPSXMDisplay()
{
PortGather = null;
}
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 List<Feedback> Feedbacks
{
get
{
var list = base.Feedbacks;
list.AddRange(new List<Feedback>
{
});
return list;
}
}
void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args)
{
if (Debug.Level == 2)
Debug.Console(2, this, "Received: '{0}'", ComTextHelper.GetEscapedText(args.Text));
if (args.Text=="DO SOMETHING HERE EVENTUALLY")
{
_IsMuted = true;
MuteFeedback.FireUpdate();
}
}
void AppendChecksumAndSend(string s)
{
int x = 0;
for (int i = 1; i < s.Length; i++)
x = x ^ s[i];
string send = s + (char)x + '\x0d';
Send(send);
}
void Send(string s)
{
if (Debug.Level == 2)
Debug.Console(2, this, "Send: '{0}'", ComTextHelper.GetEscapedText(s));
Communication.SendText(s);
}
public override void PowerOn()
{
Send(PowerOnCmd);
if (!PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown)
{
_IsWarmingUp = true;
IsWarmingUpFeedback.FireUpdate();
// Fake power-up cycle
WarmupTimer = new CTimer(o =>
{
_IsWarmingUp = false;
_PowerIsOn = true;
IsWarmingUpFeedback.FireUpdate();
PowerIsOnFeedback.FireUpdate();
}, WarmupTime);
}
}
public override void PowerOff()
{
// If a display has unreliable-power off feedback, just override this and
// remove this check.
if (PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown)
{
Send(PowerOffCmd);
_IsCoolingDown = true;
_PowerIsOn = false;
PowerIsOnFeedback.FireUpdate();
IsCoolingDownFeedback.FireUpdate();
// Fake cool-down cycle
CooldownTimer = new CTimer(o =>
{
Debug.Console(2, this, "Cooldown timer ending");
_IsCoolingDown = false;
IsCoolingDownFeedback.FireUpdate();
}, CooldownTime);
}
}
public override void PowerToggle()
{
if (PowerIsOnFeedback.BoolValue && !IsWarmingUpFeedback.BoolValue)
PowerOff();
else if (!PowerIsOnFeedback.BoolValue && !IsCoolingDownFeedback.BoolValue)
PowerOn();
}
public void InputHdmi1()
{
Send(Hdmi1Cmd);
}
public void InputHdmi2()
{
Send(Hdmi2Cmd);
}
public void InputHdmi3()
{
Send(Hdmi3Cmd);
}
public void InputHdmi4()
{
Send(Hdmi4Cmd);
}
public void InputDisplayPort1()
{
Send(Dp1Cmd);
}
public void InputDisplayPort2()
{
Send(Dp2Cmd);
}
public void InputDvi1()
{
Send(Dvi1Cmd);
}
public void InputVideo1()
{
Send(Video1Cmd);
}
public void InputVga()
{
Send(VgaCmd);
}
public void InputRgb()
{
Send(RgbCmd);
}
public override void ExecuteSwitch(object selector)
{
if (selector is Action)
(selector as Action).Invoke();
else
Debug.Console(1, this, "WARNING: ExecuteSwitch cannot handle type {0}", selector.GetType());
//Send((string)selector);
}
void SetVolume(ushort level)
{
var levelString = string.Format("{0}{1:X4}\x03", VolumeLevelPartialCmd, level);
AppendChecksumAndSend(levelString);
//Debug.Console(2, this, "Volume:{0}", ComTextHelper.GetEscapedText(levelString));
_VolumeLevel = level;
VolumeLevelFeedback.FireUpdate();
}
#region IBasicVolumeWithFeedback Members
public IntFeedback VolumeLevelFeedback { get; private set; }
public BoolFeedback MuteFeedback { get; private set; }
public void MuteOff()
{
Send(MuteOffCmd);
}
public void MuteOn()
{
Send(MuteOnCmd);
}
void IBasicVolumeWithFeedback.SetVolume(ushort level)
{
SetVolume(level);
}
#endregion
#region IBasicVolumeControls Members
public void MuteToggle()
{
Send(MuteToggleIrCmd);
}
public void VolumeDown(bool pressRelease)
{
//throw new NotImplementedException();
//#warning need incrementer for these
SetVolume(_VolumeLevel++);
}
public void VolumeUp(bool pressRelease)
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharpPro;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.Routing;
namespace PepperDash.Essentials.Devices.Displays
{
/// <summary>
///
/// </summary>
public class NecPSXMDisplay : TwoWayDisplayBase, IBasicVolumeWithFeedback, ICommunicationMonitor
{
public IBasicCommunication Communication { get; private set; }
public CommunicationGather PortGather { get; private set; }
public StatusMonitorBase CommunicationMonitor { get; private set; }
#region Command constants
public const string InputGetCmd = "\x01\x30\x41\x30\x43\x30\x36\x02\x30\x30\x36\x30\x03\x03\x0D";
public const string Hdmi1Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x31\x31\x03\x72\x0d";
public const string Hdmi2Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x31\x32\x03\x71\x0D";
public const string Hdmi3Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x38\x32\x03\x78\x0D";
public const string Hdmi4Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x38\x33\x03\x79\x0D";
public const string Dp1Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x30\x46\x03\x04\x0D";
public const string Dp2Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x31\x30\x03\x73\x0D";
public const string Dvi1Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x30\x33\x03\x71\x0d";
public const string Video1Cmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x30\x35\x03\x77\x0D";
public const string VgaCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x30\x31\x03\x73\x0D";
public const string RgbCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x30\x30\x30\x30\x32\x03\x70\x0D";
public const string PowerOnCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x30\x33\x44\x36\x30\x30\x30\x31\x03\x73\x0D";
public const string PowerOffCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x30\x33\x44\x36\x30\x30\x30\x34\x03\x76\x0D";
public const string PowerToggleIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x30\x33\x30\x33\x03\x02\x0D";
public const string MuteOffCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x38\x44\x30\x30\x30\x30\x03\x08\x0D";
public const string MuteOnCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x38\x44\x30\x30\x30\x31\x03\x09\x0D";
public const string MuteToggleIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x31\x42\x30\x33\x03\x72\x0D";
public const string MuteGetCmd = "\x01\x30\x41\x30\x43\x30\x36\x02\x30\x30\x38\x44\x03\x79\x0D";
public const string VolumeGetCmd = "\x01\x30\x41\x30\x43\x30\x36\x02\x30\x30\x36\x32\x03\x01\x0D";
public const string VolumeLevelPartialCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x30\x30\x36\x32"; //\x46\x46\x46\x46\x03\xNN\x0D
public const string VolumeUpCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x31\x30\x41\x44\x30\x30\x30\x31\x03\x71\x0D";
public const string VolumeDownCmd = "\x01\x30\x41\x30\x45\x30\x41\x02\x31\x30\x41\x44\x30\x30\x30\x32\x03\x72\x0D";
public const string MenuIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x32\x30\x30\x33\x03\x03\x0D";
public const string UpIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x31\x35\x30\x33\x03\x05\x0D";
public const string DownIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x31\x34\x30\x33\x03\x04\x0D";
public const string LeftIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x32\x31\x30\x33\x03\x02\x0D";
public const string RightIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x32\x32\x30\x33\x03\x01\x0D";
public const string SelectIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x32\x33\x30\x33\x03\x00\x0D";
public const string ExitIrCmd = "\x01\x30\x41\x30\x41\x30\x43\x02\x43\x32\x31\x30\x30\x30\x31\x46\x30\x33\x03\x76\x0D";
#endregion
bool _PowerIsOn;
bool _IsWarmingUp;
bool _IsCoolingDown;
ushort _VolumeLevel;
bool _IsMuted;
protected override Func<bool> PowerIsOnFeedbackFunc { get { return () => _PowerIsOn; } }
protected override Func<bool> IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } }
protected override Func<bool> IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } }
/// <summary>
/// Constructor for IBasicCommunication
/// </summary>
public NecPSXMDisplay(string key, string name, IBasicCommunication comm)
: base(key, name)
{
Communication = comm;
Init();
}
/// <summary>
/// Constructor for TCP
/// </summary>
public NecPSXMDisplay(string key, string name, string hostname, int port)
: base(key, name)
{
Communication = new GenericTcpIpClient(key + "-tcp", hostname, port, 5000);
Init();
}
/// <summary>
/// Constructor for COM
/// </summary>
public NecPSXMDisplay(string key, string name, ComPort port, ComPort.ComPortSpec spec)
: base(key, name)
{
Communication = new ComPortController(key + "-com", port, spec);
Init();
}
void Init()
{
PortGather = new CommunicationGather(Communication, '\x0d');
PortGather.LineReceived += this.Port_LineReceived;
CommunicationMonitor = new GenericCommunicationMonitor(this, Communication, 30000, 120000, 300000, "xx\x0d");
InputPorts.Add(new RoutingInputPort(RoutingPortNames.HdmiIn1, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi1), this));
InputPorts.Add(new RoutingInputPort(RoutingPortNames.HdmiIn2, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi2), this));
InputPorts.Add(new RoutingInputPort(RoutingPortNames.HdmiIn3, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi3), this));
InputPorts.Add(new RoutingInputPort(RoutingPortNames.HdmiIn4, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Hdmi, new Action(InputHdmi4), this));
InputPorts.Add(new RoutingInputPort(RoutingPortNames.DisplayPortIn1, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.DisplayPort, new Action(InputDisplayPort1), this));
InputPorts.Add(new RoutingInputPort(RoutingPortNames.DisplayPortIn2, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.DisplayPort, new Action(InputDisplayPort2), this));
InputPorts.Add(new RoutingInputPort(RoutingPortNames.DviIn, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Dvi, new Action(InputDvi1), this));
InputPorts.Add(new RoutingInputPort(RoutingPortNames.CompositeIn, eRoutingSignalType.AudioVideo,
eRoutingPortConnectionType.Composite, new Action(InputVideo1), this));
InputPorts.Add(new RoutingInputPort(RoutingPortNames.VgaIn, eRoutingSignalType.Video,
eRoutingPortConnectionType.Vga, new Action(InputVga), this));
InputPorts.Add(new RoutingInputPort(RoutingPortNames.RgbIn, eRoutingSignalType.Video,
eRoutingPortConnectionType.Rgb, new Action(new Action(InputRgb)), this));
VolumeLevelFeedback = new IntFeedback(() => { return _VolumeLevel; });
MuteFeedback = new BoolFeedback(() => _IsMuted);
// new BoolCueActionPair(CommonBoolCue.Menu, b => { if(b) Send(MenuIrCmd); }),
// new BoolCueActionPair(CommonBoolCue.Up, b => { if(b) Send(UpIrCmd); }),
// new BoolCueActionPair(CommonBoolCue.Down, b => { if(b) Send(DownIrCmd); }),
// new BoolCueActionPair(CommonBoolCue.Left, b => { if(b) Send(LeftIrCmd); }),
// new BoolCueActionPair(CommonBoolCue.Right, b => { if(b) Send(RightIrCmd); }),
// new BoolCueActionPair(CommonBoolCue.Select, b => { if(b) Send(SelectIrCmd); }),
// new BoolCueActionPair(CommonBoolCue.Exit, b => { if(b) Send(ExitIrCmd); }),
//};
}
~NecPSXMDisplay()
{
PortGather = null;
}
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 List<Feedback> Feedbacks
{
get
{
var list = base.Feedbacks;
list.AddRange(new List<Feedback>
{
});
return list;
}
}
void Port_LineReceived(object dev, GenericCommMethodReceiveTextArgs args)
{
if (Debug.Level == 2)
Debug.Console(2, this, "Received: '{0}'", ComTextHelper.GetEscapedText(args.Text));
if (args.Text=="DO SOMETHING HERE EVENTUALLY")
{
_IsMuted = true;
MuteFeedback.FireUpdate();
}
}
void AppendChecksumAndSend(string s)
{
int x = 0;
for (int i = 1; i < s.Length; i++)
x = x ^ s[i];
string send = s + (char)x + '\x0d';
Send(send);
}
void Send(string s)
{
if (Debug.Level == 2)
Debug.Console(2, this, "Send: '{0}'", ComTextHelper.GetEscapedText(s));
Communication.SendText(s);
}
public override void PowerOn()
{
Send(PowerOnCmd);
if (!PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown)
{
_IsWarmingUp = true;
IsWarmingUpFeedback.FireUpdate();
// Fake power-up cycle
WarmupTimer = new CTimer(o =>
{
_IsWarmingUp = false;
_PowerIsOn = true;
IsWarmingUpFeedback.FireUpdate();
PowerIsOnFeedback.FireUpdate();
}, WarmupTime);
}
}
public override void PowerOff()
{
// If a display has unreliable-power off feedback, just override this and
// remove this check.
if (PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown)
{
Send(PowerOffCmd);
_IsCoolingDown = true;
_PowerIsOn = false;
PowerIsOnFeedback.FireUpdate();
IsCoolingDownFeedback.FireUpdate();
// Fake cool-down cycle
CooldownTimer = new CTimer(o =>
{
Debug.Console(2, this, "Cooldown timer ending");
_IsCoolingDown = false;
IsCoolingDownFeedback.FireUpdate();
}, CooldownTime);
}
}
public override void PowerToggle()
{
if (PowerIsOnFeedback.BoolValue && !IsWarmingUpFeedback.BoolValue)
PowerOff();
else if (!PowerIsOnFeedback.BoolValue && !IsCoolingDownFeedback.BoolValue)
PowerOn();
}
public void InputHdmi1()
{
Send(Hdmi1Cmd);
}
public void InputHdmi2()
{
Send(Hdmi2Cmd);
}
public void InputHdmi3()
{
Send(Hdmi3Cmd);
}
public void InputHdmi4()
{
Send(Hdmi4Cmd);
}
public void InputDisplayPort1()
{
Send(Dp1Cmd);
}
public void InputDisplayPort2()
{
Send(Dp2Cmd);
}
public void InputDvi1()
{
Send(Dvi1Cmd);
}
public void InputVideo1()
{
Send(Video1Cmd);
}
public void InputVga()
{
Send(VgaCmd);
}
public void InputRgb()
{
Send(RgbCmd);
}
public override void ExecuteSwitch(object selector)
{
if (selector is Action)
(selector as Action).Invoke();
else
Debug.Console(1, this, "WARNING: ExecuteSwitch cannot handle type {0}", selector.GetType());
//Send((string)selector);
}
void SetVolume(ushort level)
{
var levelString = string.Format("{0}{1:X4}\x03", VolumeLevelPartialCmd, level);
AppendChecksumAndSend(levelString);
//Debug.Console(2, this, "Volume:{0}", ComTextHelper.GetEscapedText(levelString));
_VolumeLevel = level;
VolumeLevelFeedback.FireUpdate();
}
#region IBasicVolumeWithFeedback Members
public IntFeedback VolumeLevelFeedback { get; private set; }
public BoolFeedback MuteFeedback { get; private set; }
public void MuteOff()
{
Send(MuteOffCmd);
}
public void MuteOn()
{
Send(MuteOnCmd);
}
void IBasicVolumeWithFeedback.SetVolume(ushort level)
{
SetVolume(level);
}
#endregion
#region IBasicVolumeControls Members
public void MuteToggle()
{
Send(MuteToggleIrCmd);
}
public void VolumeDown(bool pressRelease)
{
//throw new NotImplementedException();
SetVolume(_VolumeLevel--);
}
#endregion
}
//#warning need incrementer for these
SetVolume(_VolumeLevel++);
}
public void VolumeUp(bool pressRelease)
{
//throw new NotImplementedException();
SetVolume(_VolumeLevel--);
}
#endregion
}
}

View File

@@ -142,6 +142,7 @@
<Compile Include="FOR REFERENCE Room\EssentialsRoom.cs" />
<Compile Include="Room\Cotija\CotijaConfig.cs" />
<Compile Include="Room\Cotija\CotijaRoomBridge.cs" />
<Compile Include="Room\Cotija\DeviceTypeInterfaces\IDPadExtensions.cs" />
<Compile Include="Room\EssentialsPresentationRoom.cs" />
<Compile Include="Room\EssentialsRoomBase.cs" />
<Compile Include="Room\EssentialsRoomConfig.cs" />

View File

@@ -135,22 +135,73 @@ namespace PepperDash.Essentials
}
}
*/
if (type == ChangeType.WillChange)
{
// Disconnect from previous source
if (type != ChangeType.DidChange)
return;
if (info != null)
{
var previousDev = info.SourceDevice;
JObject roomStatus = new JObject();
// device type interfaces
//if (previousDev is ISetTopBoxControls)
// (previousDev as ISetTopBoxControls).UnlinkButtons(TriList);
//// common interfaces
//if (previousDev is IChannel)
// (previousDev as IChannel).UnlinkButtons(TriList);
//if (previousDev is IColor)
// (previousDev as IColor).UnlinkButtons(TriList);
if (previousDev is IDPad)
(previousDev as IDPad).UnlinkActions(Parent);
//if (previousDev is IDvr)
// (previousDev as IDvr).UnlinkButtons(TriList);
//if (previousDev is INumericKeypad)
// (previousDev as INumericKeypad).UnlinkButtons(TriList);
//if (previousDev is IPower)
// (previousDev as IPower).UnlinkButtons(TriList);
//if (previousDev is ITransport)
// (previousDev as ITransport).UnlinkButtons(TriList);
}
var huddleRoom = room as EssentialsHuddleSpaceRoom;
//roomStatus.Add("isOn", huddleRoom.OnFeedback.BoolValue);
roomStatus.Add("selectedSourceKey", huddleRoom.CurrentSourceInfoKey);
JObject roomStatus = new JObject();
JObject message = new JObject();
var huddleRoom = room as EssentialsHuddleSpaceRoom;
//roomStatus.Add("isOn", huddleRoom.OnFeedback.BoolValue);
roomStatus.Add("selectedSourceKey", huddleRoom.CurrentSourceInfoKey);
message.Add("type", "/room/status/");
message.Add("content", roomStatus);
JObject message = new JObject();
Parent.PostToServer(Room, message);
message.Add("type", "/room/status/");
message.Add("content", roomStatus);
Parent.PostToServer(Room, message);
}
else
{
if (info != null)
{
var dev = info.SourceDevice;
//if (dev is ISetTopBoxControls)
// (dev as ISetTopBoxControls).LinkButtons(TriList);
//if (dev is IChannel)
// (dev as IChannel).LinkButtons(TriList);
//if (dev is IColor)
// (dev as IColor).LinkButtons(TriList);
if (dev is IDPad)
(dev as IDPad).LinkActions(Parent);
//if (dev is IDvr)
// (dev as IDvr).LinkButtons(TriList);
//if (dev is INumericKeypad)
// (dev as INumericKeypad).LinkButtons(TriList);
//if (dev is IPower)
// (dev as IPower).LinkButtons(TriList);
//if (dev is ITransport)
// (dev as ITransport).LinkButtons(TriList);
}
}
}
/// <summary>

View File

@@ -107,7 +107,7 @@ namespace PepperDash.Essentials
if (FileLock.TryEnter())
{
Debug.Console(1, this, "Reading Configuration File");
Debug.Console(1, this, "Reading configuration file to extract system UUID...");
postBody = File.ReadToEnd(filePath, Encoding.ASCII);
@@ -268,6 +268,20 @@ namespace PepperDash.Essentials
ServerReconnect.Reset(dueTime, repeatTime);
}
void StartHearbeatTimer(long dueTime, long repeatTime)
{
if (ServerHeartbeat == null)
{
ServerHeartbeat = new CTimer(HeartbeatExpired, null, dueTime, repeatTime);
Debug.Console(2, this, "Heartbeat Timer Started.");
}
ServerHeartbeat.Reset(dueTime, repeatTime);
Debug.Console(2, this, "Heartbeat Timer Reset.");
}
/// <summary>
/// Connects the SSE Client
@@ -319,17 +333,11 @@ namespace PepperDash.Essentials
if (type == "hello")
{
ServerHeartbeat = new CTimer(HeartbeatExpired, null, ServerHeartbeatInterval, ServerHeartbeatInterval);
Debug.Console(2, this, "Heartbeat Timer Started.");
ServerHeartbeat.Reset(ServerHeartbeatInterval, ServerHeartbeatInterval);
StartHearbeatTimer(ServerHeartbeatInterval, ServerHeartbeatInterval);
}
else if (type == "/system/heartbeat")
{
ServerHeartbeat.Reset(ServerHeartbeatInterval, ServerHeartbeatInterval);
Debug.Console(2, this, "Heartbeat Timer Reset.");
StartHearbeatTimer(ServerHeartbeatInterval, ServerHeartbeatInterval);
}
else if (type == "close")
{
@@ -366,7 +374,7 @@ namespace PepperDash.Essentials
{
PushedActions.Add(type, new CTimer(o =>
{
(action as Action<bool>)(false);
(action as PressAndHoldAction)(false);
PushedActions.Remove(type);
}, null, ButtonHeartbeatInterval, ButtonHeartbeatInterval));
}
@@ -383,7 +391,7 @@ namespace PepperDash.Essentials
}
case "false":
{
if (!PushedActions.ContainsKey(type))
if (PushedActions.ContainsKey(type))
{
PushedActions[type].Stop();
PushedActions.Remove(type);
@@ -392,7 +400,7 @@ namespace PepperDash.Essentials
}
}
(action as Action<bool>)(stateString == "true");
(action as PressAndHoldAction)(stateString == "true");
}
}
else if (action is Action<bool>)

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using PepperDash.Essentials.Core;
using PepperDash.Core;
namespace PepperDash.Essentials
{
public static class IDPadExtensions
{
public static void LinkActions(this IDPad dev, CotijaSystemController controller)
{
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
controller.AddAction(prefix + "up", new Action<bool>(dev.Up));
controller.AddAction(prefix + "down", new Action<bool>(dev.Down));
controller.AddAction(prefix + "left", new Action<bool>(dev.Left));
controller.AddAction(prefix + "right", new Action<bool>(dev.Right));
controller.AddAction(prefix + "select", new Action<bool>(dev.Select));
controller.AddAction(prefix + "menu", new Action<bool>(dev.Menu));
controller.AddAction(prefix + "exit", new Action<bool>(dev.Exit));
}
public static void UnlinkActions(this IDPad dev, CotijaSystemController controller)
{
var prefix = string.Format(@"/device/{0}/", (dev as IKeyed).Key);
controller.RemoveAction(prefix + "up");
controller.RemoveAction(prefix + "down");
controller.RemoveAction(prefix + "left");
controller.RemoveAction(prefix + "right");
controller.RemoveAction(prefix + "select");
controller.RemoveAction(prefix + "menu");
controller.RemoveAction(prefix + "exit");
}
}
}

View File

@@ -1,161 +1,161 @@
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
{
public class EssentialsHuddleSpaceRoom : EssentialsRoomBase, IHasCurrentSourceInfoChange
{
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
public event SourceInfoChangeHandler CurrentSingleSourceChange;
public EssentialsRoomPropertiesConfig Config { get; private set; }
public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
public IRoutingSinkNoSwitching DefaultAudioDevice { get; private set; }
public IBasicVolumeControls DefaultVolumeControls { get; private set; }
public bool ExcludeFromGlobalFunctions { get; set; }
/// <summary>
/// The config name of the source list
/// </summary>
public string SourceListKey { get; set; }
/// <summary>
/// If room is off, enables power on to last source. Default true
/// </summary>
public bool EnablePowerOnToLastSource { get; set; }
string LastSourceKey;
/// <summary>
///
/// </summary>
public IBasicVolumeControls CurrentVolumeControls
{
get { return _CurrentAudioDevice; }
set
{
if (value == _CurrentAudioDevice) return;
var oldDev = _CurrentAudioDevice;
// derigister this room from the device, if it can
if (oldDev is IInUseTracking)
(oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio");
var handler = CurrentVolumeDeviceChange;
if (handler != null)
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange));
_CurrentAudioDevice = value;
if (handler != null)
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange));
// register this room with new device, if it can
if (_CurrentAudioDevice is IInUseTracking)
(_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
}
}
IBasicVolumeControls _CurrentAudioDevice;
/// <summary>
/// The SourceListItem last run - containing names and icons
/// </summary>
public SourceListItem CurrentSourceInfo
{
get { return _CurrentSourceInfo; }
private set
{
if (value == _CurrentSourceInfo) return;
var handler = CurrentSingleSourceChange;
// remove from in-use tracker, if so equipped
if(_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
if (handler != null)
handler(this, _CurrentSourceInfo, ChangeType.WillChange);
_CurrentSourceInfo = value;
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
{
public class EssentialsHuddleSpaceRoom : EssentialsRoomBase, IHasCurrentSourceInfoChange
{
public event EventHandler<VolumeDeviceChangeEventArgs> CurrentVolumeDeviceChange;
public event SourceInfoChangeHandler CurrentSingleSourceChange;
public EssentialsRoomPropertiesConfig Config { get; private set; }
public IRoutingSinkWithSwitching DefaultDisplay { get; private set; }
public IRoutingSinkNoSwitching DefaultAudioDevice { get; private set; }
public IBasicVolumeControls DefaultVolumeControls { get; private set; }
public bool ExcludeFromGlobalFunctions { get; set; }
/// <summary>
/// The config name of the source list
/// </summary>
public string SourceListKey { get; set; }
/// <summary>
/// If room is off, enables power on to last source. Default true
/// </summary>
public bool EnablePowerOnToLastSource { get; set; }
string LastSourceKey;
/// <summary>
///
/// </summary>
public IBasicVolumeControls CurrentVolumeControls
{
get { return _CurrentAudioDevice; }
set
{
if (value == _CurrentAudioDevice) return;
var oldDev = _CurrentAudioDevice;
// derigister this room from the device, if it can
if (oldDev is IInUseTracking)
(oldDev as IInUseTracking).InUseTracker.RemoveUser(this, "audio");
var handler = CurrentVolumeDeviceChange;
if (handler != null)
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.WillChange));
_CurrentAudioDevice = value;
if (handler != null)
CurrentVolumeDeviceChange(this, new VolumeDeviceChangeEventArgs(oldDev, value, ChangeType.DidChange));
// register this room with new device, if it can
if (_CurrentAudioDevice is IInUseTracking)
(_CurrentAudioDevice as IInUseTracking).InUseTracker.AddUser(this, "audio");
}
}
IBasicVolumeControls _CurrentAudioDevice;
/// <summary>
/// The SourceListItem last run - containing names and icons
/// </summary>
public SourceListItem CurrentSourceInfo
{
get { return _CurrentSourceInfo; }
private set
{
if (value == _CurrentSourceInfo) return;
var handler = CurrentSingleSourceChange;
// remove from in-use tracker, if so equipped
if(_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.RemoveUser(this, "control");
if (handler != null)
handler(this, _CurrentSourceInfo, ChangeType.WillChange);
_CurrentSourceInfo = value;
// add to in-use tracking
if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
if (handler != null)
handler(this, _CurrentSourceInfo, ChangeType.DidChange);
}
}
if (_CurrentSourceInfo != null && _CurrentSourceInfo.SourceDevice is IInUseTracking)
(_CurrentSourceInfo.SourceDevice as IInUseTracking).InUseTracker.AddUser(this, "control");
if (handler != null)
handler(this, _CurrentSourceInfo, ChangeType.DidChange);
}
}
SourceListItem _CurrentSourceInfo;
public string CurrentSourceInfoKey { get; private set; }
/// <summary>
///
/// </summary>
public BoolFeedback OnFeedback { get; private set; }
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="name"></param>
public EssentialsHuddleSpaceRoom(string key, string name, IRoutingSinkWithSwitching defaultDisplay,
IRoutingSinkNoSwitching defaultAudio, EssentialsRoomPropertiesConfig config)
: base(key, name)
{
Config = config;
DefaultDisplay = defaultDisplay;
DefaultAudioDevice = defaultAudio;
if (defaultAudio is IBasicVolumeControls)
DefaultVolumeControls = defaultAudio as IBasicVolumeControls;
else if (defaultAudio is IHasVolumeDevice)
DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice;
CurrentVolumeControls = DefaultVolumeControls;
OnFeedback = new BoolFeedback(() =>
{ return CurrentSourceInfo != null
&& CurrentSourceInfo.Type == eSourceListItemType.Route; });
SourceListKey = "default";
EnablePowerOnToLastSource = true;
}
public void RunRouteAction(string routeKey)
{
RunRouteAction(routeKey, null);
}
/// <summary>
/// Gets a source from config list SourceListKey and dynamically build and executes the
/// route or commands
/// </summary>
/// <param name="name"></param>
public void RunRouteAction(string routeKey, Action successCallback)
{
// Run this on a separate thread
new CTimer(o =>
{
Debug.Console(1, this, "Run room action '{0}'", routeKey);
var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey);
if(dict == null)
{
Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey);
return;
}
// Try to get the list item by it's string key
if (!dict.ContainsKey(routeKey))
{
Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'",
routeKey, SourceListKey);
return;
}
var item = dict[routeKey];
Debug.Console(2, this, "Action {0} has {1} steps",
item.SourceKey, item.RouteList.Count);
public string CurrentSourceInfoKey { get; private set; }
/// <summary>
///
/// </summary>
public BoolFeedback OnFeedback { get; private set; }
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="name"></param>
public EssentialsHuddleSpaceRoom(string key, string name, IRoutingSinkWithSwitching defaultDisplay,
IRoutingSinkNoSwitching defaultAudio, EssentialsRoomPropertiesConfig config)
: base(key, name)
{
Config = config;
DefaultDisplay = defaultDisplay;
DefaultAudioDevice = defaultAudio;
if (defaultAudio is IBasicVolumeControls)
DefaultVolumeControls = defaultAudio as IBasicVolumeControls;
else if (defaultAudio is IHasVolumeDevice)
DefaultVolumeControls = (defaultAudio as IHasVolumeDevice).VolumeDevice;
CurrentVolumeControls = DefaultVolumeControls;
OnFeedback = new BoolFeedback(() =>
{ return CurrentSourceInfo != null
&& CurrentSourceInfo.Type == eSourceListItemType.Route; });
SourceListKey = "default";
EnablePowerOnToLastSource = true;
}
public void RunRouteAction(string routeKey)
{
RunRouteAction(routeKey, null);
}
/// <summary>
/// Gets a source from config list SourceListKey and dynamically build and executes the
/// route or commands
/// </summary>
/// <param name="name"></param>
public void RunRouteAction(string routeKey, Action successCallback)
{
// Run this on a separate thread
new CTimer(o =>
{
Debug.Console(1, this, "Run room action '{0}'", routeKey);
var dict = ConfigReader.ConfigObject.GetSourceListForKey(SourceListKey);
if(dict == null)
{
Debug.Console(1, this, "WARNING: Config source list '{0}' not found", SourceListKey);
return;
}
// Try to get the list item by it's string key
if (!dict.ContainsKey(routeKey))
{
Debug.Console(1, this, "WARNING: No item '{0}' found on config list '{1}'",
routeKey, SourceListKey);
return;
}
var item = dict[routeKey];
Debug.Console(2, this, "Action {0} has {1} steps",
item.SourceKey, item.RouteList.Count);
// Let's run it
if (routeKey.ToLower() != "roomoff")
{
@@ -164,133 +164,133 @@ namespace PepperDash.Essentials
else
{
CurrentSourceInfoKey = null;
}
foreach (var route in item.RouteList)
{
// if there is a $defaultAll on route, run two separate
if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase))
{
var tempAudio = new SourceRouteListItem
{
DestinationKey = "$defaultDisplay",
SourceKey = route.SourceKey,
Type = eRoutingSignalType.Video
};
DoRoute(tempAudio);
var tempVideo = new SourceRouteListItem
{
DestinationKey = "$defaultAudio",
SourceKey = route.SourceKey,
Type = eRoutingSignalType.Audio
};
DoRoute(tempVideo);
continue;
}
else
DoRoute(route);
}
// Set volume control on room, using default if non provided
IBasicVolumeControls volDev = null;
// Handle special cases for volume control
if (string.IsNullOrEmpty(item.VolumeControlKey)
|| item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase))
volDev = DefaultVolumeControls;
else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
volDev = DefaultDisplay as IBasicVolumeControls;
// Or a specific device, probably rarely used.
else
{
var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey);
if (dev is IBasicVolumeControls)
volDev = dev as IBasicVolumeControls;
else if (dev is IHasVolumeDevice)
volDev = (dev as IHasVolumeDevice).VolumeDevice;
}
CurrentVolumeControls = volDev;
}
foreach (var route in item.RouteList)
{
// if there is a $defaultAll on route, run two separate
if (route.DestinationKey.Equals("$defaultAll", StringComparison.OrdinalIgnoreCase))
{
var tempAudio = new SourceRouteListItem
{
DestinationKey = "$defaultDisplay",
SourceKey = route.SourceKey,
Type = eRoutingSignalType.Video
};
DoRoute(tempAudio);
var tempVideo = new SourceRouteListItem
{
DestinationKey = "$defaultAudio",
SourceKey = route.SourceKey,
Type = eRoutingSignalType.Audio
};
DoRoute(tempVideo);
continue;
}
else
DoRoute(route);
}
// Set volume control on room, using default if non provided
IBasicVolumeControls volDev = null;
// Handle special cases for volume control
if (string.IsNullOrEmpty(item.VolumeControlKey)
|| item.VolumeControlKey.Equals("$defaultAudio", StringComparison.OrdinalIgnoreCase))
volDev = DefaultVolumeControls;
else if (item.VolumeControlKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
volDev = DefaultDisplay as IBasicVolumeControls;
// Or a specific device, probably rarely used.
else
{
var dev = DeviceManager.GetDeviceForKey(item.VolumeControlKey);
if (dev is IBasicVolumeControls)
volDev = dev as IBasicVolumeControls;
else if (dev is IHasVolumeDevice)
volDev = (dev as IHasVolumeDevice).VolumeDevice;
}
CurrentVolumeControls = volDev;
// store the name and UI info for routes
if (item.SourceKey != null)
{
CurrentSourceInfoKey = routeKey;
CurrentSourceInfo = item;
}
// And finally, set the "control". This will trigger event
//CurrentControlDevice = DeviceManager.GetDeviceForKey(item.SourceKey) as Device;
OnFeedback.FireUpdate();
// report back when done
if (successCallback != null)
successCallback();
#warning Need to again handle special commands in here.
}, 0); // end of CTimer
}
/// <summary>
/// Will power the room on with the last-used source
/// </summary>
public void PowerOnToDefaultOrLastSource()
{
if (!EnablePowerOnToLastSource || LastSourceKey == null)
return;
RunRouteAction(LastSourceKey);
}
/// <summary>
///
/// </summary>
/// <param name="route"></param>
/// <returns></returns>
bool DoRoute(SourceRouteListItem route)
{
IRoutingSinkNoSwitching dest = null;
if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
dest = DefaultAudioDevice;
else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
dest = DefaultDisplay;
else
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching;
if (dest == null)
{
Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey);
return false;
}
if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
{
dest.ReleaseRoute();
if (dest is IPower)
(dest as IPower).PowerOff();
}
else
{
var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs;
if (source == null)
{
Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey);
return false;
}
dest.ReleaseAndMakeRoute(source, route.Type);
}
return true;
}
/// <summary>
/// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions
/// </summary>
public static void AllRoomsOff()
{
var allRooms = DeviceManager.AllDevices.Where(d =>
d is EssentialsHuddleSpaceRoom && !(d as EssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions);
foreach (var room in allRooms)
(room as EssentialsHuddleSpaceRoom).RunRouteAction("roomOff");
}
}
}
// And finally, set the "control". This will trigger event
//CurrentControlDevice = DeviceManager.GetDeviceForKey(item.SourceKey) as Device;
OnFeedback.FireUpdate();
// report back when done
if (successCallback != null)
successCallback();
#warning Need to again handle special commands in here.
}, 0); // end of CTimer
}
/// <summary>
/// Will power the room on with the last-used source
/// </summary>
public void PowerOnToDefaultOrLastSource()
{
if (!EnablePowerOnToLastSource || LastSourceKey == null)
return;
RunRouteAction(LastSourceKey);
}
/// <summary>
///
/// </summary>
/// <param name="route"></param>
/// <returns></returns>
bool DoRoute(SourceRouteListItem route)
{
IRoutingSinkNoSwitching dest = null;
if (route.DestinationKey.Equals("$defaultaudio", StringComparison.OrdinalIgnoreCase))
dest = DefaultAudioDevice;
else if (route.DestinationKey.Equals("$defaultDisplay", StringComparison.OrdinalIgnoreCase))
dest = DefaultDisplay;
else
dest = DeviceManager.GetDeviceForKey(route.DestinationKey) as IRoutingSinkNoSwitching;
if (dest == null)
{
Debug.Console(1, this, "Cannot route, unknown destination '{0}'", route.DestinationKey);
return false;
}
if (route.SourceKey.Equals("$off", StringComparison.OrdinalIgnoreCase))
{
dest.ReleaseRoute();
if (dest is IPower)
(dest as IPower).PowerOff();
}
else
{
var source = DeviceManager.GetDeviceForKey(route.SourceKey) as IRoutingOutputs;
if (source == null)
{
Debug.Console(1, this, "Cannot route unknown source '{0}' to {1}", route.SourceKey, route.DestinationKey);
return false;
}
dest.ReleaseAndMakeRoute(source, route.Type);
}
return true;
}
/// <summary>
/// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions
/// </summary>
public static void AllRoomsOff()
{
var allRooms = DeviceManager.AllDevices.Where(d =>
d is EssentialsHuddleSpaceRoom && !(d as EssentialsHuddleSpaceRoom).ExcludeFromGlobalFunctions);
foreach (var room in allRooms)
(room as EssentialsHuddleSpaceRoom).RunRouteAction("roomOff");
}
}
}

View File

@@ -1,196 +1,196 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.UI;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.PageManagers;
namespace PepperDash.Essentials
{
public class EssentialsTouchpanelController : Device
{
public BasicTriListWithSmartObject Panel { get; private set; }
public PanelDriverBase PanelDriver { get; private set; }
CTimer BacklightTransitionedOnTimer;
public EssentialsTouchpanelController(string key, string name, Tswx52ButtonVoiceControl tsw,
string projectName, string sgdPath)
: base(key, name)
{
Panel = tsw;
tsw.LoadSmartObjects(sgdPath);
tsw.SigChange += new Crestron.SimplSharpPro.DeviceSupport.SigEventHandler(Tsw_SigChange);
}
/// <summary>
/// Config constructor
/// </summary>
public EssentialsTouchpanelController(string key, string name, string type, CrestronTouchpanelPropertiesConfig props, uint id)
: base(key, name)
{
AddPostActivationAction(() =>
{
Debug.Console(2, this, "post-activation linking");
type = type.ToLower();
try
{
if (type == "crestronapp")
{
var app = new CrestronApp(id, Global.ControlSystem);
app.ParameterProjectName.Value = props.ProjectName;
Panel = app;
}
else if (type == "tsw752")
Panel = new Tsw752(id, Global.ControlSystem);
else if (type == "tsw1052")
Panel = new Tsw1052(id, Global.ControlSystem);
else
{
Debug.Console(0, this, "WARNING: Cannot create TSW controller with type '{0}'", type);
return;
}
}
catch (Exception e)
{
Debug.Console(0, this, "WARNING: Cannot create TSW base class. Panel will not function: {0}", e.Message);
return;
}
// Reserved sigs
if (Panel is TswFt5ButtonSystem)
{
var tsw = Panel as TswFt5ButtonSystem;
tsw.ExtenderSystemReservedSigs.Use();
tsw.ExtenderSystemReservedSigs.DeviceExtenderSigChange
+= ExtenderSystemReservedSigs_DeviceExtenderSigChange;
}
new CTimer(o =>
{
var regSuccess = Panel.Register();
if (regSuccess != eDeviceRegistrationUnRegistrationResponse.Success)
Debug.Console(0, this, "WARNING: Registration failed. Continuing, but panel may not function: {0}", regSuccess);
// Give up cleanly if SGD is not present.
var sgdName = @"\NVRAM\Program" + InitialParametersClass.ApplicationNumber
+ @"\sgd\" + props.SgdFile;
if (!File.Exists(sgdName))
{
Debug.Console(0, this, "WARNING: Smart object file '{0}' not present. Exiting TSW load", sgdName);
return;
}
Panel.LoadSmartObjects(sgdName);
Panel.SigChange += Tsw_SigChange;
var mainDriver = new EssentialsPanelMainInterfaceDriver(Panel, props);
// Then the AV driver
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Crestron.SimplSharp;
using Crestron.SimplSharp.CrestronIO;
using Crestron.SimplSharpPro;
using Crestron.SimplSharpPro.DeviceSupport;
using Crestron.SimplSharpPro.UI;
using PepperDash.Core;
using PepperDash.Essentials.Core;
using PepperDash.Essentials.Core.PageManagers;
namespace PepperDash.Essentials
{
public class EssentialsTouchpanelController : Device
{
public BasicTriListWithSmartObject Panel { get; private set; }
public PanelDriverBase PanelDriver { get; private set; }
CTimer BacklightTransitionedOnTimer;
public EssentialsTouchpanelController(string key, string name, Tswx52ButtonVoiceControl tsw,
string projectName, string sgdPath)
: base(key, name)
{
Panel = tsw;
tsw.LoadSmartObjects(sgdPath);
tsw.SigChange += new Crestron.SimplSharpPro.DeviceSupport.SigEventHandler(Tsw_SigChange);
}
/// <summary>
/// Config constructor
/// </summary>
public EssentialsTouchpanelController(string key, string name, string type, CrestronTouchpanelPropertiesConfig props, uint id)
: base(key, name)
{
AddPostActivationAction(() =>
{
Debug.Console(2, this, "post-activation linking");
type = type.ToLower();
try
{
if (type == "crestronapp")
{
var app = new CrestronApp(id, Global.ControlSystem);
app.ParameterProjectName.Value = props.ProjectName;
Panel = app;
}
else if (type == "tsw752")
Panel = new Tsw752(id, Global.ControlSystem);
else if (type == "tsw1052")
Panel = new Tsw1052(id, Global.ControlSystem);
else
{
Debug.Console(0, this, "WARNING: Cannot create TSW controller with type '{0}'", type);
return;
}
}
catch (Exception e)
{
Debug.Console(0, this, "WARNING: Cannot create TSW base class. Panel will not function: {0}", e.Message);
return;
}
// Reserved sigs
if (Panel is TswFt5ButtonSystem)
{
var tsw = Panel as TswFt5ButtonSystem;
tsw.ExtenderSystemReservedSigs.Use();
tsw.ExtenderSystemReservedSigs.DeviceExtenderSigChange
+= ExtenderSystemReservedSigs_DeviceExtenderSigChange;
}
new CTimer(o =>
{
var regSuccess = Panel.Register();
if (regSuccess != eDeviceRegistrationUnRegistrationResponse.Success)
Debug.Console(0, this, "WARNING: Registration failed. Continuing, but panel may not function: {0}", regSuccess);
// Give up cleanly if SGD is not present.
var sgdName = @"\NVRAM\Program" + InitialParametersClass.ApplicationNumber
+ @"\sgd\" + props.SgdFile;
if (!File.Exists(sgdName))
{
Debug.Console(0, this, "WARNING: Smart object file '{0}' not present. Exiting TSW load", sgdName);
return;
}
Panel.LoadSmartObjects(sgdName);
Panel.SigChange += Tsw_SigChange;
var mainDriver = new EssentialsPanelMainInterfaceDriver(Panel, props);
// Then the AV driver
// spin up different room drivers depending on room type
var room = DeviceManager.GetDeviceForKey(props.DefaultRoomKey);
if (room is EssentialsHuddleSpaceRoom)
{
Debug.Console(0, this, "Adding huddle space driver");
var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, props);
avDriver.CurrentRoom = room as EssentialsHuddleSpaceRoom;
avDriver.DefaultRoomKey = props.DefaultRoomKey;
mainDriver.AvDriver = avDriver;
LoadAndShowDriver(mainDriver); // This is a little convoluted.
if (Panel is TswFt5ButtonSystem)
{
var tsw = Panel as TswFt5ButtonSystem;
// Wire up hard keys
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.PowerButtonPressed(); });
//tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
tsw.ButtonStateChange += new ButtonEventHandler(Tsw_ButtonStateChange);
}
}
else if (room is EssentialsPresentationRoom)
{
Debug.Console(0, this, "Adding presentation room driver");
var avDriver = new EssentialsPresentationPanelAvFunctionsDriver(mainDriver, props);
avDriver.CurrentRoom = room as EssentialsPresentationRoom;
avDriver.DefaultRoomKey = props.DefaultRoomKey;
mainDriver.AvDriver = avDriver;
LoadAndShowDriver(mainDriver);
if (Panel is TswFt5ButtonSystem)
{
var tsw = Panel as TswFt5ButtonSystem;
// Wire up hard keys
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.PowerButtonPressed(); });
//tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
tsw.ButtonStateChange += new ButtonEventHandler(Tsw_ButtonStateChange);
}
}
else
{
Debug.Console(0, this, "ERROR: Cannot load AvFunctionsDriver for room '{0}'", props.DefaultRoomKey);
}
}, 0);
});
}
public void LoadAndShowDriver(PanelDriverBase driver)
{
PanelDriver = driver;
driver.Show();
}
void HomePressed()
{
if (BacklightTransitionedOnTimer != null)
Debug.Console(2, this, "Home pressed from dark screen");
else
PanelDriver.BackButtonPressed();
}
void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
{
// If the sig is transitioning on, mark it in case it was home button that transitioned it
var blOnSig = (Panel as TswFt5ButtonSystem).ExtenderSystemReservedSigs.BacklightOnFeedback;
if (args.Sig == blOnSig && blOnSig.BoolValue)
{
Debug.Console(2, this, "Backlight transitioning on");
BacklightTransitionedOnTimer = new CTimer(o =>
{
BacklightTransitionedOnTimer = null;
}, 200);
}
}
void Tsw_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args)
{
if (Debug.Level == 2)
Debug.Console(2, this, "Sig change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
var uo = args.Sig.UserObject;
if (uo is Action<bool>)
(uo as Action<bool>)(args.Sig.BoolValue);
else if (uo is Action<ushort>)
(uo as Action<ushort>)(args.Sig.UShortValue);
else if (uo is Action<string>)
(uo as Action<string>)(args.Sig.StringValue);
}
void Tsw_ButtonStateChange(GenericBase device, ButtonEventArgs args)
{
var uo = args.Button.UserObject;
if(uo is Action<bool>)
(uo as Action<bool>)(args.Button.State == eButtonState.Pressed);
}
}
var room = DeviceManager.GetDeviceForKey(props.DefaultRoomKey);
if (room is EssentialsHuddleSpaceRoom)
{
Debug.Console(0, this, "Adding huddle space driver");
var avDriver = new EssentialsHuddlePanelAvFunctionsDriver(mainDriver, props);
avDriver.CurrentRoom = room as EssentialsHuddleSpaceRoom;
avDriver.DefaultRoomKey = props.DefaultRoomKey;
mainDriver.AvDriver = avDriver;
LoadAndShowDriver(mainDriver); // This is a little convoluted.
if (Panel is TswFt5ButtonSystem)
{
var tsw = Panel as TswFt5ButtonSystem;
// Wire up hard keys
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.PowerButtonPressed(); });
//tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
tsw.ButtonStateChange += new ButtonEventHandler(Tsw_ButtonStateChange);
}
}
else if (room is EssentialsPresentationRoom)
{
Debug.Console(0, this, "Adding presentation room driver");
var avDriver = new EssentialsPresentationPanelAvFunctionsDriver(mainDriver, props);
avDriver.CurrentRoom = room as EssentialsPresentationRoom;
avDriver.DefaultRoomKey = props.DefaultRoomKey;
mainDriver.AvDriver = avDriver;
LoadAndShowDriver(mainDriver);
if (Panel is TswFt5ButtonSystem)
{
var tsw = Panel as TswFt5ButtonSystem;
// Wire up hard keys
tsw.Power.UserObject = new Action<bool>(b => { if (!b) avDriver.PowerButtonPressed(); });
//tsw.Home.UserObject = new Action<bool>(b => { if (!b) HomePressed(); });
tsw.Up.UserObject = new Action<bool>(avDriver.VolumeUpPress);
tsw.Down.UserObject = new Action<bool>(avDriver.VolumeDownPress);
tsw.ButtonStateChange += new ButtonEventHandler(Tsw_ButtonStateChange);
}
}
else
{
Debug.Console(0, this, "ERROR: Cannot load AvFunctionsDriver for room '{0}'", props.DefaultRoomKey);
}
}, 0);
});
}
public void LoadAndShowDriver(PanelDriverBase driver)
{
PanelDriver = driver;
driver.Show();
}
void HomePressed()
{
if (BacklightTransitionedOnTimer != null)
Debug.Console(2, this, "Home pressed from dark screen");
else
PanelDriver.BackButtonPressed();
}
void ExtenderSystemReservedSigs_DeviceExtenderSigChange(DeviceExtender currentDeviceExtender, SigEventArgs args)
{
// If the sig is transitioning on, mark it in case it was home button that transitioned it
var blOnSig = (Panel as TswFt5ButtonSystem).ExtenderSystemReservedSigs.BacklightOnFeedback;
if (args.Sig == blOnSig && blOnSig.BoolValue)
{
Debug.Console(2, this, "Backlight transitioning on");
BacklightTransitionedOnTimer = new CTimer(o =>
{
BacklightTransitionedOnTimer = null;
}, 200);
}
}
void Tsw_SigChange(object currentDevice, Crestron.SimplSharpPro.SigEventArgs args)
{
if (Debug.Level == 2)
Debug.Console(2, this, "Sig change: {0} {1}={2}", args.Sig.Type, args.Sig.Number, args.Sig.StringValue);
var uo = args.Sig.UserObject;
if (uo is Action<bool>)
(uo as Action<bool>)(args.Sig.BoolValue);
else if (uo is Action<ushort>)
(uo as Action<ushort>)(args.Sig.UShortValue);
else if (uo is Action<string>)
(uo as Action<string>)(args.Sig.StringValue);
}
void Tsw_ButtonStateChange(GenericBase device, ButtonEventArgs args)
{
var uo = args.Button.UserObject;
if(uo is Action<bool>)
(uo as Action<bool>)(args.Button.State == eButtonState.Pressed);
}
}
}