# 项目变更日志 - 第二阶段:MQTT 集成 ## 2023-12-02: 第二阶段启动 - MQTT 集成 - **状态**: 第一阶段开发已完成,相关日志已存档至 `LogBook_Phase1.md`。 - **当前任务**: 开始第二阶段开发,重点是 MQTT 的集成。 - **依据文档**: `springboot-init-main/doc/development_stages/stage_2_mqtt_integration.md`。 - **已完成**: 1. **数据库初始化**: 在 `mqtt_power` 数据库中成功创建了 `robot_task` 表。 2. **MQTT Broker 确定与配置**: - 确认使用公共 MQTT Broker: `broker.emqx.io:1883`。 - 更新 `springboot-init-main/src/main/resources/application.yml` 添加了 Broker 连接信息,并为 `client-id-prefix`、`command-topic-base`、`status-topic-base` 添加了项目唯一前缀 (如 `yupi_mqtt_power_project/`) 以确保在公共环境中的唯一性。 - 创建了 `springboot-init-main/src/main/java/com/yupi/project/config/properties/MqttProperties.java` 来映射 MQTT 配置。 3. **更新开发文档**: - 修改了 `springboot-init-main/doc/development_stages/stage_2_mqtt_integration.md`,反映了公共 Broker 的使用、Topic 唯一性策略以及应用层鉴权的重要性。 4. **实现 MQTT 客户端核心配置 (`MqttConfig.java`, `MqttCallbackHandler.java`, `MqttConnectionManager.java`)**: - 创建了 `com.yupi.project.mqtt.MqttCallbackHandler` 类,实现 `MqttCallbackExtended`接口,用于处理连接事件和初步的消息接收(日志记录)。在 `connectComplete` 中实现订阅状态主题 `yupi_mqtt_power_project/robot/status/+` 的逻辑。 - 创建了 `com.yupi.project.config.MqttConfig` 配置类,定义 `MqttConnectOptions` 和 `MqttClient` Beans。 - 创建了 `com.yupi.project.mqtt.MqttConnectionManager` 类,实现 `ApplicationListener` 和 `DisposableBean`,在应用启动完成后连接 MQTT,并在应用关闭前断开连接。解决了 MqttClient 初始化和连接时序问题。 5. **创建 `RobotTask` 管理基础结构**: - 在 `com.yupi.project.model.enums` 包下创建了 `CommandTypeEnum.java` 和 `TaskStatusEnum.java`。 - 在 `com.yupi.project.model.entity` 包下创建了 `RobotTask.java` 实体类,包含 MyBatis-Plus 注解。 - 在 `com.yupi.project.mapper` 包下创建了 `RobotTaskMapper.java` 接口。 - 在 `com.yupi.project.service` 包下创建了 `RobotTaskService.java` 接口,定义了任务管理的核心方法。 - 在 `com.yupi.project.service.impl` 包下创建了 `RobotTaskServiceImpl.java` 类,并为接口方法提供了最小化占位实现。 6. **详细实现 `RobotTaskServiceImpl` 中的核心业务方法**: - `createTask(String robotId, CommandTypeEnum commandType, String payloadJson, Long sessionId)`: 创建新的机器人任务,初始状态为 PENDING。 - `hasPendingOrSentTask(String robotId)`: 检查机器人是否有 PENDING 或 SENT 状态的任务。 - `markTaskAsSent(Long taskId, Date sentTime)`: 将任务状态从 PENDING 更新为 SENT,并记录发送时间。 - `findLatestSentTaskByRobotId(String robotId)`: 查找指定机器人最近一个 SENT 状态的任务。 - `markTaskAsAcknowledged(Long taskId, boolean success, String errorMessage, Date ackTime)`: 根据机器人响应更新任务状态为 ACKNOWLEDGED_SUCCESS 或 ACKNOWLEDGED_FAILURE,并记录确认时间和错误信息。 - `findAndMarkTimedOutTasks(int timeoutSeconds)`: 查找并标记已发送但超时的任务为 TIMED_OUT。 - **下一步计划 (依据 `stage_2_mqtt_integration.md`)**: 1. **实现消息发布 (`MqttService`)**: - 创建 `MqttService` 接口和 `MqttServiceImpl` 实现类。 - 实现 `sendCommand(...)` 方法,该方法会调用 `RobotTaskService.hasPendingOrSentTask` 进行检查,调用 `RobotTaskService.createTask` 创建任务,然后通过 `MqttClient` 发布指令,最后调用 `RobotTaskService.markTaskAsSent` 更新任务状态。 2. **实现消息处理 (`MqttMessageHandler`)**: - 创建 `MqttMessageHandler` 接口和 `MqttMessageHandlerImpl` 实现类 (之前 `MqttCallbackHandler` 中有占位,现在需要具体实现)。 - 实现 `handleStatusUpdate(String topic, String payload)` 方法,解析机器人状态,查找关联的 `RobotTask`,并调用 `RobotTaskService.markTaskAsAcknowledged` 更新任务。 - 根据机器人状态执行后续业务逻辑 (此阶段可留空或简单日志记录)。 3. **实现任务超时处理 (`TaskTimeoutHandler`)**: - 创建 `TaskTimeoutHandler` 类,使用 `@Scheduled` 定时调用 `RobotTaskService.findAndMarkTimedOutTasks`。 - (可选)根据超时任务更新关联的业务实体状态 (如 `ChargingRobot`, `ChargingSession`)。 - 更正了 `springboot-init-main/src/main/java/com/yupi/project/service/impl/MqttServiceImpl.java` 的实现,确保 `sendCommand` 方法的逻辑完整和正确。 - 实现 `TaskTimeoutHandler.java`,使用 `@Scheduled` 定时调用 `RobotTaskService.findAndMarkTimedOutTasks` 处理任务超时。 - 在 `MyApplication.java` 中添加 `@EnableScheduling` 以启用定时任务。 - 在 `application.yml` 中添加了 `mqtt.task.timeoutSeconds` 和 `mqtt.task.timeoutCheckRateMs` 配置项。 --- **第二阶段 (MQTT 集成) 已于 YYYY-MM-DD 完成。** 所有核心功能点,包括MQTT连接、消息发布/订阅、RobotTask状态跟踪和基础超时处理已实现。 依赖于 ChargingSession 的超时后联动处理已明确推至第三阶段。 --- ## YYYY-MM-DD (请替换为当前日期) - 第三阶段后端开发 - **核心业务实体与服务实现**: - 创建了枚举类: `RobotStatusEnum`, `ParkingSpotStatusEnum`, `ChargingSessionStatusEnum`, `PaymentStatusEnum`. - 创建了数据库实体: `ChargingRobot`, `ParkingSpot`, `ChargingSession`. - 创建了对应的Mapper接口: `ChargingRobotMapper`, `ParkingSpotMapper`, `ChargingSessionMapper`. - 创建了Service接口: `ChargingRobotService`, `ParkingSpotService`, `ChargingSessionService`. - 创建了Service实现类: `ChargingRobotServiceImpl`, `ParkingSpotServiceImpl`, `ChargingSessionServiceImpl`. - `ChargingSessionServiceImpl` 中实现了充电请求、机器人分配、状态流转 (到达、开始/结束充电)、费用计算、支付、取消、超时处理等核心逻辑。 - **API 控制器实现**: - 创建了 `ChargingRobotAdminController` 用于管理员管理充电机器人 (CRUD, 列表查询, 状态类型)。 - 创建了 `ParkingSpotAdminController` 用于管理员管理车位 (CRUD, 列表查询, 状态类型)。 - 创建了 `ChargingSessionController` 用于用户发起充电请求、查询历史会话、支付、取消会话。 - 创建了相关的DTOs (如 `ChargingRobotAddRequest`, `ParkingSpotQueryRequest`, `ChargingRequest`, `PaymentRequest`) 和 VO (`ChargingSessionVO`). - **MQTT与任务处理联动**: - 更新了 `MqttMessageHandlerImpl`,使其在收到机器人状态ACK后,能调用 `ChargingSessionService` 更新相关充电会话的状态。 - 更新了 `TaskTimeoutHandler`,使其在检测到与会话关联的任务超时后,能调用 `ChargingSessionService` 处理会话超时逻辑。 - 在 `ChargingSessionService` 中补充了 `getQueryWrapper` 方法用于支持分页和条件查询。 - **主要实现功能点**: - 管理员可以增删改查充电机器人和车位。 - 用户可以请求在特定车位充电。 - 系统能够尝试分配空闲机器人,并向其发送移动指令 (通过MQTT,并记录RobotTask)。 - 系统能够根据机器人通过MQTT反馈的状态(到达、开始充电、结束充电)更新充电会话的生命周期。 - 充电结束后,系统能计算费用,并允许用户支付。 - 用户可以在特定阶段取消充电会话。 - 机器人任务超时会影响关联的充电会话状态。 - **补充后端功能 (根据阶段计划调整)**: - 在 `ChargingSessionAdminController.java` 中添加了管理员分页查询所有充电会话的接口 (`POST /admin/session/list/page`)。 - 在 `ChargingSessionController.java` 中添加了用户"优雅停止充电"的接口 (`POST /session/stop`)。 - 此接口会向机器人发送 `STOP_CHARGE` 指令,并通过 `ChargingSessionServiceImpl.stopChargingByUser` 方法创建相应的 `RobotTask`。 - 会话的最终完成和计费依赖 `MqttMessageHandlerImpl` 收到机器人对 `STOP_CHARGE` 指令的成功ACK后,调用 `chargingSessionService.handleChargingEnd` 处理。 - **下一步**: - 进行详细的单元测试和集成测试。 - 完善错误处理、日志记录和边界条件。 - 更新API文档。 - **开始第三阶段前端开发**。 - 根据 `stage_3_core_charging_logic.md` 检查业务流程覆盖情况。 ## 后端开发 - 第三阶段核心充电逻辑完成 * **状态**: 后端核心业务逻辑、服务实现、MQTT集成及主要API Controller已完成开发并通过多轮编译错误修复。 * 充电全流程 (请求、分配、移动、到达、开始、结束、计费、支付、取消、超时) 已实现。 * 机器人和车位的状态管理服务已实现并集成到主流程。 * 用户余额扣减实现原子性操作。 * MQTT消息处理机制已建立,可处理任务ACK和常规状态上报。 * **决策**: 经过讨论,充电过程中的实时时长更新 (`currentChargingDurationSeconds`) 功能在本阶段不实现,最终计费依赖充电结束时上报的 `totalDurationSeconds`。 * **后续**: 后端已为前端开发提供基础。建议在前端大规模开发前,后端进行核心API的冒烟测试,并完善API文档(如使用Swagger)。