编辑 | blame | 历史 | 原始文档

SmartLearning 接口文档

服务默认地址:http://{host}:{port}(默认 http://0.0.0.0:2101)
交互式 API 文档:启动服务后访问 /docs
协议版本:HTTP API v1 / MQTT snlp/v1


目录


一、通用说明

1.1 Base URL

环境 地址
本地开发 http://124.222.109.197:2101
生产部署 由 .env 中 BASE_URL 配置,终端下载资源须使用该地址

1.2 请求头

JSON 接口统一使用:

Content-Type: application/json

SSE 对话流接口返回:

Content-Type: text/event-stream

1.3 错误响应

FastAPI 标准错误格式:

{
  "detail": "Course not found: course99"
}

常见 HTTP 状态码:

状态码 说明
200 成功
400 请求参数错误
404 资源不存在
422 请求体校验失败

二、HTTP 接口

2.1 系统

GET /health

健康检查,查看服务与 MQTT 连接状态。

请求示例:

curl http://124.222.109.197:2101/health

响应示例:

{
  "status": "ok",
  "mqtt_connected": true
}
字段 类型 说明
status string 服务状态,固定 "ok"
mqtt_connected boolean MQTT Broker 是否已连接

2.2 静态资源

GET /static/{path}

托管 data/ 目录下的课程文件,供终端 HTTP 下载。

URL 规则:

{BASE_URL}/static/{相对路径}

示例:

资源 URL
课程索引 http://124.222.109.197:2101/static/courses/index.json
课程配置 http://124.222.109.197:2101/static/courses/course01/course.json
课程任务包 http://124.222.109.197:2101/static/courses/course01/courseTask.json
音频 http://124.222.109.197:2101/static/courses/course01/chapter01/resources/001.mp3
封面 http://124.222.109.197:2101/static/courses/course01/chapter01/resources/001.png

请求示例:

curl -O http://124.222.109.197:2101/static/courses/course01/courseTask.json

响应: 对应文件的二进制/JSON 内容。


2.3 场景识别

POST /api/v1/scene/analyze

根据设备上下文进行场景识别,返回问候策略与建议意图。

请求体:

字段 类型 必填 说明
timestamp int 是 Unix 时间戳
audio_blob string 是 Base64 音频或占位符
device_id string 是 设备 ID
context_hints object 否 场景提示,如 {"scene":"dining","confidence":0.9}

请求示例:

curl -X POST http://124.222.109.197:2101/api/v1/scene/analyze \
  -H "Content-Type: application/json" \
  -d '{
    "timestamp": 1718365200,
    "audio_blob": "",
    "device_id": "SN-88293021",
    "context_hints": {
      "scene": "dining",
      "confidence": 0.9
    }
  }'

响应示例:

{
  "scene": "用餐",
  "confidence": 0.9,
  "greeting_strategy": "contextual",
  "suggested_intent": "What are you having for dinner?"
}
字段 类型 说明
scene string 场景名称
confidence float 置信度 0~1
greeting_strategy string "contextual" 场景问候 / "generic" 通用问候(置信度 < 0.7)
suggested_intent string 建议的开场白或提问

低置信度响应示例:

{
  "scene": "通勤",
  "confidence": 0.62,
  "greeting_strategy": "generic",
  "suggested_intent": "Hello! How can I help you practice English today?"
}

2.4 对话流

GET /api/v1/dialogue/stream

SSE(Server-Sent Events)流式返回教学对话内容。

Query 参数:

参数 类型 必填 默认值 说明
dialogue_id string 否 自动生成 UUID 对话 ID
user_text string 否 — 用户回复文本(ASR 结果)
scene_prompt string 否 — 场景开场白(来自 scene/analyze)
difficulty string 否 A2 CEFR 难度等级

请求示例:

# 仅开场问候
curl -N "http://124.222.109.197:2101/api/v1/dialogue/stream?scene_prompt=What%20are%20you%20having%20for%20dinner?&difficulty=A2"

# 含用户回复的反馈
curl -N "http://124.222.109.197:2101/api/v1/dialogue/stream?user_text=Good%20morning.&difficulty=A2"

响应格式(SSE):

event: message
data: {"dialogue_id":"a1b2c3d4-...","text":"What are you having for dinner?","audio_url":null,"intent_type":"greeting","difficulty_level":"A2"}

