352 lines
9.8 KiB
Markdown
352 lines
9.8 KiB
Markdown
|
|
# API 接口文档
|
|||
|
|
|
|||
|
|
> 充电柜矩阵系统(PMS)接口规范。PC 管理端与 H5 用户端共用同一套 API。
|
|||
|
|
|
|||
|
|
## 基础信息
|
|||
|
|
|
|||
|
|
- **测试环境**:`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` |
|
|||
|
|
| GET | `/api/cabinets/abstract/:abstract_id` | 扫码查设备(免认证) | 免认证 |
|
|||
|
|
| GET | `/api/cabinets/scan/:abstract_id` | 扫码验证(需认证) | 需认证 |
|
|||
|
|
| GET | `/api/cabinets/filter` | 设备列表(管理端) | 需认证 |
|
|||
|
|
| GET | `/api/cabinets/realtime-status` | 设备实时状态 | 需认证 |
|
|||
|
|
| GET | `/api/compartments/:id` | 仓体/通道详情 | 需认证 |
|
|||
|
|
| POST | `/api/charge/start` | 开始充电 | `charge:start` |
|
|||
|
|
| POST | `/api/charge/stop` | 停止充电 | `charge:stop` |
|
|||
|
|
| POST | `/api/door/open` | 开门 | `device:door:unlock` |
|
|||
|
|
| GET | `/api/organizations` | 组织列表 | `org:view` |
|
|||
|
|
| POST | `/api/organizations` | 创建组织 | `org:create` |
|
|||
|
|
| GET | `/api/organizations/:org_id/projects` | 项目列表 | 需认证 |
|
|||
|
|
| GET | `/api/charge-records` | 充电记录 | `charge_record:view` |
|
|||
|
|
| GET | `/api/energy-stats/summary` | 能耗统计 | 需认证 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 认证接口
|
|||
|
|
|
|||
|
|
### 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": "登录成功"
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**角色等级:** 1=普通用户,2=超级管理员
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## H5 专用接口
|
|||
|
|
|
|||
|
|
### GET /api/dashboard
|
|||
|
|
|
|||
|
|
H5 首页仪表盘数据。支持 `org_id` 参数按组织过滤。
|
|||
|
|
|
|||
|
|
**响应:**
|
|||
|
|
```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(整数)
|
|||
|
|
- `power` — mW(整数)
|
|||
|
|
- `energy` — Wh(整数)
|
|||
|
|
- `soc` — %(0-100)
|
|||
|
|
- `soh` — %(0-100)
|
|||
|
|
- `cell_voltages` — mV 数组
|
|||
|
|
|
|||
|
|
### POST /api/charge/start
|
|||
|
|
|
|||
|
|
**请求:** `{ "compartment_id": 123 }`
|
|||
|
|
|
|||
|
|
### POST /api/charge/stop
|
|||
|
|
|
|||
|
|
**请求:** `{ "compartment_id": 123 }`
|
|||
|
|
|
|||
|
|
### POST /api/door/open
|
|||
|
|
|
|||
|
|
**请求:** `{ "compartment_id": 123 }`
|
|||
|
|
|
|||
|
|
### GET /api/cabinets/scan/:abstract_id
|
|||
|
|
|
|||
|
|
扫码验证,需认证。验证当前用户是否有权访问该设备。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 数据单位规范
|
|||
|
|
|
|||
|
|
**核心原则:所有数值字段使用整数存储,禁止浮点类型 (f32/f64/DECIMAL/FLOAT)**
|
|||
|
|
|
|||
|
|
| 字段 | 类型 | 单位 | 说明 |
|
|||
|
|
|------|------|------|------|
|
|||
|
|
| `energy` | i64 | **Wh** | 充电量,不存小数 |
|
|||
|
|
| `voltage` | i64 | **mV** | 电池组总电压 |
|
|||
|
|
| `current` | i64 | **mA** | 电流,正=充电 负=放电 |
|
|||
|
|
| `power` | i64 | **mW** | 功率 |
|
|||
|
|
| `soc` / `soh` | i64 | **%** | 电量百分比 / 健康度 |
|
|||
|
|
| `max_temperature` | i64 | **0.1°C** | 25.3°C → `253` |
|
|||
|
|
| `rssi` | i64 | **dBm** | 信号强度 |
|
|||
|
|
|
|||
|
|
**温度转换:** 前端显示时除以10加小数点(25.3°C → `253`)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## TCP 设备通讯协议
|
|||
|
|
|
|||
|
|
### 通信规则
|
|||
|
|
|
|||
|
|
- TCP 长连接,无需 PING 包
|
|||
|
|
- 空闲 1 分钟上报,充电 15 秒上报
|
|||
|
|
- 超时 5000ms
|
|||
|
|
- JSON 去空格回车省流量,LF 处理粘包
|
|||
|
|
- `dev_id`:IMEI(10进制),`sub_device_id`:485 ID
|
|||
|
|
- `msg_id`:自增会话 ID
|
|||
|
|
- 全局通道号:`dev_id-sub_device_id-通道号`(如 `123456789012345-01-6`)
|
|||
|
|
|
|||
|
|
### 签名机制
|
|||
|
|
|
|||
|
|
- 设备首次连接调 `auth_str` 接口获取8位安全码(仅一次)
|
|||
|
|
- `sign = SHA256(dev_id + auth_str + timestamp).substring(56, 63)`
|
|||
|
|
- 时间戳秒级,平台校验±60秒
|
|||
|
|
|
|||
|
|
### 指令清单
|
|||
|
|
|
|||
|
|
| 动作 | 方向 | id格式 | 说明 |
|
|||
|
|
|------|------|--------|------|
|
|||
|
|
| `login` | 设备→平台 | 无 | 登录(含sign+timestamp) |
|
|||
|
|
| `auth_str` | 设备→平台 | 无 | 获取安全码(仅首次) |
|
|||
|
|
| `status_post` | 设备→平台 | 无 | 定时上报(rssi+status字典) |
|
|||
|
|
| `pow_fail` | 设备→平台 | 无 | 电源掉电上报 |
|
|||
|
|
| `bat_in` | 设备→平台 | `IMEI-仓控板-通道` | 电池插入 |
|
|||
|
|
| `bat_out` | 设备→平台 | `IMEI-仓控板-通道` | 电池拔出 |
|
|||
|
|
| `on` | **双向** | `IMEI-仓控板-通道` | 开始充电 |
|
|||
|
|
| `off` | **双向** | `IMEI-仓控板-通道` | 停止供电 |
|
|||
|
|
| `open` | 平台→设备 | `IMEI` | 开门 |
|
|||
|
|
| `pow_on` | 平台→设备 | `IMEI` | 接触器合闸 |
|
|||
|
|
| `pow_off` | 平台→设备 | `IMEI` | 接触器分闸 |
|
|||
|
|
| `reset` | 平台→设备 | `IMEI` 或 `IMEI-仓控板` | 重启整柜或仓控板 |
|
|||
|
|
|
|||
|
|
### 指令详情
|
|||
|
|
|
|||
|
|
#### login(设备→平台)
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{"act":"login","msg_id":1,"dev_id":"123456789012345","sign":"abc12345","timestamp":1719800000,"h_ver":"1.0.0","s_ver":"1.0.0"}
|
|||
|
|
// 响应:{"suc":1,"msg_id":1,"cell":6}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### auth_str(设备→平台)
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{"act":"auth_str","msg_id":2,"dev_id":"123456789012345","ccid":"89860000000000000000"}
|
|||
|
|
// 响应:{"suc":1,"msg_id":2,"data":{"auth_str":"abcd1234"}}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### status_post(设备→平台)
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{"act":"status_post","msg_id":10,"dev_id":"123456789012345","rssi":85,
|
|||
|
|
"status":{"123456789012345-01":"000100020003000400050006"}}
|
|||
|
|
// 响应:{"suc":1,"msg_id":10}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### bat_in / bat_out(设备→平台)
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{"act":"bat_in","msg_id":20,"id":"123456789012345-01-6","bms":{"soc":45,"voltage":52.3}}
|
|||
|
|
{"act":"bat_out","msg_id":21,"id":"123456789012345-01-6"}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### on / off(双向)
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
// 平台→设备:开始充电
|
|||
|
|
{"act":"on","msg_id":30,"id":"123456789012345-01-6"}
|
|||
|
|
// 设备→平台:充电开始确认
|
|||
|
|
{"act":"on","msg_id":30,"id":"123456789012345-01-6"}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### open(平台→设备)
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{"act":"open","msg_id":40,"id":"123456789012345"}
|
|||
|
|
// 错误码63 = 门锁故障
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### reset(平台→设备)
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
// 重启整柜
|
|||
|
|
{"act":"reset","msg_id":60,"id":"123456789012345"}
|
|||
|
|
// 重启仓控板
|
|||
|
|
{"act":"reset","msg_id":61,"id":"123456789012345-01"}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 充电结束原因
|
|||
|
|
|
|||
|
|
| 平台收到 | 判断原因 |
|
|||
|
|
|---------|---------|
|
|||
|
|
| `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" # 直流停电
|
|||
|
|
└─ device:{imei}:board:{board_idx} # 板级 Hash
|
|||
|
|
├─ status_hex = "00010002..." # 原始hex状态
|
|||
|
|
└─ device:{imei}:board:{board_idx}:ch:{0-5} # 通道级 Hash
|
|||
|
|
├─ on = "0/1" # 充电中
|
|||
|
|
├─ full = "0/1" # 充满
|
|||
|
|
├─ fault = "0/1" # 故障
|
|||
|
|
└─ hex = "00010002" # 原始hex
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### BMS 字段
|
|||
|
|
|
|||
|
|
| 字段 | 类型 | 单位 | 说明 |
|
|||
|
|
|------|------|------|------|
|
|||
|
|
| `soc` | i64 | % | 电池电量百分比 |
|
|||
|
|
| `soh` | i64 | % | 电池健康度百分比 |
|
|||
|
|
| `voltage` | i64 | mV | 电池组总电压 |
|
|||
|
|
| `current` | i64 | mA | 电流 |
|
|||
|
|
| `power` | i64 | mW | 功率 |
|
|||
|
|
| `energy` | i64 | Wh | 累计充电量 |
|
|||
|
|
| `cell_voltages` | i64[] | mV | 单体电芯电压数组 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 权限码列表
|
|||
|
|
|
|||
|
|
| 权限码 | 说明 |
|
|||
|
|
|--------|------|
|
|||
|
|
| `device:view` | 查看设备 |
|
|||
|
|
| `device:create` | 创建设备 |
|
|||
|
|
| `device:edit` | 编辑设备 |
|
|||
|
|
| `device:delete` | 删除设备 |
|
|||
|
|
| `device:door:unlock` | 开门 |
|
|||
|
|
| `charge:start` | 开始充电 |
|
|||
|
|
| `charge:stop` | 停止充电 |
|
|||
|
|
| `charge_record:view` | 查看充电记录 |
|
|||
|
|
| `org:view` | 查看组织 |
|
|||
|
|
| `org:create` | 创建组织 |
|
|||
|
|
| `org:edit` | 编辑组织 |
|