Files
railwaysystem/RuoYi-Vue/docs/mqtt_usage_and_status.md
T
buliping 1def568f24 refactor(iot): 移除 MQTT 传输层,仅保留设备开放接口与门禁写操作策略
- 依赖:删除根 pom 的 paho.version 与 org.eclipse.paho.client.mqttv3 依赖声明,
  同步移除 ruoyi-iot 模块中的 Paho 依赖,模块描述改为“iot设备数据与开放接口”
- MQTT 协议栈整体删除:IotMqttConfig、IotMqttProperties、MqttClientManager、
  MqttMessageDispatcher、MqttCallbackHandler、MqttConnectionCallback、
  IMqttMessageListener、MqttMessageDTO、MqttPublishRequest、MqttMessageEvent、
  IMqttService/MqttServiceImpl、IotMqttController,以及 lock 侧 topic 订阅与
  LockMessageListener、AccessRecordHandler、CommandRespHandler、
  GatewayOnlineHandler、LockSignalHandler
- MQTT 报文留痕链路删除:LockMqttLog 实体、LockMqttLogMapper(+XML)、
  ILockMqttLogService/LockMqttLogServiceImpl、LockMqttLogController,
  以及对应的前端页面 build_ui/src/views/iot/mqttlog 与 API build_ui/src/api/iot/mqttlog.js
- 命令下发改为仅落库:LockCommandServiceImpl 派发时直接置 TRANSPORT_DISABLED 失败,
  retryPending 返回 0;删除 GatewayOfflineCheckTask、LockCommandRetryTask、
  LockDeviceOfflineCheckTask 等依赖 MQTT 的补偿与离线检查定时任务
- 保留与传输无关的门禁写操作策略:新增 IotLockSecurityProperties(iot.lock-security),
  RealIotSecurityGate 及其测试改用该配置类
- 配置与调用处清理:application*.yml 中 iot.mqtt 段迁移为 iot.lock-security,
  删除 broker-url/client-id/username/password/topics/will/qos 等连接参数,
  修正 iot.face 环境标识注释引用;QA 工具启动参数改用 --iot.lock-security.*,
  并移除 browser_regression.js 的 mqttlog 路由
- 测试同步:删除依赖 MQTT 与传输层的 CommandRespHandlerMockTest、
  Round5sEgressIsolationTest、Round5sExecutionIntegrationTest、
  Round5v4BrowserFixture、Round5v4KingbaseIntegrationTest;
  更新 RealIotSecurityGateTest、FaceExtractClientMockTest、
  TrainIotLockAuthBridgeMockTest

说明:数据库侧 lock_mqtt_log 表结构与历史验收文档保留,未做数据迁移;
前端若仍配置了“MQTT报文日志”菜单,需在后台菜单管理中一并移除。
2026-11-10 16:06:23 +08:00

11 KiB
Raw Blame History

MQTT 使用情况与生效状态分析

分析对象:RuoYi-Vue(railwaysystem)全部模块 分析时间:2026-11-10 分析方式:源码静态梳理 + 运行时探测(进程、端口、Broker 连通性、日志),未修改任何代码


目录


1. 结论摘要

维度 结论
配置状态 已启用:enabled=true、mock=false、protocol-verified=true、real-device-write-enabled=true
运行状态 当前未生效(连接断开):应用进程对 Broker 处于 SYN_SENT,健康检查每约 30s 重连并持续失败
消息收发 上行不可用(未订阅,收不到任何上行报文);下行不可用(命令派发前即判失败)
代码可用性 链路完好:2026-11-09 日志中 27 次连接成功,并有真实上行报文处理记录
根因定位 环境问题,非代码缺陷:配置的 Broker 192.168.1.202:1883 网络不可达;本机 127.0.0.1:1883 实际运行着 mosquitto,但配置未指向

一句话结论:MQTT 代码与配置都已就绪,但当前连不上配置的 Broker,所有门禁上下行功能处于停摆状态。


2. MQTT 功能清单

2.1 连接与消息通道

# 功能点 说明 关键代码
1 客户端建立与重连 启动异步连接;失败后由 iot-mqtt-health 线程每 30s 兜底重连 MqttClientManager#connect / startHealthExecutor
2 启动自动订阅 5 个上行主题,QoS 1;重连后 resubscribe() 恢复订阅 MqttClientManager#resubscribe
3 消息分发 按主题分发至业务监听器,并发布 MqttMessageEvent;单监听器异常隔离 MqttMessageDispatcher#dispatch
4 报文留痕 收/发报文写入 lock_mqtt_log,payload 脱敏为 [redacted] LockMqttLogServiceImpl

2.2 上行:设备 → 平台(5 个订阅主题)