event: message
data: {"dialogue_id":"a1b2c3d4-...","text":"Great job! Your sentence looks correct.","audio_url":null,"intent_type":"praise","difficulty_level":"A2"}

event: message
data: {"dialogue_id":"a1b2c3d4-...","text":"What would you do differently next time?","audio_url":null,"intent_type":"question","difficulty_level":"A2"}

event: done
data: {"dialogue_id":"a1b2c3d4-..."}

message 事件 data 字段:

字段 类型 说明
dialogue_id string 对话 ID
text string 对话文本
audio_url string | null 音频 URL(当前为 null)
intent_type string greeting / praise / correction / question
difficulty_level string 难度等级

2.5 课程与任务

GET /api/v1/courses

获取已发布课程索引(对应 data/courses/index.json)。

请求示例:

curl http://124.222.109.197:2101/api/v1/courses

响应示例:

{
  "courses": [
    {
      "course_id": "course01",
      "config": "courses/course01/course.json"
    },
    {
      "course_id": "course02",
      "config": "courses/course02/course.json"
    }
  ]
}

GET /api/v1/courses/{course_id}

获取单门课程详情(章节与视频列表)。

请求示例:

curl http://124.222.109.197:2101/api/v1/courses/course01

响应示例:

{
  "course_id": "course01",
  "course_name": "小智学习课程01",
  "description": "课程01",
  "chapters": [
    {
      "chapter_id": "chapter01",
      "chapter_name": "第一章",
      "videos": [
        {
          "id": "001",
          "title": "课程001",
          "path": "courses/course01/chapter01/resources/001.mp3"
        }
      ]
    }
  ]
}

GET /api/v1/courses/base-manifest

预览全部基础课程同步包(MQTT 下发前的完整 payload,url 已补全)。

请求示例:

curl http://124.222.109.197:2101/api/v1/courses/base-manifest

响应示例:

{
  "scope": "base",
  "course_count": 2,
  "courses": [
    {
      "version": "1.0",
      "course_id": "course01",
      "course_name": "小智学习课程01",
      "description": "课程01终端初始化任务:下载章节视频并更新本地资源清单",
      "assets": [
        {
          "url": "http://124.222.109.197:2101/static/courses/course01/chapter01/resources/001.mp3",
          "md5": "...",
          "title": "第一章 课程001",
          "target_path": "courses/course01/chapter01/resources/001.mp3",
          "cover_url": "http://124.222.109.197:2101/static/courses/course01/chapter01/resources/001.png",
          "cover_target_path": "courses/course01/chapter01/resources/001.png"
        }
      ]
    }
  ]
}

GET /api/v1/courses/{course_id}/manifest

获取单门课程的同步包(url / cover_url 已补全为完整 HTTP 地址)。

请求示例:

curl http://124.222.109.197:2101/api/v1/courses/course01/manifest

响应示例:

{
  "version": "1.0",
  "course_id": "course01",
  "course_name": "小智学习课程01",
  "description": "课程01终端初始化任务:下载章节视频并更新本地资源清单",
  "assets": [
    {
      "url": "http://124.222.109.197:2101/static/courses/course01/chapter01/resources/001.mp3",
      "md5": "...",
      "title": "第一章 课程001",
      "target_path": "courses/course01/chapter01/resources/001.mp3",
      "cover_url": "http://124.222.109.197:2101/static/courses/course01/chapter01/resources/001.png",
      "cover_target_path": "courses/course01/chapter01/resources/001.png"
    }
  ]
}

GET /api/v1/courses/{course_id}/tasks

获取原始 courseTask.json(本地文件内容,url 为相对路径)。

请求示例:

curl http://124.222.109.197:2101/api/v1/courses/course01/tasks

响应示例:

{
  "version": "1.0",
  "course_id": "course01",
  "course_name": "小智学习课程01",
  "description": "课程01终端初始化任务:下载章节视频并更新本地资源清单",
  "assets": [
    {
      "url": "courses/course01/chapter01/resources/001.mp3",
      "md5": "...",
      "title": "第一章 课程001",
      "target_path": "courses/course01/chapter01/resources/001.mp3",
      "cover_url": "courses/course01/chapter01/resources/001.png",
      "cover_target_path": "courses/course01/chapter01/resources/001.png"
    }
  ]
}

