API 接口规范
通用约定
请求前缀
所有 API 以 /api/v1 为前缀。
统一响应格式
json
{
"code": "00000",
"msg": "Success",
"data": {}
}| 字段 | 类型 | 说明 |
|---|---|---|
code | string | 状态码,00000 表示成功 |
msg | string | 提示信息 |
data | object/array | 响应数据 |
分页响应
json
{
"code": "00000",
"msg": "Success",
"data": { "list": [], "total": 100 },
"page": { "pageNum": 1, "pageSize": 10, "total": 100 }
}认证
- 使用 JWT Bearer Token
- 请求头:
Authorization: Bearer <token> - 公开接口无需认证
认证模块 /api/v1/auth
| 方法 | 路径 | 认证 | 说明 |
|---|---|---|---|
GET | /auth/captcha | 无 | 获取图形验证码 |
POST | /auth/register | 无 | 用户注册 |
POST | /auth/login | 无 | 账号密码登录 |
POST | /auth/wx/miniapp/code-login | 无 | 微信小程序 code 登录 |
POST | /auth/wx/miniapp/phone-login | 无 | 微信手机号登录 |
DELETE | /auth/logout | JWT | 登出 |
POST | /auth/refresh-token | 无 | 刷新 Token |
登录
POST /api/v1/auth/login
Content-Type: application/json
{
"username": "admin",
"password": "123456",
"captchaId": "uuid",
"captchaCode": "abcd"
}
Response:
{
"code": "00000",
"msg": "Success",
"data": {
"accessToken": "eyJhbG...",
"refreshToken": "eyJhbG..."
}
}微信小程序登录
POST /api/v1/auth/wx/miniapp/code-login
{ "code": "wx_login_code" }
Response: { "code": "00000", "data": { "accessToken": "...", "refreshToken": "..." } }用户管理 /api/v1/users
所有接口需 JWT 认证
| 方法 | 路径 | 角色 | 说明 |
|---|---|---|---|
GET | /users/me | 任意 | 获取当前用户信息 |
PUT | /users/profile | 任意 | 更新个人资料 |
PUT | /users/password | 任意 | 修改密码 |
GET | /users | 任意 | 用户列表(分页) |
POST | /users | admin | 创建用户 |
GET | /users/:id/form | 任意 | 获取用户详情 |
PUT | /users/:id | admin | 更新用户 |
DELETE | /users/:ids | admin | 批量删除用户 |
PATCH | /users/:id/status | admin | 启用/禁用用户 |
PATCH | /users/:id/password/reset | admin | 重置密码 |
角色管理 /api/v1/roles
所有接口需 JWT 认证
| 方法 | 路径 | 角色 | 说明 |
|---|---|---|---|
GET | /roles/options | 任意 | 角色选项列表 |
POST | /roles | admin | 创建角色 |
GET | /roles | 任意 | 角色列表(分页) |
GET | /roles/:id/form | 任意 | 角色详情 |
PUT | /roles/:id | admin | 更新角色 |
DELETE | /roles/:id | admin | 删除角色 |
文件管理 /api/v1/files
所有接口需 JWT 认证(无角色限制)
| 方法 | 路径 | 说明 |
|---|---|---|
POST | /files | 上传文件(multipart/form-data) |
POST | /files/url | 获取文件 URL |
DELETE | /files | 删除文件 |
文件上传
POST /api/v1/files
Content-Type: multipart/form-data
file: <binary>
directory: "avatars" (可选)
Response: { "code": "00000", "data": { "url": "https://..." } }产品管理 /api/v1/products 🆕
所有接口需 JWT 认证
| 方法 | 路径 | 角色 | 说明 |
|---|---|---|---|
GET | /products | 任意 | 产品列表(分页) |
POST | /products | admin | 创建产品 |
GET | /products/:id | 任意 | 产品详情 |
PUT | /products/:id | admin | 更新产品 |
DELETE | /products/:id | admin | 删除产品 |
GET | /products/:id/thing-model | 任意 | 获取产品物模型 |
POST /api/v1/products
{
"id": "p_relay_4ch",
"name": "四路继电器",
"thingModel": { "version":"1.0", ... }, // 物模型 JSON
}
Response: { "code":"00000", "data": { "id":"p_relay_4ch", ... } }设备管理 /api/v1/devices 🆕
所有接口需 JWT 认证
| 方法 | 路径 | 角色 | 说明 |
|---|---|---|---|
GET | /devices | 任意 | 设备列表(分页、搜索、按产品筛选) |
POST | /devices | admin | 设备录入(手动注册) |
GET | /devices/:id | 任意 | 设备详情(含影子状态) |
PUT | /devices/:id | admin | 更新设备信息(不含名称修改,命名请用 PATCH /name) |
DELETE | /devices/:id | admin | 删除设备 |
PATCH | /devices/:id/name | 任意 | 修改设备名称(配网完成后调用) |
POST | /devices/:id/control | 任意 | 下发控制指令 |
GET | /devices/:id/telemetry | 任意 | 查询历史数据 |
设备注册
POST /api/v1/devices
{
"productId": "p_relay_4ch",
"name": "客厅继电器",
"physicalId": "A1B2C3D4E5F6" // MAC 地址
}
Response:
{
"code": "00000",
"data": {
"id": "d1a2b3c4-...", // Logical ID (平台分配)
"secret": "uuid-secret", // Device Secret (平台生成)
"productId": "p_relay_4ch",
"name": "客厅继电器",
"physicalId": "A1B2C3D4E5F6",
"isOnline": false,
"shadow": {}
}
}设备控制
POST /api/v1/devices/d1a2b3c4-.../control
{
"params": {
"relay_1": true,
"relay_2": false
}
}
Response: { "code":"00000", "msg":"指令已下发" }控制流程:API → 后端发布 MQTT sys/{pid}/{did}/thing/service/property/set → 设备执行。
历史数据查询
GET /api/v1/devices/d1a2b3c4-.../telemetry?start=2026-05-01&end=2026-05-16&keys=relay_1,temperature
Response:
{
"code": "00000",
"data": [
{ "time": "2026-05-16T10:00:00Z", "relay_1": 1, "temperature": 45.2 },
{ "time": "2026-05-16T10:01:00Z", "relay_1": 0, "temperature": 44.8 }
]
}固件升级 /api/v1/firmware 🆕
升级操作需 admin 角色,查看状态任意角色可访问
| 方法 | 路径 | 角色 | 说明 |
|---|---|---|---|
GET | /firmware/versions | 任意 | 固件版本列表 |
POST | /firmware/upload | admin | 上传固件文件 |
POST | /firmware/upgrade | admin | 触发设备升级(单设备/批量) |
GET | /firmware/upgrade/:taskId/status | 任意 | 查询升级任务进度 |
设备自动注册 /api/v1/devices/register 🆕
无需认证(设备端调用,设备首次连接时由 EMQX 直连 PostgreSQL 认证后触发注册)
POST /api/v1/devices/register
Headers: X-Device-Key: <productKey>:<deviceSecret>
{
"productKey": "p_relay_4ch",
"physicalId": "A1B2C3D4E5F6",
"clientId": "A1B2C3D4E5F6"
}
Response:
{
"code": "00000",
"data": {
"deviceId": "d1a2b3c4-...",
"mqttTopics": {
"status": "sys/p_relay_4ch/d1a2b3c4-.../thing/event/property/post",
"control": "sys/p_relay_4ch/d1a2b3c4-.../thing/service/property/set",
"config": "sys/p_relay_4ch/d1a2b3c4-.../thing/config/set"
}
}
}WebSocket 实时推送 /ws
需 JWT 认证,用于前端接收设备实时状态
| 事件 | 方向 | 说明 |
|---|---|---|
device.status | 服务端 → 客户端 | 设备上下线通知 |
device.shadow | 服务端 → 客户端 | 设备影子状态变更 |
系统监控 /api/v1/system
所有接口需 JWT + admin 角色
| 方法 | 路径 | 说明 |
|---|---|---|
GET | /system/status | 获取服务器运行状态 |
POST | /system/status/email | 发送状态报告邮件 |
系统状态响应
json
{
"code": "00000",
"data": {
"os": { "platform": "darwin", "type": "Darwin", "arch": "arm64", "hostname": "server" },
"cpu": { "model": "Apple M1", "cores": 8, "speed": 2400 },
"memory": { "total": "16 GB", "used": "8.5 GB", "free": "7.5 GB", "usage": "53.12%" },
"uptime": "5天 12小时 30分 15秒",
"timestamp": "2026-05-15T10:00:00.000Z"
}
}错误码
HTTP 状态码
| 状态码 | 说明 |
|---|---|
| 200 | 成功 |
| 400 | 请求参数错误 |
| 401 | 未认证 |
| 403 | 无权限 |
| 404 | 资源不存在 |
| 429 | 请求过于频繁 |
| 500 | 服务器内部错误 |
业务错误码
| code | 说明 | 场景 |
|---|---|---|
00000 | 成功 | 正常响应 |
A0001 | 参数校验失败 | 缺少必填字段、格式错误 |
A0002 | 用户不存在 | 登录、查询 |
A0003 | 密码错误 | 登录、修改密码 |
A0004 | Token 过期 | 需刷新或重新登录 |
A0005 | 验证码错误 | 登录 |
A0100 | 设备不存在 | 查询、控制 |
A0101 | 设备离线 | 控制指令下发时设备不在线 |
A0102 | 设备未注册 | 设备首次连接时未找到产品 |
A0103 | 设备认证失败 | Secret 不匹配 |
A0104 | 设备控制超时 | MQTT 指令下发后未收到回复 |
A0105 | 设备已存在 | 重复注册 (同 physicalId) |
A0200 | 产品不存在 | 查询、创建 |
A0201 | 物模型格式错误 | 创建/更新产品 |
A0300 | MQTT 服务异常 | Broker 连接断开 |
A0301 | 固件文件无效 | 上传文件不是合法 .bin |
A0302 | 固件版本已存在 | 同产品下版本号重复 |
A0303 | OTA 任务失败 | 设备离线或正忙 |
B0001 | 权限不足 | 角色不符 |
B0002 | 账号已禁用 | 登录 |
C0001 | 文件上传失败 | OSS 错误 / 格式不支持 |
使用约定
json
// 成功
{ "code": "00000", "msg": "Success", "data": {...} }
// 业务错误
{ "code": "A0101", "msg": "设备离线,指令无法下发" }
// 无 data 字段,前端只需检查 code !== "00000" 判定错误AI 编码指引: 后端所有异常通过
HttpExceptionFilter统一处理。业务异常抛BadRequestException('设备离线'),Filter 自动映射到对应 code。前端只需判断res.code !== '00000'展示错误提示。
全局中间件
| 组件 | 说明 |
|---|---|
| Helmet | HTTP 安全头 |
| CORS | 跨域支持 |
| ValidationPipe | 请求参数校验(whitelist + transform) |
| ThrottlerGuard | 全局限流(60秒/60次) |
| RequestLogger | 请求日志 |
| TransformInterceptor | 响应格式统一包装 |
| HttpExceptionFilter | 异常统一处理 |
