Commit 7b10b5954164a70ac9a8eb036aaa686b1ded48bf

Authored by haohao
1 parent a4e80d45

feat:【IoT 物联网】优化 MQTT 配置属性,新增 MQTT 消息处理抽象基类

yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/config/IotGatewayProperties.java
... ... @@ -103,39 +103,65 @@ public class IotGatewayProperties {
103 103 */
104 104 @NotNull(message = "是否开启不能为空")
105 105 private Boolean enabled;
  106 +
106 107 /**
107   - * HTTP 认证端口
  108 + * HTTP 认证端口(默认:8090)
108 109 */
109 110 private Integer httpAuthPort = 8090;
  111 +
110 112 /**
111 113 * MQTT 服务器地址
112 114 */
  115 + @NotEmpty(message = "MQTT 服务器地址不能为空")
113 116 private String mqttHost;
  117 +
114 118 /**
115   - * MQTT 服务器端口
  119 + * MQTT 服务器端口(默认:1883)
116 120 */
117   - private Integer mqttPort;
  121 + @NotNull(message = "MQTT 服务器端口不能为空")
  122 + private Integer mqttPort = 1883;
  123 +
118 124 /**
119 125 * MQTT 用户名
120 126 */
  127 + @NotEmpty(message = "MQTT 用户名不能为空")
121 128 private String mqttUsername;
  129 +
122 130 /**
123 131 * MQTT 密码
124 132 */
  133 + @NotEmpty(message = "MQTT 密码不能为空")
125 134 private String mqttPassword;
  135 +
126 136 /**
127   - * MQTT 是否开启 SSL
  137 + * MQTT 是否开启 SSL(默认:false)
128 138 */
129   - private Boolean mqttSsl;
  139 + @NotNull(message = "MQTT 是否开启 SSL 不能为空")
  140 + private Boolean mqttSsl = false;
  141 +
130 142 /**
131   - * MQTT客户端 ID
  143 + * MQTT 客户端 ID(如果为空,系统将自动生成)
132 144 */
133 145 private String mqttClientId;
  146 +
134 147 /**
135   - * MQTT 主题
  148 + * MQTT 主题列表
136 149 */
  150 + @NotEmpty(message = "MQTT 主题不能为空")
137 151 private List<String> mqttTopics;
138 152  
  153 + /**
  154 + * 获取 MQTT 客户端 ID,如果未配置则自动生成
  155 + *
  156 + * @return MQTT 客户端 ID
  157 + */
  158 + public String getMqttClientId() {
  159 + if (cn.hutool.core.util.StrUtil.isBlank(mqttClientId)) {
  160 + mqttClientId = "iot-gateway-mqtt-" + System.currentTimeMillis();
  161 + }
  162 + return mqttClientId;
  163 + }
  164 +
139 165 }
140 166  
141 167 }
... ...
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/mqtt/IotMqttDownstreamSubscriber.java
... ... @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.gateway.protocol.mqtt;
3 3 import cn.hutool.core.util.StrUtil;
4 4 import cn.hutool.json.JSONObject;
5 5 import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceRespDTO;
  6 +import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum;
