From 80e0c75520cdc69ec88896a7bf3933b6b2c43c7f Mon Sep 17 00:00:00 2001 From: pawmmm Date: Fri, 22 May 2026 10:21:27 -0600 Subject: [PATCH] Fix: refresh cstate.endTime when active schedule's window advances Two related fixes to the cstate.endTime refresh path so that checkCircuitEggTimerExpirationAsync does not force-turn-off a circuit whose schedule is still active. SystemBoard.syncScheduleStates previously called setEndTime only when schedIsOn != ssched.isOn. For a continuously-active schedule (e.g. a 12:00 AM -> 12:00 AM window) that transition never happens at the local midnight rollover, so cstate.endTime froze at the previous day's value while ssched.scheduleTime.endTime advanced. Within ~1 minute after midnight the circuit was being turned off in error. Now we also refresh when the schedule is still on, the circuit is still on, and the schedule's endTime has advanced past the cached cstate.endTime. IntelliCenterBoard.syncScheduleStates had `circs.push;` (a reference to the method, not a call) at line 4817, so the array stayed empty and the subsequent refresh loop never ran. Same intent, same bug class. Fixes #1192 --- controller/boards/IntelliCenterBoard.ts | 2 +- controller/boards/SystemBoard.ts | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/controller/boards/IntelliCenterBoard.ts b/controller/boards/IntelliCenterBoard.ts index b4c35d16..c753c51f 100644 --- a/controller/boards/IntelliCenterBoard.ts +++ b/controller/boards/IntelliCenterBoard.ts @@ -4814,7 +4814,7 @@ class IntelliCenterScheduleCommands extends ScheduleCommands { if (typeof c === 'undefined') { let cstate = state.circuits.getInterfaceById(ssched.circuit); c = { state: cstate, endTime: ssched.scheduleTime.endTime.getTime() }; - circs.push; + circs.push(c); } if (c.endTime < ssched.scheduleTime.endTime.getTime()) c.endTime = ssched.scheduleTime.endTime.getTime(); } diff --git a/controller/boards/SystemBoard.ts b/controller/boards/SystemBoard.ts index 996b084b..68aed067 100644 --- a/controller/boards/SystemBoard.ts +++ b/controller/boards/SystemBoard.ts @@ -3729,6 +3729,16 @@ export class ScheduleCommands extends BoardCommands { ssched.isOn = schedIsOn; sys.board.circuits.setEndTime(sys.circuits.getInterfaceById(ssched.circuit), scirc, scirc.isOn, true); } + else if (schedIsOn && scirc.isOn + && typeof scirc.endTime !== 'undefined' + && typeof ssched.scheduleTime.endTime !== 'undefined' + && ssched.scheduleTime.endTime.getTime() > scirc.endTime.toDate().getTime()) { + // The schedule's window has advanced past the cached circuit endTime + // (e.g. a continuous 24-hour schedule rolling over midnight). Without + // this refresh, checkCircuitEggTimerExpirationAsync would compare + // `now` against the stale endTime and force-turn-off the circuit. + sys.board.circuits.setEndTime(sys.circuits.getInterfaceById(ssched.circuit), scirc, scirc.isOn, true); + } ssched.emitEquipmentChange(); } } catch (err) { logger.error(`Error synchronizing schedule states`); }