mirror of
https://gitee.com/zhijiantianya/ruoyi-vue-pro.git
synced 2026-03-22 05:07:17 +08:00
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
This commit is contained in:
@@ -44,9 +44,15 @@ public class IotGatewayConfiguration {
|
||||
@Slf4j
|
||||
public static class HttpProtocolConfiguration {
|
||||
|
||||
@Bean(name = "httpVertx", destroyMethod = "close")
|
||||
public Vertx httpVertx() {
|
||||
return Vertx.vertx();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IotHttpUpstreamProtocol iotHttpUpstreamProtocol(IotGatewayProperties gatewayProperties) {
|
||||
return new IotHttpUpstreamProtocol(gatewayProperties.getProtocol().getHttp());
|
||||
public IotHttpUpstreamProtocol iotHttpUpstreamProtocol(IotGatewayProperties gatewayProperties,
|
||||
@Qualifier("httpVertx") Vertx httpVertx) {
|
||||
return new IotHttpUpstreamProtocol(gatewayProperties.getProtocol().getHttp(), httpVertx);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package cn.iocoder.yudao.module.iot.gateway.protocol.coap.router;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.text.StrPool;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
@@ -93,7 +92,10 @@ public class IotCoapUpstreamHandler {
|
||||
|
||||
// 2.2 解码消息
|
||||
IotDeviceMessage message = deviceMessageService.decodeDeviceMessage(payload, productKey, deviceName);
|
||||
Assert.equals(method, message.getMethod(), "method 不匹配");
|
||||
if (ObjUtil.notEqual(method, message.getMethod())) {
|
||||
IotCoapUtils.respondError(exchange, CoAP.ResponseCode.BAD_REQUEST, "method 不匹配");
|
||||
return;
|
||||
}
|
||||
// 2.3 发送消息到消息总线
|
||||
deviceMessageService.sendDeviceMessage(message, productKey, deviceName, protocol.getServerId());
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ public class IotEmqxAuthEventHandler {
|
||||
JsonObject body = null;
|
||||
try {
|
||||
// 1. 解析请求体
|
||||
body = parseRequestBody(context);
|
||||
body = parseEventRequestBody(context);
|
||||
if (body == null) {
|
||||
return;
|
||||
}
|
||||
@@ -153,7 +153,9 @@ public class IotEmqxAuthEventHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析请求体
|
||||
* 解析认证接口请求体
|
||||
* <p>
|
||||
* 认证接口解析失败时返回 JSON 格式响应(包含 result 字段)
|
||||
*
|
||||
* @param context 路由上下文
|
||||
* @return 请求体JSON对象,解析失败时返回null
|
||||
@@ -174,6 +176,30 @@ public class IotEmqxAuthEventHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析事件接口请求体
|
||||
* <p>
|
||||
* 事件接口解析失败时仅返回 200 状态码,无响应体(符合 EMQX Webhook 规范)
|
||||
*
|
||||
* @param context 路由上下文
|
||||
* @return 请求体JSON对象,解析失败时返回null
|
||||
*/
|
||||
private JsonObject parseEventRequestBody(RoutingContext context) {
|
||||
try {
|
||||
JsonObject body = context.body().asJsonObject();
|
||||
if (body == null) {
|
||||
log.info("[parseEventRequestBody][请求体为空]");
|
||||
context.response().setStatusCode(SUCCESS_STATUS_CODE).end();
|
||||
return null;
|
||||
}
|
||||
return body;
|
||||
} catch (Exception e) {
|
||||
log.error("[parseEventRequestBody][body({}) 解析请求体失败]", context.body().asString(), e);
|
||||
context.response().setStatusCode(SUCCESS_STATUS_CODE).end();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行设备认证
|
||||
*
|
||||
|
||||
@@ -6,7 +6,6 @@ import cn.iocoder.yudao.module.iot.gateway.protocol.http.router.IotHttpAuthHandl
|
||||
import cn.iocoder.yudao.module.iot.gateway.protocol.http.router.IotHttpRegisterHandler;
|
||||
import cn.iocoder.yudao.module.iot.gateway.protocol.http.router.IotHttpRegisterSubHandler;
|
||||
import cn.iocoder.yudao.module.iot.gateway.protocol.http.router.IotHttpUpstreamHandler;
|
||||
import io.vertx.core.AbstractVerticle;
|
||||
import io.vertx.core.Vertx;
|
||||
import io.vertx.core.http.HttpServer;
|
||||
import io.vertx.core.http.HttpServerOptions;
|
||||
@@ -24,25 +23,26 @@ import lombok.extern.slf4j.Slf4j;
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Slf4j
|
||||
public class IotHttpUpstreamProtocol extends AbstractVerticle {
|
||||
public class IotHttpUpstreamProtocol {
|
||||
|
||||
private final IotGatewayProperties.HttpProperties httpProperties;
|
||||
|
||||
private final Vertx vertx;
|
||||
|
||||
private HttpServer httpServer;
|
||||
|
||||
@Getter
|
||||
private final String serverId;
|
||||
|
||||
public IotHttpUpstreamProtocol(IotGatewayProperties.HttpProperties httpProperties) {
|
||||
public IotHttpUpstreamProtocol(IotGatewayProperties.HttpProperties httpProperties, Vertx vertx) {
|
||||
this.httpProperties = httpProperties;
|
||||
this.vertx = vertx;
|
||||
this.serverId = IotDeviceMessageUtils.generateServerId(httpProperties.getServerPort());
|
||||
}
|
||||
|
||||
@Override
|
||||
@PostConstruct
|
||||
public void start() {
|
||||
// 创建路由
|
||||
Vertx vertx = Vertx.vertx();
|
||||
Router router = Router.router(vertx);
|
||||
router.route().handler(BodyHandler.create());
|
||||
|
||||
@@ -76,7 +76,6 @@ public class IotHttpUpstreamProtocol extends AbstractVerticle {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@PreDestroy
|
||||
public void stop() {
|
||||
if (httpServer != null) {
|
||||
|
||||
@@ -51,6 +51,9 @@ public class IotHttpAuthHandler extends IotHttpAbstractHandler {
|
||||
public CommonResult<Object> handle0(RoutingContext context) {
|
||||
// 1. 解析参数
|
||||
JsonObject body = context.body().asJsonObject();
|
||||
if (body == null) {
|
||||
throw invalidParamException("请求体不能为空");
|
||||
}
|
||||
String clientId = body.getString("clientId");
|
||||
if (StrUtil.isEmpty(clientId)) {
|
||||
throw invalidParamException("clientId 不能为空");
|
||||
|
||||
@@ -34,6 +34,9 @@ public class IotHttpRegisterHandler extends IotHttpAbstractHandler {
|
||||
public CommonResult<Object> handle0(RoutingContext context) {
|
||||
// 1. 解析参数
|
||||
JsonObject body = context.body().asJsonObject();
|
||||
if (body == null) {
|
||||
throw invalidParamException("请求体不能为空");
|
||||
}
|
||||
String productKey = body.getString("productKey");
|
||||
if (StrUtil.isEmpty(productKey)) {
|
||||
throw invalidParamException("productKey 不能为空");
|
||||
|
||||
@@ -11,6 +11,7 @@ import io.vertx.ext.web.RoutingContext;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
/**
|
||||
@@ -44,6 +45,12 @@ public class IotHttpRegisterSubHandler extends IotHttpAbstractHandler {
|
||||
|
||||
// 2. 解析子设备列表
|
||||
JsonObject body = context.body().asJsonObject();
|
||||
if (body == null) {
|
||||
throw invalidParamException("请求体不能为空");
|
||||
}
|
||||
if (body.getJsonArray("params") == null) {
|
||||
throw invalidParamException("params 不能为空");
|
||||
}
|
||||
List<cn.iocoder.yudao.module.iot.core.topic.auth.IotSubDeviceRegisterReqDTO> subDevices = JsonUtils.parseArray(
|
||||
body.getJsonArray("params").toString(), cn.iocoder.yudao.module.iot.core.topic.auth.IotSubDeviceRegisterReqDTO.class);
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ import io.vertx.ext.web.RoutingContext;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException;
|
||||
|
||||
/**
|
||||
* IoT 网关 HTTP 协议的【上行】处理器
|
||||
*
|
||||
@@ -40,6 +42,9 @@ public class IotHttpUpstreamHandler extends IotHttpAbstractHandler {
|
||||
String method = context.pathParam("*").replaceAll(StrPool.SLASH, StrPool.DOT);
|
||||
|
||||
// 2.1 解析消息
|
||||
if (context.body().buffer() == null) {
|
||||
throw invalidParamException("请求体不能为空");
|
||||
}
|
||||
byte[] bytes = context.body().buffer().getBytes();
|
||||
IotDeviceMessage message = deviceMessageService.decodeDeviceMessage(bytes,
|
||||
productKey, deviceName);
|
||||
|
||||
@@ -330,15 +330,15 @@ public class IotMqttUpstreamHandler {
|
||||
String clientId = endpoint.clientIdentifier();
|
||||
try {
|
||||
// 1. 解析注册参数
|
||||
IotDeviceRegisterReqDTO registerParams = parseRegisterParams(message.getParams());
|
||||
if (registerParams == null) {
|
||||
IotDeviceRegisterReqDTO params = parseRegisterParams(message.getParams());
|
||||
if (params == null) {
|
||||
log.warn("[handleRegisterRequest][注册参数解析失败,客户端 ID: {}]", clientId);
|
||||
sendRegisterErrorResponse(endpoint, productKey, deviceName, message.getRequestId(), "注册参数不完整");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 调用动态注册 API
|
||||
CommonResult<IotDeviceRegisterRespDTO> result = deviceApi.registerDevice(registerParams);
|
||||
CommonResult<IotDeviceRegisterRespDTO> result = deviceApi.registerDevice(params);
|
||||
if (result.isError()) {
|
||||
log.warn("[handleRegisterRequest][注册失败,客户端 ID: {},错误: {}]", clientId, result.getMsg());
|
||||
sendRegisterErrorResponse(endpoint, productKey, deviceName, message.getRequestId(), result.getMsg());
|
||||
@@ -348,7 +348,7 @@ public class IotMqttUpstreamHandler {
|
||||
// 3. 发送成功响应(包含 deviceSecret)
|
||||
sendRegisterSuccessResponse(endpoint, productKey, deviceName, message.getRequestId(), result.getData());
|
||||
log.info("[handleRegisterRequest][注册成功,设备名: {},客户端 ID: {}]",
|
||||
registerParams.getDeviceName(), clientId);
|
||||
params.getDeviceName(), clientId);
|
||||
} catch (Exception e) {
|
||||
log.error("[handleRegisterRequest][注册处理异常,客户端 ID: {}]", clientId, e);
|
||||
sendRegisterErrorResponse(endpoint, productKey, deviceName, message.getRequestId(), "注册处理异常");
|
||||
@@ -361,36 +361,27 @@ public class IotMqttUpstreamHandler {
|
||||
* @param params 参数对象(通常为 Map 类型)
|
||||
* @return 注册参数 DTO,解析失败时返回 null
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({"unchecked", "DuplicatedCode"})
|
||||
private IotDeviceRegisterReqDTO parseRegisterParams(Object params) {
|
||||
if (params == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// 参数默认为 Map 类型,直接转换
|
||||
if (params instanceof Map) {
|
||||
Map<String, Object> paramMap = (Map<String, Object>) params;
|
||||
String productKey = MapUtil.getStr(paramMap, "productKey");
|
||||
String deviceName = MapUtil.getStr(paramMap, "deviceName");
|
||||
String productSecret = MapUtil.getStr(paramMap, "productSecret");
|
||||
if (StrUtil.hasBlank(productKey, deviceName, productSecret)) {
|
||||
return null;
|
||||
}
|
||||
return new IotDeviceRegisterReqDTO()
|
||||
.setProductKey(productKey)
|
||||
.setDeviceName(deviceName)
|
||||
.setProductSecret(productSecret);
|
||||
.setProductKey(MapUtil.getStr(paramMap, "productKey"))
|
||||
.setDeviceName(MapUtil.getStr(paramMap, "deviceName"))
|
||||
.setProductSecret(MapUtil.getStr(paramMap, "productSecret"));
|
||||
}
|
||||
|
||||
// 如果已经是目标类型,直接返回
|
||||
if (params instanceof IotDeviceRegisterReqDTO) {
|
||||
return (IotDeviceRegisterReqDTO) params;
|
||||
}
|
||||
|
||||
// 其他情况尝试 JSON 转换
|
||||
String jsonStr = JsonUtils.toJsonString(params);
|
||||
return JsonUtils.parseObject(jsonStr, IotDeviceRegisterReqDTO.class);
|
||||
return JsonUtils.convertObject(params, IotDeviceRegisterReqDTO.class);
|
||||
} catch (Exception e) {
|
||||
log.error("[parseRegisterParams][解析注册参数({})失败]", params, e);
|
||||
return null;
|
||||
|
||||
@@ -12,9 +12,9 @@ import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceAuthReqDTO;
|
||||
import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceRespDTO;
|
||||
import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum;
|
||||
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
|
||||
import cn.iocoder.yudao.module.iot.core.topic.IotDeviceIdentity;
|
||||
import cn.iocoder.yudao.module.iot.core.topic.auth.IotDeviceRegisterReqDTO;
|
||||
import cn.iocoder.yudao.module.iot.core.topic.auth.IotDeviceRegisterRespDTO;
|
||||
import cn.iocoder.yudao.module.iot.core.topic.IotDeviceIdentity;
|
||||
import cn.iocoder.yudao.module.iot.core.util.IotDeviceAuthUtils;
|
||||
import cn.iocoder.yudao.module.iot.gateway.codec.tcp.IotTcpBinaryDeviceMessageCodec;
|
||||
import cn.iocoder.yudao.module.iot.gateway.codec.tcp.IotTcpJsonDeviceMessageCodec;
|
||||
@@ -27,6 +27,8 @@ import io.vertx.core.buffer.Buffer;
|
||||
import io.vertx.core.net.NetSocket;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* TCP 上行消息处理器
|
||||
*
|
||||
@@ -78,6 +80,7 @@ public class IotTcpUpstreamHandler implements Handler<NetSocket> {
|
||||
|
||||
// 设置消息处理器
|
||||
socket.handler(buffer -> {
|
||||
// TODO @AI:TODO @芋艿:这里应该有拆粘包的问题;
|
||||
try {
|
||||
processMessage(clientId, buffer, socket);
|
||||
} catch (Exception e) {
|
||||
@@ -209,15 +212,15 @@ public class IotTcpUpstreamHandler implements Handler<NetSocket> {
|
||||
NetSocket socket) {
|
||||
try {
|
||||
// 1. 解析注册参数
|
||||
IotDeviceRegisterReqDTO registerParams = parseRegisterParams(message.getParams());
|
||||
if (registerParams == null) {
|
||||
IotDeviceRegisterReqDTO params = parseRegisterParams(message.getParams());
|
||||
if (params == null) {
|
||||
log.warn("[handleRegisterRequest][注册参数解析失败,客户端 ID: {}]", clientId);
|
||||
sendErrorResponse(socket, message.getRequestId(), "注册参数不完整", codecType);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 调用动态注册
|
||||
CommonResult<IotDeviceRegisterRespDTO> result = deviceApi.registerDevice(registerParams);
|
||||
CommonResult<IotDeviceRegisterRespDTO> result = deviceApi.registerDevice(params);
|
||||
if (result.isError()) {
|
||||
log.warn("[handleRegisterRequest][注册失败,客户端 ID: {},错误: {}]", clientId, result.getMsg());
|
||||
sendErrorResponse(socket, message.getRequestId(), result.getMsg(), codecType);
|
||||
@@ -227,7 +230,7 @@ public class IotTcpUpstreamHandler implements Handler<NetSocket> {
|
||||
// 3. 发送成功响应(包含 deviceSecret)
|
||||
sendRegisterSuccessResponse(socket, message.getRequestId(), result.getData(), codecType);
|
||||
log.info("[handleRegisterRequest][注册成功,客户端 ID: {},设备名: {}]",
|
||||
clientId, registerParams.getDeviceName());
|
||||
clientId, params.getDeviceName());
|
||||
} catch (Exception e) {
|
||||
log.error("[handleRegisterRequest][注册处理异常,客户端 ID: {}]", clientId, e);
|
||||
sendErrorResponse(socket, message.getRequestId(), "注册处理异常", codecType);
|
||||
@@ -419,30 +422,27 @@ public class IotTcpUpstreamHandler implements Handler<NetSocket> {
|
||||
* @param params 参数对象(通常为 Map 类型)
|
||||
* @return 认证参数 DTO,解析失败时返回 null
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({"unchecked", "DuplicatedCode"})
|
||||
private IotDeviceAuthReqDTO parseAuthParams(Object params) {
|
||||
if (params == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// 参数默认为 Map 类型,直接转换
|
||||
if (params instanceof java.util.Map) {
|
||||
java.util.Map<String, Object> paramMap = (java.util.Map<String, Object>) params;
|
||||
if (params instanceof Map) {
|
||||
Map<String, Object> paramMap = (Map<String, Object>) params;
|
||||
return new IotDeviceAuthReqDTO()
|
||||
.setClientId(MapUtil.getStr(paramMap, "clientId"))
|
||||
.setUsername(MapUtil.getStr(paramMap, "username"))
|
||||
.setPassword(MapUtil.getStr(paramMap, "password"));
|
||||
}
|
||||
|
||||
// 如果已经是目标类型,直接返回
|
||||
if (params instanceof IotDeviceAuthReqDTO) {
|
||||
return (IotDeviceAuthReqDTO) params;
|
||||
}
|
||||
|
||||
// 其他情况尝试 JSON 转换
|
||||
String jsonStr = JsonUtils.toJsonString(params);
|
||||
return JsonUtils.parseObject(jsonStr, IotDeviceAuthReqDTO.class);
|
||||
return JsonUtils.convertObject(params, IotDeviceAuthReqDTO.class);
|
||||
} catch (Exception e) {
|
||||
log.error("[parseAuthParams][解析认证参数({})失败]", params, e);
|
||||
return null;
|
||||
@@ -455,28 +455,20 @@ public class IotTcpUpstreamHandler implements Handler<NetSocket> {
|
||||
* @param params 参数对象(通常为 Map 类型)
|
||||
* @return 注册参数 DTO,解析失败时返回 null
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({"unchecked", "DuplicatedCode"})
|
||||
private IotDeviceRegisterReqDTO parseRegisterParams(Object params) {
|
||||
if (params == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// 参数默认为 Map 类型,直接转换
|
||||
if (params instanceof java.util.Map) {
|
||||
java.util.Map<String, Object> paramMap = (java.util.Map<String, Object>) params;
|
||||
String productKey = MapUtil.getStr(paramMap, "productKey");
|
||||
String deviceName = MapUtil.getStr(paramMap, "deviceName");
|
||||
String productSecret = MapUtil.getStr(paramMap, "productSecret");
|
||||
if (StrUtil.hasBlank(productKey, deviceName, productSecret)) {
|
||||
return null;
|
||||
}
|
||||
if (params instanceof Map) {
|
||||
Map<String, Object> paramMap = (Map<String, Object>) params;
|
||||
return new IotDeviceRegisterReqDTO()
|
||||
.setProductKey(productKey)
|
||||
.setDeviceName(deviceName)
|
||||
.setProductSecret(productSecret);
|
||||
.setProductKey(MapUtil.getStr(paramMap, "productKey"))
|
||||
.setDeviceName(MapUtil.getStr(paramMap, "deviceName"))
|
||||
.setProductSecret(MapUtil.getStr(paramMap, "productSecret"));
|
||||
}
|
||||
|
||||
// 如果已经是目标类型,直接返回
|
||||
if (params instanceof IotDeviceRegisterReqDTO) {
|
||||
return (IotDeviceRegisterReqDTO) params;
|
||||
|
||||
@@ -225,15 +225,15 @@ public class IotUdpUpstreamHandler {
|
||||
String addressKey = sessionManager.buildAddressKey(senderAddress);
|
||||
try {
|
||||
// 1. 解析注册参数
|
||||
IotDeviceRegisterReqDTO registerParams = parseRegisterParams(message.getParams());
|
||||
if (registerParams == null) {
|
||||
IotDeviceRegisterReqDTO params = parseRegisterParams(message.getParams());
|
||||
if (params == null) {
|
||||
log.warn("[handleRegisterRequest][注册参数解析失败,来源: {}]", addressKey);
|
||||
sendErrorResponse(socket, senderAddress, message.getRequestId(), "注册参数不完整", codecType);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 调用动态注册
|
||||
CommonResult<IotDeviceRegisterRespDTO> result = deviceApi.registerDevice(registerParams);
|
||||
CommonResult<IotDeviceRegisterRespDTO> result = deviceApi.registerDevice(params);
|
||||
if (result.isError()) {
|
||||
log.warn("[handleRegisterRequest][注册失败,来源: {},错误: {}]", addressKey, result.getMsg());
|
||||
sendErrorResponse(socket, senderAddress, message.getRequestId(), result.getMsg(), codecType);
|
||||
@@ -243,7 +243,7 @@ public class IotUdpUpstreamHandler {
|
||||
// 3. 发送成功响应(包含 deviceSecret)
|
||||
sendRegisterSuccessResponse(socket, senderAddress, message.getRequestId(), result.getData(), codecType);
|
||||
log.info("[handleRegisterRequest][注册成功,设备名: {},来源: {}]",
|
||||
registerParams.getDeviceName(), addressKey);
|
||||
params.getDeviceName(), addressKey);
|
||||
} catch (Exception e) {
|
||||
log.error("[handleRegisterRequest][注册处理异常,来源: {}]", addressKey, e);
|
||||
sendErrorResponse(socket, senderAddress, message.getRequestId(), "注册处理异常", codecType);
|
||||
@@ -484,7 +484,6 @@ public class IotUdpUpstreamHandler {
|
||||
if (params == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// 参数默认为 Map 类型,直接转换
|
||||
if (params instanceof Map) {
|
||||
@@ -494,15 +493,13 @@ public class IotUdpUpstreamHandler {
|
||||
.setUsername(MapUtil.getStr(paramMap, "username"))
|
||||
.setPassword(MapUtil.getStr(paramMap, "password"));
|
||||
}
|
||||
|
||||
// 如果已经是目标类型,直接返回
|
||||
if (params instanceof IotDeviceAuthReqDTO) {
|
||||
return (IotDeviceAuthReqDTO) params;
|
||||
}
|
||||
|
||||
// 其他情况尝试 JSON 转换
|
||||
String jsonStr = JsonUtils.toJsonString(params);
|
||||
return JsonUtils.parseObject(jsonStr, IotDeviceAuthReqDTO.class);
|
||||
return JsonUtils.convertObject(params, IotDeviceAuthReqDTO.class);
|
||||
} catch (Exception e) {
|
||||
log.error("[parseAuthParams][解析认证参数({})失败]", params, e);
|
||||
return null;
|
||||
@@ -515,36 +512,27 @@ public class IotUdpUpstreamHandler {
|
||||
* @param params 参数对象(通常为 Map 类型)
|
||||
* @return 注册参数 DTO,解析失败时返回 null
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({"unchecked", "DuplicatedCode"})
|
||||
private IotDeviceRegisterReqDTO parseRegisterParams(Object params) {
|
||||
if (params == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// 参数默认为 Map 类型,直接转换
|
||||
if (params instanceof Map) {
|
||||
Map<String, Object> paramMap = (Map<String, Object>) params;
|
||||
String productKey = MapUtil.getStr(paramMap, "productKey");
|
||||
String deviceName = MapUtil.getStr(paramMap, "deviceName");
|
||||
String productSecret = MapUtil.getStr(paramMap, "productSecret");
|
||||
if (StrUtil.hasBlank(productKey, deviceName, productSecret)) {
|
||||
return null;
|
||||
}
|
||||
return new IotDeviceRegisterReqDTO()
|
||||
.setProductKey(productKey)
|
||||
.setDeviceName(deviceName)
|
||||
.setProductSecret(productSecret);
|
||||
.setProductKey(MapUtil.getStr(paramMap, "productKey"))
|
||||
.setDeviceName(MapUtil.getStr(paramMap, "deviceName"))
|
||||
.setProductSecret(MapUtil.getStr(paramMap, "productSecret"));
|
||||
}
|
||||
|
||||
// 如果已经是目标类型,直接返回
|
||||
if (params instanceof IotDeviceRegisterReqDTO) {
|
||||
return (IotDeviceRegisterReqDTO) params;
|
||||
}
|
||||
|
||||
// 其他情况尝试 JSON 转换
|
||||
String jsonStr = JsonUtils.toJsonString(params);
|
||||
return JsonUtils.parseObject(jsonStr, IotDeviceRegisterReqDTO.class);
|
||||
return JsonUtils.convertObject(params, IotDeviceRegisterReqDTO.class);
|
||||
} catch (Exception e) {
|
||||
log.error("[parseRegisterParams][解析注册参数({})失败]", params, e);
|
||||
return null;
|
||||
|
||||
@@ -25,6 +25,8 @@ import io.vertx.core.Handler;
|
||||
import io.vertx.core.http.ServerWebSocket;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* WebSocket 上行消息处理器
|
||||
@@ -204,15 +206,16 @@ public class IotWebSocketUpstreamHandler implements Handler<ServerWebSocket> {
|
||||
private void handleRegisterRequest(String clientId, IotDeviceMessage message, ServerWebSocket socket) {
|
||||
try {
|
||||
// 1. 解析注册参数
|
||||
IotDeviceRegisterReqDTO registerParams = parseRegisterParams(message.getParams());
|
||||
if (registerParams == null) {
|
||||
IotDeviceRegisterReqDTO params = parseRegisterParams(message.getParams());
|
||||
if (params == null
|
||||
|| StrUtil.hasEmpty(params.getProductKey(), params.getDeviceName(), params.getProductSecret())) {
|
||||
log.warn("[handleRegisterRequest][注册参数解析失败,客户端 ID: {}]", clientId);
|
||||
sendErrorResponse(socket, message.getRequestId(), "注册参数不完整");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 调用动态注册
|
||||
CommonResult<IotDeviceRegisterRespDTO> result = deviceApi.registerDevice(registerParams);
|
||||
CommonResult<IotDeviceRegisterRespDTO> result = deviceApi.registerDevice(params);
|
||||
if (result.isError()) {
|
||||
log.warn("[handleRegisterRequest][注册失败,客户端 ID: {},错误: {}]", clientId, result.getMsg());
|
||||
sendErrorResponse(socket, message.getRequestId(), result.getMsg());
|
||||
@@ -222,7 +225,7 @@ public class IotWebSocketUpstreamHandler implements Handler<ServerWebSocket> {
|
||||
// 3. 发送成功响应(包含 deviceSecret)
|
||||
sendRegisterSuccessResponse(socket, message.getRequestId(), result.getData());
|
||||
log.info("[handleRegisterRequest][注册成功,客户端 ID: {},设备名: {}]",
|
||||
clientId, registerParams.getDeviceName());
|
||||
clientId, params.getDeviceName());
|
||||
} catch (Exception e) {
|
||||
log.error("[handleRegisterRequest][注册处理异常,客户端 ID: {}]", clientId, e);
|
||||
sendErrorResponse(socket, message.getRequestId(), "注册处理异常");
|
||||
@@ -384,31 +387,27 @@ public class IotWebSocketUpstreamHandler implements Handler<ServerWebSocket> {
|
||||
* @param params 参数对象(通常为 Map 类型)
|
||||
* @return 认证参数 DTO,解析失败时返回 null
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({"unchecked", "DuplicatedCode"})
|
||||
private IotDeviceAuthReqDTO parseAuthParams(Object params) {
|
||||
if (params == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// 参数默认为 Map 类型,直接转换
|
||||
if (params instanceof java.util.Map) {
|
||||
java.util.Map<String, Object> paramMap = (java.util.Map<String, Object>) params;
|
||||
if (params instanceof Map) {
|
||||
Map<String, Object> paramMap = (Map<String, Object>) params;
|
||||
return new IotDeviceAuthReqDTO()
|
||||
.setClientId(MapUtil.getStr(paramMap, "clientId"))
|
||||
.setUsername(MapUtil.getStr(paramMap, "username"))
|
||||
.setPassword(MapUtil.getStr(paramMap, "password"));
|
||||
}
|
||||
|
||||
// 如果已经是目标类型,直接返回
|
||||
if (params instanceof IotDeviceAuthReqDTO) {
|
||||
return (IotDeviceAuthReqDTO) params;
|
||||
}
|
||||
|
||||
// 其他情况尝试 JSON 转换
|
||||
// TODO @芋艿:要不要优化下;
|
||||
String jsonStr = JsonUtils.toJsonString(params);
|
||||
return JsonUtils.convertObject(jsonStr, IotDeviceAuthReqDTO.class);
|
||||
return JsonUtils.convertObject(params, IotDeviceAuthReqDTO.class);
|
||||
} catch (Exception e) {
|
||||
log.error("[parseAuthParams][解析认证参数({})失败]", params, e);
|
||||
return null;
|
||||
@@ -426,31 +425,22 @@ public class IotWebSocketUpstreamHandler implements Handler<ServerWebSocket> {
|
||||
if (params == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// 参数默认为 Map 类型,直接转换
|
||||
if (params instanceof java.util.Map) {
|
||||
java.util.Map<String, Object> paramMap = (java.util.Map<String, Object>) params;
|
||||
String productKey = MapUtil.getStr(paramMap, "productKey");
|
||||
String deviceName = MapUtil.getStr(paramMap, "deviceName");
|
||||
String productSecret = MapUtil.getStr(paramMap, "productSecret");
|
||||
if (StrUtil.hasBlank(productKey, deviceName, productSecret)) {
|
||||
return null;
|
||||
}
|
||||
if (params instanceof Map) {
|
||||
Map<String, Object> paramMap = (Map<String, Object>) params;
|
||||
return new IotDeviceRegisterReqDTO()
|
||||
.setProductKey(productKey)
|
||||
.setDeviceName(deviceName)
|
||||
.setProductSecret(productSecret);
|
||||
.setProductKey(MapUtil.getStr(paramMap, "productKey"))
|
||||
.setDeviceName(MapUtil.getStr(paramMap, "deviceName"))
|
||||
.setProductSecret(MapUtil.getStr(paramMap, "productSecret"));
|
||||
}
|
||||
|
||||
// 如果已经是目标类型,直接返回
|
||||
if (params instanceof IotDeviceRegisterReqDTO) {
|
||||
return (IotDeviceRegisterReqDTO) params;
|
||||
}
|
||||
|
||||
// 其他情况尝试 JSON 转换
|
||||
String jsonStr = JsonUtils.toJsonString(params);
|
||||
return JsonUtils.parseObject(jsonStr, IotDeviceRegisterReqDTO.class);
|
||||
return JsonUtils.convertObject(params, IotDeviceRegisterReqDTO.class);
|
||||
} catch (Exception e) {
|
||||
log.error("[parseRegisterParams][解析注册参数({})失败]", params, e);
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user