Commit 6b79cab09a5334844f8159a086e85365c82e86d0

Authored by YunaiV
1 parent c9b9fc1f

review:【iot 物联网】tcp 协议的接入

yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/message/IotDeviceMessageServiceImpl.java
... ... @@ -236,8 +236,8 @@ public class IotDeviceMessageServiceImpl implements IotDeviceMessageService {
236 236  
237 237 @Override
238 238 public Long getDeviceMessageCount(LocalDateTime createTime) {
239   - return deviceMessageMapper
240   - .selectCountByCreateTime(createTime != null ? LocalDateTimeUtil.toEpochMilli(createTime) : null);
  239 + return deviceMessageMapper.selectCountByCreateTime(
  240 + createTime != null ? LocalDateTimeUtil.toEpochMilli(createTime) : null);
241 241 }
242 242  
243 243 @Override
... ...
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/codec/alink/IotAlinkDeviceMessageCodec.java
... ... @@ -18,6 +18,8 @@ import org.springframework.stereotype.Component;
18 18 @Component
19 19 public class IotAlinkDeviceMessageCodec implements IotDeviceMessageCodec {
20 20  
  21 + private static final String TYPE = "Alink";
  22 +
21 23 @Data
22 24 @NoArgsConstructor
23 25 @AllArgsConstructor
... ... @@ -63,6 +65,11 @@ public class IotAlinkDeviceMessageCodec implements IotDeviceMessageCodec {
63 65 }
64 66  
65 67 @Override
  68 + public String type() {
  69 + return TYPE;
  70 + }
  71 +
  72 + @Override
66 73 public byte[] encode(IotDeviceMessage message) {
67 74 AlinkMessage alinkMessage = new AlinkMessage(message.getRequestId(), AlinkMessage.VERSION_1,
68 75 message.getMethod(), message.getParams(), message.getData(), message.getCode(), message.getMsg());
... ... @@ -79,9 +86,4 @@ public class IotAlinkDeviceMessageCodec implements IotDeviceMessageCodec {
79 86 alinkMessage.getData(), alinkMessage.getCode(), alinkMessage.getMsg());
80 87 }
81 88  
82   - @Override
83   - public String type() {
84   - return "Alink";
85   - }
86   -
87 89 }
... ...
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/codec/tcp/IotTcpBinaryDeviceMessageCodec.java
... ... @@ -11,17 +11,29 @@ import lombok.Data;
11 11 import lombok.NoArgsConstructor;
12 12 import org.springframework.stereotype.Component;
13 13  
  14 +// TODO @haohao:【重要】是不是二进制更彻底哈?
  15 +// 包头(4 字节)
  16 +// 消息 ID string;nvarchar(length + string)
  17 +// version(可选,不要干脆)
  18 +// method string;nvarchar;为什么不要 opcode?因为 IotTcpJsonDeviceMessageCodec 里面,实际已经没 opcode 了
  19 +// reply bit;0 请求,1 响应
  20 +// 请求时:
  21 +// params;nvarchar;json 处理
  22 +// 响应时:
  23 +// code
  24 +// msg nvarchar
  25 +// data;nvarchar;json 处理
14 26 /**
15 27 * TCP 二进制格式 {@link IotDeviceMessage} 编解码器
16 28 *
17   - * 使用自定义二进制协议格式:
18   - * 包头(4 字节) | 功能码(2 字节) | 消息序号(2 字节) | 包体数据(变长)
  29 + * 使用自定义二进制协议格式:包头(4 字节) | 功能码(2 字节) | 消息序号(2 字节) | 包体数据(变长)
19 30 *
20 31 * @author 芋道源码
21 32 */
22 33 @Component
23 34 public class IotTcpBinaryDeviceMessageCodec implements IotDeviceMessageCodec {
24 35  
  36 + // TODO @haohao:是不是叫 TCP_Binary 好点哈?
25 37 public static final String TYPE = "TCP_BINARY";
26 38  
27 39 @Data
... ... @@ -34,11 +46,13 @@ public class IotTcpBinaryDeviceMessageCodec implements IotDeviceMessageCodec {
34 46 */
35 47 private Short code;
36 48  
  49 + // TODO @haohao:这个和 AlinkMessage 里面,是一个东西哇?
37 50 /**
38 51 * 消息序号
39 52 */
40 53 private Short mid;
41 54  
  55 + // TODO @haohao:这个字段,是不是没用到呀?感觉应该也不在消息列哈?
42 56 /**
43 57 * 设备 ID
44 58 */
... ... @@ -59,6 +73,7 @@ public class IotTcpBinaryDeviceMessageCodec implements IotDeviceMessageCodec {
59 73 */
60 74 private Object data;
61 75  
  76 + // TODO @haohao:这个可以改成 code 哇?更好理解一点;
62 77 /**
63 78 * 响应错误码
64 79 */
... ... @@ -69,6 +84,8 @@ public class IotTcpBinaryDeviceMessageCodec implements IotDeviceMessageCodec {
69 84 */
70 85 private String msg;
71 86  
  87 + // TODO @haohao:TcpBinaryMessage 和 TcpJsonMessage 保持一致哈?
  88 +
72 89 }
73 90  
74 91 @Override
... ... @@ -83,13 +100,14 @@ public class IotTcpBinaryDeviceMessageCodec implements IotDeviceMessageCodec {
83 100  
84 101 try {
85 102 // 1. 确定功能码
86   - short code = MessageMethod.STATE_ONLINE.equals(message.getMethod()) ? TcpDataPackage.CODE_HEARTBEAT
87   - : TcpDataPackage.CODE_MESSAGE_UP;
  103 + short code = MessageMethod.STATE_ONLINE.equals(message.getMethod())
  104 + ? TcpDataPackage.CODE_HEARTBEAT : TcpDataPackage.CODE_MESSAGE_UP;
88 105  
89 106 // 2. 构建负载数据
90 107 String payload = buildPayload(message);
91 108  
92 109 // 3. 构建 TCP 数据包
  110 + // TODO @haohao:这个和 AlinkMessage.id 是不是一致的哈?
93 111 short mid = (short) (System.currentTimeMillis() % Short.MAX_VALUE);
94 112 TcpDataPackage dataPackage = new TcpDataPackage(code, mid, payload);
95 113  
... ... @@ -101,7 +119,6 @@ public class IotTcpBinaryDeviceMessageCodec implements IotDeviceMessageCodec {
101 119 }
102 120  
103 121 @Override
104   - @SuppressWarnings("DataFlowIssue")
105 122 public IotDeviceMessage decode(byte[] bytes) {
106 123 Assert.notNull(bytes, "待解码数据不能为空");
107 124 Assert.isTrue(bytes.length > 0, "待解码数据不能为空");
... ... @@ -188,21 +205,20 @@ public class IotTcpBinaryDeviceMessageCodec implements IotDeviceMessageCodec {
188 205 Assert.notNull(dataPackage, "数据包对象不能为空");
189 206 Assert.notNull(dataPackage.getPayload(), "负载不能为空");
190 207  
191   - Buffer buffer = Buffer.buffer();
192   -
193 208 // 1. 计算包体长度(除了包头 4 字节)
194 209 int payloadLength = dataPackage.getPayload().getBytes().length;
195 210 int totalLength = 2 + 2 + payloadLength;
196 211  
197   - // 2. 写入包头:总长度(4 字节)
  212 + // 2. 写入数据
  213 + Buffer buffer = Buffer.buffer();
  214 + // 2.1 写入包头:总长度(4 字节)
198 215 buffer.appendInt(totalLength);
199   - // 3. 写入功能码(2 字节)
  216 + // 2.2 写入功能码(2 字节)
200 217 buffer.appendShort(dataPackage.getCode());
201   - // 4. 写入消息序号(2 字节)
  218 + // 2.3 写入消息序号(2 字节)
202 219 buffer.appendShort(dataPackage.getMid());
203   - // 5. 写入包体数据(不定长)
  220 + // 2.4 写入包体数据(不定长)
204 221 buffer.appendBytes(dataPackage.getPayload().getBytes());
205   -
206 222 return buffer;
207 223 }
208 224  
... ... @@ -216,18 +232,14 @@ public class IotTcpBinaryDeviceMessageCodec implements IotDeviceMessageCodec {
216 232 Assert.isTrue(buffer.length() >= 8, "数据包长度不足");
217 233  
218 234 int index = 0;
219   -
220 235 // 1. 跳过包头(4 字节)
221 236 index += 4;
222   -
223 237 // 2. 获取功能码(2 字节)
224 238 short code = buffer.getShort(index);
225 239 index += 2;
226   -
227 240 // 3. 获取消息序号(2 字节)
228 241 short mid = buffer.getShort(index);
229 242 index += 2;
230   -
231 243 // 4. 获取包体数据
232 244 String payload = "";
233 245 if (index < buffer.length()) {
... ... @@ -239,14 +251,17 @@ public class IotTcpBinaryDeviceMessageCodec implements IotDeviceMessageCodec {
239 251  
240 252 // ==================== 内部类 ====================
241 253  
  254 + // TODO @haohao:会不会存在 reply 的时候,有 data、msg、code 参数哈。
242 255 /**
243 256 * 负载信息类
244 257 */
245 258 @Data
246 259 @AllArgsConstructor
247 260 private static class PayloadInfo {
  261 +
248 262 private String requestId;
249 263 private Object params;
  264 +
250 265 }
251 266  
252 267 /**
... ... @@ -255,6 +270,7 @@ public class IotTcpBinaryDeviceMessageCodec implements IotDeviceMessageCodec {
255 270 @Data
256 271 @AllArgsConstructor
257 272 private static class TcpDataPackage {
  273 +
258 274 // 功能码定义
259 275 public static final short CODE_REGISTER = 10;
260 276 public static final short CODE_REGISTER_REPLY = 11;
... ... @@ -263,9 +279,11 @@ public class IotTcpBinaryDeviceMessageCodec implements IotDeviceMessageCodec {
263 279 public static final short CODE_MESSAGE_UP = 30;
264 280 public static final short CODE_MESSAGE_DOWN = 40;
265 281  
  282 + // TODO @haohao:要不改成 opCode
266 283 private short code;
267 284 private short mid;
268 285 private String payload;
  286 +
269 287 }
270 288  
271 289 // ==================== 常量定义 ====================
... ... @@ -274,12 +292,15 @@ public class IotTcpBinaryDeviceMessageCodec implements IotDeviceMessageCodec {
274 292 * 消息方法常量
275 293 */
276 294 public static class MessageMethod {
  295 +
277 296 public static final String PROPERTY_POST = "thing.property.post"; // 数据上报
278 297 public static final String STATE_ONLINE = "thing.state.online"; // 心跳
  298 +
279 299 }
280 300  
281 301 // ==================== 自定义异常 ====================
282 302  
  303 + // TODO @haohao:全局异常搞个。看着可以服用哈。
283 304 /**
284 305 * TCP 编解码异常
285 306 */
... ... @@ -288,4 +309,5 @@ public class IotTcpBinaryDeviceMessageCodec implements IotDeviceMessageCodec {
288 309 super(message, cause);
289 310 }
290 311 }
  312 +
291 313 }
292 314 \ No newline at end of file
... ...
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/codec/tcp/IotTcpJsonDeviceMessageCodec.java
... ... @@ -12,15 +12,14 @@ import org.springframework.stereotype.Component;
12 12 /**
13 13 * TCP JSON 格式 {@link IotDeviceMessage} 编解码器
14 14 *
15   - * 采用纯 JSON 格式传输
16   - *
17   - * JSON 消息格式:
  15 + * 采用纯 JSON 格式传输,格式如下:
18 16 * {
19   - * "id": "消息 ID",
20   - * "method": "消息方法",
21   - * "deviceId": "设备 ID",
22   - * "params": {...},
23   - * "timestamp": 时间戳
  17 + * "id": "消息 ID",
  18 + * "method": "消息方法",
  19 + * "deviceId": "设备 ID",
  20 + * "params": {...},
  21 + * "timestamp": 时间戳
  22 + * // TODO @haohao:貌似少了 code、msg、timestamp
24 23 * }
25 24 *
26 25 * @author 芋道源码
... ... @@ -45,6 +44,7 @@ public class IotTcpJsonDeviceMessageCodec implements IotDeviceMessageCodec {
45 44 */
46 45 private String method;
47 46  
  47 + // TODO @haohao:这个字段,是不是没用到呀?感觉应该也不在消息列哈?
48 48 /**
49 49 * 设备 ID
50 50 */
... ... @@ -84,14 +84,9 @@ public class IotTcpJsonDeviceMessageCodec implements IotDeviceMessageCodec {
84 84  
85 85 @Override
86 86 public byte[] encode(IotDeviceMessage message) {
87   - TcpJsonMessage tcpJsonMessage = new TcpJsonMessage(
88   - message.getRequestId(),
89   - message.getMethod(),
  87 + TcpJsonMessage tcpJsonMessage = new TcpJsonMessage(message.getRequestId(), message.getMethod(),
90 88 message.getDeviceId(),
91   - message.getParams(),
92   - message.getData(),
93   - message.getCode(),
94   - message.getMsg(),
  89 + message.getParams(), message.getData(), message.getCode(), message.getMsg(),
95 90 System.currentTimeMillis());
96 91 return JsonUtils.toJsonByte(tcpJsonMessage);
97 92 }
... ... @@ -102,13 +97,9 @@ public class IotTcpJsonDeviceMessageCodec implements IotDeviceMessageCodec {
102 97 TcpJsonMessage tcpJsonMessage = JsonUtils.parseObject(bytes, TcpJsonMessage.class);
103 98 Assert.notNull(tcpJsonMessage, "消息不能为空");
104 99 Assert.notBlank(tcpJsonMessage.getMethod(), "消息方法不能为空");
105   - IotDeviceMessage iotDeviceMessage = IotDeviceMessage.of(
106   - tcpJsonMessage.getId(),
107   - tcpJsonMessage.getMethod(),
108   - tcpJsonMessage.getParams(),
109   - tcpJsonMessage.getData(),
110   - tcpJsonMessage.getCode(),
111   - tcpJsonMessage.getMsg());
  100 + // TODO @haohao:这个我已经改了哈。一些属性,可以放在一行,好理解一点~
  101 + IotDeviceMessage iotDeviceMessage = IotDeviceMessage.of(tcpJsonMessage.getId(), tcpJsonMessage.getMethod(),
  102 + tcpJsonMessage.getParams(), tcpJsonMessage.getData(), tcpJsonMessage.getCode(), tcpJsonMessage.getMsg());
112 103 iotDeviceMessage.setDeviceId(tcpJsonMessage.getDeviceId());
113 104 return iotDeviceMessage;
114 105 }
... ...
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/tcp/IotTcpDownstreamSubscriber.java
... ... @@ -27,10 +27,12 @@ public class IotTcpDownstreamSubscriber implements IotMessageSubscriber&lt;IotDevic
27 27  
28 28 private final IotTcpUpstreamProtocol protocol;
29 29  
  30 + // todo @haohao:不用的变量,可以去掉哈
30 31 private final IotDeviceService deviceService;
31 32  
32 33 private final IotTcpSessionManager sessionManager;
33 34  
  35 + // TODO @haohao:lombok 简化
34 36 public IotTcpDownstreamSubscriber(IotTcpUpstreamProtocol protocol,
35 37 IotDeviceMessageService messageService,
36 38 IotDeviceService deviceService,
... ...
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/tcp/manager/IotTcpAuthManager.java
... ... @@ -24,6 +24,7 @@ public class IotTcpAuthManager {
24 24 */
25 25 private final Map<NetSocket, AuthInfo> authStatusMap = new ConcurrentHashMap<>();
26 26  
  27 + // TODO @haohao:得考虑,一个设备连接多次?
27 28 /**
28 29 * 设备 ID -> NetSocket 的映射(用于快速查找)
29 30 */
... ... @@ -37,6 +38,7 @@ public class IotTcpAuthManager {
37 38 */
38 39 public void registerAuth(NetSocket socket, AuthInfo authInfo) {
39 40 // 如果设备已有其他连接,先清理旧连接
  41 + // TODO @haohao:是不是允许同时连接?就像 mqtt 应该也允许重复连接哈?
40 42 NetSocket oldSocket = deviceSocketMap.get(authInfo.getDeviceId());
41 43 if (oldSocket != null && oldSocket != socket) {
42 44 log.info("[registerAuth][设备已有其他连接,清理旧连接] 设备 ID: {}, 旧连接: {}",
... ... @@ -66,6 +68,7 @@ public class IotTcpAuthManager {
66 68 }
67 69 }
68 70  
  71 + // TODO @haohao:建议暂时没用的方法,可以删除掉;整体聚焦!
69 72 /**
70 73 * 注销设备认证信息
71 74 *
... ... @@ -158,6 +161,7 @@ public class IotTcpAuthManager {
158 161 int count = authStatusMap.size();
159 162 authStatusMap.clear();
160 163 deviceSocketMap.clear();
  164 + // TODO @haohao:第一个括号是方法,第二个括号是明细日志;其它日志,也可以检查下哈。
161 165 log.info("[clearAll][清理所有认证信息] 清理数量: {}", count);
162 166 }
163 167  
... ... @@ -166,6 +170,7 @@ public class IotTcpAuthManager {
166 170 */
167 171 @Data
168 172 public static class AuthInfo {
  173 +
169 174 /**
170 175 * 设备编号
171 176 */
... ... @@ -181,6 +186,7 @@ public class IotTcpAuthManager {
181 186 */
182 187 private String deviceName;
183 188  
  189 + // TODO @haohao:令牌不要存储,万一有安全问题哈;
184 190 /**
185 191 * 认证令牌
186 192 */
... ... @@ -190,5 +196,7 @@ public class IotTcpAuthManager {
190 196 * 客户端 ID
191 197 */
192 198 private String clientId;
  199 +
193 200 }
  201 +
194 202 }
195 203 \ No newline at end of file
... ...
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/tcp/manager/IotTcpSessionManager.java
... ... @@ -7,6 +7,7 @@ import org.springframework.stereotype.Component;
7 7 import java.util.Map;
8 8 import java.util.concurrent.ConcurrentHashMap;
9 9  
  10 +// TODO @haohao:IotTcpSessionManager、IotTcpAuthManager 是不是融合哈?
10 11 /**
11 12 * IoT 网关 TCP 会话管理器
12 13 * <p>
... ...
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/tcp/router/IotTcpDownstreamHandler.java
... ... @@ -21,6 +21,7 @@ public class IotTcpDownstreamHandler {
21 21  
22 22 private final IotTcpSessionManager sessionManager;
23 23  
  24 + // TODO @haohao:这个可以使用 lombok 简化构造方法
24 25 public IotTcpDownstreamHandler(IotDeviceMessageService messageService,
25 26 IotDeviceService deviceService, IotTcpSessionManager sessionManager) {
26 27 this.messageService = messageService;
... ... @@ -38,6 +39,7 @@ public class IotTcpDownstreamHandler {
38 39 log.info("[handle][处理下行消息] 设备 ID: {}, 方法: {}, 消息 ID: {}",
39 40 message.getDeviceId(), message.getMethod(), message.getId());
40 41  
  42 + // TODO @haohao 1. 和 2. 可以合成 1.1 1.2 并且中间可以不空行;
41 43 // 1. 获取设备信息
42 44 IotDeviceRespDTO device = deviceService.getDeviceFromCache(message.getDeviceId());
43 45 if (device == null) {
... ... @@ -62,11 +64,12 @@ public class IotTcpDownstreamHandler {
62 64 } else {
63 65 log.error("[handle][下行消息发送失败] 设备 ID: {}, 方法: {}, 消息 ID: {}",
64 66 message.getDeviceId(), message.getMethod(), message.getId());
65   - }
  67 + } // TODO @haohao:下面这个空行,可以考虑去掉的哈。
66 68  
67 69 } catch (Exception e) {
68 70 log.error("[handle][处理下行消息失败] 设备 ID: {}, 方法: {}, 消息内容: {}",
69 71 message.getDeviceId(), message.getMethod(), message.getParams(), e);
70 72 }
71 73 }
  74 +
72 75 }
73 76 \ No newline at end of file
... ...
yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/tcp/router/IotTcpUpstreamHandler.java
... ... @@ -8,6 +8,7 @@ import cn.hutool.json.JSONObject;
8 8 import cn.hutool.json.JSONUtil;
9 9 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
10 10 import cn.iocoder.yudao.module.iot.core.biz.IotDeviceCommonApi;
  11 +import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceAuthReqDTO;
11 12 import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceRespDTO;
12 13 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
13 14 import cn.iocoder.yudao.module.iot.core.util.IotDeviceAuthUtils;
... ... @@ -28,8 +29,10 @@ import lombok.extern.slf4j.Slf4j;
28 29 @Slf4j
29 30 public class IotTcpUpstreamHandler implements Handler<NetSocket> {
30 31  
  32 + // TODO @haohao:这两个变量,可以复用 IotTcpBinaryDeviceMessageCodec 的 TYPE
31 33 private static final String CODEC_TYPE_JSON = "TCP_JSON";
32 34 private static final String CODEC_TYPE_BINARY = "TCP_BINARY";
  35 +
33 36 private static final String AUTH_METHOD = "auth";
34 37  
35 38 private final IotDeviceMessageService deviceMessageService;
... ... @@ -89,6 +92,7 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; {
89 92 return;
90 93 }
91 94  
  95 + // TODO @haohao:2. 和 3. 可以合并成 2.1 2.2 ,都是异常的情况。然后 3. 可以 return 直接;
92 96 // 2. 获取设备信息
93 97 IotDeviceRespDTO device = deviceService.getDeviceFromCache(messageInfo.message.getDeviceId());
94 98 if (device == null) {
... ... @@ -114,12 +118,13 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; {
114 118 private void handleAuthRequest(String clientId, IotDeviceMessage message, NetSocket socket, String codecType) {
115 119 try {
116 120 // 1. 验证认证请求
  121 + // TODO @haohao:ObjUtil.notEquals。减少取反
117 122 if (!AUTH_METHOD.equals(message.getMethod())) {
118 123 sendError(socket, message.getRequestId(), "请先进行认证", codecType);
119 124 return;
120 125 }
121 126  
122   - // 2. 解析认证参数
  127 + // 2. 解析认证参数 // TODO @haohao:1. 和 2. 可以合并成 1.1 1.2 都是参数校验
123 128 AuthParams authParams = parseAuthParams(message.getParams());
124 129 if (authParams == null) {
125 130 sendError(socket, message.getRequestId(), "认证参数不完整", codecType);
... ... @@ -127,6 +132,7 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; {
127 132 }
128 133  
129 134 // 3. 执行认证流程
  135 + // TODO @haohao:成功失败、都大哥日志,会不会更好哈?
130 136 if (performAuthentication(authParams, socket, message.getRequestId(), codecType)) {
131 137 log.info("[handleAuthRequest][认证成功] 客户端 ID: {}, username: {}", clientId, authParams.username);
132 138 }
... ... @@ -157,6 +163,7 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; {
157 163 /**
158 164 * 解码消息
159 165 */
  166 + // TODO @haohao:是不是还是直接管理后台配置协议,然后直接使用就好啦。暂时不考虑动态解析哈。保持一致,降低理解成本哈。
160 167 private MessageInfo decodeMessage(Buffer buffer) {
161 168 try {
162 169 String rawData = buffer.toString();
... ... @@ -172,6 +179,7 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; {
172 179 /**
173 180 * 执行认证
174 181 */
  182 + // TODO @haohao:下面的 1. 2. 可以合并下,本质也是校验哈。
175 183 private boolean performAuthentication(AuthParams authParams, NetSocket socket, String requestId, String codecType) {
176 184 // 1. 执行认证
177 185 if (!authenticateDevice(authParams)) {
... ... @@ -202,7 +210,6 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; {
202 210 deviceMessageService.sendDeviceMessage(onlineMessage, deviceInfo.getProductKey(), deviceInfo.getDeviceName(),
203 211 serverId);
204 212 sendSuccess(socket, requestId, "认证成功", codecType);
205   -
206 213 return true;
207 214 }
208 215  
... ... @@ -252,8 +259,9 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; {
252 259 * 判断是否为 JSON 格式
253 260 */
254 261 private boolean isJsonFormat(String data) {
255   - if (StrUtil.isBlank(data))
  262 + if (StrUtil.isBlank(data)) {
256 263 return false;
  264 + }
257 265 String trimmed = data.trim();
258 266 return (trimmed.startsWith("{") && trimmed.endsWith("}")) || (trimmed.startsWith("[") && trimmed.endsWith("]"));
259 267 }
... ... @@ -262,15 +270,14 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; {
262 270 * 解析认证参数
263 271 */
264 272 private AuthParams parseAuthParams(Object params) {
265   - if (params == null)
  273 + if (params == null) {
266 274 return null;
267   -
  275 + }
268 276 JSONObject paramsJson = params instanceof JSONObject ? (JSONObject) params
269 277 : JSONUtil.parseObj(params.toString());
270 278 String clientId = paramsJson.getStr("clientId");
271 279 String username = paramsJson.getStr("username");
272 280 String password = paramsJson.getStr("password");
273   -
274 281 return StrUtil.hasBlank(clientId, username, password) ? null : new AuthParams(clientId, username, password);
275 282 }
276 283  
... ... @@ -278,11 +285,8 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; {
278 285 * 认证设备
279 286 */
280 287 private boolean authenticateDevice(AuthParams authParams) {
281   - CommonResult<Boolean> result = deviceApi
282   - .authDevice(new cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceAuthReqDTO()
283   - .setClientId(authParams.clientId)
284   - .setUsername(authParams.username)
285   - .setPassword(authParams.password));
  288 + CommonResult<Boolean> result = deviceApi.authDevice(new IotDeviceAuthReqDTO()
  289 + .setClientId(authParams.clientId).setUsername(authParams.username).setPassword(authParams.password));
286 290 return result.isSuccess() && result.getData();
287 291 }
288 292  
... ... @@ -291,6 +295,7 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; {
291 295 */
292 296 private void registerAuthInfo(NetSocket socket, IotDeviceRespDTO device, IotDeviceAuthUtils.DeviceInfo deviceInfo,
293 297 String token, String clientId) {
  298 + // TODO @haohao:可以链式调用;
294 299 IotTcpAuthManager.AuthInfo auth = new IotTcpAuthManager.AuthInfo();
295 300 auth.setDeviceId(device.getId());
296 301 auth.setProductKey(deviceInfo.getProductKey());
... ... @@ -316,6 +321,8 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; {
316 321 sendResponse(socket, true, message, requestId, codecType);
317 322 }
318 323  
  324 + // TODO @haohao:使用 lombok,方便 jdk8 兼容
  325 +
319 326 /**
320 327 * 认证参数
321 328 */
... ... @@ -327,4 +334,5 @@ public class IotTcpUpstreamHandler implements Handler&lt;NetSocket&gt; {
327 334 */
328 335 private record MessageInfo(IotDeviceMessage message, String codecType) {
329 336 }
  337 +
330 338 }
331 339 \ No newline at end of file
... ...