wangzhibo
2026-10-08 220e4fab27b7f419b3e89e2f2d28ae789aac09d7
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
77
78
79
from fastapi import APIRouter, HTTPException, Request
 
from app.config import settings
from app.models.schemas import InitTaskRequest
from app.mqtt.init_dispatcher import InitTaskDispatcher
from app.services.course_service import CourseService
 
router = APIRouter(prefix="/api/v1", tags=["courses"])
course_service = CourseService()
 
 
def _get_dispatcher(request: Request) -> InitTaskDispatcher:
    return request.app.state.init_dispatcher
 
 
@router.get("/courses")
async def list_courses():
    return course_service.get_course_index()
 
 
@router.get("/courses/base-manifest")
async def get_base_courses_manifest():
    payloads = course_service.build_base_course_sync_payloads(settings.base_url)
    return {
        "scope": "base",
        "course_count": len(payloads),
        "courses": payloads,
    }
 
 
@router.get("/courses/{course_id}")
async def get_course(course_id: str):
    try:
        return course_service.get_course(course_id)
    except FileNotFoundError as exc:
        raise HTTPException(status_code=404, detail=str(exc)) from exc
 
 
@router.get("/tasklist")
async def get_tasklist():
    return course_service.get_tasklist()
 
 
@router.get("/courses/{course_id}/tasks")
async def get_course_tasks(course_id: str):
    try:
        return course_service.get_course_task(course_id)
    except FileNotFoundError as exc:
        raise HTTPException(status_code=404, detail=str(exc)) from exc
 
 
@router.get("/courses/{course_id}/manifest")
async def get_course_manifest(course_id: str):
    try:
        payload = course_service.build_course_task_sync_payload(course_id, settings.base_url)
        return payload
    except FileNotFoundError as exc:
        raise HTTPException(status_code=404, detail=str(exc)) from exc
 
 
@router.post("/devices/init")
async def init_device(request: Request, body: InitTaskRequest):
    auto_init = request.app.state.auto_init
    commands, status = auto_init.dispatch_manual_init(body.device_id, force=body.force)
    return {"device_id": body.device_id, "commands": commands, "status": status}
 
 
@router.post("/devices/course-init")
async def init_course_on_device(request: Request, body: InitTaskRequest):
    if not body.course_id:
        raise HTTPException(status_code=400, detail="course_id is required")
    dispatcher = _get_dispatcher(request)
    commands = dispatcher.dispatch_course_init(body.device_id, body.course_id)
    return {
        "device_id": body.device_id,
        "course_id": body.course_id,
        "commands": commands,
        "status": "dispatched",
    }