云端 REST API 契约 v1.1

三端(嵌入式网关 / Windows GUI / 云端)唯一的 REST 契约。 MQTT 契约见 mqtt-device-protocol.md;联调矩阵见 integration-test-plan.md。

制定:主代理(2026-10-01)。任何路由/字段变更只能由主代理发起,三端同步改。

版本注记:v1.1(2026-10-02,三端联调修复批)。变更记录: - 登录端点定稿 POST /api/v1/auth/login 及返回字段(第一节写死);新增 refresh/logout; - §2 设备/latest/history 响应形状按云端 P1 实现现状改写(此前三方各表述),三个读端点改为必须带 JWT + 租户范围校验; - 新增第四节「GUI 版本管理」端点(版本列表/发布/包上传/设最新/下架/force 标记); - 角色与范围语义写进第五节(客户用户/运营/管理员/超级管理员,平台侧干预必须落审计)。

0. 基地址与版本

1. 身份(P2 交付,字段与 GUI saas-auth.md 对齐)

方法 端点 说明
POST /api/v1/auth/login {username,password} → 登录响应(见下)
POST /api/v1/auth/refresh {refresh_token} → 同登录响应形状
POST /api/v1/auth/logout {refresh_token} → 吊销该 refresh token

登录响应字段(写死,不许增删改名):

{
  "access_token": "<JWT>",
  "refresh_token": "<JWT>",
  "expires_in_s": 86400,
  "tenant_id": "t-xxxx",
  "mqtt": {
    "host": "broker.example.com",
    "port": 1883,
    "username": "{tenant_id}/{username}",
    "password": "<短期 MQTT 凭证>",
    "expires_in_s": 86400
  }
}

2. 数据(形状以云端 P1 实现为准,2026-10-02 定稿)

三个读端点(设备列表 / latest / history)必须带 JWT 并做租户范围校验:客户用户只限本租户,平台角色只限所辖租户(见第五节),跨界 403、无凭据 401。

方法 端点 说明
GET /healthz 健康检查 {"ok":true,"status":"ok","telemetry_parse_failures":N}(N 为遥测解析失败/空点累计丢弃计数)
GET /api/devices?tenant={tid} 设备列表:[{"tenant","device","last_seen","version","online"}],last_seen 为毫秒时间戳或 null
GET /api/devices/{tenant}/{device}/latest 最新值数组:[{"ts","area","address","data_type","value","quality","source","unit"}],ts 为毫秒时间戳
GET /api/telemetry?tenant=&device=&area=&address=&from=&to=&limit= 历史点数组,元素形状同 latest;from/to 为毫秒时间戳
POST /api/devices/{tenant}/{device}/cmd 下行命令 {cmd_id,action,params} → 等待 cmd_ack 配对;设备无回执时 504

3. GUI 侧适配要求

4. GUI 版本管理(v1.1 新增,形状按云端已实现并通过测试的端点定稿)

云端维护桌面 GUI 的版本与安装包,GUI 启动后带 JWT 查新。包文件先存云端本地目录(APP_PACKAGE_DIR 配置,后续可换对象存储),服务端算 SHA256。

版本对象字段:version(语义版本字符串)、notes(更新说明)、package_url(下载相对路径)、sha256(小写 hex)、size(包字节数)、min_supported_version(低于此版本必须强制更新,可为 null)、force_update(是否强制更新)、is_latest(是否当前最新)、status(published 上架 / unpublished 下架)、published_at(ISO 8601 时间)。

方法 端点 说明
GET /api/v1/app/latest (带 JWT,任意角色)当前最新已上架版本对象;没有时 404
GET /api/v1/app/versions 版本列表(平台角色:运营/管理员/超级管理员)
POST /api/v1/app/versions?version=&notes=&min_supported_version=&force_update=&filename= 发布:body 为包原始字节(管理员/超级管理员);服务端存盘、算 SHA256/size 后落库,201 返回版本对象
GET /api/v1/app/packages/{filename} 下载包字节(带 JWT,package_url 即此路径)
POST /api/v1/app/versions/{version}/latest 设为最新(管理员/超级管理员;同刻只有一个 latest)
POST /api/v1/app/versions/{version}/offline 下架(管理员/超级管理员);下架版本不再被 /api/v1/app/latest 返回
POST /api/v1/app/versions/{version}/force 改强制更新标记 {force_update: bool}(管理员/超级管理员)

5. 角色与范围(v1.1 新增)