From 451197cc31a01bf797bb0c88c40af8ca304ae0a8 Mon Sep 17 00:00:00 2001 From: sylvain Date: Mon, 9 Mar 2026 12:38:56 +0000 Subject: [PATCH] Add mqtt_subscribe and muc_send skills - mqtt_subscribe: dynamically subscribe/unsubscribe to any MQTT topic, received messages are forwarded to XMPP admins - muc_send: post a message to the XMPP MUC group (agents@muc.xmpp.ovh) Co-Authored-By: Claude Sonnet 4.6 --- skills/mqtt_subscribe.py | 59 ++++++++++++++++++++++++++++++++++++++++ skills/muc_send.py | 24 ++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 skills/mqtt_subscribe.py create mode 100644 skills/muc_send.py diff --git a/skills/mqtt_subscribe.py b/skills/mqtt_subscribe.py new file mode 100644 index 0000000..0b0c148 --- /dev/null +++ b/skills/mqtt_subscribe.py @@ -0,0 +1,59 @@ +""" +Skill MQTT_SUBSCRIBE — s'abonner dynamiquement à un topic MQTT. + +Les messages reçus sont transmis via XMPP (admin) et loggés. + +Usage LLM : + SKILL:mqtt_subscribe ARGS:subscribe | + SKILL:mqtt_subscribe ARGS:unsubscribe | + SKILL:mqtt_subscribe ARGS:list +""" +import logging + +DESCRIPTION = "S'abonner / se désabonner dynamiquement d'un topic MQTT et recevoir les messages" +USAGE = "SKILL:mqtt_subscribe ARGS:subscribe| ou unsubscribe| ou list" + +logger = logging.getLogger(__name__) + +# Stockage des souscriptions dynamiques : {topic: callback} +_dynamic_subs: dict = {} + + +def run(args: str, context) -> str: + parts = [p.strip() for p in args.split("|", 1)] + action = parts[0].lower() + + if action == "list": + if not _dynamic_subs: + return "Aucun topic MQTT surveillé." + return "Topics surveillés :\n" + "\n".join(f" • {t}" for t in _dynamic_subs) + + if len(parts) < 2 or not parts[1]: + return "Format : subscribe| ou unsubscribe| ou list" + + topic = parts[1] + + if action == "unsubscribe": + if topic in _dynamic_subs: + del _dynamic_subs[topic] + return f"Désabonné du topic '{topic}'." + return f"Pas abonné à '{topic}'." + + if action == "subscribe": + if topic in _dynamic_subs: + return f"Déjà abonné à '{topic}'." + + agent_id = context.agent_id + + def _on_message(msg, t): + payload = msg.payload if hasattr(msg, "payload") else str(msg) + text = f"[MQTT:{t}] {payload}" + logger.info(f"[mqtt_subscribe] {text}") + if context.xmpp: + context.xmpp.send_to_all_admins(text) + + _dynamic_subs[topic] = _on_message + context.mqtt.subscribe(topic, _on_message) + return f"Abonné au topic '{topic}'. Les messages seront transmis via XMPP." + + return f"Action inconnue '{action}'. Utilise : subscribe, unsubscribe, list." diff --git a/skills/muc_send.py b/skills/muc_send.py new file mode 100644 index 0000000..799edbe --- /dev/null +++ b/skills/muc_send.py @@ -0,0 +1,24 @@ +""" +Skill MUC_SEND — envoyer un message dans le groupe XMPP des agents. + +Le groupe est agents@muc.xmpp.ovh (configuré dans config.json). + +Usage LLM : SKILL:muc_send ARGS: +""" +DESCRIPTION = "Envoyer un message dans le groupe XMPP des agents (MUC)" +USAGE = "SKILL:muc_send ARGS:" + + +def run(args: str, context) -> str: + message = args.strip() + if not message: + return "Message vide." + + if not context.xmpp: + return "XMPP non configuré sur cet agent." + + if not context.xmpp.muc_room: + return "Aucun groupe MUC configuré." + + context.xmpp.send_to_group(message) + return f"Message envoyé dans le groupe {context.xmpp.muc_room}."