GET /api/v1/tasklist

获取设备开机初始化任务清单(data/tasklist.json)。

请求示例:

curl http://124.222.109.197:2101/api/v1/tasklist

响应示例:

{
  "version": "1.0",
  "description": "终端设备初始化任务清单,开机后由服务端下发执行",
  "tasks": [
    {
      "task_id": "init_001",
      "name": "同步系统时钟",
      "action": "SET_CLOCK",
      "channel": "ctl",
      "ttl": 60,
      "payload": { "ts": 0 }
    },
    {
      "task_id": "init_002",
      "name": "设置默认音量",
      "action": "SET_VOLUME",
      "channel": "ctl",
      "ttl": 60,
      "payload": { "level": 50 }
    },
    {
      "task_id": "init_003",
      "name": "唤醒设备",
      "action": "SET_POWER",
      "channel": "ctl",
      "ttl": 60,
      "payload": { "state": "wake" }
    }
  ]
}

2.6 设备初始化

POST /api/v1/devices/init

手动触发设备完整初始化(基础 ctl 指令 + 全部基础课程 SYNC_COURSE_TASK)。

请求体:

字段 类型 必填 默认值 说明
device_id string 是 — 设备 ID
force boolean 否 false 强制重新初始化(忽略已初始化记录)
course_id string 否 — 本接口不使用

请求示例:

curl -X POST http://124.222.109.197:2101/api/v1/devices/init \
  -H "Content-Type: application/json" \
  -d '{
    "device_id": "SN-88293021",
    "force": true
  }'

响应示例(成功下发):

{
  "device_id": "SN-88293021",
  "commands": [
    {
      "header": {
        "version": "1.0",
        "device_id": "SN-88293021",
        "req_id": "8f932149-719c-4464-99be-66dfcfa14f29",
        "timestamp": 1718365200,
        "ttl": 60
      },
      "action": "SET_CLOCK",
      "payload": { "ts": 1718365200 }
    },
    {
      "header": {
        "version": "1.0",
        "device_id": "SN-88293021",
        "req_id": "e1c1de2a-3067-417d-b533-67c9a9827a8e",
        "timestamp": 1718365201,
        "ttl": 7200
      },
      "action": "SYNC_COURSE_TASK",
      "payload": {
        "version": "1.0",
        "course_id": "course01",
        "course_name": "小智学习课程01",
        "assets": []
      }
    }
  ],
  "status": "dispatched"
}

响应示例(已初始化且未 force):

{
  "device_id": "SN-88293021",
  "commands": [],
  "status": "already_initialized"
}
status 值 说明
dispatched 指令已下发
already_initialized 设备已在初始化记录中,跳过

POST /api/v1/devices/course-init

手动触发单门课程资源同步(下发 1 条 SYNC_COURSE_TASK)。

请求体:

字段 类型 必填 说明
device_id string 是 设备 ID
course_id string 是 课程 ID,如 course01

请求示例:

curl -X POST http://124.222.109.197:2101/api/v1/devices/course-init \
  -H "Content-Type: application/json" \
  -d '{
    "device_id": "SN-88293021",
    "course_id": "course01"
  }'

响应示例:

{
  "device_id": "SN-88293021",
  "course_id": "course01",
  "commands": [
    {
      "header": {
        "version": "1.0",
        "device_id": "SN-88293021",
        "req_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "timestamp": 1718365300,
        "ttl": 7200
      },
      "action": "SYNC_COURSE_TASK",
      "payload": {
        "version": "1.0",
        "course_id": "course01",
        "course_name": "小智学习课程01",
        "description": "课程01终端初始化任务:下载章节视频并更新本地资源清单",
        "assets": [
          {
            "url": "http://124.222.109.197:2101/static/courses/course01/chapter01/resources/001.mp3",
            "md5": "...",
            "title": "第一章 课程001",
            "target_path": "courses/course01/chapter01/resources/001.mp3",
            "cover_url": "http://124.222.109.197:2101/static/courses/course01/chapter01/resources/001.png",
            "cover_target_path": "courses/course01/chapter01/resources/001.png"
          }
        ]
      }
    }
  ],
  "status": "dispatched"
}

2.7 设备管理

GET /api/v1/devices

获取当前在线设备列表(来自 MQTT rpt/state 上报)。