# 功能点 主题 处理结果
5 网关上下线 ydlink/+/thing/onoff_line 更新网关在线状态
6 属性设置响应 ydlink/+/thing/property/set_response 命令状态机推进
7 远程开关锁响应 ydlink/+/thing/action/execute_response 命令状态机推进
8 授权批量下发回执 ydlink/+/thing/data/batch_report 授权命令确认 / 拒绝
9 开门记录上报 ydlink/+/thing/event/trigger 写入开门记录
10 信号/电量上报 ydlink/+/thing/event/trigger(op=RSSI) 更新设备信号值

2.3 下行:平台 → 设备

# 功能点 触发入口 说明
11 门锁授权下发 / 撤销 学员入住、退宿、换宿 事务提交后派发(outbox 模式)
12 远程开锁 / 关锁 管理端门锁操作 同上
13 网关属性设置(校时、网络参数) 管理端网关管理 同上
14 命令补偿重发 LockCommandRetryTask(每 60s) retry-task-enabled=false,当前不执行
15 派发安全门禁 RealIotSecurityGate 环境隔离、SN 白名单、协议审批、真实写入总开关;不通过则 POLICY_BLOCKED_NOT_ATTEMPTED

2.4 运维与辅助

# 功能点 说明
16 `/iot/mqtt/status publish
17 /qa/mock/** 模拟接口 同上,当前不可用
18 网关离线判定 GatewayOfflineCheckTask、LockDeviceOfflineCheckTask(定时任务,遗嘱消息已关闭)

不属于 MQTT 的部分:报到机人脸上传后的"门锁入住"走 HTTP 开放平台(TrainLockStayApiClient#callStayCheckin),不受本次断连影响。


3. 相关代码文件清单

3.1 连接核心与配置(ruoyi-iot)

com/ruoyi/iot/config/IotMqttProperties.java
com/ruoyi/iot/config/IotMqttConfig.java
com/ruoyi/iot/core/MqttClientManager.java
com/ruoyi/iot/core/MqttCallbackHandler.java
com/ruoyi/iot/core/MqttConnectionCallback.java
com/ruoyi/iot/core/MqttMessageDispatcher.java
com/ruoyi/iot/core/IMqttMessageListener.java
com/ruoyi/iot/domain/MqttMessageDTO.java
com/ruoyi/iot/domain/MqttPublishRequest.java
com/ruoyi/iot/event/MqttMessageEvent.java
com/ruoyi/iot/service/IMqttService.java
com/ruoyi/iot/service/impl/MqttServiceImpl.java
com/ruoyi/iot/controller/IotMqttController.java

3.2 门禁协议与消息处理

com/ruoyi/iot/lock/mqtt/LockTopicSubscriber.java
com/ruoyi/iot/lock/mqtt/LockMessageListener.java
com/ruoyi/iot/lock/mqtt/handler/GatewayOnlineHandler.java
com/ruoyi/iot/lock/mqtt/handler/CommandRespHandler.java
com/ruoyi/iot/lock/mqtt/handler/AccessRecordHandler.java
com/ruoyi/iot/lock/mqtt/handler/LockSignalHandler.java
com/ruoyi/iot/lock/protocol/YdlinkCodec.java
com/ruoyi/iot/lock/protocol/YdlinkFrameDTO.java
com/ruoyi/iot/lock/protocol/YdlinkOp.java
com/ruoyi/iot/lock/protocol/YdlinkTopicBuilder.java
com/ruoyi/iot/lock/protocol/YdlinkTopicDTO.java
com/ruoyi/iot/lock/protocol/YdlinkTopicType.java

3.3 门禁业务

com/ruoyi/iot/lock/security/RealIotSecurityGate.java
com/ruoyi/iot/lock/service/impl/LockCommandServiceImpl.java
com/ruoyi/iot/lock/service/impl/LockAuthServiceImpl.java
com/ruoyi/iot/lock/service/impl/LockDeviceServiceImpl.java
com/ruoyi/iot/lock/service/impl/LockGatewayServiceImpl.java
com/ruoyi/iot/lock/service/impl/LockMqttLogServiceImpl.java
com/ruoyi/iot/lock/service/ILockMqttLogService.java
com/ruoyi/iot/lock/domain/LockMqttLog.java
com/ruoyi/iot/lock/mapper/LockMqttLogMapper.java
com/ruoyi/iot/lock/controller/LockMqttLogController.java
com/ruoyi/iot/lock/task/LockCommandRetryTask.java
com/ruoyi/iot/lock/task/GatewayOfflineCheckTask.java
com/ruoyi/iot/lock/task/LockDeviceOfflineCheckTask.java

3.4 业务桥接(ruoyi-train)

com/ruoyi/train/integration/lock/service/impl/TrainIotLockAuthBridgeServiceImpl.java
com/ruoyi/train/integration/lock/service/ITrainLockAuthBridgeService.java
com/ruoyi/train/integration/lock/dto/LockAuthBridgeResult.java

同目录 client/TrainLockStayApiClient.java、dto/LockStayCheckinResult.java 为 HTTP 门锁开放平台调用,不走 MQTT。

3.5 QA 与测试

ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/QaMockMqttApiController.java
ruoyi-iot/src/test/java/...(MqttClientManagerTest、MqttMessageDispatcherTest、LockMessageListenerTest 等)

3.6 配置文件

ruoyi-admin/src/main/resources/application.yml              # iot.mqtt.*(195-259 行,当前生效)
ruoyi-admin/src/main/resources/application_localhost.yml     # broker 指向 202/24
ruoyi-admin/src/main/resources/application_localhost_24.yml
ruoyi-admin/src/main/resources/application_localhost_230.yml

激活 profile 为 druid,其 application-druid.yml 无 iot.mqtt 覆盖项,最终以 application.yml 为准。


4. 生效状态分析

4.1 配置层

mqtt:
  enabled: true                  # 创建连接
  mock: false                    # 真实收发
  protocol-verified: true        # 允许真实下发
  real-device-write-enabled: true
  environment-id: railway-iot-01
  retry-task-enabled: false      # 补偿任务关闭
  broker-url: tcp://192.168.1.202:1883
  username: admin3
  password: admin3
  automatic-reconnect: true
  health-check-interval: 30000
  topics: 5 个上行主题(QoS 1)

4.2 运行时证据

检查项 结果 含义
应用进程 java.exe PID 26688 监听 0.0.0.0:8096 应用正在运行
MQTT socket 对 192.168.1.202:1883 处于 SYN_SENT TCP 连接未建立,正在重试
Broker 连通性 Test-NetConnection 192.168.1.202:1883 → TCP 失败、Ping 超时 Broker 不可达
本机 1883 127.0.0.1:1883 由 mosquitto.exe(PID 6032)监听 本地有可用 Broker,配置未指向

4.3 日志证据

日志 证据
logs/sys-error.log [iot-mqtt-health] ERROR MqttClientManager - MQTT 连接失败, broker=tcp://192.168.1.202:1883,累计 448 次,间隔约 30s;今日 13:52:50 仍有新记录
logs/sys-info.2026-11-09.log MQTT 连接成功 27 次;含真实上行处理(网关状态更新、开门记录落库)
logs/sys-info.log(今日) 无任何 MQTT 行 —— 今日连接从未成功,失败仅写 error 日志

4.4 断连时的代码行为

// LockCommandServiceImpl#dispatch
if (!mqttService.isConnected()) {
    log.warn("[TRACE-DISPATCH] cid={} isConnected=false -> TRANSPORT_DISCONNECTED", commandId);
    command.setCommandStatus(LockConstants.STATUS_FAIL);
    command.setErrorMsg("TRANSPORT_DISCONNECTED_NOT_ATTEMPTED");
    commandMapper.updateCommand(command);
    return null;
}

断连时命令在发送前即被标记失败,不会进入 AWAITING_ACK,因此不存在"平台显示已下发、设备未收到"的假成功。

4.5 功能可用性对照

功能 状态 依据
MQTT 连接 ❌ 未连接 SYN_SENT + 448 次失败日志 + Broker 不可达
上行 5 个主题 ❌ 无订阅 订阅在 connect() 成功后执行,当前未连接
网关状态 / 开门记录 / 回执处理 ❌ 停止 依赖上行报文
授权下发 / 远程开关锁 / 网关设置 ❌ 直接失败 isConnected=false → STATUS_FAIL
命令补偿重发 ❌ 不执行 retry-task-enabled=false
/iot/mqtt/status、/qa/mock/** ❌ 未加载 @ConditionalOnProperty 条件不满足,无法用接口自证状态
报到机人脸采集与门锁入住(HTTP) ✅ 正常 走 HTTP 开放平台,与 MQTT 无关

5. 判断依据与恢复方向

5.1 判断依据

  1. 配置齐备:开关、Mock、协议审批、真实写入、白名单均已就位 → 具备生效条件。
  2. 运行证据否证:应用存活但 TCP 未连通,健康检查持续失败 → 连接未建立。
  3. 产物证据缺失:无订阅即无上行;命令侧有明确的失败状态码 → 收发均不可用。
  4. 历史反证代码无缺陷:曾出现 27 次连接成功与真实报文处理 → 问题在环境与配置指向,而非实现。

5.2 恢复方向(无需改代码)

  1. 排查 192.168.1.202:1883:主机连通性、防火墙、Broker 进程、网段隔离;
  2. 若现场已有本机 Broker,将 iot.mqtt.broker-url 改为 tcp://127.0.0.1:1883,并核对 username/password;
  3. 恢复后按序验证:
    • 日志出现 MQTT 连接成功
    • 5 个主题订阅成功
    • 收到网关 onoff_line 上行
    • 对白名单内 SN 下发一次授权,确认回执进入 CONFIRMED
  4. 如需离线补偿能力,再评估开启 retry-task-enabled=true(会周期性重发至真实设备,属生产变更,需审批)。

文档结束。如需补充时序图或按模块拆分,可在此基础上扩展。