Commit 8e4b4cf20a05a16acb91146f5dacbfc569448357
1 parent
cb301eb7
feat(iot):【协议改造】udp 初步改造(100%),基于 /Users/yunai/.claude/plans/iot-udp-fix-plan.md,优化代码以及各种缺陷
Showing
7 changed files
with
32 additions
and
103 deletions
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/tcp/IotTcpProtocol.java
| @@ -155,7 +155,11 @@ public class IotTcpProtocol implements IotProtocol { | @@ -155,7 +155,11 @@ public class IotTcpProtocol implements IotProtocol { | ||
| 155 | this.downstreamSubscriber.start(); | 155 | this.downstreamSubscriber.start(); |
| 156 | } catch (Exception e) { | 156 | } catch (Exception e) { |
| 157 | log.error("[start][IoT TCP 协议 {} 启动失败]", getId(), e); | 157 | log.error("[start][IoT TCP 协议 {} 启动失败]", getId(), e); |
| 158 | - // 启动失败时关闭 Vertx | 158 | + // 启动失败时关闭资源 |
| 159 | + if (tcpServer != null) { | ||
| 160 | + tcpServer.close(); | ||
| 161 | + tcpServer = null; | ||
| 162 | + } | ||
| 159 | if (vertx != null) { | 163 | if (vertx != null) { |
| 160 | vertx.close(); | 164 | vertx.close(); |
| 161 | vertx = null; | 165 | vertx = null; |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/udp/IotUdpConfig.java
| @@ -21,17 +21,11 @@ public class IotUdpConfig { | @@ -21,17 +21,11 @@ public class IotUdpConfig { | ||
| 21 | /** | 21 | /** |
| 22 | * 会话超时时间(毫秒) | 22 | * 会话超时时间(毫秒) |
| 23 | * <p> | 23 | * <p> |
| 24 | - * 用于清理不活跃的设备地址映射 | 24 | + * 基于 Guava Cache 的 expireAfterAccess 实现自动过期清理 |
| 25 | */ | 25 | */ |
| 26 | @NotNull(message = "会话超时时间不能为空") | 26 | @NotNull(message = "会话超时时间不能为空") |
| 27 | @Min(value = 1000, message = "会话超时时间必须大于 1000 毫秒") | 27 | @Min(value = 1000, message = "会话超时时间必须大于 1000 毫秒") |
| 28 | private Long sessionTimeoutMs = 60000L; | 28 | private Long sessionTimeoutMs = 60000L; |
| 29 | - /** | ||
| 30 | - * 会话清理间隔(毫秒) | ||
| 31 | - */ | ||
| 32 | - @NotNull(message = "会话清理间隔不能为空") | ||
| 33 | - @Min(value = 1000, message = "会话清理间隔必须大于 1000 毫秒") | ||
| 34 | - private Long sessionCleanIntervalMs = 30000L; | ||
| 35 | 29 | ||
| 36 | /** | 30 | /** |
| 37 | * 接收缓冲区大小(字节) | 31 | * 接收缓冲区大小(字节) |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/udp/IotUdpProtocol.java
| 1 | package cn.iocoder.yudao.module.iot.gateway.protocol.udp; | 1 | package cn.iocoder.yudao.module.iot.gateway.protocol.udp; |
| 2 | 2 | ||
| 3 | -import cn.hutool.core.collection.CollUtil; | ||
| 4 | import cn.hutool.extra.spring.SpringUtil; | 3 | import cn.hutool.extra.spring.SpringUtil; |
| 5 | -import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceRespDTO; | ||
| 6 | import cn.iocoder.yudao.module.iot.core.enums.IotProtocolTypeEnum; | 4 | import cn.iocoder.yudao.module.iot.core.enums.IotProtocolTypeEnum; |
| 7 | import cn.iocoder.yudao.module.iot.core.enums.IotSerializeTypeEnum; | 5 | import cn.iocoder.yudao.module.iot.core.enums.IotSerializeTypeEnum; |
| 8 | import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; | 6 | import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; |
| 9 | -import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | ||
| 10 | -import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils; | ||
| 11 | import cn.iocoder.yudao.module.iot.gateway.config.IotGatewayProperties.ProtocolInstanceProperties; | 7 | import cn.iocoder.yudao.module.iot.gateway.config.IotGatewayProperties.ProtocolInstanceProperties; |
| 12 | import cn.iocoder.yudao.module.iot.gateway.protocol.IotProtocol; | 8 | import cn.iocoder.yudao.module.iot.gateway.protocol.IotProtocol; |
| 13 | import cn.iocoder.yudao.module.iot.gateway.protocol.udp.handler.downstream.IotUdpDownstreamHandler; | 9 | import cn.iocoder.yudao.module.iot.gateway.protocol.udp.handler.downstream.IotUdpDownstreamHandler; |
| @@ -16,8 +12,7 @@ import cn.iocoder.yudao.module.iot.gateway.protocol.udp.handler.upstream.IotUdpU | @@ -16,8 +12,7 @@ import cn.iocoder.yudao.module.iot.gateway.protocol.udp.handler.upstream.IotUdpU | ||
| 16 | import cn.iocoder.yudao.module.iot.gateway.protocol.udp.manager.IotUdpSessionManager; | 12 | import cn.iocoder.yudao.module.iot.gateway.protocol.udp.manager.IotUdpSessionManager; |
| 17 | import cn.iocoder.yudao.module.iot.gateway.serialize.IotMessageSerializer; | 13 | import cn.iocoder.yudao.module.iot.gateway.serialize.IotMessageSerializer; |
| 18 | import cn.iocoder.yudao.module.iot.gateway.serialize.IotMessageSerializerManager; | 14 | import cn.iocoder.yudao.module.iot.gateway.serialize.IotMessageSerializerManager; |
| 19 | -import cn.iocoder.yudao.module.iot.gateway.service.device.IotDeviceService; | ||
| 20 | -import cn.iocoder.yudao.module.iot.gateway.service.device.message.IotDeviceMessageService; | 15 | +import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils; |
| 21 | import io.vertx.core.Vertx; | 16 | import io.vertx.core.Vertx; |
| 22 | import io.vertx.core.datagram.DatagramSocket; | 17 | import io.vertx.core.datagram.DatagramSocket; |
| 23 | import io.vertx.core.datagram.DatagramSocketOptions; | 18 | import io.vertx.core.datagram.DatagramSocketOptions; |
| @@ -25,8 +20,6 @@ import lombok.Getter; | @@ -25,8 +20,6 @@ import lombok.Getter; | ||
| 25 | import lombok.extern.slf4j.Slf4j; | 20 | import lombok.extern.slf4j.Slf4j; |
| 26 | import org.springframework.util.Assert; | 21 | import org.springframework.util.Assert; |
| 27 | 22 | ||
| 28 | -import java.util.List; | ||
| 29 | - | ||
| 30 | /** | 23 | /** |
| 31 | * IoT UDP 协议实现 | 24 | * IoT UDP 协议实现 |
| 32 | * <p> | 25 | * <p> |
| @@ -78,22 +71,11 @@ public class IotUdpProtocol implements IotProtocol { | @@ -78,22 +71,11 @@ public class IotUdpProtocol implements IotProtocol { | ||
| 78 | */ | 71 | */ |
| 79 | private final IotUdpSessionManager sessionManager; | 72 | private final IotUdpSessionManager sessionManager; |
| 80 | 73 | ||
| 81 | - private final IotDeviceService deviceService; | ||
| 82 | - private final IotDeviceMessageService deviceMessageService; | ||
| 83 | - | ||
| 84 | - /** | ||
| 85 | - * 会话清理定时器 ID | ||
| 86 | - */ | ||
| 87 | - // TODO @AI:会话清理,是不是放到 sessionManager 更合适? | ||
| 88 | - private Long cleanTimerId; | ||
| 89 | - | ||
| 90 | public IotUdpProtocol(ProtocolInstanceProperties properties) { | 74 | public IotUdpProtocol(ProtocolInstanceProperties properties) { |
| 91 | IotUdpConfig udpConfig = properties.getUdp(); | 75 | IotUdpConfig udpConfig = properties.getUdp(); |
| 92 | Assert.notNull(udpConfig, "UDP 协议配置(udp)不能为空"); | 76 | Assert.notNull(udpConfig, "UDP 协议配置(udp)不能为空"); |
| 93 | this.properties = properties; | 77 | this.properties = properties; |
| 94 | this.serverId = IotDeviceMessageUtils.generateServerId(properties.getPort()); | 78 | this.serverId = IotDeviceMessageUtils.generateServerId(properties.getPort()); |
| 95 | - this.deviceService = SpringUtil.getBean(IotDeviceService.class); | ||
| 96 | - this.deviceMessageService = SpringUtil.getBean(IotDeviceMessageService.class); | ||
| 97 | 79 | ||
| 98 | // 初始化序列化器 | 80 | // 初始化序列化器 |
| 99 | IotSerializeTypeEnum serializeType = IotSerializeTypeEnum.of(properties.getSerialize()); | 81 | IotSerializeTypeEnum serializeType = IotSerializeTypeEnum.of(properties.getSerialize()); |
| @@ -102,7 +84,7 @@ public class IotUdpProtocol implements IotProtocol { | @@ -102,7 +84,7 @@ public class IotUdpProtocol implements IotProtocol { | ||
| 102 | this.serializer = serializerManager.get(serializeType); | 84 | this.serializer = serializerManager.get(serializeType); |
| 103 | 85 | ||
| 104 | // 初始化会话管理器 | 86 | // 初始化会话管理器 |
| 105 | - this.sessionManager = new IotUdpSessionManager(udpConfig.getMaxSessions()); | 87 | + this.sessionManager = new IotUdpSessionManager(udpConfig.getMaxSessions(), udpConfig.getSessionTimeoutMs()); |
| 106 | 88 | ||
| 107 | // 初始化下行消息订阅者 | 89 | // 初始化下行消息订阅者 |
| 108 | IotMessageBus messageBus = SpringUtil.getBean(IotMessageBus.class); | 90 | IotMessageBus messageBus = SpringUtil.getBean(IotMessageBus.class); |
| @@ -143,24 +125,30 @@ public class IotUdpProtocol implements IotProtocol { | @@ -143,24 +125,30 @@ public class IotUdpProtocol implements IotProtocol { | ||
| 143 | // 1.4 创建上行消息处理器 | 125 | // 1.4 创建上行消息处理器 |
| 144 | IotUdpUpstreamHandler upstreamHandler = new IotUdpUpstreamHandler(serverId, sessionManager, serializer); | 126 | IotUdpUpstreamHandler upstreamHandler = new IotUdpUpstreamHandler(serverId, sessionManager, serializer); |
| 145 | 127 | ||
| 146 | - // 1.5 监听端口 | ||
| 147 | - udpSocket.listen(properties.getPort(), "0.0.0.0", result -> { | ||
| 148 | - if (result.failed()) { | ||
| 149 | - log.error("[start][IoT UDP 协议 {} 启动失败]", getId(), result.cause()); | ||
| 150 | - return; | ||
| 151 | - } | 128 | + // 1.5 启动 UDP 服务器(阻塞式) |
| 129 | + try { | ||
| 130 | + udpSocket.listen(properties.getPort(), "0.0.0.0").result(); | ||
| 152 | // 设置数据包处理器 | 131 | // 设置数据包处理器 |
| 153 | udpSocket.handler(packet -> upstreamHandler.handle(packet, udpSocket)); | 132 | udpSocket.handler(packet -> upstreamHandler.handle(packet, udpSocket)); |
| 154 | running = true; | 133 | running = true; |
| 155 | log.info("[start][IoT UDP 协议 {} 启动成功,端口:{},serverId:{}]", | 134 | log.info("[start][IoT UDP 协议 {} 启动成功,端口:{},serverId:{}]", |
| 156 | getId(), properties.getPort(), serverId); | 135 | getId(), properties.getPort(), serverId); |
| 157 | - // 启动会话清理定时器 | ||
| 158 | - startSessionCleanTimer(udpConfig); | ||
| 159 | 136 | ||
| 160 | // 2. 启动下行消息订阅者 | 137 | // 2. 启动下行消息订阅者 |
| 161 | - // TODO @AI:这里会导致 Thread Thread[vert.x-eventloop-thread-0,5,main] has been blocked for 2992 ms, time limit is 2000 ms | ||
| 162 | this.downstreamSubscriber.start(); | 138 | this.downstreamSubscriber.start(); |
| 163 | - }); | 139 | + } catch (Exception e) { |
| 140 | + log.error("[start][IoT UDP 协议 {} 启动失败]", getId(), e); | ||
| 141 | + // 启动失败时关闭资源 | ||
| 142 | + if (udpSocket != null) { | ||
| 143 | + udpSocket.close(); | ||
| 144 | + udpSocket = null; | ||
| 145 | + } | ||
| 146 | + if (vertx != null) { | ||
| 147 | + vertx.close(); | ||
| 148 | + vertx = null; | ||
| 149 | + } | ||
| 150 | + throw e; | ||
| 151 | + } | ||
| 164 | } | 152 | } |
| 165 | 153 | ||
| 166 | @Override | 154 | @Override |
| @@ -176,13 +164,7 @@ public class IotUdpProtocol implements IotProtocol { | @@ -176,13 +164,7 @@ public class IotUdpProtocol implements IotProtocol { | ||
| 176 | log.error("[stop][IoT UDP 协议 {} 下行消息订阅者停止失败]", getId(), e); | 164 | log.error("[stop][IoT UDP 协议 {} 下行消息订阅者停止失败]", getId(), e); |
| 177 | } | 165 | } |
| 178 | 166 | ||
| 179 | - // 2.1 取消会话清理定时器 | ||
| 180 | - if (cleanTimerId != null) { | ||
| 181 | - vertx.cancelTimer(cleanTimerId); | ||
| 182 | - cleanTimerId = null; | ||
| 183 | - log.info("[stop][IoT UDP 协议 {} 会话清理定时器已取消]", getId()); | ||
| 184 | - } | ||
| 185 | - // 2.2 关闭 UDP Socket | 167 | + // 2.1 关闭 UDP Socket |
| 186 | if (udpSocket != null) { | 168 | if (udpSocket != null) { |
| 187 | try { | 169 | try { |
| 188 | udpSocket.close().result(); | 170 | udpSocket.close().result(); |
| @@ -192,7 +174,7 @@ public class IotUdpProtocol implements IotProtocol { | @@ -192,7 +174,7 @@ public class IotUdpProtocol implements IotProtocol { | ||
| 192 | } | 174 | } |
| 193 | udpSocket = null; | 175 | udpSocket = null; |
| 194 | } | 176 | } |
| 195 | - // 2.3 关闭 Vertx 实例 | 177 | + // 2.2 关闭 Vertx 实例 |
| 196 | if (vertx != null) { | 178 | if (vertx != null) { |
| 197 | try { | 179 | try { |
| 198 | vertx.close().result(); | 180 | vertx.close().result(); |
| @@ -206,54 +188,4 @@ public class IotUdpProtocol implements IotProtocol { | @@ -206,54 +188,4 @@ public class IotUdpProtocol implements IotProtocol { | ||
| 206 | log.info("[stop][IoT UDP 协议 {} 已停止]", getId()); | 188 | log.info("[stop][IoT UDP 协议 {} 已停止]", getId()); |
| 207 | } | 189 | } |
| 208 | 190 | ||
| 209 | - /** | ||
| 210 | - * 启动会话清理定时器 | ||
| 211 | - */ | ||
| 212 | - // TODO @AI:这个放到 | ||
| 213 | - private void startSessionCleanTimer(IotUdpConfig udpConfig) { | ||
| 214 | - cleanTimerId = vertx.setPeriodic(udpConfig.getSessionCleanIntervalMs(), id -> { | ||
| 215 | - try { | ||
| 216 | - // 1. 清理超时的设备会话,并获取离线设备列表 | ||
| 217 | - List<Long> offlineDeviceIds = sessionManager.cleanExpiredSessions(udpConfig.getSessionTimeoutMs()); | ||
| 218 | - | ||
| 219 | - // 2. 为每个离线设备发送离线消息 | ||
| 220 | - for (Long deviceId : offlineDeviceIds) { | ||
| 221 | - sendOfflineMessage(deviceId); | ||
| 222 | - } | ||
| 223 | - if (CollUtil.isNotEmpty(offlineDeviceIds)) { | ||
| 224 | - log.info("[cleanExpiredSessions][本次清理 {} 个超时设备]", offlineDeviceIds.size()); | ||
| 225 | - } | ||
| 226 | - } catch (Exception e) { | ||
| 227 | - log.error("[cleanExpiredSessions][清理超时会话失败]", e); | ||
| 228 | - } | ||
| 229 | - }); | ||
| 230 | - log.info("[startSessionCleanTimer][会话清理定时器启动,间隔:{} ms,超时:{} ms]", | ||
| 231 | - udpConfig.getSessionCleanIntervalMs(), udpConfig.getSessionTimeoutMs()); | ||
| 232 | - } | ||
| 233 | - | ||
| 234 | - /** | ||
| 235 | - * 发送设备离线消息 | ||
| 236 | - * | ||
| 237 | - * @param deviceId 设备 ID | ||
| 238 | - */ | ||
| 239 | - private void sendOfflineMessage(Long deviceId) { | ||
| 240 | - try { | ||
| 241 | - // 获取设备信息 | ||
| 242 | - IotDeviceRespDTO device = deviceService.getDeviceFromCache(deviceId); | ||
| 243 | - if (device == null) { | ||
| 244 | - log.warn("[sendOfflineMessage][设备不存在,设备 ID: {}]", deviceId); | ||
| 245 | - return; | ||
| 246 | - } | ||
| 247 | - | ||
| 248 | - // 发送离线消息 | ||
| 249 | - IotDeviceMessage offlineMessage = IotDeviceMessage.buildStateOffline(); | ||
| 250 | - deviceMessageService.sendDeviceMessage(offlineMessage, device.getProductKey(), | ||
| 251 | - device.getDeviceName(), serverId); | ||
| 252 | - log.info("[sendOfflineMessage][发送离线消息,设备 ID: {},设备名: {}]", | ||
| 253 | - deviceId, device.getDeviceName()); | ||
| 254 | - } catch (Exception e) { | ||
| 255 | - log.error("[sendOfflineMessage][发送离线消息失败,设备 ID: {}]", deviceId, e); | ||
| 256 | - } | ||
| 257 | - } | ||
| 258 | - | ||
| 259 | } | 191 | } |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/udp/handler/downstream/IotUdpDownstreamHandler.java
| @@ -34,7 +34,7 @@ public class IotUdpDownstreamHandler { | @@ -34,7 +34,7 @@ public class IotUdpDownstreamHandler { | ||
| 34 | log.info("[handle][处理下行消息,设备 ID: {},方法: {},消息 ID: {}]", | 34 | log.info("[handle][处理下行消息,设备 ID: {},方法: {},消息 ID: {}]", |
| 35 | message.getDeviceId(), message.getMethod(), message.getId()); | 35 | message.getDeviceId(), message.getMethod(), message.getId()); |
| 36 | // 1. 检查设备会话 | 36 | // 1. 检查设备会话 |
| 37 | - IotUdpSessionManager.SessionInfo sessionInfo = sessionManager.getSessionInfo(message.getDeviceId()); | 37 | + IotUdpSessionManager.SessionInfo sessionInfo = sessionManager.getSession(message.getDeviceId()); |
| 38 | if (sessionInfo == null) { | 38 | if (sessionInfo == null) { |
| 39 | log.warn("[handle][会话信息不存在,设备 ID: {},方法: {},消息 ID: {}]", | 39 | log.warn("[handle][会话信息不存在,设备 ID: {},方法: {},消息 ID: {}]", |
| 40 | message.getDeviceId(), message.getMethod(), message.getId()); | 40 | message.getDeviceId(), message.getMethod(), message.getId()); |
yudao-module-iot/yudao-module-iot-gateway/src/main/resources/application.yaml
| @@ -85,8 +85,7 @@ yudao: | @@ -85,8 +85,7 @@ yudao: | ||
| 85 | serialize: json | 85 | serialize: json |
| 86 | udp: | 86 | udp: |
| 87 | max-sessions: 1000 # 最大会话数 | 87 | max-sessions: 1000 # 最大会话数 |
| 88 | - session-timeout-ms: 60000 # 会话超时时间(毫秒) | ||
| 89 | - session-clean-interval-ms: 30000 # 会话清理间隔(毫秒) | 88 | + session-timeout-ms: 60000 # 会话超时时间(毫秒),基于 Guava Cache 自动过期 |
| 90 | receive-buffer-size: 65536 # 接收缓冲区大小(字节) | 89 | receive-buffer-size: 65536 # 接收缓冲区大小(字节) |
| 91 | send-buffer-size: 65536 # 发送缓冲区大小(字节) | 90 | send-buffer-size: 65536 # 发送缓冲区大小(字节) |
| 92 | 91 |
yudao-module-iot/yudao-module-iot-gateway/src/test/java/cn/iocoder/yudao/module/iot/gateway/protocol/udp/IotDirectDeviceUdpProtocolIntegrationTest.java
| @@ -65,7 +65,7 @@ public class IotDirectDeviceUdpProtocolIntegrationTest { | @@ -65,7 +65,7 @@ public class IotDirectDeviceUdpProtocolIntegrationTest { | ||
| 65 | /** | 65 | /** |
| 66 | * 直连设备 Token:从 {@link #testAuth()} 方法获取后,粘贴到这里 | 66 | * 直连设备 Token:从 {@link #testAuth()} 方法获取后,粘贴到这里 |
| 67 | */ | 67 | */ |
| 68 | - private static final String TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcm9kdWN0S2V5IjoiNGF5bVpnT1RPT0NyREtSVCIsImV4cCI6MTc2OTk0ODYzOCwiZGV2aWNlTmFtZSI6InNtYWxsIn0.TrOJisXhloZ3quLBOAIyowmpq6Syp9PHiEpfj-nQ9xo"; | 68 | + private static final String TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcm9kdWN0S2V5IjoiNGF5bVpnT1RPT0NyREtSVCIsImV4cCI6MTc3MDUyNTA0MywiZGV2aWNlTmFtZSI6InNtYWxsIn0.W9Mo-Oe1ZNLDkINndKieUeW1XhDzhVp0W0zTAwO6hJM"; |
| 69 | 69 | ||
| 70 | // ===================== 认证测试 ===================== | 70 | // ===================== 认证测试 ===================== |
| 71 | 71 | ||
| @@ -120,7 +120,7 @@ public class IotDirectDeviceUdpProtocolIntegrationTest { | @@ -120,7 +120,7 @@ public class IotDirectDeviceUdpProtocolIntegrationTest { | ||
| 120 | */ | 120 | */ |
| 121 | @Test | 121 | @Test |
| 122 | public void testPropertyPost() throws Exception { | 122 | public void testPropertyPost() throws Exception { |
| 123 | - // 1. 构建属性上报消息(UDP 协议:token 放在 params 中) | 123 | + // 1. 构建属性上报消息 |
| 124 | IotDeviceMessage request = IotDeviceMessage.requestOf( | 124 | IotDeviceMessage request = IotDeviceMessage.requestOf( |
| 125 | IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod(), | 125 | IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod(), |
| 126 | withToken(IotDevicePropertyPostReqDTO.of(MapUtil.<String, Object>builder() | 126 | withToken(IotDevicePropertyPostReqDTO.of(MapUtil.<String, Object>builder() |
yudao-module-iot/yudao-module-iot-gateway/src/test/java/cn/iocoder/yudao/module/iot/gateway/protocol/udp/IotGatewaySubDeviceUdpProtocolIntegrationTest.java
| @@ -98,7 +98,7 @@ public class IotGatewaySubDeviceUdpProtocolIntegrationTest { | @@ -98,7 +98,7 @@ public class IotGatewaySubDeviceUdpProtocolIntegrationTest { | ||
| 98 | */ | 98 | */ |
| 99 | @Test | 99 | @Test |
| 100 | public void testPropertyPost() throws Exception { | 100 | public void testPropertyPost() throws Exception { |
| 101 | - // 1. 构建属性上报消息(UDP 协议:token 放在 params 中) | 101 | + // 1. 构建属性上报消息 |
| 102 | IotDeviceMessage request = IotDeviceMessage.requestOf( | 102 | IotDeviceMessage request = IotDeviceMessage.requestOf( |
| 103 | IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod(), | 103 | IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod(), |
| 104 | withToken(IotDevicePropertyPostReqDTO.of(MapUtil.<String, Object>builder() | 104 | withToken(IotDevicePropertyPostReqDTO.of(MapUtil.<String, Object>builder() |
| @@ -120,7 +120,7 @@ public class IotGatewaySubDeviceUdpProtocolIntegrationTest { | @@ -120,7 +120,7 @@ public class IotGatewaySubDeviceUdpProtocolIntegrationTest { | ||
| 120 | */ | 120 | */ |
| 121 | @Test | 121 | @Test |
| 122 | public void testEventPost() throws Exception { | 122 | public void testEventPost() throws Exception { |
| 123 | - // 1. 构建事件上报消息(UDP 协议:token 放在 params 中) | 123 | + // 1. 构建事件上报消息 |
| 124 | IotDeviceMessage request = IotDeviceMessage.requestOf( | 124 | IotDeviceMessage request = IotDeviceMessage.requestOf( |
| 125 | IotDeviceMessageMethodEnum.EVENT_POST.getMethod(), | 125 | IotDeviceMessageMethodEnum.EVENT_POST.getMethod(), |
| 126 | withToken(IotDeviceEventPostReqDTO.of( | 126 | withToken(IotDeviceEventPostReqDTO.of( |