请求示例:

curl http://124.222.109.197:2101/api/v1/devices

响应示例:

{
  "devices": [
    {
      "device_id": "SN-88293021",
      "cpu": 15.0,
      "mem": 45.0,
      "battery": 80.0,
      "net": "wifi",
      "mode": "idle",
      "last_seen": 1718365205
    }
  ]
}

GET /api/v1/devices/initialized

获取已完成初始化的设备记录。

请求示例:

curl http://124.222.109.197:2101/api/v1/devices/initialized

响应示例:

{
  "devices": {
    "SN-88293021": {
      "initialized_at": 1718365200,
      "source": "auto",
      "mode": "idle",
      "courses_synced": true,
      "courses_sync_at": 1718365201,
      "courses_sync_count": 2
    }
  }
}

GET /api/v1/devices/{device_id}

获取单个设备最新状态。

请求示例:

curl http://124.222.109.197:2101/api/v1/devices/SN-88293021

响应示例:

{
  "device_id": "SN-88293021",
  "cpu": 15.0,
  "mem": 45.0,
  "battery": 80.0,
  "net": "wifi",
  "mode": "idle",
  "last_seen": 1718365205
}

404 响应:

{
  "detail": "Device not found"
}

GET /api/v1/devices/{device_id}/init-status

查询设备初始化状态。

请求示例:

curl http://124.222.109.197:2101/api/v1/devices/SN-88293021/init-status

响应示例(已初始化):

{
  "device_id": "SN-88293021",
  "initialized": true,
  "record": {
    "initialized_at": 1718365200,
    "source": "auto",
    "mode": "idle",
    "courses_synced": true,
    "courses_sync_at": 1718365201,
    "courses_sync_count": 2
  }
}

响应示例(未初始化):

{
  "device_id": "SN-88293021",
  "initialized": false,
  "record": null
}

DELETE /api/v1/devices/initialized/{device_id}

清除设备初始化记录,下次上报 rpt/state 时将重新触发自动初始化。

请求示例:

curl -X DELETE http://124.222.109.197:2101/api/v1/devices/initialized/SN-88293021

响应示例:

{
  "device_id": "SN-88293021",
  "status": "removed"
}

GET /api/v1/devices/{device_id}/acks

获取设备指令回执历史。

请求示例:

curl http://124.222.109.197:2101/api/v1/devices/SN-88293021/acks

响应示例:

{
  "device_id": "SN-88293021",
  "acks": [
    {
      "req_id": "8f932149-719c-4464-99be-66dfcfa14f29",
      "status": "success",
      "error_code": 0
    }
  ]
}

GET /api/v1/devices/{device_id}/events

获取设备事件与进度上报历史。

请求示例:

curl http://124.222.109.197:2101/api/v1/devices/SN-88293021/events

响应示例:

{
  "device_id": "SN-88293021",
  "events": [
    {
      "event": "asr_result",
      "text": "Good morning",
      "confidence": 0.95,
      "_type": "event"
    },
    {
      "task_id": "uuid",
      "status": "downloading",
      "progress": 45,
      "info": "Downloading assets...",
      "_type": "progress"
    }
  ]
}

POST /api/v1/devices/{device_id}/cmd

手动向设备下发实时控制指令(MQTT cmd/ctl)。

请求体:

{
  "header": {
    "device_id": "SN-88293021",
    "timestamp": 1718365200,
    "ttl": 60
  },
  "action": "SET_VOLUME",
  "payload": { "level": 80 }
}

请求示例:

curl -X POST http://124.222.109.197:2101/api/v1/devices/SN-88293021/cmd \
  -H "Content-Type: application/json" \
  -d '{
    "header": {
      "device_id": "SN-88293021",
      "timestamp": 1718365200,
      "ttl": 60
    },
    "action": "SET_VOLUME",
    "payload": { "level": 80 }
  }'

响应示例(返回实际下发的完整指令):

{
  "header": {
    "version": "1.0",
    "device_id": "SN-88293021",
    "req_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "timestamp": 1718365200,
    "ttl": 60
  },
  "action": "SET_VOLUME",
  "payload": { "level": 80 }
}

POST /api/v1/devices/{device_id}/task

手动向设备下发异步任务指令(MQTT cmd/task)。

请求示例:

