2 Commits ef8787a6c1 ... 42f1374fbe

Author SHA1 Message Date
  tuanchris 42f1374fbe Add /dev/ttyS0 to ignored serial ports list 1 week ago
  tuanchris 3c55e3f03e Fix shuffle not working when starting playlist from Home Assistant 1 week ago
3 changed files with 43 additions and 2 deletions
  1. 1 1
      modules/connection/connection_manager.py
  2. 11 0
      modules/core/state.py
  3. 31 1
      modules/mqtt/handler.py

+ 1 - 1
modules/connection/connection_manager.py

@@ -14,7 +14,7 @@ from modules.led.idle_timeout_manager import idle_timeout_manager
 
 logger = logging.getLogger(__name__)
 
-IGNORE_PORTS = ['/dev/cu.debug-console', '/dev/cu.Bluetooth-Incoming-Port']
+IGNORE_PORTS = ['/dev/cu.debug-console', '/dev/cu.Bluetooth-Incoming-Port', '/dev/ttyS0']
 
 
 async def _check_table_is_idle() -> bool:

+ 11 - 0
modules/core/state.py

@@ -89,6 +89,7 @@ class AppState:
         self._pause_time = 0
         self._clear_pattern = "none"
         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_out = None  # Custom clear from perimeter pattern
         
@@ -221,6 +222,14 @@ class AppState:
     def clear_pattern_speed(self, 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):
         """Return a dictionary representation of the state."""
         return {
@@ -248,6 +257,7 @@ class AppState:
             "pause_time": self._pause_time,
             "clear_pattern": self._clear_pattern,
             "clear_pattern_speed": self._clear_pattern_speed,
+            "shuffle": self._shuffle,
             "custom_clear_from_in": self.custom_clear_from_in,
             "custom_clear_from_out": self.custom_clear_from_out,
             "port": self.port,
@@ -315,6 +325,7 @@ class AppState:
         self._pause_time = data.get("pause_time", 0)
         self._clear_pattern = data.get("clear_pattern", "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_out = data.get("custom_clear_from_out", 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)
 
+        # 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_config = {
             "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.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):
         """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":
@@ -544,6 +566,7 @@ class MQTTHandler(BaseMQTTHandler):
                 (f"{self.device_id}/playlist/mode/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/shuffle/set", 0),
                 (self.led_power_topic, 0),
                 (self.led_brightness_topic, 0),
                 (self.led_effect_topic, 0),
@@ -599,7 +622,8 @@ class MQTTHandler(BaseMQTTHandler):
                             playlist_name=playlist_name,
                             run_mode=self.state.playlist_mode,
                             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
                     ).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"]:
                     state.clear_pattern = clear_pattern
                     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:
                 # Handle LED power command (DW LEDs only)
                 payload = msg.payload.decode()
@@ -798,6 +827,7 @@ class MQTTHandler(BaseMQTTHandler):
             self._publish_playlist_state()
             self._publish_serial_state()
             self._publish_progress_state()
+            self._publish_playlist_settings_state()
             self._publish_led_state()
 
             # Setup Home Assistant discovery