Commit 9be7d6fac003b9d011288a0a0194126242001a0d

Authored by YunaiV
1 parent f3878c30

review(iot):【场景联动】增加相关的 review 说明

yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/action/IotWebSocketDataRuleAction.java
... ... @@ -97,6 +97,7 @@ public class IotWebSocketDataRuleAction extends
97 97 }
98 98 }
99 99  
  100 + // TODO @puhui999:为什么这里要加锁呀?
100 101 /**
101 102 * 使用锁进行重连,保证同一服务器地址的重连操作线程安全
102 103 *
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/action/websocket/IotWebSocketClient.java
... ... @@ -67,7 +67,6 @@ public class IotWebSocketClient {
67 67 // 使用 CountDownLatch 等待连接完成
68 68 CountDownLatch connectLatch = new CountDownLatch(1);
69 69 AtomicBoolean connectSuccess = new AtomicBoolean(false);
70   -
71 70 // 创建 WebSocket 连接
72 71 webSocket = okHttpClient.newWebSocket(request, new IotWebSocketListener(connectLatch, connectSuccess));
73 72  
... ... @@ -77,7 +76,6 @@ public class IotWebSocketClient {
77 76 close();
78 77 throw new Exception("WebSocket 连接超时或失败,服务器地址: " + serverUrl);
79 78 }
80   -
81 79 log.info("[connect][WebSocket 客户端连接成功,服务器地址: {}]", serverUrl);
82 80 } catch (Exception e) {
83 81 close();
... ... @@ -126,6 +124,7 @@ public class IotWebSocketClient {
126 124 try {
127 125 if (webSocket != null) {
128 126 // 发送正常关闭帧,状态码 1000 表示正常关闭
  127 + // TODO @puhui999:有没 1000 的枚举哈?在 okhttp 里
129 128 webSocket.close(1000, "客户端主动关闭");
130 129 webSocket = null;
131 130 }
... ... @@ -163,6 +162,7 @@ public class IotWebSocketClient {
163 162 /**
164 163 * OkHttp WebSocket 监听器
165 164 */
  165 + @SuppressWarnings("NullableProblems")
