261 lines
12 KiB
Markdown
261 lines
12 KiB
Markdown
# 智能充电桩管理系统 (Charging Pile Management System)
|
||
|
||
## 1. 项目简介
|
||
|
||
本项目是一个基于 Spring Boot (后端) 和 Next.js (前端) 构建的智能充电桩管理与计费系统。旨在为用户提供便捷的充电服务,并为管理员提供高效的充电桩、用户及计费管理功能。支持通过 MQTT 协议与充电桩硬件(单片机)进行实时通信和控制。
|
||
|
||
### 核心功能
|
||
* **用户端**:
|
||
* 用户注册与登录
|
||
* 查看账户余额、充电记录
|
||
* 扫码/输入ID启动充电
|
||
* 停止充电
|
||
* 激活码兑换充值
|
||
* **管理端**:
|
||
* 用户管理(查询、添加、编辑、删除)
|
||
* 充电桩/车位管理(状态监控、添加、编辑、删除)
|
||
* 充电会话管理(查询、监控)
|
||
* 激活码管理(生成、查询、删除)
|
||
* MQTT通信日志查看(查询、审计所有MQTT消息)
|
||
* 系统概览与统计
|
||
* **硬件交互 (通过 MQTT)**:
|
||
* 充电桩状态上报 (空闲、连接中、充电中、故障等)
|
||
* 远程启动/停止充电指令下发
|
||
* 心跳维持
|
||
|
||
## 2. 技术栈
|
||
|
||
* **后端**: Spring Boot, Spring Security, MyBatis Plus, MySQL, Mosquitto (MQTT Broker), Spring AOP (用于日志)
|
||
* **前端**: Next.js, React, TypeScript, Ant Design, Axios
|
||
* **数据库**: MySQL
|
||
* **通信协议**: HTTP/HTTPS, MQTT
|
||
|
||
## 3. 项目部署与运行
|
||
|
||
### 3.1. 环境准备
|
||
* Java JDK 1.8 或更高版本
|
||
* Maven 3.x
|
||
* Node.js 16.x 或更高版本
|
||
* Yarn 或 npm
|
||
* MySQL 5.7 或更高版本
|
||
* MQTT Broker (例如 Mosquitto) 已安装并运行 (默认端口 1883)
|
||
|
||
### 3.2. 后端服务 (springboot-init-main)
|
||
1. **数据库配置**:
|
||
* 创建一个数据库 (例如 `charging_system_db`)。
|
||
* 修改 `springboot-init-main/src/main/resources/application.yml` (或对应环境的配置文件) 中的数据库连接信息:
|
||
```yaml
|
||
spring:
|
||
datasource:
|
||
url: jdbc:mysql://localhost:3306/your_database_name?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
|
||
username: your_db_username
|
||
password: your_db_password
|
||
```
|
||
2. **MQTT Broker 配置**:
|
||
* 确保 MQTT Broker 正在运行。
|
||
* 在 `application.yml` 中配置 MQTT 连接参数 (如果需要修改默认值或添加认证):
|
||
```yaml
|
||
mqtt:
|
||
broker-url: tcp://localhost:1883 # 替换为您的 MQTT Broker 地址
|
||
client-id-publisher: backend-publisher-default
|
||
client-id-subscriber: backend-subscriber-default
|
||
default-topic: "charging/default/topic" # 示例,具体业务主题见单片机对接部分
|
||
# username: your_mqtt_username # 如果 Broker 需要认证
|
||
# password: your_mqtt_password # 如果 Broker 需要认证
|
||
```
|
||
3. **启动后端服务**:
|
||
* 在 `springboot-init-main` 目录下,使用 Maven 运行:
|
||
```bash
|
||
mvn spring-boot:run
|
||
```
|
||
* 或者打包成 jar 文件后运行:
|
||
```bash
|
||
mvn clean package
|
||
java -jar target/springboot-init-main-0.0.1-SNAPSHOT.jar # 注意替换为实际生成的jar包名
|
||
```
|
||
* **配置文件外部化**: `application.yml` 在打包时已配置为外部化,并会复制到 `target/config/application.yml`。在生产环境部署时,可以将此文件放置于 JAR 包同级目录的 `config` 文件夹下 (例如: `your_app_dir/config/application.yml`),Spring Boot 将自动加载。或者,您也可以通过 `--spring.config.location` 启动参数来指定外部配置文件的具体路径,例如:`java -jar your_app.jar --spring.config.location=file:/path/to/your/external/application.yml`。
|
||
* 服务默认运行在 `http://localhost:7529` (或您在 `application.yml` 中配置的端口)。
|
||
|
||
### 3.3. 前端应用 (charging_web_app)
|
||
1. **安装依赖**:
|
||
在 `charging_web_app` 目录下运行:
|
||
```bash
|
||
yarn install
|
||
# 或者
|
||
# npm install
|
||
```
|
||
2. **API 代理配置**:
|
||
前端应用通过 Next.js 的代理将 `/api` 请求转发到后端服务。此配置在 `next.config.js` 中:
|
||
```javascript
|
||
// next.config.js (示例)
|
||
/** @type {import('next').NextConfig} */
|
||
const nextConfig = {
|
||
reactStrictMode: true,
|
||
async rewrites() {
|
||
return [
|
||
{
|
||
source: '/api/:path*',
|
||
destination: 'http://localhost:7529/api/:path*', // 后端服务地址
|
||
},
|
||
];
|
||
},
|
||
};
|
||
module.exports = nextConfig;
|
||
```
|
||
确保 `destination` 指向您后端服务的正确地址和端口。
|
||
3. **启动前端开发服务器**:
|
||
```bash
|
||
yarn dev
|
||
# 或者
|
||
# npm run dev
|
||
```
|
||
前端应用默认运行在 `http://localhost:3000`。
|
||
|
||
4. **构建生产版本**:
|
||
```bash
|
||
yarn build
|
||
yarn start
|
||
# 或者
|
||
# npm run build
|
||
# npm run start
|
||
```
|
||
|
||
## 4. 单片机 (充电桩硬件) 对接指南
|
||
|
||
智能充电桩硬件需通过 MQTT 协议与本系统的后端服务进行通信。
|
||
|
||
### 4.1. MQTT 连接配置
|
||
* **Broker 地址**: 单片机需配置连接到与后端服务相同的 MQTT Broker (例如 `tcp://your_mqtt_broker_address:1883`)。
|
||
* **Client ID**: 每个充电桩应使用唯一的 Client ID。建议使用充电桩的物理ID或序列号,例如 `charger_spot_001`。
|
||
* **认证**: 如果 MQTT Broker 配置了用户名/密码认证,单片机连接时也需提供。
|
||
|
||
### 4.2. MQTT 主题 (Topics) 约定
|
||
|
||
根据后端服务的实际MQTT通信实现,主题约定如下:
|
||
|
||
#### 4.2.1. 上行消息 (单片机 -> 后端)
|
||
|
||
所有类型的上行消息,包括设备状态更新、心跳以及对后端指令的执行回执 (ACK),都统一发送到以下主题:
|
||
|
||
* **统一上行主题格式**: `yupi_mqtt_power_project/robot/status/{spotUid}`
|
||
* `{spotUid}`: 充电桩/车位的唯一标识符 (例如 `ESP32_SPOT_001`,必须与后端系统中注册的设备ID一致)。
|
||
* **消息格式 (Payload)**: JSON。
|
||
消息体结构应与后端 `com.yupi.project.model.dto.mqtt.RobotStatusMessage` 类对应。通过消息体内的字段来区分具体的消息含义。
|
||
|
||
**示例 - 常规状态更新 (如移动中、充电中、空闲等) 或心跳包 (Heartbeat):**
|
||
```json
|
||
{
|
||
"robotUid": "ESP32_SPOT_001",
|
||
"actualRobotStatus": "CHARGING", // 设备当前状态, 如 IDLE, MOVING, CHARGING, COMPLETED, FAULTED
|
||
// 以下为可选的详细状态,根据实际需求和后端处理逻辑添加
|
||
"voltage": 220.5, // 充电时相关
|
||
"current": 5.1, // 充电时相关
|
||
"power": 1.12, // kW, 充电时相关
|
||
"energyConsumed": 0.5, // kWh, 本次充电已消耗电量
|
||
"errorCode": 0, // 0表示无错误,其他值表示特定错误类型
|
||
"activeTaskId": "session_xyz123" // 如果设备当前正在执行某个任务或会话,上报其ID
|
||
}
|
||
```
|
||
|
||
**示例 - 对后端指令的ACK (成功):**
|
||
```json
|
||
{
|
||
"robotUid": "ESP32_SPOT_001",
|
||
"taskId": "backend_task_789", // 对应后端指令中的taskId
|
||
"status": "SUCCESS", // 指令执行结果: SUCCESS 或 FAILURE
|
||
"message": "Command executed successfully",
|
||
"actualRobotStatus": "IDLE", // ACK发生时,设备的当前核心状态
|
||
"activeTaskId": "session_abc456" // 可选,如果ACK与特定会话相关
|
||
}
|
||
```
|
||
|
||
#### 4.2.2. 下行指令 (后端 -> 单片机)
|
||
|
||
后端服务向特定单片机下发指令时,使用以下主题格式。单片机应订阅其自身的这个专属指令主题。
|
||
|
||
* **统一下行指令主题格式**: `yupi_mqtt_power_project/robot/command/{spotUid}`
|
||
* `{spotUid}`: 目标充电桩的唯一标识符。
|
||
* **消息格式 (Payload)**: JSON。
|
||
JSON消息体内部包含了具体的指令类型和所需参数。
|
||
|
||
**示例 - 移动到车位指令 (MOVE_TO_SPOT):**
|
||
此指令指示机器人移动到指定车位。机器人到达后将自动进入充电状态。
|
||
```json
|
||
{
|
||
"commandType": "MOVE_TO_SPOT",
|
||
"taskId": "backend_task_id_for_ack_789", // 供单片机ACK时使用的任务ID
|
||
"target_spot_uid": "SPOT_UID_001" // 目标车位ID (单片机仅用于确认,主要由 spotUid 主题参数决定目标)
|
||
// "sessionId": "session_abc_123" // 可选,如果需要在payload中也传递会话ID
|
||
}
|
||
```
|
||
|
||
**示例 - 停止充电指令 (STOP_CHARGE):**
|
||
```json
|
||
{
|
||
"commandType": "STOP_CHARGE",
|
||
"taskId": "backend_task_id_for_ack_000",
|
||
"sessionId": "session_abc_123" // 关联的充电会话ID
|
||
}
|
||
```
|
||
* **单片机处理逻辑**: 单片机收到消息后,需解析JSON负载,识别 `commandType`,提取 `taskId` (用于后续ACK),并获取其他指令参数来执行相应操作。 对于 `MOVE_TO_SPOT`,到达后自动转换为 `CHARGING` 状态。
|
||
|
||
### 4.3. 单片机开发关键逻辑
|
||
1. **MQTT 初始化与重连机制**。
|
||
2. **订阅指令主题**。
|
||
3. **JSON 指令消息解析**。
|
||
4. **移动控制** (如果机器人需要物理移动)。
|
||
5. **充电启停控制** (继电器等硬件操作,停止充电时需要)。
|
||
6. **状态监测与实时上报**:
|
||
* 收到 `MOVE_TO_SPOT` 后,状态变为 `MOVING` 并上报。
|
||
* 到达目标车位后,状态变为 `CHARGING` 并上报,同时对 `MOVE_TO_SPOT` 指令进行ACK。
|
||
* 收到 `STOP_CHARGE` 后,停止充电,状态变为 `COMPLETED` (或 `IDLE`) 并上报,同时对 `STOP_CHARGE` 指令进行ACK。
|
||
7. **心跳包定时发送**。
|
||
8. **故障检测与上报**。
|
||
9. **安全性**: 确保 `spotUid` 唯一性;推荐 MQTT 通信使用 TLS/SSL 加密。
|
||
|
||
### 4.4. 示例流程:用户启动充电 (更新后)
|
||
1. 用户在前端 App 请求在车位 `SPOT001` 进行充电。
|
||
2. 后端服务验证,创建充电会话 `sessionId=789`,状态为 `REQUESTED`。
|
||
3. 后端分配机器人,创建 `MOVE_TO_SPOT` 任务 (例如 `taskId=task_move_123`),并将机器人DB状态更新为 `MOVING`,会话状态更新为 `ROBOT_ASSIGNED`。
|
||
4. 后端向 MQTT 主题 `yupi_mqtt_power_project/robot/command/SPOT001` 发布 `MOVE_TO_SPOT` 指令,payload 包含 `taskId=task_move_123`。
|
||
5. 单片机 `SPOT001` 接收指令:
|
||
a. 将其内部状态更新为 `MOVING`。
|
||
b. 向上行主题 `yupi_mqtt_power_project/robot/status/SPOT001` 上报状态 `MOVING`。
|
||
c. (模拟)执行移动。
|
||
d. 移动到达后,将其内部状态更新为 `CHARGING`。
|
||
e. 向上行主题发送 ACK 消息,确认 `taskId=task_move_123` 完成,消息中 `actualRobotStatus` 为 `CHARGING`。
|
||
f. (可选,或由ACK消息覆盖) 再次向上行主题上报状态 `CHARGING`,包含 `sessionId`。
|
||
6. 后端接收到 `MOVE_TO_SPOT` 任务 ( `taskId=task_move_123`) 的 ACK (其中机器人状态为 `CHARGING`):
|
||
a. 将 `RobotTask` ( `taskId=task_move_123`) 标记为 `COMPLETED`。
|
||
b. 将机器人 `SPOT001` 在数据库中的状态更新为 `CHARGING`。
|
||
c. 将充电会话 `sessionId=789` 的状态更新为 `CHARGING_STARTED`,并记录充电开始时间。
|
||
7. 前端界面同步更新,显示充电已开始。
|
||
|
||
## 5. 项目结构 (简要)
|
||
|
||
```
|
||
. 项目根目录
|
||
├── charging_web_app/ # 前端 Next.js 应用
|
||
│ ├── src/
|
||
│ ├── public/
|
||
│ └── package.json
|
||
├── springboot-init-main/ # 后端 Spring Boot 应用
|
||
│ ├── src/
|
||
│ │ ├── main/
|
||
│ │ │ ├── java/com/yupi/project/
|
||
│ │ │ └── resources/
|
||
│ │ └── test/
|
||
│ ├── doc/ # 项目文档 (如数据库DDL, 阶段计划等)
|
||
│ └── pom.xml
|
||
└── README.md # 本文件
|
||
```
|
||
|
||
## 6. 后续工作与展望
|
||
* 完善各模块的单元测试和集成测试。
|
||
* 进一步优化 API 文档和错误处理机制。
|
||
* 根据实际运营需求,增加更细致的统计报表功能。
|
||
* MQTT通信日志模块:
|
||
* (可选) 进一步优化Payload的展示,例如对JSON格式的Payload进行美化或提供折叠/展开功能。
|
||
* (可选) 根据实际需求,考虑日志数据的定期归档或清理策略的实现。
|
||
* 考虑引入更高级的 MQTT 特性,如QoS、遗嘱消息等。
|
||
* 前端 UI/UX 持续打磨,提升用户体验。 |