feat: FastAPI app with REST API routes and WebSocket endpoint

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
walkpan
2026-03-29 21:46:00 +08:00
parent abb170ace6
commit 957f489a0d
8 changed files with 394 additions and 0 deletions

84
src/mqtt_home/main.py Normal file
View File

@@ -0,0 +1,84 @@
import asyncio
import logging
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from mqtt_home.config import get_settings
from mqtt_home.database import init_db, get_session_factory, Base
from mqtt_home.mqtt_client import MqttClient
from mqtt_home.emqx_api import EmqxApiClient
from mqtt_home.discovery import handle_discovery_message
from mqtt_home.device_registry import handle_state_update
from mqtt_home.api import api_router
from mqtt_home.ws import websocket_endpoint, broadcast_device_update
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s: %(message)s")
logger = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI):
settings = get_settings()
await init_db()
logger.info("Database initialized")
emqx = EmqxApiClient(settings)
app.state.emqx_client = emqx
logger.info("EMQX API client initialized")
mqtt = MqttClient(settings)
app.state.mqtt_client = mqtt
session_factory = get_session_factory()
async def on_discovery(topic: str, payload: str):
async with session_factory() as db:
await handle_discovery_message(topic, payload, db, mqtt)
async def on_state(topic: str, payload: str):
async with session_factory() as db:
device = await handle_state_update(db, topic, payload)
if device:
await broadcast_device_update(device.id, {
"state": device.state,
"is_online": device.is_online,
"last_seen": device.last_seen.isoformat() if device.last_seen else None,
})
mqtt.on_message("homeassistant/#", on_discovery)
mqtt.on_message("home/#", on_state)
await mqtt.start()
logger.info("MQTT client started")
yield
await mqtt.stop()
await emqx.close()
logger.info("Shutdown complete")
app = FastAPI(title="MQTT Home", version="0.1.0", lifespan=lifespan)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(api_router)
app.websocket("/ws/devices")(websocket_endpoint)
@app.get("/health")
async def health():
mqtt = getattr(app.state, "mqtt_client", None)
return {
"status": "ok",
"mqtt_connected": mqtt.is_connected if mqtt else False,
}