curl -X POST http://124.222.109.197:2101/api/v1/devices/SN-88293021/task \
  -H "Content-Type: application/json" \
  -d '{
    "header": {
      "device_id": "SN-88293021",
      "timestamp": 1718365200,
      "ttl": 7200
    },
    "action": "SYNC_COURSE_TASK",
    "payload": {
      "version": "1.0",
      "course_id": "course01",
      "course_name": "小智学习课程01",
      "assets": []
    }
  }'

响应示例:

{
  "header": {
    "version": "1.0",
    "device_id": "SN-88293021",
    "req_id": "550e8400-e29b-41d4-a716-446655440000",
    "timestamp": 1718365200,
    "ttl": 7200
  },
  "action": "SYNC_COURSE_TASK",
  "payload": {
    "version": "1.0",
    "course_id": "course01",
    "course_name": "小智学习课程01",
    "assets": []
  }
}

三、MQTT 接口

3.1 Topic 规则

snlp/v1/{device_id}/{direct}/{msg_type}
方向 Topic QoS 说明
终端 → 云 snlp/v1/{device_id}/rpt/state 0 心跳/状态上报
终端 → 云 snlp/v1/{device_id}/rpt/event 0 事件上报
终端 → 云 snlp/v1/{device_id}/rpt/ack 1 指令执行回执
终端 → 云 snlp/v1/{device_id}/rpt/progress 0 异步任务进度
终端 → 云 snlp/v1/{device_id}/rpt/log 0 系统日志
云 → 终端 snlp/v1/{device_id}/cmd/ctl 1 实时控制指令
云 → 终端 snlp/v1/{device_id}/cmd/task 1 异步任务指令

参数说明:

参数 说明
v1 协议版本号
device_id 设备唯一 ID,不可修改
direct rpt(终端上报)/ cmd(云端下发)
msg_type state / event / ack / progress / log / ctl / task

3.2 消息通用格式

云端下发(cmd/ctl、cmd/task)

{
  "header": {
    "version": "1.0",
    "device_id": "SN-88293021",
    "req_id": "550e8400-e29b-41d4-a716-446655440000",
    "timestamp": 1718365200,
    "ttl": 3600
  },
  "action": "ACTION_TYPE",
  "payload": {}
}
header 字段 类型 说明
version string 协议语义版本,固定 "1.0"
device_id string 目标设备 ID
req_id string 指令唯一 ID(UUID),终端 ack 时须回传
timestamp int Unix 时间戳
ttl int 指令有效期(秒)

