From b92ff3dfbd4907730677d4157ea82387c086dc3b Mon Sep 17 00:00:00 2001 From: Chuck <33324927+ChuckBuilds@users.noreply.github.com> Date: Mon, 23 Feb 2026 17:22:39 -0500 Subject: [PATCH] fix(schedule): hot-reload config in schedule/dim checks + normalize per-day mode variant (#266) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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 * 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 Co-authored-by: Claude Opus 4.5 --- src/display_controller.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/display_controller.py b/src/display_controller.py index 0e9bedfb..900b952a 100644 --- a/src/display_controller.py +++ b/src/display_controller.py @@ -436,14 +436,17 @@ class DisplayController: def _check_schedule(self): """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 not schedule_config: self.is_display_active = True self._was_display_active = True # Track previous state for schedule change detection return - + # Check if schedule is explicitly disabled # Default to True (schedule enabled) if 'enabled' key is missing for backward compatibility if 'enabled' in schedule_config and not schedule_config.get('enabled', True): @@ -453,7 +456,7 @@ class DisplayController: return # Get configured timezone, default to UTC - timezone_str = self.config.get('timezone', 'UTC') + timezone_str = current_config.get('timezone', 'UTC') try: tz = pytz.timezone(timezone_str) except pytz.UnknownTimeZoneError: @@ -551,15 +554,18 @@ class DisplayController: Target brightness level (dim_brightness if in dim period, 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 - 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 not self.is_display_active: self.is_dimmed = False 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 not dim_config or not dim_config.get('enabled', False): @@ -567,7 +573,7 @@ class DisplayController: return normal_brightness # Get configured timezone - timezone_str = self.config.get('timezone', 'UTC') + timezone_str = current_config.get('timezone', 'UTC') try: tz = pytz.timezone(timezone_str) except pytz.UnknownTimeZoneError: