Explorar el Código

Add skip button to MQTT/Home Assistant integration

Expose the existing skip functionality (skip to next pattern in a
playlist) as a Home Assistant button entity via MQTT. The button is
only available when a playlist is actively running.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
tuanchris hace 5 meses
padre
commit
83650d88e1
Se han modificado 2 ficheros con 36 adiciones y 2 borrados
  1. 32 2
      modules/mqtt/handler.py
  2. 4 0
      modules/mqtt/utils.py

+ 32 - 2
modules/mqtt/handler.py

@@ -166,6 +166,23 @@ class MQTTHandler(BaseMQTTHandler):
         }
         self._publish_discovery("button", "play", play_config)
 
+        # Skip Button
+        skip_config = {
+            "name": "Skip to next pattern",
+            "unique_id": f"{self.device_id}_skip",
+            "command_topic": f"{self.device_id}/command/skip",
+            "device": base_device,
+            "icon": "mdi:skip-next",
+            "entity_category": "config",
+            "enabled_by_default": True,
+            "availability": {
+                "topic": f"{self.device_id}/command/skip/available",
+                "payload_available": "true",
+                "payload_not_available": "false"
+            }
+        }
+        self._publish_discovery("button", "skip", skip_config)
+
         # Speed Control
         speed_config = {
             "name": f"{self.device_name} Speed",
@@ -407,8 +424,12 @@ class MQTTHandler(BaseMQTTHandler):
         self.client.publish(f"{self.device_id}/command/pause/available", 
                           "true" if running_state == "running" else "false", 
                           retain=True)
-        self.client.publish(f"{self.device_id}/command/play/available", 
-                          "true" if running_state == "paused" else "false", 
+        self.client.publish(f"{self.device_id}/command/play/available",
+                          "true" if running_state == "paused" else "false",
+                          retain=True)
+        # Skip is available when running and a playlist is active
+        self.client.publish(f"{self.device_id}/command/skip/available",
+                          "true" if running_state in ("running", "paused") and bool(self.state.current_playlist) else "false",
                           retain=True)
                           
     def _publish_pattern_state(self, current_file=None):
@@ -562,6 +583,7 @@ class MQTTHandler(BaseMQTTHandler):
                 (f"{self.device_id}/command/stop", 0),
                 (f"{self.device_id}/command/pause", 0),
                 (f"{self.device_id}/command/play", 0),
+                (f"{self.device_id}/command/skip", 0),
                 (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),
@@ -660,6 +682,14 @@ class MQTTHandler(BaseMQTTHandler):
                         asyncio.run_coroutine_threadsafe(callback(), self.main_loop)
                     else:
                         callback()
+            elif msg.topic == f"{self.device_id}/command/skip":
+                # Handle skip command - only if a playlist is running
+                if self.state.current_playlist:
+                    callback = self.callback_registry['skip']
+                    if asyncio.iscoroutinefunction(callback):
+                        asyncio.run_coroutine_threadsafe(callback(), self.main_loop)
+                    else:
+                        callback()
             elif msg.topic == f"{self.device_id}/playlist/mode/set":
                 mode = msg.payload.decode()
                 if mode in ["single", "loop"]:

+ 4 - 0
modules/mqtt/utils.py

@@ -20,12 +20,16 @@ def create_mqtt_callbacks() -> Dict[str, Callable]:
     def set_speed(speed):
         state.speed = speed
 
+    def skip_pattern():
+        state.skip_requested = True
+
     return {
         'run_pattern': run_theta_rho_file,  # async function
         'run_playlist': run_playlist,  # async function
         'stop': stop_actions,  # sync function
         'pause': pause_execution,  # sync function
         'resume': resume_execution,  # sync function
+        'skip': skip_pattern,  # sync function
         'home': home,
         'set_speed': set_speed
     }