UI: Active Window Start/End time inputs on countdown form.
Leave blank = runs any time. End before start = crosses midnight.
Scheduler: checks current time against window before starting timer;
supports cross-midnight windows (e.g. 9:00 AM to 4:00 AM next day).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Countdown is now state-change-driven (no scheduled window):
- 'If turns ON → auto-OFF after duration' (on_to_off)
- 'If turns OFF → auto-ON after duration' (off_to_on)
Scheduler polls device state; timer only starts when state matches
the chosen condition. Cancels any pending timer if state changes again.
Away Mode startAction/endAction already wired; _stopAwayLoop uses endAction.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Countdown: new 'Action when timer fires' dropdown (Turn ON / Turn OFF);
scheduler uses rule.countdownAction instead of hardcoded 1/0
- Away Mode: scheduler now reads startAction/endAction from the rule
(UI already exposed these fields); _stopAwayLoop respects endAction
instead of always forcing OFF at window end
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Scheduler:
- Import sun.js calculator (already existed, never wired in)
- resolveSecs() maps -2=sunrise/-3=sunset sentinels + offset to actual seconds
- getTodaySun() reads stored location from store
- _loadSchedule(), _resumeAwayLoops(), _startAwayLoop() all resolve sun times
Server:
- Add /sun-times endpoint returning today's sunrise/sunset in seconds
UI:
- Start Time and End Time fields now show Fixed/Sunrise/Sunset dropdown
- Offset field (minutes before/after) shown when sun type selected
- Live preview shows today's base time + fires-at time with offset
- Save handler writes -2/-3 sentinels + startType/endType/startOffset/endOffset
- openDwmEdit() restores sun type and offset when editing existing rules
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>