Commit 52b8e66466f009b8fef0fdd7ef8eea15c2037dac

Authored by YunaiV
1 parent b2fef46b

feat:【iot】modbus-tcp 协议接入 100%:完善注释、完善单测

yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/tcp/manager/IotTcpConnectionManager.java
1 package cn.iocoder.yudao.module.iot.gateway.protocol.tcp.manager; 1 package cn.iocoder.yudao.module.iot.gateway.protocol.tcp.manager;
2 2
  3 +import io.vertx.core.buffer.Buffer;
3 import io.vertx.core.net.NetSocket; 4 import io.vertx.core.net.NetSocket;
4 import lombok.Data; 5 import lombok.Data;
5 import lombok.extern.slf4j.Slf4j; 6 import lombok.extern.slf4j.Slf4j;
@@ -119,7 +120,7 @@ public class IotTcpConnectionManager { @@ -119,7 +120,7 @@ public class IotTcpConnectionManager {
119 } 120 }
120 121
121 try { 122 try {
122 - socket.write(io.vertx.core.buffer.Buffer.buffer(data)); 123 + socket.write(Buffer.buffer(data));
123 log.debug("[sendToDevice][发送消息成功,设备 ID: {},数据长度: {} 字节]", deviceId, data.length); 124 log.debug("[sendToDevice][发送消息成功,设备 ID: {},数据长度: {} 字节]", deviceId, data.length);
124 return true; 125 return true;
125 } catch (Exception e) { 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 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.iocoder.yudao.module.iot.core.biz.dto.IotDeviceRespDTO;
3 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; 5 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
4 import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils; 6 import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils;
5 import cn.iocoder.yudao.module.iot.gateway.config.IotGatewayProperties; 7 import cn.iocoder.yudao.module.iot.gateway.config.IotGatewayProperties;
@@ -15,6 +17,8 @@ import jakarta.annotation.PreDestroy; @@ -15,6 +17,8 @@ import jakarta.annotation.PreDestroy;
15 import lombok.Getter; 17 import lombok.Getter;
16 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
17 19
  20 +import java.util.List;
  21 +
18 /** 22 /**
19 * IoT 网关 UDP 协议:接收设备上行消息 23 * IoT 网关 UDP 协议:接收设备上行消息
20 * <p> 24 * <p>
@@ -80,19 +84,18 @@ public class IotUdpUpstreamProtocol { @@ -80,19 +84,18 @@ public class IotUdpUpstreamProtocol {
80 84
81 // 4. 监听端口 85 // 4. 监听端口
82 udpSocket.listen(udpProperties.getPort(), "0.0.0.0", result -> { 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 log.error("[start][IoT 网关 UDP 协议启动失败]", result.cause()); 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,16 +126,14 @@ public class IotUdpUpstreamProtocol {
123 cleanTimerId = vertx.setPeriodic(udpProperties.getSessionCleanIntervalMs(), id -> { 126 cleanTimerId = vertx.setPeriodic(udpProperties.getSessionCleanIntervalMs(), id -> {
124 try { 127 try {
125 // 1. 清理超时的设备地址映射,并获取离线设备列表 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 // 2. 为每个离线设备发送离线消息 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 } catch (Exception e) { 138 } catch (Exception e) {
138 log.error("[cleanExpiredMappings][清理超时会话失败]", e); 139 log.error("[cleanExpiredMappings][清理超时会话失败]", e);
@@ -150,7 +151,7 @@ public class IotUdpUpstreamProtocol { @@ -150,7 +151,7 @@ public class IotUdpUpstreamProtocol {
150 private void sendOfflineMessage(Long deviceId) { 151 private void sendOfflineMessage(Long deviceId) {
151 try { 152 try {
152 // 获取设备信息 153 // 获取设备信息
153 - var device = deviceService.getDeviceFromCache(deviceId); 154 + IotDeviceRespDTO device = deviceService.getDeviceFromCache(deviceId);
154 if (device == null) { 155 if (device == null) {
155 log.warn("[sendOfflineMessage][设备不存在,设备 ID: {}]", deviceId); 156 log.warn("[sendOfflineMessage][设备不存在,设备 ID: {}]", deviceId);
156 return; 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,12 +2,14 @@ package cn.iocoder.yudao.module.iot.gateway.protocol.udp.manager;
2 2
3 import io.vertx.core.buffer.Buffer; 3 import io.vertx.core.buffer.Buffer;
4 import io.vertx.core.datagram.DatagramSocket; 4 import io.vertx.core.datagram.DatagramSocket;
5 -import lombok.Data;  
6 import lombok.extern.slf4j.Slf4j; 5 import lombok.extern.slf4j.Slf4j;
7 import org.springframework.stereotype.Component; 6 import org.springframework.stereotype.Component;
8 7
9 import java.net.InetSocketAddress; 8 import java.net.InetSocketAddress;
  9 +import java.time.LocalDateTime;
  10 +import java.util.ArrayList;
10 import java.util.Iterator; 11 import java.util.Iterator;
  12 +import java.util.List;
11 import java.util.Map; 13 import java.util.Map;
12 import java.util.concurrent.ConcurrentHashMap; 14 import java.util.concurrent.ConcurrentHashMap;
13 15
@@ -34,8 +36,7 @@ public class IotUdpSessionManager { @@ -34,8 +36,7 @@ public class IotUdpSessionManager {
34 /** 36 /**
35 * 设备地址 Key -> 最后活跃时间(用于清理) 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 * 设备地址 Key -> 设备 ID(反向映射,用于清理时同步) 42 * 设备地址 Key -> 设备 ID(反向映射,用于清理时同步)
@@ -52,22 +53,11 @@ public class IotUdpSessionManager { @@ -52,22 +53,11 @@ public class IotUdpSessionManager {
52 String addressKey = buildAddressKey(address); 53 String addressKey = buildAddressKey(address);
53 // 更新设备地址映射 54 // 更新设备地址映射
54 deviceAddressMap.put(deviceId, address); 55 deviceAddressMap.put(deviceId, address);
55 - lastActiveTimeMap.put(addressKey, System.currentTimeMillis()); 56 + lastActiveTimeMap.put(addressKey, LocalDateTime.now());
56 addressDeviceMap.put(addressKey, deviceId); 57 addressDeviceMap.put(addressKey, deviceId);
57 log.debug("[updateDeviceAddress][更新设备地址,设备 ID: {},地址: {}]", deviceId, addressKey); 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,46 +116,35 @@ public class IotUdpSessionManager {
126 * @param timeoutMs 超时时间(毫秒) 116 * @param timeoutMs 超时时间(毫秒)
127 * @return 清理的设备 ID 列表(用于发送离线消息) 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 while (iterator.hasNext()) { 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 iterator.remove(); 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,27 +157,4 @@ public class IotUdpSessionManager {
178 return address.getHostString() + ":" + address.getPort(); 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
1 -// TODO @AI:完善下注释,参考 mqtt 的 package.json 1 +/**
  2 + * UDP 协议实现包
  3 + * <p>
  4 + * 提供基于 Vert.x DatagramSocket 的 IoT 设备连接和消息处理功能
  5 + */
2 package cn.iocoder.yudao.module.iot.gateway.protocol.udp; 6 package cn.iocoder.yudao.module.iot.gateway.protocol.udp;
3 \ No newline at end of file 7 \ No newline at end of file
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,11 +26,10 @@ import lombok.extern.slf4j.Slf4j;
26 import java.net.InetSocketAddress; 26 import java.net.InetSocketAddress;
27 import java.util.Map; 27 import java.util.Map;
28 28
29 -// TODO @AI:注释里,不要出现 CoAP,避免理解成本过高;  
30 /** 29 /**
31 * UDP 上行消息处理器 30 * UDP 上行消息处理器
32 * <p> 31 * <p>
33 - * 采用 CoAP 风格的 Token 机制(无状态,每次请求携带 token): 32 + * 采用无状态 Token 机制(每次请求携带 token):
34 * 1. 认证请求:设备发送 auth 消息,携带 clientId、username、password 33 * 1. 认证请求:设备发送 auth 消息,携带 clientId、username、password
35 * 2. 返回 Token:服务端验证后返回 JWT token 34 * 2. 返回 Token:服务端验证后返回 JWT token
36 * 3. 后续请求:每次请求在 params 中携带 token 35 * 3. 后续请求:每次请求在 params 中携带 token
@@ -45,6 +44,10 @@ public class IotUdpUpstreamHandler { @@ -45,6 +44,10 @@ public class IotUdpUpstreamHandler {
45 private static final String CODEC_TYPE_BINARY = IotTcpBinaryDeviceMessageCodec.TYPE; 44 private static final String CODEC_TYPE_BINARY = IotTcpBinaryDeviceMessageCodec.TYPE;
46 45
47 private static final String AUTH_METHOD = "auth"; 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 private final IotDeviceMessageService deviceMessageService; 52 private final IotDeviceMessageService deviceMessageService;
50 53
@@ -70,15 +73,13 @@ public class IotUdpUpstreamHandler { @@ -70,15 +73,13 @@ public class IotUdpUpstreamHandler {
70 this.serverId = protocol.getServerId(); 73 this.serverId = protocol.getServerId();
71 } 74 }
72 75
73 - // TODO @AI:protocol 这个参数如果用不到,就删除下;  
74 /** 76 /**
75 * 处理 UDP 数据包 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 InetSocketAddress senderAddress = new InetSocketAddress(packet.sender().host(), packet.sender().port()); 83 InetSocketAddress senderAddress = new InetSocketAddress(packet.sender().host(), packet.sender().port());
83 Buffer data = packet.data(); 84 Buffer data = packet.data();
84 log.debug("[handle][收到 UDP 数据包,来源: {},数据长度: {} 字节]", 85 log.debug("[handle][收到 UDP 数据包,来源: {},数据长度: {} 字节]",
@@ -180,7 +181,7 @@ public class IotUdpUpstreamHandler { @@ -180,7 +181,7 @@ public class IotUdpUpstreamHandler {
180 return; 181 return;
181 } 182 }
182 183
183 - // 3.1 生成 JWT Token(CoAP 风格) 184 + // 3.1 生成 JWT Token(无状态)
184 String token = deviceTokenService.createToken(device.getProductKey(), device.getDeviceName()); 185 String token = deviceTokenService.createToken(device.getProductKey(), device.getDeviceName());
185 186
186 // 3.2 更新设备地址映射(用于下行消息) 187 // 3.2 更新设备地址映射(用于下行消息)
@@ -212,20 +213,18 @@ public class IotUdpUpstreamHandler { @@ -212,20 +213,18 @@ public class IotUdpUpstreamHandler {
212 InetSocketAddress senderAddress, DatagramSocket socket) { 213 InetSocketAddress senderAddress, DatagramSocket socket) {
213 String addressKey = sessionManager.buildAddressKey(senderAddress); 214 String addressKey = sessionManager.buildAddressKey(senderAddress);
214 try { 215 try {
215 - // TODO @AI:token 需要枚举个 KEY;考虑到是通过 params 传递的话,需要获取到后,从 map 里移除掉,避免影响后续业务逻辑处理;  
216 - // 1. 从消息中提取 token(CoAP 风格:消息体携带 token) 216 + // 1.1 从消息中提取 token(无状态:消息体携带 token)
217 String token = null; 217 String token = null;
218 if (message.getParams() instanceof Map) { 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 if (StrUtil.isBlank(token)) { 222 if (StrUtil.isBlank(token)) {
223 log.warn("[handleBusinessRequest][缺少 token,来源: {}]", addressKey); 223 log.warn("[handleBusinessRequest][缺少 token,来源: {}]", addressKey);
224 sendErrorResponse(socket, senderAddress, message.getRequestId(), "请先进行认证", codecType); 224 sendErrorResponse(socket, senderAddress, message.getRequestId(), "请先进行认证", codecType);
225 return; 225 return;
226 } 226 }
227 -  
228 - // 2. 验证 token,获取设备信息 227 + // 1.2 验证 token,获取设备信息
229 IotDeviceAuthUtils.DeviceInfo deviceInfo = deviceTokenService.verifyToken(token); 228 IotDeviceAuthUtils.DeviceInfo deviceInfo = deviceTokenService.verifyToken(token);
230 if (deviceInfo == null) { 229 if (deviceInfo == null) {
231 log.warn("[handleBusinessRequest][token 无效或已过期,来源: {}]", addressKey); 230 log.warn("[handleBusinessRequest][token 无效或已过期,来源: {}]", addressKey);
@@ -233,7 +232,7 @@ public class IotUdpUpstreamHandler { @@ -233,7 +232,7 @@ public class IotUdpUpstreamHandler {
233 return; 232 return;
234 } 233 }
235 234
236 - // 3. 获取设备详细信息 235 + // 2. 获取设备详细信息
237 IotDeviceRespDTO device = deviceService.getDeviceFromCache(deviceInfo.getProductKey(), 236 IotDeviceRespDTO device = deviceService.getDeviceFromCache(deviceInfo.getProductKey(),
238 deviceInfo.getDeviceName()); 237 deviceInfo.getDeviceName());
239 if (device == null) { 238 if (device == null) {
@@ -243,14 +242,14 @@ public class IotUdpUpstreamHandler { @@ -243,14 +242,14 @@ public class IotUdpUpstreamHandler {
243 return; 242 return;
244 } 243 }
245 244
246 - // 4. 更新设备地址映射(保持最新) 245 + // 3. 更新设备地址映射(保持最新)
247 sessionManager.updateDeviceAddress(device.getId(), senderAddress); 246 sessionManager.updateDeviceAddress(device.getId(), senderAddress);
248 247
249 - // 5. 发送消息到消息总线 248 + // 4. 发送消息到消息总线
250 deviceMessageService.sendDeviceMessage(message, device.getProductKey(), 249 deviceMessageService.sendDeviceMessage(message, device.getProductKey(),
251 device.getDeviceName(), serverId); 250 device.getDeviceName(), serverId);
252 251
253 - // 6. 发送成功响应 252 + // 5. 发送成功响应
254 sendSuccessResponse(socket, senderAddress, message.getRequestId(), "处理成功", codecType); 253 sendSuccessResponse(socket, senderAddress, message.getRequestId(), "处理成功", codecType);
255 log.debug("[handleBusinessRequest][业务消息处理成功,设备 ID: {},方法: {},来源: {}]", 254 log.debug("[handleBusinessRequest][业务消息处理成功,设备 ID: {},方法: {},来源: {}]",
256 device.getId(), message.getMethod(), addressKey); 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,13 +36,14 @@ public class IotUdpProtocolIntegrationTest {
36 private static final String DEVICE_NAME = "small"; 36 private static final String DEVICE_NAME = "small";
37 private static final String PASSWORD = "509e2b08f7598eb139d276388c600435913ba4c94cd0d50aebc5c0d1855bcb75"; 37 private static final String PASSWORD = "509e2b08f7598eb139d276388c600435913ba4c94cd0d50aebc5c0d1855bcb75";
38 38
  39 + // TODO @芋艿:1、IotDeviceAuthUtils 调整下拼接;2、password 的生成;3、后续给 http 也整个单测;4、后续给 tcp 也整个单测;5、后续给 mqtt 也整个单测;6、后续给 emqp 也整个单测
39 private static final String CLIENT_ID = PRODUCT_KEY + "." + DEVICE_NAME; 40 private static final String CLIENT_ID = PRODUCT_KEY + "." + DEVICE_NAME;
40 private static final String USERNAME = DEVICE_NAME + "&" + PRODUCT_KEY; 41 private static final String USERNAME = DEVICE_NAME + "&" + PRODUCT_KEY;
41 42
42 /** 43 /**
43 * 设备 Token:从 {@link #testAuth()} 方法获取后,粘贴到这里 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 * 认证测试:获取设备 Token 49 * 认证测试:获取设备 Token
@@ -107,12 +108,14 @@ public class IotUdpProtocolIntegrationTest { @@ -107,12 +108,14 @@ public class IotUdpProtocolIntegrationTest {
107 .put("id", IdUtil.fastSimpleUUID()) 108 .put("id", IdUtil.fastSimpleUUID())
108 .put("method", IotDeviceMessageMethodEnum.EVENT_POST.getMethod()) 109 .put("method", IotDeviceMessageMethodEnum.EVENT_POST.getMethod())
109 .put("version", "1.0") 110 .put("version", "1.0")
110 - .put("identifier", "eat")  
111 .put("params", MapUtil.builder() 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 .build()) 119 .build())
117 .build()); 120 .build());
118 121