From d7cccc0709294847c01582b29616a342d90d7d89 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 1 Sep 2022 11:47:52 -0600 Subject: [PATCH 1/4] feat: add cooldown logic to Magic Routing In some cases, a route can be requested while a sink is cooling down. In those cases, the routing logic should keep track of requests for a destination and wait until cooling is complete to request the new route. --- .../Routing/IRoutingInputsExtensions.cs | 71 +++++++++++++++++-- 1 file changed, 64 insertions(+), 7 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs index 0c375825..4beaa37d 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs @@ -11,12 +11,34 @@ using PepperDash.Core; namespace PepperDash.Essentials.Core { + public class RouteRequest + { + public IRoutingSink Destination {get; set;} + public IRoutingOutputs Source {get; set;} + public eRoutingSignalType SignalType {get; set;} + + public void HandleCooldown(object sender, FeedbackEventArgs args) + { + var coolingDevice = sender as IWarmingCooling; + + if(args.BoolValue == false) + { + Destination.ReleaseAndMakeRoute(Source, SignalType); + + if(sender == null) return; + + coolingDevice.IsCoolingDownFeedback.OutputChange -= HandleCooldown; + } + } + } + /// /// Extensions added to any IRoutingInputs classes to provide discovery-based routing /// on those destinations. /// public static class IRoutingInputsExtensions { + private static Dictionary RouteRequests = new Dictionary(); /// /// Gets any existing RouteDescriptor for a destination, clears it using ReleaseRoute /// and then attempts a new Route and if sucessful, stores that RouteDescriptor @@ -24,16 +46,51 @@ namespace PepperDash.Essentials.Core /// public static void ReleaseAndMakeRoute(this IRoutingSink destination, IRoutingOutputs source, eRoutingSignalType signalType) { - destination.ReleaseRoute(); + var routeRequest = new RouteRequest { + Destination = destination, + Source = source, + SignalType = signalType + }; - if (source == null) return; - var newRoute = destination.GetRouteToSource(source, signalType); - if (newRoute == null) return; - RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(newRoute); - Debug.Console(2, destination, "Executing full route"); - newRoute.ExecuteRoutes(); + var coolingDevice = destination as IWarmingCooling; + + RouteRequest existingRouteRequest; + + //We already have a route request for this device, and it's a cooling device and is cooling + if (RouteRequests.TryGetValue(destination.Key, out existingRouteRequest) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) + { + coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown; + + coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; + + RouteRequests[destination.Key] = routeRequest; + return; + } + + //New Request + if (coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) + { + coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; + + RouteRequests.Add(destination.Key, routeRequest); + return; + } + + destination.ReleaseRoute(); + + RunRouteRequest(routeRequest); } + public static void RunRouteRequest(RouteRequest request) + { + if (request.Source == null) return; + var newRoute = request.Destination.GetRouteToSource(request.Source, request.SignalType); + if (newRoute == null) return; + RouteDescriptorCollection.DefaultCollection.AddRouteDescriptor(newRoute); + Debug.Console(2, request.Destination, "Executing full route"); + newRoute.ExecuteRoutes(); + } + /// /// Will release the existing route on the destination, if it is found in /// RouteDescriptorCollection.DefaultCollection From 358f44cfe598e17fc55b7fa09d3348842b206396 Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 1 Sep 2022 11:57:40 -0600 Subject: [PATCH 2/4] refactor: remove completed request from dictionary --- .../Routing/IRoutingInputsExtensions.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs index 4beaa37d..2dbf895a 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs @@ -58,24 +58,31 @@ namespace PepperDash.Essentials.Core //We already have a route request for this device, and it's a cooling device and is cooling if (RouteRequests.TryGetValue(destination.Key, out existingRouteRequest) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) - { + { coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown; coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; RouteRequests[destination.Key] = routeRequest; return; - } + } //New Request if (coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) { + coolingDevice.IsCoolingDownFeedback.OutputChange -= routeRequest.HandleCooldown; + coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; RouteRequests.Add(destination.Key, routeRequest); return; } + if (RouteRequests.ContainsKey(destination.Key) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == false) + { + RouteRequests.Remove(destination.Key); + } + destination.ReleaseRoute(); RunRouteRequest(routeRequest); From 7fe2d04d315d8e6a63e7a7914566406e2ff749cf Mon Sep 17 00:00:00 2001 From: Andrew Welker Date: Thu, 1 Sep 2022 12:29:19 -0600 Subject: [PATCH 3/4] fix: add removal of RouteRequest when calling ReleaseRoute --- .../Routing/IRoutingInputsExtensions.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs index 2dbf895a..bd5aff73 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs @@ -105,6 +105,17 @@ namespace PepperDash.Essentials.Core /// public static void ReleaseRoute(this IRoutingSink destination) { + RouteRequest existingRequest; + + if (RouteRequests.TryGetValue(destination.Key, out existingRequest) && destination is IWarmingCooling) + { + var coolingDevice = destination as IWarmingCooling; + + coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRequest.HandleCooldown; + } + + RouteRequests.Remove(destination.Key); + var current = RouteDescriptorCollection.DefaultCollection.RemoveRouteDescriptor(destination); if (current != null) { From c4a23e08871aaad758ffe197ec5a1498bbe47541 Mon Sep 17 00:00:00 2001 From: Neil Dorin Date: Fri, 2 Sep 2022 11:19:18 -0600 Subject: [PATCH 4/4] feat(essentials): Adds RoomUiBehaviorConfig for disabling activity buttons --- .../Room/Config/EssentialsRoomConfig.cs | 9 ++++ .../Display/MockDisplay.cs | 47 +++++++++++++++---- .../Routing/IRoutingInputsExtensions.cs | 14 ++++-- 3 files changed, 57 insertions(+), 13 deletions(-) diff --git a/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs b/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs index 5a2bd34f..b0ad2ae1 100644 --- a/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs +++ b/PepperDashEssentials/Room/Config/EssentialsRoomConfig.cs @@ -202,6 +202,9 @@ namespace PepperDash.Essentials.Room.Config [JsonProperty("fusion")] public EssentialsRoomFusionConfig Fusion { get; set; } + [JsonProperty("essentialsRoomUiBehaviorConfig", NullValueHandling=NullValueHandling.Ignore)] + public EssentialsRoomUiBehaviorConfig UiBehavior { get; set; } + [JsonProperty("zeroVolumeWhenSwtichingVolumeDevices")] public bool ZeroVolumeWhenSwtichingVolumeDevices { get; set; } @@ -218,6 +221,12 @@ namespace PepperDash.Essentials.Room.Config } } + public class EssentialsRoomUiBehaviorConfig + { + [JsonProperty("disableActivityButtonsWhileWarmingCooling")] + public bool DisableActivityButtonsWhileWarmingCooling { get; set; } + } + public class EssentialsAvRoomPropertiesConfig : EssentialsRoomPropertiesConfig { [JsonProperty("defaultAudioKey")] diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs index 4ac61943..266c1cbb 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Display/MockDisplay.cs @@ -30,11 +30,40 @@ namespace PepperDash.Essentials.Core bool _PowerIsOn; bool _IsWarmingUp; - bool _IsCoolingDown; - - protected override Func PowerIsOnFeedbackFunc { get { return () => _PowerIsOn; } } - protected override Func IsCoolingDownFeedbackFunc { get { return () => _IsCoolingDown; } } - protected override Func IsWarmingUpFeedbackFunc { get { return () => _IsWarmingUp; } } + bool _IsCoolingDown; + + protected override Func PowerIsOnFeedbackFunc + { + get + { + return () => + { + Debug.Console(2, this, "*************************************************** Display Power is {0}", _PowerIsOn ? "on" : "off"); + return _PowerIsOn; + }; + } } + protected override Func IsCoolingDownFeedbackFunc + { + get + { + return () => + { + Debug.Console(2, this, "*************************************************** {0}", _IsCoolingDown ? "Display is cooling down" : "Display has finished cooling down"); + return _IsCoolingDown; + }; + } + } + protected override Func IsWarmingUpFeedbackFunc + { + get + { + return () => + { + Debug.Console(2, this, "*************************************************** {0}", _IsWarmingUp ? "Display is warming up" : "Display has finished warming up"); + return _IsWarmingUp; + }; + } + } protected override Func CurrentInputFeedbackFunc { get { return () => "Not Implemented"; } } int VolumeHeldRepeatInterval = 200; @@ -61,7 +90,7 @@ namespace PepperDash.Essentials.Core MuteFeedback = new BoolFeedback("MuteOn", () => _IsMuted); WarmupTime = 10000; - CooldownTime = 5000; + CooldownTime = 10000; } public override void PowerOn() @@ -88,15 +117,15 @@ namespace PepperDash.Essentials.Core if (PowerIsOnFeedback.BoolValue && !_IsWarmingUp && !_IsCoolingDown) { _IsCoolingDown = true; - _PowerIsOn = false; - PowerIsOnFeedback.InvokeFireUpdate(); IsCoolingDownFeedback.InvokeFireUpdate(); // Fake cool-down cycle CooldownTimer = new CTimer(o => { Debug.Console(2, this, "Cooldown timer ending"); _IsCoolingDown = false; - IsCoolingDownFeedback.InvokeFireUpdate(); + IsCoolingDownFeedback.InvokeFireUpdate(); + _PowerIsOn = false; + PowerIsOnFeedback.InvokeFireUpdate(); }, CooldownTime); } } diff --git a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs index bd5aff73..d371c2d6 100644 --- a/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs +++ b/essentials-framework/Essentials Core/PepperDashEssentialsBase/Routing/IRoutingInputsExtensions.cs @@ -58,12 +58,15 @@ namespace PepperDash.Essentials.Core //We already have a route request for this device, and it's a cooling device and is cooling if (RouteRequests.TryGetValue(destination.Key, out existingRouteRequest) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == true) - { + { coolingDevice.IsCoolingDownFeedback.OutputChange -= existingRouteRequest.HandleCooldown; coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; - RouteRequests[destination.Key] = routeRequest; + RouteRequests[destination.Key] = routeRequest; + + Debug.Console(2, "******************************************************** Device: {0} is cooling down and already has a routing request stored. Storing new route request to route to source key: {1}", destination.Key, routeRequest.Source.Key); + return; } @@ -74,13 +77,16 @@ namespace PepperDash.Essentials.Core coolingDevice.IsCoolingDownFeedback.OutputChange += routeRequest.HandleCooldown; - RouteRequests.Add(destination.Key, routeRequest); + RouteRequests.Add(destination.Key, routeRequest); + + Debug.Console(2, "******************************************************** Device: {0} is cooling down. Storing route request to route to source key: {1}", destination.Key, routeRequest.Source.Key); return; } if (RouteRequests.ContainsKey(destination.Key) && coolingDevice != null && coolingDevice.IsCoolingDownFeedback.BoolValue == false) { - RouteRequests.Remove(destination.Key); + RouteRequests.Remove(destination.Key); + Debug.Console(2, "******************************************************** Device: {0} is NOT cooling down. Removing stored route request and routing to source key: {1}", destination.Key, routeRequest.Source.Key); } destination.ReleaseRoute();