Commit d01a6e215894a4d27130528131ae9e646ce3a4c3

Authored by YunaiV
1 parent 867ec8c0

fix(iot): 修复多协议处理器的空值校验和错误码问题

1. HTTP: 增加请求体空值保护,避免 NPE 导致 500
2. HTTP: 修复 Vertx 资源泄漏,改为 Spring 管理生命周期
3. UDP/MQTT/WS/TCP: 增加动态注册参数必填字段校验
4. EMQX: 事件接口解析失败时返回空响应体,符合 Webhook 规范
5. CoAP: method 不匹配返回 4.00 而非 5.00
Showing 12 changed files with 117 additions and 105 deletions
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/config/IotGatewayConfiguration.java
@@ -44,9 +44,15 @@ public class IotGatewayConfiguration { @@ -44,9 +44,15 @@ public class IotGatewayConfiguration {
44 @Slf4j 44 @Slf4j
45 public static class HttpProtocolConfiguration { 45 public static class HttpProtocolConfiguration {
46 46
  47 + @Bean(name = "httpVertx", destroyMethod = "close")
  48 + public Vertx httpVertx() {
  49 + return Vertx.vertx();
  50 + }
  51 +
47 @Bean 52 @Bean
48 - public IotHttpUpstreamProtocol iotHttpUpstreamProtocol(IotGatewayProperties gatewayProperties) {  
49 - return new IotHttpUpstreamProtocol(gatewayProperties.getProtocol().getHttp()); 53 + public IotHttpUpstreamProtocol iotHttpUpstreamProtocol(IotGatewayProperties gatewayProperties,
  54 + @Qualifier("httpVertx") Vertx httpVertx) {
  55 + return new IotHttpUpstreamProtocol(gatewayProperties.getProtocol().getHttp(), httpVertx);
50 } 56 }
51 57
52 @Bean 58 @Bean
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/coap/router/IotCoapUpstreamHandler.java
1 package cn.iocoder.yudao.module.iot.gateway.protocol.coap.router; 1 package cn.iocoder.yudao.module.iot.gateway.protocol.coap.router;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.hutool.core.lang.Assert;  
5 import cn.hutool.core.map.MapUtil; 4 import cn.hutool.core.map.MapUtil;
6 import cn.hutool.core.text.StrPool; 5 import cn.hutool.core.text.StrPool;
7 import cn.hutool.core.util.ArrayUtil; 6 import cn.hutool.core.util.ArrayUtil;
@@ -93,7 +92,10 @@ public class IotCoapUpstreamHandler { @@ -93,7 +92,10 @@ public class IotCoapUpstreamHandler {
93 92
94 // 2.2 解码消息 93 // 2.2 解码消息
95 IotDeviceMessage message = deviceMessageService.decodeDeviceMessage(payload, productKey, deviceName); 94 IotDeviceMessage message = deviceMessageService.decodeDeviceMessage(payload, productKey, deviceName);
96 - Assert.equals(method, message.getMethod(), "method 不匹配"); 95 + if (ObjUtil.notEqual(method, message.getMethod())) {
  96 + IotCoapUtils.respondError(exchange, CoAP.ResponseCode.BAD_REQUEST, "method 不匹配");
  97 + return;
  98 + }
97 // 2.3 发送消息到消息总线 99 // 2.3 发送消息到消息总线
98 deviceMessageService.sendDeviceMessage(message, productKey, deviceName, protocol.getServerId()); 100 deviceMessageService.sendDeviceMessage(message, productKey, deviceName, protocol.getServerId());
99 101
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/emqx/router/IotEmqxAuthEventHandler.java
@@ -104,7 +104,7 @@ public class IotEmqxAuthEventHandler { @@ -104,7 +104,7 @@ public class IotEmqxAuthEventHandler {
104 JsonObject body = null; 104 JsonObject body = null;
105 try { 105 try {
106 // 1. 解析请求体 106 // 1. 解析请求体
107 - body = parseRequestBody(context); 107 + body = parseEventRequestBody(context);
108 if (body == null) { 108 if (body == null) {
109 return; 109 return;
110 } 110 }
@@ -153,7 +153,9 @@ public class IotEmqxAuthEventHandler { @@ -153,7 +153,9 @@ public class IotEmqxAuthEventHandler {
153 } 153 }
154 154
155 /** 155 /**
156 - * 解析请求体 156 + * 解析认证接口请求体
  157 + * <p>
  158 + * 认证接口解析失败时返回 JSON 格式响应(包含 result 字段)
157 * 159 *
158 * @param context 路由上下文 160 * @param context 路由上下文
159 * @return 请求体JSON对象,解析失败时返回null 161 * @return 请求体JSON对象,解析失败时返回null
@@ -175,6 +177,30 @@ public class IotEmqxAuthEventHandler { @@ -175,6 +177,30 @@ public class IotEmqxAuthEventHandler {
175 } 177 }
176 178
177 /** 179 /**
  180 + * 解析事件接口请求体
  181 + * <p>
  182 + * 事件接口解析失败时仅返回 200 状态码,无响应体(符合 EMQX Webhook 规范)
  183 + *
  184 + * @param context 路由上下文
  185 + * @return 请求体JSON对象,解析失败时返回null
  186 + */
  187 + private JsonObject parseEventRequestBody(RoutingContext context) {
  188 + try {
  189 + JsonObject body = context.body().asJsonObject();
  190 + if (body == null) {
  191 + log.info("[parseEventRequestBody][请求体为空]");
  192 + context.response().setStatusCode(SUCCESS_STATUS_CODE).end();
  193 + return null;
  194 + }
  195 + return body;
  196 + } catch (Exception e) {
  197 + log.error("[parseEventRequestBody][body({}) 解析请求体失败]", context.body().asString(), e);
  198 + context.response().setStatusCode(SUCCESS_STATUS_CODE).end();
  199 + return null;
  200 + }
  201 + }
  202 +
  203 + /**
178 * 执行设备认证 204 * 执行设备认证
179 * 205 *
180 * @param clientId 客户端ID 206 * @param clientId 客户端ID
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/IotHttpUpstreamProtocol.java
@@ -6,7 +6,6 @@ import cn.iocoder.yudao.module.iot.gateway.protocol.http.router.IotHttpAuthHandl @@ -6,7 +6,6 @@ import cn.iocoder.yudao.module.iot.gateway.protocol.http.router.IotHttpAuthHandl
6 import cn.iocoder.yudao.module.iot.gateway.protocol.http.router.IotHttpRegisterHandler; 6 import cn.iocoder.yudao.module.iot.gateway.protocol.http.router.IotHttpRegisterHandler;
7 import cn.iocoder.yudao.module.iot.gateway.protocol.http.router.IotHttpRegisterSubHandler; 7 import cn.iocoder.yudao.module.iot.gateway.protocol.http.router.IotHttpRegisterSubHandler;
8 import cn.iocoder.yudao.module.iot.gateway.protocol.http.router.IotHttpUpstreamHandler; 8 import cn.iocoder.yudao.module.iot.gateway.protocol.http.router.IotHttpUpstreamHandler;
9 -import io.vertx.core.AbstractVerticle;  
10 import io.vertx.core.Vertx; 9 import io.vertx.core.Vertx;
11 import io.vertx.core.http.HttpServer; 10 import io.vertx.core.http.HttpServer;
12 import io.vertx.core.http.HttpServerOptions; 11 import io.vertx.core.http.HttpServerOptions;
@@ -24,25 +23,26 @@ import lombok.extern.slf4j.Slf4j; @@ -24,25 +23,26 @@ import lombok.extern.slf4j.Slf4j;
24 * @author 芋道源码 23 * @author 芋道源码
25 */ 24 */
26 @Slf4j 25 @Slf4j
27 -public class IotHttpUpstreamProtocol extends AbstractVerticle { 26 +public class IotHttpUpstreamProtocol {
28 27
29 private final IotGatewayProperties.HttpProperties httpProperties; 28 private final IotGatewayProperties.HttpProperties httpProperties;
30 29
  30 + private final Vertx vertx;
  31 +
31 private HttpServer httpServer; 32 private HttpServer httpServer;
32 33
33 @Getter 34 @Getter
34 private final String serverId; 35 private final String serverId;
35 36
36 - public IotHttpUpstreamProtocol(IotGatewayProperties.HttpProperties httpProperties) { 37 + public IotHttpUpstreamProtocol(IotGatewayProperties.HttpProperties httpProperties, Vertx vertx) {
37 this.httpProperties = httpProperties; 38 this.httpProperties = httpProperties;
  39 + this.vertx = vertx;
38 this.serverId = IotDeviceMessageUtils.generateServerId(httpProperties.getServerPort()); 40 this.serverId = IotDeviceMessageUtils.generateServerId(httpProperties.getServerPort());
39 } 41 }
40 42
41 - @Override  
42 @PostConstruct 43 @PostConstruct
43 public void start() { 44 public void start() {
44 // 创建路由 45 // 创建路由
45 - Vertx vertx = Vertx.vertx();  
46 Router router = Router.router(vertx); 46 Router router = Router.router(vertx);
47 router.route().handler(BodyHandler.create()); 47 router.route().handler(BodyHandler.create());
48 48
@@ -76,7 +76,6 @@ public class IotHttpUpstreamProtocol extends AbstractVerticle { @@ -76,7 +76,6 @@ public class IotHttpUpstreamProtocol extends AbstractVerticle {
76 } 76 }
77 } 77 }
78 78
79 - @Override  
80 @PreDestroy 79 @PreDestroy
81 public void stop() { 80 public void stop() {
82 if (httpServer != null) { 81 if (httpServer != null) {
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/router/IotHttpAuthHandler.java
@@ -51,6 +51,9 @@ public class IotHttpAuthHandler extends IotHttpAbstractHandler { @@ -51,6 +51,9 @@ public class IotHttpAuthHandler extends IotHttpAbstractHandler {
51 public CommonResult<Object> handle0(RoutingContext context) { 51 public CommonResult<Object> handle0(RoutingContext context) {
52 // 1. 解析参数 52 // 1. 解析参数
53 JsonObject body = context.body().asJsonObject(); 53 JsonObject body = context.body().asJsonObject();
  54 + if (body == null) {
  55 + throw invalidParamException("请求体不能为空");
  56 + }
54 String clientId = body.getString("clientId"); 57 String clientId = body.getString("clientId");
55 if (StrUtil.isEmpty(clientId)) { 58 if (StrUtil.isEmpty(clientId)) {
56 throw invalidParamException("clientId 不能为空"); 59 throw invalidParamException("clientId 不能为空");
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/router/IotHttpRegisterHandler.java
@@ -34,6 +34,9 @@ public class IotHttpRegisterHandler extends IotHttpAbstractHandler { @@ -34,6 +34,9 @@ public class IotHttpRegisterHandler extends IotHttpAbstractHandler {
34 public CommonResult<Object> handle0(RoutingContext context) { 34 public CommonResult<Object> handle0(RoutingContext context) {
35 // 1. 解析参数 35 // 1. 解析参数
36 JsonObject body = context.body().asJsonObject(); 36 JsonObject body = context.body().asJsonObject();
  37 + if (body == null) {
  38 + throw invalidParamException("请求体不能为空");
  39 + }
37 String productKey = body.getString("productKey"); 40 String productKey = body.getString("productKey");
38 if (StrUtil.isEmpty(productKey)) { 41 if (StrUtil.isEmpty(productKey)) {
39 throw invalidParamException("productKey 不能为空"); 42 throw invalidParamException("productKey 不能为空");
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/router/IotHttpRegisterSubHandler.java
@@ -11,6 +11,7 @@ import io.vertx.ext.web.RoutingContext; @@ -11,6 +11,7 @@ import io.vertx.ext.web.RoutingContext;
11 11
12 import java.util.List; 12 import java.util.List;
13 13
  14 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException;
14 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 15 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
15 16
16 /** 17 /**
@@ -44,6 +45,12 @@ public class IotHttpRegisterSubHandler extends IotHttpAbstractHandler { @@ -44,6 +45,12 @@ public class IotHttpRegisterSubHandler extends IotHttpAbstractHandler {
44 45
45 // 2. 解析子设备列表 46 // 2. 解析子设备列表
46 JsonObject body = context.body().asJsonObject(); 47 JsonObject body = context.body().asJsonObject();
  48 + if (body == null) {
  49 + throw invalidParamException("请求体不能为空");
  50 + }
  51 + if (body.getJsonArray("params") == null) {
  52 + throw invalidParamException("params 不能为空");
  53 + }
47 List<cn.iocoder.yudao.module.iot.core.topic.auth.IotSubDeviceRegisterReqDTO> subDevices = JsonUtils.parseArray( 54 List<cn.iocoder.yudao.module.iot.core.topic.auth.IotSubDeviceRegisterReqDTO> subDevices = JsonUtils.parseArray(
48 body.getJsonArray("params").toString(), cn.iocoder.yudao.module.iot.core.topic.auth.IotSubDeviceRegisterReqDTO.class); 55 body.getJsonArray("params").toString(), cn.iocoder.yudao.module.iot.core.topic.auth.IotSubDeviceRegisterReqDTO.class);
49 56
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/http/router/IotHttpUpstreamHandler.java
@@ -12,6 +12,8 @@ import io.vertx.ext.web.RoutingContext; @@ -12,6 +12,8 @@ import io.vertx.ext.web.RoutingContext;
12 import lombok.RequiredArgsConstructor; 12 import lombok.RequiredArgsConstructor;
13 import lombok.extern.slf4j.Slf4j; 13 import lombok.extern.slf4j.Slf4j;
14 14
  15 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException;
  16 +
15 /** 17 /**
16 * IoT 网关 HTTP 协议的【上行】处理器 18 * IoT 网关 HTTP 协议的【上行】处理器
17 * 19 *
@@ -40,6 +42,9 @@ public class IotHttpUpstreamHandler extends IotHttpAbstractHandler { @@ -40,6 +42,9 @@ public class IotHttpUpstreamHandler extends IotHttpAbstractHandler {
40 String method = context.pathParam("*").replaceAll(StrPool.SLASH, StrPool.DOT); 42 String method = context.pathParam("*").replaceAll(StrPool.SLASH, StrPool.DOT);
41 43
42 // 2.1 解析消息 44 // 2.1 解析消息
  45 + if (context.body().buffer() == null) {
  46 + throw invalidParamException("请求体不能为空");
  47 + }
43 byte[] bytes = context.body().buffer().getBytes(); 48 byte[] bytes = context.body().buffer().getBytes();
44 IotDeviceMessage message = deviceMessageService.decodeDeviceMessage(bytes, 49 IotDeviceMessage message = deviceMessageService.decodeDeviceMessage(bytes,
45 productKey, deviceName); 50 productKey, deviceName);
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/mqtt/router/IotMqttUpstreamHandler.java
@@ -330,15 +330,15 @@ public class IotMqttUpstreamHandler { @@ -330,15 +330,15 @@ public class IotMqttUpstreamHandler {
330 String clientId = endpoint.clientIdentifier(); 330 String clientId = endpoint.clientIdentifier();
331 try { 331 try {
332 // 1. 解析注册参数 332 // 1. 解析注册参数
333 - IotDeviceRegisterReqDTO registerParams = parseRegisterParams(message.getParams());  
334 - if (registerParams == null) { 333 + IotDeviceRegisterReqDTO params = parseRegisterParams(message.getParams());
  334 + if (params == null) {
335 log.warn("[handleRegisterRequest][注册参数解析失败,客户端 ID: {}]", clientId); 335 log.warn("[handleRegisterRequest][注册参数解析失败,客户端 ID: {}]", clientId);
336 sendRegisterErrorResponse(endpoint, productKey, deviceName, message.getRequestId(), "注册参数不完整"); 336 sendRegisterErrorResponse(endpoint, productKey, deviceName, message.getRequestId(), "注册参数不完整");
337 return; 337 return;
338 } 338 }
339 339
340 // 2. 调用动态注册 API 340 // 2. 调用动态注册 API
341 - CommonResult<IotDeviceRegisterRespDTO> result = deviceApi.registerDevice(registerParams); 341 + CommonResult<IotDeviceRegisterRespDTO> result = deviceApi.registerDevice(params);
342 if (result.isError()) { 342 if (result.isError()) {
343 log.warn("[handleRegisterRequest][注册失败,客户端 ID: {},错误: {}]", clientId, result.getMsg()); 343 log.warn("[handleRegisterRequest][注册失败,客户端 ID: {},错误: {}]", clientId, result.getMsg());
344 sendRegisterErrorResponse(endpoint, productKey, deviceName, message.getRequestId(), result.getMsg()); 344 sendRegisterErrorResponse(endpoint, productKey, deviceName, message.getRequestId(), result.getMsg());
@@ -348,7 +348,7 @@ public class IotMqttUpstreamHandler { @@ -348,7 +348,7 @@ public class IotMqttUpstreamHandler {
348 // 3. 发送成功响应(包含 deviceSecret) 348 // 3. 发送成功响应(包含 deviceSecret)
349 sendRegisterSuccessResponse(endpoint, productKey, deviceName, message.getRequestId(), result.getData()); 349 sendRegisterSuccessResponse(endpoint, productKey, deviceName, message.getRequestId(), result.getData());
350 log.info("[handleRegisterRequest][注册成功,设备名: {},客户端 ID: {}]", 350 log.info("[handleRegisterRequest][注册成功,设备名: {},客户端 ID: {}]",
351 - registerParams.getDeviceName(), clientId); 351 + params.getDeviceName(), clientId);
352 } catch (Exception e) { 352 } catch (Exception e) {
353 log.error("[handleRegisterRequest][注册处理异常,客户端 ID: {}]", clientId, e); 353 log.error("[handleRegisterRequest][注册处理异常,客户端 ID: {}]", clientId, e);
354 sendRegisterErrorResponse(endpoint, productKey, deviceName, message.getRequestId(), "注册处理异常"); 354 sendRegisterErrorResponse(endpoint, productKey, deviceName, message.getRequestId(), "注册处理异常");
@@ -361,36 +361,27 @@ public class IotMqttUpstreamHandler { @@ -361,36 +361,27 @@ public class IotMqttUpstreamHandler {
361 * @param params 参数对象(通常为 Map 类型) 361 * @param params 参数对象(通常为 Map 类型)
362 * @return 注册参数 DTO,解析失败时返回 null 362 * @return 注册参数 DTO,解析失败时返回 null
363 */ 363 */
364 - @SuppressWarnings("unchecked") 364 + @SuppressWarnings({"unchecked", "DuplicatedCode"})
365 private IotDeviceRegisterReqDTO parseRegisterParams(Object params) { 365 private IotDeviceRegisterReqDTO parseRegisterParams(Object params) {
366 if (params == null) { 366 if (params == null) {
367 return null; 367 return null;
368 } 368 }
369 -  
370 try { 369 try {
371 // 参数默认为 Map 类型,直接转换 370 // 参数默认为 Map 类型,直接转换
372 if (params instanceof Map) { 371 if (params instanceof Map) {
373 Map<String, Object> paramMap = (Map<String, Object>) params; 372 Map<String, Object> paramMap = (Map<String, Object>) params;
374 - String productKey = MapUtil.getStr(paramMap, "productKey");  
375 - String deviceName = MapUtil.getStr(paramMap, "deviceName");  
376 - String productSecret = MapUtil.getStr(paramMap, "productSecret");  
377 - if (StrUtil.hasBlank(productKey, deviceName, productSecret)) {  
378 - return null;  
379 - }  
380 return new IotDeviceRegisterReqDTO() 373 return new IotDeviceRegisterReqDTO()
381 - .setProductKey(productKey)  
382 - .setDeviceName(deviceName)  
383 - .setProductSecret(productSecret); 374 + .setProductKey(MapUtil.getStr(paramMap, "productKey"))
  375 + .setDeviceName(MapUtil.getStr(paramMap, "deviceName"))
  376 + .setProductSecret(MapUtil.getStr(paramMap, "productSecret"));
384 } 377 }
385 -  
386 // 如果已经是目标类型,直接返回 378 // 如果已经是目标类型,直接返回
387 if (params instanceof IotDeviceRegisterReqDTO) { 379 if (params instanceof IotDeviceRegisterReqDTO) {
388 return (IotDeviceRegisterReqDTO) params; 380 return (IotDeviceRegisterReqDTO) params;
389 } 381 }
390 382
391 // 其他情况尝试 JSON 转换 383 // 其他情况尝试 JSON 转换
392 - String jsonStr = JsonUtils.toJsonString(params);  
393 - return JsonUtils.parseObject(jsonStr, IotDeviceRegisterReqDTO.class); 384 + return JsonUtils.convertObject(params, IotDeviceRegisterReqDTO.class);
394 } catch (Exception e) { 385 } catch (Exception e) {
395 log.error("[parseRegisterParams][解析注册参数({})失败]", params, e); 386 log.error("[parseRegisterParams][解析注册参数({})失败]", params, e);
396 return null; 387 return null;
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/tcp/router/IotTcpUpstreamHandler.java
@@ -12,9 +12,9 @@ import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceAuthReqDTO; @@ -12,9 +12,9 @@ import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceAuthReqDTO;
12 import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceRespDTO; 12 import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceRespDTO;
13 import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum; 13 import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum;
14 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; 14 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
  15 +import cn.iocoder.yudao.module.iot.core.topic.IotDeviceIdentity;
15 import cn.iocoder.yudao.module.iot.core.topic.auth.IotDeviceRegisterReqDTO; 16 import cn.iocoder.yudao.module.iot.core.topic.auth.IotDeviceRegisterReqDTO;
16 import cn.iocoder.yudao.module.iot.core.topic.auth.IotDeviceRegisterRespDTO; 17 import cn.iocoder.yudao.module.iot.core.topic.auth.IotDeviceRegisterRespDTO;
17 -import cn.iocoder.yudao.module.iot.core.topic.IotDeviceIdentity;  
18 import cn.iocoder.yudao.module.iot.core.util.IotDeviceAuthUtils; 18 import cn.iocoder.yudao.module.iot.core.util.IotDeviceAuthUtils;
19 import cn.iocoder.yudao.module.iot.gateway.codec.tcp.IotTcpBinaryDeviceMessageCodec; 19 import cn.iocoder.yudao.module.iot.gateway.codec.tcp.IotTcpBinaryDeviceMessageCodec;
20 import cn.iocoder.yudao.module.iot.gateway.codec.tcp.IotTcpJsonDeviceMessageCodec; 20 import cn.iocoder.yudao.module.iot.gateway.codec.tcp.IotTcpJsonDeviceMessageCodec;
@@ -27,6 +27,8 @@ import io.vertx.core.buffer.Buffer; @@ -27,6 +27,8 @@ import io.vertx.core.buffer.Buffer;
27 import io.vertx.core.net.NetSocket; 27 import io.vertx.core.net.NetSocket;
28 import lombok.extern.slf4j.Slf4j; 28 import lombok.extern.slf4j.Slf4j;
29 29
  30 +import java.util.Map;
  31 +
30 /** 32 /**
31 * TCP 上行消息处理器 33 * TCP 上行消息处理器
32 * 34 *
@@ -78,6 +80,7 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; { @@ -78,6 +80,7 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; {
78 80
79 // 设置消息处理器 81 // 设置消息处理器
80 socket.handler(buffer -> { 82 socket.handler(buffer -> {
  83 + // TODO @AI:TODO @芋艿:这里应该有拆粘包的问题;
81 try { 84 try {
82 processMessage(clientId, buffer, socket); 85 processMessage(clientId, buffer, socket);
83 } catch (Exception e) { 86 } catch (Exception e) {
@@ -209,15 +212,15 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; { @@ -209,15 +212,15 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; {
209 NetSocket socket) { 212 NetSocket socket) {
210 try { 213 try {
211 // 1. 解析注册参数 214 // 1. 解析注册参数
212 - IotDeviceRegisterReqDTO registerParams = parseRegisterParams(message.getParams());  
213 - if (registerParams == null) { 215 + IotDeviceRegisterReqDTO params = parseRegisterParams(message.getParams());
  216 + if (params == null) {
214 log.warn("[handleRegisterRequest][注册参数解析失败,客户端 ID: {}]", clientId); 217 log.warn("[handleRegisterRequest][注册参数解析失败,客户端 ID: {}]", clientId);
215 sendErrorResponse(socket, message.getRequestId(), "注册参数不完整", codecType); 218 sendErrorResponse(socket, message.getRequestId(), "注册参数不完整", codecType);
216 return; 219 return;
217 } 220 }
218 221
219 // 2. 调用动态注册 222 // 2. 调用动态注册
220 - CommonResult<IotDeviceRegisterRespDTO> result = deviceApi.registerDevice(registerParams); 223 + CommonResult<IotDeviceRegisterRespDTO> result = deviceApi.registerDevice(params);
221 if (result.isError()) { 224 if (result.isError()) {
222 log.warn("[handleRegisterRequest][注册失败,客户端 ID: {},错误: {}]", clientId, result.getMsg()); 225 log.warn("[handleRegisterRequest][注册失败,客户端 ID: {},错误: {}]", clientId, result.getMsg());
223 sendErrorResponse(socket, message.getRequestId(), result.getMsg(), codecType); 226 sendErrorResponse(socket, message.getRequestId(), result.getMsg(), codecType);
@@ -227,7 +230,7 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; { @@ -227,7 +230,7 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; {
227 // 3. 发送成功响应(包含 deviceSecret) 230 // 3. 发送成功响应(包含 deviceSecret)
228 sendRegisterSuccessResponse(socket, message.getRequestId(), result.getData(), codecType); 231 sendRegisterSuccessResponse(socket, message.getRequestId(), result.getData(), codecType);
229 log.info("[handleRegisterRequest][注册成功,客户端 ID: {},设备名: {}]", 232 log.info("[handleRegisterRequest][注册成功,客户端 ID: {},设备名: {}]",
230 - clientId, registerParams.getDeviceName()); 233 + clientId, params.getDeviceName());
231 } catch (Exception e) { 234 } catch (Exception e) {
232 log.error("[handleRegisterRequest][注册处理异常,客户端 ID: {}]", clientId, e); 235 log.error("[handleRegisterRequest][注册处理异常,客户端 ID: {}]", clientId, e);
233 sendErrorResponse(socket, message.getRequestId(), "注册处理异常", codecType); 236 sendErrorResponse(socket, message.getRequestId(), "注册处理异常", codecType);
@@ -419,30 +422,27 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; { @@ -419,30 +422,27 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; {
419 * @param params 参数对象(通常为 Map 类型) 422 * @param params 参数对象(通常为 Map 类型)
420 * @return 认证参数 DTO,解析失败时返回 null 423 * @return 认证参数 DTO,解析失败时返回 null
421 */ 424 */
422 - @SuppressWarnings("unchecked") 425 + @SuppressWarnings({"unchecked", "DuplicatedCode"})
423 private IotDeviceAuthReqDTO parseAuthParams(Object params) { 426 private IotDeviceAuthReqDTO parseAuthParams(Object params) {
424 if (params == null) { 427 if (params == null) {
425 return null; 428 return null;
426 } 429 }
427 -  
428 try { 430 try {
429 // 参数默认为 Map 类型,直接转换 431 // 参数默认为 Map 类型,直接转换
430 - if (params instanceof java.util.Map) {  
431 - java.util.Map<String, Object> paramMap = (java.util.Map<String, Object>) params; 432 + if (params instanceof Map) {
  433 + Map<String, Object> paramMap = (Map<String, Object>) params;
432 return new IotDeviceAuthReqDTO() 434 return new IotDeviceAuthReqDTO()
433 .setClientId(MapUtil.getStr(paramMap, "clientId")) 435 .setClientId(MapUtil.getStr(paramMap, "clientId"))
434 .setUsername(MapUtil.getStr(paramMap, "username")) 436 .setUsername(MapUtil.getStr(paramMap, "username"))
435 .setPassword(MapUtil.getStr(paramMap, "password")); 437 .setPassword(MapUtil.getStr(paramMap, "password"));
436 } 438 }
437 -  
438 // 如果已经是目标类型,直接返回 439 // 如果已经是目标类型,直接返回
439 if (params instanceof IotDeviceAuthReqDTO) { 440 if (params instanceof IotDeviceAuthReqDTO) {
440 return (IotDeviceAuthReqDTO) params; 441 return (IotDeviceAuthReqDTO) params;
441 } 442 }
442 443
443 // 其他情况尝试 JSON 转换 444 // 其他情况尝试 JSON 转换
444 - String jsonStr = JsonUtils.toJsonString(params);  
445 - return JsonUtils.parseObject(jsonStr, IotDeviceAuthReqDTO.class); 445 + return JsonUtils.convertObject(params, IotDeviceAuthReqDTO.class);
446 } catch (Exception e) { 446 } catch (Exception e) {
447 log.error("[parseAuthParams][解析认证参数({})失败]", params, e); 447 log.error("[parseAuthParams][解析认证参数({})失败]", params, e);
448 return null; 448 return null;
@@ -455,28 +455,20 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; { @@ -455,28 +455,20 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; {
455 * @param params 参数对象(通常为 Map 类型) 455 * @param params 参数对象(通常为 Map 类型)
456 * @return 注册参数 DTO,解析失败时返回 null 456 * @return 注册参数 DTO,解析失败时返回 null
457 */ 457 */
458 - @SuppressWarnings("unchecked") 458 + @SuppressWarnings({"unchecked", "DuplicatedCode"})
459 private IotDeviceRegisterReqDTO parseRegisterParams(Object params) { 459 private IotDeviceRegisterReqDTO parseRegisterParams(Object params) {
460 if (params == null) { 460 if (params == null) {
461 return null; 461 return null;
462 } 462 }
463 -  
464 try { 463 try {
465 // 参数默认为 Map 类型,直接转换 464 // 参数默认为 Map 类型,直接转换
466 - if (params instanceof java.util.Map) {  
467 - java.util.Map<String, Object> paramMap = (java.util.Map<String, Object>) params;  
468 - String productKey = MapUtil.getStr(paramMap, "productKey");  
469 - String deviceName = MapUtil.getStr(paramMap, "deviceName");  
470 - String productSecret = MapUtil.getStr(paramMap, "productSecret");  
471 - if (StrUtil.hasBlank(productKey, deviceName, productSecret)) {  
472 - return null;  
473 - } 465 + if (params instanceof Map) {
  466 + Map<String, Object> paramMap = (Map<String, Object>) params;
474 return new IotDeviceRegisterReqDTO() 467 return new IotDeviceRegisterReqDTO()
475 - .setProductKey(productKey)  
476 - .setDeviceName(deviceName)  
477 - .setProductSecret(productSecret); 468 + .setProductKey(MapUtil.getStr(paramMap, "productKey"))
  469 + .setDeviceName(MapUtil.getStr(paramMap, "deviceName"))
  470 + .setProductSecret(MapUtil.getStr(paramMap, "productSecret"));
478 } 471 }
479 -  
480 // 如果已经是目标类型,直接返回 472 // 如果已经是目标类型,直接返回
481 if (params instanceof IotDeviceRegisterReqDTO) { 473 if (params instanceof IotDeviceRegisterReqDTO) {
482 return (IotDeviceRegisterReqDTO) params; 474 return (IotDeviceRegisterReqDTO) params;
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/udp/router/IotUdpUpstreamHandler.java
@@ -225,15 +225,15 @@ public class IotUdpUpstreamHandler { @@ -225,15 +225,15 @@ public class IotUdpUpstreamHandler {
225 String addressKey = sessionManager.buildAddressKey(senderAddress); 225 String addressKey = sessionManager.buildAddressKey(senderAddress);
226 try { 226 try {
227 // 1. 解析注册参数 227 // 1. 解析注册参数
228 - IotDeviceRegisterReqDTO registerParams = parseRegisterParams(message.getParams());  
229 - if (registerParams == null) { 228 + IotDeviceRegisterReqDTO params = parseRegisterParams(message.getParams());
  229 + if (params == null) {
230 log.warn("[handleRegisterRequest][注册参数解析失败,来源: {}]", addressKey); 230 log.warn("[handleRegisterRequest][注册参数解析失败,来源: {}]", addressKey);
231 sendErrorResponse(socket, senderAddress, message.getRequestId(), "注册参数不完整", codecType); 231 sendErrorResponse(socket, senderAddress, message.getRequestId(), "注册参数不完整", codecType);
232 return; 232 return;
233 } 233 }
234 234
235 // 2. 调用动态注册 235 // 2. 调用动态注册
236 - CommonResult<IotDeviceRegisterRespDTO> result = deviceApi.registerDevice(registerParams); 236 + CommonResult<IotDeviceRegisterRespDTO> result = deviceApi.registerDevice(params);
237 if (result.isError()) { 237 if (result.isError()) {
238 log.warn("[handleRegisterRequest][注册失败,来源: {},错误: {}]", addressKey, result.getMsg()); 238 log.warn("[handleRegisterRequest][注册失败,来源: {},错误: {}]", addressKey, result.getMsg());
239 sendErrorResponse(socket, senderAddress, message.getRequestId(), result.getMsg(), codecType); 239 sendErrorResponse(socket, senderAddress, message.getRequestId(), result.getMsg(), codecType);
@@ -243,7 +243,7 @@ public class IotUdpUpstreamHandler { @@ -243,7 +243,7 @@ public class IotUdpUpstreamHandler {
243 // 3. 发送成功响应(包含 deviceSecret) 243 // 3. 发送成功响应(包含 deviceSecret)
244 sendRegisterSuccessResponse(socket, senderAddress, message.getRequestId(), result.getData(), codecType); 244 sendRegisterSuccessResponse(socket, senderAddress, message.getRequestId(), result.getData(), codecType);
245 log.info("[handleRegisterRequest][注册成功,设备名: {},来源: {}]", 245 log.info("[handleRegisterRequest][注册成功,设备名: {},来源: {}]",
246 - registerParams.getDeviceName(), addressKey); 246 + params.getDeviceName(), addressKey);
247 } catch (Exception e) { 247 } catch (Exception e) {
248 log.error("[handleRegisterRequest][注册处理异常,来源: {}]", addressKey, e); 248 log.error("[handleRegisterRequest][注册处理异常,来源: {}]", addressKey, e);
249 sendErrorResponse(socket, senderAddress, message.getRequestId(), "注册处理异常", codecType); 249 sendErrorResponse(socket, senderAddress, message.getRequestId(), "注册处理异常", codecType);
@@ -484,7 +484,6 @@ public class IotUdpUpstreamHandler { @@ -484,7 +484,6 @@ public class IotUdpUpstreamHandler {
484 if (params == null) { 484 if (params == null) {
485 return null; 485 return null;
486 } 486 }
487 -  
488 try { 487 try {
489 // 参数默认为 Map 类型,直接转换 488 // 参数默认为 Map 类型,直接转换
490 if (params instanceof Map) { 489 if (params instanceof Map) {
@@ -494,15 +493,13 @@ public class IotUdpUpstreamHandler { @@ -494,15 +493,13 @@ public class IotUdpUpstreamHandler {
494 .setUsername(MapUtil.getStr(paramMap, "username")) 493 .setUsername(MapUtil.getStr(paramMap, "username"))
495 .setPassword(MapUtil.getStr(paramMap, "password")); 494 .setPassword(MapUtil.getStr(paramMap, "password"));
496 } 495 }
497 -  
498 // 如果已经是目标类型,直接返回 496 // 如果已经是目标类型,直接返回
499 if (params instanceof IotDeviceAuthReqDTO) { 497 if (params instanceof IotDeviceAuthReqDTO) {
500 return (IotDeviceAuthReqDTO) params; 498 return (IotDeviceAuthReqDTO) params;
501 } 499 }
502 500
503 // 其他情况尝试 JSON 转换 501 // 其他情况尝试 JSON 转换
504 - String jsonStr = JsonUtils.toJsonString(params);  
505 - return JsonUtils.parseObject(jsonStr, IotDeviceAuthReqDTO.class); 502 + return JsonUtils.convertObject(params, IotDeviceAuthReqDTO.class);
506 } catch (Exception e) { 503 } catch (Exception e) {
507 log.error("[parseAuthParams][解析认证参数({})失败]", params, e); 504 log.error("[parseAuthParams][解析认证参数({})失败]", params, e);
508 return null; 505 return null;
@@ -515,36 +512,27 @@ public class IotUdpUpstreamHandler { @@ -515,36 +512,27 @@ public class IotUdpUpstreamHandler {
515 * @param params 参数对象(通常为 Map 类型) 512 * @param params 参数对象(通常为 Map 类型)
516 * @return 注册参数 DTO,解析失败时返回 null 513 * @return 注册参数 DTO,解析失败时返回 null
517 */ 514 */
518 - @SuppressWarnings("unchecked") 515 + @SuppressWarnings({"unchecked", "DuplicatedCode"})
519 private IotDeviceRegisterReqDTO parseRegisterParams(Object params) { 516 private IotDeviceRegisterReqDTO parseRegisterParams(Object params) {
520 if (params == null) { 517 if (params == null) {
521 return null; 518 return null;
522 } 519 }
523 -  
524 try { 520 try {
525 // 参数默认为 Map 类型,直接转换 521 // 参数默认为 Map 类型,直接转换
526 if (params instanceof Map) { 522 if (params instanceof Map) {
527 Map<String, Object> paramMap = (Map<String, Object>) params; 523 Map<String, Object> paramMap = (Map<String, Object>) params;
528 - String productKey = MapUtil.getStr(paramMap, "productKey");  
529 - String deviceName = MapUtil.getStr(paramMap, "deviceName");  
530 - String productSecret = MapUtil.getStr(paramMap, "productSecret");  
531 - if (StrUtil.hasBlank(productKey, deviceName, productSecret)) {  
532 - return null;  
533 - }  
534 return new IotDeviceRegisterReqDTO() 524 return new IotDeviceRegisterReqDTO()
535 - .setProductKey(productKey)  
536 - .setDeviceName(deviceName)  
537 - .setProductSecret(productSecret); 525 + .setProductKey(MapUtil.getStr(paramMap, "productKey"))
  526 + .setDeviceName(MapUtil.getStr(paramMap, "deviceName"))
  527 + .setProductSecret(MapUtil.getStr(paramMap, "productSecret"));
538 } 528 }
539 -  
540 // 如果已经是目标类型,直接返回 529 // 如果已经是目标类型,直接返回
541 if (params instanceof IotDeviceRegisterReqDTO) { 530 if (params instanceof IotDeviceRegisterReqDTO) {
542 return (IotDeviceRegisterReqDTO) params; 531 return (IotDeviceRegisterReqDTO) params;
543 } 532 }
544 533
545 // 其他情况尝试 JSON 转换 534 // 其他情况尝试 JSON 转换
546 - String jsonStr = JsonUtils.toJsonString(params);  
547 - return JsonUtils.parseObject(jsonStr, IotDeviceRegisterReqDTO.class); 535 + return JsonUtils.convertObject(params, IotDeviceRegisterReqDTO.class);
548 } catch (Exception e) { 536 } catch (Exception e) {
549 log.error("[parseRegisterParams][解析注册参数({})失败]", params, e); 537 log.error("[parseRegisterParams][解析注册参数({})失败]", params, e);
550 return null; 538 return null;
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/websocket/router/IotWebSocketUpstreamHandler.java
@@ -25,6 +25,8 @@ import io.vertx.core.Handler; @@ -25,6 +25,8 @@ import io.vertx.core.Handler;
25 import io.vertx.core.http.ServerWebSocket; 25 import io.vertx.core.http.ServerWebSocket;
26 import lombok.extern.slf4j.Slf4j; 26 import lombok.extern.slf4j.Slf4j;
27 27
  28 +import java.util.Map;
  29 +
28 30
29 /** 31 /**
30 * WebSocket 上行消息处理器 32 * WebSocket 上行消息处理器
@@ -204,15 +206,16 @@ public class IotWebSocketUpstreamHandler implements Handler&lt;ServerWebSocket&gt; { @@ -204,15 +206,16 @@ public class IotWebSocketUpstreamHandler implements Handler&lt;ServerWebSocket&gt; {
204 private void handleRegisterRequest(String clientId, IotDeviceMessage message, ServerWebSocket socket) { 206 private void handleRegisterRequest(String clientId, IotDeviceMessage message, ServerWebSocket socket) {
205 try { 207 try {
206 // 1. 解析注册参数 208 // 1. 解析注册参数
207 - IotDeviceRegisterReqDTO registerParams = parseRegisterParams(message.getParams());  
208 - if (registerParams == null) { 209 + IotDeviceRegisterReqDTO params = parseRegisterParams(message.getParams());
  210 + if (params == null
  211 + || StrUtil.hasEmpty(params.getProductKey(), params.getDeviceName(), params.getProductSecret())) {
209 log.warn("[handleRegisterRequest][注册参数解析失败,客户端 ID: {}]", clientId); 212 log.warn("[handleRegisterRequest][注册参数解析失败,客户端 ID: {}]", clientId);
210 sendErrorResponse(socket, message.getRequestId(), "注册参数不完整"); 213 sendErrorResponse(socket, message.getRequestId(), "注册参数不完整");
211 return; 214 return;
212 } 215 }
213 216
214 // 2. 调用动态注册 217 // 2. 调用动态注册
215 - CommonResult<IotDeviceRegisterRespDTO> result = deviceApi.registerDevice(registerParams); 218 + CommonResult<IotDeviceRegisterRespDTO> result = deviceApi.registerDevice(params);
216 if (result.isError()) { 219 if (result.isError()) {
217 log.warn("[handleRegisterRequest][注册失败,客户端 ID: {},错误: {}]", clientId, result.getMsg()); 220 log.warn("[handleRegisterRequest][注册失败,客户端 ID: {},错误: {}]", clientId, result.getMsg());
218 sendErrorResponse(socket, message.getRequestId(), result.getMsg()); 221 sendErrorResponse(socket, message.getRequestId(), result.getMsg());
@@ -222,7 +225,7 @@ public class IotWebSocketUpstreamHandler implements Handler&lt;ServerWebSocket&gt; { @@ -222,7 +225,7 @@ public class IotWebSocketUpstreamHandler implements Handler&lt;ServerWebSocket&gt; {
222 // 3. 发送成功响应(包含 deviceSecret) 225 // 3. 发送成功响应(包含 deviceSecret)
223 sendRegisterSuccessResponse(socket, message.getRequestId(), result.getData()); 226 sendRegisterSuccessResponse(socket, message.getRequestId(), result.getData());
224 log.info("[handleRegisterRequest][注册成功,客户端 ID: {},设备名: {}]", 227 log.info("[handleRegisterRequest][注册成功,客户端 ID: {},设备名: {}]",
225 - clientId, registerParams.getDeviceName()); 228 + clientId, params.getDeviceName());
226 } catch (Exception e) { 229 } catch (Exception e) {
227 log.error("[handleRegisterRequest][注册处理异常,客户端 ID: {}]", clientId, e); 230 log.error("[handleRegisterRequest][注册处理异常,客户端 ID: {}]", clientId, e);
228 sendErrorResponse(socket, message.getRequestId(), "注册处理异常"); 231 sendErrorResponse(socket, message.getRequestId(), "注册处理异常");
@@ -384,31 +387,27 @@ public class IotWebSocketUpstreamHandler implements Handler&lt;ServerWebSocket&gt; { @@ -384,31 +387,27 @@ public class IotWebSocketUpstreamHandler implements Handler&lt;ServerWebSocket&gt; {
384 * @param params 参数对象(通常为 Map 类型) 387 * @param params 参数对象(通常为 Map 类型)
385 * @return 认证参数 DTO,解析失败时返回 null 388 * @return 认证参数 DTO,解析失败时返回 null
386 */ 389 */
387 - @SuppressWarnings("unchecked") 390 + @SuppressWarnings({"unchecked", "DuplicatedCode"})
388 private IotDeviceAuthReqDTO parseAuthParams(Object params) { 391 private IotDeviceAuthReqDTO parseAuthParams(Object params) {
389 if (params == null) { 392 if (params == null) {
390 return null; 393 return null;
391 } 394 }
392 -  
393 try { 395 try {
394 // 参数默认为 Map 类型,直接转换 396 // 参数默认为 Map 类型,直接转换
395 - if (params instanceof java.util.Map) {  
396 - java.util.Map<String, Object> paramMap = (java.util.Map<String, Object>) params; 397 + if (params instanceof Map) {
  398 + Map<String, Object> paramMap = (Map<String, Object>) params;
397 return new IotDeviceAuthReqDTO() 399 return new IotDeviceAuthReqDTO()
398 .setClientId(MapUtil.getStr(paramMap, "clientId")) 400 .setClientId(MapUtil.getStr(paramMap, "clientId"))
399 .setUsername(MapUtil.getStr(paramMap, "username")) 401 .setUsername(MapUtil.getStr(paramMap, "username"))
400 .setPassword(MapUtil.getStr(paramMap, "password")); 402 .setPassword(MapUtil.getStr(paramMap, "password"));
401 } 403 }
402 -  
403 // 如果已经是目标类型,直接返回 404 // 如果已经是目标类型,直接返回
404 if (params instanceof IotDeviceAuthReqDTO) { 405 if (params instanceof IotDeviceAuthReqDTO) {
405 return (IotDeviceAuthReqDTO) params; 406 return (IotDeviceAuthReqDTO) params;
406 } 407 }
407 408
408 // 其他情况尝试 JSON 转换 409 // 其他情况尝试 JSON 转换
409 - // TODO @芋艿:要不要优化下;  
410 - String jsonStr = JsonUtils.toJsonString(params);  
411 - return JsonUtils.convertObject(jsonStr, IotDeviceAuthReqDTO.class); 410 + return JsonUtils.convertObject(params, IotDeviceAuthReqDTO.class);
412 } catch (Exception e) { 411 } catch (Exception e) {
413 log.error("[parseAuthParams][解析认证参数({})失败]", params, e); 412 log.error("[parseAuthParams][解析认证参数({})失败]", params, e);
414 return null; 413 return null;
@@ -426,31 +425,22 @@ public class IotWebSocketUpstreamHandler implements Handler&lt;ServerWebSocket&gt; { @@ -426,31 +425,22 @@ public class IotWebSocketUpstreamHandler implements Handler&lt;ServerWebSocket&gt; {
426 if (params == null) { 425 if (params == null) {
427 return null; 426 return null;
428 } 427 }
429 -  
430 try { 428 try {
431 // 参数默认为 Map 类型,直接转换 429 // 参数默认为 Map 类型,直接转换
432 - if (params instanceof java.util.Map) {  
433 - java.util.Map<String, Object> paramMap = (java.util.Map<String, Object>) params;  
434 - String productKey = MapUtil.getStr(paramMap, "productKey");  
435 - String deviceName = MapUtil.getStr(paramMap, "deviceName");  
436 - String productSecret = MapUtil.getStr(paramMap, "productSecret");  
437 - if (StrUtil.hasBlank(productKey, deviceName, productSecret)) {  
438 - return null;  
439 - } 430 + if (params instanceof Map) {
  431 + Map<String, Object> paramMap = (Map<String, Object>) params;
440 return new IotDeviceRegisterReqDTO() 432 return new IotDeviceRegisterReqDTO()
441 - .setProductKey(productKey)  
442 - .setDeviceName(deviceName)  
443 - .setProductSecret(productSecret); 433 + .setProductKey(MapUtil.getStr(paramMap, "productKey"))
  434 + .setDeviceName(MapUtil.getStr(paramMap, "deviceName"))
  435 + .setProductSecret(MapUtil.getStr(paramMap, "productSecret"));
444 } 436 }
445 -  
446 // 如果已经是目标类型,直接返回 437 // 如果已经是目标类型,直接返回
447 if (params instanceof IotDeviceRegisterReqDTO) { 438 if (params instanceof IotDeviceRegisterReqDTO) {
448 return (IotDeviceRegisterReqDTO) params; 439 return (IotDeviceRegisterReqDTO) params;
449 } 440 }
450 441
451 // 其他情况尝试 JSON 转换 442 // 其他情况尝试 JSON 转换
452 - String jsonStr = JsonUtils.toJsonString(params);  
453 - return JsonUtils.parseObject(jsonStr, IotDeviceRegisterReqDTO.class); 443 + return JsonUtils.convertObject(params, IotDeviceRegisterReqDTO.class);
454 } catch (Exception e) { 444 } catch (Exception e) {
455 log.error("[parseRegisterParams][解析注册参数({})失败]", params, e); 445 log.error("[parseRegisterParams][解析注册参数({})失败]", params, e);
456 return null; 446 return null;