Commit 50a88a9ce76af69bd4b05ceae449a02b91ed1d29

Authored by YunaiV
1 parent 6fdd91d0

review:【iot】mqtt websocket 协议

yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/mqttws/manager/IotMqttWsConnectionManager.java
1 1 package cn.iocoder.yudao.module.iot.gateway.protocol.mqttws.manager;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import io.vertx.core.http.ServerWebSocket;
4 5 import lombok.extern.slf4j.Slf4j;
5 6 import org.springframework.stereotype.Component;
... ... @@ -187,7 +188,7 @@ public class IotMqttWsConnectionManager {
187 188 */
188 189 public boolean isSubscribed(String deviceKey, String topic) {
189 190 Set<String> subscriptions = deviceSubscriptions.get(deviceKey);
190   - if (subscriptions == null || subscriptions.isEmpty()) {
  191 + if (CollUtil.isEmpty(subscriptions)) {
191 192 return false;
192 193 }
193 194  
... ... @@ -210,6 +211,7 @@ public class IotMqttWsConnectionManager {
210 211 return deviceSubscriptions.get(deviceKey);
211 212 }
212 213  
  214 + // TODO @haohao:这个方法,是不是也可以考虑抽到 IotMqttTopicUtils 里面去哈;感觉更简洁一点?
213 215 /**
214 216 * MQTT 主题匹配
215 217 * 支持通配符:
... ... @@ -227,25 +229,25 @@ public class IotMqttWsConnectionManager {
227 229 }
228 230  
229 231 // 不包含通配符
  232 + // TODO @haohao:这里要不要枚举下哈;+ #
230 233 if (!subscription.contains("+") && !subscription.contains("#")) {
231 234 return false;
232 235 }
233 236  
234 237 String[] subscriptionParts = subscription.split("/");
235 238 String[] topicParts = topic.split("/");
236   -
237 239 int i = 0;
238 240 for (; i < subscriptionParts.length && i < topicParts.length; i++) {
239 241 String subPart = subscriptionParts[i];
240 242 String topicPart = topicParts[i];
241 243  
  244 + // # 匹配剩余所有层级,且必须在末尾
242 245 if (subPart.equals("#")) {
243   - // # 匹配剩余所有层级,且必须在末尾
244 246 return i == subscriptionParts.length - 1;
245 247 }
246 248  
  249 + // 不是通配符且不匹配
247 250 if (!subPart.equals("+") && !subPart.equals(topicPart)) {
248   - // 不是通配符且不匹配
249 251 return false;
250 252 }
251 253 }
... ...
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/mqttws/router/IotMqttWsDownstreamHandler.java
... ... @@ -148,7 +148,7 @@ public class IotMqttWsDownstreamHandler {
148 148 try {
149 149 int messageId = qos > 0 ? generateMessageId() : 0;
150 150  
151   - // 手动编码MQTT PUBLISH消息
  151 + // 手动编码 MQTT PUBLISH 消息
152 152 io.netty.buffer.ByteBuf byteBuf = io.netty.buffer.Unpooled.buffer();
153 153  
154 154 // 固定头:消息类型(PUBLISH=3) + DUP(0) + QoS + RETAIN
... ... @@ -159,11 +159,11 @@ public class IotMqttWsDownstreamHandler {
159 159 int topicLength = topic.getBytes().length;
160 160 int remainingLength = 2 + topicLength + (qos > 0 ? 2 : 0) + payload.length;
161 161  
162   - // 写入剩余长度(简化版本,假设小于128字节)
  162 + // 写入剩余长度(简化版本,假设小于 128 字节)
163 163 if (remainingLength < 128) {
164 164 byteBuf.writeByte(remainingLength);
165 165 } else {
166   - // 处理大于127的情况
  166 + // 处理大于 127 的情况
167 167 int x = remainingLength;
168 168 do {
169 169 int encodedByte = x % 128;
... ... @@ -179,7 +179,7 @@ public class IotMqttWsDownstreamHandler {
179 179 byteBuf.writeShort(topicLength);
180 180 byteBuf.writeBytes(topic.getBytes());
181 181  
182   - // 可变头:消息ID(仅QoS>0时)
  182 + // 可变头:消息 ID(仅 QoS > 0 时)
183 183 if (qos > 0) {
184 184 byteBuf.writeShort(messageId);
185 185 }
... ... @@ -191,7 +191,6 @@ public class IotMqttWsDownstreamHandler {
191 191 byte[] bytes = new byte[byteBuf.readableBytes()];
192 192 byteBuf.readBytes(bytes);
193 193 byteBuf.release();
194   -
195 194 socket.writeBinaryMessage(Buffer.buffer(bytes));
196 195  
197 196 log.info("[sendMessageToDevice][消息已发送到设备,deviceKey: {},topic: {},qos: {},messageId: {}]",
... ... @@ -211,6 +210,7 @@ public class IotMqttWsDownstreamHandler {
211 210 private int generateMessageId() {
212 211 int id = messageIdGenerator.getAndIncrement();
213 212 // MQTT 消息 ID 范围是 1-65535
  213 + // TODO @haohao:并发可能有问题;
214 214 if (id > 65535) {
215 215 messageIdGenerator.set(1);
216 216 return 1;
... ...
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/mqttws/router/IotMqttWsUpstreamHandler.java
... ... @@ -253,7 +253,6 @@ public class IotMqttWsUpstreamHandler {
253 253  
254 254 // 5. 发送设备上线消息
255 255 sendOnlineMessage(device);
256   -
257 256 } catch (Exception e) {
258 257 log.error("[handleConnect][处理 CONNECT 消息失败,socketId: {}]", socketId, e);
259 258 sendConnAck(socket, MqttConnectReturnCode.CONNECTION_REFUSED_SERVER_UNAVAILABLE);
... ... @@ -311,7 +310,6 @@ public class IotMqttWsUpstreamHandler {
311 310 sendPubRec(socket, messageId);
312 311 }
313 312 // QoS 0 无需确认
314   -
315 313 } catch (Exception e) {
316 314 log.error("[handlePublish][处理 PUBLISH 消息失败,deviceId: {}]", device.getId(), e);
317 315 }
... ... @@ -323,7 +321,6 @@ public class IotMqttWsUpstreamHandler {
323 321 private void handlePubAck(ServerWebSocket socket, MqttMessage message) {
324 322 String socketId = socketIdMap.get(socket);
325 323 IotDeviceRespDTO device = socketDeviceMap.get(socketId);
326   -
327 324 if (device == null) {
328 325 log.warn("[handlePubAck][设备未认证,socketId: {}]", socketId);
329 326 socket.close();
... ... @@ -340,7 +337,6 @@ public class IotMqttWsUpstreamHandler {
340 337 private void handlePubRec(ServerWebSocket socket, MqttMessage message) {
341 338 String socketId = socketIdMap.get(socket);
342 339 IotDeviceRespDTO device = socketDeviceMap.get(socketId);
343   -
344 340 if (device == null) {
345 341 log.warn("[handlePubRec][设备未认证,socketId: {}]", socketId);
346 342 socket.close();
... ... @@ -349,7 +345,6 @@ public class IotMqttWsUpstreamHandler {
349 345  
350 346 int messageId = ((MqttMessageIdVariableHeader) message.variableHeader()).messageId();
351 347 log.debug("[handlePubRec][收到 PUBREC,messageId: {},deviceId: {}]", messageId, device.getId());
352   -
353 348 // 发送 PUBREL
354 349 sendPubRel(socket, messageId);
355 350 }
... ... @@ -369,7 +364,6 @@ public class IotMqttWsUpstreamHandler {
369 364  
370 365 int messageId = ((MqttMessageIdVariableHeader) message.variableHeader()).messageId();
371 366 log.debug("[handlePubRel][收到 PUBREL,messageId: {},deviceId: {}]", messageId, device.getId());
372   -
373 367 // 发送 PUBCOMP
374 368 sendPubComp(socket, messageId);
375 369 }
... ... @@ -397,7 +391,6 @@ public class IotMqttWsUpstreamHandler {
397 391 private void handleSubscribe(ServerWebSocket socket, MqttSubscribeMessage message) {
398 392 String socketId = socketIdMap.get(socket);
399 393 IotDeviceRespDTO device = socketDeviceMap.get(socketId);
400   -
401 394 if (device == null) {
402 395 log.warn("[handleSubscribe][设备未认证,socketId: {}]", socketId);
403 396 socket.close();
... ... @@ -429,7 +422,6 @@ public class IotMqttWsUpstreamHandler {
429 422  
430 423 // 3. 发送 SUBACK
431 424 sendSubAck(socket, messageId, grantedQosList);
432   -
433 425 } catch (Exception e) {
434 426 log.error("[handleSubscribe][处理 SUBSCRIBE 消息失败,deviceId: {}]", device.getId(), e);
435 427 }
... ... @@ -441,7 +433,6 @@ public class IotMqttWsUpstreamHandler {
441 433 private void handleUnsubscribe(ServerWebSocket socket, MqttUnsubscribeMessage message) {
442 434 String socketId = socketIdMap.get(socket);
443 435 IotDeviceRespDTO device = socketDeviceMap.get(socketId);
444   -
445 436 if (device == null) {
446 437 log.warn("[handleUnsubscribe][设备未认证,socketId: {}]", socketId);
447 438 socket.close();
... ... @@ -465,7 +456,6 @@ public class IotMqttWsUpstreamHandler {
465 456  
466 457 // 3. 发送 UNSUBACK
467 458 sendUnsubAck(socket, messageId);
468   -
469 459 } catch (Exception e) {
470 460 log.error("[handleUnsubscribe][处理 UNSUBSCRIBE 消息失败,deviceId: {}]", device.getId(), e);
471 461 }
... ... @@ -477,7 +467,6 @@ public class IotMqttWsUpstreamHandler {
477 467 private void handlePingReq(ServerWebSocket socket) {
478 468 String socketId = socketIdMap.get(socket);
479 469 IotDeviceRespDTO device = socketDeviceMap.get(socketId);
480   -
481 470 if (device == null) {
482 471 log.warn("[handlePingReq][设备未认证,socketId: {}]", socketId);
483 472 socket.close();
... ... @@ -485,7 +474,6 @@ public class IotMqttWsUpstreamHandler {
485 474 }
486 475  
487 476 log.debug("[handlePingReq][收到心跳请求,deviceId: {}]", device.getId());
488   -
489 477 // 发送 PINGRESP
490 478 sendPingResp(socket);
491 479 }
... ... @@ -496,7 +484,6 @@ public class IotMqttWsUpstreamHandler {
496 484 private void handleDisconnect(ServerWebSocket socket) {
497 485 String socketId = socketIdMap.get(socket);
498 486 IotDeviceRespDTO device = socketDeviceMap.remove(socketId);
499   -
500 487 if (device != null) {
501 488 String deviceKey = device.getProductKey() + ":" + device.getDeviceName();
502 489 connectionManager.removeConnection(deviceKey);
... ... @@ -600,7 +587,6 @@ public class IotMqttWsUpstreamHandler {
600 587  
601 588 // 编码并发送
602 589 sendMqttMessage(socket, connAckMessage);
603   -
604 590 log.debug("[sendConnAck][发送 CONNACK 消息,returnCode: {}]", returnCode);
605 591 } catch (Exception e) {
606 592 log.error("[sendConnAck][发送 CONNACK 消息失败]", e);
... ... @@ -620,7 +606,6 @@ public class IotMqttWsUpstreamHandler {
620 606  
621 607 // 编码并发送
622 608 sendMqttMessage(socket, pubAckMessage);
623   -
624 609 log.debug("[sendPubAck][发送 PUBACK 消息,messageId: {}]", messageId);
625 610 } catch (Exception e) {
626 611 log.error("[sendPubAck][发送 PUBACK 消息失败,messageId: {}]", messageId, e);
... ... @@ -640,7 +625,6 @@ public class IotMqttWsUpstreamHandler {
640 625  
641 626 // 编码并发送
642 627 sendMqttMessage(socket, pubRecMessage);
643   -
644 628 log.debug("[sendPubRec][发送 PUBREC 消息,messageId: {}]", messageId);
645 629 } catch (Exception e) {
646 630 log.error("[sendPubRec][发送 PUBREC 消息失败,messageId: {}]", messageId, e);
... ... @@ -660,7 +644,6 @@ public class IotMqttWsUpstreamHandler {
660 644  
661 645 // 编码并发送
662 646 sendMqttMessage(socket, pubRelMessage);
663   -
664 647 log.debug("[sendPubRel][发送 PUBREL 消息,messageId: {}]", messageId);
665 648 } catch (Exception e) {
666 649 log.error("[sendPubRel][发送 PUBREL 消息失败,messageId: {}]", messageId, e);
... ... @@ -680,7 +663,6 @@ public class IotMqttWsUpstreamHandler {
680 663  
681 664 // 编码并发送
682 665 sendMqttMessage(socket, pubCompMessage);
683   -
684 666 log.debug("[sendPubComp][发送 PUBCOMP 消息,messageId: {}]", messageId);
685 667 } catch (Exception e) {
686 668 log.error("[sendPubComp][发送 PUBCOMP 消息失败,messageId: {}]", messageId, e);
... ... @@ -701,7 +683,6 @@ public class IotMqttWsUpstreamHandler {
701 683  
702 684 // 编码并发送
703 685 sendMqttMessage(socket, subAckMessage);
704   -
705 686 log.debug("[sendSubAck][发送 SUBACK 消息,messageId: {},主题数量: {}]", messageId, grantedQosList.length);
706 687 } catch (Exception e) {
707 688 log.error("[sendSubAck][发送 SUBACK 消息失败,messageId: {}]", messageId, e);
... ... @@ -721,7 +702,6 @@ public class IotMqttWsUpstreamHandler {
721 702  
722 703 // 编码并发送
723 704 sendMqttMessage(socket, unsubAckMessage);
724   -
725 705 log.debug("[sendUnsubAck][发送 UNSUBACK 消息,messageId: {}]", messageId);
726 706 } catch (Exception e) {
727 707 log.error("[sendUnsubAck][发送 UNSUBACK 消息失败,messageId: {}]", messageId, e);
... ... @@ -740,7 +720,6 @@ public class IotMqttWsUpstreamHandler {
740 720  
741 721 // 编码并发送
742 722 sendMqttMessage(socket, pingRespMessage);
743   -
744 723 log.debug("[sendPingResp][发送 PINGRESP 消息]");
745 724 } catch (Exception e) {
746 725 log.error("[sendPingResp][发送 PINGRESP 消息失败]", e);
... ...