From 3f6b3ffba0f0ae8108ef40035817b8fc8f3beb03 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 28 Jun 2017 16:29:17 -0600 Subject: [PATCH] Added IPad Extension methods to link actions between Cotija server and devices for proof of concept --- .../DeviceTypeInterfaces/IDPad.cs | 2 +- .../Display/MockDisplay.cs | 34 +- .../PepperDash_Essentials_Core.projectinfo | Bin 1286 -> 1283 bytes .../Essentials_DM/Essentials_DM.projectinfo | Bin 1140 -> 1137 bytes .../Display/NECPSXMDisplay.cs | 704 +++++++++--------- .../Essentials Devices Common.projectinfo | Bin 1158 -> 1158 bytes .../PepperDashEssentials.csproj | 1 + .../PepperDashEssentials.projectinfo | Bin 1860 -> 1863 bytes .../Room/Cotija/CotijaRoomBridge.cs | 71 +- .../Room/Cotija/CotijaSystemController.cs | 32 +- .../DeviceTypeInterfaces/IDPadExtensions.cs | 39 + .../Room/EssentialsHuddleSpaceRoom.cs | 558 +++++++------- .../UI/EssentialsTouchpanelController.cs | 388 +++++----- 13 files changed, 969 insertions(+), 860 deletions(-) create mode 100644 Essentials/PepperDashEssentials/Room/Cotija/DeviceTypeInterfaces/IDPadExtensions.cs diff --git a/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IDPad.cs b/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IDPad.cs index 2e0f3ae7..131b24c0 100644 --- a/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IDPad.cs +++ b/Essentials Core/PepperDashEssentialsBase/DeviceTypeInterfaces/IDPad.cs @@ -45,6 +45,6 @@ namespace PepperDash.Essentials.Core triList.ClearBoolSigAction(142); triList.ClearBoolSigAction(130); triList.ClearBoolSigAction(134); - } + } } } \ No newline at end of file diff --git a/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs b/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs index bffea411..db064059 100644 --- a/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs +++ b/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs @@ -34,6 +34,8 @@ namespace PepperDash.Essentials.Core protected override Func IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } } protected override Func 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() diff --git a/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.projectinfo b/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.projectinfo index 66eccd5fb40f3d921915c0e82a651e0d5f316f64..ab60f177faad7a9d234da3c9460e1b06b64fd71a 100644 GIT binary patch delta 1109 zcmV-b1giUn3WExey?=u@yPrPV-FdY8>G)uO@4*B5Z0FNQJ3G{FPVG(}{l35NcdPns zvAjs17Ii*ttGdXW-}m=*{r$eb@9Q7`eShEFcKZANz7ByD2>6ZNS5LBrzL^wD|LZR9 zAbkiEjOH0tLrz_v#Olsb@S09BS?E6{gTl~Ulhw?v0gkY>cv%7 z=RZj;h(-{z@qf&+XLP7um8n&zshvdXGN6kv|M2zQ~H@ zF@3d|l-CZ#K7HfO+6FMQvZS^FCFsAs2lsX!eAFXYmr~y*i1b4Q)AvV3xHFMseL zJHNkoaQ}XO|K6vcPIvNq(|xd#%+;+%q=dh@;qz*mm482!X}Xy&g^W-0Rlc0%%PDpJ z(WCE~*|;Ch#z{@nU02KT>teAgU(d68MdCYtnqL;v{PlXZs_Iq&DuJh2mhVsY_wGN; zvhz=OAMV_Lc)pY6_xAT6+?$-w_Iv`r2XuMo_I=!LW*)r<20!E}>`&46M<2b)8>R#Q z`AbG-(tkd^-K2dH&eUXfem|R@X9qje>AlJ1;KBLc?kt}iJlx&gJDBXwZZlH`WH3Fq z0Q`Z|W4ir+@ti!k)tsER^SoZ>Et#*ydRa^}7{Vr;r+c5~pMH98|KWq(hxd2)ck=wx z^WDjQKAGOXcYZ(59^7J{Hg*%t-7Px%u({ia%76ch=kwrJ^Z6=YRBhgw!0deQ(|l*L zcW-BZ?_vJw!@cS3-u<0?`suyt!<`3{{1y`!!VPBZ7SKOz#=^e;Upz$*Z#6|-3cef z8-J?jj3~wS9^NCfzVj)u^26EvgUP4&A3mJq*{A$jmJc~+9-v?XZUOF=6ACVIH{n@>pS(eXcv-5+8_ow$h&8Cy{Y?|-P?)$Xg04|IM?oH#7^c^79g5ceOlQwtsmIdW6%F-#b4)$Y+yDcCbI4&K~UEzdw2S z@L-?fm;Hl-N#I7`25c}dw*da$^D^A^|C=Z1-p~ZS{)y+`&P(cLV1CYbruTR5&t~~_ zc91Hfj=AlsYLU=Q{l-hYtiGh+994<1Yh3`vZJw17K#YG$ delta 1112 zcmV-e1gHCh3Wf@hy?;;N?Cw6gzx!xscYN>OgT03jKc$Z!?d(vyIkh`^^!xt4->vGm z#quJ3TGaWpt?D9ge&65M_4oV!zOR4$_x*iy+v)H7`#Jhh`esrr{ja;Y zkEg5h2ZTytsq(U}ewwg2Tb@_XiZWkji~NUx<^~K`f>1#S5r3j*4RzmMo2h$!-L(1Q zg&?_cifCLHb+$O0y~!?a*>;iFGNH$_SvpwnUuNykKDSeEUu4VTJa1Zu>OK1OM*c9A_#!Ko z$Mn@=QeHa{`}B=BYa77K%97d!l%W6iKE1cM_fd~vT}pkMAkt^Eo!$M1(@8e@G=KQ% z!-v_u+3w`Qy@ScUPw&m92fLqAOPQ-%jYtW9bHnG=G=D39DARN^UkVwY=Bs=;%a>E? z`lCnRGqZ6&oQ;#3rn|0|&cBAlto?EHQ+pIe56cyLT|zo!w@p49H-5 zZUOiMr^j^r|Kd4$aH}~vZRdHt%v&;Fi}kXYW-x?JI8XOJ%|HG0-u}Y}yASX0?(gLJ zr{}wq{d_XLfA9Q$o;|q5JZ*JpzNp%~GlALp-lzG_ zWbfY2{@%m<(}#Q0*}eNa`SjC!(}z0`CiyKUFoYY-*e#%c*o=jJ|G#*O9^Pt-zB&tM zXXoJIz1_WRXFA!L?BBolVCTW!j2M3J-hTdIH{ZF<>{yV&#M}b#hfR#__W#9mvbz&b zihnm$&lypQ?LE9lW_{;VV&#Xk`v;Rx?>~Gv$+J)Svn=27ry>q0n1EY=yX6GLJNth# z*>^*-JH~mDU$vxgtMiWE_HerMaC(1sZ)cX}v)SzY;Nku0y-&00u{?7f` zET7H}vIhtEX8V%|_xE-m+~3)qP9_fq=4TLUFg>?`{od0v*z^DUW~cLkovTiwz)_9u zY1U@rS=PGQIoR8oe7ZZ`KbRh5ds7=nH4$A$6#xKA8-%|A diff --git a/Essentials DM/Essentials_DM/Essentials_DM.projectinfo b/Essentials DM/Essentials_DM/Essentials_DM.projectinfo index a1d68468ae29e099cc28d5dcff2e3600679ef21d..d3fdabc8c56d633b7c8e806ee23a122968c9962c 100644 GIT binary patch delta 605 zcmV-j0;2u&2=NGzu@rakX7|%ayE~8e?v3|$?tl95{-?3UFadvi5AN+^T08XV66V_k zk3M^_H+k^j!S2C>d*`$LhxZ<22lsaF?VRt=CX;(Rvz-HKDN}Qc(I}N~YWBREX64V; zj3}esK(nX$Dqqg><&^sR=+XBK;qQlpKdEV6>uNcET`X4R>v>kMNC3xA^UGqIzh19a zRoyB;rRFrt^8IGX{@(qES$6*E?!%q?56^e9{NDclgL{+n*`80$_kb?%+`f<7OvI!2 z=>KPb#`<&e{n1CS@`eY_fBuq@nWax}H%n%&m28vQ`TcBqo*nE=r}rk4g9qn(yR&?9 z@Njo`?_jb!yOY=gFaw@_%99HN9Dh9j^ueclSw6Y9mp^!ro!{R(xPL#tfA7;zr#tz* z>HZMK<1ho_-vaXc5y(%QySmF-oyJ3@_a@Neec18 r>CG16gZ%yoYQNIFadwN5AWaG`>02sE@8e+ z@aVJIEc}kHrm$Q61rM^CT^gToP`yt^^YMR%&T8>{Ai&go0p4BT7!12@kvY6(t*Q-@k zw+c|HInAC@ZIl9_8I+hlfrKbxLs2Rqa0y~*U@!TH|qET0@a z+}+(fAPKmW+5#{GPI?EE4Fep1e73W@|8P3VCZFaHKYjQxyEogNJh*o-x%cV4+4Nxd z(*cUdVFtv%1?2Z7e!SQJcg+JVrZ*2xL|^1rZMAHw^NuBWINf5lk8xBI-Nb(y?=l5@ZrIJ{^^7LgM&$6iEjfon21{df6s{+?)d*@GqO80 zBd>qr`M2|uuo#$-^PTDao%^#{KAjz84-W3l_9qYS@9jRgzq31?OdbqO$RN~UK5hZ~ zJ?CSv-~U%kN9O}OIeSA-lk+rdv+*oz-E - /// - /// - 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 PowerIsOnFeedbackFunc { get { return () => _PowerIsOn; } } - protected override Func IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } } - protected override Func IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } } - - /// - /// Constructor for IBasicCommunication - /// - public NecPSXMDisplay(string key, string name, IBasicCommunication comm) - : base(key, name) - { - Communication = comm; - Init(); - } - /// - /// Constructor for TCP - /// - public NecPSXMDisplay(string key, string name, string hostname, int port) - : base(key, name) - { - Communication = new GenericTcpIpClient(key + "-tcp", hostname, port, 5000); - Init(); - } - - - /// - /// Constructor for COM - /// - 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 Feedbacks - { - get - { - var list = base.Feedbacks; - list.AddRange(new List - { - - }); - 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 +{ + /// + /// + /// + 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 PowerIsOnFeedbackFunc { get { return () => _PowerIsOn; } } + protected override Func IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } } + protected override Func IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } } + + /// + /// Constructor for IBasicCommunication + /// + public NecPSXMDisplay(string key, string name, IBasicCommunication comm) + : base(key, name) + { + Communication = comm; + Init(); + } + /// + /// Constructor for TCP + /// + public NecPSXMDisplay(string key, string name, string hostname, int port) + : base(key, name) + { + Communication = new GenericTcpIpClient(key + "-tcp", hostname, port, 5000); + Init(); + } + + + /// + /// Constructor for COM + /// + 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 Feedbacks + { + get + { + var list = base.Feedbacks; + list.AddRange(new List + { + + }); + 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 + } } \ No newline at end of file diff --git a/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.projectinfo b/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.projectinfo index 08ced49865194415a2fe09206b48a150d25d7694..6d19ee970b1114bd276fe85936d9a7009de167f9 100644 GIT binary patch delta 610 zcmV-o0-gPa35E%f!W0K@c0YZzyYpyoXT1C1-odAzeoC>{Dgl4@;NH%`M?K1QN%n0b z1AX>zXS)9|-bOLT{_q>{Bi`ZW?H1ra zXwo`;|9@k?9)$Dd@cI2usyYwnXYb)XV)~s=@9peAoZUZ|e0u-k!%3cf%AaNVjz2$f zK*4<60^IH9Bi`5lH|T#bNPpKyWGeDcAAGu(<&%4R`GW`9`Tc*rgZuaM`}aQmbh?w@ zo9+)yMI2@@E4P6B-m?<#_Wv6b^e~(tC-N`ytF~G;)p^JMJe=-4oZg?^+nHtgY&JVT zczAz$@6&8LInSo~&g{NFH5;G>lX44~x0{p=9sYk~I(B!4=HpdPpE!R1;9wFs2Dbqlip|Zy-*<+Fd;b5(RP7E; z)$5;l{_VUZ>;`7)d}n%p=l*P#PiF_&gM)js{mFy-d%F+r@9a(|lLrGcH3&7Bs9V5( z--#OR`2W@O)cL^9+TPHtJh}B>Ogz z0iW$nAKZWV;NHWBv)P0E-t^Nf+nwzkJlMOpJK5dK&{8JtHsjF=xUt>yYMPZl?Af}J zQH7jO^Hsi_<;y7{@zJC2nMt`HPRdD5lU~zHuZzX1d_B+V6-oA3AiiF&R#n|9Kqd4v z%kurnJ_&A?oqv;p0!e>85{B&F!T!Cyy@Txj?BQ-c`SjC+y@%%q*)3+S12~wpTY&$d zN$d3e|Bd;25YCsw=l4IU>O7pEy@&UR>32T8x3m9ncK=}V>HUWfCwcZMf0pGt{`|xN z1@mzWaJQR}cwhhDp#Q-j{aqiCshI8T?mwJPvdO3U!%rVR%Ag?0>Et|{<~y_d{?u%M7EH=5VBT(0Hgx#^jp^9k8Jdq*`FV-pqFSCU+q?#4 z!imZ6ou41%v&nxXJJ_F2XAgGo-=92uc(9*;`e6UyU=lb6w*ec>&@F(!?+gw1{Qr@u z+8vsz*FW+6+j&XY4b0T}&h-Ay{n;#^&JMB%2lr + diff --git a/Essentials/PepperDashEssentials/PepperDashEssentials.projectinfo b/Essentials/PepperDashEssentials/PepperDashEssentials.projectinfo index e67ef7467533b47a1d6907ebea5ccf92155693dd..540ae9e365140943f4366c30d9114a1b3eef806a 100644 GIT binary patch delta 1436 zcmV;N1!MZe4#y6Vwtok2c0YZzyYp!8!T7vGm z#quJ3TGaWpt?D9ge&65M_4NDxzOR4$_x*iy+u!f|`?|jUcK)Z6Vj2HxJYD^Ox-RU< zU)I%6Q?F;s^Xgeq=F4o6|Lma^#b_lM6odg`cGggT?X{VY*MHYdn=f7nRs+AlJ1;KBLcE;07O!`@rsEcXzwUIH{{G)L2M=yF z2dC{kua|jCwq>zi7Sjw?%7~zn@7|~Rr=Q;2fB0bc;r-qHojm{ae0Q>+Pp0?po!`&1 z2e+7)jok!ub&Jlv=3H&W;s1T}cW|rud$xu-34iBnZ%Wo+|9&>RpJh7_56&MPO!p_B zP9J`HFFW6xo!>^o1z>~uxdrgAIX^+4|L>cRhqs!K&$Bka%C0*S^k8p)FW=kU%d&e1 z`}g+t4zl~Rhr2|`PY?DUo*!hln2`?PU`}oU{%g)jr`P}Y&C2f1t)}HwzNp%~Gb_Zf zpMT~%lf8R8`+E=bPap10XZP;!ES(!+IBuAmHlvb|6uaz{f7@HdG;xPmgPHf!ux+zHD)ydBgC#q&=ee7cwAl*z~+Jjl-P?;YH~pWnat>8I13{N8kbh~jaW0r77E z`8|jq@9_VH^U#UBf8#^w2Hp?$CJ!Dw*gbe~?|ioZ@ZN*$;NH%?o%8+KWO8q3wsUav zEX3pPTfqH#bMXJ-uzR-?cRPpSq`qFYNDHs#*JsN%ug|k-M;vCe{Ra^x3x2PUBNEr8vg&aRLD7ZSJ=4Lht~<>w_9gsbI%e&O&aCzmBV*q=^k q4|eb0pFDhcun|uV=KjIKB*>R{H~pBLD#1Q9+*o delta 1433 zcmV;K1!nrk4#W8_x*icPrvW)`})U!-`_X4{r$ebuj|`y=YKjWmhrE~)71~C>%xxw zWnKL=^?J5EubvfUzRVW+&mLM)j8=j{K^PEbXASk&UYq%NeSh7w`Qn9OH9&nD!bP1e z&Sr12iyK=l@>*u;cs48AqFQDp#x9?oRErf6VfN+nmQ!e6_}M4jO*4ABnB=q9)w-VM z$MtkxT;_I)PpZ}Ro9bCr&honX=#i0ty^ns$=%X)+WwBTg0=TS)Auh>oB}WpKh3X9r+hou{@>^7nAbZy}M7} zc(W3He^!>%Di|~UxBKw^J-po^O_wI$CRp^@d3G;*u>0`f-t@u!PxHO~?7@Tco%4M6 zoc`P2dk8=>E1L(QwB69+c{R<-pUo-Q#A8CKr}-*h&VTadl=}MU(f16g?}wy5sc91H zYB_#gELP>~c~-AT_Qp^1%VL_pUawYF-6}w(;WW$g{mK5`{fAk0{^{<+o%;{Zce4E6 z{{Dk|lk?f0Ps8_sF7MpFj~nLT(R+0L!3?~4urro zgVT1N*UP*m+p<_Mi)jWcWkgWPckk2u(@*d1KP1g_e|LW;&p$oio$Tk6>HT}>_w($* zE#_roH^E%pqO-3#R~vEof8YEa+-m-wtzk~W`G4A*=95qN?`O07S+?`=;QYbCbbs>c z^x>!Xvh%&!`E4{@05+JPTLAx>^Aq&>|GxQnc&qvNJZtl-?7AaC5BB!=^1a=?EW3BG ze{XN^AiF<%xJ!im^kDDd`9XGz8R-BH=HwROzvi5Ddi{UjtnBXGYFb|9i>l2#vqB8} zX@9;m*}JzxzEl3`!@cS3-u<0?`suyt!<`3{{1&qk!VM`=Z#5@h zorTk}bMWvU@$k-cvNPGgfA7K0gS{Ck{=Iwq`Gehj=Qh(}K?XB%3&3A;9Egn9&_weCt_BW5BBcuPKbsN{Ykh9WH1T0 z0DRLV+|=Ly3n$@TI0+8uNmb`B$%W6#*VoHwI0p~2$-R?p1Rj3|Q*aBoH%-9}-Tl9C z2KI+$;P=M}I*!xBdla?pd`c?&;q3mw}8_Qox-ZrW;b+_rTwS(95mFf~M| z$^LAAdVlvJDf0W-`NN%^-B0t`G~1hf`spNaleq>>d!J_03C6iI zyC0{24_ZeOZiIPz()YUhe<9U75px)2=I?Sx?(_3c4{{1xAAU;F>+E1}hcZ9=d%F)P zv7P04b{;3U0~65s7Qk*#XV=I73klqbh8@zi@bz&nA=XV1GKDJ=nc} nfAa9*6TyD|>4W`)gGrE0?ShSg4JP0gldJ}m2T4Rsh$8?1PL@1x diff --git a/Essentials/PepperDashEssentials/Room/Cotija/CotijaRoomBridge.cs b/Essentials/PepperDashEssentials/Room/Cotija/CotijaRoomBridge.cs index e8e468fa..1e1f2559 100644 --- a/Essentials/PepperDashEssentials/Room/Cotija/CotijaRoomBridge.cs +++ b/Essentials/PepperDashEssentials/Room/Cotija/CotijaRoomBridge.cs @@ -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); + } + } + + } /// diff --git a/Essentials/PepperDashEssentials/Room/Cotija/CotijaSystemController.cs b/Essentials/PepperDashEssentials/Room/Cotija/CotijaSystemController.cs index 3f038bac..a89b7c7f 100644 --- a/Essentials/PepperDashEssentials/Room/Cotija/CotijaSystemController.cs +++ b/Essentials/PepperDashEssentials/Room/Cotija/CotijaSystemController.cs @@ -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."); + } + /// /// 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)(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)(stateString == "true"); + (action as PressAndHoldAction)(stateString == "true"); } } else if (action is Action) diff --git a/Essentials/PepperDashEssentials/Room/Cotija/DeviceTypeInterfaces/IDPadExtensions.cs b/Essentials/PepperDashEssentials/Room/Cotija/DeviceTypeInterfaces/IDPadExtensions.cs new file mode 100644 index 00000000..f6d3e0c1 --- /dev/null +++ b/Essentials/PepperDashEssentials/Room/Cotija/DeviceTypeInterfaces/IDPadExtensions.cs @@ -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(dev.Up)); + controller.AddAction(prefix + "down", new Action(dev.Down)); + controller.AddAction(prefix + "left", new Action(dev.Left)); + controller.AddAction(prefix + "right", new Action(dev.Right)); + controller.AddAction(prefix + "select", new Action(dev.Select)); + controller.AddAction(prefix + "menu", new Action(dev.Menu)); + controller.AddAction(prefix + "exit", new Action(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"); + } + } +} \ No newline at end of file diff --git a/Essentials/PepperDashEssentials/Room/EssentialsHuddleSpaceRoom.cs b/Essentials/PepperDashEssentials/Room/EssentialsHuddleSpaceRoom.cs index fa7bee4c..baf71ee5 100644 --- a/Essentials/PepperDashEssentials/Room/EssentialsHuddleSpaceRoom.cs +++ b/Essentials/PepperDashEssentials/Room/EssentialsHuddleSpaceRoom.cs @@ -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 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; } - - /// - /// The config name of the source list - /// - public string SourceListKey { get; set; } - - /// - /// If room is off, enables power on to last source. Default true - /// - public bool EnablePowerOnToLastSource { get; set; } - string LastSourceKey; - - /// - /// - /// - 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; - - /// - /// The SourceListItem last run - containing names and icons - /// - 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 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; } + + /// + /// The config name of the source list + /// + public string SourceListKey { get; set; } + + /// + /// If room is off, enables power on to last source. Default true + /// + public bool EnablePowerOnToLastSource { get; set; } + string LastSourceKey; + + /// + /// + /// + 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; + + /// + /// The SourceListItem last run - containing names and icons + /// + 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; } - - /// - /// - /// - public BoolFeedback OnFeedback { get; private set; } - - /// - /// - /// - /// - /// - 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); - } - - /// - /// Gets a source from config list SourceListKey and dynamically build and executes the - /// route or commands - /// - /// - 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; } + + /// + /// + /// + public BoolFeedback OnFeedback { get; private set; } + + /// + /// + /// + /// + /// + 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); + } + + /// + /// Gets a source from config list SourceListKey and dynamically build and executes the + /// route or commands + /// + /// + 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 - } - - /// - /// Will power the room on with the last-used source - /// - public void PowerOnToDefaultOrLastSource() - { - if (!EnablePowerOnToLastSource || LastSourceKey == null) - return; - RunRouteAction(LastSourceKey); - } - - /// - /// - /// - /// - /// - 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; - } - - /// - /// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions - /// - 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 + } + + /// + /// Will power the room on with the last-used source + /// + public void PowerOnToDefaultOrLastSource() + { + if (!EnablePowerOnToLastSource || LastSourceKey == null) + return; + RunRouteAction(LastSourceKey); + } + + /// + /// + /// + /// + /// + 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; + } + + /// + /// Runs "roomOff" action on all rooms not set to ExcludeFromGlobalFunctions + /// + 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"); + } + } } \ No newline at end of file diff --git a/Essentials/PepperDashEssentials/UI/EssentialsTouchpanelController.cs b/Essentials/PepperDashEssentials/UI/EssentialsTouchpanelController.cs index a6b1f623..50a4281a 100644 --- a/Essentials/PepperDashEssentials/UI/EssentialsTouchpanelController.cs +++ b/Essentials/PepperDashEssentials/UI/EssentialsTouchpanelController.cs @@ -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); - } - - /// - /// Config constructor - /// - 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); + } + + /// + /// Config constructor + /// + 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(b => { if (!b) avDriver.PowerButtonPressed(); }); - //tsw.Home.UserObject = new Action(b => { if (!b) HomePressed(); }); - tsw.Up.UserObject = new Action(avDriver.VolumeUpPress); - tsw.Down.UserObject = new Action(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(b => { if (!b) avDriver.PowerButtonPressed(); }); - //tsw.Home.UserObject = new Action(b => { if (!b) HomePressed(); }); - tsw.Up.UserObject = new Action(avDriver.VolumeUpPress); - tsw.Down.UserObject = new Action(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) - (uo as Action)(args.Sig.BoolValue); - else if (uo is Action) - (uo as Action)(args.Sig.UShortValue); - else if (uo is Action) - (uo as Action)(args.Sig.StringValue); - } - - void Tsw_ButtonStateChange(GenericBase device, ButtonEventArgs args) - { - var uo = args.Button.UserObject; - if(uo is Action) - (uo as Action)(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(b => { if (!b) avDriver.PowerButtonPressed(); }); + //tsw.Home.UserObject = new Action(b => { if (!b) HomePressed(); }); + tsw.Up.UserObject = new Action(avDriver.VolumeUpPress); + tsw.Down.UserObject = new Action(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(b => { if (!b) avDriver.PowerButtonPressed(); }); + //tsw.Home.UserObject = new Action(b => { if (!b) HomePressed(); }); + tsw.Up.UserObject = new Action(avDriver.VolumeUpPress); + tsw.Down.UserObject = new Action(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) + (uo as Action)(args.Sig.BoolValue); + else if (uo is Action) + (uo as Action)(args.Sig.UShortValue); + else if (uo is Action) + (uo as Action)(args.Sig.StringValue); + } + + void Tsw_ButtonStateChange(GenericBase device, ButtonEventArgs args) + { + var uo = args.Button.UserObject; + if(uo is Action) + (uo as Action)(args.Button.State == eButtonState.Pressed); + } + } } \ No newline at end of file