# 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` | 编辑组织 |