From 0f3b0580f052650474a330362143f014ba639c45 Mon Sep 17 00:00:00 2001 From: mhengeli Date: Wed, 7 Jun 2023 09:45:25 -0400 Subject: [PATCH 01/50] feat: add videomute on/off for rmc scaler c --- .../PepperDashEssentials.csproj | 2 +- .../JoinMaps/DmRmcControllerJoinMap.cs | 12 ++++++ .../PepperDash_Essentials_Core.csproj | 2 +- .../Receivers/DmRmc4KScalerCController.cs | 43 ++++++++++++++++++- .../Endpoints/Receivers/DmRmcHelper.cs | 21 ++++++++- .../PepperDash_Essentials_DM.csproj | 5 ++- .../Essentials Devices Common.csproj | 2 +- 7 files changed, 79 insertions(+), 8 deletions(-) diff --git a/PepperDashEssentials/PepperDashEssentials.csproj b/PepperDashEssentials/PepperDashEssentials.csproj index e4a0cff6..f406d8be 100644 --- a/PepperDashEssentials/PepperDashEssentials.csproj +++ b/PepperDashEssentials/PepperDashEssentials.csproj @@ -73,7 +73,7 @@ False - ..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll + ..\..\PepperDashCore\Pepperdash Core\Pepperdash Core\bin\PepperDash_Core.dll False diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/DmRmcControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/DmRmcControllerJoinMap.cs index cff5bffe..c0e7141f 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/DmRmcControllerJoinMap.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/DmRmcControllerJoinMap.cs @@ -8,6 +8,18 @@ namespace PepperDash.Essentials.Core.Bridges public JoinDataComplete IsOnline = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, new JoinMetadata { Description = "DM RMC Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + [JoinName("VideoMuteOn")] + public JoinDataComplete VideoMuteOn = new JoinDataComplete(new JoinData { JoinNumber = 3, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC Mute Video", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("VideoMuteOff")] + public JoinDataComplete VideoMuteOff = new JoinDataComplete(new JoinData { JoinNumber = 4, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC UnMute Video", JoinCapabilities = eJoinCapabilities.ToFromSIMPL, JoinType = eJoinType.Digital }); + + [JoinName("VideoMuteToggle")] + public JoinDataComplete VideoMuteToggle = new JoinDataComplete(new JoinData { JoinNumber = 5, JoinSpan = 1 }, + new JoinMetadata { Description = "DM RMC Mute Video Toggle", JoinCapabilities = eJoinCapabilities.FromSIMPL, JoinType = eJoinType.Digital }); + [JoinName("CurrentOutputResolution")] public JoinDataComplete CurrentOutputResolution = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, new JoinMetadata { Description = "DM RMC Current Output Resolution", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Serial }); diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index e0859077..e87ac31d 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -85,7 +85,7 @@ False - ..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll + ..\..\..\..\PepperDashCore\Pepperdash Core\Pepperdash Core\bin\PepperDash_Core.dll False diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmc4KScalerCController.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmc4KScalerCController.cs index 79069430..79debd63 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmc4KScalerCController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmc4KScalerCController.cs @@ -7,6 +7,7 @@ using PepperDash.Core; using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash_Essentials_DM; +using System.Collections.Generic; namespace PepperDash.Essentials.DM { @@ -16,7 +17,7 @@ namespace PepperDash.Essentials.DM /// [Description("Wrapper Class for DM-RMC-4K-SCALER-C")] public class DmRmc4kScalerCController : DmRmcControllerBase, IRoutingInputsOutputs, IBasicVolumeWithFeedback, - IIROutputPorts, IComPorts, ICec, IRelayPorts, IHasDmInHdcp + IIROutputPorts, IComPorts, ICec, IRelayPorts, IHasDmInHdcp, IBasicVideoMuteWithFeedback { private readonly DmRmc4kScalerC _rmc; @@ -68,6 +69,7 @@ namespace PepperDash.Essentials.DM AddToFeedbackList(DmInHdcpStateFeedback); + VideoMuteIsOn = new BoolFeedback("HdmiOutputVideoMuteIsOn", () => _rmc.HdmiOutput.BlankEnabledFeedback.BoolValue); _rmc.HdmiOutput.OutputStreamChange += HdmiOutput_OutputStreamChange; _rmc.HdmiOutput.ConnectedDevice.DeviceInformationChange += ConnectedDevice_DeviceInformationChange; @@ -83,6 +85,10 @@ namespace PepperDash.Essentials.DM { VideoOutputResolutionFeedback.FireUpdate(); } + else if (args.EventId == EndpointOutputStreamEventIds.BlankEnabledFeedbackEventId) + { + VideoMuteIsOn.FireUpdate(); + } } void ConnectedDevice_DeviceInformationChange(ConnectedDeviceInformation connectedDevice, ConnectedDeviceEventArgs args) @@ -216,5 +222,40 @@ namespace PepperDash.Essentials.DM _rmc.DmInput.HdcpCapability = hdcpState; } + + #region IBasicVideoMuteWithFeedback Members + + public BoolFeedback VideoMuteIsOn + { + get; + private set; + } + + public void VideoMuteOn() + { + Debug.Console(2, this, "Video Mute On"); + _rmc.HdmiOutput.BlankEnabled(); + } + + public void VideoMuteOff() + { + Debug.Console(2, this, "Video Mute Off"); + _rmc.HdmiOutput.BlankDisabled(); + } + + #endregion + + #region IBasicVideoMute Members + + public void VideoMuteToggle() + { + Debug.Console(2, this, "Video Mute Toggle"); + if (_rmc.HdmiOutput.BlankEnabledFeedback.BoolValue == true) + VideoMuteOff(); + else + VideoMuteOn(); + } + + #endregion } } \ No newline at end of file diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs index 57f522fd..ef0c15a3 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs @@ -59,8 +59,13 @@ namespace PepperDash.Essentials.DM else { Debug.Console(0, this, "Please update config to use 'eiscapiadvanced' to get all join map features for this device."); - } + } + + LinkDmRmcToApi(rmc, trilist, joinMap); + } + protected void LinkDmRmcToApi(DmRmcControllerBase rmc, BasicTriList trilist, DmRmcControllerJoinMap joinMap) + { Debug.Console(1, rmc, "Linking to Trilist '{0}'", trilist.ID.ToString("X")); IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); @@ -137,7 +142,18 @@ namespace PepperDash.Essentials.DM trilist.UShortInput[joinMap.HdcpSupportCapability.JoinNumber].UShortValue = (ushort)hdcpCapability; - trilist.UShortInput[joinMap.HdcpInputPortCount.JoinNumber].UShortValue = (ushort)routing.InputPorts.Count; + trilist.UShortInput[joinMap.HdcpInputPortCount.JoinNumber].UShortValue = (ushort)routing.InputPorts.Count; + + var dmRmcScalerCBasicVideoMuteWithFeedback = rmc as IBasicVideoMuteWithFeedback; + + if (dmRmcScalerCBasicVideoMuteWithFeedback != null) + { + Debug.Console(1, this, "Device is IBasicVideoMuteWithFeedback, linking video mute"); + trilist.SetSigTrueAction(joinMap.VideoMuteToggle.JoinNumber, () => dmRmcScalerCBasicVideoMuteWithFeedback.VideoMuteToggle()); + trilist.SetSigTrueAction(joinMap.VideoMuteOn.JoinNumber, () => dmRmcScalerCBasicVideoMuteWithFeedback.VideoMuteOn()); + trilist.SetSigTrueAction(joinMap.VideoMuteOff.JoinNumber, () => dmRmcScalerCBasicVideoMuteWithFeedback.VideoMuteOff()); + dmRmcScalerCBasicVideoMuteWithFeedback.VideoMuteIsOn.LinkInputSig(trilist.BooleanInput[joinMap.VideoMuteOn.JoinNumber]); + } var routingWithFeedback = routing as IRmcRouting; if (routingWithFeedback == null) return; @@ -149,6 +165,7 @@ namespace PepperDash.Essentials.DM trilist.SetUShortSigAction(joinMap.AudioVideoSource.JoinNumber, a => routingWithFeedback.ExecuteNumericSwitch(a, 1, eRoutingSignalType.AudioVideo)); + } #region Implementation of IDeviceInfoProvider diff --git a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj index 068d39cf..85447e03 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj +++ b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj @@ -59,9 +59,9 @@ ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll - + False - ..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll + ..\..\..\..\PepperDashCore\Pepperdash Core\Pepperdash Core\bin\PepperDash_Core.dll False @@ -153,6 +153,7 @@ + diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj index a1cc37f2..a59b663f 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj @@ -65,7 +65,7 @@ False - ..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll + ..\..\..\..\PepperDashCore\Pepperdash Core\Pepperdash Core\bin\PepperDash_Core.dll False From 16ea7a88be4b8a5397d565d9061460960131ad07 Mon Sep 17 00:00:00 2001 From: mhengeli Date: Wed, 7 Jun 2023 12:22:03 -0400 Subject: [PATCH 02/50] fix: updated Core references --- PepperDashEssentials/PepperDashEssentials.csproj | 4 ++-- .../PepperDash_Essentials_Core.csproj | 4 ++-- .../Essentials_DM/PepperDash_Essentials_DM.csproj | 4 ++-- .../Essentials Devices Common.csproj | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/PepperDashEssentials/PepperDashEssentials.csproj b/PepperDashEssentials/PepperDashEssentials.csproj index f406d8be..05c20381 100644 --- a/PepperDashEssentials/PepperDashEssentials.csproj +++ b/PepperDashEssentials/PepperDashEssentials.csproj @@ -71,9 +71,9 @@ ..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll - + False - ..\..\PepperDashCore\Pepperdash Core\Pepperdash Core\bin\PepperDash_Core.dll + ..\.packages\PepperDashCore\lib\net35\PepperDash_Core.dll False diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index e87ac31d..db967390 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -83,9 +83,9 @@ ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll - + False - ..\..\..\..\PepperDashCore\Pepperdash Core\Pepperdash Core\bin\PepperDash_Core.dll + ..\..\..\.packages\PepperDashCore\lib\net35\PepperDash_Core.dll False diff --git a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj index 85447e03..a089dccf 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj +++ b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj @@ -59,9 +59,9 @@ ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.UI.dll - + False - ..\..\..\..\PepperDashCore\Pepperdash Core\Pepperdash Core\bin\PepperDash_Core.dll + ..\..\..\.packages\PepperDashCore\lib\net35\PepperDash_Core.dll False diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj index a59b663f..104026b0 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj @@ -63,9 +63,9 @@ ..\..\..\..\..\..\..\..\..\ProgramData\Crestron\SDK\SSPDevices\Crestron.SimplSharpPro.Lighting.dll - + False - ..\..\..\..\PepperDashCore\Pepperdash Core\Pepperdash Core\bin\PepperDash_Core.dll + ..\..\..\.packages\PepperDashCore\lib\net35\PepperDash_Core.dll False From 515ffd07f067735a36fb9623ecfb74d48d16d402 Mon Sep 17 00:00:00 2001 From: mhengeli Date: Wed, 7 Jun 2023 13:16:06 -0400 Subject: [PATCH 03/50] fix: added complimentary link for mute off. fix: Update references --- PepperDashEssentials/PepperDashEssentials.csproj | 2 +- .../PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj | 2 +- .../Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs | 1 + .../Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj | 2 +- .../Essentials Devices Common/Essentials Devices Common.csproj | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/PepperDashEssentials/PepperDashEssentials.csproj b/PepperDashEssentials/PepperDashEssentials.csproj index 05c20381..66a20f72 100644 --- a/PepperDashEssentials/PepperDashEssentials.csproj +++ b/PepperDashEssentials/PepperDashEssentials.csproj @@ -73,7 +73,7 @@ False - ..\.packages\PepperDashCore\lib\net35\PepperDash_Core.dll + ..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll False diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index db967390..ba59a085 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -85,7 +85,7 @@ False - ..\..\..\.packages\PepperDashCore\lib\net35\PepperDash_Core.dll + ..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll False diff --git a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs index ef0c15a3..ee423436 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Endpoints/Receivers/DmRmcHelper.cs @@ -153,6 +153,7 @@ namespace PepperDash.Essentials.DM trilist.SetSigTrueAction(joinMap.VideoMuteOn.JoinNumber, () => dmRmcScalerCBasicVideoMuteWithFeedback.VideoMuteOn()); trilist.SetSigTrueAction(joinMap.VideoMuteOff.JoinNumber, () => dmRmcScalerCBasicVideoMuteWithFeedback.VideoMuteOff()); dmRmcScalerCBasicVideoMuteWithFeedback.VideoMuteIsOn.LinkInputSig(trilist.BooleanInput[joinMap.VideoMuteOn.JoinNumber]); + dmRmcScalerCBasicVideoMuteWithFeedback.VideoMuteIsOn.LinkComplementInputSig(trilist.BooleanInput[joinMap.VideoMuteOff.JoinNumber]); } var routingWithFeedback = routing as IRmcRouting; diff --git a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj index a089dccf..adfddbe3 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj +++ b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj @@ -61,7 +61,7 @@ False - ..\..\..\.packages\PepperDashCore\lib\net35\PepperDash_Core.dll + ..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll False diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj index 104026b0..845b61ef 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Essentials Devices Common.csproj @@ -65,7 +65,7 @@ False - ..\..\..\.packages\PepperDashCore\lib\net35\PepperDash_Core.dll + ..\..\..\packages\PepperDashCore\lib\net35\PepperDash_Core.dll False From 43f06d216786701a10edfb152f6b459b1f6e8552 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Fri, 16 Jun 2023 14:26:52 -0500 Subject: [PATCH 04/50] feature: Add USB-C as eRoutingPortConnectionType option --- .../PepperDashEssentialsBase/Routing/RoutingPort.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs index 79dd4eda..8dc8fc4e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs @@ -42,7 +42,7 @@ namespace PepperDash.Essentials.Core public enum eRoutingPortConnectionType { None, BackplaneOnly, DisplayPort, Dvi, Hdmi, Rgb, Vga, LineAudio, DigitalAudio, Sdi, - Composite, Component, DmCat, DmMmFiber, DmSmFiber, Speaker, Streaming + Composite, Component, DmCat, DmMmFiber, DmSmFiber, Speaker, Streaming, UsbC } /// From 0ee6322684e62e1dec9b9d01a0eb0a4f3518e4e9 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Fri, 16 Jun 2023 14:50:10 -0500 Subject: [PATCH 05/50] feature: Add USBCIn and Out Names for RoutingPortNames --- .../Routing/RoutingPortNames.cs | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPortNames.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPortNames.cs index 00e85191..beef0dae 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPortNames.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPortNames.cs @@ -199,5 +199,37 @@ namespace PepperDash.Essentials.Core.Routing /// MediaPlayer /// public const string MediaPlayer = "mediaPlayer"; - } + /// + /// UsbCIn + /// + public const string UsbCIn = "usbCIn"; + /// + /// UsbCIn1 + /// + public const string UsbCIn1 = "usbCIn1"; + /// + /// UsbCIn2 + /// + public const string UsbCIn2 = "usbCIn2"; + /// + /// UsbCIn3 + /// + public const string UsbCIn3 = "usbCIn3"; + /// + /// UsbCOut + /// + public const string UsbCOut = "usbCOut"; + /// + /// UsbCOut1 + /// + public const string UsbCOut1 = "usbCOut1"; + /// + /// UsbCOut2 + /// + public const string UsbCOut2 = "usbCOut2"; + /// + /// UsbCOut3 + /// + public const string UsbCOut3 = "usbCOut3"; + } } \ No newline at end of file From a04bfd1fcb172d20ef73fd31a08a3bb937fadada Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Fri, 16 Jun 2023 14:56:21 -0500 Subject: [PATCH 06/50] feature: Add HdBaseTIn and HdBaseTOut as RoutingPortNames --- .../PepperDashEssentialsBase/Routing/RoutingPortNames.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPortNames.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPortNames.cs index beef0dae..7029443b 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPortNames.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPortNames.cs @@ -231,5 +231,13 @@ namespace PepperDash.Essentials.Core.Routing /// UsbCOut3 /// public const string UsbCOut3 = "usbCOut3"; + /// + /// HdBaseTIn + /// + public const string HdBaseTIn = "hdBaseTIn"; + /// + /// HdBaseTOut + /// + public const string HdBaseTOut = "hdBaseTOut"; } } \ No newline at end of file From f4af1b6e7c853dc1df0e4f9d9319f3e64e190c8e Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Fri, 16 Jun 2023 14:57:48 -0500 Subject: [PATCH 07/50] feature: Add HdBaseT as a eRoutingPortConnectionType --- .../PepperDashEssentialsBase/Routing/RoutingPort.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs index 8dc8fc4e..ab64f15e 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingPort.cs @@ -42,7 +42,7 @@ namespace PepperDash.Essentials.Core public enum eRoutingPortConnectionType { None, BackplaneOnly, DisplayPort, Dvi, Hdmi, Rgb, Vga, LineAudio, DigitalAudio, Sdi, - Composite, Component, DmCat, DmMmFiber, DmSmFiber, Speaker, Streaming, UsbC + Composite, Component, DmCat, DmMmFiber, DmSmFiber, Speaker, Streaming, UsbC, HdBaseT } /// From 3f6b2f05a28dab2bf0e394bf70d9c4d428cf1921 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Tue, 4 Jul 2023 23:53:31 -0500 Subject: [PATCH 08/50] feature: Add Static Class to assist with getting network information about connected devices feature: Add overload to 'Contains' extension method to allow for some more verbose comparisons feature: Add 'TrimAll' string extension method to TrimStart and TrimEnd with an overload to set the character to trim docs: improve XML summary comments for string extensions --- .../Device Info/NetworkDeviceHelpers.cs | 218 ++++++++++++++++++ .../Extensions/StringExtensions.cs | 54 +++++ .../PepperDash_Essentials_Core.csproj | 1 + 3 files changed, 273 insertions(+) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Device Info/NetworkDeviceHelpers.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Device Info/NetworkDeviceHelpers.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Device Info/NetworkDeviceHelpers.cs new file mode 100644 index 00000000..04e697c9 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Device Info/NetworkDeviceHelpers.cs @@ -0,0 +1,218 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using PepperDash.Core; +using Crestron.SimplSharp; +using PepperDash.Essentials.Core; + +namespace PepperDash.Essentials.Core.DeviceInfo +{ + public static class NetworkDeviceHelpers + { + /// + /// Event raised when ArpTable changes + /// + public static event ArpTableEventHandler ArpTableUpdated; + + /// + /// Delegate called by ArpTableUpdated + /// + /// contains the entire ARP table and a bool to note if there was an error in retrieving the data + public delegate void ArpTableEventHandler(ArpTableEventArgs args); + + private static readonly char NewLineSplitter = CrestronEnvironment.NewLine.ToCharArray().First(); + private static readonly string NewLine = CrestronEnvironment.NewLine; + + private static readonly CCriticalSection Lock = new CCriticalSection(); + + /// + /// Last resolved ARP table - it is recommended to refresh the arp before using this. + /// + public static List ArpTable { get; private set; } + + /// + /// Force recheck of ARP table + /// + public static void RefreshArp() + { + var error = false; + try + { + Lock.Enter(); + var consoleResponse = string.Empty; + if (!CrestronConsole.SendControlSystemCommand("showarptable", ref consoleResponse)) return; + if (string.IsNullOrEmpty(consoleResponse)) + { + error = true; + return; + } + ArpTable.Clear(); + + Debug.Console(2, "ConsoleResponse of 'showarptable' : {0}{1}", NewLine, consoleResponse); + + var myLines = + consoleResponse.Split(NewLineSplitter) + .ToList() + .Where(o => (o.Contains(':') && !o.Contains("Type", StringComparison.OrdinalIgnoreCase))) + .ToList(); + foreach (var line in myLines) + { + var item = line; + var seperator = item.Contains('\t') ? '\t' : ' '; + var dataPoints = item.Split(seperator); + if (dataPoints == null || dataPoints.Length < 2) continue; + var ipAddress = SanitizeIpAddress(dataPoints.First().TrimAll()); + var macAddress = dataPoints.Last(); + ArpTable.Add(new ArpEntry(ipAddress, macAddress)); + } + } + catch (Exception ex) + { + Debug.Console(0, "Exception in \"RefreshArp\" : {0}", ex.Message); + error = true; + } + finally + { + Lock.Leave(); + OnArpTableUpdated(new ArpTableEventArgs(ArpTable, error)); + } + } + + + private static void OnArpTableUpdated(ArpTableEventArgs args) + { + if (args == null) return; + var handler = ArpTableUpdated; + if (handler == null) return; + handler.Invoke(args); + } + + static NetworkDeviceHelpers() + { + ArpTable = new List(); + } + + /// + /// Removes leading zeros, leading whitespace, and trailing whitespace from an IPAddress string + /// + /// Ip Address to Santitize + /// Sanitized Ip Address + public static string SanitizeIpAddress(string ipAddressIn) + { + try + { + var ipAddress = IPAddress.Parse(ipAddressIn.TrimStart('0')); + return ipAddress.ToString(); + } + catch (Exception ex) + { + Debug.Console(0, "Unable to Santize Ip : {0}", ex.Message); + return ipAddressIn; + } + } + + /// + /// Resolves a hostname by IP Address using DNS + /// + /// IP Address to resolve from + /// Resolved Hostname - on failure to determine hostname, will return IP Address + public static string ResolveHostnameFromIp(string ipAddress) + { + try + { + var santitizedIp = SanitizeIpAddress(ipAddress); + var hostEntry = Dns.GetHostEntry(santitizedIp); + return hostEntry == null ? ipAddress : hostEntry.HostName; + } + catch (Exception ex) + { + Debug.Console(0, "Exception Resolving Hostname from IP Address : {0}", ex.Message); + return ipAddress; + } + } + + /// + /// Resolves an IP Address by hostname using DNS + /// + /// Hostname to resolve from + /// Resolved IP Address - on a failure to determine IP Address, will return hostname + public static string ResolveIpFromHostname(string hostName) + { + try + { + var hostEntry = Dns.GetHostEntry(hostName); + return hostEntry == null ? hostName : hostEntry.AddressList.First().ToString(); + } + catch (Exception ex) + { + Debug.Console(0, "Exception Resolving IP Address from Hostname : {0}", ex.Message); + return hostName; + } + } + + } + + /// + /// Object to hold data about an arp entry + /// + public class ArpEntry + { + public readonly IPAddress IpAddress; + public readonly string MacAddress; + + /// + /// Constructs new ArpEntry object + /// + /// string formatted as ipv4 address + /// mac address string - format is unimportant + public ArpEntry(string ipAddress, string macAddress) + { + if (string.IsNullOrEmpty(ipAddress)) + { + throw new ArgumentException("\"ipAddress\" cannot be null or empty"); + } + if (string.IsNullOrEmpty(macAddress)) + { + throw new ArgumentException("\"macAddress\" cannot be null or empty"); + } + IpAddress = IPAddress.Parse(ipAddress.TrimStart().TrimStart('0').TrimEnd()); + MacAddress = macAddress; + } + } + + /// + /// Arguments passed by the ArpTableUpdated event + /// + public class ArpTableEventArgs : EventArgs + { + /// + /// The retrieved ARP Table + /// + public readonly List ArpTable; + /// + /// True if there was a problem retrieving the ARP Table + /// + public readonly bool Error; + + /// + /// Constructor for ArpTableEventArgs + /// + /// The entirety of the retrieved ARP table + /// True of an error was encountered updating the ARP table + public ArpTableEventArgs(List arpTable, bool error) + { + ArpTable = arpTable; + Error = error; + } + + /// + /// Constructor for ArpTableEventArgs - assumes no error encountered in retrieving ARP Table + /// + /// The entirety of the retrieved ARP table + public ArpTableEventArgs(List arpTable) + { + ArpTable = arpTable; + Error = false; + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/StringExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/StringExtensions.cs index 39501387..7bf8d5a5 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/StringExtensions.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Extensions/StringExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Collections.Generic; using System.Linq; using System.Text; @@ -8,17 +9,70 @@ namespace PepperDash.Essentials.Core { public static class StringExtensions { + /// + /// Returns null if a string is empty, otherwise returns the string + /// + /// string input + /// null if the string is emtpy, otherwise returns the string public static string NullIfEmpty(this string s) { return string.IsNullOrEmpty(s) ? null : s; } + + /// + /// Returns null if a string is empty or made of only whitespace characters, otherwise returns the string + /// + /// string input + /// null if the string is wempty or made of only whitespace characters, otherwise returns the string public static string NullIfWhiteSpace(this string s) { return string.IsNullOrEmpty(s.Trim()) ? null : s; } + + /// + /// Returns a replacement string if the input string is empty or made of only whitespace characters, otherwise returns the input string + /// + /// input string + /// string to replace with if input string is empty or whitespace + /// returns newString if s is null, emtpy, or made of whitespace characters, otherwise returns s public static string ReplaceIfNullOrEmpty(this string s, string newString) { return string.IsNullOrEmpty(s) ? newString : s; } + + /// + /// Overload for Contains that allows setting an explicit String Comparison + /// + /// Source String + /// String to check in Source String + /// Comparison parameters + /// true of string contains "toCheck" + public static bool Contains(this string source, string toCheck, StringComparison comp) + { + if (string.IsNullOrEmpty(source)) return false; + return source.IndexOf(toCheck, comp) >= 0; + } + + /// + /// Performs TrimStart() and TrimEnd() on source string + /// + /// String to Trim + /// Trimmed String + public static string TrimAll(this string source) + { + return string.IsNullOrEmpty(source) ? string.Empty : source.TrimStart().TrimEnd(); + } + + /// + /// Performs TrimStart(chars char[]) and TrimEnd(chars char[]) on source string. + /// + /// String to Trim + /// Char Array to trim from string + /// Trimmed String + public static string TrimAll(this string source, char[] chars) + { + return string.IsNullOrEmpty(source) ? string.Empty : source.TrimStart(chars).TrimEnd(chars); + } + } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 7930f49e..aff99ea7 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -200,6 +200,7 @@ + From c3ba6d5c2851b65d7e874135601b494a867320a4 Mon Sep 17 00:00:00 2001 From: Trevor Payne Date: Wed, 12 Jul 2023 12:27:38 -0500 Subject: [PATCH 09/50] fix: fix issue where the customactivate for the base class was beig suppressed in airmedia controllers --- .../Essentials DM/Essentials_DM/AirMedia/AirMediaController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/AirMedia/AirMediaController.cs b/essentials-framework/Essentials DM/Essentials_DM/AirMedia/AirMediaController.cs index ff07a54b..b1fa3186 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/AirMedia/AirMediaController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/AirMedia/AirMediaController.cs @@ -129,7 +129,7 @@ namespace PepperDash.Essentials.DM.AirMedia else AirMedia.DisplayControl.DisableAutomaticRouting(); - return true; + return base.CustomActivate(); } public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) From f0ae0094dcc359ef1481f900cd42e18a722512bf Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 19 Jul 2023 09:50:48 -0600 Subject: [PATCH 10/50] Adds optional enable property to partition sensor config and defaults to enable --- .../GlsPartitionSensorController.cs | 36 +++++++++++++------ .../GlsPartitionSensorPropertiesConfig.cs | 5 ++- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PartitionSensor/GlsPartitionSensorController.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PartitionSensor/GlsPartitionSensorController.cs index 16b2f265..73f15cf2 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PartitionSensor/GlsPartitionSensorController.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PartitionSensor/GlsPartitionSensorController.cs @@ -85,18 +85,32 @@ namespace PepperDash.Essentials.Core { if (_partitionSensor.IsOnline == false) return; - Debug.Console(1, this, "Attempting to apply settings to sensor from config"); + // Default to enable + _partitionSensor.Enable.BoolValue = true; - if (PropertiesConfig.Sensitivity != null) - { - Debug.Console(1, this, "Sensitivity found, attempting to set value '{0}' from config", - PropertiesConfig.Sensitivity); - _partitionSensor.Sensitivity.UShortValue = (ushort) PropertiesConfig.Sensitivity; - } - else - { - Debug.Console(1, this, "Sensitivity null, no value specified in config"); - } + Debug.Console(1, this, "Attempting to apply settings to sensor from config"); + + if (PropertiesConfig.Sensitivity != null) + { + Debug.Console(1, this, "Sensitivity found, attempting to set value '{0}' from config", + PropertiesConfig.Sensitivity); + _partitionSensor.Sensitivity.UShortValue = (ushort)PropertiesConfig.Sensitivity; + } + else + { + Debug.Console(1, this, "Sensitivity null, no value specified in config"); + } + + if (PropertiesConfig.Enable != null) + { + Debug.Console(1, this, "Enable found, attempting to set value '{0}' from config", + PropertiesConfig.Enable); + _partitionSensor.Enable.BoolValue = (bool)PropertiesConfig.Enable; + } + else + { + Debug.Console(1, this, "Enable null, no value specified in config"); + } } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PartitionSensor/GlsPartitionSensorPropertiesConfig.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PartitionSensor/GlsPartitionSensorPropertiesConfig.cs index 8a303662..c9f715b5 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PartitionSensor/GlsPartitionSensorPropertiesConfig.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PartitionSensor/GlsPartitionSensorPropertiesConfig.cs @@ -16,6 +16,9 @@ namespace PepperDash_Essentials_Core.PartitionSensor /// The sensitivity range shall be between 1(lowest) to 10 (highest). /// [JsonProperty("sensitivity")] - public ushort? Sensitivity { get; set; } + public ushort? Sensitivity { get; set; } + + [JsonProperty("enable")] + public bool? Enable { get; set; } } } \ No newline at end of file From a787be6ccc70f82acdeb1d63f38830a1830898f9 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 19 Jul 2023 15:28:24 -0600 Subject: [PATCH 11/50] Updates Vtc1 room types to allow for deactivation/activation --- .gitignore | 1 + .../Types/EssentialsCombinedHuddleVtc1Room.cs | 298 +++++++++++++----- .../Room/Types/EssentialsHuddleVtc1Room.cs | 296 ++++++++++------- 3 files changed, 399 insertions(+), 196 deletions(-) diff --git a/.gitignore b/.gitignore index 94b7d400..739a60ab 100644 --- a/.gitignore +++ b/.gitignore @@ -389,3 +389,4 @@ MigrationBackup/ # Fody - auto-generated XML schema FodyWeavers.xsd essentials-framework/Essentials Interfaces/PepperDash_Essentials_Interfaces/PepperDash_Essentials_Interfaces.csproj +.DS_Store diff --git a/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs index 50186d0b..3ed0946d 100644 --- a/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs @@ -226,66 +226,66 @@ namespace PepperDash.Essentials } } - void Initialize() + public override void Initialize() { try { - if (DefaultAudioDevice is IBasicVolumeControls) - DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls; - else if (DefaultAudioDevice is IHasVolumeDevice) - DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice; - CurrentVolumeControls = DefaultVolumeControls; + //if (DefaultAudioDevice is IBasicVolumeControls) + // DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls; + //else if (DefaultAudioDevice is IHasVolumeDevice) + // DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice; + //CurrentVolumeControls = DefaultVolumeControls; - // Combines call feedback from both codecs if available - InCallFeedback = new BoolFeedback(() => - { - bool inAudioCall = false; - bool inVideoCall = false; + //// Combines call feedback from both codecs if available + //InCallFeedback = new BoolFeedback(() => + //{ + // bool inAudioCall = false; + // bool inVideoCall = false; - if (AudioCodec != null) - inAudioCall = AudioCodec.IsInCall; + // if (AudioCodec != null) + // inAudioCall = AudioCodec.IsInCall; - if (VideoCodec != null) - inVideoCall = VideoCodec.IsInCall; + // if (VideoCodec != null) + // inVideoCall = VideoCodec.IsInCall; - if (inAudioCall || inVideoCall) - return true; - else - return false; - }); + // if (inAudioCall || inVideoCall) + // return true; + // else + // return false; + //}); - SetupDisplays(); + //SetupDisplays(); - // Get Microphone Privacy object, if any MUST HAPPEN AFTER setting InCallFeedback - this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this); + //// Get Microphone Privacy object, if any MUST HAPPEN AFTER setting InCallFeedback + //this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this); - Debug.Console(2, this, "Microphone Privacy Config evaluated."); + //Debug.Console(2, this, "Microphone Privacy Config evaluated."); - // Get emergency object, if any - this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this); + //// Get emergency object, if any + //this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this); - Debug.Console(2, this, "Emergency Config evaluated."); + //Debug.Console(2, this, "Emergency Config evaluated."); - VideoCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate(); - VideoCodec.IsReadyChange += (o, a) => { this.SetCodecExternalSources(); SetCodecBranding(); }; + //VideoCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate(); + //VideoCodec.IsReadyChange += (o, a) => { this.SetCodecExternalSources(); SetCodecBranding(); }; - if (AudioCodec != null) - AudioCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate(); + //if (AudioCodec != null) + // AudioCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate(); - IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue); - VideoCodec.SharingContentIsOnFeedback.OutputChange += (o, a) => this.IsSharingFeedback.FireUpdate(); + //IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue); + //VideoCodec.SharingContentIsOnFeedback.OutputChange += (o, a) => this.IsSharingFeedback.FireUpdate(); - // link privacy to VC (for now?) - PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue); - VideoCodec.PrivacyModeIsOnFeedback.OutputChange += (o, a) => this.PrivacyModeIsOnFeedback.FireUpdate(); + //// link privacy to VC (for now?) + //PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue); + //VideoCodec.PrivacyModeIsOnFeedback.OutputChange += (o, a) => this.PrivacyModeIsOnFeedback.FireUpdate(); - CallTypeFeedback = new IntFeedback(() => 0); + //CallTypeFeedback = new IntFeedback(() => 0); SetSourceListKey(); - EnablePowerOnToLastSource = true; + //EnablePowerOnToLastSource = true; } catch (Exception e) { @@ -297,7 +297,9 @@ namespace PepperDash.Essentials { //DefaultDisplay = DeviceManager.GetDeviceForKey(PropertiesConfig.DefaultDisplayKey) as IRoutingSinkWithSwitching; - var destinationList = ConfigReader.ConfigObject.DestinationLists[PropertiesConfig.DestinationListKey]; + var destinationList = ConfigReader.ConfigObject.DestinationLists[PropertiesConfig.DestinationListKey]; + + Displays.Clear(); foreach (var destination in destinationList) { @@ -314,37 +316,54 @@ namespace PepperDash.Essentials // Link power, warming, cooling to display var dispTwoWay = display as IHasPowerControlWithFeedback; if (dispTwoWay != null) - { - dispTwoWay.PowerIsOnFeedback.OutputChange += (o, a) => - { - if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue) - { - //if (!dispTwoWay.PowerIsOnFeedback.BoolValue) - // CurrentSourceInfo = null; - OnFeedback.FireUpdate(); - } - if (dispTwoWay.PowerIsOnFeedback.BoolValue) - { - SetDefaultLevels(); - } - }; - } - - display.IsWarmingUpFeedback.OutputChange += (o, a) => - { - IsWarmingUpFeedback.FireUpdate(); - if (!IsWarmingUpFeedback.BoolValue) - (CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume); - }; - display.IsCoolingDownFeedback.OutputChange += (o, a) => - { - IsCoolingDownFeedback.FireUpdate(); - }; + { + dispTwoWay.PowerIsOnFeedback.OutputChange -= PowerIsOnFeedback_OutputChange; + dispTwoWay.PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange; + + if (dispTwoWay.PowerIsOnFeedback.BoolValue) + { + SetDefaultLevels(); + } + } + + display.IsWarmingUpFeedback.OutputChange -= IsWarmingUpFeedback_OutputChange; + display.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange; + + display.IsCoolingDownFeedback.OutputChange -= IsCoolingDownFeedback_OutputChange; + display.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange; } } + } + + void IsCoolingDownFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + IsCoolingDownFeedback.FireUpdate(); + } + + void IsWarmingUpFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + IsWarmingUpFeedback.FireUpdate(); + if (!IsWarmingUpFeedback.BoolValue) + (CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume); + } + + void PowerIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + var dispTwoWay = sender as IHasPowerControlWithFeedback; + + if (dispTwoWay != null && dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue) + { + //if (!dispTwoWay.PowerIsOnFeedback.BoolValue) + // CurrentSourceInfo = null; + OnFeedback.FireUpdate(); + } } + + + + private void SetSourceListKey() { if (!string.IsNullOrEmpty(PropertiesConfig.SourceListKey)) @@ -367,26 +386,143 @@ namespace PepperDash.Essentials PropertiesConfig = newPropertiesConfig; ConfigWriter.UpdateRoomConfig(config); + } + + public override bool Deactivate() + { + // Stop listining to this event when room deactivated + VideoCodec.IsReadyChange -= VideoCodec_IsReadyChange; + + return base.Deactivate(); } public override bool CustomActivate() - { - // Add Occupancy object from config - if (PropertiesConfig.Occupancy != null) - { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Setting Occupancy Provider for room"); - this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as - IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes); - } - - this.LogoUrlLightBkgnd = PropertiesConfig.LogoLight.GetLogoUrlLight(); - this.LogoUrlDarkBkgnd = PropertiesConfig.LogoDark.GetLogoUrlDark(); - - this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem; - this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100); - + { + try + { + if (DefaultAudioDevice is IBasicVolumeControls) + DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls; + else if (DefaultAudioDevice is IHasVolumeDevice) + DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice; + CurrentVolumeControls = DefaultVolumeControls; + + + // Combines call feedback from both codecs if available + InCallFeedback = new BoolFeedback(() => + { + bool inAudioCall = false; + bool inVideoCall = false; + + if (AudioCodec != null) + inAudioCall = AudioCodec.IsInCall; + + if (VideoCodec != null) + inVideoCall = VideoCodec.IsInCall; + + if (inAudioCall || inVideoCall) + return true; + else + return false; + }); + + SetupDisplays(); + + // Get Microphone Privacy object, if any MUST HAPPEN AFTER setting InCallFeedback + this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this); + + Debug.Console(2, this, "Microphone Privacy Config evaluated."); + + // Get emergency object, if any + this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this); + + Debug.Console(2, this, "Emergency Config evaluated."); + + if (AudioCodec != null) + { + AudioCodec.CallStatusChange -= AudioCodec_CallStatusChange; + AudioCodec.CallStatusChange += AudioCodec_CallStatusChange; + } + + VideoCodec.CallStatusChange -= VideoCodec_CallStatusChange; + VideoCodec.CallStatusChange += VideoCodec_CallStatusChange; + + VideoCodec.IsReadyChange -= VideoCodec_IsReadyChange; + VideoCodec.IsReadyChange += VideoCodec_IsReadyChange; + + VideoCodec.SharingContentIsOnFeedback.OutputChange -= SharingContentIsOnFeedback_OutputChange; + VideoCodec.SharingContentIsOnFeedback.OutputChange += SharingContentIsOnFeedback_OutputChange; + + + IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue); + + // link privacy to VC (for now?) + PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue); + + VideoCodec.PrivacyModeIsOnFeedback.OutputChange -= PrivacyModeIsOnFeedback_OutputChange; + VideoCodec.PrivacyModeIsOnFeedback.OutputChange += PrivacyModeIsOnFeedback_OutputChange; + + CallTypeFeedback = new IntFeedback(() => 0); + + SetSourceListKey(); + + EnablePowerOnToLastSource = true; + + + // Add Occupancy object from config + if (PropertiesConfig.Occupancy != null) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Setting Occupancy Provider for room"); + this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as + IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes); + } + + this.LogoUrlLightBkgnd = PropertiesConfig.LogoLight.GetLogoUrlLight(); + this.LogoUrlDarkBkgnd = PropertiesConfig.LogoDark.GetLogoUrlDark(); + + this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem; + this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100); + + } + catch (Exception e) + { + Debug.Console(0, this, "Error Activiating Room: {0}", e); + } + return base.CustomActivate(); - } + } + + void AudioCodec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e) + { + InCallFeedback.FireUpdate(); + } + + void PrivacyModeIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + PrivacyModeIsOnFeedback.FireUpdate(); + } + + void VideoCodec_IsReadyChange(object sender, EventArgs e) + { + SetUpVideoCodec(); + } + + void SetUpVideoCodec() + { + SetCodecExternalSources(); + SetCodecBranding(); + } + + void VideoCodec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e) + { + InCallFeedback.FireUpdate(); + } + + void SharingContentIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + IsSharingFeedback.FireUpdate(); + } + + /// /// diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index d04de3cc..457e4ae2 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -19,6 +19,8 @@ namespace PepperDash.Essentials { public class EssentialsHuddleVtc1Room : EssentialsRoomBase, IEssentialsHuddleVtc1Room { + private IEssentialsRoomCombiner _roomCombiner; + private bool _codecExternalSourceChange; public event EventHandler CurrentVolumeDeviceChange; public event SourceInfoChangeHandler CurrentSourceChange; @@ -234,7 +236,7 @@ namespace PepperDash.Essentials throw new ArgumentNullException("DefaultAudioDevice cannot be null"); } - InitializeRoom(); + Initialize(); } catch (Exception e) { @@ -242,109 +244,6 @@ namespace PepperDash.Essentials } } - void InitializeRoom() - { - try - { - if (DefaultAudioDevice is IBasicVolumeControls) - DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls; - else if (DefaultAudioDevice is IHasVolumeDevice) - DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice; - CurrentVolumeControls = DefaultVolumeControls; - - - // Combines call feedback from both codecs if available - InCallFeedback = new BoolFeedback(() => - { - bool inAudioCall = false; - bool inVideoCall = false; - - if (AudioCodec != null) - inAudioCall = AudioCodec.IsInCall; - - if (VideoCodec != null) - inVideoCall = VideoCodec.IsInCall; - - if (inAudioCall || inVideoCall) - return true; - else - return false; - }); - - var disp = DefaultDisplay as DisplayBase; - if (disp != null) - { - // Link power, warming, cooling to display - var dispTwoWay = disp as IHasPowerControlWithFeedback; - if (dispTwoWay != null) - { - dispTwoWay.PowerIsOnFeedback.OutputChange += (o, a) => - { - if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue) - { - if (!dispTwoWay.PowerIsOnFeedback.BoolValue) - CurrentSourceInfo = null; - OnFeedback.FireUpdate(); - } - if (dispTwoWay.PowerIsOnFeedback.BoolValue) - { - SetDefaultLevels(); - } - }; - } - - disp.IsWarmingUpFeedback.OutputChange += (o, a) => - { - IsWarmingUpFeedback.FireUpdate(); - if (!IsWarmingUpFeedback.BoolValue) - (CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume); - }; - disp.IsCoolingDownFeedback.OutputChange += (o, a) => - { - IsCoolingDownFeedback.FireUpdate(); - }; - - } - - - - // Get Microphone Privacy object, if any MUST HAPPEN AFTER setting InCallFeedback - this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this); - - Debug.Console(2, this, "Microphone Privacy Config evaluated."); - - // Get emergency object, if any - this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this); - - Debug.Console(2, this, "Emergency Config evaluated."); - - - VideoCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate(); - VideoCodec.IsReadyChange += (o, a) => { this.SetCodecExternalSources(); SetCodecBranding(); }; - - if (AudioCodec != null) - AudioCodec.CallStatusChange += (o, a) => this.InCallFeedback.FireUpdate(); - - IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue); - VideoCodec.SharingContentIsOnFeedback.OutputChange += (o, a) => this.IsSharingFeedback.FireUpdate(); - - // link privacy to VC (for now?) - PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue); - VideoCodec.PrivacyModeIsOnFeedback.OutputChange += (o, a) => this.PrivacyModeIsOnFeedback.FireUpdate(); - - CallTypeFeedback = new IntFeedback(() => 0); - - SetupEnvironmentalControlDevices(); - - SetSourceListKey(); - - EnablePowerOnToLastSource = true; - } - catch (Exception e) - { - Debug.Console(0, this, "Error Initializing Room: {0}", e); - } - } private void SetupEnvironmentalControlDevices() { @@ -352,6 +251,8 @@ namespace PepperDash.Essentials { if (PropertiesConfig.Environment.Enabled) { + EnvironmentalControlDevices.Clear(); + foreach (var d in PropertiesConfig.Environment.DeviceKeys) { var envDevice = DeviceManager.GetDeviceForKey(d) as EssentialsDevice; @@ -386,25 +287,190 @@ namespace PepperDash.Essentials ConfigWriter.UpdateRoomConfig(config); } + public override bool Deactivate() + { + + // Stop listining to this event when room deactivated + VideoCodec.IsReadyChange -= VideoCodec_IsReadyChange; + + return base.Deactivate(); + } + public override bool CustomActivate() { - // Add Occupancy object from config - if (PropertiesConfig.Occupancy != null) + try { - Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Setting Occupancy Provider for room"); - this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as - IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes); + if (DefaultAudioDevice is IBasicVolumeControls) + DefaultVolumeControls = DefaultAudioDevice as IBasicVolumeControls; + else if (DefaultAudioDevice is IHasVolumeDevice) + DefaultVolumeControls = (DefaultAudioDevice as IHasVolumeDevice).VolumeDevice; + CurrentVolumeControls = DefaultVolumeControls; + + + // Combines call feedback from both codecs if available + InCallFeedback = new BoolFeedback(() => + { + bool inAudioCall = false; + bool inVideoCall = false; + + if (AudioCodec != null) + inAudioCall = AudioCodec.IsInCall; + + if (VideoCodec != null) + inVideoCall = VideoCodec.IsInCall; + + if (inAudioCall || inVideoCall) + return true; + else + return false; + }); + + var disp = DefaultDisplay as DisplayBase; + if (disp != null) + { + // Link power, warming, cooling to display + var dispTwoWay = disp as IHasPowerControlWithFeedback; + if (dispTwoWay != null) + { + dispTwoWay.PowerIsOnFeedback.OutputChange -= PowerIsOnFeedback_OutputChange; + dispTwoWay.PowerIsOnFeedback.OutputChange += PowerIsOnFeedback_OutputChange; + } + + disp.IsWarmingUpFeedback.OutputChange -= IsWarmingUpFeedback_OutputChange; + disp.IsWarmingUpFeedback.OutputChange += IsWarmingUpFeedback_OutputChange; + + disp.IsCoolingDownFeedback.OutputChange -= IsCoolingDownFeedback_OutputChange; + disp.IsCoolingDownFeedback.OutputChange += IsCoolingDownFeedback_OutputChange; + } + + + + // Get Microphone Privacy object, if any MUST HAPPEN AFTER setting InCallFeedback + this.MicrophonePrivacy = EssentialsRoomConfigHelper.GetMicrophonePrivacy(PropertiesConfig, this); + + Debug.Console(2, this, "Microphone Privacy Config evaluated."); + + // Get emergency object, if any + this.Emergency = EssentialsRoomConfigHelper.GetEmergency(PropertiesConfig, this); + + Debug.Console(2, this, "Emergency Config evaluated."); + + if (AudioCodec != null) + { + AudioCodec.CallStatusChange -= AudioCodec_CallStatusChange; + AudioCodec.CallStatusChange += AudioCodec_CallStatusChange; + } + + VideoCodec.CallStatusChange -= VideoCodec_CallStatusChange; + VideoCodec.CallStatusChange += VideoCodec_CallStatusChange; + + VideoCodec.IsReadyChange -= VideoCodec_IsReadyChange; + VideoCodec.IsReadyChange += VideoCodec_IsReadyChange; + + VideoCodec.SharingContentIsOnFeedback.OutputChange -= SharingContentIsOnFeedback_OutputChange; + VideoCodec.SharingContentIsOnFeedback.OutputChange += SharingContentIsOnFeedback_OutputChange; + + + IsSharingFeedback = new BoolFeedback(() => VideoCodec.SharingContentIsOnFeedback.BoolValue); + + // link privacy to VC (for now?) + PrivacyModeIsOnFeedback = new BoolFeedback(() => VideoCodec.PrivacyModeIsOnFeedback.BoolValue); + + VideoCodec.PrivacyModeIsOnFeedback.OutputChange -= PrivacyModeIsOnFeedback_OutputChange; + VideoCodec.PrivacyModeIsOnFeedback.OutputChange += PrivacyModeIsOnFeedback_OutputChange; + + CallTypeFeedback = new IntFeedback(() => 0); + + SetupEnvironmentalControlDevices(); + + SetSourceListKey(); + + EnablePowerOnToLastSource = true; + + + // Add Occupancy object from config + if (PropertiesConfig.Occupancy != null) + { + Debug.Console(0, this, Debug.ErrorLogLevel.Notice, "Setting Occupancy Provider for room"); + this.SetRoomOccupancy(DeviceManager.GetDeviceForKey(PropertiesConfig.Occupancy.DeviceKey) as + IOccupancyStatusProvider, PropertiesConfig.Occupancy.TimeoutMinutes); + } + + this.LogoUrlLightBkgnd = PropertiesConfig.LogoLight.GetLogoUrlLight(); + this.LogoUrlDarkBkgnd = PropertiesConfig.LogoDark.GetLogoUrlDark(); + + this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem; + this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100); + } + catch (Exception e) + { + Debug.Console(0, this, "Error Activiating Room: {0}", e); } - - this.LogoUrlLightBkgnd = PropertiesConfig.LogoLight.GetLogoUrlLight(); - this.LogoUrlDarkBkgnd = PropertiesConfig.LogoDark.GetLogoUrlDark(); - - this.DefaultSourceItem = PropertiesConfig.DefaultSourceItem; - this.DefaultVolume = (ushort)(PropertiesConfig.Volumes.Master.Level * 65535 / 100); return base.CustomActivate(); } + void PrivacyModeIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + PrivacyModeIsOnFeedback.FireUpdate(); + } + + void SharingContentIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + IsSharingFeedback.FireUpdate(); + } + + void AudioCodec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e) + { + InCallFeedback.FireUpdate(); + } + + void VideoCodec_IsReadyChange(object sender, EventArgs e) + { + SetUpVideoCodec(); + } + + void SetUpVideoCodec() + { + SetCodecExternalSources(); + SetCodecBranding(); + } + + void VideoCodec_CallStatusChange(object sender, CodecCallStatusItemChangeEventArgs e) + { + InCallFeedback.FireUpdate(); + } + + void IsCoolingDownFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + IsCoolingDownFeedback.FireUpdate(); + } + + void IsWarmingUpFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + IsWarmingUpFeedback.FireUpdate(); + if (!IsWarmingUpFeedback.BoolValue) + (CurrentVolumeControls as IBasicVolumeWithFeedback).SetVolume(DefaultVolume); + + } + + void PowerIsOnFeedback_OutputChange(object sender, FeedbackEventArgs e) + { + var dispTwoWay = DefaultDisplay as IHasPowerControlWithFeedback; + + if (dispTwoWay.PowerIsOnFeedback.BoolValue != OnFeedback.BoolValue) + { + if (!dispTwoWay.PowerIsOnFeedback.BoolValue) + CurrentSourceInfo = null; + OnFeedback.FireUpdate(); + } + if (dispTwoWay.PowerIsOnFeedback.BoolValue) + { + SetDefaultLevels(); + } + + } + /// From f73d6994b8d6d869037d0b6ef50794582640a04b Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 19 Jul 2023 16:22:20 -0600 Subject: [PATCH 12/50] Additional updates to allow occupancy sensor to be cleared when room not active --- .../Room/Types/EssentialsCombinedHuddleVtc1Room.cs | 7 +++++++ .../Room/Types/EssentialsHuddleVtc1Room.cs | 8 +++++++- .../PepperDashEssentialsBase/Room/EssentialsRoomBase.cs | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs index 3ed0946d..8ffd63e5 100644 --- a/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs @@ -393,6 +393,11 @@ namespace PepperDash.Essentials // Stop listining to this event when room deactivated VideoCodec.IsReadyChange -= VideoCodec_IsReadyChange; + // Clear occupancy + RoomOccupancy = null; + + Debug.Console(0, this, "Room '{0}' Deactivated", Name); + return base.Deactivate(); } @@ -488,6 +493,8 @@ namespace PepperDash.Essentials Debug.Console(0, this, "Error Activiating Room: {0}", e); } + + Debug.Console(0, this, "Room '{0}' Activated", Name); return base.CustomActivate(); } diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index 457e4ae2..3df86b9a 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -293,6 +293,11 @@ namespace PepperDash.Essentials // Stop listining to this event when room deactivated VideoCodec.IsReadyChange -= VideoCodec_IsReadyChange; + // Clear occupancy + RoomOccupancy = null; + + Debug.Console(0, this, "Room '{0}' Deactivated", Name); + return base.Deactivate(); } @@ -406,7 +411,8 @@ namespace PepperDash.Essentials { Debug.Console(0, this, "Error Activiating Room: {0}", e); } - + + Debug.Console(0, this, "Room '{0}' Activated", Name); return base.CustomActivate(); } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs index f5e3dee8..0c7e0de0 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/EssentialsRoomBase.cs @@ -35,7 +35,7 @@ namespace PepperDash.Essentials.Core public BoolFeedback IsWarmingUpFeedback { get; private set; } public BoolFeedback IsCoolingDownFeedback { get; private set; } - public IOccupancyStatusProvider RoomOccupancy { get; private set; } + public IOccupancyStatusProvider RoomOccupancy { get; protected set; } public bool OccupancyStatusProviderIsRemote { get; private set; } From c46409dc3ff52235d09fa8455c87ab7f772eabd6 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Wed, 19 Jul 2023 16:55:53 -0600 Subject: [PATCH 13/50] Minor adjustments and added debug messages --- .../Room/Types/EssentialsCombinedHuddleVtc1Room.cs | 10 ++++++---- .../Room/Types/EssentialsHuddleVtc1Room.cs | 4 +++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs index 8ffd63e5..cbe1b579 100644 --- a/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsCombinedHuddleVtc1Room.cs @@ -373,9 +373,9 @@ namespace PepperDash.Essentials else { SetSourceListKey(Key); - } - - SetCodecExternalSources(); + } + + SetUpVideoCodec(); } protected override void CustomSetConfig(DeviceConfig config) @@ -922,7 +922,9 @@ namespace PepperDash.Essentials videoCodecWithExternalSwitching.AddExternalSource(codecInputConnectorName, kvp.Key, srcConfig.PreferredName, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceType.desktop); videoCodecWithExternalSwitching.SetExternalSourceState(kvp.Key, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceMode.Ready); } - } + } + + Debug.Console(1, this, "Successfully set up codec external sources for room: {0}", Name); } catch (Exception e) { diff --git a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs index 3df86b9a..2aae2f75 100644 --- a/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/EssentialsHuddleVtc1Room.cs @@ -274,7 +274,7 @@ namespace PepperDash.Essentials SetSourceListKey(Key); } - SetCodecExternalSources(); + SetUpVideoCodec(); } protected override void CustomSetConfig(DeviceConfig config) @@ -904,6 +904,8 @@ namespace PepperDash.Essentials videoCodecWithExternalSwitching.SetExternalSourceState(kvp.Key, PepperDash.Essentials.Devices.Common.VideoCodec.Cisco.eExternalSourceMode.Ready); } } + Debug.Console(1, this, "Successfully set up codec external sources for room: {0}", Name); + } catch (Exception e) { From 62f175c24a19785806e4df26960c8b6348790db2 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 15 Aug 2023 09:38:34 -0600 Subject: [PATCH 14/50] chore: trigger build with new Crestron DBs From b5bf87c634e65a92da041ca8ad9dbb11fefe3147 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 15 Aug 2023 10:02:42 -0600 Subject: [PATCH 15/50] build: update PD Core version --- packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages.config b/packages.config index 35ed241d..4b9c93be 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + From daf3f321bd49dc444aafc78c2b78e96e3ec126d0 Mon Sep 17 00:00:00 2001 From: Nick Genovese Date: Wed, 16 Aug 2023 10:25:26 -0400 Subject: [PATCH 16/50] fix: bumped core version - bumped core to 1.3.1-hotfix-337 for ssh fixe --- packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages.config b/packages.config index 4b9c93be..bf1e451d 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + From da4070bad0c9190b7857ce0cd25ad9d08e7c4b59 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 21 Aug 2023 15:23:33 -0600 Subject: [PATCH 17/50] docs: correct PDU Online join name for printing --- .../PepperDashEssentialsBase/Bridges/JoinMaps/PduJoinMapBase.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/PduJoinMapBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/PduJoinMapBase.cs index 2ac56ff1..0c2e9ed9 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/PduJoinMapBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/PduJoinMapBase.cs @@ -10,7 +10,7 @@ namespace PepperDash.Essentials.Core.Bridges [JoinName("Online")] public JoinDataComplete Online = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, - new JoinMetadata { Description = "PDU Name", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); + new JoinMetadata { Description = "Online", JoinCapabilities = eJoinCapabilities.ToSIMPL, JoinType = eJoinType.Digital }); [JoinName("OutletCount")] public JoinDataComplete OutletCount = new JoinDataComplete(new JoinData { JoinNumber = 1, JoinSpan = 1 }, From 4d2ce83e7503dcdc1f82b6b10012f2b8abf3c84f Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 21 Aug 2023 15:27:25 -0600 Subject: [PATCH 18/50] fix: rework setting custom join data The previous method was causing an Exception to be thrown if a join didn't exist in the default join map for a device. This exception would prevent other devices from linking to a bridge correctly. This method now allows for join names to not be matched and the method will keep going. --- .../PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs index 60aa6275..12df7f14 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/JoinMaps/JoinMapBase.cs @@ -356,16 +356,18 @@ namespace PepperDash.Essentials.Core { foreach (var customJoinData in joinData) { - var join = Joins[customJoinData.Key]; + JoinDataComplete join; + + if (!Joins.TryGetValue(customJoinData.Key, out join)) + { + Debug.Console(2, "No matching key found in join map for: '{0}'", customJoinData.Key); + continue; + } if (join != null) { join.SetCustomJoinData(customJoinData.Value); } - else - { - Debug.Console(2, "No matching key found in join map for: '{0}'", customJoinData.Key); - } } PrintJoinMapInfo(); From 4c0fb6311bc21319b4ee9595c92075ebf35d6ce2 Mon Sep 17 00:00:00 2001 From: Nick Genovese Date: Thu, 24 Aug 2023 08:15:31 -0400 Subject: [PATCH 19/50] fix: set core version to 1.3.1 --- packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages.config b/packages.config index bf1e451d..761b11cb 100644 --- a/packages.config +++ b/packages.config @@ -1,3 +1,3 @@ - + From 93134cae5cdbe59b05ff7fe15714e2e16fbbc123 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Mon, 28 Aug 2023 15:20:57 -0600 Subject: [PATCH 20/50] fix: add `Dialable` property to Meeting class Previously, the meeting class was determining Dialable based on a meeting ID being "0". This is a Zoom-specific thing, but it has recently become a thing for Cisco codecs to have meetings that aren't necessarily dialable. Adding this property to the `Meeting` class allows the specific codec type to set it correctly based on that codec's needs. --- .../Essentials Devices Common/Codec/iHasScheduleAwareness.cs | 4 ++++ .../VideoCodec/CiscoCodec/BookingsDataClasses.cs | 2 ++ .../Essentials Devices Common/VideoCodec/VideoCodecBase.cs | 2 +- .../VideoCodec/ZoomRoom/ResponseObjects.cs | 2 ++ 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs index 9169fd7c..c4473c67 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/Codec/iHasScheduleAwareness.cs @@ -216,6 +216,10 @@ namespace PepperDash.Essentials.Devices.Common.Codec return joinable; } } + + [JsonProperty("dialable")] + public bool Dialable { get; set; } + //public string ConferenceNumberToDial { get; set; } [JsonProperty("conferencePassword")] public string ConferencePassword { get; set; } diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/BookingsDataClasses.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/BookingsDataClasses.cs index 59823bb9..05456ad4 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/BookingsDataClasses.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/CiscoCodec/BookingsDataClasses.cs @@ -348,6 +348,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec if (b.DialInfo.ConnectMode.Value.ToLower() == "obtp" || b.DialInfo.ConnectMode.Value.ToLower() == "manual") meeting.IsOneButtonToPushMeeting = true; + meeting.Dialable = b.DialInfo.Calls.Call.Count > 0; + if (b.DialInfo.Calls.Call != null) { foreach (Call c in b.DialInfo.Calls.Call) diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs index c0048a68..187cc855 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/VideoCodecBase.cs @@ -940,7 +940,7 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec //digitals tokenArray[digitalIndex] = new XSigDigitalToken(digitalIndex + 1, meeting.Joinable); - tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, meeting.Id != "0"); + tokenArray[digitalIndex + 1] = new XSigDigitalToken(digitalIndex + 2, meeting.Dialable); //serials tokenArray[stringIndex] = new XSigSerialToken(stringIndex + 1, meeting.Organizer); diff --git a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs index 79a5395d..09069146 100644 --- a/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs +++ b/essentials-framework/Essentials Devices Common/Essentials Devices Common/VideoCodec/ZoomRoom/ResponseObjects.cs @@ -1510,6 +1510,8 @@ namespace PepperDash.Essentials.Devices.Common.VideoCodec.ZoomRoom meeting.Privacy = b.IsPrivate ? eMeetingPrivacy.Private : eMeetingPrivacy.Public; + meeting.Dialable = meeting.Id != "0"; + // No meeting.Calls data exists for Zoom Rooms. Leaving out for now. var now = DateTime.Now; if (meeting.StartTime < now && meeting.EndTime < now) From 759fb1d72949bd88e76cc071249740eb6399327e Mon Sep 17 00:00:00 2001 From: jdevito Date: Wed, 6 Sep 2023 11:22:19 -0500 Subject: [PATCH 21/50] feature: adds support for HdSpXxx switchers WIP: added support for HD-PS401, HD-PS402, HD-PS621 and HD-PS622, pending testing with device. --- .../JoinMaps/HdPsXxxControllerJoinMap.cs | 190 ++++++ .../PepperDash_Essentials_Core.csproj | 1 + .../Chassis/HdPsXxxController.cs | 637 ++++++++++++++++++ .../Config/HdPsXxxPropertiesConfig.cs | 18 + .../PepperDash_Essentials_DM.csproj | 2 + 5 files changed, 848 insertions(+) create mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/HdPsXxxControllerJoinMap.cs create mode 100644 essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs create mode 100644 essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/HdPsXxxControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/HdPsXxxControllerJoinMap.cs new file mode 100644 index 00000000..3f2901c9 --- /dev/null +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/HdPsXxxControllerJoinMap.cs @@ -0,0 +1,190 @@ +using System; +using PepperDash.Essentials.Core; + +namespace PepperDash_Essentials_Core.Bridges +{ + public class HdPsXxxControllerJoinMap : JoinMapBaseAdvanced + { + + #region Digital + + [JoinName("EnableAutoRoute")] + public JoinDataComplete EnableAutoRoute = new JoinDataComplete( + new JoinData + { + JoinNumber = 1, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Enable Automatic Routing on Xx1 Switchers", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + + [JoinName("InputSync")] + public JoinDataComplete InputSync = new JoinDataComplete( + new JoinData + { + JoinNumber = 2, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "Device Input Sync", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + + [JoinName("EnableInputHdcp")] + public JoinDataComplete EnableInputHdcp = new JoinDataComplete( + new JoinData + { + JoinNumber = 11, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "Device Enable Input Hdcp", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + + [JoinName("DisableInputHdcp")] + public JoinDataComplete DisableInputHdcp = new JoinDataComplete( + new JoinData + { + JoinNumber = 21, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "Device Disnable Input Hdcp", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Digital + }); + + + [JoinName("IsOnline")] + public JoinDataComplete IsOnline = new JoinDataComplete( + new JoinData + { + JoinNumber = 30, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Device Onlne", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Digital + }); + + #endregion + + + #region Analog + + [JoinName("OutputRoute")] + public JoinDataComplete OutputRoute = new JoinDataComplete( + new JoinData + { + JoinNumber = 11, + JoinSpan = 2 + }, + new JoinMetadata + { + Description = "Device Output Route Set/Get", + JoinCapabilities = eJoinCapabilities.ToFromSIMPL, + JoinType = eJoinType.Analog + }); + + #endregion + + + #region Serial + + [JoinName("Name")] + public JoinDataComplete Name = new JoinDataComplete( + new JoinData + { + JoinNumber = 1, + JoinSpan = 1 + }, + new JoinMetadata + { + Description = "Device Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + + [JoinName("InputName")] + public JoinDataComplete InputName = new JoinDataComplete( + new JoinData + { + JoinNumber = 2, + JoinSpan = 8 + }, + new JoinMetadata + { + Description = "Device Input Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + + [JoinName("OutputName")] + public JoinDataComplete OutputName = new JoinDataComplete( + new JoinData + { + JoinNumber = 11, + JoinSpan = 2 + }, + new JoinMetadata + { + Description = "Device Output Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + + [JoinName("OutputRoutedName")] + public JoinDataComplete OutputRoutedName = new JoinDataComplete( + new JoinData + { + JoinNumber = 16, + JoinSpan = 2 + }, + new JoinMetadata + { + Description = "Device Output Route Name", + JoinCapabilities = eJoinCapabilities.ToSIMPL, + JoinType = eJoinType.Serial + }); + + + #endregion + + /// + /// Constructor to use when instantiating this join map without inheriting from it + /// + /// Join this join map will start at + public HdPsXxxControllerJoinMap(uint joinStart) + : this(joinStart, typeof(HdPsXxxControllerJoinMap)) + { + } + + /// + /// Constructor to use when extending this Join map + /// + /// Join this join map will start at + /// Type of the child join map + protected HdPsXxxControllerJoinMap(uint joinStart, Type type) + : base(joinStart, type) + { + } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 75d4626d..0d9aa9bc 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -127,6 +127,7 @@ + diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs new file mode 100644 index 00000000..78da7a7b --- /dev/null +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -0,0 +1,637 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Crestron.SimplSharp; +using Crestron.SimplSharpPro; +using Crestron.SimplSharpPro.DeviceSupport; +using Crestron.SimplSharpPro.DM; +using Newtonsoft.Json; +using PepperDash.Core; +using PepperDash.Essentials.Core; +using PepperDash.Essentials.Core.Bridges; +using PepperDash.Essentials.Core.Config; +using PepperDash_Essentials_Core.Bridges; +using PepperDash_Essentials_DM.Config; + +namespace PepperDash_Essentials_DM.Chassis +{ + [Description("Wrapper class for all HdPsXxx switchers")] + public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IHasFeedback + { + + private readonly HdPsXxx _chassis; + private readonly HdPs401 _chassis401; + private readonly HdPs621 _chassis621; + + public RoutingPortCollection InputPorts { get; private set; } + public RoutingPortCollection OutputPorts { get; private set; } + + public Dictionary InputNames { get; set; } + public Dictionary OutputNames { get; set; } + + public FeedbackCollection InputNameFeedbacks { get; private set; } + public FeedbackCollection InputHdcpEnableFeedback { get; private set; } + + public FeedbackCollection OutputNameFeedbacks { get; private set; } + public FeedbackCollection OutputRouteNameFeedback { get; private set; } + + public FeedbackCollection VideoInputSyncFeedbacks { get; private set; } + public FeedbackCollection VideoOutputRouteFeedbacks { get; private set; } + + public StringFeedback DeviceNameFeedback { get; private set; } + public BoolFeedback AutoRouteFeedback { get; private set; } + + public event EventHandler NumericSwitchChange; + + /// + /// Constructor + /// + /// + /// + /// HdPs401 device instance + /// + public HdPsXxxController(string key, string name, HdPsXxx chassis, HdPsXxxPropertiesConfig props) + : base(key, name) + { + _chassis = chassis; + Name = name; + + if (props == null) + { + Debug.Console(1, this, "HdPsXxxController properties are null, failed to build device"); + return; + } + + InputPorts = new RoutingPortCollection(); + InputNames = new Dictionary(); + InputNameFeedbacks = new FeedbackCollection(); + InputHdcpEnableFeedback = new FeedbackCollection(); + + OutputPorts = new RoutingPortCollection(); + OutputNames = new Dictionary(); + OutputNameFeedbacks = new FeedbackCollection(); + OutputRouteNameFeedback = new FeedbackCollection(); + + VideoInputSyncFeedbacks = new FeedbackCollection(); + VideoOutputRouteFeedbacks = new FeedbackCollection(); + + if (_chassis.NumberOfOutputs == 1) + { + if (_chassis is HdPs401) + _chassis401 = _chassis as HdPs401; + if (_chassis is HdPs621) + _chassis621 = _chassis as HdPs621; + + AutoRouteFeedback = new BoolFeedback(() => _chassis401.PriorityRouteOnFeedback.BoolValue); + } + + SetupInputs(props.Inputs); + SetupOutputs(props.Outputs); + + AddPostActivationAction(AddFeedbackCollecitons); + } + + // input setup + private void SetupInputs(Dictionary dict) + { + InputNames = dict; + + for (uint i = 1; i <= _chassis.NumberOfInputs; i++) + { + var index = i; + var name = string.IsNullOrEmpty(InputNames[index]) ? string.Format("Input {0}", index) : InputNames[index]; + var input = _chassis.Inputs[index]; + var hdmiInput = _chassis.HdmiInputs[index]; + var dmLiteInput = _chassis.DmLiteInputs[index]; + + InputNameFeedbacks.Add(new StringFeedback(name, () => InputNames[index])); + + // TODO [ ] verify which input type is needed + input.Name.StringValue = name; + hdmiInput.Name.StringValue = name; + dmLiteInput.Name.StringValue = name; + + var port = new RoutingInputPort(name, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) + { + FeedbackMatchObject = input + }; + InputPorts.Add(port); + + InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => hdmiInput.InputPort.HdcpSupportOnFeedback.BoolValue)); + + VideoInputSyncFeedbacks.Add(new BoolFeedback(name, () => input.VideoDetectedFeedback.BoolValue)); + } + + _chassis.DMInputChange += _chassis_InputChange; + } + + // output setup + private void SetupOutputs(Dictionary dict) + { + OutputNames = dict; + + for (uint i = 1; i <= _chassis.NumberOfOutputs; i++) + { + var index = i; + var name = string.IsNullOrEmpty(OutputNames[index]) ? string.Format("Output {0}", index) : OutputNames[index]; + var output = _chassis.Outputs[index]; + var hdmiDmLiteOutput = _chassis.HdmiDmLiteOutputs[index]; + + OutputNameFeedbacks.Add(new StringFeedback(name, () => OutputNames[index])); + + // TODO [ ] verify which output type is needed + output.Name.StringValue = name; + hdmiDmLiteOutput.Name.StringValue = name; + + var port = new RoutingOutputPort(name, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, output, this) + { + FeedbackMatchObject = output + }; + OutputPorts.Add(port); + + OutputRouteNameFeedback.Add(new StringFeedback(name, () => output.VideoOutFeedback.NameFeedback.StringValue)); + + VideoOutputRouteFeedbacks.Add(new IntFeedback(name, () => output.VideoOutFeedback == null ? 0 : (int)output.VideoOutFeedback.Number)); + } + + _chassis.DMOutputChange += _chassis_OutputChange; + } + + + #region BridgeLinking + + /// + /// Link device to API + /// + /// + /// + /// + /// + public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) + { + var joinMap = new HdPsXxxControllerJoinMap(joinStart); + + if (bridge != null) + { + bridge.AddJoinMap(Key, joinMap); + } + else + { + Debug.Console(0, this, "Please update config to use 'eiscApiAdvanced' to get all join map features for this device"); + } + + IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); + DeviceNameFeedback.LinkInputSig(trilist.StringInput[joinMap.Name.JoinNumber]); + + _chassis.OnlineStatusChange += _chassis_OnlineStatusChange; + + if (_chassis401 != null) LinkChassis401ToApi(trilist, joinMap); + + if (_chassis621 != null) LinkChassis621ToApi(trilist, joinMap); + + LinkChassisInputsToApi(trilist, joinMap); + LinkChassisOutputsToApi(trilist, joinMap); + + trilist.OnlineStatusChange += (sender, args) => + { + if (!args.DeviceOnLine) return; + }; + } + + + // links inputs to API + private void LinkChassisInputsToApi(BasicTriList trilist, HdPsXxxControllerJoinMap joinMap) + { + for (uint i = 1; i <= _chassis.NumberOfInputs; i++) + { + var input = i; + var inputName = InputNames[input]; + var indexWithOffset = input - 1; + + trilist.SetSigTrueAction(joinMap.EnableInputHdcp.JoinNumber + indexWithOffset, () => EnableHdcp(input)); + trilist.SetSigTrueAction(joinMap.DisableInputHdcp.JoinNumber + indexWithOffset, () => DisableHdcp(input)); + + InputHdcpEnableFeedback[inputName].LinkInputSig(trilist.BooleanInput[joinMap.EnableInputHdcp.JoinNumber + indexWithOffset]); + InputHdcpEnableFeedback[inputName].LinkComplementInputSig(trilist.BooleanInput[joinMap.EnableInputHdcp.JoinNumber + indexWithOffset]); + + VideoInputSyncFeedbacks[inputName].LinkInputSig(trilist.BooleanInput[joinMap.InputSync.JoinNumber + indexWithOffset]); + + InputNameFeedbacks[inputName].LinkInputSig(trilist.StringInput[joinMap.InputName.JoinNumber + indexWithOffset]); + } + } + + + // links outputs to API + private void LinkChassisOutputsToApi(BasicTriList trilist, HdPsXxxControllerJoinMap joinMap) + { + for (uint i = 1; i <= _chassis.NumberOfOutputs; i++) + { + var output = i; + var outputName = OutputNames[output]; + var indexWithOffset = output - 1; + + trilist.SetUShortSigAction(joinMap.OutputRoute.JoinNumber + indexWithOffset, (a) => + ExecuteNumericSwitch(a, (ushort) output, eRoutingSignalType.AudioVideo)); + + OutputNameFeedbacks[outputName].LinkInputSig(trilist.StringInput[joinMap.OutputName.JoinNumber + indexWithOffset]); + OutputRouteNameFeedback[outputName].LinkInputSig(trilist.StringInput[joinMap.OutputRoutedName.JoinNumber + indexWithOffset]); + + VideoOutputRouteFeedbacks[outputName].LinkInputSig(trilist.UShortInput[joinMap.OutputRoute.JoinNumber + indexWithOffset]); + } + } + + + // links HdPs401 chassis to API + private void LinkChassis401ToApi(BasicTriList trilist, HdPsXxxControllerJoinMap joinMap) + { + trilist.SetSigTrueAction(joinMap.EnableAutoRoute.JoinNumber, () => _chassis401.AutoRouteOn()); + trilist.SetSigFalseAction(joinMap.EnableAutoRoute.JoinNumber, () => _chassis401.AutoRouteOff()); + + AutoRouteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableAutoRoute.JoinNumber]); + } + + + // links HdPs621 chassis to API + private void LinkChassis621ToApi(BasicTriList trilist, HdPsXxxControllerJoinMap joinMap) + { + trilist.SetSigTrueAction(joinMap.EnableAutoRoute.JoinNumber, () => _chassis621.AutoRouteOn()); + trilist.SetSigFalseAction(joinMap.EnableAutoRoute.JoinNumber, () => _chassis621.AutoRouteOff()); + + AutoRouteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableAutoRoute.JoinNumber]); + } + + + #endregion + + + /// + /// Executes a device switch using objects + /// + /// + /// + /// + public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) + { + var input = inputSelector as HdPsXxxHdmiInput; + var output = outputSelector as HdPsXxxHdmiOutput; + + Debug.Console(2, this, "ExecuteSwitch: input={0}, output={1}", input, output); + + if (output == null) + { + Debug.Console(0, this, "Unable to make switch, output selector is not HdPsXxxHdmiOutput"); + return; + } + + // TODO [ ] Validate if sending the same input toggles the switch + var current = output.VideoOut; + if (current != input) + output.VideoOut = input; + } + + + /// + /// Executes a device switch using numeric values + /// + /// + /// + /// + public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType signalType) + { + var input = inputSelector == 0 ? null : _chassis.Inputs[inputSelector]; + var output = _chassis.Outputs[outputSelector]; + + Debug.Console(2, this, "ExecuteNumericSwitch: input={0}, output={1}", input, output); + + ExecuteSwitch(input, output, signalType); + } + + + /// + /// Enables Hdcp on the provided port + /// + /// + public void EnableHdcp(uint port) + { + if (port <= 0 || port > _chassis.NumberOfInputs) return; + + _chassis.HdmiInputs[port].InputPort.HdcpSupportOn(); + InputHdcpEnableFeedback[InputNames[port]].FireUpdate(); + } + + + /// + /// Disables Hdcp on the provided port + /// + /// + public void DisableHdcp(uint port) + { + if (port <= 0 || port > _chassis.NumberOfInputs) return; + + _chassis.HdmiInputs[port].InputPort.HdcpSupportOff(); + InputHdcpEnableFeedback[InputNames[port]].FireUpdate(); + } + + + /// + /// Enables switcher auto route + /// + public void EnableAutoRoute() + { + if (_chassis.NumberOfInputs != 1) return; + + if (_chassis401 != null) + { + _chassis401.AutoRouteOn(); + } + + if (_chassis621 != null) + { + _chassis621.AutoRouteOn(); + } + } + + + /// + /// Disables switcher auto route + /// + public void DisableAutoRoute() + { + if (_chassis.NumberOfInputs != 1) return; + + if (_chassis401 != null) + { + _chassis401.AutoRouteOff(); + } + + if (_chassis621 != null) + { + _chassis621.AutoRouteOff(); + } + } + + #region Events + + + // _chassis online/offline event + private void _chassis_OnlineStatusChange(GenericBase currentDevice, + OnlineOfflineEventArgs args) + { + IsOnline.FireUpdate(); + + if (!args.DeviceOnLine) return; + + foreach (var feedback in Feedbacks) + { + feedback.FireUpdate(); + } + } + + + // _chassis input change event + private void _chassis_InputChange(Switch device, DMInputEventArgs args) + { + var eventId = args.EventId; + + switch (eventId) + { + case DMInputEventIds.VideoDetectedEventId: + { + Debug.Console(1, this, "Event ID {0}: Updating VideoInputSyncFeedbacks", eventId); + foreach (var item in VideoInputSyncFeedbacks) + { + item.FireUpdate(); + } + break; + } + case DMInputEventIds.InputNameFeedbackEventId: + case DMInputEventIds.InputNameEventId: + case DMInputEventIds.NameFeedbackEventId: + { + Debug.Console(1, this, "Event ID {0}: Updating name feedbacks", eventId); + + var input = args.Number; + var name = _chassis.HdmiInputs[input].NameFeedback.StringValue; + + Debug.Console(1, this, "Input {0} Name {1}", input, name); + break; + } + default: + { + Debug.Console(1, this, "Uhandled DM Input Event ID {0}", eventId); + break; + } + } + } + + + // _chassis output change event + private void _chassis_OutputChange(Switch device, DMOutputEventArgs args) + { + if (args.EventId != DMOutputEventIds.VideoOutEventId) return; + + var output = args.Number; + + var input = _chassis.HdmiDmLiteOutputs[output].VideoOutFeedback == null + ? 0 + : _chassis.HdmiDmLiteOutputs[output].VideoOutFeedback.Number; + + var outputName = OutputNames[output]; + + var feedback = VideoOutputRouteFeedbacks[outputName]; + if (feedback == null) return; + + var inputPort = InputPorts.FirstOrDefault( + p => p.FeedbackMatchObject == _chassis.HdmiDmLiteOutputs[output].VideoOutFeedback); + + var outputPort = OutputPorts.FirstOrDefault( + p => p.FeedbackMatchObject == _chassis.HdmiDmLiteOutputs[output]); + + feedback.FireUpdate(); + + OnSwitchChange(new RoutingNumericEventArgs( + output, input, outputPort, inputPort, eRoutingSignalType.AudioVideo)); + } + + + /// + /// Raise an event when the status of a switch object changes. + /// + /// Argumetns defined as IKeyName sender, output, input, & eRoutingSignalType + private void OnSwitchChange(RoutingNumericEventArgs args) + { + var newEvent = NumericSwitchChange; + if (newEvent != null) newEvent(this, args); + } + + + #endregion + + + #region FeedbacksAndFeedbackCollections + + + /// + /// Add feedback colleciton arrays to feedback collections + /// + /// BoolFeedback[] arrays + public void AddCollectionsToList(params FeedbackCollection[] feedbackCollections) + { + foreach (var item in feedbackCollections.SelectMany(feedbackCollection => feedbackCollections)) + { + AddCollectionsToList(item); + } + } + + + /// + /// Add feedback colleciton arrays to feedback collections + /// + /// IntFeedback[] arrays + public void AddCollectionsToList(params FeedbackCollection[] feedbackCollections) + { + foreach (var item in feedbackCollections.SelectMany(feedbackCollection => feedbackCollections)) + { + AddCollectionsToList(item); + } + } + + + /// + /// Add feedback colleciton arrays to feedback collections + /// + /// StringFeedback[] arrays + public void AddCollectionsToList(params FeedbackCollection[] feedbackCollections) + { + foreach (var item in feedbackCollections.SelectMany(feedbackCollection => feedbackCollections)) + { + AddCollectionsToList(item); + } + } + + + /// + /// Adds feedback colleciton to feedback collections + /// + /// BoolFeedback + public void AddCollectionToList(FeedbackCollection feedbackCollection) + { + foreach (var item in feedbackCollection.Where(item => item != null)) + { + AddFeedbackToList(item); + } + } + + + /// + /// Adds feedback colleciton to feedback collections + /// + /// IntFeedback + public void AddCollectionToList(FeedbackCollection feedbackCollection) + { + foreach (var item in feedbackCollection.Where(item => item != null)) + { + AddFeedbackToList(item); + } + } + + + /// + /// Adds feedback colleciton to feedback collections + /// + /// StringFeedback + public void AddCollectionToList(FeedbackCollection feedbackCollection) + { + foreach (var item in feedbackCollection.Where(item => item != null)) + { + AddFeedbackToList(item); + } + } + + + /// + /// Adds individual feedbacks to feedback collection + /// + /// Feedback + public void AddFeedbackToList(PepperDash.Essentials.Core.Feedback fb) + { + if (fb == null || Feedbacks.Contains(fb)) return; + + Feedbacks.Add(fb); + } + + + /// + /// Adds provided feedbacks to feedback collection list + /// + public void AddFeedbackCollecitons() + { + AddFeedbackToList(DeviceNameFeedback); + AddCollectionsToList(VideoInputSyncFeedbacks, InputHdcpEnableFeedback); + AddCollectionsToList(VideoOutputRouteFeedbacks); + AddCollectionsToList(InputNameFeedbacks, OutputNameFeedbacks, OutputRouteNameFeedback); + } + + + #endregion + + + #region Factory + + + public class HdSp401ControllerFactory : EssentialsDeviceFactory + { + public HdSp401ControllerFactory() + { + TypeNames = new List() { "hdsp401", "hdsp402", "hdsp621", "hdsp622" }; + } + public override EssentialsDevice BuildDevice(DeviceConfig dc) + { + Debug.Console(1, "Factory Attempting to create new HD-PSXxx device"); + + var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); + if (props == null) + { + Debug.Console(1, "Factory failed to create new HD-PSXxx device, properties config was null"); + return null; + } + + var key = dc.Key; + var name = dc.Name; + var type = dc.Type.ToLower(); + var control = props.Control; + var ipid = control.IpIdInt; + var address = control.TcpSshProperties.Address; + + switch (type) + { + case ("hdps401"): + { + return new HdPsXxxController(key, name, new HdPs401(ipid, Global.ControlSystem), props); + } + case ("hdsp402"): + { + return new HdPsXxxController(key, name, new HdPs402(ipid, Global.ControlSystem), props); + } + case ("hdsp621"): + { + return new HdPsXxxController(key, name, new HdPs621(ipid, Global.ControlSystem), props); + } + case ("hdsp622"): + { + return new HdPsXxxController(key, name, new HdPs622(ipid, Global.ControlSystem), props); + } + default: + { + Debug.Console(1, "Factory failed to create new {0} device", type); + return null; + } + } + } + } + + + #endregion + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs b/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs new file mode 100644 index 00000000..b521facf --- /dev/null +++ b/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using Newtonsoft.Json; +using PepperDash.Core; + +namespace PepperDash_Essentials_DM.Config +{ + public class HdPsXxxPropertiesConfig + { + [JsonProperty("control")] + public ControlPropertiesConfig Control { get; set; } + + [JsonProperty("inputs")] + public Dictionary Inputs { get; set; } + + [JsonProperty("outputs")] + public Dictionary Outputs { get; set; } + } +} \ No newline at end of file diff --git a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj index adfddbe3..0011c305 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj +++ b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj @@ -104,6 +104,8 @@ + + From b06d0c0debd2a75245f2105b563625dc5f45758f Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Thu, 7 Sep 2023 18:37:21 -0500 Subject: [PATCH 22/50] fix: resolves typo of hdpsXxx type name in the factory --- .../Essentials_DM/Chassis/HdPsXxxController.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 78da7a7b..499dd865 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -52,7 +52,7 @@ namespace PepperDash_Essentials_DM.Chassis /// HdPs401 device instance /// public HdPsXxxController(string key, string name, HdPsXxx chassis, HdPsXxxPropertiesConfig props) - : base(key, name) + : base(key, name, chassis) { _chassis = chassis; Name = name; @@ -584,7 +584,7 @@ namespace PepperDash_Essentials_DM.Chassis { public HdSp401ControllerFactory() { - TypeNames = new List() { "hdsp401", "hdsp402", "hdsp621", "hdsp622" }; + TypeNames = new List() { "hdps401", "hdps402", "hdps621", "hdps622" }; } public override EssentialsDevice BuildDevice(DeviceConfig dc) { @@ -610,15 +610,15 @@ namespace PepperDash_Essentials_DM.Chassis { return new HdPsXxxController(key, name, new HdPs401(ipid, Global.ControlSystem), props); } - case ("hdsp402"): + case ("hdps402"): { return new HdPsXxxController(key, name, new HdPs402(ipid, Global.ControlSystem), props); } - case ("hdsp621"): + case ("hdps621"): { return new HdPsXxxController(key, name, new HdPs621(ipid, Global.ControlSystem), props); } - case ("hdsp622"): + case ("hdps622"): { return new HdPsXxxController(key, name, new HdPs622(ipid, Global.ControlSystem), props); } From d74c5de65130c1fe03db44394a65b9dc3cb96c64 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Fri, 8 Sep 2023 10:51:19 -0500 Subject: [PATCH 23/50] wip: updates to HdPsXxx class while test implementation to resolve exceptions --- .../Chassis/HdPsXxxController.cs | 28 ++++++++++++++++--- .../Config/HdPsXxxPropertiesConfig.cs | 14 +++++++++- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 499dd865..d923949e 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -63,15 +63,17 @@ namespace PepperDash_Essentials_DM.Chassis return; } - InputPorts = new RoutingPortCollection(); - InputNames = new Dictionary(); + InputPorts = new RoutingPortCollection(); InputNameFeedbacks = new FeedbackCollection(); InputHdcpEnableFeedback = new FeedbackCollection(); + InputNames = new Dictionary(); + //InputNames = props.Inputs; OutputPorts = new RoutingPortCollection(); - OutputNames = new Dictionary(); OutputNameFeedbacks = new FeedbackCollection(); OutputRouteNameFeedback = new FeedbackCollection(); + OutputNames = new Dictionary(); + //OutputNames = props.Outputs; VideoInputSyncFeedbacks = new FeedbackCollection(); VideoOutputRouteFeedbacks = new FeedbackCollection(); @@ -95,6 +97,15 @@ namespace PepperDash_Essentials_DM.Chassis // input setup private void SetupInputs(Dictionary dict) { + if (dict == null) + { + Debug.Console(1, this, "Failed to setup inputs, properties are null"); + return; + } + foreach (var kvp in dict) + { + Debug.Console(1, this, "props.Input[{0}]: {1}", kvp.Key, kvp.Value); + } InputNames = dict; for (uint i = 1; i <= _chassis.NumberOfInputs; i++) @@ -129,6 +140,15 @@ namespace PepperDash_Essentials_DM.Chassis // output setup private void SetupOutputs(Dictionary dict) { + if (dict == null) + { + Debug.Console(1, this, "Failed to setup outputs, properties are null"); + return; + } + foreach (var kvp in dict) + { + Debug.Console(1, this, "props.Output[{0}]: {1}", kvp.Key, kvp.Value); + } OutputNames = dict; for (uint i = 1; i <= _chassis.NumberOfOutputs; i++) @@ -602,7 +622,7 @@ namespace PepperDash_Essentials_DM.Chassis var type = dc.Type.ToLower(); var control = props.Control; var ipid = control.IpIdInt; - var address = control.TcpSshProperties.Address; + //var address = control.TcpSshProperties.Address; switch (type) { diff --git a/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs b/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs index b521facf..c02fc511 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using Newtonsoft.Json; using PepperDash.Core; +using PepperDash.Essentials.DM.Config; namespace PepperDash_Essentials_DM.Config { @@ -10,9 +11,20 @@ namespace PepperDash_Essentials_DM.Config public ControlPropertiesConfig Control { get; set; } [JsonProperty("inputs")] + //public Dictionary Inputs { get; set; } public Dictionary Inputs { get; set; } [JsonProperty("outputs")] - public Dictionary Outputs { get; set; } + //public Dictionary Outputs { get; set; } + public Dictionary Outputs { get; set; } + + public HdPsXxxPropertiesConfig() + { + //Inputs = new Dictionary(); + //Outputs = new Dictionary(); + + Inputs = new Dictionary(); + Outputs = new Dictionary(); + } } } \ No newline at end of file From 527457baf54d557f5c5991330335d0be894165b2 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Fri, 8 Sep 2023 13:00:27 -0500 Subject: [PATCH 24/50] refactor(wip): MPC3 class refactor constructor --- PepperDashEssentials/ControlSystem.cs | 48 ++-- .../Touchpanels/Mpc3Touchpanel.cs | 231 +++++++++++------- 2 files changed, 169 insertions(+), 110 deletions(-) diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index f24cb828..0ebfd927 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -392,50 +392,45 @@ namespace PepperDash.Essentials { Debug.Console(2, "Adding DmpsRoutingController for {0} to Device Manager.", this.ControllerPrompt); - var propertiesConfig = JsonConvert.DeserializeObject(devConf.Properties.ToString()); + var propertiesConfig = JsonConvert.DeserializeObject(devConf.Properties.ToString()) ?? + new DM.Config.DmpsRoutingPropertiesConfig(); - if(propertiesConfig == null) - propertiesConfig = new DM.Config.DmpsRoutingPropertiesConfig(); - - DeviceManager.AddDevice(DmpsRoutingController.GetDmpsRoutingController("processor-avRouting", this.ControllerPrompt, propertiesConfig)); + DeviceManager.AddDevice(DmpsRoutingController.GetDmpsRoutingController("processor-avRouting", this.ControllerPrompt, propertiesConfig)); } else if (this.ControllerPrompt.IndexOf("mpc3", StringComparison.OrdinalIgnoreCase) > -1) { Debug.Console(2, "MPC3 processor type detected. Adding Mpc3TouchpanelController."); var butToken = devConf.Properties["buttons"]; - if (butToken != null) - { - var buttons = butToken.ToObject>(); - var tpController = new Essentials.Core.Touchpanels.Mpc3TouchpanelController(devConf.Key, devConf.Name, Global.ControlSystem, buttons); - DeviceManager.AddDevice(tpController); - } - else - { - Debug.Console(0, Debug.ErrorLogLevel.Error, "Error: Unable to deserialize buttons collection for device: {0}", devConf.Key); - } - + if (butToken == null) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, + "Error: Unable to deserialize buttons collection for device: {0}", devConf.Key); + continue; + } + + var buttons = butToken.ToObject>(); + var tpController = new Core.Touchpanels.Mpc3TouchpanelController( + string.Format("{0}-keypadButtons", devConf.Key), devConf.Name, Global.ControlSystem, buttons); + + DeviceManager.AddDevice(tpController); } else { Debug.Console(2, "************Processor is not DMPS type***************"); } - - continue; } // Try local factories first - IKeyed newDev = null; + var newDev = null ?? PepperDash.Essentials.Core.DeviceFactory.GetDevice(devConf); - if (newDev == null) - newDev = PepperDash.Essentials.Core.DeviceFactory.GetDevice(devConf); - - if (newDev != null) - DeviceManager.AddDevice(newDev); - else - Debug.Console(0, Debug.ErrorLogLevel.Error, "ERROR: Cannot load unknown device type '{0}', key '{1}'.", devConf.Type, devConf.Key); + if (newDev == null) + Debug.Console(0, Debug.ErrorLogLevel.Error, "ERROR: Cannot load unknown device type '{0}', key '{1}'.", + devConf.Type, devConf.Key); + else + DeviceManager.AddDevice(newDev); } catch (Exception e) { @@ -443,7 +438,6 @@ namespace PepperDash.Essentials } } Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Devices Loaded."); - } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs index c9a5f605..97a18d50 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs @@ -1,12 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; +using System.Collections.Generic; +using System.Globalization; using Crestron.SimplSharpPro; - +using Newtonsoft.Json; using PepperDash.Core; -using PepperDash.Essentials.Core; namespace PepperDash.Essentials.Core.Touchpanels { @@ -16,82 +12,147 @@ namespace PepperDash.Essentials.Core.Touchpanels /// public class Mpc3TouchpanelController : Device { - MPC3Basic _Touchpanel; + readonly MPC3Basic _touchpanel; - Dictionary _Buttons; + readonly Dictionary _buttons; public Mpc3TouchpanelController(string key, string name, CrestronControlSystem processor, Dictionary buttons) : base(key, name) { - _Touchpanel = processor.ControllerTouchScreenSlotDevice as MPC3Basic; - _Buttons = buttons; + _touchpanel = processor.ControllerTouchScreenSlotDevice as MPC3Basic; + if (_touchpanel == null) + { + Debug.Console(1, this, "Failed to construct {0}, check configuration", key); + return; + } + + _touchpanel.ButtonStateChange += _touchpanel_ButtonStateChange; + _buttons = buttons; - _Touchpanel.ButtonStateChange += new Crestron.SimplSharpPro.DeviceSupport.ButtonEventHandler(_Touchpanel_ButtonStateChange); + AddPostActivationAction(() => + { + // Link up the button feedbacks to the specified BoolFeedbacks + foreach (var button in _buttons) + { + var buttonKey = button.Key.ToLower(); + var buttonConfig = button.Value; + if (buttonConfig == null) + { + Debug.Console(1, this, "Unable to get button config for {0}-{1}", Key, button.Key); + continue; + } - AddPostActivationAction(() => - { - // Link up the button feedbacks to the specified BoolFeedbacks - foreach (var button in _Buttons) - { - var feedbackConfig = button.Value.Feedback; - var device = DeviceManager.GetDeviceForKey(feedbackConfig.DeviceKey) as Device; - if (device != null) - { - var bKey = button.Key.ToLower(); + int buttonNumber; + if (TryParseInt(buttonKey, out buttonNumber)) + { + Debug.Console(0, this, "buttonFeedback: tryIntParse successful, buttonNumber = {0}", buttonNumber); + _touchpanel.EnableNumericalButton((uint)buttonNumber); + } + else + { + Debug.Console(0, this, "buttonFeedback: tryIntParse failed, buttonKey = {0}", buttonKey); + } - var feedback = device.GetFeedbackProperty(feedbackConfig.FeedbackName); + //var buttonEventTypes = buttonConfig.EventTypes; - var bFeedback = feedback as BoolFeedback; - var iFeedback = feedback as IntFeedback; - if (bFeedback != null) - { + var buttonFeedback = buttonConfig.Feedback; + if (buttonFeedback == null) + { + Debug.Console(1, this, "Button '{0}' feedback not configured, feedback will not be implemented", buttonKey); + continue; + } + + var device = DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) as Device; + if (device == null) + { + Debug.Console(1, this, "Unable to get device with key {0}, feedback will not be implemented", + buttonFeedback.DeviceKey); + continue; + } - if (bKey == "power") - { - bFeedback.LinkCrestronFeedback(_Touchpanel.FeedbackPower); - continue; - } - else if (bKey == "mute") - { - bFeedback.LinkCrestronFeedback(_Touchpanel.FeedbackMute); - continue; - } + var deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); + Debug.Console(0, this, "deviceFeedback.GetType().Name: {0}", deviceFeedback.GetType().Name); + //switch (feedback.GetType().Name.ToLower()) + //{ + // case("boolfeedback"): + // { - // Link to the Crestron Feedback corresponding to the button number - bFeedback.LinkCrestronFeedback(_Touchpanel.Feedbacks[UInt16.Parse(button.Key)]); - } - else if (iFeedback != null) - { - if (bKey == "volumefeedback") - { - var volFeedback = feedback as IntFeedback; - // TODO: Figure out how to subsribe to a volume IntFeedback and link it to the voluem - volFeedback.LinkInputSig(_Touchpanel.VolumeBargraph); - } - } - else - { - Debug.Console(1, this, "Unable to get BoolFeedback with name: {0} from device: {1}", feedbackConfig.FeedbackName, device.Key); - } - } - else - { - Debug.Console(1, this, "Unable to get device with key: {0}", feedbackConfig.DeviceKey); - } - } - }); + // break; + // } + // case("intfeedback"): + // { + + // break; + // } + //} + + var boolFeedback = deviceFeedback as BoolFeedback; + var intFeedback = deviceFeedback as IntFeedback; + + switch (buttonKey) + { + case ("power"): + { + if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackPower); + break; + } + case ("volumeup"): + { + break; + } + case ("volumedown"): + { + break; + } + case ("volumefeedback"): + { + if (intFeedback != null) + { + var volumeFeedback = intFeedback; + volumeFeedback.LinkInputSig(_touchpanel.VolumeBargraph); + } + break; + } + case ("mute"): + { + if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackMute); + break; + } + default: + { + if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.Feedbacks[(uint)buttonNumber]); + break; + } + } + } + }); } - void _Touchpanel_ButtonStateChange(GenericBase device, Crestron.SimplSharpPro.DeviceSupport.ButtonEventArgs args) + public bool TryParseInt(string str, out int result) + { + result = 0; + + foreach (var c in str) + { + if(c < '0' || c > '9') + return false; + + result = result*10 + (c - '0'); + } + + return true; + } + + void _touchpanel_ButtonStateChange(GenericBase device, Crestron.SimplSharpPro.DeviceSupport.ButtonEventArgs args) { Debug.Console(1, this, "Button {0} ({1}), {2}", args.Button.Number, args.Button.Name, args.NewButtonState); var type = args.NewButtonState.ToString(); - if (_Buttons.ContainsKey(args.Button.Number.ToString())) + if (_buttons.ContainsKey(args.Button.Number.ToString(CultureInfo.InvariantCulture))) { - Press(args.Button.Number.ToString(), type); + Press(args.Button.Number.ToString(CultureInfo.InvariantCulture), type); } - else if(_Buttons.ContainsKey(args.Button.Name.ToString())) + else if(_buttons.ContainsKey(args.Button.Name.ToString())) { Press(args.Button.Name.ToString(), type); } @@ -101,29 +162,30 @@ namespace PepperDash.Essentials.Core.Touchpanels /// Runs the function associated with this button/type. One of the following strings: /// Pressed, Released, Tapped, DoubleTapped, Held, HeldReleased /// - /// + /// /// - public void Press(string number, string type) + public void Press(string buttonKey, string type) { // TODO: In future, consider modifying this to generate actions at device activation time // to prevent the need to dynamically call the method via reflection on each button press - if (!_Buttons.ContainsKey(number)) { return; } - var but = _Buttons[number]; - if (but.EventTypes.ContainsKey(type)) - { - foreach (var a in but.EventTypes[type]) { DeviceJsonApi.DoDeviceAction(a); } - } + if (!_buttons.ContainsKey(buttonKey)) return; + + var button = _buttons[buttonKey]; + if (!button.EventTypes.ContainsKey(type)) return; + + foreach (var eventType in button.EventTypes[type]) DeviceJsonApi.DoDeviceAction(eventType); } - - } /// - /// Represents the configuration of a keybad buggon + /// Represents the configuration of a keypad button /// public class KeypadButton { + [JsonProperty("eventTypes")] public Dictionary EventTypes { get; set; } + + [JsonProperty("feedback")] public KeypadButtonFeedback Feedback { get; set; } public KeypadButton() @@ -133,12 +195,15 @@ namespace PepperDash.Essentials.Core.Touchpanels } } - /// - /// - /// - public class KeypadButtonFeedback - { - public string DeviceKey { get; set; } - public string FeedbackName { get; set; } - } + /// + /// Represents the configuration of a keypad button feedback + /// + public class KeypadButtonFeedback + { + [JsonProperty("deviceKey")] + public string DeviceKey { get; set; } + + [JsonProperty("feedbackName")] + public string FeedbackName { get; set; } + } } \ No newline at end of file From 13df52ab497f785cb114aaf7dbeea427e77fe012 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Fri, 8 Sep 2023 13:47:34 -0500 Subject: [PATCH 25/50] refactor(wip): updates constructor postActiviate call to seperate methods for enabling/disabling buttons and feedbacks --- .../Touchpanels/Mpc3Touchpanel.cs | 574 +++++++++++++----- 1 file changed, 413 insertions(+), 161 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs index 97a18d50..2cab16e6 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs @@ -1,199 +1,451 @@ using System.Collections.Generic; using System.Globalization; +using System.Linq; using Crestron.SimplSharpPro; using Newtonsoft.Json; using PepperDash.Core; namespace PepperDash.Essentials.Core.Touchpanels { - /// - /// A wrapper class for the touchpanel portion of an MPC3 class process to allow for configurable - /// behavior of the keybad buttons - /// - public class Mpc3TouchpanelController : Device - { - readonly MPC3Basic _touchpanel; + /// + /// A wrapper class for the touchpanel portion of an MPC3 class process to allow for configurable + /// behavior of the keybad buttons + /// + public class Mpc3TouchpanelController : Device + { + readonly MPC3Basic _touchpanel; - readonly Dictionary _buttons; + readonly Dictionary _buttons; + + public Mpc3TouchpanelController(string key, string name, CrestronControlSystem processor, Dictionary buttons) + : base(key, name) + { + _touchpanel = processor.ControllerTouchScreenSlotDevice as MPC3Basic; + if (_touchpanel == null) + { + Debug.Console(1, this, "Failed to construct MPC3 Touchpanel Controller with key {0}, check configuration", key); + return; + } - public Mpc3TouchpanelController(string key, string name, CrestronControlSystem processor, Dictionary buttons) - : base(key, name) - { - _touchpanel = processor.ControllerTouchScreenSlotDevice as MPC3Basic; - if (_touchpanel == null) - { - Debug.Console(1, this, "Failed to construct {0}, check configuration", key); - return; - } - _touchpanel.ButtonStateChange += _touchpanel_ButtonStateChange; _buttons = buttons; - AddPostActivationAction(() => - { - // Link up the button feedbacks to the specified BoolFeedbacks - foreach (var button in _buttons) - { - var buttonKey = button.Key.ToLower(); - var buttonConfig = button.Value; - if (buttonConfig == null) - { - Debug.Console(1, this, "Unable to get button config for {0}-{1}", Key, button.Key); - continue; - } + AddPostActivationAction(() => + { + SetupButtonsForEvents(); + SetupButtonFeedbacks(); - int buttonNumber; - if (TryParseInt(buttonKey, out buttonNumber)) + // check button config + //foreach (var button in _buttons) + //{ + // var buttonKey = button.Key.ToLower(); + // var buttonConfig = button.Value; + // if (buttonConfig == null) + // { + // Debug.Console(1, this, "Unable to get button config for {0}-{1}", Key, button.Key); + // continue; + // } + + // int buttonNumber; + // if (TryParseInt(buttonKey, out buttonNumber)) + // Debug.Console(0, this, "buttonFeedback: tryIntParse successful, buttonNumber = {0}", buttonNumber); + // else + // Debug.Console(0, this, "buttonFeedback: tryIntParse failed, buttonKey = {0}", buttonKey); + + + // // button event type configuration enables/disables keypad button + // var buttonEventTypes = buttonConfig.EventTypes; + // switch (buttonKey) + // { + // case ("power"): + // { + // if (buttonEventTypes == null) + // _touchpanel.DisablePowerButton(); + // else + // _touchpanel.EnablePowerButton(); + + // break; + // } + // case ("volumeup"): + // { + // if (buttonEventTypes == null) + // _touchpanel.DisableVolumeUpButton(); + + // break; + // } + // case ("volumedown"): + // { + // if(buttonEventTypes == null) + // _touchpanel.DisableVolumeDownButton(); + + // break; + // } + // case ("volumefeedback"): + // { + + // break; + // } + // case ("mute"): + // { + // if(buttonEventTypes == null) + // _touchpanel.DisableMuteButton(); + // else + // _touchpanel.EnableMuteButton(); + + // break; + // } + // default: + // { + // if(buttonNumber == 0) + // break; + + // if (buttonEventTypes == null) + // _touchpanel.DisableNumericalButton((uint)buttonNumber); + // else + // _touchpanel.EnableNumericalButton((uint)buttonNumber); + + // break; + // } + // } + + + // // Link up the button feedbacks to the specified device feedback + // var buttonFeedback = buttonConfig.Feedback; + // if (buttonFeedback == null) + // { + // Debug.Console(1, this, "Button '{0}' feedback not configured, feedback will not be implemented", buttonKey); + // continue; + // } + + // var device = DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) as Device; + // if (device == null) + // { + // Debug.Console(1, this, "Unable to get device with key {0}, feedback will not be implemented", + // buttonFeedback.DeviceKey); + // continue; + // } + + // var deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); + // Debug.Console(0, this, "deviceFeedback.GetType().Name: {0}", deviceFeedback.GetType().Name); + // //switch (feedback.GetType().Name.ToLower()) + // //{ + // // case("boolfeedback"): + // // { + + // // break; + // // } + // // case("intfeedback"): + // // { + + // // break; + // // } + // //} + + // var boolFeedback = deviceFeedback as BoolFeedback; + // var intFeedback = deviceFeedback as IntFeedback; + + // switch (buttonKey) + // { + // case ("power"): + // { + // if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackPower); + // break; + // } + // case ("volumeup"): + // { + // break; + // } + // case ("volumedown"): + // { + // break; + // } + // case ("volumefeedback"): + // { + // if (intFeedback != null) + // { + // var volumeFeedback = intFeedback; + // volumeFeedback.LinkInputSig(_touchpanel.VolumeBargraph); + // } + // break; + // } + // case ("mute"): + // { + // if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackMute); + // break; + // } + // default: + // { + // if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.Feedbacks[(uint)buttonNumber]); + // break; + // } + // } + //} + }); + } + + public void SetupButtonsForEvents() + { + if (_buttons == null) + { + Debug.Console(1, this, "Button properties are null, failed to setup buttons for events. Verify button configuraiton."); + return; + } + + // check button config + foreach (var button in _buttons) + { + var buttonKey = button.Key.ToLower(); + var buttonConfig = button.Value; + if (buttonConfig == null) + { + Debug.Console(1, this, "Unable to get button config for {0}-{1}", Key, button.Key); + continue; + } + + int buttonNumber; + if (TryParseInt(buttonKey, out buttonNumber)) + Debug.Console(0, this, "buttonFeedback: tryIntParse successful, buttonNumber = {0}", buttonNumber); + else + Debug.Console(0, this, "buttonFeedback: tryIntParse failed, buttonKey = {0}", buttonKey); + + + // button event type configuration enables/disables keypad button + var buttonEventTypes = buttonConfig.EventTypes; + switch (buttonKey) + { + case ("power"): { - Debug.Console(0, this, "buttonFeedback: tryIntParse successful, buttonNumber = {0}", buttonNumber); - _touchpanel.EnableNumericalButton((uint)buttonNumber); + if (buttonEventTypes == null) + _touchpanel.DisablePowerButton(); + else + _touchpanel.EnablePowerButton(); + + break; } - else + case ("volumeup"): { - Debug.Console(0, this, "buttonFeedback: tryIntParse failed, buttonKey = {0}", buttonKey); + if (buttonEventTypes == null) + _touchpanel.DisableVolumeUpButton(); + + break; } - - //var buttonEventTypes = buttonConfig.EventTypes; - - var buttonFeedback = buttonConfig.Feedback; - if (buttonFeedback == null) - { - Debug.Console(1, this, "Button '{0}' feedback not configured, feedback will not be implemented", buttonKey); - continue; - } - - var device = DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) as Device; - if (device == null) - { - Debug.Console(1, this, "Unable to get device with key {0}, feedback will not be implemented", - buttonFeedback.DeviceKey); - continue; - } - - var deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); - Debug.Console(0, this, "deviceFeedback.GetType().Name: {0}", deviceFeedback.GetType().Name); - //switch (feedback.GetType().Name.ToLower()) - //{ - // case("boolfeedback"): - // { - - // break; - // } - // case("intfeedback"): - // { - - // break; - // } - //} - - var boolFeedback = deviceFeedback as BoolFeedback; - var intFeedback = deviceFeedback as IntFeedback; - - switch (buttonKey) + case ("volumedown"): { - case ("power"): + if (buttonEventTypes == null) + _touchpanel.DisableVolumeDownButton(); + + break; + } + case ("volumefeedback"): + { + + break; + } + case ("mute"): + { + if (buttonEventTypes == null) + _touchpanel.DisableMuteButton(); + else + _touchpanel.EnableMuteButton(); + + break; + } + default: + { + if (buttonNumber == 0) + break; + + if (buttonEventTypes == null) + _touchpanel.DisableNumericalButton((uint) buttonNumber); + else + _touchpanel.EnableNumericalButton((uint) buttonNumber); + + break; + } + } + } + } + + public void SetupButtonFeedbacks() + { + if (_buttons == null) + { + Debug.Console(1, this, "Button properties are null, failed to setup buttons for events. Verify button configuraiton."); + return; + } + + // check button config + foreach (var button in _buttons) + { + var buttonKey = button.Key.ToLower(); + var buttonConfig = button.Value; + if (buttonConfig == null) + { + Debug.Console(1, this, "Unable to get button config for {0}-{1}", Key, button.Key); + continue; + } + + int buttonNumber; + if (TryParseInt(buttonKey, out buttonNumber)) + Debug.Console(0, this, "buttonFeedback: tryIntParse successful, buttonNumber = {0}", buttonNumber); + else + Debug.Console(0, this, "buttonFeedback: tryIntParse failed, buttonKey = {0}", buttonKey); + + // Link up the button feedbacks to the specified device feedback + var buttonFeedback = buttonConfig.Feedback; + if (buttonFeedback == null) + { + Debug.Console(1, this, "Button '{0}' feedback not configured, feedback will not be implemented", buttonKey); + continue; + } + + var device = DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) as Device; + if (device == null) + { + Debug.Console(1, this, "Unable to get device with key {0}, feedback will not be implemented", + buttonFeedback.DeviceKey); + continue; + } + + var deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); + Debug.Console(0, this, "deviceFeedback.GetType().Name: {0}", deviceFeedback.GetType().Name); + //switch (feedback.GetType().Name.ToLower()) + //{ + // case("boolfeedback"): + // { + + // break; + // } + // case("intfeedback"): + // { + + // break; + // } + //} + + var boolFeedback = deviceFeedback as BoolFeedback; + var intFeedback = deviceFeedback as IntFeedback; + + switch (buttonKey) + { + case ("power"): + { + if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackPower); + break; + } + case ("volumeup"): + { + break; + } + case ("volumedown"): + { + break; + } + case ("volumefeedback"): + { + if (intFeedback != null) { - if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackPower); - break; + var volumeFeedback = intFeedback; + volumeFeedback.LinkInputSig(_touchpanel.VolumeBargraph); } - case ("volumeup"): - { - break; - } - case ("volumedown"): - { - break; - } - case ("volumefeedback"): - { - if (intFeedback != null) - { - var volumeFeedback = intFeedback; - volumeFeedback.LinkInputSig(_touchpanel.VolumeBargraph); - } - break; - } - case ("mute"): - { - if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackMute); - break; - } - default: - { - if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.Feedbacks[(uint)buttonNumber]); - break; - } - } - } - }); - } + break; + } + case ("mute"): + { + if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackMute); + break; + } + default: + { + if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.Feedbacks[(uint)buttonNumber]); + break; + } + } + } + } - public bool TryParseInt(string str, out int result) - { - result = 0; + public bool TryParseInt(string str, out int result) + { + try + { + result = int.Parse(str); + return true; + } + catch + { + result = 0; + return false; + } + } - foreach (var c in str) - { - if(c < '0' || c > '9') - return false; + public bool TryExtractInt(string str, out int result) + { + result = str.Where(c => c >= '0' && c <= '9').Aggregate(0, (current, c) => current * 10 + (c - '0')); - result = result*10 + (c - '0'); - } + //foreach (var c in str) + //{ + // if(c < '0' || c > '9') + // //return false + // continue; - return true; - } + // result = result*10 + (c - '0'); + //} - void _touchpanel_ButtonStateChange(GenericBase device, Crestron.SimplSharpPro.DeviceSupport.ButtonEventArgs args) - { - Debug.Console(1, this, "Button {0} ({1}), {2}", args.Button.Number, args.Button.Name, args.NewButtonState); - var type = args.NewButtonState.ToString(); + Debug.Console(0, this, "TryParseInt: str-'{0}', result-'{1}'", str, result); + return result != 0; + } - if (_buttons.ContainsKey(args.Button.Number.ToString(CultureInfo.InvariantCulture))) - { - Press(args.Button.Number.ToString(CultureInfo.InvariantCulture), type); - } - else if(_buttons.ContainsKey(args.Button.Name.ToString())) - { - Press(args.Button.Name.ToString(), type); - } - } + void _touchpanel_ButtonStateChange(GenericBase device, Crestron.SimplSharpPro.DeviceSupport.ButtonEventArgs args) + { + Debug.Console(1, this, "Button {0} ({1}), {2}", args.Button.Number, args.Button.Name, args.NewButtonState); + var type = args.NewButtonState.ToString(); - /// - /// Runs the function associated with this button/type. One of the following strings: - /// Pressed, Released, Tapped, DoubleTapped, Held, HeldReleased - /// - /// - /// - public void Press(string buttonKey, string type) - { - // TODO: In future, consider modifying this to generate actions at device activation time - // to prevent the need to dynamically call the method via reflection on each button press - if (!_buttons.ContainsKey(buttonKey)) return; + if (_buttons.ContainsKey(args.Button.Number.ToString(CultureInfo.InvariantCulture))) + { + Press(args.Button.Number.ToString(CultureInfo.InvariantCulture), type); + } + else if (_buttons.ContainsKey(args.Button.Name.ToString())) + { + Press(args.Button.Name.ToString(), type); + } + } - var button = _buttons[buttonKey]; - if (!button.EventTypes.ContainsKey(type)) return; + /// + /// Runs the function associated with this button/type. One of the following strings: + /// Pressed, Released, Tapped, DoubleTapped, Held, HeldReleased + /// + /// + /// + public void Press(string buttonKey, string type) + { + // TODO: In future, consider modifying this to generate actions at device activation time + // to prevent the need to dynamically call the method via reflection on each button press + if (!_buttons.ContainsKey(buttonKey)) return; - foreach (var eventType in button.EventTypes[type]) DeviceJsonApi.DoDeviceAction(eventType); - } - } + var button = _buttons[buttonKey]; + if (!button.EventTypes.ContainsKey(type)) return; - /// - /// Represents the configuration of a keypad button - /// - public class KeypadButton - { + foreach (var eventType in button.EventTypes[type]) DeviceJsonApi.DoDeviceAction(eventType); + } + } + + /// + /// Represents the configuration of a keypad button + /// + public class KeypadButton + { [JsonProperty("eventTypes")] - public Dictionary EventTypes { get; set; } + public Dictionary EventTypes { get; set; } [JsonProperty("feedback")] - public KeypadButtonFeedback Feedback { get; set; } + public KeypadButtonFeedback Feedback { get; set; } - public KeypadButton() - { - EventTypes = new Dictionary(); - Feedback = new KeypadButtonFeedback(); - } - } + public KeypadButton() + { + EventTypes = new Dictionary(); + Feedback = new KeypadButtonFeedback(); + } + } /// /// Represents the configuration of a keypad button feedback From 316d545bda853569792c2e56b337470a4661c576 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Fri, 8 Sep 2023 15:20:29 -0500 Subject: [PATCH 26/50] refactor(wip): updates keypad initializeFeedbacks method --- .../Touchpanels/Mpc3Touchpanel.cs | 402 +++++------------- 1 file changed, 118 insertions(+), 284 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs index 2cab16e6..f4611a70 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Globalization; -using System.Linq; using Crestron.SimplSharpPro; using Newtonsoft.Json; using PepperDash.Core; @@ -29,191 +28,47 @@ namespace PepperDash.Essentials.Core.Touchpanels _touchpanel.ButtonStateChange += _touchpanel_ButtonStateChange; _buttons = buttons; - - AddPostActivationAction(() => - { - SetupButtonsForEvents(); - SetupButtonFeedbacks(); - - // check button config - //foreach (var button in _buttons) - //{ - // var buttonKey = button.Key.ToLower(); - // var buttonConfig = button.Value; - // if (buttonConfig == null) - // { - // Debug.Console(1, this, "Unable to get button config for {0}-{1}", Key, button.Key); - // continue; - // } - - // int buttonNumber; - // if (TryParseInt(buttonKey, out buttonNumber)) - // Debug.Console(0, this, "buttonFeedback: tryIntParse successful, buttonNumber = {0}", buttonNumber); - // else - // Debug.Console(0, this, "buttonFeedback: tryIntParse failed, buttonKey = {0}", buttonKey); - - - // // button event type configuration enables/disables keypad button - // var buttonEventTypes = buttonConfig.EventTypes; - // switch (buttonKey) - // { - // case ("power"): - // { - // if (buttonEventTypes == null) - // _touchpanel.DisablePowerButton(); - // else - // _touchpanel.EnablePowerButton(); - - // break; - // } - // case ("volumeup"): - // { - // if (buttonEventTypes == null) - // _touchpanel.DisableVolumeUpButton(); - - // break; - // } - // case ("volumedown"): - // { - // if(buttonEventTypes == null) - // _touchpanel.DisableVolumeDownButton(); - - // break; - // } - // case ("volumefeedback"): - // { - - // break; - // } - // case ("mute"): - // { - // if(buttonEventTypes == null) - // _touchpanel.DisableMuteButton(); - // else - // _touchpanel.EnableMuteButton(); - - // break; - // } - // default: - // { - // if(buttonNumber == 0) - // break; - - // if (buttonEventTypes == null) - // _touchpanel.DisableNumericalButton((uint)buttonNumber); - // else - // _touchpanel.EnableNumericalButton((uint)buttonNumber); - - // break; - // } - // } - - - // // Link up the button feedbacks to the specified device feedback - // var buttonFeedback = buttonConfig.Feedback; - // if (buttonFeedback == null) - // { - // Debug.Console(1, this, "Button '{0}' feedback not configured, feedback will not be implemented", buttonKey); - // continue; - // } - - // var device = DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) as Device; - // if (device == null) - // { - // Debug.Console(1, this, "Unable to get device with key {0}, feedback will not be implemented", - // buttonFeedback.DeviceKey); - // continue; - // } - - // var deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); - // Debug.Console(0, this, "deviceFeedback.GetType().Name: {0}", deviceFeedback.GetType().Name); - // //switch (feedback.GetType().Name.ToLower()) - // //{ - // // case("boolfeedback"): - // // { - - // // break; - // // } - // // case("intfeedback"): - // // { - - // // break; - // // } - // //} - - // var boolFeedback = deviceFeedback as BoolFeedback; - // var intFeedback = deviceFeedback as IntFeedback; - - // switch (buttonKey) - // { - // case ("power"): - // { - // if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackPower); - // break; - // } - // case ("volumeup"): - // { - // break; - // } - // case ("volumedown"): - // { - // break; - // } - // case ("volumefeedback"): - // { - // if (intFeedback != null) - // { - // var volumeFeedback = intFeedback; - // volumeFeedback.LinkInputSig(_touchpanel.VolumeBargraph); - // } - // break; - // } - // case ("mute"): - // { - // if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackMute); - // break; - // } - // default: - // { - // if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.Feedbacks[(uint)buttonNumber]); - // break; - // } - // } - //} - }); - } - - public void SetupButtonsForEvents() - { if (_buttons == null) { - Debug.Console(1, this, "Button properties are null, failed to setup buttons for events. Verify button configuraiton."); + Debug.Console(1, this, + "Button properties are null, failed to setup MPC3 Touch Controller, check configuration"); return; } - // check button config - foreach (var button in _buttons) + AddPostActivationAction(() => { - var buttonKey = button.Key.ToLower(); - var buttonConfig = button.Value; - if (buttonConfig == null) + foreach (var button in _buttons) { - Debug.Console(1, this, "Unable to get button config for {0}-{1}", Key, button.Key); - continue; + var buttonKey = button.Key.ToLower(); + var buttonConfig = button.Value; + + InitializeButton(buttonKey, buttonConfig); + InitializeButtonFeedback(buttonKey, buttonConfig); } + }); + } - int buttonNumber; - if (TryParseInt(buttonKey, out buttonNumber)) - Debug.Console(0, this, "buttonFeedback: tryIntParse successful, buttonNumber = {0}", buttonNumber); - else - Debug.Console(0, this, "buttonFeedback: tryIntParse failed, buttonKey = {0}", buttonKey); + /// + /// Enables/disables buttons based on event type configuration + /// + /// + /// + public void InitializeButton(string key, KeypadButton config) + { + if (config == null) + { + Debug.Console(1, this, "Button '{0}' config is null, unable to initialize", key); + return; + } + int buttonNumber; + TryParseInt(key, out buttonNumber); - // button event type configuration enables/disables keypad button - var buttonEventTypes = buttonConfig.EventTypes; - switch (buttonKey) - { - case ("power"): + var buttonEventTypes = config.EventTypes; + + switch (key) + { + case ("power"): { if (buttonEventTypes == null) _touchpanel.DisablePowerButton(); @@ -222,26 +77,26 @@ namespace PepperDash.Essentials.Core.Touchpanels break; } - case ("volumeup"): + case ("volumeup"): { if (buttonEventTypes == null) _touchpanel.DisableVolumeUpButton(); break; } - case ("volumedown"): + case ("volumedown"): { if (buttonEventTypes == null) _touchpanel.DisableVolumeDownButton(); break; } - case ("volumefeedback"): + case ("volumefeedback"): { break; } - case ("mute"): + case ("mute"): { if (buttonEventTypes == null) _touchpanel.DisableMuteButton(); @@ -250,120 +105,116 @@ namespace PepperDash.Essentials.Core.Touchpanels break; } - default: + default: { if (buttonNumber == 0) break; if (buttonEventTypes == null) - _touchpanel.DisableNumericalButton((uint) buttonNumber); + _touchpanel.DisableNumericalButton((uint)buttonNumber); else - _touchpanel.EnableNumericalButton((uint) buttonNumber); + _touchpanel.EnableNumericalButton((uint)buttonNumber); break; } - } } + + Debug.Console(1, this, "Button '{0}' {1}", key, buttonEventTypes == null + ? "is disabled, verify eventTypes are configured." + : "is enabled"); } - public void SetupButtonFeedbacks() + /// + /// Links button feedback if configured + /// + /// + /// + public void InitializeButtonFeedback(string key, KeypadButton config) { - if (_buttons == null) + if (config == null) { - Debug.Console(1, this, "Button properties are null, failed to setup buttons for events. Verify button configuraiton."); + Debug.Console(1, this, "Button '{0}' config is null, unable to initialize feedback", key); return; } - // check button config - foreach (var button in _buttons) + int buttonNumber; + TryParseInt(key, out buttonNumber); + + // Link up the button feedbacks to the specified device feedback + var buttonFeedback = config.Feedback; + if (buttonFeedback == null) { - var buttonKey = button.Key.ToLower(); - var buttonConfig = button.Value; - if (buttonConfig == null) - { - Debug.Console(1, this, "Unable to get button config for {0}-{1}", Key, button.Key); - continue; - } + Debug.Console(1, this, "Button '{0}' feedback not configured and will not be implemented. Verify feedback is configured if required.", key); + return; + } - int buttonNumber; - if (TryParseInt(buttonKey, out buttonNumber)) - Debug.Console(0, this, "buttonFeedback: tryIntParse successful, buttonNumber = {0}", buttonNumber); - else - Debug.Console(0, this, "buttonFeedback: tryIntParse failed, buttonKey = {0}", buttonKey); + var device = DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) as Device; + if (device == null) + { + Debug.Console(1, this, "Button '{0}' feedback device with key '{0}' not found, feedback will not be implemented. Verify feedback deviceKey is properly configured.", + buttonFeedback.DeviceKey); + return; + } - // Link up the button feedbacks to the specified device feedback - var buttonFeedback = buttonConfig.Feedback; - if (buttonFeedback == null) - { - Debug.Console(1, this, "Button '{0}' feedback not configured, feedback will not be implemented", buttonKey); - continue; - } + // TODO [ ] verify if this can replace the current method + var deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); + Debug.Console(0, this, "deviceFeedback.GetType().Name: '{0}'", deviceFeedback.GetType().Name); + //switch (feedback.GetType().Name.ToLower()) + //{ + // case("boolfeedback"): + // { + // break; + // } + // case("intfeedback"): + // { + // break; + // } + // case("stringfeedback"): + // { + // break; + // } + //} - var device = DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) as Device; - if (device == null) - { - Debug.Console(1, this, "Unable to get device with key {0}, feedback will not be implemented", - buttonFeedback.DeviceKey); - continue; - } + var boolFeedback = deviceFeedback as BoolFeedback; + var intFeedback = deviceFeedback as IntFeedback; - var deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); - Debug.Console(0, this, "deviceFeedback.GetType().Name: {0}", deviceFeedback.GetType().Name); - //switch (feedback.GetType().Name.ToLower()) - //{ - // case("boolfeedback"): - // { - - // break; - // } - // case("intfeedback"): - // { - - // break; - // } - //} - - var boolFeedback = deviceFeedback as BoolFeedback; - var intFeedback = deviceFeedback as IntFeedback; - - switch (buttonKey) - { - case ("power"): + switch (key) + { + case ("power"): + { + if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackPower); + break; + } + case ("volumeup"): + case ("volumedown"): + case ("volumefeedback"): + { + if (intFeedback != null) { - if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackPower); - break; + var volumeFeedback = intFeedback; + volumeFeedback.LinkInputSig(_touchpanel.VolumeBargraph); } - case ("volumeup"): - { - break; - } - case ("volumedown"): - { - break; - } - case ("volumefeedback"): - { - if (intFeedback != null) - { - var volumeFeedback = intFeedback; - volumeFeedback.LinkInputSig(_touchpanel.VolumeBargraph); - } - break; - } - case ("mute"): - { - if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackMute); - break; - } - default: - { - if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.Feedbacks[(uint)buttonNumber]); - break; - } - } + break; + } + case ("mute"): + { + if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.FeedbackMute); + break; + } + default: + { + if (boolFeedback != null) boolFeedback.LinkCrestronFeedback(_touchpanel.Feedbacks[(uint)buttonNumber]); + break; + } } } + /// + /// Try parse int helper method + /// + /// + /// + /// public bool TryParseInt(string str, out int result) { try @@ -378,24 +229,7 @@ namespace PepperDash.Essentials.Core.Touchpanels } } - public bool TryExtractInt(string str, out int result) - { - result = str.Where(c => c >= '0' && c <= '9').Aggregate(0, (current, c) => current * 10 + (c - '0')); - - //foreach (var c in str) - //{ - // if(c < '0' || c > '9') - // //return false - // continue; - - // result = result*10 + (c - '0'); - //} - - Debug.Console(0, this, "TryParseInt: str-'{0}', result-'{1}'", str, result); - return result != 0; - } - - void _touchpanel_ButtonStateChange(GenericBase device, Crestron.SimplSharpPro.DeviceSupport.ButtonEventArgs args) + private void _touchpanel_ButtonStateChange(GenericBase device, Crestron.SimplSharpPro.DeviceSupport.ButtonEventArgs args) { Debug.Console(1, this, "Button {0} ({1}), {2}", args.Button.Number, args.Button.Name, args.NewButtonState); var type = args.NewButtonState.ToString(); From 97c0bddb48aa4ed3dbdc82cd2fc231c7daa3ae86 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Mon, 11 Sep 2023 14:49:46 -0500 Subject: [PATCH 27/50] fix(wip): refactors SetupInputs() and SetupOutputs() to handle io types --- .../Chassis/HdPsXxxController.cs | 192 ++++++++---------- 1 file changed, 80 insertions(+), 112 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index d923949e..9884be8e 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -21,8 +21,6 @@ namespace PepperDash_Essentials_DM.Chassis { private readonly HdPsXxx _chassis; - private readonly HdPs401 _chassis401; - private readonly HdPs621 _chassis621; public RoutingPortCollection InputPorts { get; private set; } public RoutingPortCollection OutputPorts { get; private set; } @@ -63,33 +61,35 @@ namespace PepperDash_Essentials_DM.Chassis return; } - InputPorts = new RoutingPortCollection(); + InputPorts = new RoutingPortCollection(); InputNameFeedbacks = new FeedbackCollection(); InputHdcpEnableFeedback = new FeedbackCollection(); - InputNames = new Dictionary(); - //InputNames = props.Inputs; + InputNames = new Dictionary(); OutputPorts = new RoutingPortCollection(); OutputNameFeedbacks = new FeedbackCollection(); OutputRouteNameFeedback = new FeedbackCollection(); OutputNames = new Dictionary(); - //OutputNames = props.Outputs; VideoInputSyncFeedbacks = new FeedbackCollection(); VideoOutputRouteFeedbacks = new FeedbackCollection(); if (_chassis.NumberOfOutputs == 1) { - if (_chassis is HdPs401) - _chassis401 = _chassis as HdPs401; - if (_chassis is HdPs621) - _chassis621 = _chassis as HdPs621; + //if (_chassis is HdPs401) + // _chassis401 = _chassis as HdPs401; + //if (_chassis is HdPs621) + // _chassis621 = _chassis as HdPs621; - AutoRouteFeedback = new BoolFeedback(() => _chassis401.PriorityRouteOnFeedback.BoolValue); + AutoRouteFeedback = new BoolFeedback(() => _chassis.PriorityRouteOnFeedback.BoolValue); } - SetupInputs(props.Inputs); - SetupOutputs(props.Outputs); + + InputNames = props.Inputs; + SetupInputs(InputNames); + + OutputNames = props.Outputs; + SetupOutputs(OutputNames); AddPostActivationAction(AddFeedbackCollecitons); } @@ -106,35 +106,49 @@ namespace PepperDash_Essentials_DM.Chassis { Debug.Console(1, this, "props.Input[{0}]: {1}", kvp.Key, kvp.Value); } - InputNames = dict; - for (uint i = 1; i <= _chassis.NumberOfInputs; i++) + foreach (var item in _chassis.HdmiInputs) { - var index = i; - var name = string.IsNullOrEmpty(InputNames[index]) ? string.Format("Input {0}", index) : InputNames[index]; - var input = _chassis.Inputs[index]; - var hdmiInput = _chassis.HdmiInputs[index]; - var dmLiteInput = _chassis.DmLiteInputs[index]; - + var input = item; + var index = item.Number; + var name = string.IsNullOrEmpty(InputNames[index]) ? string.Format("HDMI Input {0}", index) : InputNames[index]; + InputNameFeedbacks.Add(new StringFeedback(name, () => InputNames[index])); - // TODO [ ] verify which input type is needed - input.Name.StringValue = name; - hdmiInput.Name.StringValue = name; - dmLiteInput.Name.StringValue = name; - var port = new RoutingInputPort(name, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) { FeedbackMatchObject = input }; InputPorts.Add(port); - InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => hdmiInput.InputPort.HdcpSupportOnFeedback.BoolValue)); + InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); VideoInputSyncFeedbacks.Add(new BoolFeedback(name, () => input.VideoDetectedFeedback.BoolValue)); } - _chassis.DMInputChange += _chassis_InputChange; + foreach (var item in _chassis.DmLiteInputs) + { + var input = item; + var index = item.Number; + + var name = string.IsNullOrEmpty(InputNames[index]) ? string.Format("DM Input {0}", index) : InputNames[index]; + input.Name.StringValue = name; + + InputNameFeedbacks.Add(new StringFeedback(name, () => InputNames[index])); + + var port = new RoutingInputPort(name, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) + { + FeedbackMatchObject = input + }; + InputPorts.Add(port); + + + InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); + + VideoInputSyncFeedbacks.Add(new BoolFeedback(name, () => input.VideoDetectedFeedback.BoolValue)); + } + + _chassis.DMInputChange += _chassis_InputChange; } // output setup @@ -149,20 +163,14 @@ namespace PepperDash_Essentials_DM.Chassis { Debug.Console(1, this, "props.Output[{0}]: {1}", kvp.Key, kvp.Value); } - OutputNames = dict; - for (uint i = 1; i <= _chassis.NumberOfOutputs; i++) + foreach (var item in _chassis.HdmiDmLiteOutputs) { - var index = i; + var output = item; + var index = item.Number; + var name = string.IsNullOrEmpty(OutputNames[index]) ? string.Format("Output {0}", index) : OutputNames[index]; - var output = _chassis.Outputs[index]; - var hdmiDmLiteOutput = _chassis.HdmiDmLiteOutputs[index]; - - OutputNameFeedbacks.Add(new StringFeedback(name, () => OutputNames[index])); - - // TODO [ ] verify which output type is needed output.Name.StringValue = name; - hdmiDmLiteOutput.Name.StringValue = name; var port = new RoutingOutputPort(name, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, output, this) { @@ -206,10 +214,6 @@ namespace PepperDash_Essentials_DM.Chassis _chassis.OnlineStatusChange += _chassis_OnlineStatusChange; - if (_chassis401 != null) LinkChassis401ToApi(trilist, joinMap); - - if (_chassis621 != null) LinkChassis621ToApi(trilist, joinMap); - LinkChassisInputsToApi(trilist, joinMap); LinkChassisOutputsToApi(trilist, joinMap); @@ -252,36 +256,17 @@ namespace PepperDash_Essentials_DM.Chassis var indexWithOffset = output - 1; trilist.SetUShortSigAction(joinMap.OutputRoute.JoinNumber + indexWithOffset, (a) => - ExecuteNumericSwitch(a, (ushort) output, eRoutingSignalType.AudioVideo)); + ExecuteNumericSwitch(a, (ushort)output, eRoutingSignalType.AudioVideo)); OutputNameFeedbacks[outputName].LinkInputSig(trilist.StringInput[joinMap.OutputName.JoinNumber + indexWithOffset]); OutputRouteNameFeedback[outputName].LinkInputSig(trilist.StringInput[joinMap.OutputRoutedName.JoinNumber + indexWithOffset]); VideoOutputRouteFeedbacks[outputName].LinkInputSig(trilist.UShortInput[joinMap.OutputRoute.JoinNumber + indexWithOffset]); } - } - - - // links HdPs401 chassis to API - private void LinkChassis401ToApi(BasicTriList trilist, HdPsXxxControllerJoinMap joinMap) - { - trilist.SetSigTrueAction(joinMap.EnableAutoRoute.JoinNumber, () => _chassis401.AutoRouteOn()); - trilist.SetSigFalseAction(joinMap.EnableAutoRoute.JoinNumber, () => _chassis401.AutoRouteOff()); AutoRouteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableAutoRoute.JoinNumber]); } - - // links HdPs621 chassis to API - private void LinkChassis621ToApi(BasicTriList trilist, HdPsXxxControllerJoinMap joinMap) - { - trilist.SetSigTrueAction(joinMap.EnableAutoRoute.JoinNumber, () => _chassis621.AutoRouteOn()); - trilist.SetSigFalseAction(joinMap.EnableAutoRoute.JoinNumber, () => _chassis621.AutoRouteOff()); - - AutoRouteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableAutoRoute.JoinNumber]); - } - - #endregion @@ -359,17 +344,9 @@ namespace PepperDash_Essentials_DM.Chassis /// public void EnableAutoRoute() { - if (_chassis.NumberOfInputs != 1) return; + if (_chassis.NumberOfInputs == 1) return; - if (_chassis401 != null) - { - _chassis401.AutoRouteOn(); - } - - if (_chassis621 != null) - { - _chassis621.AutoRouteOn(); - } + _chassis.AutoRouteOn(); } @@ -378,20 +355,12 @@ namespace PepperDash_Essentials_DM.Chassis /// public void DisableAutoRoute() { - if (_chassis.NumberOfInputs != 1) return; + if (_chassis.NumberOfInputs == 1) return; - if (_chassis401 != null) - { - _chassis401.AutoRouteOff(); - } - - if (_chassis621 != null) - { - _chassis621.AutoRouteOff(); - } + _chassis.AutoRouteOff(); } - #region Events + #region Events // _chassis online/offline event @@ -417,31 +386,31 @@ namespace PepperDash_Essentials_DM.Chassis switch (eventId) { case DMInputEventIds.VideoDetectedEventId: - { - Debug.Console(1, this, "Event ID {0}: Updating VideoInputSyncFeedbacks", eventId); - foreach (var item in VideoInputSyncFeedbacks) { - item.FireUpdate(); + Debug.Console(1, this, "Event ID {0}: Updating VideoInputSyncFeedbacks", eventId); + foreach (var item in VideoInputSyncFeedbacks) + { + item.FireUpdate(); + } + break; } - break; - } case DMInputEventIds.InputNameFeedbackEventId: case DMInputEventIds.InputNameEventId: case DMInputEventIds.NameFeedbackEventId: - { - Debug.Console(1, this, "Event ID {0}: Updating name feedbacks", eventId); + { + Debug.Console(1, this, "Event ID {0}: Updating name feedbacks", eventId); - var input = args.Number; - var name = _chassis.HdmiInputs[input].NameFeedback.StringValue; + var input = args.Number; + var name = _chassis.HdmiInputs[input].NameFeedback.StringValue; - Debug.Console(1, this, "Input {0} Name {1}", input, name); - break; - } + Debug.Console(1, this, "Input {0} Name {1}", input, name); + break; + } default: - { - Debug.Console(1, this, "Uhandled DM Input Event ID {0}", eventId); - break; - } + { + Debug.Console(1, this, "Uhandled DM Input Event ID {0}", eventId); + break; + } } } @@ -493,7 +462,7 @@ namespace PepperDash_Essentials_DM.Chassis /// - /// Add feedback colleciton arrays to feedback collections + /// Add feedback collection arrays to feedback collections /// /// BoolFeedback[] arrays public void AddCollectionsToList(params FeedbackCollection[] feedbackCollections) @@ -587,10 +556,10 @@ namespace PepperDash_Essentials_DM.Chassis /// public void AddFeedbackCollecitons() { - AddFeedbackToList(DeviceNameFeedback); - AddCollectionsToList(VideoInputSyncFeedbacks, InputHdcpEnableFeedback); - AddCollectionsToList(VideoOutputRouteFeedbacks); - AddCollectionsToList(InputNameFeedbacks, OutputNameFeedbacks, OutputRouteNameFeedback); + //AddFeedbackToList(DeviceNameFeedback); + //AddCollectionsToList(VideoInputSyncFeedbacks, InputHdcpEnableFeedback); + //AddCollectionsToList(VideoOutputRouteFeedbacks); + //AddCollectionsToList(InputNameFeedbacks, OutputNameFeedbacks, OutputRouteNameFeedback); } @@ -608,7 +577,11 @@ namespace PepperDash_Essentials_DM.Chassis } public override EssentialsDevice BuildDevice(DeviceConfig dc) { - Debug.Console(1, "Factory Attempting to create new HD-PSXxx device"); + var key = dc.Key; + var name = dc.Name; + var type = dc.Type.ToLower(); + + Debug.Console(1, "Factory Attempting to create new {0} device", type); var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); if (props == null) @@ -617,12 +590,7 @@ namespace PepperDash_Essentials_DM.Chassis return null; } - var key = dc.Key; - var name = dc.Name; - var type = dc.Type.ToLower(); - var control = props.Control; - var ipid = control.IpIdInt; - //var address = control.TcpSshProperties.Address; + var ipid = props.Control.IpIdInt; switch (type) { From 08af6370a6124800aacca276b4ec6a56d597e64f Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Mon, 11 Sep 2023 15:48:34 -0500 Subject: [PATCH 28/50] fix(wip): adds Debug.Console() statements to identify keys per input; adds ICec interface, pending implementation --- .../Chassis/HdPsXxxController.cs | 164 +++++------------- 1 file changed, 41 insertions(+), 123 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 9884be8e..f4c725f0 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -17,7 +17,7 @@ using PepperDash_Essentials_DM.Config; namespace PepperDash_Essentials_DM.Chassis { [Description("Wrapper class for all HdPsXxx switchers")] - public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IHasFeedback + public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, ICec, IHasHdmiInHdcp, IHasFeedback { private readonly HdPsXxx _chassis; @@ -75,15 +75,7 @@ namespace PepperDash_Essentials_DM.Chassis VideoOutputRouteFeedbacks = new FeedbackCollection(); if (_chassis.NumberOfOutputs == 1) - { - //if (_chassis is HdPs401) - // _chassis401 = _chassis as HdPs401; - //if (_chassis is HdPs621) - // _chassis621 = _chassis as HdPs621; - AutoRouteFeedback = new BoolFeedback(() => _chassis.PriorityRouteOnFeedback.BoolValue); - } - InputNames = props.Inputs; SetupInputs(InputNames); @@ -91,7 +83,7 @@ namespace PepperDash_Essentials_DM.Chassis OutputNames = props.Outputs; SetupOutputs(OutputNames); - AddPostActivationAction(AddFeedbackCollecitons); + //AddPostActivationAction(); } // input setup @@ -107,6 +99,20 @@ namespace PepperDash_Essentials_DM.Chassis Debug.Console(1, this, "props.Input[{0}]: {1}", kvp.Key, kvp.Value); } + // TODO [ ] testing + var hdmiKeys = _chassis.HdmiInputs.Keys; + foreach (var key in hdmiKeys) + { + Debug.Console(0, this, "HDMI Input key-'{0}'", key); + } + + var dmKeys = _chassis.DmLiteInputs.Keys; + foreach (var key in dmKeys) + { + Debug.Console(0, this, "DM Input key-'{0}'", key); + } + + foreach (var item in _chassis.HdmiInputs) { var input = item; @@ -123,7 +129,7 @@ namespace PepperDash_Essentials_DM.Chassis InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); - VideoInputSyncFeedbacks.Add(new BoolFeedback(name, () => input.VideoDetectedFeedback.BoolValue)); + VideoInputSyncFeedbacks.Add(new BoolFeedback(name, () => input.VideoDetectedFeedback.BoolValue)); } foreach (var item in _chassis.DmLiteInputs) @@ -164,9 +170,17 @@ namespace PepperDash_Essentials_DM.Chassis Debug.Console(1, this, "props.Output[{0}]: {1}", kvp.Key, kvp.Value); } + + // TODO [ ] testing + var keys = _chassis.HdmiDmLiteOutputs.Keys; + foreach (var key in keys) + { + Debug.Console(0, this, "HdmiDmLite Output key-'{0}'", key); + } + foreach (var item in _chassis.HdmiDmLiteOutputs) { - var output = item; + var output = item; var index = item.Number; var name = string.IsNullOrEmpty(OutputNames[index]) ? string.Format("Output {0}", index) : OutputNames[index]; @@ -182,7 +196,7 @@ namespace PepperDash_Essentials_DM.Chassis VideoOutputRouteFeedbacks.Add(new IntFeedback(name, () => output.VideoOutFeedback == null ? 0 : (int)output.VideoOutFeedback.Number)); } - + _chassis.DMOutputChange += _chassis_OutputChange; } @@ -268,7 +282,7 @@ namespace PepperDash_Essentials_DM.Chassis } #endregion - + /// /// Executes a device switch using objects @@ -455,115 +469,7 @@ namespace PepperDash_Essentials_DM.Chassis } - #endregion - - - #region FeedbacksAndFeedbackCollections - - - /// - /// Add feedback collection arrays to feedback collections - /// - /// BoolFeedback[] arrays - public void AddCollectionsToList(params FeedbackCollection[] feedbackCollections) - { - foreach (var item in feedbackCollections.SelectMany(feedbackCollection => feedbackCollections)) - { - AddCollectionsToList(item); - } - } - - - /// - /// Add feedback colleciton arrays to feedback collections - /// - /// IntFeedback[] arrays - public void AddCollectionsToList(params FeedbackCollection[] feedbackCollections) - { - foreach (var item in feedbackCollections.SelectMany(feedbackCollection => feedbackCollections)) - { - AddCollectionsToList(item); - } - } - - - /// - /// Add feedback colleciton arrays to feedback collections - /// - /// StringFeedback[] arrays - public void AddCollectionsToList(params FeedbackCollection[] feedbackCollections) - { - foreach (var item in feedbackCollections.SelectMany(feedbackCollection => feedbackCollections)) - { - AddCollectionsToList(item); - } - } - - - /// - /// Adds feedback colleciton to feedback collections - /// - /// BoolFeedback - public void AddCollectionToList(FeedbackCollection feedbackCollection) - { - foreach (var item in feedbackCollection.Where(item => item != null)) - { - AddFeedbackToList(item); - } - } - - - /// - /// Adds feedback colleciton to feedback collections - /// - /// IntFeedback - public void AddCollectionToList(FeedbackCollection feedbackCollection) - { - foreach (var item in feedbackCollection.Where(item => item != null)) - { - AddFeedbackToList(item); - } - } - - - /// - /// Adds feedback colleciton to feedback collections - /// - /// StringFeedback - public void AddCollectionToList(FeedbackCollection feedbackCollection) - { - foreach (var item in feedbackCollection.Where(item => item != null)) - { - AddFeedbackToList(item); - } - } - - - /// - /// Adds individual feedbacks to feedback collection - /// - /// Feedback - public void AddFeedbackToList(PepperDash.Essentials.Core.Feedback fb) - { - if (fb == null || Feedbacks.Contains(fb)) return; - - Feedbacks.Add(fb); - } - - - /// - /// Adds provided feedbacks to feedback collection list - /// - public void AddFeedbackCollecitons() - { - //AddFeedbackToList(DeviceNameFeedback); - //AddCollectionsToList(VideoInputSyncFeedbacks, InputHdcpEnableFeedback); - //AddCollectionsToList(VideoOutputRouteFeedbacks); - //AddCollectionsToList(InputNameFeedbacks, OutputNameFeedbacks, OutputRouteNameFeedback); - } - - - #endregion + #endregion #region Factory @@ -621,5 +527,17 @@ namespace PepperDash_Essentials_DM.Chassis #endregion + + // TODO [ ] Implement CEC control + // return _chassis.HdmiDmLiteOutputs[0].DmLiteOutput.DmLiteOutputPort.StreamCec; + public Cec StreamCec { get; private set; } + + public IntFeedback HdmiInHdcpStateFeedback { get; private set; } + public void SetHdmiInHdcpState(eHdcpCapabilityType hdcpState) + { + throw new NotImplementedException(); + } + + public eHdcpCapabilityType HdmiInHdcpCapability { get; private set; } } } \ No newline at end of file From 4e33743f5015742798a556096b61d47905a777eb Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Mon, 11 Sep 2023 19:24:21 -0500 Subject: [PATCH 29/50] refactor: SetupInput() and SetupOutput() methods to set standard keys for ports that are instantiated --- .../Chassis/HdPsXxxController.cs | 56 ++++++++----------- 1 file changed, 23 insertions(+), 33 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index f4c725f0..8bfab826 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using Crestron.SimplSharp; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; using Crestron.SimplSharpPro.DM; @@ -19,7 +17,6 @@ namespace PepperDash_Essentials_DM.Chassis [Description("Wrapper class for all HdPsXxx switchers")] public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, ICec, IHasHdmiInHdcp, IHasFeedback { - private readonly HdPsXxx _chassis; public RoutingPortCollection InputPorts { get; private set; } @@ -99,32 +96,20 @@ namespace PepperDash_Essentials_DM.Chassis Debug.Console(1, this, "props.Input[{0}]: {1}", kvp.Key, kvp.Value); } - // TODO [ ] testing - var hdmiKeys = _chassis.HdmiInputs.Keys; - foreach (var key in hdmiKeys) - { - Debug.Console(0, this, "HDMI Input key-'{0}'", key); - } - - var dmKeys = _chassis.DmLiteInputs.Keys; - foreach (var key in dmKeys) - { - Debug.Console(0, this, "DM Input key-'{0}'", key); - } - - foreach (var item in _chassis.HdmiInputs) { var input = item; var index = item.Number; + var key = string.Format("hdmiIn{0}", index); var name = string.IsNullOrEmpty(InputNames[index]) ? string.Format("HDMI Input {0}", index) : InputNames[index]; InputNameFeedbacks.Add(new StringFeedback(name, () => InputNames[index])); - var port = new RoutingInputPort(name, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) + var port = new RoutingInputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) { FeedbackMatchObject = input }; + Debug.Console(1, this, "Adding HDMI Input port: {0}", port.Key); InputPorts.Add(port); InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); @@ -136,7 +121,7 @@ namespace PepperDash_Essentials_DM.Chassis { var input = item; var index = item.Number; - + var key = string.Format("dmLiteIn{0}", index); var name = string.IsNullOrEmpty(InputNames[index]) ? string.Format("DM Input {0}", index) : InputNames[index]; input.Name.StringValue = name; @@ -146,8 +131,8 @@ namespace PepperDash_Essentials_DM.Chassis { FeedbackMatchObject = input }; + Debug.Console(0, this, "Adding DM Input port: {0}",port.Key); InputPorts.Add(port); - InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); @@ -170,26 +155,22 @@ namespace PepperDash_Essentials_DM.Chassis Debug.Console(1, this, "props.Output[{0}]: {1}", kvp.Key, kvp.Value); } - - // TODO [ ] testing - var keys = _chassis.HdmiDmLiteOutputs.Keys; - foreach (var key in keys) - { - Debug.Console(0, this, "HdmiDmLite Output key-'{0}'", key); - } - foreach (var item in _chassis.HdmiDmLiteOutputs) { - var output = item; + var output = item; var index = item.Number; - + var key = string.Format("hdmiDmLiteOut{0}", index); var name = string.IsNullOrEmpty(OutputNames[index]) ? string.Format("Output {0}", index) : OutputNames[index]; output.Name.StringValue = name; - var port = new RoutingOutputPort(name, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, output, this) + var port = new RoutingOutputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, output, this) { - FeedbackMatchObject = output + FeedbackMatchObject = output, + // set port for CEC + Port = output }; + Debug.Console(0, this, "Adding HdmiDmLite Output port: {0} {1}", + port.Key, port.ParentDevice); OutputPorts.Add(port); OutputRouteNameFeedback.Add(new StringFeedback(name, () => output.VideoOutFeedback.NameFeedback.StringValue)); @@ -530,7 +511,16 @@ namespace PepperDash_Essentials_DM.Chassis // TODO [ ] Implement CEC control // return _chassis.HdmiDmLiteOutputs[0].DmLiteOutput.DmLiteOutputPort.StreamCec; - public Cec StreamCec { get; private set; } + public Cec StreamCec + { + get + { + return _chassis.NumberOfOutputs == 1 + //? _chassis.HdmiDmLiteOutputs[0].DmLiteOutput.DmLiteOutputPort.StreamCec + ? _chassis.HdmiDmLiteOutputs[0].HdmiOutput.HdmiOutputPort.StreamCec + : null; + } + } public IntFeedback HdmiInHdcpStateFeedback { get; private set; } public void SetHdmiInHdcpState(eHdcpCapabilityType hdcpState) From 27bac4e83dfd83fdc46a861c1f113f072e73e76e Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 12 Sep 2023 10:09:37 -0500 Subject: [PATCH 30/50] fix(wip): updates stream cec implementation to handle switchers with multiple outputs --- .../Chassis/HdPsXxxController.cs | 76 +++++++++++-------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 8bfab826..c7ef719c 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -15,7 +15,7 @@ using PepperDash_Essentials_DM.Config; namespace PepperDash_Essentials_DM.Chassis { [Description("Wrapper class for all HdPsXxx switchers")] - public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, ICec, IHasHdmiInHdcp, IHasFeedback + public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback { private readonly HdPsXxx _chassis; @@ -61,7 +61,7 @@ namespace PepperDash_Essentials_DM.Chassis InputPorts = new RoutingPortCollection(); InputNameFeedbacks = new FeedbackCollection(); InputHdcpEnableFeedback = new FeedbackCollection(); - InputNames = new Dictionary(); + InputNames = new Dictionary(); OutputPorts = new RoutingPortCollection(); OutputNameFeedbacks = new FeedbackCollection(); @@ -79,8 +79,6 @@ namespace PepperDash_Essentials_DM.Chassis OutputNames = props.Outputs; SetupOutputs(OutputNames); - - //AddPostActivationAction(); } // input setup @@ -102,19 +100,19 @@ namespace PepperDash_Essentials_DM.Chassis var index = item.Number; var key = string.Format("hdmiIn{0}", index); var name = string.IsNullOrEmpty(InputNames[index]) ? string.Format("HDMI Input {0}", index) : InputNames[index]; - + InputNameFeedbacks.Add(new StringFeedback(name, () => InputNames[index])); var port = new RoutingInputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) { FeedbackMatchObject = input }; - Debug.Console(1, this, "Adding HDMI Input port: {0}", port.Key); + Debug.Console(1, this, "Adding Input port: {0}", port.Key); InputPorts.Add(port); InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); - VideoInputSyncFeedbacks.Add(new BoolFeedback(name, () => input.VideoDetectedFeedback.BoolValue)); + VideoInputSyncFeedbacks.Add(new BoolFeedback(name, () => input.VideoDetectedFeedback.BoolValue)); } foreach (var item in _chassis.DmLiteInputs) @@ -127,13 +125,13 @@ namespace PepperDash_Essentials_DM.Chassis InputNameFeedbacks.Add(new StringFeedback(name, () => InputNames[index])); - var port = new RoutingInputPort(name, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) + var port = new RoutingInputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) { FeedbackMatchObject = input }; - Debug.Console(0, this, "Adding DM Input port: {0}",port.Key); + Debug.Console(0, this, "Adding Input port: {0}", port.Key); InputPorts.Add(port); - + InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); VideoInputSyncFeedbacks.Add(new BoolFeedback(name, () => input.VideoDetectedFeedback.BoolValue)); @@ -169,15 +167,35 @@ namespace PepperDash_Essentials_DM.Chassis // set port for CEC Port = output }; - Debug.Console(0, this, "Adding HdmiDmLite Output port: {0} {1}", - port.Key, port.ParentDevice); + Debug.Console(0, this, "Adding Output port: {0}", port.Key); OutputPorts.Add(port); OutputRouteNameFeedback.Add(new StringFeedback(name, () => output.VideoOutFeedback.NameFeedback.StringValue)); VideoOutputRouteFeedbacks.Add(new IntFeedback(name, () => output.VideoOutFeedback == null ? 0 : (int)output.VideoOutFeedback.Number)); + + // TODO [ ] Investigate setting input priorities per output + // {{in1-priority-level}, {in2-priority-level}, .... {in6-priority-level}} + // default priority level input 1-4 ascending + output.OutputPort.InputPriorities(new byte[] { 1, 2, 3, 4 }); + + if (port.Port == null) continue; + + var hdmiOutputStreamCec = output.HdmiOutput.HdmiOutputPort.StreamCec; + if (hdmiOutputStreamCec != null) + { + var streamCec = new StreamCecWrapper(string.Format("{0}-hdmiOut{1}-streamCec", Key, index), hdmiOutputStreamCec); + DeviceManager.AddDevice(streamCec); + } + + var dmLiteOutputStreamCec = output.DmLiteOutput.DmLiteOutputPort.StreamCec; + if (dmLiteOutputStreamCec != null) + { + var streamCec = new StreamCecWrapper(string.Format("{0}-dmLiteOut{1}-streamCec", Key, index), dmLiteOutputStreamCec); + DeviceManager.AddDevice(streamCec); + } } - + _chassis.DMOutputChange += _chassis_OutputChange; } @@ -263,7 +281,7 @@ namespace PepperDash_Essentials_DM.Chassis } #endregion - + /// /// Executes a device switch using objects @@ -450,7 +468,7 @@ namespace PepperDash_Essentials_DM.Chassis } - #endregion + #endregion #region Factory @@ -508,26 +526,18 @@ namespace PepperDash_Essentials_DM.Chassis #endregion + } - // TODO [ ] Implement CEC control - // return _chassis.HdmiDmLiteOutputs[0].DmLiteOutput.DmLiteOutputPort.StreamCec; - public Cec StreamCec + + public class StreamCecWrapper : IKeyed, ICec + { + public string Key { get; private set; } + public Cec StreamCec { get; private set; } + + public StreamCecWrapper(string key, Cec streamCec) { - get - { - return _chassis.NumberOfOutputs == 1 - //? _chassis.HdmiDmLiteOutputs[0].DmLiteOutput.DmLiteOutputPort.StreamCec - ? _chassis.HdmiDmLiteOutputs[0].HdmiOutput.HdmiOutputPort.StreamCec - : null; - } + Key = key; + StreamCec = streamCec; } - - public IntFeedback HdmiInHdcpStateFeedback { get; private set; } - public void SetHdmiInHdcpState(eHdcpCapabilityType hdcpState) - { - throw new NotImplementedException(); - } - - public eHdcpCapabilityType HdmiInHdcpCapability { get; private set; } } } \ No newline at end of file From 1aa95905872d5007f11ed7c55ba33184c30fa63c Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 12 Sep 2023 13:23:18 -0500 Subject: [PATCH 31/50] feature: adds DmInputChange event --- .../Essentials_DM/Chassis/HdPsXxxController.cs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index c7ef719c..1c6f8781 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -38,6 +38,7 @@ namespace PepperDash_Essentials_DM.Chassis public BoolFeedback AutoRouteFeedback { get; private set; } public event EventHandler NumericSwitchChange; + public event EventHandler DmInputChange; /// /// Constructor @@ -425,6 +426,8 @@ namespace PepperDash_Essentials_DM.Chassis break; } } + + OnDmInputChange(args); } @@ -457,16 +460,20 @@ namespace PepperDash_Essentials_DM.Chassis } - /// - /// Raise an event when the status of a switch object changes. - /// - /// Argumetns defined as IKeyName sender, output, input, & eRoutingSignalType + // Raise an event when the status of a switch object changes. private void OnSwitchChange(RoutingNumericEventArgs args) { var newEvent = NumericSwitchChange; if (newEvent != null) newEvent(this, args); } + // Raise an event when the DM input changes. + private void OnDmInputChange(DMInputEventArgs args) + { + var newEvent = DmInputChange; + if (newEvent != null) newEvent(this, args); + } + #endregion From 2afa9df705ffb5d6e473861968da0e886825253b Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 12 Sep 2023 14:08:20 -0500 Subject: [PATCH 32/50] fix: removes HdPsXxx controller, propertiesConfig and join map --- PepperDashEssentials/ControlSystem.cs | 49 +- .../JoinMaps/HdPsXxxControllerJoinMap.cs | 190 ----- .../PepperDash_Essentials_Core.csproj | 1 - .../Chassis/HdPsXxxController.cs | 657 ------------------ .../Config/HdPsXxxPropertiesConfig.cs | 30 - .../PepperDash_Essentials_DM.csproj | 2 - 6 files changed, 28 insertions(+), 901 deletions(-) delete mode 100644 essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/HdPsXxxControllerJoinMap.cs delete mode 100644 essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs delete mode 100644 essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs diff --git a/PepperDashEssentials/ControlSystem.cs b/PepperDashEssentials/ControlSystem.cs index 0ebfd927..1bafbbac 100644 --- a/PepperDashEssentials/ControlSystem.cs +++ b/PepperDashEssentials/ControlSystem.cs @@ -392,45 +392,51 @@ namespace PepperDash.Essentials { Debug.Console(2, "Adding DmpsRoutingController for {0} to Device Manager.", this.ControllerPrompt); - var propertiesConfig = JsonConvert.DeserializeObject(devConf.Properties.ToString()) ?? - new DM.Config.DmpsRoutingPropertiesConfig(); + var propertiesConfig = JsonConvert.DeserializeObject(devConf.Properties.ToString()); - DeviceManager.AddDevice(DmpsRoutingController.GetDmpsRoutingController("processor-avRouting", this.ControllerPrompt, propertiesConfig)); + if(propertiesConfig == null) + propertiesConfig = new DM.Config.DmpsRoutingPropertiesConfig(); + + DeviceManager.AddDevice(DmpsRoutingController.GetDmpsRoutingController("processor-avRouting", this.ControllerPrompt, propertiesConfig)); } else if (this.ControllerPrompt.IndexOf("mpc3", StringComparison.OrdinalIgnoreCase) > -1) { - Debug.Console(2, "MPC3 processor type detected. Adding Mpc3TouchpanelController."); + Debug.Console(2, "MPC3 processor type detected. Adding Mpc3TouchpanelController."); - var butToken = devConf.Properties["buttons"]; - if (butToken == null) - { - Debug.Console(0, Debug.ErrorLogLevel.Error, - "Error: Unable to deserialize buttons collection for device: {0}", devConf.Key); + var butToken = devConf.Properties["buttons"]; + if (butToken == null) + { + Debug.Console(0, Debug.ErrorLogLevel.Error, + "Error: Unable to deserialize buttons collection for device: {0}", devConf.Key); continue; - } - - var buttons = butToken.ToObject>(); - var tpController = new Core.Touchpanels.Mpc3TouchpanelController( - string.Format("{0}-keypadButtons", devConf.Key), devConf.Name, Global.ControlSystem, buttons); + } - DeviceManager.AddDevice(tpController); + var buttons = butToken.ToObject>(); + var tpController = new Core.Touchpanels.Mpc3TouchpanelController( + string.Format("{0}-keypadButtons", devConf.Key), devConf.Name, Global.ControlSystem, buttons); + + DeviceManager.AddDevice(tpController); } else { Debug.Console(2, "************Processor is not DMPS type***************"); } + + continue; } // Try local factories first - var newDev = null ?? PepperDash.Essentials.Core.DeviceFactory.GetDevice(devConf); + IKeyed newDev = null; - if (newDev == null) - Debug.Console(0, Debug.ErrorLogLevel.Error, "ERROR: Cannot load unknown device type '{0}', key '{1}'.", - devConf.Type, devConf.Key); - else - DeviceManager.AddDevice(newDev); + if (newDev == null) + newDev = PepperDash.Essentials.Core.DeviceFactory.GetDevice(devConf); + + if (newDev != null) + DeviceManager.AddDevice(newDev); + else + Debug.Console(0, Debug.ErrorLogLevel.Error, "ERROR: Cannot load unknown device type '{0}', key '{1}'.", devConf.Type, devConf.Key); } catch (Exception e) { @@ -438,6 +444,7 @@ namespace PepperDash.Essentials } } Debug.Console(0, Debug.ErrorLogLevel.Notice, "All Devices Loaded."); + } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/HdPsXxxControllerJoinMap.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/HdPsXxxControllerJoinMap.cs deleted file mode 100644 index 3f2901c9..00000000 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Bridges/JoinMaps/HdPsXxxControllerJoinMap.cs +++ /dev/null @@ -1,190 +0,0 @@ -using System; -using PepperDash.Essentials.Core; - -namespace PepperDash_Essentials_Core.Bridges -{ - public class HdPsXxxControllerJoinMap : JoinMapBaseAdvanced - { - - #region Digital - - [JoinName("EnableAutoRoute")] - public JoinDataComplete EnableAutoRoute = new JoinDataComplete( - new JoinData - { - JoinNumber = 1, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Enable Automatic Routing on Xx1 Switchers", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - - [JoinName("InputSync")] - public JoinDataComplete InputSync = new JoinDataComplete( - new JoinData - { - JoinNumber = 2, - JoinSpan = 8 - }, - new JoinMetadata - { - Description = "Device Input Sync", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - - [JoinName("EnableInputHdcp")] - public JoinDataComplete EnableInputHdcp = new JoinDataComplete( - new JoinData - { - JoinNumber = 11, - JoinSpan = 8 - }, - new JoinMetadata - { - Description = "Device Enable Input Hdcp", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - - [JoinName("DisableInputHdcp")] - public JoinDataComplete DisableInputHdcp = new JoinDataComplete( - new JoinData - { - JoinNumber = 21, - JoinSpan = 8 - }, - new JoinMetadata - { - Description = "Device Disnable Input Hdcp", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Digital - }); - - - [JoinName("IsOnline")] - public JoinDataComplete IsOnline = new JoinDataComplete( - new JoinData - { - JoinNumber = 30, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Device Onlne", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Digital - }); - - #endregion - - - #region Analog - - [JoinName("OutputRoute")] - public JoinDataComplete OutputRoute = new JoinDataComplete( - new JoinData - { - JoinNumber = 11, - JoinSpan = 2 - }, - new JoinMetadata - { - Description = "Device Output Route Set/Get", - JoinCapabilities = eJoinCapabilities.ToFromSIMPL, - JoinType = eJoinType.Analog - }); - - #endregion - - - #region Serial - - [JoinName("Name")] - public JoinDataComplete Name = new JoinDataComplete( - new JoinData - { - JoinNumber = 1, - JoinSpan = 1 - }, - new JoinMetadata - { - Description = "Device Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - - [JoinName("InputName")] - public JoinDataComplete InputName = new JoinDataComplete( - new JoinData - { - JoinNumber = 2, - JoinSpan = 8 - }, - new JoinMetadata - { - Description = "Device Input Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - - [JoinName("OutputName")] - public JoinDataComplete OutputName = new JoinDataComplete( - new JoinData - { - JoinNumber = 11, - JoinSpan = 2 - }, - new JoinMetadata - { - Description = "Device Output Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - - [JoinName("OutputRoutedName")] - public JoinDataComplete OutputRoutedName = new JoinDataComplete( - new JoinData - { - JoinNumber = 16, - JoinSpan = 2 - }, - new JoinMetadata - { - Description = "Device Output Route Name", - JoinCapabilities = eJoinCapabilities.ToSIMPL, - JoinType = eJoinType.Serial - }); - - - #endregion - - /// - /// Constructor to use when instantiating this join map without inheriting from it - /// - /// Join this join map will start at - public HdPsXxxControllerJoinMap(uint joinStart) - : this(joinStart, typeof(HdPsXxxControllerJoinMap)) - { - } - - /// - /// Constructor to use when extending this Join map - /// - /// Join this join map will start at - /// Type of the child join map - protected HdPsXxxControllerJoinMap(uint joinStart, Type type) - : base(joinStart, type) - { - } - } -} \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj index 0d9aa9bc..75d4626d 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/PepperDash_Essentials_Core.csproj @@ -127,7 +127,6 @@ - diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs deleted file mode 100644 index d923949e..00000000 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ /dev/null @@ -1,657 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Crestron.SimplSharp; -using Crestron.SimplSharpPro; -using Crestron.SimplSharpPro.DeviceSupport; -using Crestron.SimplSharpPro.DM; -using Newtonsoft.Json; -using PepperDash.Core; -using PepperDash.Essentials.Core; -using PepperDash.Essentials.Core.Bridges; -using PepperDash.Essentials.Core.Config; -using PepperDash_Essentials_Core.Bridges; -using PepperDash_Essentials_DM.Config; - -namespace PepperDash_Essentials_DM.Chassis -{ - [Description("Wrapper class for all HdPsXxx switchers")] - public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IHasFeedback - { - - private readonly HdPsXxx _chassis; - private readonly HdPs401 _chassis401; - private readonly HdPs621 _chassis621; - - public RoutingPortCollection InputPorts { get; private set; } - public RoutingPortCollection OutputPorts { get; private set; } - - public Dictionary InputNames { get; set; } - public Dictionary OutputNames { get; set; } - - public FeedbackCollection InputNameFeedbacks { get; private set; } - public FeedbackCollection InputHdcpEnableFeedback { get; private set; } - - public FeedbackCollection OutputNameFeedbacks { get; private set; } - public FeedbackCollection OutputRouteNameFeedback { get; private set; } - - public FeedbackCollection VideoInputSyncFeedbacks { get; private set; } - public FeedbackCollection VideoOutputRouteFeedbacks { get; private set; } - - public StringFeedback DeviceNameFeedback { get; private set; } - public BoolFeedback AutoRouteFeedback { get; private set; } - - public event EventHandler NumericSwitchChange; - - /// - /// Constructor - /// - /// - /// - /// HdPs401 device instance - /// - public HdPsXxxController(string key, string name, HdPsXxx chassis, HdPsXxxPropertiesConfig props) - : base(key, name, chassis) - { - _chassis = chassis; - Name = name; - - if (props == null) - { - Debug.Console(1, this, "HdPsXxxController properties are null, failed to build device"); - return; - } - - InputPorts = new RoutingPortCollection(); - InputNameFeedbacks = new FeedbackCollection(); - InputHdcpEnableFeedback = new FeedbackCollection(); - InputNames = new Dictionary(); - //InputNames = props.Inputs; - - OutputPorts = new RoutingPortCollection(); - OutputNameFeedbacks = new FeedbackCollection(); - OutputRouteNameFeedback = new FeedbackCollection(); - OutputNames = new Dictionary(); - //OutputNames = props.Outputs; - - VideoInputSyncFeedbacks = new FeedbackCollection(); - VideoOutputRouteFeedbacks = new FeedbackCollection(); - - if (_chassis.NumberOfOutputs == 1) - { - if (_chassis is HdPs401) - _chassis401 = _chassis as HdPs401; - if (_chassis is HdPs621) - _chassis621 = _chassis as HdPs621; - - AutoRouteFeedback = new BoolFeedback(() => _chassis401.PriorityRouteOnFeedback.BoolValue); - } - - SetupInputs(props.Inputs); - SetupOutputs(props.Outputs); - - AddPostActivationAction(AddFeedbackCollecitons); - } - - // input setup - private void SetupInputs(Dictionary dict) - { - if (dict == null) - { - Debug.Console(1, this, "Failed to setup inputs, properties are null"); - return; - } - foreach (var kvp in dict) - { - Debug.Console(1, this, "props.Input[{0}]: {1}", kvp.Key, kvp.Value); - } - InputNames = dict; - - for (uint i = 1; i <= _chassis.NumberOfInputs; i++) - { - var index = i; - var name = string.IsNullOrEmpty(InputNames[index]) ? string.Format("Input {0}", index) : InputNames[index]; - var input = _chassis.Inputs[index]; - var hdmiInput = _chassis.HdmiInputs[index]; - var dmLiteInput = _chassis.DmLiteInputs[index]; - - InputNameFeedbacks.Add(new StringFeedback(name, () => InputNames[index])); - - // TODO [ ] verify which input type is needed - input.Name.StringValue = name; - hdmiInput.Name.StringValue = name; - dmLiteInput.Name.StringValue = name; - - var port = new RoutingInputPort(name, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) - { - FeedbackMatchObject = input - }; - InputPorts.Add(port); - - InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => hdmiInput.InputPort.HdcpSupportOnFeedback.BoolValue)); - - VideoInputSyncFeedbacks.Add(new BoolFeedback(name, () => input.VideoDetectedFeedback.BoolValue)); - } - - _chassis.DMInputChange += _chassis_InputChange; - } - - // output setup - private void SetupOutputs(Dictionary dict) - { - if (dict == null) - { - Debug.Console(1, this, "Failed to setup outputs, properties are null"); - return; - } - foreach (var kvp in dict) - { - Debug.Console(1, this, "props.Output[{0}]: {1}", kvp.Key, kvp.Value); - } - OutputNames = dict; - - for (uint i = 1; i <= _chassis.NumberOfOutputs; i++) - { - var index = i; - var name = string.IsNullOrEmpty(OutputNames[index]) ? string.Format("Output {0}", index) : OutputNames[index]; - var output = _chassis.Outputs[index]; - var hdmiDmLiteOutput = _chassis.HdmiDmLiteOutputs[index]; - - OutputNameFeedbacks.Add(new StringFeedback(name, () => OutputNames[index])); - - // TODO [ ] verify which output type is needed - output.Name.StringValue = name; - hdmiDmLiteOutput.Name.StringValue = name; - - var port = new RoutingOutputPort(name, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, output, this) - { - FeedbackMatchObject = output - }; - OutputPorts.Add(port); - - OutputRouteNameFeedback.Add(new StringFeedback(name, () => output.VideoOutFeedback.NameFeedback.StringValue)); - - VideoOutputRouteFeedbacks.Add(new IntFeedback(name, () => output.VideoOutFeedback == null ? 0 : (int)output.VideoOutFeedback.Number)); - } - - _chassis.DMOutputChange += _chassis_OutputChange; - } - - - #region BridgeLinking - - /// - /// Link device to API - /// - /// - /// - /// - /// - public override void LinkToApi(BasicTriList trilist, uint joinStart, string joinMapKey, EiscApiAdvanced bridge) - { - var joinMap = new HdPsXxxControllerJoinMap(joinStart); - - if (bridge != null) - { - bridge.AddJoinMap(Key, joinMap); - } - else - { - Debug.Console(0, this, "Please update config to use 'eiscApiAdvanced' to get all join map features for this device"); - } - - IsOnline.LinkInputSig(trilist.BooleanInput[joinMap.IsOnline.JoinNumber]); - DeviceNameFeedback.LinkInputSig(trilist.StringInput[joinMap.Name.JoinNumber]); - - _chassis.OnlineStatusChange += _chassis_OnlineStatusChange; - - if (_chassis401 != null) LinkChassis401ToApi(trilist, joinMap); - - if (_chassis621 != null) LinkChassis621ToApi(trilist, joinMap); - - LinkChassisInputsToApi(trilist, joinMap); - LinkChassisOutputsToApi(trilist, joinMap); - - trilist.OnlineStatusChange += (sender, args) => - { - if (!args.DeviceOnLine) return; - }; - } - - - // links inputs to API - private void LinkChassisInputsToApi(BasicTriList trilist, HdPsXxxControllerJoinMap joinMap) - { - for (uint i = 1; i <= _chassis.NumberOfInputs; i++) - { - var input = i; - var inputName = InputNames[input]; - var indexWithOffset = input - 1; - - trilist.SetSigTrueAction(joinMap.EnableInputHdcp.JoinNumber + indexWithOffset, () => EnableHdcp(input)); - trilist.SetSigTrueAction(joinMap.DisableInputHdcp.JoinNumber + indexWithOffset, () => DisableHdcp(input)); - - InputHdcpEnableFeedback[inputName].LinkInputSig(trilist.BooleanInput[joinMap.EnableInputHdcp.JoinNumber + indexWithOffset]); - InputHdcpEnableFeedback[inputName].LinkComplementInputSig(trilist.BooleanInput[joinMap.EnableInputHdcp.JoinNumber + indexWithOffset]); - - VideoInputSyncFeedbacks[inputName].LinkInputSig(trilist.BooleanInput[joinMap.InputSync.JoinNumber + indexWithOffset]); - - InputNameFeedbacks[inputName].LinkInputSig(trilist.StringInput[joinMap.InputName.JoinNumber + indexWithOffset]); - } - } - - - // links outputs to API - private void LinkChassisOutputsToApi(BasicTriList trilist, HdPsXxxControllerJoinMap joinMap) - { - for (uint i = 1; i <= _chassis.NumberOfOutputs; i++) - { - var output = i; - var outputName = OutputNames[output]; - var indexWithOffset = output - 1; - - trilist.SetUShortSigAction(joinMap.OutputRoute.JoinNumber + indexWithOffset, (a) => - ExecuteNumericSwitch(a, (ushort) output, eRoutingSignalType.AudioVideo)); - - OutputNameFeedbacks[outputName].LinkInputSig(trilist.StringInput[joinMap.OutputName.JoinNumber + indexWithOffset]); - OutputRouteNameFeedback[outputName].LinkInputSig(trilist.StringInput[joinMap.OutputRoutedName.JoinNumber + indexWithOffset]); - - VideoOutputRouteFeedbacks[outputName].LinkInputSig(trilist.UShortInput[joinMap.OutputRoute.JoinNumber + indexWithOffset]); - } - } - - - // links HdPs401 chassis to API - private void LinkChassis401ToApi(BasicTriList trilist, HdPsXxxControllerJoinMap joinMap) - { - trilist.SetSigTrueAction(joinMap.EnableAutoRoute.JoinNumber, () => _chassis401.AutoRouteOn()); - trilist.SetSigFalseAction(joinMap.EnableAutoRoute.JoinNumber, () => _chassis401.AutoRouteOff()); - - AutoRouteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableAutoRoute.JoinNumber]); - } - - - // links HdPs621 chassis to API - private void LinkChassis621ToApi(BasicTriList trilist, HdPsXxxControllerJoinMap joinMap) - { - trilist.SetSigTrueAction(joinMap.EnableAutoRoute.JoinNumber, () => _chassis621.AutoRouteOn()); - trilist.SetSigFalseAction(joinMap.EnableAutoRoute.JoinNumber, () => _chassis621.AutoRouteOff()); - - AutoRouteFeedback.LinkInputSig(trilist.BooleanInput[joinMap.EnableAutoRoute.JoinNumber]); - } - - - #endregion - - - /// - /// Executes a device switch using objects - /// - /// - /// - /// - public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) - { - var input = inputSelector as HdPsXxxHdmiInput; - var output = outputSelector as HdPsXxxHdmiOutput; - - Debug.Console(2, this, "ExecuteSwitch: input={0}, output={1}", input, output); - - if (output == null) - { - Debug.Console(0, this, "Unable to make switch, output selector is not HdPsXxxHdmiOutput"); - return; - } - - // TODO [ ] Validate if sending the same input toggles the switch - var current = output.VideoOut; - if (current != input) - output.VideoOut = input; - } - - - /// - /// Executes a device switch using numeric values - /// - /// - /// - /// - public void ExecuteNumericSwitch(ushort inputSelector, ushort outputSelector, eRoutingSignalType signalType) - { - var input = inputSelector == 0 ? null : _chassis.Inputs[inputSelector]; - var output = _chassis.Outputs[outputSelector]; - - Debug.Console(2, this, "ExecuteNumericSwitch: input={0}, output={1}", input, output); - - ExecuteSwitch(input, output, signalType); - } - - - /// - /// Enables Hdcp on the provided port - /// - /// - public void EnableHdcp(uint port) - { - if (port <= 0 || port > _chassis.NumberOfInputs) return; - - _chassis.HdmiInputs[port].InputPort.HdcpSupportOn(); - InputHdcpEnableFeedback[InputNames[port]].FireUpdate(); - } - - - /// - /// Disables Hdcp on the provided port - /// - /// - public void DisableHdcp(uint port) - { - if (port <= 0 || port > _chassis.NumberOfInputs) return; - - _chassis.HdmiInputs[port].InputPort.HdcpSupportOff(); - InputHdcpEnableFeedback[InputNames[port]].FireUpdate(); - } - - - /// - /// Enables switcher auto route - /// - public void EnableAutoRoute() - { - if (_chassis.NumberOfInputs != 1) return; - - if (_chassis401 != null) - { - _chassis401.AutoRouteOn(); - } - - if (_chassis621 != null) - { - _chassis621.AutoRouteOn(); - } - } - - - /// - /// Disables switcher auto route - /// - public void DisableAutoRoute() - { - if (_chassis.NumberOfInputs != 1) return; - - if (_chassis401 != null) - { - _chassis401.AutoRouteOff(); - } - - if (_chassis621 != null) - { - _chassis621.AutoRouteOff(); - } - } - - #region Events - - - // _chassis online/offline event - private void _chassis_OnlineStatusChange(GenericBase currentDevice, - OnlineOfflineEventArgs args) - { - IsOnline.FireUpdate(); - - if (!args.DeviceOnLine) return; - - foreach (var feedback in Feedbacks) - { - feedback.FireUpdate(); - } - } - - - // _chassis input change event - private void _chassis_InputChange(Switch device, DMInputEventArgs args) - { - var eventId = args.EventId; - - switch (eventId) - { - case DMInputEventIds.VideoDetectedEventId: - { - Debug.Console(1, this, "Event ID {0}: Updating VideoInputSyncFeedbacks", eventId); - foreach (var item in VideoInputSyncFeedbacks) - { - item.FireUpdate(); - } - break; - } - case DMInputEventIds.InputNameFeedbackEventId: - case DMInputEventIds.InputNameEventId: - case DMInputEventIds.NameFeedbackEventId: - { - Debug.Console(1, this, "Event ID {0}: Updating name feedbacks", eventId); - - var input = args.Number; - var name = _chassis.HdmiInputs[input].NameFeedback.StringValue; - - Debug.Console(1, this, "Input {0} Name {1}", input, name); - break; - } - default: - { - Debug.Console(1, this, "Uhandled DM Input Event ID {0}", eventId); - break; - } - } - } - - - // _chassis output change event - private void _chassis_OutputChange(Switch device, DMOutputEventArgs args) - { - if (args.EventId != DMOutputEventIds.VideoOutEventId) return; - - var output = args.Number; - - var input = _chassis.HdmiDmLiteOutputs[output].VideoOutFeedback == null - ? 0 - : _chassis.HdmiDmLiteOutputs[output].VideoOutFeedback.Number; - - var outputName = OutputNames[output]; - - var feedback = VideoOutputRouteFeedbacks[outputName]; - if (feedback == null) return; - - var inputPort = InputPorts.FirstOrDefault( - p => p.FeedbackMatchObject == _chassis.HdmiDmLiteOutputs[output].VideoOutFeedback); - - var outputPort = OutputPorts.FirstOrDefault( - p => p.FeedbackMatchObject == _chassis.HdmiDmLiteOutputs[output]); - - feedback.FireUpdate(); - - OnSwitchChange(new RoutingNumericEventArgs( - output, input, outputPort, inputPort, eRoutingSignalType.AudioVideo)); - } - - - /// - /// Raise an event when the status of a switch object changes. - /// - /// Argumetns defined as IKeyName sender, output, input, & eRoutingSignalType - private void OnSwitchChange(RoutingNumericEventArgs args) - { - var newEvent = NumericSwitchChange; - if (newEvent != null) newEvent(this, args); - } - - - #endregion - - - #region FeedbacksAndFeedbackCollections - - - /// - /// Add feedback colleciton arrays to feedback collections - /// - /// BoolFeedback[] arrays - public void AddCollectionsToList(params FeedbackCollection[] feedbackCollections) - { - foreach (var item in feedbackCollections.SelectMany(feedbackCollection => feedbackCollections)) - { - AddCollectionsToList(item); - } - } - - - /// - /// Add feedback colleciton arrays to feedback collections - /// - /// IntFeedback[] arrays - public void AddCollectionsToList(params FeedbackCollection[] feedbackCollections) - { - foreach (var item in feedbackCollections.SelectMany(feedbackCollection => feedbackCollections)) - { - AddCollectionsToList(item); - } - } - - - /// - /// Add feedback colleciton arrays to feedback collections - /// - /// StringFeedback[] arrays - public void AddCollectionsToList(params FeedbackCollection[] feedbackCollections) - { - foreach (var item in feedbackCollections.SelectMany(feedbackCollection => feedbackCollections)) - { - AddCollectionsToList(item); - } - } - - - /// - /// Adds feedback colleciton to feedback collections - /// - /// BoolFeedback - public void AddCollectionToList(FeedbackCollection feedbackCollection) - { - foreach (var item in feedbackCollection.Where(item => item != null)) - { - AddFeedbackToList(item); - } - } - - - /// - /// Adds feedback colleciton to feedback collections - /// - /// IntFeedback - public void AddCollectionToList(FeedbackCollection feedbackCollection) - { - foreach (var item in feedbackCollection.Where(item => item != null)) - { - AddFeedbackToList(item); - } - } - - - /// - /// Adds feedback colleciton to feedback collections - /// - /// StringFeedback - public void AddCollectionToList(FeedbackCollection feedbackCollection) - { - foreach (var item in feedbackCollection.Where(item => item != null)) - { - AddFeedbackToList(item); - } - } - - - /// - /// Adds individual feedbacks to feedback collection - /// - /// Feedback - public void AddFeedbackToList(PepperDash.Essentials.Core.Feedback fb) - { - if (fb == null || Feedbacks.Contains(fb)) return; - - Feedbacks.Add(fb); - } - - - /// - /// Adds provided feedbacks to feedback collection list - /// - public void AddFeedbackCollecitons() - { - AddFeedbackToList(DeviceNameFeedback); - AddCollectionsToList(VideoInputSyncFeedbacks, InputHdcpEnableFeedback); - AddCollectionsToList(VideoOutputRouteFeedbacks); - AddCollectionsToList(InputNameFeedbacks, OutputNameFeedbacks, OutputRouteNameFeedback); - } - - - #endregion - - - #region Factory - - - public class HdSp401ControllerFactory : EssentialsDeviceFactory - { - public HdSp401ControllerFactory() - { - TypeNames = new List() { "hdps401", "hdps402", "hdps621", "hdps622" }; - } - public override EssentialsDevice BuildDevice(DeviceConfig dc) - { - Debug.Console(1, "Factory Attempting to create new HD-PSXxx device"); - - var props = JsonConvert.DeserializeObject(dc.Properties.ToString()); - if (props == null) - { - Debug.Console(1, "Factory failed to create new HD-PSXxx device, properties config was null"); - return null; - } - - var key = dc.Key; - var name = dc.Name; - var type = dc.Type.ToLower(); - var control = props.Control; - var ipid = control.IpIdInt; - //var address = control.TcpSshProperties.Address; - - switch (type) - { - case ("hdps401"): - { - return new HdPsXxxController(key, name, new HdPs401(ipid, Global.ControlSystem), props); - } - case ("hdps402"): - { - return new HdPsXxxController(key, name, new HdPs402(ipid, Global.ControlSystem), props); - } - case ("hdps621"): - { - return new HdPsXxxController(key, name, new HdPs621(ipid, Global.ControlSystem), props); - } - case ("hdps622"): - { - return new HdPsXxxController(key, name, new HdPs622(ipid, Global.ControlSystem), props); - } - default: - { - Debug.Console(1, "Factory failed to create new {0} device", type); - return null; - } - } - } - } - - - #endregion - } -} \ No newline at end of file diff --git a/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs b/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs deleted file mode 100644 index c02fc511..00000000 --- a/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Collections.Generic; -using Newtonsoft.Json; -using PepperDash.Core; -using PepperDash.Essentials.DM.Config; - -namespace PepperDash_Essentials_DM.Config -{ - public class HdPsXxxPropertiesConfig - { - [JsonProperty("control")] - public ControlPropertiesConfig Control { get; set; } - - [JsonProperty("inputs")] - //public Dictionary Inputs { get; set; } - public Dictionary Inputs { get; set; } - - [JsonProperty("outputs")] - //public Dictionary Outputs { get; set; } - public Dictionary Outputs { get; set; } - - public HdPsXxxPropertiesConfig() - { - //Inputs = new Dictionary(); - //Outputs = new Dictionary(); - - Inputs = new Dictionary(); - Outputs = new Dictionary(); - } - } -} \ No newline at end of file diff --git a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj index 0011c305..adfddbe3 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj +++ b/essentials-framework/Essentials DM/Essentials_DM/PepperDash_Essentials_DM.csproj @@ -104,8 +104,6 @@ - - From da5d2d74f29d7be3a02f9147399fe8fb3420f4f8 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 12 Sep 2023 14:36:17 -0500 Subject: [PATCH 33/50] fix: removes OutputPort.InputPriorities reference --- .../Essentials_DM/Chassis/HdPsXxxController.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 1c6f8781..7c1e0431 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -10,6 +10,7 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; using PepperDash_Essentials_Core.Bridges; +using PepperDash_Essentials_DM; using PepperDash_Essentials_DM.Config; namespace PepperDash_Essentials_DM.Chassis @@ -173,12 +174,14 @@ namespace PepperDash_Essentials_DM.Chassis OutputRouteNameFeedback.Add(new StringFeedback(name, () => output.VideoOutFeedback.NameFeedback.StringValue)); - VideoOutputRouteFeedbacks.Add(new IntFeedback(name, () => output.VideoOutFeedback == null ? 0 : (int)output.VideoOutFeedback.Number)); + VideoOutputRouteFeedbacks.Add(new IntFeedback(name, + () => output.VideoOutFeedback == null ? 0 : (int) output.VideoOutFeedback.Number)); // TODO [ ] Investigate setting input priorities per output // {{in1-priority-level}, {in2-priority-level}, .... {in6-priority-level}} - // default priority level input 1-4 ascending - output.OutputPort.InputPriorities(new byte[] { 1, 2, 3, 4 }); + // default priority level input 1-4 ascending + //var priorities = new byte[] {1,2,3,4}; + //output.OutputPort.InputPriorities(priorities); if (port.Port == null) continue; From 189c4706030e4d5cf8c1de496aee94130ef00b02 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 12 Sep 2023 17:10:25 -0500 Subject: [PATCH 34/50] feature(wip): adds inputPriorities configuration property --- .../Chassis/HdPsXxxController.cs | 22 ++++++++++++++----- .../Config/HdPsXxxPropertiesConfig.cs | 12 +++++----- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 7c1e0431..2e998133 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -10,7 +10,6 @@ using PepperDash.Essentials.Core; using PepperDash.Essentials.Core.Bridges; using PepperDash.Essentials.Core.Config; using PepperDash_Essentials_Core.Bridges; -using PepperDash_Essentials_DM; using PepperDash_Essentials_DM.Config; namespace PepperDash_Essentials_DM.Chassis @@ -19,6 +18,7 @@ namespace PepperDash_Essentials_DM.Chassis public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback { private readonly HdPsXxx _chassis; + private byte[] _inputPriorityParams; public RoutingPortCollection InputPorts { get; private set; } public RoutingPortCollection OutputPorts { get; private set; } @@ -76,6 +76,12 @@ namespace PepperDash_Essentials_DM.Chassis if (_chassis.NumberOfOutputs == 1) AutoRouteFeedback = new BoolFeedback(() => _chassis.PriorityRouteOnFeedback.BoolValue); + if (props.InputPriorities != null) + { + _inputPriorityParams = new byte[_chassis.NumberOfInputs]; + _inputPriorityParams = GetInputPriorities(props); + } + InputNames = props.Inputs; SetupInputs(InputNames); @@ -83,6 +89,12 @@ namespace PepperDash_Essentials_DM.Chassis SetupOutputs(OutputNames); } + // get input priorities + private byte[] GetInputPriorities(HdPsXxxPropertiesConfig props) + { + throw new NotImplementedException(); + } + // input setup private void SetupInputs(Dictionary dict) { @@ -175,13 +187,13 @@ namespace PepperDash_Essentials_DM.Chassis OutputRouteNameFeedback.Add(new StringFeedback(name, () => output.VideoOutFeedback.NameFeedback.StringValue)); VideoOutputRouteFeedbacks.Add(new IntFeedback(name, - () => output.VideoOutFeedback == null ? 0 : (int) output.VideoOutFeedback.Number)); + () => output.VideoOutFeedback == null ? 0 : (int)output.VideoOutFeedback.Number)); // TODO [ ] Investigate setting input priorities per output // {{in1-priority-level}, {in2-priority-level}, .... {in6-priority-level}} - // default priority level input 1-4 ascending - //var priorities = new byte[] {1,2,3,4}; - //output.OutputPort.InputPriorities(priorities); + // default priority level input 1-4 ascending + if (_inputPriorityParams != null && _inputPriorityParams.Count() > 0) + output.OutputPort.InputPriorities(_inputPriorityParams); if (port.Port == null) continue; diff --git a/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs b/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs index c02fc511..576b74f0 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Config/HdPsXxxPropertiesConfig.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using Newtonsoft.Json; using PepperDash.Core; -using PepperDash.Essentials.DM.Config; namespace PepperDash_Essentials_DM.Config { @@ -11,18 +10,17 @@ namespace PepperDash_Essentials_DM.Config public ControlPropertiesConfig Control { get; set; } [JsonProperty("inputs")] - //public Dictionary Inputs { get; set; } public Dictionary Inputs { get; set; } - + [JsonProperty("outputs")] - //public Dictionary Outputs { get; set; } public Dictionary Outputs { get; set; } + // "inputPriorities": "1,4,3,2" + [JsonProperty("inputPriorities")] + public string InputPriorities { get; set; } + public HdPsXxxPropertiesConfig() { - //Inputs = new Dictionary(); - //Outputs = new Dictionary(); - Inputs = new Dictionary(); Outputs = new Dictionary(); } From e590c7cedb251cf4b324b4e4a43bd49afaf0c85b Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 12 Sep 2023 19:26:55 -0500 Subject: [PATCH 35/50] feature(wip): adds inputPriorities configuration property --- .../Essentials_DM/Chassis/HdPsXxxController.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 2e998133..bba85d25 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -18,7 +18,7 @@ namespace PepperDash_Essentials_DM.Chassis public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback { private readonly HdPsXxx _chassis; - private byte[] _inputPriorityParams; + //private byte[] _inputPriorityParams; public RoutingPortCollection InputPorts { get; private set; } public RoutingPortCollection OutputPorts { get; private set; } @@ -76,11 +76,11 @@ namespace PepperDash_Essentials_DM.Chassis if (_chassis.NumberOfOutputs == 1) AutoRouteFeedback = new BoolFeedback(() => _chassis.PriorityRouteOnFeedback.BoolValue); - if (props.InputPriorities != null) - { - _inputPriorityParams = new byte[_chassis.NumberOfInputs]; - _inputPriorityParams = GetInputPriorities(props); - } + //if (props.InputPriorities != null) + //{ + // _inputPriorityParams = new byte[_chassis.NumberOfInputs]; + // _inputPriorityParams = GetInputPriorities(props); + //} InputNames = props.Inputs; SetupInputs(InputNames); @@ -192,8 +192,8 @@ namespace PepperDash_Essentials_DM.Chassis // TODO [ ] Investigate setting input priorities per output // {{in1-priority-level}, {in2-priority-level}, .... {in6-priority-level}} // default priority level input 1-4 ascending - if (_inputPriorityParams != null && _inputPriorityParams.Count() > 0) - output.OutputPort.InputPriorities(_inputPriorityParams); + //if (_inputPriorityParams != null && _inputPriorityParams.Count() > 0) + // output.OutputPort.InputPriorities(_inputPriorityParams); if (port.Port == null) continue; From 334a62c32943d80337f9a382fe934a4af337662b Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 13 Sep 2023 08:32:07 -0500 Subject: [PATCH 36/50] fix: wraps GetDeviceForKey and GetFeedbackProperty methods in a try/catch --- .../Touchpanels/Mpc3Touchpanel.cs | 73 ++++++++++++------- 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs index f4611a70..f1153879 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Globalization; using Crestron.SimplSharpPro; using Newtonsoft.Json; @@ -27,6 +28,7 @@ namespace PepperDash.Essentials.Core.Touchpanels } _touchpanel.ButtonStateChange += _touchpanel_ButtonStateChange; + _buttons = buttons; if (_buttons == null) { @@ -55,6 +57,8 @@ namespace PepperDash.Essentials.Core.Touchpanels /// public void InitializeButton(string key, KeypadButton config) { + Debug.Console(1, this, "Initializing button '{0}'...", key); + if (config == null) { Debug.Console(1, this, "Button '{0}' config is null, unable to initialize", key); @@ -131,6 +135,8 @@ namespace PepperDash.Essentials.Core.Touchpanels /// public void InitializeButtonFeedback(string key, KeypadButton config) { + Debug.Console(1, this, "Initializing button '{0}' feedback...", key); + if (config == null) { Debug.Console(1, this, "Button '{0}' config is null, unable to initialize feedback", key); @@ -144,37 +150,54 @@ namespace PepperDash.Essentials.Core.Touchpanels var buttonFeedback = config.Feedback; if (buttonFeedback == null) { - Debug.Console(1, this, "Button '{0}' feedback not configured and will not be implemented. Verify feedback is configured if required.", key); + Debug.Console(1, this, "Button '{0}' feedback not configured and will not be implemented. If feedback is required, verify configuration.", + key); return; } - var device = DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) as Device; - if (device == null) + Feedback deviceFeedback = null; + + try { - Debug.Console(1, this, "Button '{0}' feedback device with key '{0}' not found, feedback will not be implemented. Verify feedback deviceKey is properly configured.", - buttonFeedback.DeviceKey); + var device = DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) as Device; + if (device == null) + { + Debug.Console(1, this, "Button '{0}' feedback with deviceKey '{1}' not found, feedback will not be implemented. Verify feedback deviceKey is properly configured.", + key, buttonFeedback.DeviceKey); + return; + } + + // TODO [ ] verify if this can replace the current method + deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); + //Debug.Console(0, this, "deviceFeedback.GetType().Name: '{0}'", deviceFeedback.GetType().Name); + //switch (feedback.GetType().Name.ToLower()) + //{ + // case("boolfeedback"): + // { + // break; + // } + // case("intfeedback"): + // { + // break; + // } + // case("stringfeedback"): + // { + // break; + // } + //} + } + catch (Exception ex) + { + Debug.Console(0, this, "Failed to initialize button '{0}' feedback with deviceKey '{1}'. If feedback is required, verify configuration.", + key, buttonFeedback.DeviceKey); + + Debug.Console(1, this, "InitializeButtonFeedback Exception Message: {0}", ex.Message); + Debug.Console(2, this, "InitializeButtonFeedback Exception StackTrace: {0}", ex.StackTrace); + if (ex.InnerException != null) Debug.Console(2, this, "InitializeButtonFeedback Exception InnerExceptioni: {0}", ex.InnerException); + return; } - // TODO [ ] verify if this can replace the current method - var deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); - Debug.Console(0, this, "deviceFeedback.GetType().Name: '{0}'", deviceFeedback.GetType().Name); - //switch (feedback.GetType().Name.ToLower()) - //{ - // case("boolfeedback"): - // { - // break; - // } - // case("intfeedback"): - // { - // break; - // } - // case("stringfeedback"): - // { - // break; - // } - //} - var boolFeedback = deviceFeedback as BoolFeedback; var intFeedback = deviceFeedback as IntFeedback; From 0fad667fabfc1fc5f1776cd6891c228254ed38e0 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 13 Sep 2023 08:56:13 -0500 Subject: [PATCH 37/50] fix: adds additional debug statements when attempting to get feedback property for device --- .../Touchpanels/Mpc3Touchpanel.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs index f1153879..296965f9 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs @@ -155,7 +155,7 @@ namespace PepperDash.Essentials.Core.Touchpanels return; } - Feedback deviceFeedback = null; + Feedback deviceFeedback; try { @@ -166,9 +166,16 @@ namespace PepperDash.Essentials.Core.Touchpanels key, buttonFeedback.DeviceKey); return; } + + deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); + if (deviceFeedback == null) + { + Debug.Console(1, this, "Button '{0}' feedback failed to get feedback property for '{1}', feedback will not be implemented. Verify feedback deviceKey is properly configured.", + key, buttonFeedback.FeedbackName); + return; + } // TODO [ ] verify if this can replace the current method - deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); //Debug.Console(0, this, "deviceFeedback.GetType().Name: '{0}'", deviceFeedback.GetType().Name); //switch (feedback.GetType().Name.ToLower()) //{ From 5a67a4060db2c715081f05cbb428218b919c9c76 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 13 Sep 2023 09:31:25 -0500 Subject: [PATCH 38/50] feat: adds routing sync provider interface and delegate --- .../PepperDashEssentialsBase/Routing/RoutingInterfaces.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs index 467bf045..e24480ff 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs @@ -204,4 +204,11 @@ namespace PepperDash.Essentials.Core SigType = sigType; } } + + public interface IRoutingSyncProvider + { + event RoutingSyncProviderDelegate SyncChanged; + } + + public delegate void RoutingSyncProviderDelegate(uint inputNumber, bool hasSync); } \ No newline at end of file From 8b6a9db7e0a04aac3868e8b31d4883f52de7dc6c Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 13 Sep 2023 09:32:44 -0500 Subject: [PATCH 39/50] refactor: refactors GetCecPort method --- .../Comm and IR/CommFactory.cs | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs index 9667b5b9..fd5fcfe2 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs @@ -117,39 +117,37 @@ namespace PepperDash.Essentials.Core { var dev = DeviceManager.GetDeviceForKey(config.ControlPortDevKey); - if (dev != null) - { - if (!String.IsNullOrEmpty(config.ControlPortName)) - { + Debug.Console(0, "GetCecPort: device '{0}' {1}", config.ControlPortDevKey, dev == null + ? "is not valid, failed to create build cec port" + : "found in device manager, attempting to build cec port"); - var inputPort = (dev as IRoutingInputsOutputs).InputPorts[config.ControlPortName]; + if (dev == null) + return null; - if (inputPort != null) - { - if (inputPort.Port is ICec) - return inputPort.Port as ICec; - } + if (String.IsNullOrEmpty(config.ControlPortName)) + { + Debug.Console(0, "GetCecPort: '{0}' - Configuration missing 'ControlPortName'", config.ControlPortDevKey); + return null; + } - var outputPort = (dev as IRoutingInputsOutputs).OutputPorts[config.ControlPortName]; + var inputPort = (dev as IRoutingInputsOutputs).InputPorts[config.ControlPortName]; + if (inputPort != null) + { + if (inputPort.Port is ICec) + return inputPort.Port as ICec; + } - if (outputPort != null) - { - if (outputPort.Port is ICec) - return outputPort.Port as ICec; - } + var outputPort = (dev as IRoutingInputsOutputs).OutputPorts[config.ControlPortName]; + if (outputPort != null) + { + if (outputPort.Port is ICec) + return outputPort.Port as ICec; + } - else - Debug.Console(0, "GetCecPort: Device '{0}' does not have a CEC port called: '{1}'", - config.ControlPortDevKey, config.ControlPortName); - } - else - { - Debug.Console(0, "GetCecPort: '{0}' - Configuration missing 'ControlPortName'", config.ControlPortDevKey); - } - } - Debug.Console(0, "GetCecPort: Device '{0}' is not a valid device.", config.ControlPortDevKey); + Debug.Console(0, "GetCecPort: Device '{0}' does not have a CEC port called: '{1}'", + config.ControlPortDevKey, config.ControlPortName); - return null; + return null; } /// From 9fb16f30b06ec392aa7194dbbacd2a7177c8520a Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 13 Sep 2023 10:02:20 -0500 Subject: [PATCH 40/50] refactor: Changes IRoutingHasSync interface - Changed IRoutingHasSync interface to IRoutingHasVideoInputSyncFeedbacks. - Remvoed IRoutingHasSynDelegate - Added interface to HdPsXxxController class --- .../PepperDashEssentialsBase/Routing/RoutingInterfaces.cs | 8 +++----- .../Essentials_DM/Chassis/HdPsXxxController.cs | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs index e24480ff..45245066 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/RoutingInterfaces.cs @@ -205,10 +205,8 @@ namespace PepperDash.Essentials.Core } } - public interface IRoutingSyncProvider + public interface IRoutingHasVideoInputSyncFeedbacks { - event RoutingSyncProviderDelegate SyncChanged; - } - - public delegate void RoutingSyncProviderDelegate(uint inputNumber, bool hasSync); + FeedbackCollection VideoInputSyncFeedbacks { get; } + } } \ No newline at end of file diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index bba85d25..1bf40083 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -15,7 +15,7 @@ using PepperDash_Essentials_DM.Config; namespace PepperDash_Essentials_DM.Chassis { [Description("Wrapper class for all HdPsXxx switchers")] - public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback + public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IRoutingHasVideoInputSyncFeedbacks { private readonly HdPsXxx _chassis; //private byte[] _inputPriorityParams; From 393033b6c9c4a80778e2c68c3921f97bc592db9d Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 13 Sep 2023 10:13:39 -0500 Subject: [PATCH 41/50] refactor: Updates HdPsXxxController class - Modifies `SetupInput()` and `SetupOutput()` - Renames `GetInputPriorities()` to `SetInputPriorities()` --- .../Chassis/HdPsXxxController.cs | 106 ++++++++---------- 1 file changed, 46 insertions(+), 60 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 1bf40083..705061d2 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using Crestron.SimplSharpPro; using Crestron.SimplSharpPro.DeviceSupport; @@ -18,7 +19,6 @@ namespace PepperDash_Essentials_DM.Chassis public class HdPsXxxController : CrestronGenericBridgeableBaseDevice, IRoutingNumericWithFeedback, IRoutingHasVideoInputSyncFeedbacks { private readonly HdPsXxx _chassis; - //private byte[] _inputPriorityParams; public RoutingPortCollection InputPorts { get; private set; } public RoutingPortCollection OutputPorts { get; private set; } @@ -41,6 +41,7 @@ namespace PepperDash_Essentials_DM.Chassis public event EventHandler NumericSwitchChange; public event EventHandler DmInputChange; + /// /// Constructor /// @@ -76,12 +77,6 @@ namespace PepperDash_Essentials_DM.Chassis if (_chassis.NumberOfOutputs == 1) AutoRouteFeedback = new BoolFeedback(() => _chassis.PriorityRouteOnFeedback.BoolValue); - //if (props.InputPriorities != null) - //{ - // _inputPriorityParams = new byte[_chassis.NumberOfInputs]; - // _inputPriorityParams = GetInputPriorities(props); - //} - InputNames = props.Inputs; SetupInputs(InputNames); @@ -90,7 +85,7 @@ namespace PepperDash_Essentials_DM.Chassis } // get input priorities - private byte[] GetInputPriorities(HdPsXxxPropertiesConfig props) + private byte[] SetInputPriorities(HdPsXxxPropertiesConfig props) { throw new NotImplementedException(); } @@ -103,52 +98,59 @@ namespace PepperDash_Essentials_DM.Chassis Debug.Console(1, this, "Failed to setup inputs, properties are null"); return; } - foreach (var kvp in dict) - { - Debug.Console(1, this, "props.Input[{0}]: {1}", kvp.Key, kvp.Value); - } - + + // iterate through HDMI inputs foreach (var item in _chassis.HdmiInputs) { var input = item; var index = item.Number; var key = string.Format("hdmiIn{0}", index); - var name = string.IsNullOrEmpty(InputNames[index]) ? string.Format("HDMI Input {0}", index) : InputNames[index]; + input.Name.StringValue = string.IsNullOrEmpty(InputNames[index]) + ? string.Format("HDMI Input {0}", index) + : InputNames[index]; - InputNameFeedbacks.Add(new StringFeedback(name, () => InputNames[index])); + InputNameFeedbacks.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), + () => InputNames[index])); var port = new RoutingInputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) { FeedbackMatchObject = input }; - Debug.Console(1, this, "Adding Input port: {0}", port.Key); + Debug.Console(1, this, "Adding Input port: {0} - {1}", port.Key, input.Name); InputPorts.Add(port); - InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); + InputHdcpEnableFeedback.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), + () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); - VideoInputSyncFeedbacks.Add(new BoolFeedback(name, () => input.VideoDetectedFeedback.BoolValue)); + VideoInputSyncFeedbacks.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), + () => input.VideoDetectedFeedback.BoolValue)); } + // iterate through DM Lite inputs foreach (var item in _chassis.DmLiteInputs) { var input = item; var index = item.Number; var key = string.Format("dmLiteIn{0}", index); - var name = string.IsNullOrEmpty(InputNames[index]) ? string.Format("DM Input {0}", index) : InputNames[index]; - input.Name.StringValue = name; + input.Name.StringValue = string.IsNullOrEmpty(InputNames[index]) + ? string.Format("DM Input {0}", index) + : InputNames[index]; - InputNameFeedbacks.Add(new StringFeedback(name, () => InputNames[index])); + InputNameFeedbacks.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), + () => InputNames[index])); var port = new RoutingInputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, input, this) { FeedbackMatchObject = input }; - Debug.Console(0, this, "Adding Input port: {0}", port.Key); + Debug.Console(0, this, "Adding Input port: {0} - {1}", port.Key, input.Name); InputPorts.Add(port); - InputHdcpEnableFeedback.Add(new BoolFeedback(name, () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); + InputHdcpEnableFeedback.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), + () => input.InputPort.HdcpSupportOnFeedback.BoolValue)); - VideoInputSyncFeedbacks.Add(new BoolFeedback(name, () => input.VideoDetectedFeedback.BoolValue)); + VideoInputSyncFeedbacks.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), + () => input.VideoDetectedFeedback.BoolValue)); } _chassis.DMInputChange += _chassis_InputChange; @@ -162,54 +164,38 @@ namespace PepperDash_Essentials_DM.Chassis Debug.Console(1, this, "Failed to setup outputs, properties are null"); return; } - foreach (var kvp in dict) - { - Debug.Console(1, this, "props.Output[{0}]: {1}", kvp.Key, kvp.Value); - } foreach (var item in _chassis.HdmiDmLiteOutputs) { var output = item; var index = item.Number; var key = string.Format("hdmiDmLiteOut{0}", index); - var name = string.IsNullOrEmpty(OutputNames[index]) ? string.Format("Output {0}", index) : OutputNames[index]; - output.Name.StringValue = name; + + output.Name.StringValue = string.IsNullOrEmpty(OutputNames[index]) + ? string.Format("Output {0}", index) + : OutputNames[index]; - var port = new RoutingOutputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, output, this) + var hdmiPort = new RoutingOutputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, output, this) { FeedbackMatchObject = output, - // set port for CEC - Port = output + Port = output.HdmiOutput.HdmiOutputPort.StreamCec }; - Debug.Console(0, this, "Adding Output port: {0}", port.Key); - OutputPorts.Add(port); + Debug.Console(1, this, "Adding Output port: {0} - {1}", hdmiPort.Key, output.Name); + OutputPorts.Add(hdmiPort); - OutputRouteNameFeedback.Add(new StringFeedback(name, () => output.VideoOutFeedback.NameFeedback.StringValue)); + var dmLitePort = new RoutingOutputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.DmCat, output, this) + { + FeedbackMatchObject = output, + Port = output.DmLiteOutput.DmLiteOutputPort.StreamCec + }; + Debug.Console(1, this, "Adding Output port: {0} - {1}", dmLitePort.Key, output.Name); + OutputPorts.Add(dmLitePort); - VideoOutputRouteFeedbacks.Add(new IntFeedback(name, + OutputRouteNameFeedback.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), + () => output.VideoOutFeedback.NameFeedback.StringValue)); + + VideoOutputRouteFeedbacks.Add(new IntFeedback(index.ToString(CultureInfo.InvariantCulture), () => output.VideoOutFeedback == null ? 0 : (int)output.VideoOutFeedback.Number)); - - // TODO [ ] Investigate setting input priorities per output - // {{in1-priority-level}, {in2-priority-level}, .... {in6-priority-level}} - // default priority level input 1-4 ascending - //if (_inputPriorityParams != null && _inputPriorityParams.Count() > 0) - // output.OutputPort.InputPriorities(_inputPriorityParams); - - if (port.Port == null) continue; - - var hdmiOutputStreamCec = output.HdmiOutput.HdmiOutputPort.StreamCec; - if (hdmiOutputStreamCec != null) - { - var streamCec = new StreamCecWrapper(string.Format("{0}-hdmiOut{1}-streamCec", Key, index), hdmiOutputStreamCec); - DeviceManager.AddDevice(streamCec); - } - - var dmLiteOutputStreamCec = output.DmLiteOutput.DmLiteOutputPort.StreamCec; - if (dmLiteOutputStreamCec != null) - { - var streamCec = new StreamCecWrapper(string.Format("{0}-dmLiteOut{1}-streamCec", Key, index), dmLiteOutputStreamCec); - DeviceManager.AddDevice(streamCec); - } } _chassis.DMOutputChange += _chassis_OutputChange; @@ -547,7 +533,7 @@ namespace PepperDash_Essentials_DM.Chassis } - #endregion + #endregion } From 7ecb2ecf6dfeadcf2191d49cca1be0a03e10b54d Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 13 Sep 2023 16:43:23 -0500 Subject: [PATCH 42/50] fix: updates SetupOutputs to create a hdmiOutX and dmLiteOutX port --- .../Chassis/HdPsXxxController.cs | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 705061d2..cbcf2a7c 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -105,10 +105,12 @@ namespace PepperDash_Essentials_DM.Chassis var input = item; var index = item.Number; var key = string.Format("hdmiIn{0}", index); - input.Name.StringValue = string.IsNullOrEmpty(InputNames[index]) - ? string.Format("HDMI Input {0}", index) + var name = string.IsNullOrEmpty(InputNames[index]) + ? string.Format("HDMI Input {0}", index) : InputNames[index]; + input.Name.StringValue = name; + InputNameFeedbacks.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), () => InputNames[index])); @@ -116,7 +118,7 @@ namespace PepperDash_Essentials_DM.Chassis { FeedbackMatchObject = input }; - Debug.Console(1, this, "Adding Input port: {0} - {1}", port.Key, input.Name); + Debug.Console(1, this, "Adding Input port: {0} - {1}", port.Key, name); InputPorts.Add(port); InputHdcpEnableFeedback.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), @@ -132,10 +134,12 @@ namespace PepperDash_Essentials_DM.Chassis var input = item; var index = item.Number; var key = string.Format("dmLiteIn{0}", index); - input.Name.StringValue = string.IsNullOrEmpty(InputNames[index]) + var name = string.IsNullOrEmpty(InputNames[index]) ? string.Format("DM Input {0}", index) : InputNames[index]; + input.Name.StringValue = name; + InputNameFeedbacks.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), () => InputNames[index])); @@ -143,7 +147,7 @@ namespace PepperDash_Essentials_DM.Chassis { FeedbackMatchObject = input }; - Debug.Console(0, this, "Adding Input port: {0} - {1}", port.Key, input.Name); + Debug.Console(0, this, "Adding Input port: {0} - {1}", port.Key, name); InputPorts.Add(port); InputHdcpEnableFeedback.Add(new BoolFeedback(index.ToString(CultureInfo.InvariantCulture), @@ -169,26 +173,28 @@ namespace PepperDash_Essentials_DM.Chassis { var output = item; var index = item.Number; - var key = string.Format("hdmiDmLiteOut{0}", index); - - output.Name.StringValue = string.IsNullOrEmpty(OutputNames[index]) + var name = string.IsNullOrEmpty(OutputNames[index]) ? string.Format("Output {0}", index) - : OutputNames[index]; + : OutputNames[index]; + + output.Name.StringValue = name; - var hdmiPort = new RoutingOutputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, output, this) + var hdmiKey = string.Format("hdmiOut{0}", index); + var hdmiPort = new RoutingOutputPort(hdmiKey, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, output, this) { FeedbackMatchObject = output, Port = output.HdmiOutput.HdmiOutputPort.StreamCec }; - Debug.Console(1, this, "Adding Output port: {0} - {1}", hdmiPort.Key, output.Name); + Debug.Console(1, this, "Adding Output port: {0} - {1}", hdmiPort.Key, name); OutputPorts.Add(hdmiPort); - var dmLitePort = new RoutingOutputPort(key, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.DmCat, output, this) + var dmLiteKey = string.Format("dmLiteOut{0}", index); + var dmLitePort = new RoutingOutputPort(dmLiteKey, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.DmCat, output, this) { FeedbackMatchObject = output, Port = output.DmLiteOutput.DmLiteOutputPort.StreamCec }; - Debug.Console(1, this, "Adding Output port: {0} - {1}", dmLitePort.Key, output.Name); + Debug.Console(1, this, "Adding Output port: {0} - {1}", dmLitePort.Key, name); OutputPorts.Add(dmLitePort); OutputRouteNameFeedback.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), From 6d020132cfb2283fbcd1fa3bee89f3f4081eedac Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 20 Sep 2023 15:38:25 -0500 Subject: [PATCH 43/50] refactor: GetCecPort method to handle exceptions --- .../Comm and IR/CommFactory.cs | 71 +++++++++++-------- 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs index fd5fcfe2..549404e0 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs @@ -115,39 +115,54 @@ namespace PepperDash.Essentials.Core /// public static ICec GetCecPort(ControlPropertiesConfig config) { - var dev = DeviceManager.GetDeviceForKey(config.ControlPortDevKey); - - Debug.Console(0, "GetCecPort: device '{0}' {1}", config.ControlPortDevKey, dev == null - ? "is not valid, failed to create build cec port" - : "found in device manager, attempting to build cec port"); - - if (dev == null) - return null; - - if (String.IsNullOrEmpty(config.ControlPortName)) + try { - Debug.Console(0, "GetCecPort: '{0}' - Configuration missing 'ControlPortName'", config.ControlPortDevKey); - return null; + var dev = DeviceManager.GetDeviceForKey(config.ControlPortDevKey); + + Debug.Console(0, "GetCecPort: device '{0}' {1}", config.ControlPortDevKey, dev == null + ? "is not valid, failed to get cec port" + : "found in device manager, attempting to get cec port"); + + if (dev == null) + return null; + + if (String.IsNullOrEmpty(config.ControlPortName)) + { + Debug.Console(0, "GetCecPort: '{0}' - Configuration missing 'ControlPortName'", config.ControlPortDevKey); + return null; + } + + + var inputsOutputs = dev as IRoutingInputsOutputs; + if (inputsOutputs == null) + { + Debug.Console(0, "GetCecPort: Device '{0}' does not support IRoutingInputsOutputs, failed to get CEC port called '{1}'", + config.ControlPortDevKey, config.ControlPortName); + + return null; + } + + var inputPort = inputsOutputs.InputPorts[config.ControlPortName]; + if (inputPort != null && inputPort.Port is ICec) + return inputPort.Port as ICec; + + + var outputPort = inputsOutputs.OutputPorts[config.ControlPortName]; + if (outputPort != null && outputPort.Port is ICec) + return outputPort.Port as ICec; + } + catch (Exception ex) + { + Debug.Console(1, "GetCecPort Exception Message: {0}", ex.Message); + Debug.Console(2, "GetCecPort Exception StackTrace: {0}", ex.StackTrace); + if (ex.InnerException != null) + Debug.Console(0, "GetCecPort Exception InnerException: {0}", ex.InnerException); } - var inputPort = (dev as IRoutingInputsOutputs).InputPorts[config.ControlPortName]; - if (inputPort != null) - { - if (inputPort.Port is ICec) - return inputPort.Port as ICec; - } - - var outputPort = (dev as IRoutingInputsOutputs).OutputPorts[config.ControlPortName]; - if (outputPort != null) - { - if (outputPort.Port is ICec) - return outputPort.Port as ICec; - } - - Debug.Console(0, "GetCecPort: Device '{0}' does not have a CEC port called: '{1}'", + Debug.Console(0, "GetCecPort: Device '{0}' does not have a CEC port called '{1}'", config.ControlPortDevKey, config.ControlPortName); - return null; + return null; } /// From 1569c12450a11c8b99b1b8f6f0d917b0d35a0dde Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 20 Sep 2023 15:41:06 -0500 Subject: [PATCH 44/50] fix: Updates SetupOutputs method Corrects the port referencece to exclude `.StreamCec` when building the port. --- .../Essentials_DM/Chassis/HdPsXxxController.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index cbcf2a7c..bf9f72cc 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -183,7 +183,7 @@ namespace PepperDash_Essentials_DM.Chassis var hdmiPort = new RoutingOutputPort(hdmiKey, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.Hdmi, output, this) { FeedbackMatchObject = output, - Port = output.HdmiOutput.HdmiOutputPort.StreamCec + Port = output.HdmiOutput.HdmiOutputPort }; Debug.Console(1, this, "Adding Output port: {0} - {1}", hdmiPort.Key, name); OutputPorts.Add(hdmiPort); @@ -192,13 +192,13 @@ namespace PepperDash_Essentials_DM.Chassis var dmLitePort = new RoutingOutputPort(dmLiteKey, eRoutingSignalType.AudioVideo, eRoutingPortConnectionType.DmCat, output, this) { FeedbackMatchObject = output, - Port = output.DmLiteOutput.DmLiteOutputPort.StreamCec + Port = output.DmLiteOutput.DmLiteOutputPort }; Debug.Console(1, this, "Adding Output port: {0} - {1}", dmLitePort.Key, name); OutputPorts.Add(dmLitePort); - + OutputRouteNameFeedback.Add(new StringFeedback(index.ToString(CultureInfo.InvariantCulture), - () => output.VideoOutFeedback.NameFeedback.StringValue)); + () => output.VideoOutFeedback.NameFeedback.StringValue)); VideoOutputRouteFeedbacks.Add(new IntFeedback(index.ToString(CultureInfo.InvariantCulture), () => output.VideoOutFeedback == null ? 0 : (int)output.VideoOutFeedback.Number)); From b9fd9f23a4e5fcae2c7b941572c47c02ce3fbd74 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Tue, 4 Oct 2022 17:42:58 -0600 Subject: [PATCH 45/50] refactor: break IEssentialsRoom down further In order to allow for easier composition of interfaces for room plugins, the IEssentialsRoom interface needed to be broken down further to the simplest components a room would need to function. The interfaces are composited in the huddle space and the Huddle VTC interfaces. --- .../Interfaces/IEssentialsHuddleSpaceRoom.cs | 3 +- .../Interfaces/IEssentialsHuddleVtc1Room.cs | 3 +- .../Devices/IVolumeAndAudioInterfaces.cs | 4 +++ ...lsHuddleSpaceFusionSystemControllerBase.cs | 28 ++++++++++------ .../RoomOnToDefaultSourceWhenOccupied.cs | 25 +++++++++++---- .../Room/IEssentialsRoom.cs | 32 ++++--------------- .../Room/Interfaces.cs | 27 +++++++++++++++- 7 files changed, 77 insertions(+), 45 deletions(-) diff --git a/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleSpaceRoom.cs b/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleSpaceRoom.cs index 41616d96..dccae06a 100644 --- a/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleSpaceRoom.cs +++ b/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleSpaceRoom.cs @@ -7,7 +7,8 @@ using PepperDash.Essentials.Room.Config; namespace PepperDash.Essentials { - public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasDefaultDisplay, IHasCurrentVolumeControls + public interface IEssentialsHuddleSpaceRoom : IEssentialsRoom, IHasCurrentSourceInfoChange, IRunRouteAction, IRunDefaultPresentRoute, IHasDefaultDisplay, IHasCurrentVolumeControls, IRoomOccupancy, + IEmergency, IMicrophonePrivacy { bool ExcludeFromGlobalFunctions { get; } diff --git a/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs b/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs index 03f7340b..85937828 100644 --- a/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs +++ b/PepperDashEssentials/Room/Types/Interfaces/IEssentialsHuddleVtc1Room.cs @@ -8,7 +8,8 @@ using PepperDash.Essentials.Devices.Common.AudioCodec; namespace PepperDash.Essentials { public interface IEssentialsHuddleVtc1Room : IEssentialsRoom, IHasCurrentSourceInfoChange, - IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback + IPrivacy, IHasCurrentVolumeControls, IRunRouteAction, IRunDefaultCallRoute, IHasVideoCodec, IHasAudioCodec, IHasDefaultDisplay, IHasInCallFeedback, + IRoomOccupancy, IEmergency, IMicrophonePrivacy { EssentialsHuddleVtc1PropertiesConfig PropertiesConfig { get; } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IVolumeAndAudioInterfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IVolumeAndAudioInterfaces.cs index c8a5df39..c8033b92 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IVolumeAndAudioInterfaces.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Devices/IVolumeAndAudioInterfaces.cs @@ -72,6 +72,10 @@ namespace PepperDash.Essentials.Core { IBasicVolumeControls CurrentVolumeControls { get; } event EventHandler CurrentVolumeDeviceChange; + + void SetDefaultLevels(); + + bool ZeroVolumeWhenSwtichingVolumeDevices { get; } } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs index 1bf925d6..a675f765 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Fusion/EssentialsHuddleSpaceFusionSystemControllerBase.cs @@ -148,15 +148,20 @@ namespace PepperDash.Essentials.Core.Fusion ReadGuidFile(guidFilePath); } - if (Room.RoomOccupancy != null) + var occupancyRoom = Room as IRoomOccupancy; + + if (occupancyRoom != null) { - if (Room.OccupancyStatusProviderIsRemote) + if (occupancyRoom.RoomOccupancy != null) { - SetUpRemoteOccupancy(); - } - else - { - SetUpLocalOccupancy(); + if (occupancyRoom.OccupancyStatusProviderIsRemote) + { + SetUpRemoteOccupancy(); + } + else + { + SetUpLocalOccupancy(); + } } } @@ -1523,10 +1528,15 @@ namespace PepperDash.Essentials.Core.Fusion // Tie to method on occupancy object //occSensorShutdownMinutes.OutputSig.UserObject(new Action(ushort)(b => Room.OccupancyObj.SetShutdownMinutes(b)); + var occRoom = Room as IRoomOccupancy; + if (occRoom != null) + { + occRoom.RoomOccupancy.RoomIsOccupiedFeedback.LinkInputSig(occSensorAsset.RoomOccupied.InputSig); + occRoom.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange; + } RoomOccupancyRemoteStringFeedback = new StringFeedback(() => _roomOccupancyRemoteString); - Room.RoomOccupancy.RoomIsOccupiedFeedback.LinkInputSig(occSensorAsset.RoomOccupied.InputSig); - Room.RoomOccupancy.RoomIsOccupiedFeedback.OutputChange += RoomIsOccupiedFeedback_OutputChange; + RoomOccupancyRemoteStringFeedback.LinkInputSig(occSensorAsset.RoomOccupancyInfo.InputSig); //} diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Behaviours/RoomOnToDefaultSourceWhenOccupied.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Behaviours/RoomOnToDefaultSourceWhenOccupied.cs index 81cbff9e..b7440213 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Behaviours/RoomOnToDefaultSourceWhenOccupied.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Behaviours/RoomOnToDefaultSourceWhenOccupied.cs @@ -38,7 +38,7 @@ namespace PepperDash.Essentials.Core ScheduledEventGroup FeatureEventGroup; - public IEssentialsRoom Room { get; private set; } + public IRoomOccupancy Room { get; private set; } private Fusion.EssentialsHuddleSpaceFusionSystemControllerBase FusionRoom; @@ -84,7 +84,7 @@ namespace PepperDash.Essentials.Core /// void SetUpDevice() { - Room = DeviceManager.GetDeviceForKey(PropertiesConfig.RoomKey) as IEssentialsRoom; + Room = DeviceManager.GetDeviceForKey(PropertiesConfig.RoomKey) as IRoomOccupancy; if (Room != null) { @@ -235,12 +235,23 @@ namespace PepperDash.Essentials.Core if (FeatureEnabled) { - // Check room power state first - if (!Room.OnFeedback.BoolValue) - { - Debug.Console(1, this, "Powering Room on to default source"); - Room.RunDefaultPresentRoute(); + var essentialsRoom = Room as IEssentialsRoom; + + if (essentialsRoom != null) { + if (!essentialsRoom.OnFeedback.BoolValue) + { + Debug.Console(1, this, "Powering Room on to default source"); + + var defaultRouteRoom = Room as IRunDefaultPresentRoute; + + if (defaultRouteRoom != null) + { + defaultRouteRoom.RunDefaultPresentRoute(); + } + } } + // Check room power state first + } } } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/IEssentialsRoom.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/IEssentialsRoom.cs index 2273690f..9a70f980 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/IEssentialsRoom.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/IEssentialsRoom.cs @@ -17,15 +17,10 @@ namespace PepperDash.Essentials.Core /// public interface IEssentialsRoom : IKeyName, IReconfigurableDevice, IRunDefaultPresentRoute, IEnvironmentalControls { - BoolFeedback OnFeedback { get; } - - event EventHandler RoomOccupancyIsSet; + BoolFeedback OnFeedback { get; } BoolFeedback IsWarmingUpFeedback { get; } - BoolFeedback IsCoolingDownFeedback { get; } - - IOccupancyStatusProvider RoomOccupancy { get; } - bool OccupancyStatusProviderIsRemote { get; } + BoolFeedback IsCoolingDownFeedback { get; } bool IsMobileControlEnabled { get; } IMobileControlRoomBridge MobileControlRoomBridge { get; } @@ -35,31 +30,16 @@ namespace PepperDash.Essentials.Core SecondsCountdownTimer ShutdownPromptTimer { get; } int ShutdownPromptSeconds { get; } int ShutdownVacancySeconds { get; } - eShutdownType ShutdownType { get; } - - EssentialsRoomEmergencyBase Emergency { get; } - - Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; } + eShutdownType ShutdownType { get; } string LogoUrlLightBkgnd { get; } string LogoUrlDarkBkgnd { get; } - eVacancyMode VacancyMode { get; } + void StartShutdown(eShutdownType type); - bool ZeroVolumeWhenSwtichingVolumeDevices { get; } + void Shutdown(); - void StartShutdown(eShutdownType type); - void StartRoomVacancyTimer(eVacancyMode mode); - - void Shutdown(); - - void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes); - - void PowerOnToDefaultOrLastSource(); - - void SetDefaultLevels(); - - void RoomVacatedForTimeoutPeriod(object o); + void PowerOnToDefaultOrLastSource(); } } \ No newline at end of file diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Interfaces.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Interfaces.cs index b5121e9c..e962e604 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Interfaces.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Room/Interfaces.cs @@ -41,7 +41,6 @@ namespace PepperDash.Essentials.Core void RunRouteAction(string routeKey, string sourceListKey); void RunRouteAction(string routeKey, string sourceListKey, Action successCallback); - } /// @@ -78,4 +77,30 @@ namespace PepperDash.Essentials.Core bool HasEnvironmentalControlDevices { get; } } + public interface IRoomOccupancy:IKeyed + { + IOccupancyStatusProvider RoomOccupancy { get; } + bool OccupancyStatusProviderIsRemote { get; } + + void SetRoomOccupancy(IOccupancyStatusProvider statusProvider, int timeoutMinutes); + + void RoomVacatedForTimeoutPeriod(object o); + + void StartRoomVacancyTimer(eVacancyMode mode); + + eVacancyMode VacancyMode { get; } + + event EventHandler RoomOccupancyIsSet; + } + + public interface IEmergency + { + EssentialsRoomEmergencyBase Emergency { get; } + } + + public interface IMicrophonePrivacy + { + Core.Privacy.MicrophonePrivacyController MicrophonePrivacy { get; } + } + } \ No newline at end of file From de6f8c7896c96a58fbd303553e91ba85880c7781 Mon Sep 17 00:00:00 2001 From: jdevito Date: Tue, 10 Oct 2023 06:07:37 -0500 Subject: [PATCH 46/50] feat: adds secureTcpClient to comm factory --- .../PepperDashEssentialsBase/Comm and IR/CommFactory.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs index 9667b5b9..1742fac4 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Comm and IR/CommFactory.cs @@ -81,6 +81,15 @@ namespace PepperDash.Essentials.Core } case eControlMethod.Telnet: break; + case eControlMethod.SecureTcpIp: + { + var secureTcp = new GenericSecureTcpIpClient(deviceConfig.Key + "-secureTcp", c.Address, c.Port, c.BufferSize); + secureTcp.AutoReconnect = c.AutoReconnect; + if (secureTcp.AutoReconnect) + secureTcp.AutoReconnectIntervalMs = c.AutoReconnectIntervalMs; + comm = secureTcp; + break; + } default: break; } From 6c41b8e19de5a4b0a6af374afa6c83598d1dff1e Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 24 Oct 2023 15:24:44 -0500 Subject: [PATCH 47/50] fix: updates executeSwitch, add helper method 1. Updated executeSwitch object casting to resolve routing issues. 2. Added ListRoutingPorts method. --- .../Chassis/HdPsXxxController.cs | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index bf9f72cc..216f3d19 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -208,6 +208,38 @@ namespace PepperDash_Essentials_DM.Chassis } + public void ListRoutingPorts() + { + try + { + foreach (var port in InputPorts) + { + Debug.Console(0, this, @"Input Port Key: {0} +Port: {1} +Type: {2} +ConnectionType: {3} +Selector: {4} +", port.Key, port.Port, port.Type, port.ConnectionType, port.Selector); + } + + foreach (var port in OutputPorts) + { + Debug.Console(0, this, @"Output Port Key: {0} +Port: {1} +Type: {2} +ConnectionType: {3} +Selector: {4} +", port.Key, port.Port, port.Type, port.ConnectionType, port.Selector); + } + } + catch (Exception ex) + { + Debug.Console(0, this, "ListRoutingPorts Exception Message: {0}", ex.Message); + Debug.Console(0, this, "ListRoutingPorts Exception StackTrace: {0}", ex.StackTrace); + if (ex.InnerException != null) Debug.Console(0, this, "ListRoutingPorts InnerException: {0}", ex.InnerException); + } + } + #region BridgeLinking /// @@ -299,9 +331,12 @@ namespace PepperDash_Essentials_DM.Chassis /// public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) { - var input = inputSelector as HdPsXxxHdmiInput; - var output = outputSelector as HdPsXxxHdmiOutput; + //var input = inputSelector as HdPsXxxHdmiInput; + //var output = outputSelector as HdPsXxxHdmiOutput; + var input = inputSelector as HdPsXxxInput; + var output = outputSelector as HdPsXxxOutput; + Debug.Console(2, this, "ExecuteSwitch: input={0}, output={1}", input, output); if (output == null) From 53b96d54e69e2108ac9c8aa67c6f35437a3b514c Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Tue, 24 Oct 2023 15:36:04 -0500 Subject: [PATCH 48/50] fix: removes old selector casting statements --- .../Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs index 216f3d19..36e99bc6 100644 --- a/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs +++ b/essentials-framework/Essentials DM/Essentials_DM/Chassis/HdPsXxxController.cs @@ -331,9 +331,6 @@ Selector: {4} /// public void ExecuteSwitch(object inputSelector, object outputSelector, eRoutingSignalType signalType) { - //var input = inputSelector as HdPsXxxHdmiInput; - //var output = outputSelector as HdPsXxxHdmiOutput; - var input = inputSelector as HdPsXxxInput; var output = outputSelector as HdPsXxxOutput; From 6698dcb46e7cdc6824d5725ecf9528385e5fe03a Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 25 Oct 2023 15:26:42 -0500 Subject: [PATCH 49/50] refactor: update init methods and add events - Updated InitializeButton method to enable/disable buttons based on config. - Updated InitializeButtonFeedback method debug statements. - Added BaseEvent event subscription. - Added PanelStateChnage event subscription. --- .../Touchpanels/Mpc3Touchpanel.cs | 109 +++++++++++------- 1 file changed, 68 insertions(+), 41 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs index 296965f9..2d36fe49 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs @@ -27,7 +27,15 @@ namespace PepperDash.Essentials.Core.Touchpanels return; } + if (_touchpanel.Registerable) + { + _touchpanel.Register(); + Debug.Console(0, this, ""); + } + + _touchpanel.BaseEvent += _touchpanel_BaseEvent; _touchpanel.ButtonStateChange += _touchpanel_ButtonStateChange; + _touchpanel.PanelStateChange += _touchpanel_PanelStateChange; _buttons = buttons; if (_buttons == null) @@ -57,8 +65,6 @@ namespace PepperDash.Essentials.Core.Touchpanels /// public void InitializeButton(string key, KeypadButton config) { - Debug.Console(1, this, "Initializing button '{0}'...", key); - if (config == null) { Debug.Console(1, this, "Button '{0}' config is null, unable to initialize", key); @@ -69,63 +75,72 @@ namespace PepperDash.Essentials.Core.Touchpanels TryParseInt(key, out buttonNumber); var buttonEventTypes = config.EventTypes; + BoolOutputSig enabledFb = null; + BoolOutputSig disabledFb = null; switch (key) { case ("power"): { - if (buttonEventTypes == null) + if (buttonEventTypes == null || buttonEventTypes.Keys == null) _touchpanel.DisablePowerButton(); else _touchpanel.EnablePowerButton(); - break; - } - case ("volumeup"): - { - if (buttonEventTypes == null) - _touchpanel.DisableVolumeUpButton(); - - break; - } - case ("volumedown"): - { - if (buttonEventTypes == null) - _touchpanel.DisableVolumeDownButton(); - - break; - } - case ("volumefeedback"): - { + + enabledFb = _touchpanel.PowerButtonEnabledFeedBack; + disabledFb = _touchpanel.PowerButtonDisabledFeedBack; break; } + //case ("volumeup"): + // { + // break; + // } + //case ("volumedown"): + // { + // break; + // } + //case ("volumefeedback"): + // { + // break; + // } case ("mute"): { - if (buttonEventTypes == null) + if (buttonEventTypes == null || buttonEventTypes.Keys == null) _touchpanel.DisableMuteButton(); else _touchpanel.EnableMuteButton(); + + enabledFb = _touchpanel.MuteButtonEnabledFeedBack; + disabledFb = _touchpanel.MuteButtonDisabledFeedBack; + break; } default: { - if (buttonNumber == 0) + if (buttonNumber == 0 || buttonNumber > 9) break; - if (buttonEventTypes == null) + if (buttonEventTypes == null || buttonEventTypes.Keys == null) _touchpanel.DisableNumericalButton((uint)buttonNumber); else _touchpanel.EnableNumericalButton((uint)buttonNumber); + + if (_touchpanel.NumericalButtonEnabledFeedBack != null) + enabledFb = _touchpanel.NumericalButtonEnabledFeedBack[(uint)buttonNumber]; + + if (_touchpanel.NumericalButtonDisabledFeedBack != null) + disabledFb = _touchpanel.NumericalButtonDisabledFeedBack[(uint)buttonNumber]; + break; } } - Debug.Console(1, this, "Button '{0}' {1}", key, buttonEventTypes == null - ? "is disabled, verify eventTypes are configured." - : "is enabled"); + Debug.Console(0, this, "InitializeButton: key-'{0}' enabledFb-'{1}', disabledFb-'{2}'", + key, enabledFb ?? (object)"null", disabledFb ?? (object)"null"); } /// @@ -135,11 +150,11 @@ namespace PepperDash.Essentials.Core.Touchpanels /// public void InitializeButtonFeedback(string key, KeypadButton config) { - Debug.Console(1, this, "Initializing button '{0}' feedback...", key); + //Debug.Console(1, this, "Initializing button '{0}' feedback...", key); if (config == null) { - Debug.Console(1, this, "Button '{0}' config is null, unable to initialize feedback", key); + Debug.Console(1, this, "Button '{0}' config is null, skipping.", key); return; } @@ -148,9 +163,9 @@ namespace PepperDash.Essentials.Core.Touchpanels // Link up the button feedbacks to the specified device feedback var buttonFeedback = config.Feedback; - if (buttonFeedback == null) + if (buttonFeedback == null || string.IsNullOrEmpty(buttonFeedback.DeviceKey)) { - Debug.Console(1, this, "Button '{0}' feedback not configured and will not be implemented. If feedback is required, verify configuration.", + Debug.Console(1, this, "Button '{0}' feedback not configured, skipping.", key); return; } @@ -162,15 +177,15 @@ namespace PepperDash.Essentials.Core.Touchpanels var device = DeviceManager.GetDeviceForKey(buttonFeedback.DeviceKey) as Device; if (device == null) { - Debug.Console(1, this, "Button '{0}' feedback with deviceKey '{1}' not found, feedback will not be implemented. Verify feedback deviceKey is properly configured.", + Debug.Console(1, this, "Button '{0}' feedback deviceKey '{1}' not found.", key, buttonFeedback.DeviceKey); return; } - + deviceFeedback = device.GetFeedbackProperty(buttonFeedback.FeedbackName); if (deviceFeedback == null) { - Debug.Console(1, this, "Button '{0}' feedback failed to get feedback property for '{1}', feedback will not be implemented. Verify feedback deviceKey is properly configured.", + Debug.Console(1, this, "Button '{0}' feedbackName property '{1}' not found.", key, buttonFeedback.FeedbackName); return; } @@ -195,12 +210,12 @@ namespace PepperDash.Essentials.Core.Touchpanels } catch (Exception ex) { - Debug.Console(0, this, "Failed to initialize button '{0}' feedback with deviceKey '{1}'. If feedback is required, verify configuration.", - key, buttonFeedback.DeviceKey); - - Debug.Console(1, this, "InitializeButtonFeedback Exception Message: {0}", ex.Message); - Debug.Console(2, this, "InitializeButtonFeedback Exception StackTrace: {0}", ex.StackTrace); - if (ex.InnerException != null) Debug.Console(2, this, "InitializeButtonFeedback Exception InnerExceptioni: {0}", ex.InnerException); + Debug.Console(1, this, "InitializeButtonFeedback (button '{1}', deviceKey '{2}') Exception Message: {0}", + ex.Message, key, buttonFeedback.DeviceKey); + Debug.Console(2, this, "InitializeButtonFeedback (button '{1}', deviceKey '{2}') Exception StackTrace: {0}", + ex.StackTrace, key, buttonFeedback.DeviceKey); + if (ex.InnerException != null) Debug.Console(2, this, "InitializeButtonFeedback (button '{1}', deviceKey '{2}') InnerException: {0}", + ex.InnerException, key, buttonFeedback.DeviceKey); return; } @@ -259,9 +274,14 @@ namespace PepperDash.Essentials.Core.Touchpanels } } + private void _touchpanel_BaseEvent(GenericBase device, BaseEventArgs args) + { + Debug.Console(1, this, "BaseEvent: eventId-'{0}', index-'{1}'", args.EventId, args.Index); + } + private void _touchpanel_ButtonStateChange(GenericBase device, Crestron.SimplSharpPro.DeviceSupport.ButtonEventArgs args) { - Debug.Console(1, this, "Button {0} ({1}), {2}", args.Button.Number, args.Button.Name, args.NewButtonState); + Debug.Console(1, this, "ButtonStateChange: buttonNumber-'{0}' buttonName-'{1}', buttonState-'{2}'", args.Button.Number, args.Button.Name, args.NewButtonState); var type = args.NewButtonState.ToString(); if (_buttons.ContainsKey(args.Button.Number.ToString(CultureInfo.InvariantCulture))) @@ -274,6 +294,11 @@ namespace PepperDash.Essentials.Core.Touchpanels } } + private void _touchpanel_PanelStateChange(GenericBase device, BaseEventArgs args) + { + Debug.Console(1, this, "PanelStateChange: eventId-'{0}', index-'{1}'", args.EventId, args.Index); + } + /// /// Runs the function associated with this button/type. One of the following strings: /// Pressed, Released, Tapped, DoubleTapped, Held, HeldReleased @@ -282,6 +307,8 @@ namespace PepperDash.Essentials.Core.Touchpanels /// public void Press(string buttonKey, string type) { + Debug.Console(2, this, "Press: buttonKey-'{0}', type-'{1}'", buttonKey, type); + // TODO: In future, consider modifying this to generate actions at device activation time // to prevent the need to dynamically call the method via reflection on each button press if (!_buttons.ContainsKey(buttonKey)) return; From d1d1d81165ce61ad21c7c4563ceff801c2184c30 Mon Sep 17 00:00:00 2001 From: Jason DeVito Date: Wed, 25 Oct 2023 15:44:39 -0500 Subject: [PATCH 50/50] fix: update registration debug statement to include response --- .../PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs index 2d36fe49..2f6074dd 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Touchpanels/Mpc3Touchpanel.cs @@ -29,8 +29,8 @@ namespace PepperDash.Essentials.Core.Touchpanels if (_touchpanel.Registerable) { - _touchpanel.Register(); - Debug.Console(0, this, ""); + var registrationResponse = _touchpanel.Register(); + Debug.Console(0, this, "touchpanel registration response: {0}", registrationResponse); } _touchpanel.BaseEvent += _touchpanel_BaseEvent;