فهرست منبع

Fix shuffle not working when starting playlist from Home Assistant

The MQTT handler was not passing the shuffle parameter when running
playlists. Added shuffle state property and HA entity for control.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
tuanchris 1 هفته پیش
والد
کامیت
3c55e3f03e
2فایلهای تغییر یافته به همراه42 افزوده شده و 1 حذف شده
  1. 11 0
      modules/core/state.py
  2. 31 1
      modules/mqtt/handler.py

+ 11 - 0
modules/core/state.py

@@ -89,6 +89,7 @@ class AppState:
         self._pause_time = 0
         self._pause_time = 0
         self._clear_pattern = "none"
         self._clear_pattern = "none"
         self._clear_pattern_speed = None  # None means use state.speed as default
         self._clear_pattern_speed = None  # None means use state.speed as default
+        self._shuffle = False  # Shuffle playlist order
         self.custom_clear_from_in = None  # Custom clear from center pattern
         self.custom_clear_from_in = None  # Custom clear from center pattern
         self.custom_clear_from_out = None  # Custom clear from perimeter pattern
         self.custom_clear_from_out = None  # Custom clear from perimeter pattern
         
         
@@ -221,6 +222,14 @@ class AppState:
     def clear_pattern_speed(self, value):
     def clear_pattern_speed(self, value):
         self._clear_pattern_speed = value
         self._clear_pattern_speed = value
 
 
+    @property
+    def shuffle(self):
+        return self._shuffle
+
+    @shuffle.setter
+    def shuffle(self, value):
+        self._shuffle = value
+
     def to_dict(self):
     def to_dict(self):
         """Return a dictionary representation of the state."""
         """Return a dictionary representation of the state."""
         return {
         return {
@@ -248,6 +257,7 @@ class AppState:
             "pause_time": self._pause_time,
             "pause_time": self._pause_time,
             "clear_pattern": self._clear_pattern,
             "clear_pattern": self._clear_pattern,
             "clear_pattern_speed": self._clear_pattern_speed,
             "clear_pattern_speed": self._clear_pattern_speed,
+            "shuffle": self._shuffle,
             "custom_clear_from_in": self.custom_clear_from_in,
             "custom_clear_from_in": self.custom_clear_from_in,
             "custom_clear_from_out": self.custom_clear_from_out,
             "custom_clear_from_out": self.custom_clear_from_out,
             "port": self.port,
             "port": self.port,
@@ -315,6 +325,7 @@ class AppState:
         self._pause_time = data.get("pause_time", 0)
         self._pause_time = data.get("pause_time", 0)
         self._clear_pattern = data.get("clear_pattern", "none")
         self._clear_pattern = data.get("clear_pattern", "none")
         self._clear_pattern_speed = data.get("clear_pattern_speed", None)
         self._clear_pattern_speed = data.get("clear_pattern_speed", None)
+        self._shuffle = data.get("shuffle", False)
         self.custom_clear_from_in = data.get("custom_clear_from_in", None)
         self.custom_clear_from_in = data.get("custom_clear_from_in", None)
         self.custom_clear_from_out = data.get("custom_clear_from_out", None)
         self.custom_clear_from_out = data.get("custom_clear_from_out", None)
         self.port = data.get("port", None)
         self.port = data.get("port", None)

+ 31 - 1
modules/mqtt/handler.py

@@ -248,6 +248,20 @@ class MQTTHandler(BaseMQTTHandler):
         }
         }
         self._publish_discovery("select", "clear_pattern", clear_pattern_config)
         self._publish_discovery("select", "clear_pattern", clear_pattern_config)
 
 
