Commit 50ac2ca5f6fcd3e5685622ca1ef29c13bf44ef9c
1 parent
14336002
feat:【IoT 物联网】优化 MQTT 协议实现
Showing
4 changed files
with
103 additions
and
81 deletions
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/config/IotGatewayConfiguration.java
| ... | ... | @@ -129,12 +129,11 @@ public class IotGatewayConfiguration { |
| 129 | 129 | |
| 130 | 130 | @Bean |
| 131 | 131 | public IotMqttUpstreamProtocol iotMqttUpstreamProtocol(IotGatewayProperties gatewayProperties, |
| 132 | - IotDeviceService deviceService, | |
| 133 | 132 | IotDeviceMessageService messageService, |
| 134 | 133 | IotMqttConnectionManager connectionManager, |
| 135 | 134 | Vertx mqttVertx) { |
| 136 | - return new IotMqttUpstreamProtocol(gatewayProperties.getProtocol().getMqtt(), | |
| 137 | - deviceService, messageService, connectionManager, mqttVertx); | |
| 135 | + return new IotMqttUpstreamProtocol(gatewayProperties.getProtocol().getMqtt(), messageService, | |
| 136 | + connectionManager, mqttVertx); | |
| 138 | 137 | } |
| 139 | 138 | |
| 140 | 139 | @Bean | ... | ... |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/mqtt/IotMqttUpstreamProtocol.java
| ... | ... | @@ -4,7 +4,6 @@ import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils; |
| 4 | 4 | import cn.iocoder.yudao.module.iot.gateway.config.IotGatewayProperties; |
| 5 | 5 | import cn.iocoder.yudao.module.iot.gateway.protocol.mqtt.manager.IotMqttConnectionManager; |
| 6 | 6 | import cn.iocoder.yudao.module.iot.gateway.protocol.mqtt.router.IotMqttUpstreamHandler; |
| 7 | -import cn.iocoder.yudao.module.iot.gateway.service.device.IotDeviceService; | |
| 8 | 7 | import cn.iocoder.yudao.module.iot.gateway.service.device.message.IotDeviceMessageService; |
| 9 | 8 | import io.vertx.core.Vertx; |
| 10 | 9 | import io.vertx.mqtt.MqttServer; |
| ... | ... | @@ -24,8 +23,6 @@ public class IotMqttUpstreamProtocol { |
| 24 | 23 | |
| 25 | 24 | private final IotGatewayProperties.MqttProperties mqttProperties; |
| 26 | 25 | |
| 27 | - private final IotDeviceService deviceService; | |
| 28 | - | |
| 29 | 26 | private final IotDeviceMessageService messageService; |
| 30 | 27 | |
| 31 | 28 | private final IotMqttConnectionManager connectionManager; |
| ... | ... | @@ -38,12 +35,10 @@ public class IotMqttUpstreamProtocol { |
| 38 | 35 | private MqttServer mqttServer; |
| 39 | 36 | |
| 40 | 37 | public IotMqttUpstreamProtocol(IotGatewayProperties.MqttProperties mqttProperties, |
| 41 | - IotDeviceService deviceService, | |
| 42 | 38 | IotDeviceMessageService messageService, |
| 43 | 39 | IotMqttConnectionManager connectionManager, |
| 44 | 40 | Vertx vertx) { |
| 45 | 41 | this.mqttProperties = mqttProperties; |
| 46 | - this.deviceService = deviceService; | |
| 47 | 42 | this.messageService = messageService; |
| 48 | 43 | this.connectionManager = connectionManager; |
| 49 | 44 | this.vertx = vertx; |
| ... | ... | @@ -54,22 +49,22 @@ public class IotMqttUpstreamProtocol { |
| 54 | 49 | @PostConstruct |
| 55 | 50 | public void start() { |
| 56 | 51 | // 创建服务器选项 |
| 57 | - MqttServerOptions options = new MqttServerOptions(); | |
| 58 | - options.setPort(mqttProperties.getPort()); | |
| 59 | - options.setMaxMessageSize(mqttProperties.getMaxMessageSize()); | |
| 60 | - options.setTimeoutOnConnect(mqttProperties.getConnectTimeoutSeconds()); | |
| 52 | + MqttServerOptions options = new MqttServerOptions() | |
| 53 | + .setPort(mqttProperties.getPort()) | |
| 54 | + .setMaxMessageSize(mqttProperties.getMaxMessageSize()) | |
| 55 | + .setTimeoutOnConnect(mqttProperties.getConnectTimeoutSeconds()); | |
| 61 | 56 | |
| 62 | 57 | // 配置 SSL(如果启用) |
| 63 | 58 | if (Boolean.TRUE.equals(mqttProperties.getSslEnabled())) { |
| 64 | - options.setSsl(true).setKeyCertOptions(mqttProperties.getSslOptions().getKeyCertOptions()) | |
| 59 | + options.setSsl(true) | |
| 60 | + .setKeyCertOptions(mqttProperties.getSslOptions().getKeyCertOptions()) | |
| 65 | 61 | .setTrustOptions(mqttProperties.getSslOptions().getTrustOptions()); |
| 66 | 62 | } |
| 67 | 63 | |
| 68 | 64 | // 创建服务器并设置连接处理器 |
| 69 | 65 | mqttServer = MqttServer.create(vertx, options); |
| 70 | 66 | mqttServer.endpointHandler(endpoint -> { |
| 71 | - IotMqttUpstreamHandler handler = new IotMqttUpstreamHandler(this, messageService, deviceService, | |
| 72 | - connectionManager); | |
| 67 | + IotMqttUpstreamHandler handler = new IotMqttUpstreamHandler(this, messageService, connectionManager); | |
| 73 | 68 | handler.handle(endpoint); |
| 74 | 69 | }); |
| 75 | 70 | ... | ... |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/mqtt/manager/IotMqttConnectionManager.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.gateway.protocol.mqtt.manager; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.util.StrUtil; | |
| 3 | 4 | import io.netty.handler.codec.mqtt.MqttQoS; |
| 4 | 5 | import io.vertx.mqtt.MqttEndpoint; |
| 5 | 6 | import lombok.Data; |
| ... | ... | @@ -24,6 +25,11 @@ import java.util.concurrent.ConcurrentHashMap; |
| 24 | 25 | public class IotMqttConnectionManager { |
| 25 | 26 | |
| 26 | 27 | /** |
| 28 | + * 未知地址常量(当获取端点地址失败时使用) | |
| 29 | + */ | |
| 30 | + private static final String UNKNOWN_ADDRESS = "unknown"; | |
| 31 | + | |
| 32 | + /** | |
| 27 | 33 | * 连接信息映射:MqttEndpoint -> 连接信息 |
| 28 | 34 | */ |
| 29 | 35 | private final Map<MqttEndpoint, ConnectionInfo> connectionMap = new ConcurrentHashMap<>(); |
| ... | ... | @@ -35,21 +41,32 @@ public class IotMqttConnectionManager { |
| 35 | 41 | |
| 36 | 42 | /** |
| 37 | 43 | * 安全获取 endpoint 地址 |
| 44 | + * <p> | |
| 45 | + * 优先从缓存获取地址,缓存为空时再尝试实时获取 | |
| 38 | 46 | * |
| 39 | 47 | * @param endpoint MQTT 连接端点 |
| 40 | - * @return 地址字符串,如果获取失败则返回 "unknown" | |
| 48 | + * @return 地址字符串,获取失败时返回 "unknown" | |
| 41 | 49 | */ |
| 42 | - private String getEndpointAddress(MqttEndpoint endpoint) { | |
| 50 | + public String getEndpointAddress(MqttEndpoint endpoint) { | |
| 51 | + String realTimeAddress = UNKNOWN_ADDRESS; | |
| 52 | + if (endpoint == null) { | |
| 53 | + return realTimeAddress; | |
| 54 | + } | |
| 55 | + | |
| 56 | + // 1. 优先从缓存获取(避免连接关闭时的异常) | |
| 57 | + ConnectionInfo connectionInfo = connectionMap.get(endpoint); | |
| 58 | + if (connectionInfo != null && StrUtil.isNotBlank(connectionInfo.getRemoteAddress())) { | |
| 59 | + return connectionInfo.getRemoteAddress(); | |
| 60 | + } | |
| 61 | + | |
| 62 | + // 2. 缓存为空时尝试实时获取 | |
| 43 | 63 | try { |
| 44 | - if (endpoint != null) { | |
| 45 | - return endpoint.remoteAddress().toString(); | |
| 46 | - } | |
| 47 | - } catch (Exception e) { | |
| 48 | - // 忽略异常,返回默认值 | |
| 49 | - // TODO @haohao:这个比较稳定会出现哇? | |
| 64 | + realTimeAddress = endpoint.remoteAddress().toString(); | |
| 65 | + } catch (Exception ignored) { | |
| 66 | + // 连接已关闭,忽略异常 | |
| 50 | 67 | } |
| 51 | - // TODO @haohao:这个要枚举下么? | |
| 52 | - return "unknown"; | |
| 68 | + | |
| 69 | + return realTimeAddress; | |
| 53 | 70 | } |
| 54 | 71 | |
| 55 | 72 | /** |
| ... | ... | @@ -87,8 +104,9 @@ public class IotMqttConnectionManager { |
| 87 | 104 | if (connectionInfo != null) { |
| 88 | 105 | Long deviceId = connectionInfo.getDeviceId(); |
| 89 | 106 | deviceEndpointMap.remove(deviceId); |
| 90 | - log.info("[unregisterConnection][注销设备连接,设备 ID: {},连接: {}]", | |
| 91 | - deviceId, getEndpointAddress(endpoint)); | |
| 107 | + | |
| 108 | + log.info("[unregisterConnection][注销设备连接,设备 ID: {},连接: {}]", deviceId, | |
| 109 | + getEndpointAddress(endpoint)); | |
| 92 | 110 | } |
| 93 | 111 | } |
| 94 | 112 | |
| ... | ... | @@ -195,6 +213,11 @@ public class IotMqttConnectionManager { |
| 195 | 213 | */ |
| 196 | 214 | private boolean authenticated; |
| 197 | 215 | |
| 216 | + /** | |
| 217 | + * 连接地址 | |
| 218 | + */ | |
| 219 | + private String remoteAddress; | |
| 220 | + | |
| 198 | 221 | } |
| 199 | 222 | |
| 200 | 223 | } | ... | ... |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/mqtt/router/IotMqttUpstreamHandler.java
| ... | ... | @@ -12,7 +12,6 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; |
| 12 | 12 | import cn.iocoder.yudao.module.iot.core.util.IotDeviceAuthUtils; |
| 13 | 13 | import cn.iocoder.yudao.module.iot.gateway.protocol.mqtt.IotMqttUpstreamProtocol; |
| 14 | 14 | import cn.iocoder.yudao.module.iot.gateway.protocol.mqtt.manager.IotMqttConnectionManager; |
| 15 | -import cn.iocoder.yudao.module.iot.gateway.service.device.IotDeviceService; | |
| 16 | 15 | import cn.iocoder.yudao.module.iot.gateway.service.device.message.IotDeviceMessageService; |
| 17 | 16 | import io.netty.handler.codec.mqtt.MqttConnectReturnCode; |
| 18 | 17 | import io.netty.handler.codec.mqtt.MqttQoS; |
| ... | ... | @@ -40,8 +39,6 @@ public class IotMqttUpstreamHandler { |
| 40 | 39 | |
| 41 | 40 | public IotMqttUpstreamHandler(IotMqttUpstreamProtocol protocol, |
| 42 | 41 | IotDeviceMessageService deviceMessageService, |
| 43 | - // TODO @haohao:用不到的 deviceService 可以删除哈; | |
| 44 | - IotDeviceService deviceService, | |
| 45 | 42 | IotMqttConnectionManager connectionManager) { |
| 46 | 43 | this.deviceMessageService = deviceMessageService; |
| 47 | 44 | this.deviceApi = SpringUtil.getBean(IotDeviceCommonApi.class); |
| ... | ... | @@ -60,7 +57,7 @@ public class IotMqttUpstreamHandler { |
| 60 | 57 | String password = endpoint.auth() != null ? endpoint.auth().getPassword() : null; |
| 61 | 58 | |
| 62 | 59 | log.debug("[handle][设备连接请求,客户端 ID: {},用户名: {},地址: {}]", |
| 63 | - clientId, username, getEndpointAddress(endpoint)); | |
| 60 | + clientId, username, connectionManager.getEndpointAddress(endpoint)); | |
| 64 | 61 | |
| 65 | 62 | // 1. 先进行认证 |
| 66 | 63 | if (!authenticateDevice(clientId, username, password, endpoint)) { |
| ... | ... | @@ -71,32 +68,46 @@ public class IotMqttUpstreamHandler { |
| 71 | 68 | |
| 72 | 69 | log.info("[handle][设备认证成功,建立连接,客户端 ID: {},用户名: {}]", clientId, username); |
| 73 | 70 | |
| 74 | - // TODO @haohao:这里是不是少了序号哈? | |
| 75 | - // 设置异常和关闭处理器 | |
| 71 | + // 2. 设置异常和关闭处理器 | |
| 76 | 72 | endpoint.exceptionHandler(ex -> { |
| 77 | - log.warn("[handle][连接异常,客户端 ID: {},地址: {}]", clientId, getEndpointAddress(endpoint)); | |
| 73 | + log.warn("[handle][连接异常,客户端 ID: {},地址: {}]", clientId, connectionManager.getEndpointAddress(endpoint)); | |
| 78 | 74 | cleanupConnection(endpoint); |
| 79 | 75 | }); |
| 80 | 76 | endpoint.closeHandler(v -> { |
| 81 | - log.debug("[handle][连接关闭,客户端 ID: {},地址: {}]", clientId, getEndpointAddress(endpoint)); | |
| 82 | 77 | cleanupConnection(endpoint); |
| 83 | 78 | }); |
| 84 | 79 | |
| 85 | - // 设置消息处理器 | |
| 80 | + // 3. 设置消息处理器 | |
| 86 | 81 | endpoint.publishHandler(message -> { |
| 87 | 82 | try { |
| 88 | - processMessage(clientId, message.topicName(), message.payload().getBytes(), endpoint); | |
| 83 | + processMessage(clientId, message.topicName(), message.payload().getBytes()); | |
| 84 | + | |
| 85 | + // 根据 QoS 级别发送相应的确认消息 | |
| 86 | + if (message.qosLevel() == MqttQoS.AT_LEAST_ONCE) { | |
| 87 | + // QoS 1: 发送 PUBACK 确认 | |
| 88 | + endpoint.publishAcknowledge(message.messageId()); | |
| 89 | + } else if (message.qosLevel() == MqttQoS.EXACTLY_ONCE) { | |
| 90 | + // QoS 2: 发送 PUBREC 确认 | |
| 91 | + endpoint.publishReceived(message.messageId()); | |
| 92 | + } | |
| 93 | + // QoS 0 无需确认 | |
| 94 | + | |
| 89 | 95 | } catch (Exception e) { |
| 90 | 96 | log.error("[handle][消息解码失败,断开连接,客户端 ID: {},地址: {},错误: {}]", |
| 91 | - clientId, getEndpointAddress(endpoint), e.getMessage()); | |
| 97 | + clientId, connectionManager.getEndpointAddress(endpoint), e.getMessage()); | |
| 92 | 98 | cleanupConnection(endpoint); |
| 93 | 99 | endpoint.close(); |
| 94 | 100 | } |
| 95 | 101 | }); |
| 96 | 102 | |
| 97 | - // 设置订阅处理器 | |
| 103 | + // 4. 设置订阅处理器 | |
| 98 | 104 | endpoint.subscribeHandler(subscribe -> { |
| 99 | - log.debug("[handle][设备订阅,客户端 ID: {},主题: {}]", clientId, subscribe.topicSubscriptions()); | |
| 105 | + // 提取主题名称列表用于日志显示 | |
| 106 | + List<String> topicNames = subscribe.topicSubscriptions().stream() | |
| 107 | + .map(MqttTopicSubscription::topicName) | |
| 108 | + .collect(java.util.stream.Collectors.toList()); | |
| 109 | + log.debug("[handle][设备订阅,客户端 ID: {},主题: {}]", clientId, topicNames); | |
| 110 | + | |
| 100 | 111 | // 提取 QoS 列表 |
| 101 | 112 | List<MqttQoS> grantedQoSLevels = subscribe.topicSubscriptions().stream() |
| 102 | 113 | .map(MqttTopicSubscription::qualityOfService) |
| ... | ... | @@ -104,19 +115,22 @@ public class IotMqttUpstreamHandler { |
| 104 | 115 | endpoint.subscribeAcknowledge(subscribe.messageId(), grantedQoSLevels); |
| 105 | 116 | }); |
| 106 | 117 | |
| 107 | - // 设置取消订阅处理器 | |
| 118 | + // 5. 设置取消订阅处理器 | |
| 108 | 119 | endpoint.unsubscribeHandler(unsubscribe -> { |
| 109 | 120 | log.debug("[handle][设备取消订阅,客户端 ID: {},主题: {}]", clientId, unsubscribe.topics()); |
| 110 | 121 | endpoint.unsubscribeAcknowledge(unsubscribe.messageId()); |
| 111 | 122 | }); |
| 112 | 123 | |
| 113 | - // 设置断开连接处理器 | |
| 124 | + // 6. 设置 QoS 2消息的 PUBREL 处理器 | |
| 125 | + endpoint.publishReleaseHandler(endpoint::publishComplete); | |
| 126 | + | |
| 127 | + // 7. 设置断开连接处理器 | |
| 114 | 128 | endpoint.disconnectHandler(v -> { |
| 115 | 129 | log.debug("[handle][设备断开连接,客户端 ID: {}]", clientId); |
| 116 | 130 | cleanupConnection(endpoint); |
| 117 | 131 | }); |
| 118 | 132 | |
| 119 | - // 接受连接 | |
| 133 | + // 8. 接受连接 | |
| 120 | 134 | endpoint.accept(false); |
| 121 | 135 | } |
| 122 | 136 | |
| ... | ... | @@ -126,10 +140,8 @@ public class IotMqttUpstreamHandler { |
| 126 | 140 | * @param clientId 客户端 ID |
| 127 | 141 | * @param topic 主题 |
| 128 | 142 | * @param payload 消息内容 |
| 129 | - * @param endpoint MQTT 连接端点 | |
| 130 | - * @throws Exception 消息解码失败时抛出异常 | |
| 131 | 143 | */ |
| 132 | - private void processMessage(String clientId, String topic, byte[] payload, MqttEndpoint endpoint) throws Exception { | |
| 144 | + private void processMessage(String clientId, String topic, byte[] payload) { | |
| 133 | 145 | // 1. 基础检查 |
| 134 | 146 | if (payload == null || payload.length == 0) { |
| 135 | 147 | return; |
| ... | ... | @@ -146,14 +158,22 @@ public class IotMqttUpstreamHandler { |
| 146 | 158 | String deviceName = topicParts[3]; |
| 147 | 159 | |
| 148 | 160 | // 3. 解码消息(使用从 topic 解析的 productKey 和 deviceName) |
| 149 | - IotDeviceMessage message = deviceMessageService.decodeDeviceMessage(payload, productKey, deviceName); | |
| 150 | - if (message == null) { | |
| 151 | - log.warn("[processMessage][消息解码失败,客户端 ID: {},主题: {}]", clientId, topic); | |
| 152 | - return; | |
| 153 | - } | |
| 161 | + try { | |
| 162 | + IotDeviceMessage message = deviceMessageService.decodeDeviceMessage(payload, productKey, deviceName); | |
| 163 | + if (message == null) { | |
| 164 | + log.warn("[processMessage][消息解码失败,客户端 ID: {},主题: {}]", clientId, topic); | |
| 165 | + return; | |
| 166 | + } | |
| 154 | 167 | |
| 155 | - // 4. 处理业务消息(认证已在连接时完成) | |
| 156 | - handleBusinessRequest(clientId, message, productKey, deviceName, endpoint); | |
| 168 | + log.info("[processMessage][收到设备消息,设备: {}.{}, 方法: {}]", | |
| 169 | + productKey, deviceName, message.getMethod()); | |
| 170 | + | |
| 171 | + // 4. 处理业务消息(认证已在连接时完成) | |
| 172 | + handleBusinessRequest(message, productKey, deviceName); | |
| 173 | + } catch (Exception e) { | |
| 174 | + log.error("[processMessage][消息处理异常,客户端 ID: {},主题: {},错误: {}]", | |
| 175 | + clientId, topic, e.getMessage(), e); | |
| 176 | + } | |
| 157 | 177 | } |
| 158 | 178 | |
| 159 | 179 | /** |
| ... | ... | @@ -194,9 +214,10 @@ public class IotMqttUpstreamHandler { |
| 194 | 214 | return false; |
| 195 | 215 | } |
| 196 | 216 | |
| 197 | - IotDeviceGetReqDTO getReqDTO = new IotDeviceGetReqDTO(); | |
| 198 | - getReqDTO.setProductKey(deviceInfo.getProductKey()); | |
| 199 | - getReqDTO.setDeviceName(deviceInfo.getDeviceName()); | |
| 217 | + IotDeviceGetReqDTO getReqDTO = new IotDeviceGetReqDTO() | |
| 218 | + .setProductKey(deviceInfo.getProductKey()) | |
| 219 | + .setDeviceName(deviceInfo.getDeviceName()); | |
| 220 | + | |
| 200 | 221 | CommonResult<IotDeviceRespDTO> deviceResult = deviceApi.getDevice(getReqDTO); |
| 201 | 222 | if (!deviceResult.isSuccess() || deviceResult.getData() == null) { |
| 202 | 223 | log.warn("[authenticateDevice][获取设备信息失败,客户端 ID: {},用户名: {},错误: {}]", |
| ... | ... | @@ -221,8 +242,7 @@ public class IotMqttUpstreamHandler { |
| 221 | 242 | /** |
| 222 | 243 | * 处理业务请求 |
| 223 | 244 | */ |
| 224 | - private void handleBusinessRequest(String clientId, IotDeviceMessage message, String productKey, String deviceName, | |
| 225 | - MqttEndpoint endpoint) { | |
| 245 | + private void handleBusinessRequest(IotDeviceMessage message, String productKey, String deviceName) { | |
| 226 | 246 | // 发送消息到消息总线 |
| 227 | 247 | message.setServerId(serverId); |
| 228 | 248 | deviceMessageService.sendDeviceMessage(message, productKey, deviceName, serverId); |
| ... | ... | @@ -233,12 +253,14 @@ public class IotMqttUpstreamHandler { |
| 233 | 253 | */ |
| 234 | 254 | private void registerConnection(MqttEndpoint endpoint, IotDeviceRespDTO device, |
| 235 | 255 | String clientId) { |
| 236 | - IotMqttConnectionManager.ConnectionInfo connectionInfo = new IotMqttConnectionManager.ConnectionInfo(); | |
| 237 | - connectionInfo.setDeviceId(device.getId()); | |
| 238 | - connectionInfo.setProductKey(device.getProductKey()); | |
| 239 | - connectionInfo.setDeviceName(device.getDeviceName()); | |
| 240 | - connectionInfo.setClientId(clientId); | |
| 241 | - connectionInfo.setAuthenticated(true); | |
| 256 | + | |
| 257 | + IotMqttConnectionManager.ConnectionInfo connectionInfo = new IotMqttConnectionManager.ConnectionInfo() | |
| 258 | + .setDeviceId(device.getId()) | |
| 259 | + .setProductKey(device.getProductKey()) | |
| 260 | + .setDeviceName(device.getDeviceName()) | |
| 261 | + .setClientId(clientId) | |
| 262 | + .setAuthenticated(true) | |
| 263 | + .setRemoteAddress(connectionManager.getEndpointAddress(endpoint)); | |
| 242 | 264 | |
| 243 | 265 | connectionManager.registerConnection(endpoint, device.getId(), connectionInfo); |
| 244 | 266 | } |
| ... | ... | @@ -258,23 +280,6 @@ public class IotMqttUpstreamHandler { |
| 258 | 280 | } |
| 259 | 281 | |
| 260 | 282 | /** |
| 261 | - * 安全获取 endpoint 地址 | |
| 262 | - * | |
| 263 | - * @param endpoint MQTT 连接端点 | |
| 264 | - * @return 地址字符串,如果获取失败则返回 "unknown" | |
| 265 | - */ | |
| 266 | - private String getEndpointAddress(MqttEndpoint endpoint) { | |
| 267 | - try { | |
| 268 | - if (endpoint != null) { | |
| 269 | - return endpoint.remoteAddress().toString(); | |
| 270 | - } | |
| 271 | - } catch (Exception e) { | |
| 272 | - // 忽略异常,返回默认值 | |
| 273 | - } | |
| 274 | - return "unknown"; | |
| 275 | - } | |
| 276 | - | |
| 277 | - /** | |
| 278 | 283 | * 清理连接 |
| 279 | 284 | */ |
| 280 | 285 | private void cleanupConnection(MqttEndpoint endpoint) { | ... | ... |