166 166 private class IotWebSocketListener extends WebSocketListener {
167 167  
168 168 private final CountDownLatch connectLatch;
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/IotSceneRuleTimeHelper.java
... ... @@ -4,6 +4,8 @@ import cn.hutool.core.lang.Assert;
4 4 import cn.hutool.core.text.CharPool;
5 5 import cn.hutool.core.util.StrUtil;
6 6 import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionOperatorEnum;
  7 +import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.condition.IotCurrentTimeConditionMatcher;
  8 +import cn.iocoder.yudao.module.iot.service.rule.scene.timer.IotTimerConditionEvaluator;
7 9 import lombok.extern.slf4j.Slf4j;
8 10  
9 11 import java.time.LocalDateTime;
... ... @@ -15,8 +17,7 @@ import java.util.List;
15 17 /**
16 18 * IoT 场景规则时间匹配工具类
17 19 * <p>
18   - * 提供时间条件匹配的通用方法,供 {@link cn.iocoder.yudao.module.iot.service.rule.scene.matcher.condition.IotCurrentTimeConditionMatcher}
19   - * 和 {@link cn.iocoder.yudao.module.iot.service.rule.scene.timer.IotTimerConditionEvaluator} 共同使用。
  20 + * 提供时间条件匹配的通用方法,供 {@link IotCurrentTimeConditionMatcher} 和 {@link IotTimerConditionEvaluator} 共同使用。
20 21 *
21 22 * @author HUIHUI
22 23 */
... ... @@ -33,6 +34,7 @@ public class IotSceneRuleTimeHelper {
33 34 */
34 35 private static final DateTimeFormatter TIME_FORMATTER_SHORT = DateTimeFormatter.ofPattern("HH:mm");
35 36  
  37 + // TODO @puhui999:可以使用 lombok 简化
36 38 private IotSceneRuleTimeHelper() {
37 39 // 工具类,禁止实例化
38 40 }
... ... @@ -94,6 +96,7 @@ public class IotSceneRuleTimeHelper {
94 96 * @param param 参数值
95 97 * @return 是否匹配
96 98 */
  99 + @SuppressWarnings("EnhancedSwitchMigration")
97 100 public static boolean matchDateTime(long currentTimestamp, IotSceneRuleConditionOperatorEnum operatorEnum,
98 101 String param) {
99 102 try {
... ... @@ -133,6 +136,7 @@ public class IotSceneRuleTimeHelper {
133 136 }
134 137 long startTimestamp = Long.parseLong(timestampRange.get(0).trim());
135 138 long endTimestamp = Long.parseLong(timestampRange.get(1).trim());
  139 + // TODO @puhui999:hutool 里,看看有没 between 方法
136 140 return currentTimestamp >= startTimestamp && currentTimestamp <= endTimestamp;
137 141 }
138 142  
... ... @@ -144,6 +148,7 @@ public class IotSceneRuleTimeHelper {
144 148 * @param param 参数值
145 149 * @return 是否匹配
146 150 */
  151 + @SuppressWarnings("EnhancedSwitchMigration")
147 152 public static boolean matchTime(LocalTime currentTime, IotSceneRuleConditionOperatorEnum operatorEnum,
148 153 String param) {
149 154 try {
... ... @@ -183,6 +188,7 @@ public class IotSceneRuleTimeHelper {
183 188 }
184 189 LocalTime startTime = parseTime(timeRange.get(0).trim());
185 190 LocalTime endTime = parseTime(timeRange.get(1).trim());
  191 + // TODO @puhui999:hutool 里,看看有没 between 方法
186 192 return !currentTime.isBefore(startTime) && !currentTime.isAfter(endTime);
187 193 }
188 194  
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/matcher/trigger/IotDeviceServiceInvokeTriggerMatcher.java
... ... @@ -31,13 +31,11 @@ public class IotDeviceServiceInvokeTriggerMatcher implements IotSceneRuleTrigger
31 31 IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "触发器基础参数无效");
32 32 return false;
33 33 }
34   -
35 34 // 1.2 检查消息方法是否匹配
36 35 if (!IotDeviceMessageMethodEnum.SERVICE_INVOKE.getMethod().equals(message.getMethod())) {
37 36 IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "消息方法不匹配,期望: " + IotDeviceMessageMethodEnum.SERVICE_INVOKE.getMethod() + ", 实际: " + message.getMethod());
38 37 return false;
39 38 }
40   -
41 39 // 1.3 检查标识符是否匹配
42 40 String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message);
43 41 if (!IotSceneRuleMatcherHelper.isIdentifierMatched(trigger.getIdentifier(), messageIdentifier)) {
... ... @@ -73,21 +71,21 @@ public class IotDeviceServiceInvokeTriggerMatcher implements IotSceneRuleTrigger
73 71 * @return 是否匹配
74 72 */
75 73 private boolean matchParameterCondition(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger) {
76   - // 从消息中提取服务调用的输入参数
  74 + // 1.1 从消息中提取服务调用的输入参数
77 75 Map<String, Object> inputParams = IotDeviceMessageUtils.extractServiceInputParams(message);
  76 + // TODO @puhui999:要考虑 empty 的情况么?
78 77 if (inputParams == null) {
79 78 IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "消息中缺少服务输入参数");
80 79 return false;
81 80 }
82   -
83   - // 获取要匹配的参数值(使用 identifier 作为参数名)
  81 + // 1.2 获取要匹配的参数值(使用 identifier 作为参数名)
84 82 Object paramValue = inputParams.get(trigger.getIdentifier());
85 83 if (paramValue == null) {
86 84 IotSceneRuleMatcherHelper.logTriggerMatchFailure(message, trigger, "服务输入参数中缺少指定参数: " + trigger.getIdentifier());
87 85 return false;
88 86 }
89 87  
90   - // 使用条件评估器进行匹配
  88 + // 2. 使用条件评估器进行匹配
91 89 boolean matched = IotSceneRuleMatcherHelper.evaluateCondition(paramValue, trigger.getOperator(), trigger.getValue());
92 90 if (matched) {
93 91 IotSceneRuleMatcherHelper.logTriggerMatchSuccess(message, trigger);
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/timer/IotTimerConditionEvaluator.java
1 1 package cn.iocoder.yudao.module.iot.service.rule.scene.timer;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.hutool.core.util.StrUtil;
4 5 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
5 6 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
... ... @@ -40,14 +41,14 @@ public class IotTimerConditionEvaluator {
40 41 * @param condition 条件配置
41 42 * @return 是否满足条件
42 43 */
  44 + @SuppressWarnings("EnhancedSwitchMigration")
43 45 public boolean evaluate(IotSceneRuleDO.TriggerCondition condition) {
44   - // 1. 基础参数校验
  46 + // 1.1 基础参数校验
45 47 if (condition == null || condition.getType() == null) {
46 48 log.warn("[evaluate][条件为空或类型为空]");
47 49 return false;
48 50 }
49   -
50   - // 2. 根据条件类型分发到具体的评估方法
  51 + // 1.2 根据条件类型分发到具体的评估方法
51 52 IotSceneRuleConditionTypeEnum conditionType =
52 53 IotSceneRuleConditionTypeEnum.typeOf(condition.getType());
53 54 if (conditionType == null) {
... ... @@ -55,6 +56,7 @@ public class IotTimerConditionEvaluator {
55 56 return false;
56 57 }
57 58  
  59 + // 2. 分发评估
58 60 switch (conditionType) {
59 61 case DEVICE_PROPERTY:
60 62 return evaluateDevicePropertyCondition(condition);
... ... @@ -89,15 +91,14 @@ public class IotTimerConditionEvaluator {
89 91 return false;
90 92 }
91 93  
92   - // 2. 获取设备最新属性值
  94 + // 2.1 获取设备最新属性值
93 95 Map<String, IotDevicePropertyDO> properties =
94 96 devicePropertyService.getLatestDeviceProperties(condition.getDeviceId());
95   - if (properties == null || properties.isEmpty()) {
  97 + if (CollUtil.isEmpty(properties)) {
96 98 log.debug("[evaluateDevicePropertyCondition][设备({}) 无属性数据]", condition.getDeviceId());
97 99 return false;
98 100 }
99   -
100   - // 3. 获取指定属性
  101 + // 2.2 获取指定属性
101 102 IotDevicePropertyDO property = properties.get(condition.getIdentifier());
102 103 if (property == null || property.getValue() == null) {
103 104 log.debug("[evaluateDevicePropertyCondition][设备({}) 属性({}) 不存在或值为空]",
... ... @@ -105,7 +106,7 @@ public class IotTimerConditionEvaluator {
105 106 return false;
106 107 }
107 108  
108   - // 4. 使用现有的条件评估逻辑进行比较
  109 + // 3. 使用现有的条件评估逻辑进行比较
109 110 boolean matched = IotSceneRuleMatcherHelper.evaluateCondition(
110 111 property.getValue(), condition.getOperator(), condition.getParam());
111 112 log.debug("[evaluateDevicePropertyCondition][设备({}) 属性({}) 值({}) 操作符({}) 参数({}) 匹配结果: {}]",
... ... @@ -131,21 +132,20 @@ public class IotTimerConditionEvaluator {
131 132 return false;
132 133 }
133 134  
134   - // 2. 获取设备信息
  135 + // 2.1 获取设备信息
135 136 IotDeviceDO device = deviceService.getDevice(condition.getDeviceId());
136 137 if (device == null) {
137 138 log.debug("[evaluateDeviceStateCondition][设备({}) 不存在]", condition.getDeviceId());
138 139 return false;
139 140 }
140   -
141   - // 3. 获取设备状态
  141 + // 2.2 获取设备状态
142 142 Integer state = device.getState();
143 143 if (state == null) {
144 144 log.debug("[evaluateDeviceStateCondition][设备({}) 状态为空]", condition.getDeviceId());
145 145 return false;
146 146 }
147 147  
148   - // 4. 比较状态
  148 + // 3. 比较状态
149 149 boolean matched = IotSceneRuleMatcherHelper.evaluateCondition(
150 150 state.toString(), condition.getOperator(), condition.getParam());
151 151 log.debug("[evaluateDeviceStateCondition][设备({}) 状态({}) 操作符({}) 参数({}) 匹配结果: {}]",
... ... @@ -160,26 +160,24 @@ public class IotTimerConditionEvaluator {
160 160 * @return 是否满足条件
161 161 */
162 162 private boolean evaluateCurrentTimeCondition(IotSceneRuleDO.TriggerCondition condition) {
163   - // 1. 校验必要参数
  163 + // 1.1 校验必要参数
164 164 if (!IotSceneRuleMatcherHelper.isConditionOperatorAndParamValid(condition)) {
165 165 log.debug("[evaluateCurrentTimeCondition][操作符或参数无效]");
166 166 return false;
167 167 }
168   -
169   - // 2. 验证操作符是否为支持的时间操作符
  168 + // 1.2 验证操作符是否为支持的时间操作符
170 169 IotSceneRuleConditionOperatorEnum operatorEnum =
171 170 IotSceneRuleConditionOperatorEnum.operatorOf(condition.getOperator());
172 171 if (operatorEnum == null) {
173 172 log.debug("[evaluateCurrentTimeCondition][无效的操作符: {}]", condition.getOperator());
174 173 return false;
175 174 }
176   -
177 175 if (IotSceneRuleTimeHelper.isTimeOperator(operatorEnum)) {
178 176 log.debug("[evaluateCurrentTimeCondition][不支持的时间操作符: {}]", condition.getOperator());
179 177 return false;
180 178 }
181 179  
182   - // 3. 执行时间匹配
  180 + // 2. 执行时间匹配
183 181 boolean matched = IotSceneRuleTimeHelper.executeTimeMatching(operatorEnum, condition.getParam());
184 182 log.debug("[evaluateCurrentTimeCondition][操作符({}) 参数({}) 匹配结果: {}]",
185 183 condition.getOperator(), condition.getParam(), matched);
... ...
yudao-module-iot/yudao-module-iot-core/src/main/java/cn/iocoder/yudao/module/iot/core/util/IotDeviceMessageUtils.java
... ... @@ -72,7 +72,7 @@ public class IotDeviceMessageUtils {
72 72  
73 73 /**
74 74 * 判断消息中是否包含指定的标识符
75   - *
  75 + * <p>
76 76 * 对于不同消息类型的处理:
77 77 * - EVENT_POST/SERVICE_INVOKE:检查 params.identifier 是否匹配
78 78 * - STATE_UPDATE:检查 params.state 是否匹配
... ... @@ -212,8 +212,8 @@ public class IotDeviceMessageUtils {
212 212 * <p>
213 213 * 服务调用消息的 params 结构通常为:
214 214 * {
215   - * "identifier": "serviceIdentifier",
216   - * "inputData": { ... } 或 "inputParams": { ... }
  215 + * "identifier": "serviceIdentifier",
  216 + * "inputData": { ... } 或 "inputParams": { ... }
217 217 * }
218 218 *
219 219 * @param message 设备消息
... ... @@ -221,6 +221,7 @@ public class IotDeviceMessageUtils {
221 221 */
222 222 @SuppressWarnings("unchecked")
223 223 public static Map<String, Object> extractServiceInputParams(IotDeviceMessage message) {
  224 + // 1. 参数校验
224 225 Object params = message.getParams();
225 226 if (params == null) {
226 227 return null;
... ... @@ -235,13 +236,11 @@ public class IotDeviceMessageUtils {
235 236 if (inputData instanceof Map) {
236 237 return (Map<String, Object>) inputData;
237 238 }
238   -
239 239 // 尝试从 inputParams 字段获取
240 240 Object inputParams = paramsMap.get("inputParams");
241 241 if (inputParams instanceof Map) {
242 242 return (Map<String, Object>) inputParams;
243 243 }
244   -
245 244 return null;
246 245 }
247 246  
... ...