Commit b0949c085116819fa76523580ca100f7ebb40692
1 parent
65cd56bc
feat:【IoT 物联网】优化 TCP JSON 编解码器和认证参数解析逻辑
Showing
2 changed files
with
53 additions
and
4 deletions
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/codec/tcp/IotTcpJsonDeviceMessageCodec.java
| @@ -9,6 +9,8 @@ import lombok.Data; | @@ -9,6 +9,8 @@ import lombok.Data; | ||
| 9 | import lombok.NoArgsConstructor; | 9 | import lombok.NoArgsConstructor; |
| 10 | import org.springframework.stereotype.Component; | 10 | import org.springframework.stereotype.Component; |
| 11 | 11 | ||
| 12 | +import java.nio.charset.StandardCharsets; | ||
| 13 | + | ||
| 12 | /** | 14 | /** |
| 13 | * TCP JSON 格式 {@link IotDeviceMessage} 编解码器 | 15 | * TCP JSON 格式 {@link IotDeviceMessage} 编解码器 |
| 14 | * | 16 | * |
| @@ -93,7 +95,8 @@ public class IotTcpJsonDeviceMessageCodec implements IotDeviceMessageCodec { | @@ -93,7 +95,8 @@ public class IotTcpJsonDeviceMessageCodec implements IotDeviceMessageCodec { | ||
| 93 | @Override | 95 | @Override |
| 94 | @SuppressWarnings("DataFlowIssue") | 96 | @SuppressWarnings("DataFlowIssue") |
| 95 | public IotDeviceMessage decode(byte[] bytes) { | 97 | public IotDeviceMessage decode(byte[] bytes) { |
| 96 | - TcpJsonMessage tcpJsonMessage = JsonUtils.parseObject(bytes, TcpJsonMessage.class); | 98 | + String jsonStr = new String(bytes, StandardCharsets.UTF_8).trim(); |
| 99 | + TcpJsonMessage tcpJsonMessage = JsonUtils.parseObject(jsonStr, TcpJsonMessage.class); | ||
| 97 | Assert.notNull(tcpJsonMessage, "消息不能为空"); | 100 | Assert.notNull(tcpJsonMessage, "消息不能为空"); |
| 98 | Assert.notBlank(tcpJsonMessage.getMethod(), "消息方法不能为空"); | 101 | Assert.notBlank(tcpJsonMessage.getMethod(), "消息方法不能为空"); |
| 99 | return IotDeviceMessage.of( | 102 | return IotDeviceMessage.of( |
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/tcp/router/IotTcpUpstreamHandler.java
| @@ -124,7 +124,14 @@ public class IotTcpUpstreamHandler implements Handler<NetSocket> { | @@ -124,7 +124,14 @@ public class IotTcpUpstreamHandler implements Handler<NetSocket> { | ||
| 124 | handleBusinessRequest(clientId, message, codecType, socket); | 124 | handleBusinessRequest(clientId, message, codecType, socket); |
| 125 | } | 125 | } |
| 126 | } catch (Exception e) { | 126 | } catch (Exception e) { |
| 127 | - log.error("[processMessage][处理消息失败,客户端 ID: {}]", clientId, e); | 127 | + log.error("[processMessage][处理消息失败,客户端 ID: {},消息方法: {}]", |
| 128 | + clientId, message.getMethod(), e); | ||
| 129 | + // 发送错误响应,避免客户端一直等待 | ||
| 130 | + try { | ||
| 131 | + sendErrorResponse(socket, message.getRequestId(), "消息处理失败", codecType); | ||
| 132 | + } catch (Exception responseEx) { | ||
| 133 | + log.error("[processMessage][发送错误响应失败,客户端 ID: {}]", clientId, responseEx); | ||
| 134 | + } | ||
| 128 | } | 135 | } |
| 129 | } | 136 | } |
| 130 | 137 | ||
| @@ -140,9 +147,9 @@ public class IotTcpUpstreamHandler implements Handler<NetSocket> { | @@ -140,9 +147,9 @@ public class IotTcpUpstreamHandler implements Handler<NetSocket> { | ||
| 140 | NetSocket socket) { | 147 | NetSocket socket) { |
| 141 | try { | 148 | try { |
| 142 | // 1.1 解析认证参数 | 149 | // 1.1 解析认证参数 |
| 143 | - IotDeviceAuthReqDTO authParams = JsonUtils.parseObject(message.getParams().toString(), | ||
| 144 | - IotDeviceAuthReqDTO.class); | 150 | + IotDeviceAuthReqDTO authParams = parseAuthParams(message.getParams()); |
| 145 | if (authParams == null) { | 151 | if (authParams == null) { |
| 152 | + log.warn("[handleAuthenticationRequest][认证参数解析失败,客户端 ID: {}]", clientId); | ||
| 146 | sendErrorResponse(socket, message.getRequestId(), "认证参数不完整", codecType); | 153 | sendErrorResponse(socket, message.getRequestId(), "认证参数不完整", codecType); |
| 147 | return; | 154 | return; |
| 148 | } | 155 | } |
| @@ -205,6 +212,8 @@ public class IotTcpUpstreamHandler implements Handler<NetSocket> { | @@ -205,6 +212,8 @@ public class IotTcpUpstreamHandler implements Handler<NetSocket> { | ||
| 205 | // 3. 发送消息到消息总线 | 212 | // 3. 发送消息到消息总线 |
| 206 | deviceMessageService.sendDeviceMessage(message, connectionInfo.getProductKey(), | 213 | deviceMessageService.sendDeviceMessage(message, connectionInfo.getProductKey(), |
| 207 | connectionInfo.getDeviceName(), serverId); | 214 | connectionInfo.getDeviceName(), serverId); |
| 215 | + log.info("[handleBusinessRequest][发送消息到消息总线,客户端 ID: {},消息: {}", | ||
| 216 | + clientId, message.toString()); | ||
| 208 | } catch (Exception e) { | 217 | } catch (Exception e) { |
| 209 | log.error("[handleBusinessRequest][业务请求处理异常,客户端 ID: {}]", clientId, e); | 218 | log.error("[handleBusinessRequest][业务请求处理异常,客户端 ID: {}]", clientId, e); |
| 210 | } | 219 | } |
| @@ -359,4 +368,41 @@ public class IotTcpUpstreamHandler implements Handler<NetSocket> { | @@ -359,4 +368,41 @@ public class IotTcpUpstreamHandler implements Handler<NetSocket> { | ||
| 359 | sendResponse(socket, true, message, requestId, codecType); | 368 | sendResponse(socket, true, message, requestId, codecType); |
| 360 | } | 369 | } |
| 361 | 370 | ||
| 371 | + /** | ||
| 372 | + * 解析认证参数 | ||
| 373 | + * | ||
| 374 | + * @param params 参数对象(通常为 Map 类型) | ||
| 375 | + * @return 认证参数 DTO,解析失败时返回 null | ||
| 376 | + */ | ||
| 377 | + private IotDeviceAuthReqDTO parseAuthParams(Object params) { | ||
| 378 | + if (params == null) { | ||
| 379 | + return null; | ||
| 380 | + } | ||
| 381 | + | ||
| 382 | + try { | ||
| 383 | + // 参数默认为 Map 类型,直接转换 | ||
| 384 | + if (params instanceof java.util.Map) { | ||
| 385 | + @SuppressWarnings("unchecked") | ||
| 386 | + java.util.Map<String, Object> paramMap = (java.util.Map<String, Object>) params; | ||
| 387 | + return new IotDeviceAuthReqDTO() | ||
| 388 | + .setClientId(MapUtil.getStr(paramMap, "clientId")) | ||
| 389 | + .setUsername(MapUtil.getStr(paramMap, "username")) | ||
| 390 | + .setPassword(MapUtil.getStr(paramMap, "password")); | ||
| 391 | + } | ||
| 392 | + | ||
| 393 | + // 如果已经是目标类型,直接返回 | ||
| 394 | + if (params instanceof IotDeviceAuthReqDTO) { | ||
| 395 | + return (IotDeviceAuthReqDTO) params; | ||
| 396 | + } | ||
| 397 | + | ||
| 398 | + // 其他情况尝试 JSON 转换 | ||
| 399 | + String jsonStr = JsonUtils.toJsonString(params); | ||
| 400 | + return JsonUtils.parseObject(jsonStr, IotDeviceAuthReqDTO.class); | ||
| 401 | + | ||
| 402 | + } catch (Exception e) { | ||
| 403 | + log.error("[parseAuthParams][解析认证参数失败]", e); | ||
| 404 | + return null; | ||
| 405 | + } | ||
| 406 | + } | ||
| 407 | + | ||
| 362 | } | 408 | } |
| 363 | \ No newline at end of file | 409 | \ No newline at end of file |