2026-06-24 f4bd1f3c89d906131495a0aca5aaf82966378510
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
package cn.iocoder.yudao.module.iot.service.rule.scene.timer;
 
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionOperatorEnum;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum;
import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
import cn.iocoder.yudao.module.iot.service.device.property.IotDevicePropertyService;
import cn.iocoder.yudao.module.iot.service.rule.scene.IotSceneRuleTimeHelper;
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcherHelper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
 
import java.util.Map;
 
/**
 * IoT 定时触发器条件评估器
 * <p>
 * 与设备触发器不同,定时触发器没有设备消息上下文,
 * 需要主动查询设备属性和状态来评估条件。
 *
 * @author HUIHUI
 */
@Component
@Slf4j
public class IotTimerConditionEvaluator {
 
    @Resource
    private IotDevicePropertyService devicePropertyService;
 
    @Resource
    private IotDeviceService deviceService;
 
    /**
     * 评估条件
     *
     * @param condition 条件配置
     * @return 是否满足条件
     */
    @SuppressWarnings("EnhancedSwitchMigration")
    public boolean evaluate(IotSceneRuleDO.TriggerCondition condition) {
        // 1.1 基础参数校验
        if (condition == null || condition.getType() == null) {
            log.warn("[evaluate][条件为空或类型为空]");
            return false;
        }
        // 1.2 根据条件类型分发到具体的评估方法
        IotSceneRuleConditionTypeEnum conditionType =
                IotSceneRuleConditionTypeEnum.typeOf(condition.getType());
        if (conditionType == null) {
            log.warn("[evaluate][未知的条件类型: {}]", condition.getType());
            return false;
        }
 
        // 2. 分发评估
        switch (conditionType) {
            case DEVICE_PROPERTY:
                return evaluateDevicePropertyCondition(condition);
            case DEVICE_STATE:
                return evaluateDeviceStateCondition(condition);
            case CURRENT_TIME:
                return evaluateCurrentTimeCondition(condition);
            default:
                log.warn("[evaluate][未知的条件类型: {}]", conditionType);
                return false;
        }
    }
 
    /**
     * 评估设备属性条件
     *
     * @param condition 条件配置
     * @return 是否满足条件
     */
    private boolean evaluateDevicePropertyCondition(IotSceneRuleDO.TriggerCondition condition) {
        // 1. 校验必要参数
        if (condition.getDeviceId() == null) {
            log.debug("[evaluateDevicePropertyCondition][设备ID为空]");
            return false;
        }
        if (StrUtil.isBlank(condition.getIdentifier())) {
            log.debug("[evaluateDevicePropertyCondition][属性标识符为空]");
            return false;
        }
        if (!IotSceneRuleMatcherHelper.isConditionOperatorAndParamValid(condition)) {
            log.debug("[evaluateDevicePropertyCondition][操作符或参数无效]");
            return false;
        }
 
        // 2.1 获取设备最新属性值
        Map<String, IotDevicePropertyDO> properties =
                devicePropertyService.getLatestDeviceProperties(condition.getDeviceId());
        if (CollUtil.isEmpty(properties)) {
            log.debug("[evaluateDevicePropertyCondition][设备({}) 无属性数据]", condition.getDeviceId());
            return false;
        }
        // 2.2 获取指定属性
        IotDevicePropertyDO property = properties.get(condition.getIdentifier());
        if (property == null || property.getValue() == null) {
            log.debug("[evaluateDevicePropertyCondition][设备({}) 属性({}) 不存在或值为空]",
                    condition.getDeviceId(), condition.getIdentifier());
            return false;
        }
 
        // 3. 使用现有的条件评估逻辑进行比较
        boolean matched = IotSceneRuleMatcherHelper.evaluateCondition(
                property.getValue(), condition.getOperator(), condition.getParam());
        log.debug("[evaluateDevicePropertyCondition][设备({}) 属性({}) 值({}) 操作符({}) 参数({}) 匹配结果: {}]",
                condition.getDeviceId(), condition.getIdentifier(), property.getValue(),
                condition.getOperator(), condition.getParam(), matched);
        return matched;
    }
 
    /**
     * 评估设备状态条件
     *
     * @param condition 条件配置
     * @return 是否满足条件
     */
    private boolean evaluateDeviceStateCondition(IotSceneRuleDO.TriggerCondition condition) {
        // 1. 校验必要参数
        if (condition.getDeviceId() == null) {
            log.debug("[evaluateDeviceStateCondition][设备ID为空]");
            return false;
        }
        if (!IotSceneRuleMatcherHelper.isConditionOperatorAndParamValid(condition)) {
            log.debug("[evaluateDeviceStateCondition][操作符或参数无效]");
            return false;
        }
 
        // 2.1 获取设备信息
        IotDeviceDO device = deviceService.getDevice(condition.getDeviceId());
        if (device == null) {
            log.debug("[evaluateDeviceStateCondition][设备({}) 不存在]", condition.getDeviceId());
            return false;
        }
        // 2.2 获取设备状态
        Integer state = device.getState();
        if (state == null) {
            log.debug("[evaluateDeviceStateCondition][设备({}) 状态为空]", condition.getDeviceId());
            return false;
        }
 
        // 3. 比较状态
        boolean matched = IotSceneRuleMatcherHelper.evaluateCondition(
                state.toString(), condition.getOperator(), condition.getParam());
        log.debug("[evaluateDeviceStateCondition][设备({}) 状态({}) 操作符({}) 参数({}) 匹配结果: {}]",
                condition.getDeviceId(), state, condition.getOperator(), condition.getParam(), matched);
        return matched;
    }
 
    /**
     * 评估当前时间条件
     *
     * @param condition 条件配置
     * @return 是否满足条件
     */
    private boolean evaluateCurrentTimeCondition(IotSceneRuleDO.TriggerCondition condition) {
        // 1.1 校验必要参数
        if (!IotSceneRuleMatcherHelper.isConditionOperatorAndParamValid(condition)) {
            log.debug("[evaluateCurrentTimeCondition][操作符或参数无效]");
            return false;
        }
        // 1.2 验证操作符是否为支持的时间操作符
        IotSceneRuleConditionOperatorEnum operatorEnum =
                IotSceneRuleConditionOperatorEnum.operatorOf(condition.getOperator());
        if (operatorEnum == null) {
            log.debug("[evaluateCurrentTimeCondition][无效的操作符: {}]", condition.getOperator());
            return false;
        }
        if (IotSceneRuleTimeHelper.isTimeOperator(operatorEnum)) {
            log.debug("[evaluateCurrentTimeCondition][不支持的时间操作符: {}]", condition.getOperator());
            return false;
        }
 
        // 2. 执行时间匹配
        boolean matched = IotSceneRuleTimeHelper.executeTimeMatching(operatorEnum, condition.getParam());
        log.debug("[evaluateCurrentTimeCondition][操作符({}) 参数({}) 匹配结果: {}]",
                condition.getOperator(), condition.getParam(), matched);
        return matched;
    }
 
}