feat: add MQTT integration for real-time entity updates

- aiomqtt async client with auto-reconnect and topic store
- MQTT router: GET /api/mqtt, GET /api/mqtt/topic/{path}, POST /api/mqtt/publish
- MQTT entities included in /api/all + WebSocket broadcast
- MqttCard frontend component with category filters, entity list
- Configurable via ENV: MQTT_HOST, MQTT_PORT, MQTT_USERNAME,
  MQTT_PASSWORD, MQTT_TOPICS (comma-separated or JSON array)
- Gracefully disabled when MQTT_HOST is not set

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sam 2026-03-02 10:13:50 +01:00
parent 9f7330e217
commit 89ed0c6d0a
11 changed files with 542 additions and 1 deletions

View file

@ -12,6 +12,7 @@ from fastapi.staticfiles import StaticFiles
from server.config import settings
from server.services import news_service
from server.services.mqtt_service import mqtt_service
logger = logging.getLogger("daily-briefing")
logging.basicConfig(
@ -42,10 +43,28 @@ async def lifespan(app: FastAPI):
except Exception:
logger.exception("Failed to initialize database pool — news will be unavailable")
# Start MQTT service
if settings.mqtt_host:
try:
await mqtt_service.start(
host=settings.mqtt_host,
port=settings.mqtt_port,
username=settings.mqtt_username or None,
password=settings.mqtt_password or None,
topics=settings.mqtt_topics,
client_id=settings.mqtt_client_id,
)
logger.info("MQTT service started (broker %s:%d)", settings.mqtt_host, settings.mqtt_port)
except Exception:
logger.exception("Failed to start MQTT service — MQTT will be unavailable")
else:
logger.info("MQTT disabled — set MQTT_HOST to enable")
yield
# Shutdown
logger.info("Shutting down...")
await mqtt_service.stop()
await news_service.close_pool()
@ -65,13 +84,14 @@ app.add_middleware(
)
# --- Register Routers ---
from server.routers import dashboard, homeassistant, news, servers, tasks, weather # noqa: E402
from server.routers import dashboard, homeassistant, mqtt, news, servers, tasks, weather # noqa: E402
app.include_router(weather.router)
app.include_router(news.router)
app.include_router(servers.router)
app.include_router(homeassistant.router)
app.include_router(tasks.router)
app.include_router(mqtt.router)
app.include_router(dashboard.router)
# --- Serve static frontend (production) ---