Compare commits

...

6 Commits

Author SHA1 Message Date
equinoy
7f03f5111c feat Enhance ScreenLiftController to improve command banking during movement 2025-12-27 15:22:09 -06:00
copilot-swe-agent[bot]
ae0b2fe086 Refactor timer disposal and improve code readability
Co-authored-by: erikdred <88980320+erikdred@users.noreply.github.com>
2025-12-27 20:17:59 +00:00
copilot-swe-agent[bot]
bd11c827da Split movement time into separate raise/lower times and remove timing from latched mode
Co-authored-by: erikdred <88980320+erikdred@users.noreply.github.com>
2025-12-27 20:14:39 +00:00
copilot-swe-agent[bot]
7ea1efbabf Add raise/lower movement time configuration and banked command support
Co-authored-by: erikdred <88980320+erikdred@users.noreply.github.com>
2025-12-27 20:09:31 +00:00
copilot-swe-agent[bot]
9d6aaa2a0e Initial plan 2025-12-27 20:02:52 +00:00
Neil Dorin
39c1f60a4d Merge pull request #1370 from PepperDash/udp-eisc 2025-12-23 12:10:37 -05:00
2 changed files with 136 additions and 2 deletions

View File

@@ -10,6 +10,16 @@ using Serilog.Events;
namespace PepperDash.Essentials.Devices.Common.Shades
{
/// <summary>
/// Enumeration for requested state
/// </summary>
enum RequestedState
{
None,
Raise,
Lower
}
/// <summary>
/// Controls a single shade using three relays
/// </summary>
@@ -25,6 +35,10 @@ namespace PepperDash.Essentials.Devices.Common.Shades
ISwitchedOutput LowerRelay;
ISwitchedOutput LatchedRelay;
private bool _isMoving;
private RequestedState _requestedState;
private CTimer _movementTimer;
/// <summary>
/// Gets or sets the InUpPosition
/// </summary>
@@ -163,22 +177,47 @@ 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, just bank the command - don't interrupt current movement
if (_isMoving)
{
Debug.LogMessage(LogEventLevel.Debug, this, $"Device is moving, banking Raise command for execution after movement completes");
_requestedState = RequestedState.Raise;
return;
}
Debug.LogMessage(LogEventLevel.Debug, this, $"Raising {Type}");
switch (Mode)
{
case eScreenLiftControlMode.momentary:
{
// Ensure lower relay is off to prevent simultaneous relay activation
if (LowerRelay != null) LowerRelay.Off();
PulseOutput(RaiseRelay, RaiseRelayConfig.PulseTimeInMs);
// Always set moving flag to enable command banking, even if no timer is configured
_isMoving = true;
DisposeMovementTimer();
// Start timer if movement time is configured
if (RaiseRelayConfig.RaiseTimeInMs > 0)
{
_movementTimer = new CTimer(OnMovementComplete, RaiseRelayConfig.RaiseTimeInMs);
}
InUpPosition = true;
break;
}
case eScreenLiftControlMode.latched:
{
LatchedRelay.Off();
InUpPosition = true;
break;
}
}
InUpPosition = true;
}
/// <summary>
@@ -188,22 +227,105 @@ 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, just bank the command - don't interrupt current movement
if (_isMoving)
{
Debug.LogMessage(LogEventLevel.Debug, this, $"Device is moving, banking Lower command for execution after movement completes");
_requestedState = RequestedState.Lower;
return;
}
Debug.LogMessage(LogEventLevel.Debug, this, $"Lowering {Type}");
switch (Mode)
{
case eScreenLiftControlMode.momentary:
{
// Ensure raise relay is off to prevent simultaneous relay activation
if (RaiseRelay != null) RaiseRelay.Off();
PulseOutput(LowerRelay, LowerRelayConfig.PulseTimeInMs);
// Always set moving flag to enable command banking, even if no timer is configured
_isMoving = true;
DisposeMovementTimer();
// Start timer if movement time is configured
if (LowerRelayConfig.LowerTimeInMs > 0)
{
_movementTimer = new CTimer(OnMovementComplete, LowerRelayConfig.LowerTimeInMs);
}
InUpPosition = false;
break;
}
case eScreenLiftControlMode.latched:
{
LatchedRelay.On();
InUpPosition = false;
break;
}
}
InUpPosition = false;
}
/// <summary>
/// Disposes the current movement timer if it exists
/// </summary>
private void DisposeMovementTimer()
{
if (_movementTimer != null)
{
_movementTimer.Stop();
_movementTimer.Dispose();
_movementTimer = null;
}
}
/// <summary>
/// Called when movement timer completes
/// </summary>
private 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 and execute if different
switch (commandToExecute)
{
case RequestedState.Raise:
if (InUpPosition)
{
Debug.LogMessage(LogEventLevel.Debug, this, $"Already in up position, ignoring banked Raise command");
}
else
{
Raise();
}
break;
case RequestedState.Lower:
if (!InUpPosition)
{
Debug.LogMessage(LogEventLevel.Debug, this, $"Already in down position, ignoring banked Lower command");
}
else
{
Lower();
}
break;
}
}
}
void PulseOutput(ISwitchedOutput output, int pulseTime)

View File

@@ -18,5 +18,17 @@ namespace PepperDash.Essentials.Devices.Common.Shades
/// </summary>
[JsonProperty("pulseTimeInMs")]
public int PulseTimeInMs { get; set; }
/// <summary>
/// Gets or sets the RaiseTimeInMs - time in milliseconds for the raise movement to complete
/// </summary>
[JsonProperty("raiseTimeInMs")]
public int RaiseTimeInMs { get; set; }
/// <summary>
/// Gets or sets the LowerTimeInMs - time in milliseconds for the lower movement to complete
/// </summary>
[JsonProperty("lowerTimeInMs")]
public int LowerTimeInMs { get; set; }
}
}