diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftController.cs b/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftController.cs index 9163c2a3..5d25a58a 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftController.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftController.cs @@ -10,6 +10,16 @@ using Serilog.Events; namespace PepperDash.Essentials.Devices.Common.Shades { + /// + /// Enumeration for requested state + /// + enum RequestedState + { + None, + Raise, + Lower + } + /// /// Controls a single shade using three relays /// @@ -25,6 +35,10 @@ namespace PepperDash.Essentials.Devices.Common.Shades ISwitchedOutput LowerRelay; ISwitchedOutput LatchedRelay; + private bool _isMoving; + private RequestedState _requestedState; + private CTimer _movementTimer; + /// /// Gets or sets the InUpPosition /// @@ -163,6 +177,16 @@ namespace PepperDash.Essentials.Devices.Common.Shades { if (RaiseRelay == null && LatchedRelay == null) return; + Debug.LogMessage(LogEventLevel.Debug, this, $"Raise called for {Type}"); + + // If device is moving, bank the command + if (_isMoving) + { + Debug.LogMessage(LogEventLevel.Debug, this, $"Device is moving, banking Raise command"); + _requestedState = RequestedState.Raise; + return; + } + Debug.LogMessage(LogEventLevel.Debug, this, $"Raising {Type}"); switch (Mode) @@ -170,11 +194,25 @@ namespace PepperDash.Essentials.Devices.Common.Shades case eScreenLiftControlMode.momentary: { PulseOutput(RaiseRelay, RaiseRelayConfig.PulseTimeInMs); + + // Set moving flag and start timer if movement time is configured + if (RaiseRelayConfig.MovementTimeInMs > 0) + { + _isMoving = true; + _movementTimer = new CTimer(OnMovementComplete, RaiseRelayConfig.MovementTimeInMs); + } break; } case eScreenLiftControlMode.latched: { LatchedRelay.Off(); + + // Set moving flag and start timer if movement time is configured + if (LatchedRelayConfig.MovementTimeInMs > 0) + { + _isMoving = true; + _movementTimer = new CTimer(OnMovementComplete, LatchedRelayConfig.MovementTimeInMs); + } break; } } @@ -188,6 +226,16 @@ namespace PepperDash.Essentials.Devices.Common.Shades { if (LowerRelay == null && LatchedRelay == null) return; + Debug.LogMessage(LogEventLevel.Debug, this, $"Lower called for {Type}"); + + // If device is moving, bank the command + if (_isMoving) + { + Debug.LogMessage(LogEventLevel.Debug, this, $"Device is moving, banking Lower command"); + _requestedState = RequestedState.Lower; + return; + } + Debug.LogMessage(LogEventLevel.Debug, this, $"Lowering {Type}"); switch (Mode) @@ -195,17 +243,74 @@ namespace PepperDash.Essentials.Devices.Common.Shades case eScreenLiftControlMode.momentary: { PulseOutput(LowerRelay, LowerRelayConfig.PulseTimeInMs); + + // Set moving flag and start timer if movement time is configured + if (LowerRelayConfig.MovementTimeInMs > 0) + { + _isMoving = true; + _movementTimer = new CTimer(OnMovementComplete, LowerRelayConfig.MovementTimeInMs); + } break; } case eScreenLiftControlMode.latched: { LatchedRelay.On(); + + // Set moving flag and start timer if movement time is configured + if (LatchedRelayConfig.MovementTimeInMs > 0) + { + _isMoving = true; + _movementTimer = new CTimer(OnMovementComplete, LatchedRelayConfig.MovementTimeInMs); + } break; } } InUpPosition = false; } + /// + /// Called when movement timer completes + /// + void OnMovementComplete(object o) + { + Debug.LogMessage(LogEventLevel.Debug, this, $"Movement complete"); + + _isMoving = false; + + // Execute banked command if one exists + if (_requestedState != RequestedState.None) + { + Debug.LogMessage(LogEventLevel.Debug, this, $"Executing banked command: {_requestedState}"); + + var commandToExecute = _requestedState; + _requestedState = RequestedState.None; + + // Check if current state matches what the banked command would do + // If so, ignore it + if (commandToExecute == RequestedState.Raise && InUpPosition) + { + Debug.LogMessage(LogEventLevel.Debug, this, $"Already in up position, ignoring banked Raise command"); + return; + } + + if (commandToExecute == RequestedState.Lower && !InUpPosition) + { + Debug.LogMessage(LogEventLevel.Debug, this, $"Already in down position, ignoring banked Lower command"); + return; + } + + // Execute the banked command + if (commandToExecute == RequestedState.Raise) + { + Raise(); + } + else if (commandToExecute == RequestedState.Lower) + { + Lower(); + } + } + } + void PulseOutput(ISwitchedOutput output, int pulseTime) { output.On(); diff --git a/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftRelaysConfig.cs b/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftRelaysConfig.cs index 4de9eb25..a99f82d3 100644 --- a/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftRelaysConfig.cs +++ b/src/PepperDash.Essentials.Devices.Common/Displays/ScreenLiftRelaysConfig.cs @@ -18,5 +18,11 @@ namespace PepperDash.Essentials.Devices.Common.Shades /// [JsonProperty("pulseTimeInMs")] public int PulseTimeInMs { get; set; } + + /// + /// Gets or sets the MovementTimeInMs - time in milliseconds for the movement to complete + /// + [JsonProperty("movementTimeInMs")] + public int MovementTimeInMs { get; set; } } } \ No newline at end of file