ADR-0024 — Sincronización de estado Music Assistant ↔ Home Assistant para el DJ de Vera¶
Fecha: 2026-07-25
Estado: propuesto — no implementado, sin cambios aplicados
Ámbito: LXC 100 (Vera / dj MCP server), VM 208 (Music Assistant), VM 171 (Home Assistant)
Contexto¶
El DJ conversacional de Vera (documentación) habla
directamente con Music Assistant por su propia conexión WebSocket autenticada
(un JWT dedicado, vera-dj-skill), sin pasar por Home Assistant. Esto le da al
DJ telemetría rica e inmediata (elapsed_time exacto, estado en tiempo real —
verificado con números idénticos hasta el último decimal entre altavoces
sincronizados) sin depender de que HA esté arriba ni de su ciclo de refresco.
Problema descubierto: cuando el DJ reproduce/para música por su cuenta, las
entidades media_player.* de Home Assistant no reflejan el cambio. Se
verificó exhaustivamente antes de escribir este ADR:
- Altavoz sin agrupar (Cocina) reproduciendo de verdad (confirmado por
dj_now_playingy por consulta directa a MA) → HA sigue mostrandoidle, sin título ni artista. - Mismo resultado esperando 12+ segundos (descarta que sea solo latencia de sondeo).
- Mismo resultado tras un reload completo de la integración
(
homeassistant.reload_config_entry) — descarta que sea una suscripción "dormida" que un refresco despierte. - El mismo patrón se repite en altavoces agrupados (grupo persistente
sync_group) y sin agrupar — no es un problema específico de los grupos, es general a cualquier acción disparada desde fuera de la sesión propia de HA.
Hipótesis de causa raíz (no confirmada — no se inspeccionó el código fuente
de la integración music_assistant de HA ni el de Music Assistant): la
integración de HA mantiene su propia sesión/suscripción WebSocket con MA y
depende de eventos que MA le empuja a esa sesión concreta. Una segunda sesión
externa (la del DJ) puede disparar acciones reales en MA sin que necesariamente
se emita el mismo evento de "player actualizado" hacia la sesión de HA — o si se
emite, HA no lo está aplicando al estado de la entidad por alguna razón no
determinada. Esto queda como pregunta abierta, no como diagnóstico cerrado.
Qué NO es este problema¶
- No afecta a la funcionalidad del DJ en sí —
dj_now_playing, el volumen, los grupos sincronizados, todo funciona y se verifica correctamente por su propio canal. - No afecta a acciones iniciadas desde la propia HA (p. ej. si alguien pulsa play en el dashboard de HA o en la app móvil) — solo a las que dispara el DJ desde fuera.
Opciones consideradas¶
1. No hacer nada¶
Dejar el DJ como está: control y telemetría fiables por su cuenta, HA simplemente no se entera de esas reproducciones concretas.
- Pros: cero riesgo, cero esfuerzo, no toca código que ya funciona y está verificado en producción (Vera).
- Contras: cualquier automatización futura de HA que dependa de "¿está sonando música en tal sitio?" no vería las reproducciones del DJ. El dashboard de HA/tablet mostraría "idle" aunque haya música real sonando.
2. Reenrutar el DJ para que hable SIEMPRE a través de los servicios de HA¶
dj_play/dj_stop/dj_set_volume dejarían de llamar a la API de Music
Assistant directamente y llamarían a media_player.play_media /
media_player.turn_off / media_player.volume_set de Home Assistant, que a su
vez reenvía a MA por la conexión que HA sí escucha.
- Pros: sincronía garantizada por diseño — es HA quien dispara la acción, así que su propio estado se actualiza por definición. Sin ambigüedad de causa raíz que investigar.
- Contras:
- Riesgo real: reescribe un componente ya probado y en uso (
server.pyde Vera) en su ruta más crítica (reproducir/parar), con las precauciones ya conocidas de tocar un asistente en producción diaria. - Nueva dependencia dura: el DJ dejaría de funcionar si HA está caído o lento, cuando hoy es independiente de HA.
- Pérdida de telemetría rica: la comparación exacta de
elapsed_timeentre altavoces de un grupo (la prueba que demostró la sincronía real) se hizo consultando MA directamente — por los servicios de HA esa precisión no está garantizada de la misma forma. - Cambia el diseño "fino y sin estado" del servidor (documentado como
principio en
music-dj.md), añadiendo una dependencia de infraestructura a cada llamada.
3. Un "trigger" que sincronice HA aparte, sin tocar cómo reproduce el DJ¶
La idea que propone el usuario: mantener el DJ hablando directo con MA (control + telemetría como hasta ahora), y añadir un mecanismo aparte que empuje ese estado hacia HA después de cada acción. Tres variantes concretas, de más a menos robusta:
3a. Entidad propia del DJ en HA (recomendada si se decide seguir adelante)
El DJ, tras cada dj_play/dj_stop, escribe su propio estado a una entidad
que él mismo posee (p. ej. un sensor/input_text vía la API REST de HA, o
MQTT discovery — mismo patrón ya usado por el agente de Bazzite en este
homelab). Algo como sensor.dj_now_playing con atributos player/title/
artist/state, actualizado por el propio DJ.
- Pros: sortea la incertidumbre de causa raíz por completo — no depende de entender ni arreglar la suscripción de MA↔HA, solo añade una fuente de verdad nueva y fiable. Reutiliza un patrón que ya existe en esta casa (Bazzite → MQTT → HA). Cero riesgo para el DJ existente (es aditivo).
- Contras: es una entidad paralela, no "arregla" que
media_player.cocinamuestre el estado real — un dashboard que ya use esa entidad nativa seguiría sin verlo. Duplica la fuente de información (la entidad nativa de MA + la nueva del DJ) para las mismas reproducciones.
3b. Forzar refresco puntual de la entidad tras cada acción del DJ
(homeassistant.update_entity sobre la entidad concreta, no recarga completa)
- Pros: si funcionara, sería la solución "correcta" — arregla la entidad real, no una paralela.
- Contras: especulativo. Ya se probó la recarga completa de la
integración y no sirvió; es razonable sospechar (sin certeza) que si la
integración usa un modelo de actualización por push de eventos en vez de
sondeo,
update_entityno tendría nada que "sondear" y tampoco serviría. Requeriría probarlo para saberlo — no se ha hecho, por decisión explícita de no tocar nada en esta sesión.
3c. Webhook del DJ → automatización de HA que refresca desde dentro
El DJ llama a un webhook de HA (patrón ya existente:
webhooks.routes.alert en openclaw.json) tras cada acción; una
automatización de HA, ejecutándose dentro de su propio contexto, intenta
refrescar la entidad.
- Pros: mantiene la lógica de refresco dentro de HA (más fácil de depurar con sus propias herramientas).
- Contras: si el problema de fondo es que MA no emite el evento hacia la sesión de HA en absoluto (no solo que HA no procesa un evento ya recibido), esto tampoco lo arreglaría — es, en esencia, un intento más fino de la misma idea que la opción 3b, con el mismo riesgo de no funcionar por la misma razón no confirmada.
4. Investigar la causa raíz real antes de construir nada¶
Mirar el código fuente de la integración music_assistant de HA (o preguntar
en su GitHub/Discord) para entender exactamente cómo decide actualizar el
estado de una entidad, y si hay una forma nativa/soportada de notificarle un
cambio externo — en vez de adivinar con paliativos.
- Pros: la única opción que podría dar una solución "correcta" en vez de un parche; evita construir 3a/3b/3c a ciegas para descubrir después que ninguna aborda la causa real.
- Contras: coste de investigación desconocido de antemano; puede no haber una vía soportada y tener que llegar a la misma conclusión que las opciones 3 de todas formas.
Utilidad real — ¿esto merece la pena?¶
Antes de decidir cómo, vale la pena preguntar si. Hoy, ninguna automatización existente depende de que HA vea las reproducciones del DJ:
- Las dos automatizaciones de ejemplo que se dejaron pendientes de Music Assistant (modo noche, llegada a casa) se disparan por hora y presencia, no por "¿está sonando música?" — no las bloquea este gap.
- El propio DJ ya tiene su fuente de verdad fiable (
dj_now_playing) para cualquier cosa que Vera necesite saber sobre sí misma.
El valor real de arreglar esto sería:
- Consistencia visual — que el dashboard de HA (o la tablet, que ya lee entidades de HA en otras vistas) no muestre "idle" mientras suena música de verdad por orden del DJ. Esto es sobre todo relevante si en el futuro se quiere un widget "sonando ahora" en HA/tablet que también refleje lo que pone Vera, no solo lo que se reproduce desde la propia HA/tablet.
- Automatizaciones futuras condicionadas a reproducción — algo tipo "si el DJ pone música en el dormitorio de noche, atenúa las luces". Hoy esto no funcionaría con el DJ (aunque sí funcionaría si esa misma música se pusiera desde la app de HA en vez de por Vera).
Ninguno de los dos es una necesidad hoy — son mejoras de cara a usos futuros concretos, no una funcionalidad rota que bloquee algo actual.
Recomendación¶
No implementar nada todavía. Si en el futuro aparece un caso de uso concreto (un dashboard, una automatización) que realmente necesite ver el estado del DJ en HA, la opción 3a (entidad propia del DJ) es la más segura y aditiva — no depende de entender la causa raíz, no toca el DJ existente, y reutiliza un patrón ya probado en este homelab (Bazzite→MQTT→HA). La opción 2 (reenrutar todo por HA) solo se justificaría si ese caso de uso exige específicamente que sea la entidad nativa la que se actualice, no una paralela — y aun así, antes de tocar el DJ en producción, valdría la pena la opción 4 (investigar la causa raíz) primero, para no arriesgar el funcionamiento actual del DJ a cambio de un apaño que quizás ni siquiera resuelva el problema real.
Próximos pasos (si se decide seguir adelante en el futuro)¶
- Definir el caso de uso concreto que lo necesita (evita construir una solución genérica para un problema hipotético).
- Si se sigue adelante, empezar por la opción 4 (investigar causa raíz) antes que por un paliativo — más barato entender el problema que adivinar tres veces.
- Si no hay tiempo/interés en investigar, ir directo a 3a (entidad propia) por ser la opción de menor riesgo y mayor certeza de que funcionará.