Files
mqtt_power/README.md

261 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 智能充电桩管理系统 (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 持续打磨,提升用户体验。