HTTP API参考
API根路径为/api/v1。NestJS全局prefix为api,URI版本默认1;Swagger仅非production环境在/api-docs开放。正文DTO启用转换、白名单及未知字段拒绝。普通API使用Bearer访问Token,MQTT回调使用独立头,不共享用户Token。
响应、分页与错误
普通成功包装:
{"code":"00000","msg":"Success","data":{"example":"value"}}分页服务返回data或list数组及page时,拦截器输出:
{"code":"00000","msg":"Success","data":[],"page":{"pageNum":1,"pageSize":20,"total":0}}部分Controller自身已返回业务code,会再被拦截器包一层。控制结果须检查response.data.code,历史结果数组在response.data.data。不能只看HTTP200或外层00000:
{"code":"00000","msg":"Success","data":{"code":"A0104","msg":"指令执行失败或设备未响应","msgId":"11111111-1111-4111-8111-111111111111"}}异常HTTP状态保留,统一body为code/msg/data:400=A0001,401=A0200,403=A0300,404=A0400,500=B0001,503=B0100;其他状态(包括409/410/429)当前默认B0001,因此同时查看HTTP状态及msg。MQTT回调成功直接返回result结构,不采用业务包装。
登录与会话
| 方法与路径(相对/api/v1) | 请求 | 行为 |
|---|---|---|
| GET auth/captcha | 无 | 返回验证码ID和图片;字段以响应为准 |
| POST auth/register | username、password≥6,可选email/phone | 普通账号注册,不允许传roleIds自提权 |
| POST auth/login | username、password、captchaId、captchaCode | 账号/邮箱/手机号作为账号标识;不是免验证手机号登录,5次/分钟限流 |
| POST auth/wx/miniapp/code-login | 服务端微信交换,需MP_APPID/MP_SECRET,无mock身份 | |
| POST auth/wx/miniapp/phone-login | 路由保留 | 未实现可信手机号交换,拒绝登录;不要作为产品入口 |
| POST auth/refresh-token | 只能用refresh类型刷新,不能当普通Bearer | |
| DELETE auth/logout | Bearer,body可选refreshToken | 撤销当前sid会话 |
登录data含accessToken、refreshToken、tokenType=Bearer、expiresIn(秒)。访问Token推荐1小时,JWT_EXPIRATION范围1秒至7天;刷新Token签名寿命7天,但Redis会话从首次登录起最多7天且不滑动延期,刷新不能延长该会话。HTTP和WS校验当前账号/会话,角色撤销或禁用对旧Token生效。
客户端401共用一次刷新并各自重放原请求一次,403不刷新;退出/切账号使迟到刷新失效,网络错误不自动当作会话失效。七天会话到期须重新登录。
设备、认领与分享
下列:id为Device.id逻辑UUID。
| 方法/路径 | 请求或查询 | 当前权限 |
|---|---|---|
| GET devices | pageNum/pageSize,scope=accessible等 | 管理员默认管理列表;普通用户仅可访问设备 |
| GET devices/:id | 无 | 管理员/拥有者/有效分享者 |
| POST devices | CreateDeviceDto | 管理员登记,不是手机配网入口 |
| PATCH devices/:id/name | 拥有者或管理员 | |
| POST devices/:id/control | {"params":{"relay_1":true}} | 拥有者/有效分享者;管理员身份不单独授予控制 |
| GET devices/:id/telemetry | start、end ISO时间,keys逗号分隔 | 有查看权限;只读数值属性,31天限制;内层data数组 |
| GET devices/:id/logs | 无 | 拥有者/管理员 |
| POST devices/:id/secret/reset | 无 | 管理员,新密钥仅本次返回 |
| DELETE devices/:id | 无 | 管理员删除;与解绑不同 |
| PATCH devices/:id/family | 历史接口 | 返回410,家庭功能暂缓 |
| POST device-claims | productId、physicalId、setupCode,可选bootstrapHash | 已登录账号;创建10分钟票据,非绑定完成 |
| GET device-claims/:claimId | 无 | 仅该认领账号;pending/completed/expired/revoked |
| POST device-claims/devices/:id/unbind | 无 | 拥有者,撤销共享与票据,保留身份/历史 |
| POST device-shares/:id/invites | 无 | 拥有者,24小时单次邀请 |
| POST device-shares/accept | 接收账号,不是设备MQTT令牌 | |
| GET device-shares/:id | 无 | 拥有者 |
| DELETE device-shares/:id/invites/:inviteId | 无 | 拥有者撤销邀请 |
| DELETE device-shares/:id/recipients/:userId | 无 | 拥有者撤销分享 |
| POST device-shares/:id/leave | 无 | 接收者退出 |
配置与服务
读取GET devices/:id/configuration得到available、canConfigure、模型/能力定义及settings/schedules视图(revision、desired、reported、accepted/appliedRevision、syncStatus、error、highestRuleId、updatedAt)。只能把available且匹配能力的操作展示给用户。
保存完整定时例,PUT devices/:id/configuration/schedules,拥有者、expectedRevision必须等于刚读取版本:
{"expectedRevision":0,"params":{"timezoneMinutes":480,"rules":[{"id":1,"enabled":true,"trigger":{"kind":"weekly","weekdays":31,"minute":480},"action":{"type":"property.set","params":{"relay_1":true}}}]}}settings相同路径换为settings,params是可写改动集,例如传感器{"sample_interval_s":30,"report_interval_s":120}。响应data包含configuration视图和delivery=published/queued/superseded;并发版本或归属变化返回409。
调用POST devices/:id/services/:serviceId,body为{"params":{...}}。五个标准服务输入/权限见MQTT参考。返回msgId、state=pending与delivery,随后GET devices/:id/services/results/:msgId查询结果;结果仅原账号可取并重新验证访问权限。内部binding_sync禁止公开调用。
产品、文件与OTA
产品读取需登录,产品创建/修改/删除与物模型修改仅管理员。权限字典写入仅管理员,读取需登录;个人资料PUT users/profile不能修改角色关系。具体后台字典路径以各Controller为准,不使用文档虚构的统一CRUD装饰器。
文件POST files使用multipart字段file,directory不决定实际目录,服务端按当前userId生成路径;POST files/url body={url},DELETE files body={path}只允许当前用户路径(管理员有独立授权逻辑)。不能为任意已知OSS路径签名或删除。OSS文件字节由客户端/设备直接下载,不经业务服务器转发。
固件GET firmware/versions?productId=...、GET firmware/:id需登录;POST firmware/upload(file/productId/version/chip/hardware/changelog)、DELETE firmware/:id限管理员,上传OTA应用最大4MiB。OTA任务POST ota-tasks body={deviceId,firmwareId},GET列表/详情,POST :id/retry;按任务权限及拥有者快照校验,分享者不可升级。烧录工具GET tools/esp32/firmware及GET tools/esp32/firmware/:productId/:version/download-url需登录,后者返回data.url/expiresAt,签名300秒。
开发验证
在隔离测试中复用真实Controller/守卫和响应拦截器;不要凭Swagger摘要推断角色或包装。新增接口先对照Controller、DTO、Service权限,再同步本文。测试入口见测试策略。
完整方法/路径清单见Controller路由源码索引,它补充系统管理入口,不替代这里的行为、包装与权限说明。
