fix(schedule): hot-reload config in schedule/dim checks + normalize per-day mode variant (#266)

* fix(web): handle string boolean values in schedule-picker widget

The normalizeSchedule function used strict equality (===) to check the
enabled field, which would fail if the config value was a string "true"
instead of boolean true. This could cause the checkbox to always appear
unchecked even when the setting was enabled.

Added coerceToBoolean helper that properly handles:
- Boolean true/false (returns as-is)
- String "true", "1", "on" (case-insensitive) → true
- String "false" or other values → false

Applied to both main schedule enabled and per-day enabled fields.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: trim whitespace in coerceToBoolean string handling

* fix: normalize mode value to handle per_day and per-day variants

* fix: use hot-reload config for schedule and dim schedule checks

The display controller was caching the config at startup and not picking
up changes made via the web UI. Now _check_schedule and _check_dim_schedule
read from config_service.get_config() to get the latest configuration,
allowing schedule changes to take effect without restarting the service.

---------

Co-authored-by: Chuck <chuck@example.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Chuck
2026-02-23 17:22:39 -05:00
committed by GitHub
parent 4c4efd614a
commit b92ff3dfbd

View File

@@ -436,7 +436,10 @@ class DisplayController:
def _check_schedule(self): def _check_schedule(self):
"""Check if display should be active based on schedule.""" """Check if display should be active based on schedule."""
schedule_config = self.config.get('schedule', {}) # Get fresh config from config_service to support hot-reload
current_config = self.config_service.get_config()
schedule_config = current_config.get('schedule', {})
# If schedule config doesn't exist or is empty, default to always active # If schedule config doesn't exist or is empty, default to always active
if not schedule_config: if not schedule_config:
@@ -453,7 +456,7 @@ class DisplayController:
return return
# Get configured timezone, default to UTC # Get configured timezone, default to UTC
timezone_str = self.config.get('timezone', 'UTC') timezone_str = current_config.get('timezone', 'UTC')
try: try:
tz = pytz.timezone(timezone_str) tz = pytz.timezone(timezone_str)
except pytz.UnknownTimeZoneError: except pytz.UnknownTimeZoneError:
@@ -551,15 +554,18 @@ class DisplayController:
Target brightness level (dim_brightness if in dim period, Target brightness level (dim_brightness if in dim period,
normal brightness otherwise) normal brightness otherwise)
""" """
# Get fresh config from config_service to support hot-reload
current_config = self.config_service.get_config()
# Get normal brightness from config # Get normal brightness from config
normal_brightness = self.config.get('display', {}).get('hardware', {}).get('brightness', 90) normal_brightness = current_config.get('display', {}).get('hardware', {}).get('brightness', 90)
# If display is OFF via schedule, don't process dim schedule # If display is OFF via schedule, don't process dim schedule
if not self.is_display_active: if not self.is_display_active:
self.is_dimmed = False self.is_dimmed = False
return normal_brightness return normal_brightness
dim_config = self.config.get('dim_schedule', {}) dim_config = current_config.get('dim_schedule', {})
# If dim schedule doesn't exist or is disabled, use normal brightness # If dim schedule doesn't exist or is disabled, use normal brightness
if not dim_config or not dim_config.get('enabled', False): if not dim_config or not dim_config.get('enabled', False):
@@ -567,7 +573,7 @@ class DisplayController:
return normal_brightness return normal_brightness
# Get configured timezone # Get configured timezone
timezone_str = self.config.get('timezone', 'UTC') timezone_str = current_config.get('timezone', 'UTC')
try: try:
tz = pytz.timezone(timezone_str) tz = pytz.timezone(timezone_str)
except pytz.UnknownTimeZoneError: except pytz.UnknownTimeZoneError: