Commit d01a6e215894a4d27130528131ae9e646ce3a4c3
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<NetSocket> { | @@ -78,6 +80,7 @@ public class IotTcpUpstreamHandler implements Handler<NetSocket> { | ||
| 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<NetSocket> { | @@ -209,15 +212,15 @@ public class IotTcpUpstreamHandler implements Handler<NetSocket> { | ||
| 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<NetSocket> { | @@ -227,7 +230,7 @@ public class IotTcpUpstreamHandler implements Handler<NetSocket> { | ||
| 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<NetSocket> { | @@ -419,30 +422,27 @@ public class IotTcpUpstreamHandler implements Handler<NetSocket> { | ||
| 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<NetSocket> { | @@ -455,28 +455,20 @@ public class IotTcpUpstreamHandler implements Handler<NetSocket> { | ||
| 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<ServerWebSocket> { | @@ -204,15 +206,16 @@ public class IotWebSocketUpstreamHandler implements Handler<ServerWebSocket> { | ||
| 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<ServerWebSocket> { | @@ -222,7 +225,7 @@ public class IotWebSocketUpstreamHandler implements Handler<ServerWebSocket> { | ||
| 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<ServerWebSocket> { | @@ -384,31 +387,27 @@ public class IotWebSocketUpstreamHandler implements Handler<ServerWebSocket> { | ||
| 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<ServerWebSocket> { | @@ -426,31 +425,22 @@ public class IotWebSocketUpstreamHandler implements Handler<ServerWebSocket> { | ||
| 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; |