Просмотр исходного кода

Fix WLED presets and MQTT idle state not triggering during playlist execution

- WLED presets 1 (idle) and 2 (playing) were not being triggered because
  the code checked for dw_led_*_effect configs which are only used by
  embedded DW_LED system, not WLED's hardcoded presets
- Added check for led_provider == "wled" as alternative condition
- MQTT/HA integration now correctly reports "idle" between playlist
  patterns by clearing current_playing_file during pause periods
- LED idle preset also triggers during pauses between patterns

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
tuanchris 1 день назад
Родитель
Сommit
1c110dec10
2 измененных файлов с 28 добавлено и 10 удалено
  1. 1 1
      VERSION
  2. 27 9
      modules/core/pattern_manager.py

+ 1 - 1
VERSION

@@ -1 +1 @@
-4.0.2
+4.0.3

+ 27 - 9
modules/core/pattern_manager.py

@@ -359,8 +359,10 @@ async def start_idle_led_timeout(check_still_sands: bool = True):
         await state.led_controller.set_power_async(0)
         return
 
-    # Normal flow: show idle effect (only if one is configured)
-    if not state.dw_led_idle_effect:
+    # Normal flow: show idle effect
+    # For WLED: always trigger (uses hardcoded preset 1)
+    # For DW_LED: only trigger if effect is configured
+    if state.led_provider != "wled" and not state.dw_led_idle_effect:
         logger.debug("No idle effect configured, leaving LEDs unchanged")
         return
     await state.led_controller.effect_idle_async(state.dw_led_idle_effect)
@@ -1225,7 +1227,9 @@ async def _execute_pattern_internal(file_path):
     total_pause_time = 0  # Track total time spent paused (manual + scheduled)
     completed_weight = 0.0  # Track rho-weighted progress
     smoothed_rate = None  # For exponential smoothing of time-per-unit-weight rate
-    if state.led_controller and state.dw_led_playing_effect:
+    # For WLED: always trigger (uses hardcoded preset 2)
+    # For DW_LED: only trigger if effect is configured
+    if state.led_controller and (state.led_provider == "wled" or state.dw_led_playing_effect):
         logger.info(f"Setting LED to playing effect: {state.dw_led_playing_effect}")
         await state.led_controller.effect_playing_async(state.dw_led_playing_effect)
         # Cancel idle timeout when playing starts
@@ -1337,9 +1341,11 @@ async def _execute_pattern_internal(file_path):
                 logger.info("Execution resumed...")
                 if state.led_controller:
                     # Turn LED controller back on if it was turned off for scheduled pause
-                    # Only power on if a playing effect is configured, otherwise leave LEDs off
+                    # For WLED: always trigger (uses hardcoded preset 2)
+                    # For DW_LED: only trigger if effect is configured
+                    should_trigger_led = state.led_provider == "wled" or state.dw_led_playing_effect
                     if wled_was_off_for_scheduled:
-                        if state.dw_led_playing_effect:
+                        if should_trigger_led:
                             logger.info("Turning LED lights back on as Still Sands period ended")
                             await state.led_controller.set_power_async(1)
                             # CRITICAL: Give LED controller time to fully power on before sending more commands
@@ -1347,7 +1353,7 @@ async def _execute_pattern_internal(file_path):
                             await asyncio.sleep(0.5)
                         else:
                             logger.info("No playing effect configured, keeping LEDs off after Still Sands")
-                    if state.dw_led_playing_effect:
+                    if should_trigger_led:
                         await state.led_controller.effect_playing_async(state.dw_led_playing_effect)
                     # Cancel idle timeout when resuming from pause
                     idle_timeout_manager.cancel_timeout()
@@ -1591,21 +1597,28 @@ async def run_theta_rho_files(file_paths, pause_time=0, clear_pattern=None, run_
                     if result == 'completed':
                         logger.info("Still Sands period ended. Resuming playlist...")
                         if state.led_controller:
-                            # Only power on if a playing effect is configured, otherwise leave LEDs off
+                            # For WLED: always trigger (uses hardcoded preset 2)
+                            # For DW_LED: only trigger if effect is configured
+                            should_trigger_led = state.led_provider == "wled" or state.dw_led_playing_effect
                             if wled_was_off_for_scheduled:
-                                if state.dw_led_playing_effect:
+                                if should_trigger_led:
                                     logger.info("Turning LED lights back on as Still Sands period ended")
                                     await state.led_controller.set_power_async(1)
                                     await asyncio.sleep(0.5)
                                 else:
                                     logger.info("No playing effect configured, keeping LEDs off after Still Sands")
-                            if state.dw_led_playing_effect:
+                            if should_trigger_led:
                                 await state.led_controller.effect_playing_async(state.dw_led_playing_effect)
                             idle_timeout_manager.cancel_timeout()
 
                 # Handle pause between patterns
                 if state.current_playlist and idx < len(state.current_playlist) - 1 and not state.stop_requested and pause_time > 0 and not state.skip_requested:
                     logger.info(f"Pausing for {pause_time} seconds")
+                    # Clear current_playing_file to report "idle" state to MQTT/HA during pause
+                    # This will be set again when the next pattern starts
+                    state.current_playing_file = None
+                    # Trigger idle LED state during pause between patterns
+                    await start_idle_led_timeout(check_still_sands=False)
                     state.original_pause_time = pause_time
                     pause_start = time.time()
                     while time.time() - pause_start < pause_time:
@@ -1641,6 +1654,11 @@ async def run_theta_rho_files(file_paths, pause_time=0, clear_pattern=None, run_
             if run_mode == "indefinite":
                 logger.info("Playlist completed. Restarting as per 'indefinite' run mode")
                 if pause_time > 0:
+                    # Clear current_playing_file to report "idle" state to MQTT/HA during pause
+                    state.current_playing_file = None
+                    # Trigger idle LED state during pause between playlist cycles
+                    await start_idle_led_timeout(check_still_sands=False)
+                    state.original_pause_time = pause_time
                     pause_start = time.time()
                     while time.time() - pause_start < pause_time:
                         state.pause_time_remaining = pause_start + pause_time - time.time()