wangrong
2026-08-24 beef6536e7c8dd3f5cbe8f73585611479910bea7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import logging
from contextlib import asynccontextmanager
from pathlib import Path
 
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
 
from app.config import settings
from app.mqtt.client import MqttService
from app.mqtt.init_dispatcher import InitTaskDispatcher
from app.routes import courses, devices, dialogue, scene
from app.services.auto_init import AutoInitService
from app.services.course_service import CourseService
from app.services.device_store import DeviceStore
from app.services.init_registry import InitRegistry
 
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s: %(message)s")
logger = logging.getLogger(__name__)
 
 
@asynccontextmanager
async def lifespan(app: FastAPI):
    device_store = DeviceStore()
    init_registry = InitRegistry()
    course_service = CourseService()
    mqtt_service = MqttService(device_store)
    init_dispatcher = InitTaskDispatcher(mqtt_service, course_service)
    auto_init = AutoInitService(init_registry, init_dispatcher, mqtt_service)
    mqtt_service.auto_init = auto_init
 
    app.state.device_store = device_store
    app.state.init_registry = init_registry
    app.state.mqtt = mqtt_service
    app.state.init_dispatcher = init_dispatcher
    app.state.auto_init = auto_init
 
    mqtt_service.start()
    logger.info("SmartLearning server started")
    yield
    mqtt_service.stop()
    logger.info("SmartLearning server stopped")
 
 
app = FastAPI(
    title="SmartLearning Server",
    description="情境感知智能英语学习系统 - 服务端",
    version="1.0.0",
    lifespan=lifespan,
)
 
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
 
app.include_router(scene.router)
app.include_router(dialogue.router)
app.include_router(courses.router)
app.include_router(devices.router)
 
data_path = Path(settings.data_dir)
if data_path.exists():
    app.mount("/static", StaticFiles(directory=str(data_path)), name="static")
 
 
@app.get("/health")
async def health():
    mqtt = app.state.mqtt if hasattr(app.state, "mqtt") else None
    return {
        "status": "ok",
        "mqtt_connected": mqtt.connected if mqtt else False,
    }