终端上报(rpt/*)

{
  "header": {
    "device_id": "SN-88293021",
    "timestamp": 1718365205
  },
  "msg_type": "state",
  "payload": {}
}

3.3 终端上报(rpt)

rpt/state — 心跳/状态

Topic: snlp/v1/{device_id}/rpt/state

发布示例(终端 → 云):

{
  "header": {
    "device_id": "SN-88293021",
    "timestamp": 1718365205
  },
  "msg_type": "state",
  "payload": {
    "cpu": 15,
    "mem": 45,
    "battery": 80,
    "net": "wifi",
    "mode": "idle"
  }
}

服务端行为:

  • 更新设备在线状态
  • 若设备未初始化且 MQTT 已连接 → 自动触发完整初始化流程

mode 常见值: idle / dialogue / translate / study / sleep


rpt/event — 事件上报

Topic: snlp/v1/{device_id}/rpt/event

发布示例:

{
  "header": {
    "device_id": "SN-88293021",
    "timestamp": 1718365210
  },
  "msg_type": "event",
  "payload": {
    "event": "asr_result",
    "text": "Good morning",
    "confidence": 0.95
  }
}

常见 event 类型:

event 说明
wake 唤醒触发
sleep 休眠触发
asr_result ASR 识别结果
alarm 异常报警

rpt/ack — 指令回执

Topic: snlp/v1/{device_id}/rpt/ack

发布示例:

{
  "header": {
    "device_id": "SN-88293021",
    "timestamp": 1718365215
  },
  "msg_type": "ack",
  "payload": {
    "req_id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "success",
    "error_code": 0
  }
}
payload 字段 说明
req_id 对应下发指令的 req_id
status success / failed
error_code 0 表示成功,非 0 为错误码

rpt/progress — 任务进度

Topic: snlp/v1/{device_id}/rpt/progress

发布示例:

{
  "header": {
    "device_id": "SN-88293021",
    "timestamp": 1718365220
  },
  "msg_type": "progress",
  "payload": {
    "task_id": "550e8400-e29b-41d4-a716-446655440000",
    "status": "downloading",
    "progress": 45,
    "info": "Downloading courses/course01/chapter01/resources/001.mp3"
  }
}

rpt/log — 系统日志

Topic: snlp/v1/{device_id}/rpt/log

发布示例:

{
  "header": {
    "device_id": "SN-88293021",
    "timestamp": 1718365230
  },
  "msg_type": "log",
  "payload": {
    "level": "error",
    "module": "audio",
    "message": "Microphone init failed"
  }
}

3.4 云端下发(cmd)

cmd/ctl — 实时控制指令

Topic: snlp/v1/{device_id}/cmd/ctl

Action 列表:

Action payload 示例 说明
SET_VOLUME {"level": 50} 设置音量 0–100
SET_POWER {"state": "wake"} 唤醒 / sleep 休眠
SET_CLOCK {"ts": 1718365200} 同步 Unix 时间戳
PLAY_MEDIA {"path": "courses/course01/chapter01/resources/001.mp3", "volume": 50, "loop": false} 播放本地媒体
STOP_MEDIA {} 停止播放
SET_ALARM {"id": "alarm_01", "time": "07:00", "repeat": [1,2,3,4,5], "action": "add"} 设置闹钟
UNSET_ALARM {"id": "alarm_01"} 删除闹钟
REBOOT {"delay": 5} 延时重启

SET_CLOCK 下发示例:

{
  "header": {
    "version": "1.0",
    "device_id": "SN-88293021",
    "req_id": "8f932149-719c-4464-99be-66dfcfa14f29",
    "timestamp": 1718365200,
    "ttl": 60
  },
  "action": "SET_CLOCK",
  "payload": {
    "ts": 1718365200
  }
}

SET_VOLUME 下发示例:

{
  "header": {
    "version": "1.0",
    "device_id": "SN-88293021",
    "req_id": "34dc4157-9e52-4a99-bdad-b3daf665df11",
    "timestamp": 1718365200,
    "ttl": 60
  },
  "action": "SET_VOLUME",
  "payload": {
    "level": 50
  }
}

SET_POWER 下发示例:

{
  "header": {
    "version": "1.0",
    "device_id": "SN-88293021",
    "req_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "timestamp": 1718365200,
    "ttl": 60
  },
  "action": "SET_POWER",
  "payload": {
    "state": "wake"
  }
}

cmd/task — 异步任务指令

Topic: snlp/v1/{device_id}/cmd/task

当前实现使用的 Action:

Action 说明
SYNC_COURSE_TASK 下发完整课程资源包(courseTask.json 格式),终端按 assets 批量下载

SYNC_COURSE_TASK 下发示例:

{
  "header": {
    "version": "1.0",
    "device_id": "SN-88293021",
    "req_id": "e1c1de2a-3067-417d-b533-67c9a9827a8e",
    "timestamp": 1718365201,
    "ttl": 7200
  },
  "action": "SYNC_COURSE_TASK",
  "payload": {
    "version": "1.0",
    "course_id": "course01",
    "course_name": "小智学习课程01",
    "description": "课程01终端初始化任务:下载章节视频并更新本地资源清单",
    "assets": [
      {
        "url": "http://your-server:2101/static/courses/course01/chapter01/resources/001.mp3",
        "md5": "...",
        "title": "第一章 课程001",
        "target_path": "courses/course01/chapter01/resources/001.mp3",
        "cover_url": "http://your-server:2101/static/courses/course01/chapter01/resources/001.png",
        "cover_target_path": "courses/course01/chapter01/resources/001.png"
      },
      {
        "url": "http://your-server:2101/static/courses/course01/chapter01/resources/002.mp3",
        "md5": "...",
        "title": "第一章 课程002",
        "target_path": "courses/course01/chapter01/resources/002.mp3",
        "cover_url": "http://your-server:2101/static/courses/course01/chapter01/resources/002.png",
        "cover_target_path": "courses/course01/chapter01/resources/002.png"
      }
    ]
  }
}

assets 字段说明:

字段 说明
url 资源完整 HTTP 下载地址(服务端自动补全)
md5 文件校验值
title 资源标题
target_path 终端存储相对路径(与服务端目录结构一致)
cover_url 封面完整 HTTP 下载地址
cover_target_path 封面终端存储相对路径

终端处理逻辑:

  1. 收到 SYNC_COURSE_TASK 后解析 assets 列表
  2. 按每项的 url 下载文件,保存到存储卡 target_path 路径
  3. 按 cover_url 下载封面,保存到 cover_target_path
  4. 下载过程中通过 rpt/progress 上报进度
  5. 完成后通过 rpt/ack 回传 req_id 与执行结果

PRD 预留 Action(可通过 HTTP /devices/{id}/task 手动下发):

Action payload 示例 说明
DOWNLOAD {"task_id":"uuid","url":"...","md5":"...","target_path":"..."} 单文件下载
UPDATE_MANIFEST {"course_id":"...","assets":[...]} 更新资源清单
OTA_UPDATE {"url":"...","version":"1.0.2"} 固件升级
DELETE_FILE {"path":"..."} 删除文件

3.5 服务端自动下发流程

设备首次上报 rpt/state 时,服务端自动执行:

1. cmd/ctl  SET_CLOCK   {"ts": <当前时间戳>}
2. cmd/ctl  SET_VOLUME  {"level": 50}
3. cmd/ctl  SET_POWER   {"state": "wake"}
4. cmd/task SYNC_COURSE_TASK  {course01 完整 payload}
5. cmd/task SYNC_COURSE_TASK  {course02 完整 payload}
   ... index.json 中每门基础课程各 1 条

手动 MQTT 发布示例(mosquitto_pub):

mosquitto_pub \
  -h your-mqtt-broker -p 2100 \
  -u your-username -P your-password \
  -t "snlp/v1/SN-88293021/cmd/task" \
  -q 1 \
  -m '{"header":{"version":"1.0","device_id":"SN-88293021","req_id":"manual-uuid","timestamp":1718365200,"ttl":7200},"action":"SYNC_COURSE_TASK","payload":{"version":"1.0","course_id":"course01","course_name":"小智学习课程01","assets":[]}}'

四、接口速查表

HTTP 接口

方法 路径 说明
GET /health 健康检查
GET /static/{path} 静态资源下载
POST /api/v1/scene/analyze 场景识别
GET /api/v1/dialogue/stream SSE 对话流
GET /api/v1/courses 课程索引
GET /api/v1/courses/base-manifest 全部基础课程同步包预览
GET /api/v1/courses/{course_id} 课程详情
GET /api/v1/courses/{course_id}/manifest 单课程同步包预览
GET /api/v1/courses/{course_id}/tasks 原始 courseTask.json
GET /api/v1/tasklist 设备初始化任务清单
POST /api/v1/devices/init 手动设备初始化
POST /api/v1/devices/course-init 手动单课程同步
GET /api/v1/devices 在线设备列表
GET /api/v1/devices/initialized 已初始化设备
DELETE /api/v1/devices/initialized/{device_id} 清除初始化记录
GET /api/v1/devices/{device_id} 设备状态
GET /api/v1/devices/{device_id}/init-status 初始化状态
GET /api/v1/devices/{device_id}/acks 指令回执历史
GET /api/v1/devices/{device_id}/events 事件/进度历史
POST /api/v1/devices/{device_id}/cmd 手动下发 ctl 指令
POST /api/v1/devices/{device_id}/task 手动下发 task 指令

MQTT 接口

方向 Topic 关键 Action / 用途
终端 → 云 snlp/v1/{id}/rpt/state 心跳,触发自动初始化
终端 → 云 snlp/v1/{id}/rpt/event ASR 结果、唤醒/休眠事件
终端 → 云 snlp/v1/{id}/rpt/ack 指令执行回执
终端 → 云 snlp/v1/{id}/rpt/progress 下载/OTA 进度
终端 → 云 snlp/v1/{id}/rpt/log 远程排障日志
云 → 终端 snlp/v1/{id}/cmd/ctl SET_CLOCK / SET_VOLUME / SET_POWER / PLAY_MEDIA 等
云 → 终端 snlp/v1/{id}/cmd/task SYNC_COURSE_TASK(课程资源包同步)

文档版本:1.0 | 对应服务端版本:1.0.0