Commit 52b8e66466f009b8fef0fdd7ef8eea15c2037dac
1 parent
b2fef46b
feat:【iot】modbus-tcp 协议接入 100%:完善注释、完善单测
Showing
6 changed files
with
83 additions
and
119 deletions
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/tcp/manager/IotTcpConnectionManager.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.gateway.protocol.tcp.manager; |
| 2 | 2 | |
| 3 | +import io.vertx.core.buffer.Buffer; | |
| 3 | 4 | import io.vertx.core.net.NetSocket; |
| 4 | 5 | import lombok.Data; |
| 5 | 6 | import lombok.extern.slf4j.Slf4j; |
| ... | ... | @@ -119,7 +120,7 @@ public class IotTcpConnectionManager { |
| 119 | 120 | } |
| 120 | 121 | |
| 121 | 122 | try { |
| 122 | - socket.write(io.vertx.core.buffer.Buffer.buffer(data)); | |
| 123 | + socket.write(Buffer.buffer(data)); | |
| 123 | 124 | log.debug("[sendToDevice][发送消息成功,设备 ID: {},数据长度: {} 字节]", deviceId, data.length); |
| 124 | 125 | return true; |
| 125 | 126 | } catch (Exception e) { | ... | ... |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/udp/IotUdpUpstreamProtocol.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.gateway.protocol.udp; |
| 2 | 2 | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceRespDTO; | |
| 3 | 5 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; |
| 4 | 6 | import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils; |
| 5 | 7 | import cn.iocoder.yudao.module.iot.gateway.config.IotGatewayProperties; |
| ... | ... | @@ -15,6 +17,8 @@ import jakarta.annotation.PreDestroy; |
| 15 | 17 | import lombok.Getter; |
| 16 | 18 | import lombok.extern.slf4j.Slf4j; |
| 17 | 19 | |
| 20 | +import java.util.List; | |
| 21 | + | |
| 18 | 22 | /** |
| 19 | 23 | * IoT 网关 UDP 协议:接收设备上行消息 |
| 20 | 24 | * <p> |
| ... | ... | @@ -80,19 +84,18 @@ public class IotUdpUpstreamProtocol { |
| 80 | 84 | |
| 81 | 85 | // 4. 监听端口 |
| 82 | 86 | udpSocket.listen(udpProperties.getPort(), "0.0.0.0", result -> { |
| 83 | - // TODO @AI:if return;简化下;成功才继续往下走; | |
| 84 | - if (result.succeeded()) { | |
| 85 | - // 设置数据包处理器 | |
| 86 | - udpSocket.handler(packet -> upstreamHandler.handle(packet, udpSocket, this)); | |
| 87 | - log.info("[start][IoT 网关 UDP 协议启动成功,端口:{},接收缓冲区:{} 字节,发送缓冲区:{} 字节]", | |
| 88 | - udpProperties.getPort(), udpProperties.getReceiveBufferSize(), | |
| 89 | - udpProperties.getSendBufferSize()); | |
| 90 | - | |
| 91 | - // 5. 启动会话清理定时器 | |
| 92 | - startSessionCleanTimer(); | |
| 93 | - } else { | |
| 87 | + if (result.failed()) { | |
| 94 | 88 | log.error("[start][IoT 网关 UDP 协议启动失败]", result.cause()); |
| 89 | + return; | |
| 95 | 90 | } |
| 91 | + // 设置数据包处理器 | |
| 92 | + udpSocket.handler(packet -> upstreamHandler.handle(packet, udpSocket)); | |
| 93 | + log.info("[start][IoT 网关 UDP 协议启动成功,端口:{},接收缓冲区:{} 字节,发送缓冲区:{} 字节]", | |
| 94 | + udpProperties.getPort(), udpProperties.getReceiveBufferSize(), | |
| 95 | + udpProperties.getSendBufferSize()); | |
| 96 | + | |
| 97 | + // 5. 启动会话清理定时器 | |
| 98 | + startSessionCleanTimer(); | |
| 96 | 99 | }); |
| 97 | 100 | } |
| 98 | 101 | |
| ... | ... | @@ -123,16 +126,14 @@ public class IotUdpUpstreamProtocol { |
| 123 | 126 | cleanTimerId = vertx.setPeriodic(udpProperties.getSessionCleanIntervalMs(), id -> { |
| 124 | 127 | try { |
| 125 | 128 | // 1. 清理超时的设备地址映射,并获取离线设备列表 |
| 126 | - // TODO @AI:兼容 jdk8,不要用 var; | |
| 127 | - var offlineDevices = sessionManager.cleanExpiredMappings(udpProperties.getSessionTimeoutMs()); | |
| 129 | + List<Long> offlineDeviceIds = sessionManager.cleanExpiredMappings(udpProperties.getSessionTimeoutMs()); | |
| 128 | 130 | |
| 129 | 131 | // 2. 为每个离线设备发送离线消息 |
| 130 | - for (var offlineInfo : offlineDevices) { | |
| 131 | - sendOfflineMessage(offlineInfo.getDeviceId()); | |
| 132 | + for (Long deviceId : offlineDeviceIds) { | |
| 133 | + sendOfflineMessage(deviceId); | |
| 132 | 134 | } |
| 133 | - // TODO @AI:CollUtil.isNotEmpty ;简化下 if 判断; | |
| 134 | - if (!offlineDevices.isEmpty()) { | |
| 135 | - log.info("[cleanExpiredMappings][本次清理 {} 个超时设备]", offlineDevices.size()); | |
| 135 | + if (CollUtil.isNotEmpty(offlineDeviceIds)) { | |
| 136 | + log.info("[cleanExpiredMappings][本次清理 {} 个超时设备]", offlineDeviceIds.size()); | |
| 136 | 137 | } |
| 137 | 138 | } catch (Exception e) { |
| 138 | 139 | log.error("[cleanExpiredMappings][清理超时会话失败]", e); |
| ... | ... | @@ -150,7 +151,7 @@ public class IotUdpUpstreamProtocol { |
| 150 | 151 | private void sendOfflineMessage(Long deviceId) { |
| 151 | 152 | try { |
| 152 | 153 | // 获取设备信息 |
| 153 | - var device = deviceService.getDeviceFromCache(deviceId); | |
| 154 | + IotDeviceRespDTO device = deviceService.getDeviceFromCache(deviceId); | |
| 154 | 155 | if (device == null) { |
| 155 | 156 | log.warn("[sendOfflineMessage][设备不存在,设备 ID: {}]", deviceId); |
| 156 | 157 | return; | ... | ... |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/udp/manager/IotUdpSessionManager.java
| ... | ... | @@ -2,12 +2,14 @@ package cn.iocoder.yudao.module.iot.gateway.protocol.udp.manager; |
| 2 | 2 | |
| 3 | 3 | import io.vertx.core.buffer.Buffer; |
| 4 | 4 | import io.vertx.core.datagram.DatagramSocket; |
| 5 | -import lombok.Data; | |
| 6 | 5 | import lombok.extern.slf4j.Slf4j; |
| 7 | 6 | import org.springframework.stereotype.Component; |
| 8 | 7 | |
| 9 | 8 | import java.net.InetSocketAddress; |
| 9 | +import java.time.LocalDateTime; | |
| 10 | +import java.util.ArrayList; | |
| 10 | 11 | import java.util.Iterator; |
| 12 | +import java.util.List; | |
| 11 | 13 | import java.util.Map; |
| 12 | 14 | import java.util.concurrent.ConcurrentHashMap; |
| 13 | 15 | |
| ... | ... | @@ -34,8 +36,7 @@ public class IotUdpSessionManager { |
| 34 | 36 | /** |
| 35 | 37 | * 设备地址 Key -> 最后活跃时间(用于清理) |
| 36 | 38 | */ |
| 37 | - // TODO @AI:是不是尽量使用 LocalDateTime ?统一时间类型 | |
| 38 | - private final Map<String, Long> lastActiveTimeMap = new ConcurrentHashMap<>(); | |
| 39 | + private final Map<String, LocalDateTime> lastActiveTimeMap = new ConcurrentHashMap<>(); | |
| 39 | 40 | |
| 40 | 41 | /** |
| 41 | 42 | * 设备地址 Key -> 设备 ID(反向映射,用于清理时同步) |
| ... | ... | @@ -52,22 +53,11 @@ public class IotUdpSessionManager { |
| 52 | 53 | String addressKey = buildAddressKey(address); |
| 53 | 54 | // 更新设备地址映射 |
| 54 | 55 | deviceAddressMap.put(deviceId, address); |
| 55 | - lastActiveTimeMap.put(addressKey, System.currentTimeMillis()); | |
| 56 | + lastActiveTimeMap.put(addressKey, LocalDateTime.now()); | |
| 56 | 57 | addressDeviceMap.put(addressKey, deviceId); |
| 57 | 58 | log.debug("[updateDeviceAddress][更新设备地址,设备 ID: {},地址: {}]", deviceId, addressKey); |
| 58 | 59 | } |
| 59 | 60 | |
| 60 | - // TODO @AI:是不是用不到?用不掉就删除掉!简化 | |
| 61 | - /** | |
| 62 | - * 获取设备地址(下行消息发送时使用) | |
| 63 | - * | |
| 64 | - * @param deviceId 设备 ID | |
| 65 | - * @return 设备地址,如果不存在返回 null | |
| 66 | - */ | |
| 67 | - public InetSocketAddress getDeviceAddress(Long deviceId) { | |
| 68 | - return deviceAddressMap.get(deviceId); | |
| 69 | - } | |
| 70 | - | |
| 71 | 61 | /** |
| 72 | 62 | * 检查设备是否在线(即是否有地址映射) |
| 73 | 63 | * |
| ... | ... | @@ -126,46 +116,35 @@ public class IotUdpSessionManager { |
| 126 | 116 | * @param timeoutMs 超时时间(毫秒) |
| 127 | 117 | * @return 清理的设备 ID 列表(用于发送离线消息) |
| 128 | 118 | */ |
| 129 | - // TODO @AI:目前暂时用不到 address 字段,是不是只返回 list of deviceId 就行?简化 | |
| 130 | - public java.util.List<DeviceOfflineInfo> cleanExpiredMappings(long timeoutMs) { | |
| 131 | - java.util.List<DeviceOfflineInfo> offlineDevices = new java.util.ArrayList<>(); | |
| 132 | - long now = System.currentTimeMillis(); | |
| 133 | - Iterator<Map.Entry<String, Long>> iterator = lastActiveTimeMap.entrySet().iterator(); | |
| 119 | + public List<Long> cleanExpiredMappings(long timeoutMs) { | |
| 120 | + List<Long> offlineDeviceIds = new ArrayList<>(); | |
| 121 | + LocalDateTime now = LocalDateTime.now(); | |
| 122 | + LocalDateTime expireTime = now.minusNanos(timeoutMs * 1_000_000); | |
| 123 | + Iterator<Map.Entry<String, LocalDateTime>> iterator = lastActiveTimeMap.entrySet().iterator(); | |
| 134 | 124 | while (iterator.hasNext()) { |
| 135 | - Map.Entry<String, Long> entry = iterator.next(); | |
| 136 | - if (now - entry.getValue() > timeoutMs) { | |
| 137 | - String addressKey = entry.getKey(); | |
| 138 | - Long deviceId = addressDeviceMap.remove(addressKey); | |
| 139 | - // TODO @AI:if continue,减少括号层级; | |
| 140 | - if (deviceId != null) { | |
| 141 | - InetSocketAddress address = deviceAddressMap.remove(deviceId); | |
| 142 | - if (address != null) { | |
| 143 | - // 获取设备信息用于发送离线消息 | |
| 144 | - offlineDevices.add(new DeviceOfflineInfo(deviceId, addressKey)); | |
| 145 | - log.info("[cleanExpiredMappings][清理超时设备,设备 ID: {},地址: {},最后活跃时间: {}ms 前]", | |
| 146 | - deviceId, addressKey, now - entry.getValue()); | |
| 147 | - } | |
| 148 | - } | |
| 125 | + // 未过期,跳过 | |
| 126 | + Map.Entry<String, LocalDateTime> entry = iterator.next(); | |
| 127 | + if (entry.getValue().isAfter(expireTime)) { | |
| 128 | + continue; | |
| 129 | + } | |
| 130 | + // 过期处理:记录离线设备 ID | |
| 131 | + String addressKey = entry.getKey(); | |
| 132 | + Long deviceId = addressDeviceMap.remove(addressKey); | |
| 133 | + if (deviceId == null) { | |
| 149 | 134 | iterator.remove(); |
| 135 | + continue; | |
| 150 | 136 | } |
| 137 | + InetSocketAddress address = deviceAddressMap.remove(deviceId); | |
| 138 | + if (address == null) { | |
| 139 | + iterator.remove(); | |
| 140 | + continue; | |
| 141 | + } | |
| 142 | + offlineDeviceIds.add(deviceId); | |
| 143 | + log.debug("[cleanExpiredMappings][清理超时设备,设备 ID: {},地址: {},最后活跃时间: {}]", | |
| 144 | + deviceId, addressKey, entry.getValue()); | |
| 145 | + iterator.remove(); | |
| 151 | 146 | } |
| 152 | - return offlineDevices; | |
| 153 | - } | |
| 154 | - | |
| 155 | - // TODO @AI:是不是用不到?用不掉就删除掉!简化 | |
| 156 | - /** | |
| 157 | - * 移除设备地址映射 | |
| 158 | - * | |
| 159 | - * @param deviceId 设备 ID | |
| 160 | - */ | |
| 161 | - public void removeDeviceAddress(Long deviceId) { | |
| 162 | - InetSocketAddress address = deviceAddressMap.remove(deviceId); | |
| 163 | - if (address != null) { | |
| 164 | - String addressKey = buildAddressKey(address); | |
| 165 | - lastActiveTimeMap.remove(addressKey); | |
| 166 | - addressDeviceMap.remove(addressKey); | |
| 167 | - log.debug("[removeDeviceAddress][移除设备地址,设备 ID: {},地址: {}]", deviceId, addressKey); | |
| 168 | - } | |
| 147 | + return offlineDeviceIds; | |
| 169 | 148 | } |
| 170 | 149 | |
| 171 | 150 | /** |
| ... | ... | @@ -178,27 +157,4 @@ public class IotUdpSessionManager { |
| 178 | 157 | return address.getHostString() + ":" + address.getPort(); |
| 179 | 158 | } |
| 180 | 159 | |
| 181 | - /** | |
| 182 | - * 设备离线信息 | |
| 183 | - */ | |
| 184 | - @Data | |
| 185 | - public static class DeviceOfflineInfo { | |
| 186 | - | |
| 187 | - /** | |
| 188 | - * 设备 ID | |
| 189 | - */ | |
| 190 | - private final Long deviceId; | |
| 191 | - | |
| 192 | - /** | |
| 193 | - * 设备地址 | |
| 194 | - */ | |
| 195 | - private final String address; | |
| 196 | - | |
| 197 | - public DeviceOfflineInfo(Long deviceId, String address) { | |
| 198 | - this.deviceId = deviceId; | |
| 199 | - this.address = address; | |
| 200 | - } | |
| 201 | - | |
| 202 | - } | |
| 203 | - | |
| 204 | 160 | } | ... | ... |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/udp/package-info.java
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/udp/router/IotUdpUpstreamHandler.java
| ... | ... | @@ -26,11 +26,10 @@ import lombok.extern.slf4j.Slf4j; |
| 26 | 26 | import java.net.InetSocketAddress; |
| 27 | 27 | import java.util.Map; |
| 28 | 28 | |
| 29 | -// TODO @AI:注释里,不要出现 CoAP,避免理解成本过高; | |
| 30 | 29 | /** |
| 31 | 30 | * UDP 上行消息处理器 |
| 32 | 31 | * <p> |
| 33 | - * 采用 CoAP 风格的 Token 机制(无状态,每次请求携带 token): | |
| 32 | + * 采用无状态 Token 机制(每次请求携带 token): | |
| 34 | 33 | * 1. 认证请求:设备发送 auth 消息,携带 clientId、username、password |
| 35 | 34 | * 2. 返回 Token:服务端验证后返回 JWT token |
| 36 | 35 | * 3. 后续请求:每次请求在 params 中携带 token |
| ... | ... | @@ -45,6 +44,10 @@ public class IotUdpUpstreamHandler { |
| 45 | 44 | private static final String CODEC_TYPE_BINARY = IotTcpBinaryDeviceMessageCodec.TYPE; |
| 46 | 45 | |
| 47 | 46 | private static final String AUTH_METHOD = "auth"; |
| 47 | + /** | |
| 48 | + * Token 参数 Key | |
| 49 | + */ | |
| 50 | + private static final String PARAM_KEY_TOKEN = "token"; | |
| 48 | 51 | |
| 49 | 52 | private final IotDeviceMessageService deviceMessageService; |
| 50 | 53 | |
| ... | ... | @@ -70,15 +73,13 @@ public class IotUdpUpstreamHandler { |
| 70 | 73 | this.serverId = protocol.getServerId(); |
| 71 | 74 | } |
| 72 | 75 | |
| 73 | - // TODO @AI:protocol 这个参数如果用不到,就删除下; | |
| 74 | 76 | /** |
| 75 | 77 | * 处理 UDP 数据包 |
| 76 | 78 | * |
| 77 | - * @param packet 数据包 | |
| 78 | - * @param socket UDP Socket | |
| 79 | - * @param protocol UDP 协议 | |
| 79 | + * @param packet 数据包 | |
| 80 | + * @param socket UDP Socket | |
| 80 | 81 | */ |
| 81 | - public void handle(DatagramPacket packet, DatagramSocket socket, IotUdpUpstreamProtocol protocol) { | |
| 82 | + public void handle(DatagramPacket packet, DatagramSocket socket) { | |
| 82 | 83 | InetSocketAddress senderAddress = new InetSocketAddress(packet.sender().host(), packet.sender().port()); |
| 83 | 84 | Buffer data = packet.data(); |
| 84 | 85 | log.debug("[handle][收到 UDP 数据包,来源: {},数据长度: {} 字节]", |
| ... | ... | @@ -180,7 +181,7 @@ public class IotUdpUpstreamHandler { |
| 180 | 181 | return; |
| 181 | 182 | } |
| 182 | 183 | |
| 183 | - // 3.1 生成 JWT Token(CoAP 风格) | |
| 184 | + // 3.1 生成 JWT Token(无状态) | |
| 184 | 185 | String token = deviceTokenService.createToken(device.getProductKey(), device.getDeviceName()); |
| 185 | 186 | |
| 186 | 187 | // 3.2 更新设备地址映射(用于下行消息) |
| ... | ... | @@ -212,20 +213,18 @@ public class IotUdpUpstreamHandler { |
| 212 | 213 | InetSocketAddress senderAddress, DatagramSocket socket) { |
| 213 | 214 | String addressKey = sessionManager.buildAddressKey(senderAddress); |
| 214 | 215 | try { |
| 215 | - // TODO @AI:token 需要枚举个 KEY;考虑到是通过 params 传递的话,需要获取到后,从 map 里移除掉,避免影响后续业务逻辑处理; | |
| 216 | - // 1. 从消息中提取 token(CoAP 风格:消息体携带 token) | |
| 216 | + // 1.1 从消息中提取 token(无状态:消息体携带 token) | |
| 217 | 217 | String token = null; |
| 218 | 218 | if (message.getParams() instanceof Map) { |
| 219 | - token = MapUtil.getStr((Map<String, Object>) message.getParams(), "token"); | |
| 219 | + Map<String, Object> paramsMap = (Map<String, Object>) message.getParams(); | |
| 220 | + token = (String) paramsMap.remove(PARAM_KEY_TOKEN); | |
| 220 | 221 | } |
| 221 | - | |
| 222 | 222 | if (StrUtil.isBlank(token)) { |
| 223 | 223 | log.warn("[handleBusinessRequest][缺少 token,来源: {}]", addressKey); |
| 224 | 224 | sendErrorResponse(socket, senderAddress, message.getRequestId(), "请先进行认证", codecType); |
| 225 | 225 | return; |
| 226 | 226 | } |
| 227 | - | |
| 228 | - // 2. 验证 token,获取设备信息 | |
| 227 | + // 1.2 验证 token,获取设备信息 | |
| 229 | 228 | IotDeviceAuthUtils.DeviceInfo deviceInfo = deviceTokenService.verifyToken(token); |
| 230 | 229 | if (deviceInfo == null) { |
| 231 | 230 | log.warn("[handleBusinessRequest][token 无效或已过期,来源: {}]", addressKey); |
| ... | ... | @@ -233,7 +232,7 @@ public class IotUdpUpstreamHandler { |
| 233 | 232 | return; |
| 234 | 233 | } |
| 235 | 234 | |
| 236 | - // 3. 获取设备详细信息 | |
| 235 | + // 2. 获取设备详细信息 | |
| 237 | 236 | IotDeviceRespDTO device = deviceService.getDeviceFromCache(deviceInfo.getProductKey(), |
| 238 | 237 | deviceInfo.getDeviceName()); |
| 239 | 238 | if (device == null) { |
| ... | ... | @@ -243,14 +242,14 @@ public class IotUdpUpstreamHandler { |
| 243 | 242 | return; |
| 244 | 243 | } |
| 245 | 244 | |
| 246 | - // 4. 更新设备地址映射(保持最新) | |
| 245 | + // 3. 更新设备地址映射(保持最新) | |
| 247 | 246 | sessionManager.updateDeviceAddress(device.getId(), senderAddress); |
| 248 | 247 | |
| 249 | - // 5. 发送消息到消息总线 | |
| 248 | + // 4. 发送消息到消息总线 | |
| 250 | 249 | deviceMessageService.sendDeviceMessage(message, device.getProductKey(), |
| 251 | 250 | device.getDeviceName(), serverId); |
| 252 | 251 | |
| 253 | - // 6. 发送成功响应 | |
| 252 | + // 5. 发送成功响应 | |
| 254 | 253 | sendSuccessResponse(socket, senderAddress, message.getRequestId(), "处理成功", codecType); |
| 255 | 254 | log.debug("[handleBusinessRequest][业务消息处理成功,设备 ID: {},方法: {},来源: {}]", |
| 256 | 255 | device.getId(), message.getMethod(), addressKey); | ... | ... |
yudao-module-iot/yudao-module-iot-gateway/src/test/java/cn/iocoder/yudao/module/iot/gateway/protocol/udp/IotUdpProtocolIntegrationTest.java
| ... | ... | @@ -36,13 +36,14 @@ public class IotUdpProtocolIntegrationTest { |
| 36 | 36 | private static final String DEVICE_NAME = "small"; |
| 37 | 37 | private static final String PASSWORD = "509e2b08f7598eb139d276388c600435913ba4c94cd0d50aebc5c0d1855bcb75"; |
| 38 | 38 | |
| 39 | + // TODO @芋艿:1、IotDeviceAuthUtils 调整下拼接;2、password 的生成;3、后续给 http 也整个单测;4、后续给 tcp 也整个单测;5、后续给 mqtt 也整个单测;6、后续给 emqp 也整个单测 | |
| 39 | 40 | private static final String CLIENT_ID = PRODUCT_KEY + "." + DEVICE_NAME; |
| 40 | 41 | private static final String USERNAME = DEVICE_NAME + "&" + PRODUCT_KEY; |
| 41 | 42 | |
| 42 | 43 | /** |
| 43 | 44 | * 设备 Token:从 {@link #testAuth()} 方法获取后,粘贴到这里 |
| 44 | 45 | */ |
| 45 | - private static final String TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcm9kdWN0S2V5IjoiNGF5bVpnT1RPT0NyREtSVCIsImV4cCI6MTc2OTMwNTA1NSwiZGV2aWNlTmFtZSI6InNtYWxsIn0.mf3MEATCn5bp6cXgULunZjs8d00RGUxj96JEz0hMS7k"; | |
| 46 | + private static final String TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcm9kdWN0S2V5IjoiNGF5bVpnT1RPT0NyREtSVCIsImV4cCI6MTc2OTMxMTY0NiwiZGV2aWNlTmFtZSI6InNtYWxsIn0.re6LCaRfKiE9VQTP3w0Brh2ScVIgrvN3H96z_snndoM"; | |
| 46 | 47 | |
| 47 | 48 | /** |
| 48 | 49 | * 认证测试:获取设备 Token |
| ... | ... | @@ -107,12 +108,14 @@ public class IotUdpProtocolIntegrationTest { |
| 107 | 108 | .put("id", IdUtil.fastSimpleUUID()) |
| 108 | 109 | .put("method", IotDeviceMessageMethodEnum.EVENT_POST.getMethod()) |
| 109 | 110 | .put("version", "1.0") |
| 110 | - .put("identifier", "eat") | |
| 111 | 111 | .put("params", MapUtil.builder() |
| 112 | - .put("token", TOKEN) | |
| 113 | - .put("width", 1) | |
| 114 | - .put("height", "2") | |
| 115 | - .put("oneThree", "3") | |
| 112 | + .put("identifier", "eat") | |
| 113 | + .put("value", MapUtil.builder() | |
| 114 | + .put("width", 1) | |
| 115 | + .put("height", "2") | |
| 116 | + .put("oneThree", "3") | |
| 117 | + .build()) | |
| 118 | + .put("time", System.currentTimeMillis()) | |
| 116 | 119 | .build()) |
| 117 | 120 | .build()); |
| 118 | 121 | ... | ... |