9.7 KiB
9.7 KiB
项目变更日志 - 第二阶段:MQTT 集成
2023-12-02: 第二阶段启动 - MQTT 集成
-
状态: 第一阶段开发已完成,相关日志已存档至
LogBook_Phase1.md。 -
当前任务: 开始第二阶段开发,重点是 MQTT 的集成。
-
依据文档:
springboot-init-main/doc/development_stages/stage_2_mqtt_integration.md。 -
已完成:
- 数据库初始化: 在
mqtt_power数据库中成功创建了robot_task表。 - 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 配置。
- 确认使用公共 MQTT Broker:
- 更新开发文档:
- 修改了
springboot-init-main/doc/development_stages/stage_2_mqtt_integration.md,反映了公共 Broker 的使用、Topic 唯一性策略以及应用层鉴权的重要性。
- 修改了
- 实现 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和MqttClientBeans。 - 创建了
com.yupi.project.mqtt.MqttConnectionManager类,实现ApplicationListener<ContextRefreshedEvent>和DisposableBean,在应用启动完成后连接 MQTT,并在应用关闭前断开连接。解决了 MqttClient 初始化和连接时序问题。
- 创建了
- 创建
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类,并为接口方法提供了最小化占位实现。
- 在
- 详细实现
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):- 实现消息发布 (
MqttService):- 创建
MqttService接口和MqttServiceImpl实现类。 - 实现
sendCommand(...)方法,该方法会调用RobotTaskService.hasPendingOrSentTask进行检查,调用RobotTaskService.createTask创建任务,然后通过MqttClient发布指令,最后调用RobotTaskService.markTaskAsSent更新任务状态。
- 创建
- 实现消息处理 (
MqttMessageHandler):- 创建
MqttMessageHandler接口和MqttMessageHandlerImpl实现类 (之前MqttCallbackHandler中有占位,现在需要具体实现)。 - 实现
handleStatusUpdate(String topic, String payload)方法,解析机器人状态,查找关联的RobotTask,并调用RobotTaskService.markTaskAsAcknowledged更新任务。 - 根据机器人状态执行后续业务逻辑 (此阶段可留空或简单日志记录)。
- 创建
- 实现任务超时处理 (
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)。