+        # Shuffle Switch
+        shuffle_config = {
+            "name": f"{self.device_name} Shuffle",
+            "unique_id": f"{self.device_id}_shuffle",
+            "command_topic": f"{self.device_id}/playlist/shuffle/set",
+            "state_topic": f"{self.device_id}/playlist/shuffle/state",
+            "payload_on": "ON",
+            "payload_off": "OFF",
+            "device": base_device,
+            "icon": "mdi:shuffle-variant",
+            "entity_category": "config"
+        }
+        self._publish_discovery("switch", "shuffle", shuffle_config)
+
         # Completion Percentage Sensor
         # Completion Percentage Sensor
         completion_config = {
         completion_config = {
             "name": f"{self.device_name} Completion",
             "name": f"{self.device_name} Completion",
@@ -448,6 +462,14 @@ class MQTTHandler(BaseMQTTHandler):
             self.client.publish(self.completion_topic, 0, retain=True)
             self.client.publish(self.completion_topic, 0, retain=True)
             self.client.publish(self.time_remaining_topic, 0, retain=True)
             self.client.publish(self.time_remaining_topic, 0, retain=True)
 
 
+    def _publish_playlist_settings_state(self):
+        """Helper to publish playlist settings state (mode, pause_time, clear_pattern, shuffle)."""
+        self.client.publish(f"{self.device_id}/playlist/mode/state", state.playlist_mode, retain=True)
+        self.client.publish(f"{self.device_id}/playlist/pause_time/state", state.pause_time, retain=True)
+        self.client.publish(f"{self.device_id}/playlist/clear_pattern/state", state.clear_pattern, retain=True)
+        shuffle_state = "ON" if state.shuffle else "OFF"
+        self.client.publish(f"{self.device_id}/playlist/shuffle/state", shuffle_state, retain=True)
+
     def _publish_led_state(self):
     def _publish_led_state(self):
         """Helper to publish LED state to MQTT (DW LEDs only - WLED has its own MQTT)."""
         """Helper to publish LED state to MQTT (DW LEDs only - WLED has its own MQTT)."""
         if not state.led_controller or state.led_provider != "dw_leds":
         if not state.led_controller or state.led_provider != "dw_leds":
@@ -544,6 +566,7 @@ class MQTTHandler(BaseMQTTHandler):
                 (f"{self.device_id}/playlist/mode/set", 0),
                 (f"{self.device_id}/playlist/mode/set", 0),
                 (f"{self.device_id}/playlist/pause_time/set", 0),
                 (f"{self.device_id}/playlist/pause_time/set", 0),
                 (f"{self.device_id}/playlist/clear_pattern/set", 0),
                 (f"{self.device_id}/playlist/clear_pattern/set", 0),
+                (f"{self.device_id}/playlist/shuffle/set", 0),
                 (self.led_power_topic, 0),
                 (self.led_power_topic, 0),
                 (self.led_brightness_topic, 0),
                 (self.led_brightness_topic, 0),
                 (self.led_effect_topic, 0),
                 (self.led_effect_topic, 0),
@@ -599,7 +622,8 @@ class MQTTHandler(BaseMQTTHandler):
                             playlist_name=playlist_name,
                             playlist_name=playlist_name,
                             run_mode=self.state.playlist_mode,
                             run_mode=self.state.playlist_mode,
                             pause_time=self.state.pause_time,
                             pause_time=self.state.pause_time,
-                            clear_pattern=self.state.clear_pattern
+                            clear_pattern=self.state.clear_pattern,
+                            shuffle=self.state.shuffle
                         ),
                         ),
                         self.main_loop
                         self.main_loop
                     ).add_done_callback(
                     ).add_done_callback(
@@ -652,6 +676,11 @@ class MQTTHandler(BaseMQTTHandler):
                 if clear_pattern in ["none", "random", "adaptive", "clear_from_in", "clear_from_out", "clear_sideway"]:
                 if clear_pattern in ["none", "random", "adaptive", "clear_from_in", "clear_from_out", "clear_sideway"]:
                     state.clear_pattern = clear_pattern
                     state.clear_pattern = clear_pattern
                     self.client.publish(f"{self.device_id}/playlist/clear_pattern/state", clear_pattern, retain=True)
                     self.client.publish(f"{self.device_id}/playlist/clear_pattern/state", clear_pattern, retain=True)
+            elif msg.topic == f"{self.device_id}/playlist/shuffle/set":
+                payload = msg.payload.decode()
+                shuffle_value = payload == "ON"
+                state.shuffle = shuffle_value
+                self.client.publish(f"{self.device_id}/playlist/shuffle/state", payload, retain=True)
             elif msg.topic == self.led_power_topic:
             elif msg.topic == self.led_power_topic:
                 # Handle LED power command (DW LEDs only)
                 # Handle LED power command (DW LEDs only)
                 payload = msg.payload.decode()
                 payload = msg.payload.decode()
@@ -798,6 +827,7 @@ class MQTTHandler(BaseMQTTHandler):
             self._publish_playlist_state()
             self._publish_playlist_state()
             self._publish_serial_state()
             self._publish_serial_state()
             self._publish_progress_state()
             self._publish_progress_state()
+            self._publish_playlist_settings_state()
             self._publish_led_state()
             self._publish_led_state()
 
 
             # Setup Home Assistant discovery
             # Setup Home Assistant discovery