用电设备控制平台 · 控制端接口文档
一、概述
本文档定义用电设备控制平台的控制端接口规范,涵盖 App 与小程序使用的接口,供前端开发人员联调使用。管理后台接口请参阅《管理端接口文档》。
每个接口均包含功能说明、请求参数、响应结构以及请求 / 响应示例;接口清单见第四章,字段定义与错误码见附录。
二、业务流程图
下图展示用户从注册登录到设备控制的完整业务流程:
三、接口约定
3.1 认证方式
除认证模块中的登录、注册、短信验证码、刷新令牌接口外,其余接口均需在请求头中携带 JWT 令牌:
Authorization: Bearer {accessToken}
令牌过期(默认 2 小时)后,需使用 refreshToken 调用刷新接口获取新令牌。refreshToken 有效期 7 天,使用后立即吊销并返回新值(旋转机制)。
3.2 统一响应格式
所有接口返回统一包装结构:
| 字段 | 类型 | 说明 |
|---|---|---|
| code | int | 业务状态码,0 表示成功,非 0 表示失败 |
| message | string | 提示信息 |
| data | object | 业务数据,失败时为 null |
3.3 分页响应格式
3.4 时间参数
所有时间参数均使用 毫秒级 Unix 时间戳。
四、接口目录
本章按模块汇总全部接口名称与路径,便于速查。点击接口名称可跳转至详细说明。
4.1 控制端 · 认证(/app/v1/auth)
| 接口名称 | 方法 | 路径 | 认证 |
|---|---|---|---|
| 发送短信验证码 | POST | /app/v1/auth/sms-code | 公开 |
| 用户注册 | POST | /app/v1/auth/register | 公开 |
| 密码登录 | POST | /app/v1/auth/login | 公开 |
| 短信验证码登录 | POST | /app/v1/auth/login-by-sms | 公开 |
| 微信小程序登录 | POST | /app/v1/auth/login-by-wechat | 公开 |
| 微信绑定手机号 | POST | /app/v1/auth/bind-phone | 公开 |
| 刷新令牌 | POST | /app/v1/auth/refresh | 公开 |
| 退出登录 | POST | /app/v1/auth/logout | 需认证 |
| 当前用户信息 | GET | /app/v1/auth/me | 需认证 |
| 当前用户权限码 | GET | /app/v1/auth/permissions | 需认证 |
| 当前用户菜单树 | GET | /app/v1/auth/menus | 需认证 |
4.2 控制端 · 设备(/app/v1/devices)
| 接口名称 | 方法 | 路径 | 认证 |
|---|---|---|---|
| 设备列表 | GET | /app/v1/devices | 需认证 |
| 批量实时状态 | GET | /app/v1/devices/status | 需认证 |
| 设备详情 | GET | /app/v1/devices/{deviceId} | 需认证 |
| 绑定设备 | POST | /app/v1/devices/bind | 需认证 |
| 解绑设备 | POST | /app/v1/devices/{deviceId}/unbind | 需认证 |
| 修改设备 | PUT | /app/v1/devices/{deviceId} | 需认证 |
| 远程开关控制 | POST | /app/v1/devices/{deviceId}/control | 需认证 |
| 查询指令执行结果 | GET | /app/v1/devices/{deviceId}/commands/{requestId} | 需认证 |
| 历史用电趋势 | GET | /app/v1/devices/{deviceId}/energy-history | 需认证 |
| 清零用电量 | POST | /app/v1/devices/reset | 需认证 |
4.3 控制端 · 分组(/app/v1/groups)
| 接口名称 | 方法 | 路径 | 认证 |
|---|---|---|---|
| 分组列表(含设备数量) | GET | /app/v1/groups | 需认证 |
| 新增分组 | POST | /app/v1/groups | 需认证 |
| 修改分组 | PUT | /app/v1/groups/{groupId} | 需认证 |
| 删除分组 | DELETE | /app/v1/groups/{groupId} | 需认证 |
| 加入设备 | POST | /app/v1/groups/{groupId}/devices | 需认证 |
| 移出设备 | POST | /app/v1/groups/{groupId}/devices/remove | 需认证 |
| 分组批量开关 | POST | /app/v1/groups/{groupId}/switch | 需认证 |
4.4 控制端 · 电费与功率(/app/v1)
| 接口名称 | 方法 | 路径 | 认证 |
|---|---|---|---|
| 电费单价查询 | GET | /app/v1/fee-config | 需认证 |
| 电费单价变更历史 | GET | /app/v1/fee-config/history | 需认证 |
| 设置电费单价 | PUT | /app/v1/fee-config | 需认证 |
| 功率配置查询 | GET | /app/v1/power-config | 需认证 |
| 功率配置保存 | PUT | /app/v1/power-config | 需认证 |
4.5 控制端 · 历史记录(/app/v1/history)
| 接口名称 | 方法 | 路径 | 认证 |
|---|---|---|---|
| 告警历史 | GET | /app/v1/history/alarms | 需认证 |
| 本人操作日志 | GET | /app/v1/history/operation-logs | 需认证 |
4.5.1 控制端 · 实时推送(WebSocket)
| 接口名称 | 协议 | 路径 | 认证 |
|---|---|---|---|
| 设备状态实时推送 | WS | /ws/device-status?token={accessToken} | 需认证 |
4.6 控制端 · 菜单与权限(/app/v1/rbac)
| 接口名称 | 方法 | 路径 | 认证 |
|---|---|---|---|
| 小程序菜单树 | GET | /app/v1/rbac/menus | 需认证 |
| 全部菜单(扁平) | GET | /app/v1/rbac/menus/all | 需认证 |
| 新增菜单 | POST | /app/v1/rbac/menus | 需认证 |
| 修改菜单 | PUT | /app/v1/rbac/menus/{menuId} | 需认证 |
| 删除菜单 | DELETE | /app/v1/rbac/menus/{menuId} | 需认证 |
| 角色列表 | GET | /app/v1/rbac/roles | 需认证 |
| 新增角色 | POST | /app/v1/rbac/roles | 需认证 |
| 修改角色 | PUT | /app/v1/rbac/roles/{roleId} | 需认证 |
| 删除角色 | DELETE | /app/v1/rbac/roles/{roleId} | 需认证 |
| 分配角色菜单 | POST | /app/v1/rbac/roles/{roleId}/menus | 需认证 |
4.7 平台 · 探活与健康
| 接口名称 | 方法 | 路径 | 认证 |
|---|---|---|---|
| 控制端服务探活 | GET | /app/v1/ping | 公开 |
| 聚合健康检查 | GET | /api/health | 公开 |
/app/v1,供 App 与小程序使用;4.7 为平台级探活与健康检查接口。令牌由控制端认证模块签发。
五、认证模块
认证模块接口前缀:/app/v1/auth,除"当前用户信息"外均无需认证。
请求参数(Body)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| phone | string | 是 | 手机号,11 位,1 开头 |
请求示例
{ "phone": "13800138000" }
响应示例
触发频率限制时返回 20102;当日发送次数超限返回 20103。
请求参数(Body)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| phone | string | 是 | 手机号,11 位,1 开头 |
| password | string | 是 | 密码,6~64 位 |
| nickname | string | 否 | 昵称,最长 64 字符 |
| code | string | 是 | 短信验证码,6 位数字 |
请求示例
{
"phone": "13800138000",
"password": "Abc@123456",
"nickname": "张三",
"code": "123456"
}
响应示例
注册成功后使用同一手机号与密码调用密码登录接口获取令牌。验证码错误返回 20101。
请求参数(Body)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| phone | string | 是 | 手机号 |
| password | string | 是 | 密码 |
响应 data 字段
| 字段 | 类型 | 说明 |
|---|---|---|
| accessToken | string | JWT 访问令牌 |
| tokenType | string | 固定值 "Bearer" |
| expiresIn | long | accessToken 有效期(秒) |
| roles | string[] | 角色编码列表 |
| refreshToken | string | 刷新令牌 |
| refreshExpiresIn | long | refreshToken 有效期(秒) |
请求示例
{ "phone": "13800138000", "password": "Abc@123456" }
响应示例
密码连续错误 5 次返回 20104,账号锁定 15 分钟;账号被禁用时登录失败。
请求参数(Body)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| phone | string | 是 | 手机号 |
| code | string | 是 | 短信验证码,6 位数字 |
请求示例
{ "phone": "13800138000", "code": "123456" }
响应示例
请求参数(Body)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| code | string | 是 | wx.login 获取的临时 code |
响应 data 额外字段
| 字段 | 类型 | 说明 |
|---|---|---|
| needBindPhone | boolean | 是否需要绑定手机号 |
| tempTicket | string | 绑定手机号临时票据 |
请求示例
{ "code": "0815Xyz12345" }
响应示例(已绑定手机号)
首次登录且未绑定手机号时,accessToken 为空,needBindPhone 为 true,前端须携带 tempTicket 调用绑定手机号接口。
请求参数(Body)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| tempTicket | string | 是 | 微信登录返回的临时票据 |
| phone | string | 是 | 手机号 |
| code | string | 是 | 短信验证码 |
请求示例
{
"tempTicket": "tk_9f2c4a1b7d3e",
"phone": "13800138000",
"code": "123456"
}
响应示例
临时票据失效返回 10100,验证码错误返回 20101。
请求参数(Body)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| refreshToken | string | 是 | 登录返回的 refreshToken |
请求示例
{ "refreshToken": "a1b2c3d4e5f6" }
响应示例
令牌无效或已过期返回 20107。前端应保存响应中的新 refreshToken 覆盖旧值。
请求参数(Body,可选)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| refreshToken | string | 否 | 刷新令牌,传入则一并吊销 |
请求示例
{ "refreshToken": "a1b2c3d4e5f6" }
响应示例
请求头仍需携带有效的 Authorization: Bearer {accessToken}。
响应 data 字段
| 字段 | 类型 | 说明 |
|---|---|---|
| id | long | 用户 ID |
| phone | string | 手机号 |
| nickname | string | 昵称 |
| roles | string[] | 角色编码列表 |
| permissions | string[] | 权限码列表,"*" 表示全部权限 |
请求参数
无。用户身份由请求头令牌解析。
响应示例
device:*、group:*),管理后台权限码(system:*)不会出现在此接口。拥有 ADMIN 或 SUPER_ADMIN 角色时返回通配符 "*",表示不限权限。请求参数
无。用户身份由请求头 Authorization: Bearer {accessToken} 解析。
响应 data
字符串数组,权限码格式为"模块:动作",例如 device:view、device:control、group:manage。
响应示例
六、设备模块
设备模块接口前缀:/app/v1/devices,所有接口均需认证。仅返回当前登录用户名下的设备。
请求参数(Query)
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| keyword | string | 否 | - | 关键词(设备名称或序列号) |
| groupId | long | 否 | - | 分组 ID |
| pageNum | int | 否 | 1 | 页码,从 1 开始 |
| pageSize | int | 否 | 20 | 每页条数,上限 100 |
响应 data
分页结构,list 元素为 Device 对象。
请求示例
GET /app/v1/devices?keyword=空压机&groupId=7&pageNum=1&pageSize=20
响应示例
请求参数(Query)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| deviceIds | long[] | 否 | 设备 ID 列表,多个用逗号分隔 |
响应 data
DeviceStatusView 数组,详见 数据模型。
请求示例
GET /app/v1/devices/status?deviceIds=101,102,103
响应示例
路径参数
| 字段 | 类型 | 说明 |
|---|---|---|
| deviceId | long | 设备 ID |
响应 data 字段(DeviceDetail)
| 字段 | 类型 | 说明 |
|---|---|---|
| device | Device | 设备基础信息 |
| groupName | string | 所属分组名称,未分组时为 null |
| latest | DeviceLatestSnapshot | 最近一次上报快照 |
| status | DeviceStatusView | 实时状态视图 |
| unitPrice | decimal | 当前生效电费单价(元/kWh) |
| activeAlarms | DeviceAlarm[] | 进行中的告警列表 |
请求示例
GET /app/v1/devices/101
响应示例
设备不存在返回 30101;访问非本人设备返回 30104。
请求参数(Body)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| serialNo | string | 是 | 设备序列号,1~64 位字母数字下划线短横线 |
| name | string | 否 | 设备名称,留空默认使用序列号 |
响应 data
绑定成功的 Device 对象。
请求示例
{ "serialNo": "DEV-2026-0001", "name": "一号车间空压机" }
响应示例
设备已被其他用户绑定返回 30102;序列号格式不合法返回 10000。
路径参数
| 字段 | 类型 | 说明 |
|---|---|---|
| deviceId | long | 设备 ID |
请求示例
POST /app/v1/devices/101/unbind
响应示例
解绑后该设备不再出现在本人设备列表中,重新绑定后可恢复。
路径参数
| 字段 | 类型 | 说明 |
|---|---|---|
| deviceId | long | 设备 ID |
请求参数(Body)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | 否 | 设备名称 |
| groupId | long | 否 | 分组 ID,null 表示不修改,0 表示移出分组 |
请求示例
{ "name": "二号车间空压机", "groupId": 8 }
响应示例
路径参数
| 字段 | 类型 | 说明 |
|---|---|---|
| deviceId | long | 设备 ID |
请求参数(Body)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| action | string | 是 | 动作:on(开)或 off(关) |
响应 data 字段
| 字段 | 类型 | 说明 |
|---|---|---|
| requestId | string | 指令请求 ID,用于查询执行结果 |
| sent | boolean | 指令是否已发送 |
| status | string | 初始状态:pending |
| failReason | string | 失败原因,成功时为 null |
请求示例
{ "action": "on" }
响应示例
设备离线时 sent 为 false 并返回失败原因;模板缺失或 MQTT 不可用返回 30106。
路径参数
| 字段 | 类型 | 说明 |
|---|---|---|
| deviceId | long | 设备 ID |
| requestId | string | 控制接口返回的请求 ID |
响应 data 关键字段
| 字段 | 类型 | 说明 |
|---|---|---|
| status | string | pending / success / timeout / failed |
| failReason | string | 失败原因 |
| sentAt | datetime | 下发时间 |
| ackAt | datetime | 设备确认时间 |
请求示例
GET /app/v1/devices/101/commands/cmd-20261029-0001
响应示例
建议控制接口调用后每 1~2 秒轮询一次,最长轮询 30 秒;超时后状态固定为 timeout。
路径参数
| 字段 | 类型 | 说明 |
|---|---|---|
| deviceId | long | 设备 ID |
请求参数(Query)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| startTime | long | 是 | 开始时间(毫秒时间戳) |
| endTime | long | 是 | 结束时间(毫秒时间戳) |
响应 data 字段
| 字段 | 类型 | 说明 |
|---|---|---|
| points | array | 趋势点列表 |
| resolution | string | 分辨率:minute / hour / day |
| usage | decimal | 区间用电量(kWh) |
| fee | decimal | 区间费用(元) |
| resetAt | long | 最近一次清零时间,无则为 null |
请求示例
GET /app/v1/devices/101/energy-history?startTime=1793145600000&endTime=1793232000000
响应示例
起止时间缺失或区间非法返回 10000。
请求参数(Body)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| scope | string | 是 | 范围:device / group / all |
| deviceId | long | 条件必填 | 设备 ID,scope=device 时必填 |
| groupId | long | 条件必填 | 分组 ID,scope=group 时必填 |
响应 data 字段
| 字段 | 类型 | 说明 |
|---|---|---|
| scope | string | 清零范围 |
| successCount | int | 成功台数 |
| failedCount | int | 失败台数 |
| failures | array | 失败明细(deviceId + reason) |
请求示例(按分组清零)
{ "scope": "group", "groupId": 7 }
响应示例
scope 取值非法返回 40104;scope=device 时缺少 deviceId 返回 10000。
七、分组模块
分组模块接口前缀:/app/v1/groups,所有接口均需认证。一台设备同一时间只属于一个分组,重复加入即移动。单分组设备上限 200 台。
响应 data
数组,每个元素包含 group(分组信息)和 deviceCount(设备数量)。
请求示例
GET /app/v1/groups
响应示例
请求参数(Body)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | 是 | 分组名称,最长 64 字符 |
| sortNo | int | 否 | 排序号,越小越靠前,0~9999 |
请求示例
{ "name": "一号车间", "sortNo": 1 }
响应示例
同一用户名下分组名称重复返回 40102。
路径参数
| 字段 | 类型 | 说明 |
|---|---|---|
| groupId | long | 分组 ID |
请求参数(Body)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| action | string | 是 | 动作:on / off |
请求示例
{ "action": "off" }
响应示例
分组不存在或不属于当前用户返回 40101。部分设备失败不影响整体返回成功。
路径参数
| 字段 | 类型 | 说明 |
|---|---|---|
| groupId | long | 分组 ID |
请求参数(Body)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | 是 | 分组名称,最长 64 字符 |
| sortNo | int | 否 | 排序号,0~9999,越小越靠前 |
请求示例
{ "name": "一号车间(东区)", "sortNo": 2 }
响应示例
路径参数
| 字段 | 类型 | 说明 |
|---|---|---|
| groupId | long | 分组 ID |
响应示例
路径参数
| 字段 | 类型 | 说明 |
|---|---|---|
| groupId | long | 分组 ID |
请求参数(Body)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| deviceIds | long[] | 是 | 设备 ID 列表,不可为空 |
请求示例
{ "deviceIds": [101, 102, 103] }
响应示例
路径参数
| 字段 | 类型 | 说明 |
|---|---|---|
| groupId | long | 分组 ID |
请求参数(Body)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| deviceIds | long[] | 是 | 设备 ID 列表,不可为空 |
请求示例
{ "deviceIds": [101, 102] }
响应示例
八、电费与功率配置
本章接口前缀:/app/v1,均需认证,配置按用户维度独立生效。历史用电费用按各时段生效单价分段计算。
请求参数
无。
响应 data 字段(FeeConfig)
| 字段 | 类型 | 说明 |
|---|---|---|
| id | long | 配置记录 ID |
| userId | long | 所属用户 ID |
| unitPrice | decimal | 电费单价(元/kWh) |
| effectiveFrom | datetime | 生效时间 |
响应示例
请求参数
无。
响应 data
FeeConfig 数组。
响应示例
请求参数(Body)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| unitPrice | decimal | 是 | 电费单价(元/kWh),范围 0~100 |
请求示例
{ "unitPrice": 0.6500 }
响应 data
更新后的 FeeConfig 对象。
响应示例
单价超出 0~100 范围返回 10000。
请求参数
无。
响应 data 字段(PowerConfig)
| 字段 | 类型 | 说明 |
|---|---|---|
| id | long | 配置记录 ID |
| userId | long | 所属用户 ID |
| maxPower | decimal | 最大功率阈值(W),实时功率超过即触发告警 |
| recoverPower | decimal | 恢复功率阈值(W),实时功率回落到此值以下告警解除 |
| alarmEnabled | boolean | 是否开启越限告警 |
| autoCutoff | boolean | 越限后是否自动下发断电指令 |
响应示例
请求参数(Body)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| maxPower | decimal | 是 | 最大功率阈值(W),须大于 0 |
| recoverPower | decimal | 否 | 恢复阈值(W),为空时取 maxPower × 0.95 |
| alarmEnabled | boolean | 否 | 是否开启越限告警 |
| autoCutoff | boolean | 否 | 越限后是否自动断电 |
请求示例
{
"maxPower": 3000,
"recoverPower": 2850,
"alarmEnabled": true,
"autoCutoff": false
}
响应 data
保存后的 PowerConfig 对象。
响应示例
maxPower 小于等于 0 返回 10000;recoverPower 应小于 maxPower。
九、控制端历史记录
本章接口前缀:/app/v1/history,均需认证,仅返回当前登录用户自身的数据。
请求参数(Query)
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| status | string | 否 | - | 告警状态:active(进行中)/ recovered(已恢复),不传返回全部 |
| alarmType | string | 否 | - | 告警类型:power_overload(功率越限)/ offline(离线)/ power_lost(失电) |
| pageNum | int | 否 | 1 | 页码 |
| pageSize | int | 否 | 20 | 每页条数,上限 100 |
响应 data
分页结构,list 元素为 DeviceAlarm。
响应示例
请求参数(Query)
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
| operationType | string | 否 | - | 操作类型,精确匹配 |
| startTime | long | 否 | - | 开始时间(毫秒时间戳) |
| endTime | long | 否 | - | 结束时间(毫秒时间戳) |
| pageNum | int | 否 | 1 | 页码 |
| pageSize | int | 否 | 20 | 每页条数,上限 100 |
响应 data
分页结构,list 元素包含:id、userId、channel、httpMethod、path、querySummary、operationType、targetType、targetId、content、ip、durationMs、success、createdAt。
响应示例
九(附)、设备状态实时推送(WebSocket)
平台通过 WebSocket 向小程序端实时推送设备状态变更(上线/离线、开关状态变化、告警触发/恢复等),无需轮询。连接建立时须携带有效的 accessToken,服务端按用户维度维护会话并定向推送。
ping 心跳,服务端回复 pong。连接断开后须使用最新的 accessToken 重新握手。连接方式
| 项 | 说明 |
|---|---|
| 协议 | ws://(生产环境使用 wss://) |
| 路径 | /ws/device-status |
| 鉴权 | URL Query 参数 token = 登录返回的 accessToken |
| 跨域 | 允许任意来源(setAllowedOriginPatterns("*")) |
连接示例
服务端推送消息结构(DeviceStatusEvent)
| 字段 | 类型 | 说明 |
|---|---|---|
| userId | long | 接收推送的用户 ID |
| type | String | 事件类型,如 status_change、alarm 等 |
| deviceId | long | 设备 ID |
| serialNo | String | 设备序列号 |
| name | String | 设备名称 |
| online | boolean | 是否在线 |
| powerStatus | String | 电源状态:on / off |
| displayStatus | String | 展示状态文案 |
| alarmType | String | 告警类型(无告警时为 null) |
| timestamp | long | 事件时间戳(毫秒) |
推送示例
心跳
客户端发送文本 ping,服务端回复 pong。建议每 30 秒发送一次,超过 90 秒未收到 pong 可判定连接异常并重连。
十、菜单与权限(RBAC)
本章接口前缀为 /app/v1/rbac,供小程序端使用。小程序端可管理 APP 渠道的菜单与角色,与管理后台的菜单/权限物理隔离。
channel 字段(APP/ADMIN)归属小程序端或管理后台,两套菜单物理隔离。小程序端 /app/v1/auth/menus 仅返回 APP 渠道菜单,管理后台 /admin/v1/rbac/menus 仅返回 ADMIN 渠道菜单;普通用户的权限码同样按渠道过滤,device:* 与 system:* 互不交叉。
10.1 权限模型
| 概念 | 说明 |
|---|---|
| 菜单(menu) | 前端导航项,包含名称、路由、图标、排序号,支持多级父子结构 |
| 按钮(button) | 页面内操作权限点,通过权限码标识,不参与导航展示 |
| 权限码 | 格式为"模块:动作",如 system:rbac、device:control,接口按权限码校验 |
| 角色 | 权限集合,一个角色可绑定多个菜单,一个用户可拥有多个角色 |
| SUPER_ADMIN | 内置超级管理员角色,不可停用、不可删除 |
/admin/v1/rbac/** 需权限码 system:rbac;/admin/v1/users/** 需权限码 system:user。无对应权限返回错误码 10300。
10.2 小程序端菜单与权限
小程序端同样提供完整的菜单与角色管理接口,前缀为 /app/v1/rbac,仅操作 APP 渠道的菜单。新增菜单自动归属 APP 渠道,修改、删除、分配均校验渠道,防止越权操作管理后台菜单。
请求参数
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| code | String | 是 | 角色编码,大写字母/下划线,2-32 位 |
| name | String | 是 | 角色名称,最长 64 |
| description | String | 否 | 角色描述,最长 255 |
| enabled | boolean | 否 | 是否启用,默认 true |
响应 data
Role 对象。
请求参数
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | String | 是 | 角色名称 |
| description | String | 否 | 角色描述 |
| enabled | boolean | 否 | 是否启用 |
请求参数
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| menuIds | Long[] | 是 | 菜单 ID 列表,空数组表示清空 |
请求示例
10.3 权限校验说明
| 场景 | 返回 |
|---|---|
| 令牌缺失或已过期 | 错误码 10100,需重新登录 |
| 已登录但缺少接口要求的权限码 | 错误码 10300,无权限 |
| 菜单已停用(enabled=false) | 不参与菜单树返回,权限码同步失效 |
| 角色已停用(enabled=false) | 该角色下的授权全部失效 |
十一、平台探活与健康
本章接口无需认证,供运维监控、网关探活与部署校验使用。建议探活接口调用间隔不低于 10 秒。
请求参数
无。
响应示例
网关或负载均衡应判断 code 是否为 0,而非 HTTP 状态码。
code=0,调用方需读取 data.status 判断。执行 SQL SELECT 1 检测数据库,PING 检测 Redis,检测 MQTT 客户端连接状态。请求参数
无。
响应 data 字段
| 字段 | 类型 | 说明 |
|---|---|---|
| application | string | 应用标识,固定 device-platform |
| phase | int | 建设阶段标识 |
| postgres | string | 数据库状态:UP / DOWN |
| redis | string | 缓存状态:UP / DOWN |
| mqtt | string | 消息通道状态:UP / DOWN |
| status | string | 整体状态:全 UP 为 UP,否则为 DEGRADED |
响应示例(全部正常)
响应示例(MQTT 异常)
MQTT 为 DOWN 时远程控制指令无法下发,设备实时状态可能停止刷新。
十二、数据模型
Device — 设备信息
| 字段 | 类型 | 说明 |
|---|---|---|
| id | long | 设备主键 |
| serialNo | string | 设备序列号(MQTT deviceId) |
| name | string | 设备名称 |
| ownerUserId | long | 归属用户 ID |
| groupId | long | 分组 ID |
| model | string | 设备型号 |
| ratedPower | decimal | 额定功率(W) |
| status | int | 状态:1 启用,0 停用 |
| powerStatus | string | 最近开关状态:on / off |
| createdAt | datetime | 创建时间 |
DeviceStatusView — 设备实时状态
| 字段 | 类型 | 说明 |
|---|---|---|
| deviceId | long | 设备 ID |
| serialNo | string | 设备序列号 |
| name | string | 设备名称 |
| groupId | long | 分组 ID |
| online | boolean | 是否在线 |
| powerStatus | string | 开关状态:on / off |
| realTimePower | decimal | 实时功率(W) |
| totalUsage | decimal | 累计用电量(kWh) |
| currentUsage | decimal | 清零后用电量(kWh) |
| currentFee | decimal | 当前费用(元) |
| signalStrength | int | 信号强度 |
| displayStatus | string | 展示状态:on / off / offline / power_lost / alarm / alarm_cutoff |
| alarmType | string | 活动告警类型 |
| lastReportTime | long | 最近上报时间(毫秒时间戳) |
DeviceAlarm — 告警信息
| 字段 | 类型 | 说明 |
|---|---|---|
| id | long | 告警 ID |
| deviceId | long | 设备 ID |
| alarmType | string | 告警类型:power_overload / offline / power_lost |
| level | string | 告警级别 |
| detail | string | 告警详情 |
| status | string | 状态:active / recovered |
| triggeredAt | datetime | 触发时间 |
| recoveredAt | datetime | 恢复时间 |
Menu — 菜单/按钮
| 字段 | 类型 | 说明 |
|---|---|---|
| id | long | 菜单 ID |
| parentId | long | 父级菜单 ID,null 表示顶级 |
| name | string | 菜单名称 |
| type | string | 类型:menu / button |
| path | string | 前端路由地址 |
| permissionCode | string | 权限码,格式"模块:动作" |
| icon | string | 图标标识 |
| sortNo | int | 排序号,升序排列 |
| enabled | boolean | 是否启用 |
| channel | string | 归属渠道:APP=小程序端,ADMIN=管理后台。菜单按渠道物理隔离,小程序端仅可见 APP 菜单,管理后台仅可见 ADMIN 菜单 |
DeviceStatusEvent — WebSocket 推送事件
| 字段 | 类型 | 说明 |
|---|---|---|
| userId | long | 接收推送的用户 ID |
| type | string | 事件类型,如 status_change、alarm |
| deviceId | long | 设备 ID |
| serialNo | string | 设备序列号 |
| name | string | 设备名称 |
| online | boolean | 是否在线 |
| powerStatus | string | 电源状态:on / off |
| displayStatus | string | 展示状态文案 |
| alarmType | string | 告警类型,无告警时为 null |
| timestamp | long | 事件时间戳(毫秒) |
MenuNode — 菜单树节点
| 字段 | 类型 | 说明 |
|---|---|---|
| menu | Menu | 当前节点菜单信息 |
| children | MenuNode[] | 子节点列表,无子节点时为空数组 |
Role — 角色
| 字段 | 类型 | 说明 |
|---|---|---|
| id | long | 角色 ID |
| code | string | 角色编码,大写字母或下划线 |
| name | string | 角色名称 |
| description | string | 角色描述 |
| enabled | boolean | 是否启用 |
DeviceLatestSnapshot — 最近上报快照
| 字段 | 类型 | 说明 |
|---|---|---|
| serialNo | string | 设备序列号 |
| totalUsage | decimal | 累计用电量(kWh) |
| realTimePower | decimal | 实时功率(W) |
| powerStatus | string | 开关状态:on / off |
| voltage | decimal | 电压(V) |
| current | decimal | 电流(A) |
| signalStrength | int | 信号强度(dBm) |
| lastReportTime | long | 最近上报时间(毫秒时间戳) |
| alarmActive | boolean | 是否存在活动告警 |
| alarmType | string | 活动告警类型,无告警时为 null |
DeviceDetail — 设备详情
| 字段 | 类型 | 说明 |
|---|---|---|
| device | Device | 设备基础信息 |
| groupName | string | 所属分组名称,未分组时为 null |
| latest | DeviceLatestSnapshot | 最近上报快照 |
| status | DeviceStatusView | 实时状态视图 |
| unitPrice | decimal | 当前生效电费单价(元/kWh) |
| activeAlarms | DeviceAlarm[] | 进行中的告警列表 |
EnergyHistoryResponse — 历史用电
| 字段 | 类型 | 说明 |
|---|---|---|
| points | EnergyHistoryPoint[] | 趋势点列表 |
| resolution | string | 聚合粒度:minute / hour / day |
| usage | decimal | 区间用电量(kWh) |
| fee | decimal | 区间费用(元),按历史单价分段计算 |
| resetAt | long | 最近一次清零时间(毫秒时间戳),无则为 null |
EnergyHistoryPoint — 用电趋势点
| 字段 | 类型 | 说明 |
|---|---|---|
| bucketTime | long | 时间桶起点(毫秒时间戳) |
| avgPower | decimal | 区间平均功率(W) |
| maxPower | decimal | 区间最大功率(W) |
| minPower | decimal | 区间最小功率(W) |
| totalUsage | decimal | 区间用电量(kWh) |
| sampleCount | int | 区间采样点数 |
FeeConfig — 电费配置
| 字段 | 类型 | 说明 |
|---|---|---|
| id | long | 配置记录 ID |
| userId | long | 所属用户 ID |
| unitPrice | decimal | 电费单价(元/kWh) |
| effectiveFrom | datetime | 生效时间 |
PowerConfig — 功率配置
| 字段 | 类型 | 说明 |
|---|---|---|
| id | long | 配置记录 ID |
| userId | long | 所属用户 ID |
| maxPower | decimal | 最大功率阈值(W) |
| recoverPower | decimal | 恢复功率阈值(W) |
| alarmEnabled | boolean | 是否开启越限告警 |
| autoCutoff | boolean | 越限后是否自动断电 |
DeviceGroup — 分组
| 字段 | 类型 | 说明 |
|---|---|---|
| id | long | 分组 ID |
| ownerUserId | long | 所属用户 ID |
| name | string | 分组名称 |
| sortNo | int | 排序号,越小越靠前 |
| createdAt | datetime | 创建时间 |
| updatedAt | datetime | 更新时间 |
DeviceGroupView — 分组视图
| 字段 | 类型 | 说明 |
|---|---|---|
| group | DeviceGroup | 分组信息 |
| deviceCount | int | 分组内设备数量 |
GroupSwitchResult — 分组批量开关结果
| 字段 | 类型 | 说明 |
|---|---|---|
| successCount | int | 指令发送成功的设备数 |
| failedCount | int | 发送失败的设备数 |
| failures | object[] | 失败明细,元素含 deviceId 与 reason |
ResetResult — 清零结果
| 字段 | 类型 | 说明 |
|---|---|---|
| scope | string | 清零范围:device / group / all |
| successCount | int | 成功台数 |
| failedCount | int | 失败台数 |
| failures | object[] | 失败明细,元素含 deviceId 与 reason |
CommandResult — 指令下发结果
| 字段 | 类型 | 说明 |
|---|---|---|
| requestId | string | 指令请求 ID,全局唯一 |
| sent | boolean | 指令是否已提交至消息通道 |
| status | string | 初始状态固定为 pending |
| failReason | string | 失败原因,成功时为 null |
CommandLog — 指令记录
| 字段 | 类型 | 说明 |
|---|---|---|
| id | long | 记录 ID |
| requestId | string | 指令请求 ID |
| deviceId | long | 设备 ID |
| serialNo | string | 设备序列号 |
| msgType | string | 消息类型 |
| topic | string | 实际下发主题 |
| payload | string | 实际下发报文 |
| expectedStatus | string | 期望达到的开关状态 |
| status | string | pending / success / timeout / failed |
| failReason | string | 失败原因 |
| operatorUserId | long | 操作人用户 ID |
| sentAt | datetime | 下发时间 |
| ackAt | datetime | 设备确认时间 |
| createdAt | datetime | 创建时间 |
CommandTemplate — 指令模板
| 字段 | 类型 | 说明 |
|---|---|---|
| id | long | 模板 ID |
| name | string | 模板名称,全局唯一 |
| msgType | string | 消息类型标识 |
| topicTemplate | string | 主题模板,支持 ${deviceId} |
| payloadTemplate | string | 报文模板,支持 ${deviceId} ${requestId} ${powerStatus} ${timestamp} |
| description | string | 模板说明 |
| enabled | boolean | 是否启用 |
| createdAt | datetime | 创建时间 |
| updatedAt | datetime | 更新时间 |
LoginResponse — 登录响应
| 字段 | 类型 | 说明 |
|---|---|---|
| accessToken | string | JWT 访问令牌 |
| tokenType | string | 固定 Bearer |
| expiresIn | long | 访问令牌有效秒数 |
| roles | string[] | 角色编码列表 |
| refreshToken | string | 刷新令牌 |
| refreshExpiresIn | long | 刷新令牌有效秒数 |
| needBindPhone | boolean | 是否需要绑定手机号,仅微信登录返回 |
| tempTicket | string | 绑定手机号临时票据,仅微信登录且未绑定时返回 |
UserProfileResponse — 用户资料
| 字段 | 类型 | 说明 |
|---|---|---|
| id | long | 用户 ID |
| phone | string | 手机号(登录账号) |
| nickname | string | 昵称 |
| roles | string[] | 角色编码列表 |
| permissions | string[] | 权限码列表,"*" 表示全部权限 |
十三、错误码表
| 错误码 | 说明 |
|---|---|
| 0 | 成功 |
| 10000 | 请求参数错误 |
| 10100 | 未登录或登录已失效 |
| 10300 | 无权限 |
| 10400 | 资源不存在 |
| 10500 | 系统异常 |
| 20101 | 验证码错误或已过期 |
| 20102 | 验证码发送过于频繁 |
| 20103 | 验证码发送次数已达上限 |
| 20104 | 密码错误次数过多,账号已锁定 15 分钟 |
| 20105 | 微信登录未配置 |
| 20107 | 刷新令牌无效或已过期 |
| 30101 | 设备不存在 |
| 30102 | 设备已被其他用户绑定 |
| 30104 | 无权操作该设备 |
| 30106 | 指令下发失败 |
| 40101 | 分组不存在 |
| 40102 | 分组名称已存在 |
| 40103 | 分组设备数量已达上限 |
| 40104 | 清零范围参数不合法 |
| 60101 | 缺少权限 |