2026-07-04 04:03:02 +08:00
|
|
|
|
# API 接口文档
|
|
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
> 充电柜矩阵系统(PMS)接口规范。PC 管理端与微信小程序用户端共用同一套 API。
|
2026-07-04 04:03:02 +08:00
|
|
|
|
|
|
|
|
|
|
## 基础信息
|
|
|
|
|
|
|
|
|
|
|
|
- **测试环境**:`https://test.anzhizhichong.com/pms/api/`
|
|
|
|
|
|
- **正式环境**:`https://app.anzhizhichong.com/pms/api/`
|
|
|
|
|
|
- **认证方式**:Bearer Token(JWT)
|
|
|
|
|
|
- **响应格式**:`{ "code": 0, "data": ..., "message": "ok" }`
|
|
|
|
|
|
|
|
|
|
|
|
## 统一端点清单
|
|
|
|
|
|
|
|
|
|
|
|
| 方法 | 路径 | 说明 | 权限 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| POST | `/api/auth/login` | 登录 | 免认证 |
|
|
|
|
|
|
| GET | `/api/auth/logout` | 登出 | 需认证 |
|
|
|
|
|
|
| GET | `/api/auth/me` | 当前用户信息 | 需认证 |
|
|
|
|
|
|
| GET | `/api/dashboard` | 仪表盘数据 | 需认证 |
|
|
|
|
|
|
| GET | `/api/cabinets` | 设备列表(含 RSSI) | `device:view` |
|
|
|
|
|
|
| POST | `/api/cabinets` | 批量创建柜子 | `device:create` |
|
|
|
|
|
|
| GET | `/api/cabinets/:id` | 设备详情(含仓板+仓体) | `device:view` |
|
|
|
|
|
|
| PUT | `/api/cabinets/:id` | 更新柜子 | `device:edit` |
|
|
|
|
|
|
| DELETE | `/api/cabinets/:id` | 删除柜子 | `device:delete` |
|
2026-09-19 23:40:46 +08:00
|
|
|
|
| POST | `/api/cabinets/:id/regenerate-auth` | 重置安全码(仅总管理员) | `device:auth_str:reset` |
|
|
|
|
|
|
| POST | `/api/cabinets/:id/bind` | 绑定设备到项目 | `device:edit` |
|
|
|
|
|
|
| POST | `/api/cabinets/:id/replace-imei` | 更换 IMEI | `device:edit` |
|
2026-07-04 04:03:02 +08:00
|
|
|
|
| GET | `/api/cabinets/abstract/:abstract_id` | 扫码查设备(免认证) | 免认证 |
|
|
|
|
|
|
| GET | `/api/cabinets/scan/:abstract_id` | 扫码验证(需认证) | 需认证 |
|
|
|
|
|
|
| GET | `/api/cabinets/filter` | 设备列表(管理端) | 需认证 |
|
2026-09-19 23:40:46 +08:00
|
|
|
|
| GET | `/api/cabinets/options` | 设备下拉选项 | 需认证 |
|
|
|
|
|
|
| GET | `/api/cabin-boards/options` | 仓控板下拉选项 | 需认证 |
|
|
|
|
|
|
| GET | `/api/compartments/options` | 仓体下拉选项 | 需认证 |
|
2026-07-04 04:03:02 +08:00
|
|
|
|
| GET | `/api/cabinets/realtime-status` | 设备实时状态 | 需认证 |
|
|
|
|
|
|
| GET | `/api/compartments/:id` | 仓体/通道详情 | 需认证 |
|
|
|
|
|
|
| POST | `/api/charge/start` | 开始充电 | `charge:start` |
|
|
|
|
|
|
| POST | `/api/charge/stop` | 停止充电 | `charge:stop` |
|
2026-09-19 23:40:46 +08:00
|
|
|
|
| POST | `/api/door/open` | 开门(**柜级**:整柜共用一扇门,只解锁需人拉开) | `charge:open_door` |
|
|
|
|
|
|
| POST | `/api/cabinets/{id}/open` | 解锁柜门(柜级,同上;管理端设备详情页用) | `charge:open_door` |
|
|
|
|
|
|
| POST | `/api/cabinets/{id}/pow-on` | 接触器合闸(柜级) | `device:operate` |
|
|
|
|
|
|
| POST | `/api/cabinets/{id}/pow-off` | 接触器分闸(柜级) | `device:operate` |
|
|
|
|
|
|
| POST | `/api/cabinets/{id}/reset` | 重启整柜(柜级) | `device:operate` |
|
|
|
|
|
|
| POST | `/api/cabin-boards/{id}/reset` | 重启单块仓控板 | `device:operate` |
|
2026-07-04 04:03:02 +08:00
|
|
|
|
| GET | `/api/organizations` | 组织列表 | `org:view` |
|
|
|
|
|
|
| POST | `/api/organizations` | 创建组织 | `org:create` |
|
2026-09-19 23:40:46 +08:00
|
|
|
|
| PUT | `/api/organizations/:id` | 更新组织 | `org:edit` |
|
|
|
|
|
|
| DELETE | `/api/organizations/:id` | 删除组织 | `org:delete` |
|
2026-07-04 04:03:02 +08:00
|
|
|
|
| GET | `/api/organizations/:org_id/projects` | 项目列表 | 需认证 |
|
2026-09-19 23:40:46 +08:00
|
|
|
|
| POST | `/api/organizations/:org_id/projects` | 创建项目 | `project:create` |
|
|
|
|
|
|
| PUT | `/api/projects/:id` | 更新项目 | `project:edit` |
|
|
|
|
|
|
| DELETE | `/api/projects/:id` | 删除项目 | `project:delete` |
|
|
|
|
|
|
| GET | `/api/organization-tree` | 组织树(含项目/设备) | 需认证 |
|
2026-07-04 04:03:02 +08:00
|
|
|
|
| GET | `/api/charge-records` | 充电记录 | `charge_record:view` |
|
2026-09-19 23:40:46 +08:00
|
|
|
|
| GET | `/api/charge-records/export` | 导出充电记录 | `charge_record:export` |
|
|
|
|
|
|
| GET | `/api/charge-orders` | 充电订单列表 | `charge_record:view` |
|
|
|
|
|
|
| GET | `/api/batteries` | 电池台账列表 | `device:view` |
|
|
|
|
|
|
| GET | `/api/energy-stats/summary` | 能耗概览 | `energy:view` |
|
|
|
|
|
|
| GET | `/api/energy-stats/cabinets` | 柜子能耗排行 | `energy:view` |
|
|
|
|
|
|
| GET | `/api/energy-stats/projects` | 项目能耗统计 | `energy:view` |
|
|
|
|
|
|
| GET | `/api/energy-stats/trend` | 能耗趋势 | `energy:view` |
|
|
|
|
|
|
| GET | `/api/energy-stats/export` | 导出能耗数据 | `energy:view` |
|
|
|
|
|
|
| GET | `/api/device-logs` | 设备日志 | `device:view` |
|
|
|
|
|
|
| GET | `/api/operation-logs` | 操作日志 | `system:log` |
|
|
|
|
|
|
| GET | `/api/users` | 用户列表 | `user:view` |
|
|
|
|
|
|
| POST | `/api/users` | 创建用户 | `user:create` |
|
|
|
|
|
|
| PUT | `/api/users/:id` | 更新用户 | `user:edit` |
|
|
|
|
|
|
| DELETE | `/api/users/:id` | 删除用户 | `user:delete` |
|
|
|
|
|
|
| PUT | `/api/users/:id/reset-password` | 重置密码 | `user:edit` |
|
|
|
|
|
|
| PUT | `/api/users/:id/status` | 设置用户状态 | `user:edit` |
|
|
|
|
|
|
| GET | `/api/users/:id/permissions` | 用户权限 | `user:view` |
|
|
|
|
|
|
| PUT | `/api/users/:id/roles` | 分配角色 | `user:edit` |
|
|
|
|
|
|
| GET | `/api/users/:id/scopes` | 用户数据范围 | `user:view` |
|
|
|
|
|
|
| PUT | `/api/users/:id/scopes` | 设置数据范围 | `user:edit` |
|
|
|
|
|
|
| GET | `/api/roles` | 角色列表 | `role:view` |
|
|
|
|
|
|
| POST | `/api/roles` | 创建角色 | `role:create` |
|
|
|
|
|
|
| PUT | `/api/roles/:id` | 更新角色 | `role:edit` |
|
|
|
|
|
|
| DELETE | `/api/roles/:id` | 删除角色 | `role:delete` |
|
|
|
|
|
|
| PUT | `/api/roles/:id/permissions` | 角色赋权 | `role:edit` |
|
|
|
|
|
|
| GET | `/api/permissions` | 权限码列表 | `role:view` |
|
|
|
|
|
|
| GET | `/api/downloads` | 下载中心 | 需认证 |
|
|
|
|
|
|
| GET | `/api/downloads/:id` | 下载详情 | 需认证 |
|
|
|
|
|
|
| GET | `/api/downloads/:id/file` | 下载文件 | 需认证 |
|
|
|
|
|
|
| POST | `/api/downloads/cleanup` | 清理过期下载 | 需认证 |
|
|
|
|
|
|
| POST | `/api/devices/:dev_id/command` | 下发设备指令 | `device:operate` |
|
|
|
|
|
|
| GET | `/api/devices/stats` | 设备服务统计 | 需认证 |
|
|
|
|
|
|
| GET | `/api/health` | 健康检查 | 免认证 |
|
2026-07-04 04:03:02 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 认证接口
|
|
|
|
|
|
|
|
|
|
|
|
### POST /api/auth/login
|
|
|
|
|
|
|
|
|
|
|
|
**请求:**
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"phone": "13800138000",
|
|
|
|
|
|
"password": "admin123"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**响应:**
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 0,
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"token": "eyJ0eXAi...",
|
|
|
|
|
|
"user": {
|
|
|
|
|
|
"id": 1,
|
|
|
|
|
|
"name": "管理员",
|
|
|
|
|
|
"phone": "13800138000",
|
|
|
|
|
|
"role_level": 2,
|
|
|
|
|
|
"organization_id": null,
|
|
|
|
|
|
"permissions": ["device:view", "device:create", "..."]
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
"message": "登录成功"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
**角色等级:** 0=操作员,1=企业管理员,2=总管理员
|
2026-07-04 04:03:02 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
## 小程序专用接口
|
2026-07-04 04:03:02 +08:00
|
|
|
|
|
|
|
|
|
|
### GET /api/dashboard
|
|
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
小程序首页仪表盘数据。支持 `org_id` 参数按组织过滤。
|
2026-07-04 04:03:02 +08:00
|
|
|
|
|
|
|
|
|
|
**响应:**
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 0,
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"online_cabinets": 68,
|
|
|
|
|
|
"charging_count": 214,
|
|
|
|
|
|
"idle_channels": 722,
|
|
|
|
|
|
"fault_channels": 0,
|
|
|
|
|
|
"full_count": 0,
|
|
|
|
|
|
"today_charge_count": 0,
|
|
|
|
|
|
"today_energy_kwh": 0,
|
|
|
|
|
|
"today_charge_hours": 0,
|
|
|
|
|
|
"alerts": [],
|
|
|
|
|
|
"projects": [
|
|
|
|
|
|
{ "id": 1, "name": "无锡太湖新城换电站", "cabinet_count": 2, "charging": 16, "idle": 56, "fault": 0 }
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### GET /api/cabinets
|
|
|
|
|
|
|
|
|
|
|
|
设备列表,支持 `project_id` 和 `org_id` 过滤。响应包含实时 RSSI。
|
|
|
|
|
|
|
|
|
|
|
|
**响应字段:**
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": 1,
|
|
|
|
|
|
"abstract_id": "10-00000001",
|
|
|
|
|
|
"name": "太湖新城换电柜A",
|
|
|
|
|
|
"status": 1,
|
|
|
|
|
|
"project_id": 1,
|
|
|
|
|
|
"rssi": 85,
|
|
|
|
|
|
"channel_count": 36,
|
|
|
|
|
|
"idle_count": 30,
|
|
|
|
|
|
"charging_count": 6,
|
|
|
|
|
|
"full_count": 0,
|
|
|
|
|
|
"fault_count": 0
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### GET /api/cabinets/abstract/:abstract_id
|
|
|
|
|
|
|
|
|
|
|
|
扫码入口,免认证。通过二维码中的抽象ID查找设备。
|
|
|
|
|
|
|
|
|
|
|
|
**响应:**
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 0,
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"id": 1,
|
|
|
|
|
|
"abstract_id": "10-00000001",
|
|
|
|
|
|
"imei": "864720562557021",
|
|
|
|
|
|
"iccid": "8986012520983901841",
|
|
|
|
|
|
"name": "太湖新城换电柜A",
|
|
|
|
|
|
"status": 1,
|
|
|
|
|
|
"cabin_boards": [
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": 1,
|
|
|
|
|
|
"board_id": 1,
|
|
|
|
|
|
"status": 0,
|
|
|
|
|
|
"compartments": [
|
|
|
|
|
|
{ "id": 1, "channel_id": 1, "status": 0 }
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### GET /api/compartments/:id
|
|
|
|
|
|
|
|
|
|
|
|
仓体/通道详情,含实时 BMS 数据和充电记录。
|
|
|
|
|
|
|
|
|
|
|
|
**响应字段:**
|
|
|
|
|
|
- `voltage` — mV(整数)
|
|
|
|
|
|
- `current` — mA(整数)
|
|
|
|
|
|
- `energy` — Wh(整数)
|
2026-09-19 23:40:46 +08:00
|
|
|
|
- `soc` — ‰(0-10000,前端已自动转为 %)
|
2026-07-04 04:03:02 +08:00
|
|
|
|
- `cell_voltages` — mV 数组
|
|
|
|
|
|
|
|
|
|
|
|
### POST /api/charge/start
|
|
|
|
|
|
|
|
|
|
|
|
**请求:** `{ "compartment_id": 123 }`
|
|
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
> 权限:`charge:start` + 组织隔离(用户只能操作所属组织的设备)
|
|
|
|
|
|
|
2026-07-04 04:03:02 +08:00
|
|
|
|
### POST /api/charge/stop
|
|
|
|
|
|
|
|
|
|
|
|
**请求:** `{ "compartment_id": 123 }`
|
|
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
> 权限:`charge:stop` + 组织隔离
|
|
|
|
|
|
|
2026-07-04 04:03:02 +08:00
|
|
|
|
### POST /api/door/open
|
|
|
|
|
|
|
|
|
|
|
|
**请求:** `{ "compartment_id": 123 }`
|
|
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
> 权限:`charge:open_door` + 组织隔离
|
|
|
|
|
|
|
2026-07-04 04:03:02 +08:00
|
|
|
|
### GET /api/cabinets/scan/:abstract_id
|
|
|
|
|
|
|
|
|
|
|
|
扫码验证,需认证。验证当前用户是否有权访问该设备。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
## 管理端接口
|
|
|
|
|
|
|
|
|
|
|
|
### GET /api/charge-records
|
|
|
|
|
|
|
|
|
|
|
|
充电记录列表,支持按柜子/时间过滤,响应含组织数据隔离。
|
|
|
|
|
|
|
|
|
|
|
|
**查询参数:**
|
|
|
|
|
|
|
|
|
|
|
|
| 参数 | 类型 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `page` | int | 页码(默认 1) |
|
|
|
|
|
|
| `page_size` | int | 每页条数(默认 20,最大 100) |
|
|
|
|
|
|
| `cabinet_id` | int | 按柜子过滤 |
|
|
|
|
|
|
| `cabin_board_id` | int | 按仓控板过滤 |
|
|
|
|
|
|
| `compartment_id` | int | 按仓体过滤 |
|
|
|
|
|
|
| `start_time` | string | 开始时间(含),格式 `YYYY-MM-DD HH:MM:SS` |
|
|
|
|
|
|
| `end_time` | string | 结束时间(含),格式同上 |
|
|
|
|
|
|
|
|
|
|
|
|
**响应:**
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 0,
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"list": [
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": 1,
|
|
|
|
|
|
"cabinet_id": 1,
|
|
|
|
|
|
"cabinet_name": "太湖新城换电柜A",
|
|
|
|
|
|
"cabin_board_id": 1,
|
|
|
|
|
|
"board_id": 1,
|
|
|
|
|
|
"compartment_id": 1,
|
|
|
|
|
|
"channel_id": 1,
|
|
|
|
|
|
"start_time": "2026-07-05 10:00:00",
|
|
|
|
|
|
"end_time": "2026-07-05 12:00:00",
|
|
|
|
|
|
"energy": 1200,
|
|
|
|
|
|
"max_temperature": 30435,
|
|
|
|
|
|
"status": 1,
|
|
|
|
|
|
"status_text": "正常结束"
|
|
|
|
|
|
}
|
|
|
|
|
|
],
|
|
|
|
|
|
"total": 50,
|
|
|
|
|
|
"page": 1,
|
|
|
|
|
|
"page_size": 20
|
|
|
|
|
|
},
|
|
|
|
|
|
"message": "ok"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**状态码:** 0=充电中,1=正常结束,2=异常中断,3=手动停止
|
|
|
|
|
|
|
|
|
|
|
|
### GET /api/charge-records/export
|
|
|
|
|
|
|
|
|
|
|
|
异步导出充电记录 Excel。创建导出任务后自行去下载中心取文件。
|
|
|
|
|
|
|
|
|
|
|
|
**查询参数:** 同 `GET /api/charge-records`
|
|
|
|
|
|
|
|
|
|
|
|
**响应:**
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{ "code": 0, "data": { "task_id": 1 }, "message": "导出任务已创建" }
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### GET /api/charge-orders
|
|
|
|
|
|
|
|
|
|
|
|
充电订单列表。订单记录一次充电事件,含电池ID、SOC变化、结束原因。
|
|
|
|
|
|
|
|
|
|
|
|
**查询参数:**
|
|
|
|
|
|
|
|
|
|
|
|
| 参数 | 类型 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `page` | int | 页码(默认 1) |
|
|
|
|
|
|
| `page_size` | int | 每页条数(默认 20,最大 100) |
|
|
|
|
|
|
| `cabinet_id` | int | 按柜子过滤 |
|
|
|
|
|
|
| `compartment_id` | int | 按仓体过滤 |
|
|
|
|
|
|
| `battery_id` | string | 电池ID(模糊匹配) |
|
|
|
|
|
|
| `status` | int | 状态过滤 |
|
|
|
|
|
|
| `start_time` | string | 开始时间(含) |
|
|
|
|
|
|
| `end_time` | string | 结束时间(含) |
|
|
|
|
|
|
|
|
|
|
|
|
**响应:**
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 0,
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"list": [
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": 1,
|
|
|
|
|
|
"cabinet_id": 1,
|
|
|
|
|
|
"cabinet_name": "太湖新城换电柜A",
|
|
|
|
|
|
"compartment_id": 1,
|
|
|
|
|
|
"battery_id": "BAT001",
|
|
|
|
|
|
"start_time": "2026-07-05 10:00:00",
|
|
|
|
|
|
"end_time": "2026-07-05 12:00:00",
|
|
|
|
|
|
"start_soc": 20,
|
|
|
|
|
|
"end_soc": 95,
|
|
|
|
|
|
"energy": 1200,
|
|
|
|
|
|
"reason": null,
|
|
|
|
|
|
"reason_text": "-",
|
|
|
|
|
|
"status": 1,
|
|
|
|
|
|
"status_text": "正常结束",
|
|
|
|
|
|
"created_at": "2026-07-05 10:00:05"
|
|
|
|
|
|
}
|
|
|
|
|
|
],
|
|
|
|
|
|
"total": 50,
|
|
|
|
|
|
"page": 1,
|
|
|
|
|
|
"page_size": 20
|
|
|
|
|
|
},
|
|
|
|
|
|
"message": "ok"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**订单状态:** 0=充电中,1=正常结束,2=手动停止,3=异常终止,4=拔出结束
|
|
|
|
|
|
|
|
|
|
|
|
### GET /api/batteries
|
|
|
|
|
|
|
|
|
|
|
|
电池台账列表。记录每块电池的插入/拔出事件和当前状态。
|
|
|
|
|
|
|
|
|
|
|
|
**查询参数:**
|
|
|
|
|
|
|
|
|
|
|
|
| 参数 | 类型 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `page` | int | 页码(默认 1) |
|
|
|
|
|
|
| `page_size` | int | 每页条数(默认 20,最大 100) |
|
|
|
|
|
|
| `status` | int | 状态过滤 |
|
|
|
|
|
|
| `battery_id` | string | 电池ID(模糊匹配) |
|
|
|
|
|
|
|
|
|
|
|
|
**响应:**
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 0,
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"list": [
|
|
|
|
|
|
{
|
|
|
|
|
|
"id": 1,
|
|
|
|
|
|
"battery_id": "BAT001",
|
|
|
|
|
|
"brand": "星恒",
|
|
|
|
|
|
"model": "XH-48V",
|
|
|
|
|
|
"voltage": 52000,
|
|
|
|
|
|
"soc": 45,
|
|
|
|
|
|
"status": 1,
|
|
|
|
|
|
"cabinet_id": 1,
|
|
|
|
|
|
"compartment_id": 1,
|
|
|
|
|
|
"last_seen": "2026-07-05 12:00:00",
|
|
|
|
|
|
"created_at": "2026-07-01 08:00:00"
|
|
|
|
|
|
}
|
|
|
|
|
|
],
|
|
|
|
|
|
"total": 50,
|
|
|
|
|
|
"page": 1,
|
|
|
|
|
|
"page_size": 20
|
|
|
|
|
|
},
|
|
|
|
|
|
"message": "ok"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### GET /api/energy-stats/summary
|
|
|
|
|
|
|
|
|
|
|
|
能耗概览,按组织数据隔离返回今日/本月能耗数据。
|
|
|
|
|
|
|
|
|
|
|
|
**响应:**
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 0,
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"today_energy": 45000,
|
|
|
|
|
|
"month_energy": 1200000,
|
|
|
|
|
|
"estimated_cost": 840.00,
|
|
|
|
|
|
"cabinet_count": 36,
|
|
|
|
|
|
"online_count": 34
|
|
|
|
|
|
},
|
|
|
|
|
|
"message": "ok"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- `today_energy` / `month_energy` — Wh(整数)
|
|
|
|
|
|
- `estimated_cost` — 预估费用(float,元),按 `COST_PER_WH` 单价计算
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-07-04 04:03:02 +08:00
|
|
|
|
## 数据单位规范
|
|
|
|
|
|
|
|
|
|
|
|
**核心原则:所有数值字段使用整数存储,禁止浮点类型 (f32/f64/DECIMAL/FLOAT)**
|
|
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
**单位转换仅在前端:** API 始终返回原始单位值,前端负责转换为用户友好单位显示。后端禁止做任何单位换算。
|
|
|
|
|
|
|
|
|
|
|
|
### 标量字段
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 类型 | 单位 | 前端显示 | 转换公式 |
|
|
|
|
|
|
|------|------|------|----------|---------|
|
|
|
|
|
|
| `energy` / `total_energy` / `today_energy` / `month_energy` / `energy_kwh`¹ | i64 | **Wh** | kWh | `/ 1000` |
|
|
|
|
|
|
| `voltage` / `cell_voltages[]` | i64 | **mV** | V | `/ 1000` |
|
|
|
|
|
|
| `current` | i64 | **mA** | A | `/ 1000` |
|
|
|
|
|
|
| `soc` / `start_soc` / `end_soc` | i64 | **‰** | % | `/ 10` |
|
|
|
|
|
|
| `temp` / `cell_temps[]` / `max_temperature` | i64 | **K×100** | °C | `/ 100 - 273.15` |
|
|
|
|
|
|
| `rssi` | i64 | **0–99 信号等级** | 直接显示 | 不转换(不是 dBm) |
|
|
|
|
|
|
| `cost` / `estimated_cost` | i64/f64 | **元** | ¥ | 不转换(后端业务计算) |
|
|
|
|
|
|
| `today_charge_count` / `today_charge_hours` | i64 | 计数值 | 直接显示 | 不转换 |
|
|
|
|
|
|
|
|
|
|
|
|
¹ 注意:`energy_kwh` / `today_energy_kwh` 为历史遗留命名,实际值仍为 **Wh**,前端仍需 `/ 1000`。
|
|
|
|
|
|
|
|
|
|
|
|
### 示例
|
|
|
|
|
|
|
|
|
|
|
|
| 原始值 | 含义 | 前端显示 |
|
|
|
|
|
|
|--------|------|----------|
|
|
|
|
|
|
| `52000` | 电压(mV) | `52.0 V` |
|
|
|
|
|
|
| `10000` | 电流(mA) | `10.0 A` |
|
|
|
|
|
|
| `120000` | 功率(mW) | `120.0 W` |
|
|
|
|
|
|
| `1000` | 充电量(Wh) | `1.000 kWh` |
|
|
|
|
|
|
| `850` | SOC(‰) | `85.0%` |
|
|
|
|
|
|
| `29865` | 温度(K×100) | `25.5°C` |
|
|
|
|
|
|
| `85` | RSSI 信号等级(0–99) | `85` |
|
|
|
|
|
|
| `[32456,32500,32300]` | 单体电压(mV) | `32.456V, 32.500V, 32.300V` |
|
|
|
|
|
|
| `[29865,29900]` | 单体温度(K×100) | `25.5°C, 25.9°C` |
|
2026-07-04 04:03:02 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## TCP 设备通讯协议
|
|
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
> ⛔ **本节(自本行起至下一个 `##` 标题之前)全部内容已废弃,禁止作为实现依据。**
|
|
|
|
|
|
> **唯一权威文档:[`柜控板固件对接文档.md`](./柜控板固件对接文档.md)(v1.1)** —— 所有 TCP 报文格式、字段名、
|
|
|
|
|
|
> `act` 清单、签名算法、保活/超时规则、时序与异常处理,**一律以该文档为准**。
|
|
|
|
|
|
>
|
|
|
|
|
|
> 本节保留仅为历史参考。已知与定稿规范的**重大冲突**(仅列关键几处,避免误读):
|
|
|
|
|
|
> - ~~`dev_id` 上行全部报文必带~~ → **只有 `auth_str` / `login` 带**,其余报文不带(设备身份由 TCP 连接确定)
|
|
|
|
|
|
> - ~~`id` = `IMEI` / `IMEI-仓控板-通道`~~ → **`id` 不含 IMEI**:柜级**省略**、单板一段 `"01"`、仓体级两段 `"01-3"`
|
|
|
|
|
|
> - ~~空闲 1 分钟 / 充电 15 秒上报~~ → **`status_post` 固定每 60 秒一次、每次全量**
|
|
|
|
|
|
> - ~~`login` 应答返回 `cell`~~ → 返回 **`spec`**(柜子规格,如 `"0606"`)与 **`work_mode`**
|
|
|
|
|
|
> - ~~`pow_fail` 带 `info`~~ → 改为 **`pow_fail_dc` / `pow_fail_ac` 两条独立指令**,无附加字段
|
|
|
|
|
|
> - ~~`status_post` 的 `status` HEX 字典 / `bat_in` 的 `bms` 块~~ → 改为 **`cabinet` + `boards[].channels[]`(每通道 18 字符 hex 透传)** 与 **`battery` 块**
|
|
|
|
|
|
> - ~~`bat_in` 建单~~ → **`bat_in` 与订单无关,订单只由 `on` 建立**
|
|
|
|
|
|
> - 内部字段已由 `id` 改为 **`_dev_id`**(供 device-server 路由,下发前摘除)
|
|
|
|
|
|
|
|
|
|
|
|
### 设计原则
|
|
|
|
|
|
|
|
|
|
|
|
> MCU(Air780E)资源有限,TCP 协议遵循以下原则:
|
|
|
|
|
|
> 1. **响应扁平化**:字段直接放在顶层,不包 `data`/`result` 等嵌套层
|
|
|
|
|
|
> 2. **字段最小化**:需要几个字段传几个,不传空值、默认值
|
|
|
|
|
|
> 3. **JSON 紧凑**:去空格回车,不传多余引号和逗号(可用 `serde_json::to_string` 紧凑模式)
|
|
|
|
|
|
> 4. **响应必达**:所有**上行**报文平台都会回复;但**设备回执(带 `suc`)平台不再回包**(防误配对)
|
|
|
|
|
|
|
|
|
|
|
|
### 通信规则(⚠️ 下列旧描述已废弃,见节首说明)
|
|
|
|
|
|
|
|
|
|
|
|
- TCP 长连接,无需 PING 包 ✅(保活由 `status_post` 承担)
|
|
|
|
|
|
- ~~空闲 1 分钟上报,充电 15 秒上报~~ ❌ → **固定每 60 秒全量**
|
|
|
|
|
|
- ~~超时 5000ms~~ ❌ → **每个交互 60 秒超时,超时作废、迟到应答丢弃、不重试**
|
|
|
|
|
|
- JSON 去空格回车省流量,LF 处理粘包 ✅
|
|
|
|
|
|
- ~~`dev_id`:设备上报时使用~~ ❌ → **仅 `auth_str` / `login` 携带**
|
|
|
|
|
|
- ~~`id`:`IMEI-仓控板-通道` / `IMEI`~~ ❌ → **不含 IMEI**:柜级省略 / 单板 `"01"` / 仓体级 `"01-3"`
|
|
|
|
|
|
- `msg_id`:两个方向**各自独立计数,都每连接从 `1` 起自增**,重连归零;判"应答 vs 指令"看有无 `suc`
|
2026-07-04 04:03:02 +08:00
|
|
|
|
|
|
|
|
|
|
### 签名机制
|
|
|
|
|
|
|
|
|
|
|
|
- 设备首次连接调 `auth_str` 接口获取8位安全码(仅一次)
|
|
|
|
|
|
- `sign = SHA256(dev_id + auth_str + timestamp).substring(56, 63)`
|
|
|
|
|
|
- 时间戳秒级,平台校验±60秒
|
|
|
|
|
|
|
|
|
|
|
|
### 指令清单
|
|
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
> ⛔ **以下整段(含本表与其后的报文示例、`cell` / `pow_fail` / `bms` 字段说明)均为废弃的历史内容,请勿据此实现。**
|
|
|
|
|
|
> 现行清单与报文以 [`柜控板固件对接文档.md`](./柜控板固件对接文档.md) §4 / §5 为准。**`act` 共 13 个**:
|
|
|
|
|
|
> `auth_str` / `login` / `status_post` / `pow_fail_dc` / `pow_fail_ac` / `bat_in` / `bat_out` / `on` / `off` / `open` / `pow_on` / `pow_off` / `reset`
|
|
|
|
|
|
> (**已无 `pow_fail`**,拆成 `pow_fail_dc` / `pow_fail_ac`)
|
|
|
|
|
|
|
|
|
|
|
|
| 动作 | 方向 | 说明(⚠️ 历史,见上方说明) |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `login` | 设备→平台 | 登录(含 `sign`+`timestamp`+`iccid`);成功应答返回 **`spec`** + **`work_mode`**(不再是 `cell`) |
|
|
|
|
|
|
| `auth_str` | 设备→平台 | 获取安全码(首次 / 重置后;失败统一回 `invalid signature` 之外的两条见权威文档) |
|
|
|
|
|
|
| `status_post` | 设备→平台 | **每 60 秒全量**;结构为 `cabinet` + `boards[].channels[]`(每通道 18 字符 hex),**不再是 `status` 字典** |
|
|
|
|
|
|
| ~~`pow_fail`~~ | 设备→平台 | **已废弃** → 改为 `pow_fail_dc` / `pow_fail_ac`(无附加字段) |
|
|
|
|
|
|
| `pow_fail_dc` / `pow_fail_ac` | 设备→平台 | 直流停电 / 交流停电(事件上报) |
|
|
|
|
|
|
| `bat_in` | 设备→平台 | 电池插入(`battery` 块:属性 + `info` 18hex + `cells` hex);**不建单** |
|
|
|
|
|
|
| `bat_out` | 设备→平台 | 电池拔出(结束订单 `user_stop`) |
|
|
|
|
|
|
| `on` | **双向** | 开始充电(上行两形态:带 `suc`=回执 / 不带=上报;**建单唯一入口**) |
|
|
|
|
|
|
| `off` | **双向** | 充电停止(结束订单 `normal`) |
|
|
|
|
|
|
| `open` | 平台→设备 | **柜门解锁**(柜级:整柜共用一扇门,需人拉开;无"关门"指令) |
|
|
|
|
|
|
| `pow_on` / `pow_off` | 平台→设备 | 接触器合闸 / 分闸(`pow_off` 后仓控板随之下电 → 上报 `pow_fail_dc`) |
|
|
|
|
|
|
| `reset` | 平台→设备 | 重启整柜(`id` 省略)或单块仓控板(`id="01"`);**先回执再重启** |
|
|
|
|
|
|
|
|
|
|
|
|
> ⚠️ 所有设备上报消息平台都会回复 `{"suc":1,"msg_id":N}` 确认。响应字段扁平化,不加 `data` 包裹。
|
|
|
|
|
|
|
|
|
|
|
|
### 全局单位规范
|
|
|
|
|
|
|
|
|
|
|
|
所有数值字段使用整数存储,禁止浮点类型:
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 单位 | 精度 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| `voltage` | mV | 1 | 52000 = 52.000V |
|
|
|
|
|
|
| `current` | mA | 1 | 10000 = 10.000A |
|
|
|
|
|
|
| `temp` | K×100 | 0.01K | 29865 = 298.65K = 25.5°C |
|
|
|
|
|
|
| `soc` | ‰ | 0.1% | 4500 = 45.00% |
|
|
|
|
|
|
|
|
|
|
|
|
### 服务架构
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
设备 ─TCP─→ device-server ─LPUSH→ Redis ─BRPOP→ api-server
|
|
|
|
|
|
设备 ←TCP─ device-server ←BRPOP─ Redis ←LPUSH─ api-server
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**职责分层:**
|
|
|
|
|
|
|
|
|
|
|
|
| 层 | 职责 |
|
|
|
|
|
|
|---|------|
|
|
|
|
|
|
| **device-server** | TCP连接管理、协议解析(HEX→结构化)、消息转发 |
|
|
|
|
|
|
| **api-server** | 业务逻辑:签名验证、状态持久化、充电事件、告警、指令下发 |
|
|
|
|
|
|
|
|
|
|
|
|
**Redis 队列:**
|
|
|
|
|
|
|
|
|
|
|
|
| 队列 | 方向 | 说明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| `device:reports` | 设备→平台 | device-server 转发设备上报 |
|
|
|
|
|
|
| `device:commands` | 平台→设备 | api-server 下发指令/响应 |
|
|
|
|
|
|
|
|
|
|
|
|
### 全局单位规范
|
2026-07-04 04:03:02 +08:00
|
|
|
|
|
|
|
|
|
|
#### login(设备→平台)
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
2026-09-19 23:40:46 +08:00
|
|
|
|
{"act":"login","msg_id":1,"dev_id":"123456789012345","sign":"abc12345","timestamp":1719800000,"iccid":"89860000000000000000"}
|
2026-07-04 04:03:02 +08:00
|
|
|
|
// 响应:{"suc":1,"msg_id":1,"cell":6}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
- `iccid` — SIM卡ICCID(变更时写 SIM 变更日志)
|
|
|
|
|
|
- `cell` — 仓控板数量(柜子配置属性)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-07-04 04:03:02 +08:00
|
|
|
|
#### auth_str(设备→平台)
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
2026-09-19 23:40:46 +08:00
|
|
|
|
{"act":"auth_str","msg_id":2,"dev_id":"123456789012345"}
|
|
|
|
|
|
// 响应:{"suc":1,"msg_id":2,"auth_str":"abcd1234"}
|
2026-07-04 04:03:02 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
- `auth_str` — 8位随机安全码(仅返回一次,标记后不可重复获取)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-07-04 04:03:02 +08:00
|
|
|
|
#### status_post(设备→平台)
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{"act":"status_post","msg_id":10,"dev_id":"123456789012345","rssi":85,
|
2026-09-19 23:40:46 +08:00
|
|
|
|
"status":{"00":"0001","01":"000100020003000400050006","02":"000100020003000400050006"}}
|
2026-07-04 04:03:02 +08:00
|
|
|
|
// 响应:{"suc":1,"msg_id":10}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
**status 字段:**
|
|
|
|
|
|
- key: `"00"`=柜子级, `"01"`~`"N"`=仓控板级(N = cell-1)
|
|
|
|
|
|
- value: 6通道状态拼接(每通道4个HEX字符=2字节)
|
|
|
|
|
|
- device-server 解析后附加 `parsed_status` 字段,api-server 直接写入 Redis
|
|
|
|
|
|
|
|
|
|
|
|
**HEX 解析(device-server 负责,格式待硬件团队最终确认):**
|
|
|
|
|
|
- 字节1 bit1=充电中, bit2=充满, bit3=故障
|
|
|
|
|
|
- 当前实现:每通道4字符,取字节1解析
|
|
|
|
|
|
|
|
|
|
|
|
> ⚠️ HEX 编码格式待硬件团队最终确认,当前为预留实现。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
#### pow_fail(设备→平台)
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{"act":"pow_fail","msg_id":15,"dev_id":"123456789012345","info":"0"}
|
|
|
|
|
|
// 响应:{"suc":1,"msg_id":15}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
- `info` — 停电类型:`0`=直流停电(12V掉电),`1`=交流停电(380V掉电)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-07-04 04:03:02 +08:00
|
|
|
|
#### bat_in / bat_out(设备→平台)
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
2026-09-19 23:40:46 +08:00
|
|
|
|
{"act":"bat_in","msg_id":20,"id":"123456789012345-01-01","bms":{
|
|
|
|
|
|
"soc":4500,"voltage":52000,"current":10000,"temp":29865,
|
|
|
|
|
|
"battery_id":"BAT001","brand":"星恒","model":"XH-48V","sn":"SN123456"
|
|
|
|
|
|
}}
|
|
|
|
|
|
// 响应:{"suc":1,"msg_id":20}
|
|
|
|
|
|
|
|
|
|
|
|
{"act":"bat_out","msg_id":21,"id":"123456789012345-01-01","bms":{
|
|
|
|
|
|
"battery_id":"BAT001","soc":4500
|
|
|
|
|
|
}}
|
|
|
|
|
|
// 响应:{"suc":1,"msg_id":21}
|
2026-07-04 04:03:02 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
**BMS 字段(全局整数单位):**
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 单位 | 精度 | 说明 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| `soc` | ‰ | 0.1% | 4500 = 45.00% |
|
|
|
|
|
|
| `voltage` | mV | 1 | 52000 = 52.000V |
|
|
|
|
|
|
| `current` | mA | 1 | 10000 = 10.000A |
|
|
|
|
|
|
| `temp` | K×100 | 0.01K | 29865 = 298.65K = 25.5°C |
|
|
|
|
|
|
| `battery_id` | — | — | 电池唯一标识 |
|
|
|
|
|
|
| `brand` | — | — | BMS品牌 |
|
|
|
|
|
|
| `model` | — | — | BMS型号 |
|
|
|
|
|
|
| `sn` | — | — | BMS序列号 |
|
|
|
|
|
|
| `cell_voltages` | mV | 1 | 单体电芯电压数组 |
|
|
|
|
|
|
|
|
|
|
|
|
> `bat_out` 只需上传 `battery_id`、`soc`(其他数据不变)。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-07-04 04:03:02 +08:00
|
|
|
|
#### on / off(双向)
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
2026-09-19 23:40:46 +08:00
|
|
|
|
// 平台→设备:下发充电
|
|
|
|
|
|
{"act":"on","msg_id":30,"id":"123456789012345-01-01"}
|
|
|
|
|
|
// 设备响应:{"suc":1,"msg_id":30}
|
|
|
|
|
|
|
2026-07-04 04:03:02 +08:00
|
|
|
|
// 设备→平台:充电开始确认
|
2026-09-19 23:40:46 +08:00
|
|
|
|
{"act":"on","msg_id":30,"id":"123456789012345-01-01"}
|
|
|
|
|
|
// 平台响应:{"suc":1,"msg_id":30}
|
|
|
|
|
|
|
|
|
|
|
|
// 平台→设备:下发停止
|
|
|
|
|
|
{"act":"off","msg_id":31,"id":"123456789012345-01-01"}
|
|
|
|
|
|
// 设备响应:{"suc":1,"msg_id":31}
|
|
|
|
|
|
|
|
|
|
|
|
// 设备→平台:充满自动停止
|
|
|
|
|
|
{"act":"off","msg_id":31,"id":"123456789012345-01-01"}
|
|
|
|
|
|
// 平台响应:{"suc":1,"msg_id":31}
|
2026-07-04 04:03:02 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
> `on` 必须由平台下发,设备不可主动充电。MCU 保证 `off` → `bat_out` 顺序。
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-07-04 04:03:02 +08:00
|
|
|
|
#### open(平台→设备)
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{"act":"open","msg_id":40,"id":"123456789012345"}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
**响应:** `{"suc":1,"msg_id":40}`
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
#### pow_on / pow_off(平台→设备)
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{"act":"pow_on","msg_id":50,"id":"123456789012345"}
|
|
|
|
|
|
{"act":"pow_off","msg_id":51,"id":"123456789012345"}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**响应:** `{"suc":1,"msg_id":50}`
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-07-04 04:03:02 +08:00
|
|
|
|
#### reset(平台→设备)
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
// 重启整柜
|
|
|
|
|
|
{"act":"reset","msg_id":60,"id":"123456789012345"}
|
|
|
|
|
|
// 重启仓控板
|
|
|
|
|
|
{"act":"reset","msg_id":61,"id":"123456789012345-01"}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
**响应:** `{"suc":1,"msg_id":60}`
|
|
|
|
|
|
|
2026-07-04 04:03:02 +08:00
|
|
|
|
### 充电结束原因
|
|
|
|
|
|
|
|
|
|
|
|
| 平台收到 | 判断原因 |
|
|
|
|
|
|
|---------|---------|
|
|
|
|
|
|
| `off` (设备→平台) | `normal` — 正常充满 |
|
|
|
|
|
|
| `off` (平台→设备) | `user_stop` — 用户手动停止 |
|
|
|
|
|
|
| `bat_out` | `normal` — 电池拔出 |
|
|
|
|
|
|
| `bat_in` (通道已有电池) | `forced` — 新电池插入强制结束 |
|
|
|
|
|
|
| 超时未响应 | `timeout` — 通信超时 |
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## Redis 实时状态存储
|
|
|
|
|
|
|
|
|
|
|
|
### 层级结构
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
device:{imei} # 设备级 Hash
|
|
|
|
|
|
├─ online = "1" # 在线标记(TTL 300秒)
|
|
|
|
|
|
├─ rssi = "85" # 信号强度
|
|
|
|
|
|
├─ pow_fail_dc = "0/1" # 直流停电
|
2026-09-19 23:40:46 +08:00
|
|
|
|
├─ pow_fail_ac = "0/1" # 交流停电
|
2026-07-04 04:03:02 +08:00
|
|
|
|
└─ device:{imei}:board:{board_idx} # 板级 Hash
|
|
|
|
|
|
├─ status_hex = "00010002..." # 原始hex状态
|
2026-09-19 23:40:46 +08:00
|
|
|
|
└─ device:{imei}:board:{board_idx}:ch:{ch} # 通道级 Hash(1~6)
|
|
|
|
|
|
├─ on = "0/1" # 充电中
|
2026-07-04 04:03:02 +08:00
|
|
|
|
├─ full = "0/1" # 充满
|
|
|
|
|
|
├─ fault = "0/1" # 故障
|
2026-09-19 23:40:46 +08:00
|
|
|
|
├─ hex = "0001" # 原始hex(4字符)
|
|
|
|
|
|
├─ battery_id = "BAT001" # 电池ID(bat_in 写入,bat_out 清除)
|
|
|
|
|
|
├─ soc = "4500" # 电量 ‰
|
|
|
|
|
|
├─ voltage = "52000" # 电压 mV
|
|
|
|
|
|
├─ current = "10000" # 电流 mA
|
|
|
|
|
|
├─ temp = "29865" # 温度 K×100
|
|
|
|
|
|
├─ brand = "星恒" # BMS品牌
|
|
|
|
|
|
├─ model = "XH-48V" # BMS型号
|
|
|
|
|
|
└─ sn = "SN123456" # BMS序列号
|
2026-07-04 04:03:02 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
> HEX 解析由 device-server 负责,api-server 只接收结构化数据写入 Redis。
|
2026-07-04 04:03:02 +08:00
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
### BMS 字段(全局整数单位)
|
|
|
|
|
|
|
|
|
|
|
|
| 字段 | 单位 | 精度 | 说明 |
|
2026-07-04 04:03:02 +08:00
|
|
|
|
|------|------|------|------|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
| `soc` | ‰ | 0.1% | 4500 = 45.00% |
|
|
|
|
|
|
| `voltage` | mV | 1 | 52000 = 52.000V |
|
|
|
|
|
|
| `current` | mA | 1 | 10000 = 10.000A |
|
|
|
|
|
|
| `energy` | Wh | 1 | 累计充电量 |
|
|
|
|
|
|
| `temp` | K×100 | 0.01K | 29865 = 298.65K = 25.5°C |
|
|
|
|
|
|
| `battery_id` | — | — | 电池唯一标识 |
|
|
|
|
|
|
| `brand` | — | — | BMS品牌 |
|
|
|
|
|
|
| `model` | — | — | BMS型号 |
|
|
|
|
|
|
| `sn` | — | — | BMS序列号 |
|
|
|
|
|
|
| `cell_voltages` | mV | 1 | 单体电芯电压数组 |
|
2026-07-04 04:03:02 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 权限码列表
|
|
|
|
|
|
|
2026-09-19 23:40:46 +08:00
|
|
|
|
> 以 `software/api-server/src/db/migrate.rs::seed_permissions` 的**种子表为准**(下表与之对齐)。
|
|
|
|
|
|
> ⚠️ 历史上代码里曾误用一个**不存在**的权限码 `device:door:unlock`(种子里从来没有它)→ 导致开门对所有角色 403,**已修正为 `charge:open_door`**。
|
|
|
|
|
|
|
2026-07-04 04:03:02 +08:00
|
|
|
|
| 权限码 | 说明 |
|
|
|
|
|
|
|--------|------|
|
|
|
|
|
|
| `device:view` | 查看设备 |
|
2026-09-19 23:40:46 +08:00
|
|
|
|
| `device:operate` | 操作设备(开合闸 / 重启 / 开门等柜级控制) |
|
|
|
|
|
|
| `device:create` | 添加设备 |
|
|
|
|
|
|
| `device:edit` | 编辑设备(含修改充电工作模式) |
|
2026-07-04 04:03:02 +08:00
|
|
|
|
| `device:delete` | 删除设备 |
|
2026-09-19 23:40:46 +08:00
|
|
|
|
| `device:auth_str:reset` | 重置安全码(**仅总管理员**) |
|
2026-07-04 04:03:02 +08:00
|
|
|
|
| `charge:start` | 开始充电 |
|
|
|
|
|
|
| `charge:stop` | 停止充电 |
|
2026-09-19 23:40:46 +08:00
|
|
|
|
| `charge:open_door` | 开门(柜门解锁) |
|
2026-07-04 04:03:02 +08:00
|
|
|
|
| `charge_record:view` | 查看充电记录 |
|
2026-09-19 23:40:46 +08:00
|
|
|
|
| `charge_record:export` | 导出充电记录 |
|
|
|
|
|
|
| `device_log:view` | 查看设备日志 |
|
|
|
|
|
|
| `energy:view` | 查看能耗 |
|
|
|
|
|
|
| `energy:export` | 导出能耗 |
|
|
|
|
|
|
| `user:view` / `user:create` / `user:edit` / `user:delete` | 用户管理 |
|
|
|
|
|
|
| `role:view` / `role:create` / `role:edit` / `role:delete` | 角色管理 |
|
|
|
|
|
|
| `operation_log:view` | 查看操作日志 |
|
|
|
|
|
|
| `org:view` / `org:create` / `org:edit` / `org:delete` | 组织管理 |
|