6 7 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
7 8 import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber;
8 9 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
... ... @@ -47,19 +48,28 @@ public class IotMqttDownstreamSubscriber implements IotMessageSubscriber&lt;IotDevi
47 48  
48 49 @Override
49 50 public void onMessage(IotDeviceMessage message) {
50   - log.info("[onMessage][接收到下行消息:{}]", message);
  51 + log.info("[onMessage][接收到下行消息][messageId: {}][method: {}][deviceId: {}]",
  52 + message.getId(), message.getMethod(), message.getDeviceId());
51 53 try {
52 54 // 根据消息方法处理不同的下行消息
53 55 String method = message.getMethod();
54 56 if (method == null) {
55   - log.warn("[onMessage][消息({})方法为空]", message);
  57 + log.warn("[onMessage][消息方法为空][messageId: {}][deviceId: {}]",
  58 + message.getId(), message.getDeviceId());
  59 + return;
  60 + }
  61 +
  62 + // 过滤上行消息:下行订阅者只处理下行消息
  63 + if (isUpstreamMessage(method)) {
  64 + log.debug("[onMessage][忽略上行消息][method: {}][messageId: {}]", method, message.getId());
56 65 return;
57 66 }
58 67  
59 68 // 处理下行消息
60 69 handleDownstreamMessage(message);
61 70 } catch (Exception e) {
62   - log.error("[onMessage][处理下行消息失败:{}]", message, e);
  71 + log.error("[onMessage][处理下行消息失败][messageId: {}][method: {}][deviceId: {}]",
  72 + message.getId(), message.getMethod(), message.getDeviceId(), e);
63 73 }
64 74 }
65 75  
... ... @@ -155,4 +165,15 @@ public class IotMqttDownstreamSubscriber implements IotMessageSubscriber&lt;IotDevi
155 165 return payload;
156 166 }
157 167  
  168 + /**
  169 + * 判断是否为上行消息
  170 + *
  171 + * @param method 消息方法
  172 + * @return 是否为上行消息
  173 + */
  174 + private boolean isUpstreamMessage(String method) {
  175 + IotDeviceMessageMethodEnum methodEnum = IotDeviceMessageMethodEnum.of(method);
  176 + return methodEnum != null && methodEnum.getUpstream();
  177 + }
  178 +
158 179 }
159 180 \ No newline at end of file
... ...
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/mqtt/IotMqttUpstreamProtocol.java
... ... @@ -37,10 +37,20 @@ import java.util.concurrent.TimeUnit;
37 37 public class IotMqttUpstreamProtocol {
38 38  
39 39 /**
40   - * 默认 QoS 级别
  40 + * 默认 QoS 级别 - 至少一次
41 41 */
42 42 private static final MqttQoS DEFAULT_QOS = MqttQoS.AT_LEAST_ONCE;
43 43  
  44 + /**
  45 + * 连接超时时间(秒)
  46 + */
  47 + private static final int CONNECT_TIMEOUT_SECONDS = 10;
  48 +
  49 + /**
  50 + * 重连延迟时间(毫秒)
  51 + */
  52 + private static final long RECONNECT_DELAY_MS = 5000;
  53 +
44 54 private final IotGatewayProperties.EmqxProperties emqxProperties;
45 55  
46 56 // 共享资源
... ... @@ -227,25 +237,26 @@ public class IotMqttUpstreamProtocol {
227 237 * 连接 MQTT Broker 并订阅主题
228 238 */
229 239 private void connectMqtt() {
  240 + // 参数校验
230 241 String host = emqxProperties.getMqttHost();
231 242 Integer port = emqxProperties.getMqttPort();
232 243  
233 244 if (StrUtil.isBlank(host)) {
234   - String msg = "[connectMqtt][MQTT Host 为空,无法连接]";
235   - log.error(msg);
236   - return;
  245 + log.error("[connectMqtt][MQTT Host 为空,无法连接]");
  246 + throw new IllegalArgumentException("MQTT Host 不能为空");
237 247 }
238   - if (port == null) {
239   - log.warn("[connectMqtt][MQTT Port 为 null,使用默认端口 1883]");
240   - port = 1883;
  248 + if (port == null || port <= 0) {
  249 + log.error("[connectMqtt][MQTT Port 无效:{}]", port);
  250 + throw new IllegalArgumentException("MQTT Port 必须为正整数");
241 251 }
242 252  
243   - final Integer finalPort = port;
244   - CompletableFuture<Void> connectFuture = mqttClient.connect(finalPort, host)
  253 + log.info("[connectMqtt][开始连接 MQTT Broker][host: {}][port: {}]", host, port);
  254 +
  255 + CompletableFuture<Void> connectFuture = mqttClient.connect(port, host)
245 256 .toCompletionStage()
246 257 .toCompletableFuture()
247 258 .thenAccept(connAck -> {
248   - log.info("[connectMqtt][MQTT 客户端连接成功]");
  259 + log.info("[connectMqtt][MQTT 客户端连接成功][host: {}][port: {}]", host, port);
249 260 // 设置断开重连监听器
250 261 mqttClient.closeHandler(closeEvent -> {
251 262 log.warn("[closeHandler][MQTT 连接已断开,准备重连]");
... ... @@ -257,17 +268,19 @@ public class IotMqttUpstreamProtocol {
257 268 subscribeToTopics();
258 269 })
259 270 .exceptionally(error -> {
260   - log.error("[connectMqtt][连接 MQTT Broker 失败]", error);
  271 + log.error("[connectMqtt][连接 MQTT Broker 失败][host: {}][port: {}]", host, port, error);
  272 + // 连接失败时也要尝试重连
261 273 reconnectWithDelay();
262 274 return null;
263 275 });
264 276  
265 277 // 等待连接完成
266 278 try {
267   - connectFuture.get(10, TimeUnit.SECONDS);
  279 + connectFuture.get(CONNECT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
268 280 log.info("[connectMqtt][MQTT 客户端启动完成]");
269 281 } catch (Exception e) {
270 282 log.error("[connectMqtt][MQTT 客户端启动失败]", e);
  283 + throw new RuntimeException("MQTT 客户端启动失败", e);
271 284 }
272 285 }
273 286  
... ... @@ -284,15 +297,19 @@ public class IotMqttUpstreamProtocol {
284 297 */
285 298 private void subscribeToTopics() {
286 299 List<String> topicList = emqxProperties.getMqttTopics();
287   - if (CollUtil.isEmpty(topicList)) {
288   - log.warn("[subscribeToTopics][没有配置要订阅的主题]");
289   - return;
290   - }
  300 + // @NotEmpty 注解已保证 topicList 不为空,无需重复校验
  301 +
  302 + log.info("[subscribeToTopics][开始订阅主题,共 {} 个]", topicList.size());
291 303  
292 304 for (String topic : topicList) {
  305 + if (StrUtil.isBlank(topic)) {
  306 + log.warn("[subscribeToTopics][跳过空主题]");
  307 + continue;
  308 + }
  309 +
293 310 mqttClient.subscribe(topic, DEFAULT_QOS.value(), subscribeResult -> {
294 311 if (subscribeResult.succeeded()) {
295   - log.info("[subscribeToTopics][订阅主题成功: {}]", topic);
  312 + log.info("[subscribeToTopics][订阅主题成功: {}][QoS: {}]", topic, DEFAULT_QOS.value());
296 313 } else {
297 314 log.error("[subscribeToTopics][订阅主题失败: {}]", topic, subscribeResult.cause());
298 315 }
... ... @@ -304,10 +321,16 @@ public class IotMqttUpstreamProtocol {
304 321 * 延迟重连
305 322 */
306 323 private void reconnectWithDelay() {
307   - vertx.setTimer(5000, timerId -> {
  324 + vertx.setTimer(RECONNECT_DELAY_MS, timerId -> {
308 325 if (isRunning && (mqttClient == null || !mqttClient.isConnected())) {
309   - log.info("[reconnectWithDelay][开始重连 MQTT Broker]");
310   - connectMqtt();
  326 + log.info("[reconnectWithDelay][开始重连 MQTT Broker,延迟 {} 毫秒]", RECONNECT_DELAY_MS);
  327 + try {
  328 + connectMqtt();
  329 + } catch (Exception e) {
  330 + log.error("[reconnectWithDelay][重连失败,将继续尝试重连]", e);
  331 + // 重连失败时继续尝试重连
  332 + reconnectWithDelay();
  333 + }
311 334 }
312 335 });
313 336 }
... ...
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/mqtt/router/IotMqttAbstractHandler.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.gateway.protocol.mqtt.router;
  2 +
  3 +import cn.hutool.core.util.StrUtil;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +
  6 +/**
  7 + * IoT 网关 MQTT 协议的处理器抽象基类
  8 + * <p>
  9 + * 提供通用的异常处理、参数校验等功能
  10 + *
  11 + * @author 芋道源码
  12 + */
  13 +@Slf4j
  14 +public abstract class IotMqttAbstractHandler {
  15 +
  16 + /**
  17 + * 处理 MQTT 消息的模板方法
  18 + *
  19 + * @param topic 主题
  20 + * @param payload 消息内容
  21 + */
  22 + public final void handle(String topic, String payload) {
  23 + try {
  24 + // 1. 前置校验
  25 + if (!validateInput(topic, payload)) {
  26 + return;
  27 + }
  28 +
  29 + // 2. 执行具体逻辑
  30 + doHandle(topic, payload);
  31 +
  32 + } catch (Exception e) {
  33 + log.error("[handle][处理 MQTT 消息失败][topic: {}][payload: {}]", topic, payload, e);
  34 + handleException(topic, payload, e);
  35 + }
  36 + }
  37 +
  38 + /**
  39 + * 具体的处理逻辑,由子类实现
  40 + *
  41 + * @param topic 主题
  42 + * @param payload 消息内容
  43 + */
  44 + protected abstract void doHandle(String topic, String payload);
  45 +
  46 + /**
  47 + * 输入参数校验
  48 + *
  49 + * @param topic 主题
  50 + * @param payload 消息内容
  51 + * @return 校验是否通过
  52 + */
  53 + protected boolean validateInput(String topic, String payload) {
  54 + if (StrUtil.isBlank(topic)) {
  55 + log.warn("[validateInput][主题为空,忽略消息]");
  56 + return false;
  57 + }
  58 +
  59 + if (StrUtil.isBlank(payload)) {
  60 + log.warn("[validateInput][消息内容为空][topic: {}]", topic);
  61 + return false;
  62 + }
  63 +
  64 + return true;
  65 + }
  66 +
  67 + /**
  68 + * 异常处理
  69 + *
  70 + * @param topic 主题
  71 + * @param payload 消息内容
  72 + * @param e 异常
  73 + */
  74 + protected void handleException(String topic, String payload, Exception e) {
  75 + // 默认实现:记录错误日志
  76 + // 子类可以重写此方法,添加特定的异常处理逻辑
  77 + log.error("[handleException][MQTT 消息处理异常][topic: {}]", topic, e);
  78 + }
  79 +
  80 + /**
  81 + * 解析主题,获取主题各部分
  82 + *
  83 + * @param topic 主题
  84 + * @return 主题各部分数组,如果解析失败返回 null
  85 + */
  86 + protected String[] parseTopic(String topic) {
  87 + String[] topicParts = topic.split("/");
  88 + if (topicParts.length < 7) {
  89 + log.warn("[parseTopic][主题格式不正确][topic: {}]", topic);
  90 + return null;
  91 + }
  92 + return topicParts;
  93 + }
  94 +}
0 95 \ No newline at end of file
... ...
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/mqtt/router/IotMqttHttpAuthHandler.java
... ... @@ -13,10 +13,12 @@ import io.vertx.core.json.JsonObject;
13 13 import io.vertx.ext.web.RoutingContext;
14 14 import lombok.extern.slf4j.Slf4j;
15 15  
  16 +import static cn.iocoder.yudao.module.iot.gateway.enums.ErrorCodeConstants.DEVICE_AUTH_FAIL;
  17 +
16 18 /**
17 19 * IoT 网关 MQTT HTTP 认证处理器
18 20 * <p>
19   - * 处理 EMQX 的认证请求和事件钩子
  21 + * 处理 EMQX 的认证请求和事件钩子,提供统一的错误处理和参数校验
20 22 *
21 23 * @author 芋道源码
22 24 */
... ... @@ -24,6 +26,26 @@ import lombok.extern.slf4j.Slf4j;
24 26 public class IotMqttHttpAuthHandler {
25 27  
26 28 /**
  29 + * 认证成功状态码
  30 + */
  31 + private static final int SUCCESS_STATUS_CODE = 200;
  32 +
  33 + /**
  34 + * 参数错误状态码
  35 + */
  36 + private static final int BAD_REQUEST_STATUS_CODE = 400;
  37 +
  38 + /**
  39 + * 认证失败状态码
  40 + */
  41 + private static final int UNAUTHORIZED_STATUS_CODE = 401;
  42 +
  43 + /**
  44 + * 服务器错误状态码
  45 + */
  46 + private static final int INTERNAL_ERROR_STATUS_CODE = 500;
  47 +
  48 + /**
27 49 * EMQX 认证接口
28 50 */
29 51 public void authenticate(RoutingContext context) {
... ... @@ -44,7 +66,7 @@ public class IotMqttHttpAuthHandler {
44 66 // 参数校验
45 67 if (StrUtil.isEmpty(clientid) || StrUtil.isEmpty(username) || StrUtil.isEmpty(password)) {
46 68 log.warn("[authenticate][认证参数不完整][clientId: {}][username: {}]", clientid, username);
47   - sendErrorResponse(context, 400, "认证参数不完整");
  69 + sendErrorResponse(context, BAD_REQUEST_STATUS_CODE, "认证参数不完整");
48 70 return;
49 71 }
50 72  
... ... @@ -58,7 +80,7 @@ public class IotMqttHttpAuthHandler {
58 80 result.checkError();
59 81 if (!BooleanUtil.isTrue(result.getData())) {
60 82 log.warn("[authenticate][设备认证失败][clientId: {}][username: {}]", clientid, username);
61   - sendErrorResponse(context, 401, "设备认证失败");
  83 + sendErrorResponse(context, UNAUTHORIZED_STATUS_CODE, DEVICE_AUTH_FAIL.getMsg());
62 84 return;
63 85 }
64 86  
... ... @@ -67,7 +89,7 @@ public class IotMqttHttpAuthHandler {
67 89  
68 90 } catch (Exception e) {
69 91 log.error("[authenticate][设备认证异常]", e);
70   - sendErrorResponse(context, 500, "认证服务异常");
  92 + sendErrorResponse(context, INTERNAL_ERROR_STATUS_CODE, "认证服务异常");
71 93 }
72 94 }
73 95  
... ... @@ -79,7 +101,7 @@ public class IotMqttHttpAuthHandler {
79 101 // 解析请求体
80 102 JsonObject body = context.body().asJsonObject();
81 103 if (body == null) {
82   - sendErrorResponse(context, 400, "请求体不能为空");
  104 + sendErrorResponse(context, BAD_REQUEST_STATUS_CODE, "请求体不能为空");
83 105 return;
84 106 }
85 107  
... ... @@ -94,7 +116,7 @@ public class IotMqttHttpAuthHandler {
94 116  
95 117 } catch (Exception e) {
96 118 log.error("[connected][处理设备连接事件失败]", e);
97   - sendErrorResponse(context, 500, "处理失败");
  119 + sendErrorResponse(context, INTERNAL_ERROR_STATUS_CODE, "处理失败");
98 120 }
99 121 }
100 122  
... ... @@ -106,7 +128,7 @@ public class IotMqttHttpAuthHandler {
106 128 // 解析请求体
107 129 JsonObject body = context.body().asJsonObject();
108 130 if (body == null) {
109   - sendErrorResponse(context, 400, "请求体不能为空");
  131 + sendErrorResponse(context, BAD_REQUEST_STATUS_CODE, "请求体不能为空");
110 132 return;
111 133 }
112 134  
... ... @@ -123,7 +145,7 @@ public class IotMqttHttpAuthHandler {
123 145  
124 146 } catch (Exception e) {
125 147 log.error("[disconnected][处理设备断开连接事件失败]", e);
126   - sendErrorResponse(context, 500, "处理失败");
  148 + sendErrorResponse(context, INTERNAL_ERROR_STATUS_CODE, "处理失败");
127 149 }
128 150 }
129 151  
... ... @@ -175,7 +197,7 @@ public class IotMqttHttpAuthHandler {
175 197 */
176 198 private void sendSuccessResponse(RoutingContext context, String message) {
177 199 context.response()
178   - .setStatusCode(200)
  200 + .setStatusCode(SUCCESS_STATUS_CODE)
179 201 .putHeader("Content-Type", "text/plain; charset=utf-8")
180 202 .end(message);
181 203 }
... ...
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/mqtt/router/IotMqttUpstreamHandler.java
1 1 package cn.iocoder.yudao.module.iot.gateway.protocol.mqtt.router;
2 2  
3   -import cn.hutool.core.util.StrUtil;
4 3 import cn.hutool.extra.spring.SpringUtil;
5 4 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
6   -import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer;
7 5 import cn.iocoder.yudao.module.iot.gateway.enums.IotDeviceTopicEnum;
8 6 import cn.iocoder.yudao.module.iot.gateway.service.device.message.IotDeviceMessageService;
9 7 import io.vertx.mqtt.messages.MqttPublishMessage;
... ... @@ -19,14 +17,12 @@ import java.nio.charset.StandardCharsets;
19 17 * @author 芋道源码
20 18 */
21 19 @Slf4j
22   -public class IotMqttUpstreamHandler {
  20 +public class IotMqttUpstreamHandler extends IotMqttAbstractHandler {
23 21  
24   - private final IotDeviceMessageProducer deviceMessageProducer;
25 22 private final IotDeviceMessageService deviceMessageService;
26 23 private final String serverId;
27 24  
28 25 public IotMqttUpstreamHandler(cn.iocoder.yudao.module.iot.gateway.protocol.mqtt.IotMqttUpstreamProtocol protocol) {
29   - this.deviceMessageProducer = SpringUtil.getBean(IotDeviceMessageProducer.class);
30 26 this.deviceMessageService = SpringUtil.getBean(IotDeviceMessageService.class);
31 27 this.serverId = protocol.getServerId();
32 28 }
... ... @@ -38,41 +34,22 @@ public class IotMqttUpstreamHandler {
38 34 String topic = message.topicName();
39 35 String payload = message.payload().toString(StandardCharsets.UTF_8);
40 36  
41   - if (StrUtil.isBlank(topic)) {
42   - log.warn("[handle][主题为空,忽略消息]");
43   - return;
44   - }
45   -
46   - if (StrUtil.isBlank(payload)) {
47   - log.warn("[handle][消息内容为空][topic: {}]", topic);
48   - return;
49   - }
50   -
51 37 log.debug("[handle][收到 MQTT 消息][topic: {}]", topic);
  38 + // 调用父类的 handle 方法,父类会进行参数校验
52 39 handle(topic, payload);
53 40 }
54 41  
55   - /**
56   - * 处理 MQTT 消息
57   - *
58   - * @param topic 主题
59   - * @param payload 消息内容
60   - */
61   - public void handle(String topic, String payload) {
62   - try {
63   - // 1. 识别并验证消息类型
64   - String messageType = getMessageType(topic);
65   - if (messageType == null) {
66   - log.warn("[handle][未知的消息类型][topic: {}]", topic);
67   - return;
68   - }
69   -
70   - // 2. 处理消息
71   - processMessage(topic, payload, messageType);
72   -
73   - } catch (Exception e) {
74   - log.error("[handle][处理消息失败][topic: {}][payload: {}]", topic, payload, e);
  42 + @Override
  43 + protected void doHandle(String topic, String payload) {
  44 + // 1. 识别并验证消息类型
  45 + String messageType = getMessageType(topic);
  46 + if (messageType == null) {
  47 + log.warn("[doHandle][未知的消息类型][topic: {}]", topic);
  48 + return;
75 49 }
  50 +
  51 + // 2. 处理消息
  52 + processMessage(topic, payload, messageType);
76 53 }
77 54  
78 55 /**
... ... @@ -109,39 +86,37 @@ public class IotMqttUpstreamHandler {
109 86 * @return 消息类型描述,如果不支持返回 null
110 87 */
111 88 private String getMessageType(String topic) {
112   - if (StrUtil.isBlank(topic)) {
113   - return null;
114   - }
  89 + // 此方法由 doHandle 调用,topic 已经在父类中校验过,无需重复校验
115 90  
116 91 // 按优先级匹配主题类型,避免误匹配
117 92  
118   - // 1. 设备属性上报: /sys/{productKey}/{deviceName}/thing/event/property/post
  93 + // 1. 设备属性上报: /sys/{productKey}/{deviceName}/thing/property/post
119 94 if (isPropertyPostTopic(topic)) {
120 95 return IotDeviceTopicEnum.PROPERTY_POST_TOPIC.getDescription();
121 96 }
122 97  
123   - // 2. 设备事件上报: /sys/{productKey}/{deviceName}/thing/event/{eventIdentifier}/post
  98 + // 2. 设备事件上报: /sys/{productKey}/{deviceName}/thing/{eventIdentifier}/post
124 99 if (isEventPostTopic(topic)) {
125 100 return "设备事件上报";
126 101 }
127 102  
128   - // 3. 设备属性设置响应: /sys/{productKey}/{deviceName}/thing/service/property/set_reply
  103 + // 3. 设备属性设置响应: /sys/{productKey}/{deviceName}/thing/property/set_reply
129 104 if (isPropertySetReplyTopic(topic)) {
130 105 return "设备属性设置响应";
131 106 }
132 107  
133   - // 4. 设备属性获取响应: /sys/{productKey}/{deviceName}/thing/service/property/get_reply
  108 + // 4. 设备属性获取响应: /sys/{productKey}/{deviceName}/thing/property/get_reply
134 109 if (isPropertyGetReplyTopic(topic)) {
135 110 return "设备属性获取响应";
136 111 }
137 112  
138   - // 5. 设备配置设置响应: /sys/{productKey}/{deviceName}/thing/service/config/set_reply
  113 + // 5. 设备配置设置响应: /sys/{productKey}/{deviceName}/thing/config/set_reply
139 114 if (isConfigSetReplyTopic(topic)) {
140 115 return IotDeviceTopicEnum.CONFIG_SET_TOPIC.getDescription() + "响应";
141 116 }
142 117  
143 118 // 6. 设备 OTA 升级响应:
144   - // /sys/{productKey}/{deviceName}/thing/service/ota/upgrade_reply
  119 + // /sys/{productKey}/{deviceName}/thing/ota/upgrade_reply
145 120 if (isOtaUpgradeReplyTopic(topic)) {
146 121 return IotDeviceTopicEnum.OTA_UPGRADE_TOPIC.getDescription() + "响应";
147 122 }
... ... @@ -214,18 +189,4 @@ public class IotMqttUpstreamHandler {
214 189 && !topic.contains("ota");
215 190 }
216 191  
217   - /**
218   - * 解析主题,获取主题各部分
219   - *
220   - * @param topic 主题
221   - * @return 主题各部分数组,如果解析失败返回 null
222   - */
223   - private String[] parseTopic(String topic) {
224   - String[] topicParts = topic.split("/");
225   - if (topicParts.length < 7) {
226   - log.warn("[parseTopic][主题格式不正确][topic: {}]", topic);
227   - return null;
228   - }
229   - return topicParts;
230   - }
231 192 }
232 193 \ No newline at end of file
... ...