|
|
@@ -1,17 +1,10 @@
|
|
|
-/*
|
|
|
- * 文 件 名: StrategyTriggerListener
|
|
|
- * 版 权: 华设设计集团股份有限公司
|
|
|
- * 描 述: <描述>
|
|
|
- * 修 改 人: lvwenbin
|
|
|
- * 修改时间: 2025/12/9
|
|
|
- * 跟踪单号: <跟踪单号>
|
|
|
- * 修改单号: <修改单号>
|
|
|
- * 修改内容: <修改内容>
|
|
|
- */
|
|
|
package com.ruoyi.ems.task;
|
|
|
|
|
|
+import com.ruoyi.ems.domain.OpEnergyStrategyTrigger;
|
|
|
+import com.ruoyi.ems.service.IOpEnergyStrategyTriggerService;
|
|
|
import com.ruoyi.ems.strategy.evaluator.ConditionEvaluator;
|
|
|
import com.ruoyi.ems.strategy.executor.StrategyExecutor;
|
|
|
+import lombok.Data;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.context.ApplicationContext;
|
|
|
@@ -22,57 +15,45 @@ import java.util.HashMap;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
-import java.util.concurrent.ExecutorService;
|
|
|
-import java.util.concurrent.Executors;
|
|
|
|
|
|
/**
|
|
|
- * 策略触发监听器
|
|
|
- * 由 Controller 的 onAttrValueChanged 接口调用
|
|
|
+ * 策略触发监听器 (事件 / 属性)
|
|
|
+ *
|
|
|
+ * 针对 StrategyScheduler 的新版 registerTrigger() 逻辑进行了修复:
|
|
|
+ * - registerEventTrigger()
|
|
|
+ * - registerAttrTrigger()
|
|
|
+ * - unregisterTriggers()
|
|
|
+ * - clearAll()
|
|
|
+ * - 分发入口 onEventReceived() / onAttrChanged()
|
|
|
+ *
|
|
|
+ * @author
|
|
|
*/
|
|
|
@Slf4j
|
|
|
@Component
|
|
|
public class StrategyTriggerListener {
|
|
|
|
|
|
@Autowired
|
|
|
- private ApplicationContext applicationContext;
|
|
|
+ private IOpEnergyStrategyTriggerService triggerService;
|
|
|
|
|
|
@Autowired
|
|
|
private ConditionEvaluator conditionEvaluator;
|
|
|
|
|
|
- /**
|
|
|
- * StrategyExecutor 延迟加载,避免循环依赖
|
|
|
- */
|
|
|
+ @Autowired
|
|
|
+ private ApplicationContext applicationContext;
|
|
|
+
|
|
|
private StrategyExecutor strategyExecutor;
|
|
|
|
|
|
- /**
|
|
|
- * 属性触发器注册表
|
|
|
- * key: objCode + ":" + attrKey
|
|
|
- * value: 触发器配置列表
|
|
|
- */
|
|
|
- private final Map<String, List<AttrTriggerConfig>> attrTriggers = new ConcurrentHashMap<>();
|
|
|
+ /** key = objCode:eventKey */
|
|
|
+ private final Map<String, List<TriggerInfo>> eventTriggers = new ConcurrentHashMap<>();
|
|
|
|
|
|
- /**
|
|
|
- * 事件触发器注册表
|
|
|
- * key: objCode + ":" + eventKey
|
|
|
- * value: 触发器配置列表
|
|
|
- */
|
|
|
- private final Map<String, List<EventTriggerConfig>> eventTriggers = new ConcurrentHashMap<>();
|
|
|
+ /** key = objCode:attrKey */
|
|
|
+ private final Map<String, List<TriggerInfo>> attrTriggers = new ConcurrentHashMap<>();
|
|
|
|
|
|
- /**
|
|
|
- * 策略代码到触发器Key的映射(用于注销时快速查找)
|
|
|
- * key: strategyCode
|
|
|
- * value: 触发器Key列表 (格式: "ATTR:objCode:attrKey" 或 "EVENT:objCode:eventKey")
|
|
|
- */
|
|
|
- private final Map<String, List<String>> strategyTriggerKeys = new ConcurrentHashMap<>();
|
|
|
+ /** 缓存触发器 → 用于注销 */
|
|
|
+ private final Map<String, List<TriggerInfo>> strategyTriggerIndex = new ConcurrentHashMap<>();
|
|
|
|
|
|
- /**
|
|
|
- * 异步执行线程池
|
|
|
- */
|
|
|
- private final ExecutorService asyncExecutor = Executors.newFixedThreadPool(5);
|
|
|
|
|
|
- /**
|
|
|
- * 获取 StrategyExecutor(延迟加载,避免循环依赖)
|
|
|
- */
|
|
|
+ // 延迟加载
|
|
|
private StrategyExecutor getStrategyExecutor() {
|
|
|
if (strategyExecutor == null) {
|
|
|
synchronized (this) {
|
|
|
@@ -84,399 +65,228 @@ public class StrategyTriggerListener {
|
|
|
return strategyExecutor;
|
|
|
}
|
|
|
|
|
|
- // ==================== 触发器注册方法 ====================
|
|
|
+ /* ============================================================
|
|
|
+ * 注册触发器
|
|
|
+ * ============================================================ */
|
|
|
|
|
|
- /**
|
|
|
- * 注册属性变化触发器
|
|
|
- *
|
|
|
- * @param strategyCode 策略代码
|
|
|
- * @param objCode 设备代码
|
|
|
- * @param attrKey 属性键
|
|
|
- * @param conditionExpr 条件表达式(JSON格式)
|
|
|
- */
|
|
|
- public void registerAttrTrigger(String strategyCode, String objCode, String attrKey, String conditionExpr) {
|
|
|
- String triggerKey = objCode + ":" + attrKey;
|
|
|
-
|
|
|
- // 创建触发器配置
|
|
|
- AttrTriggerConfig config = new AttrTriggerConfig();
|
|
|
- config.strategyCode = strategyCode;
|
|
|
- config.objCode = objCode;
|
|
|
- config.attrKey = attrKey;
|
|
|
- config.conditionExpr = conditionExpr;
|
|
|
-
|
|
|
- // 添加到触发器列表
|
|
|
- List<AttrTriggerConfig> configList = attrTriggers.computeIfAbsent(triggerKey, k -> new ArrayList<>());
|
|
|
-
|
|
|
- // 避免重复注册
|
|
|
- boolean exists = configList.stream().anyMatch(c -> c.strategyCode.equals(strategyCode));
|
|
|
- if (!exists) {
|
|
|
- configList.add(config);
|
|
|
- }
|
|
|
+ /** 单个事件触发器 */
|
|
|
+ public void registerEventTrigger(String strategyCode, OpEnergyStrategyTrigger trigger) {
|
|
|
+ String key = trigger.getSourceObjCode() + ":" + trigger.getEventKey();
|
|
|
|
|
|
- // 记录策略到触发器的映射(用于注销)
|
|
|
- List<String> keys = strategyTriggerKeys.computeIfAbsent(strategyCode, k -> new ArrayList<>());
|
|
|
- String mappingKey = "ATTR:" + triggerKey;
|
|
|
- if (!keys.contains(mappingKey)) {
|
|
|
- keys.add(mappingKey);
|
|
|
- }
|
|
|
-
|
|
|
- log.debug("注册属性触发器: triggerKey={}, strategy={}, condition={}", triggerKey, strategyCode, conditionExpr);
|
|
|
- }
|
|
|
+ TriggerInfo info = new TriggerInfo(strategyCode, trigger);
|
|
|
|
|
|
- /**
|
|
|
- * 注册事件触发器
|
|
|
- *
|
|
|
- * @param strategyCode 策略代码
|
|
|
- * @param objCode 设备代码
|
|
|
- * @param eventKey 事件键
|
|
|
- * @param conditionExpr 条件表达式(JSON格式)
|
|
|
- */
|
|
|
- public void registerEventTrigger(String strategyCode, String objCode, String eventKey, String conditionExpr) {
|
|
|
- String triggerKey = objCode + ":" + eventKey;
|
|
|
-
|
|
|
- // 创建触发器配置
|
|
|
- EventTriggerConfig config = new EventTriggerConfig();
|
|
|
- config.strategyCode = strategyCode;
|
|
|
- config.objCode = objCode;
|
|
|
- config.eventKey = eventKey;
|
|
|
- config.conditionExpr = conditionExpr;
|
|
|
-
|
|
|
- // 添加到触发器列表
|
|
|
- List<EventTriggerConfig> configList = eventTriggers.computeIfAbsent(triggerKey, k -> new ArrayList<>());
|
|
|
-
|
|
|
- // 避免重复注册
|
|
|
- boolean exists = configList.stream().anyMatch(c -> c.strategyCode.equals(strategyCode));
|
|
|
- if (!exists) {
|
|
|
- configList.add(config);
|
|
|
- }
|
|
|
+ eventTriggers.computeIfAbsent(key, k -> new ArrayList<>()).add(info);
|
|
|
|
|
|
- // 记录策略到触发器的映射
|
|
|
- List<String> keys = strategyTriggerKeys.computeIfAbsent(strategyCode, k -> new ArrayList<>());
|
|
|
- String mappingKey = "EVENT:" + triggerKey;
|
|
|
- if (!keys.contains(mappingKey)) {
|
|
|
- keys.add(mappingKey);
|
|
|
- }
|
|
|
+ // 建立反向索引,注销时用
|
|
|
+ strategyTriggerIndex.computeIfAbsent(strategyCode, k -> new ArrayList<>()).add(info);
|
|
|
|
|
|
- log.debug("注册事件触发器: triggerKey={}, strategy={}", triggerKey, strategyCode);
|
|
|
+ log.info("事件触发器已注册: key={}, strategy={}", key, strategyCode);
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 注销策略的所有触发器
|
|
|
- *
|
|
|
- * @param strategyCode 策略代码
|
|
|
- */
|
|
|
- public void unregisterStrategy(String strategyCode) {
|
|
|
- List<String> keys = strategyTriggerKeys.remove(strategyCode);
|
|
|
- if (keys == null || keys.isEmpty()) {
|
|
|
- log.debug("策略[{}]没有注册的触发器", strategyCode);
|
|
|
- return;
|
|
|
- }
|
|
|
+ /** 单个属性触发器 */
|
|
|
+ public void registerAttrTrigger(String strategyCode, OpEnergyStrategyTrigger trigger) {
|
|
|
+ String key = trigger.getSourceObjCode() + ":" + trigger.getAttrKey();
|
|
|
|
|
|
- for (String key : keys) {
|
|
|
- if (key.startsWith("ATTR:")) {
|
|
|
- // 属性触发器
|
|
|
- String triggerKey = key.substring(5); // 去掉 "ATTR:" 前缀
|
|
|
- List<AttrTriggerConfig> configList = attrTriggers.get(triggerKey);
|
|
|
- if (configList != null) {
|
|
|
- configList.removeIf(c -> strategyCode.equals(c.strategyCode));
|
|
|
- if (configList.isEmpty()) {
|
|
|
- attrTriggers.remove(triggerKey);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- else if (key.startsWith("EVENT:")) {
|
|
|
- // 事件触发器
|
|
|
- String triggerKey = key.substring(6); // 去掉 "EVENT:" 前缀
|
|
|
- List<EventTriggerConfig> configList = eventTriggers.get(triggerKey);
|
|
|
- if (configList != null) {
|
|
|
- configList.removeIf(c -> strategyCode.equals(c.strategyCode));
|
|
|
- if (configList.isEmpty()) {
|
|
|
- eventTriggers.remove(triggerKey);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ TriggerInfo info = new TriggerInfo(strategyCode, trigger);
|
|
|
|
|
|
- log.debug("注销策略[{}]的所有触发器,共{}个", strategyCode, keys.size());
|
|
|
- }
|
|
|
+ attrTriggers.computeIfAbsent(key, k -> new ArrayList<>()).add(info);
|
|
|
+ strategyTriggerIndex.computeIfAbsent(strategyCode, k -> new ArrayList<>()).add(info);
|
|
|
|
|
|
- // ==================== 触发器处理方法 ====================
|
|
|
+ log.info("属性触发器已注册: key={}, strategy={}", key, strategyCode);
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
- * 处理属性变化事件
|
|
|
- * 由 Controller 的 /onAttrValueChanged 接口调用
|
|
|
- *
|
|
|
- * @param objCode 设备代码
|
|
|
- * @param attrKey 属性键
|
|
|
- * @param oldValue 旧值(可为null)
|
|
|
- * @param newValue 新值
|
|
|
- * @return 触发的策略数量
|
|
|
- */
|
|
|
- public int handleAttrChange(String objCode, String attrKey, Object oldValue, Object newValue) {
|
|
|
- String triggerKey = objCode + ":" + attrKey;
|
|
|
- List<AttrTriggerConfig> configList = attrTriggers.get(triggerKey);
|
|
|
|
|
|
- if (configList == null || configList.isEmpty()) {
|
|
|
- log.debug("无匹配的属性触发器: {}", triggerKey);
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ /* ============================================================
|
|
|
+ * 注销 & 清空
|
|
|
+ * ============================================================ */
|
|
|
|
|
|
- log.info("属性变化触发检查: obj={}, attr={}, {} -> {}", objCode, attrKey, oldValue, newValue);
|
|
|
+ /** 注销某个策略的所有事件/属性触发器 */
|
|
|
+ public void unregisterTriggers(String strategyCode) {
|
|
|
+ List<TriggerInfo> list = strategyTriggerIndex.remove(strategyCode);
|
|
|
+ if (list == null || list.isEmpty()) return;
|
|
|
|
|
|
- int triggeredCount = 0;
|
|
|
+ for (TriggerInfo info : list) {
|
|
|
+ OpEnergyStrategyTrigger t = info.getTrigger();
|
|
|
+ String key;
|
|
|
|
|
|
- // 遍历所有匹配的触发器
|
|
|
- for (AttrTriggerConfig config : configList) {
|
|
|
- try {
|
|
|
- boolean triggered = checkAndExecuteAttrTrigger(config, oldValue, newValue);
|
|
|
- if (triggered) {
|
|
|
- triggeredCount++;
|
|
|
- }
|
|
|
- }
|
|
|
- catch (Exception e) {
|
|
|
- log.error("属性触发器执行异常: strategy={}", config.strategyCode, e);
|
|
|
+ if ("EVENT".equals(t.getTriggerType())) {
|
|
|
+ key = t.getSourceObjCode() + ":" + t.getEventKey();
|
|
|
+ removeTrigger(eventTriggers, key, info);
|
|
|
+ } else if ("ATTR".equals(t.getTriggerType())) {
|
|
|
+ key = t.getSourceObjCode() + ":" + t.getAttrKey();
|
|
|
+ removeTrigger(attrTriggers, key, info);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return triggeredCount;
|
|
|
+ log.info("触发器已注销: strategy={}", strategyCode);
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 处理设备事件
|
|
|
- *
|
|
|
- * @param objCode 设备代码
|
|
|
- * @param eventKey 事件键
|
|
|
- * @param eventData 事件数据
|
|
|
- * @return 触发的策略数量
|
|
|
- */
|
|
|
- public int handleDeviceEvent(String objCode, String eventKey, Map<String, Object> eventData) {
|
|
|
- String triggerKey = objCode + ":" + eventKey;
|
|
|
- List<EventTriggerConfig> configList = eventTriggers.get(triggerKey);
|
|
|
-
|
|
|
- if (configList == null || configList.isEmpty()) {
|
|
|
- log.debug("无匹配的事件触发器: {}", triggerKey);
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- log.info("设备事件触发检查: obj={}, event={}", objCode, eventKey);
|
|
|
-
|
|
|
- int triggeredCount = 0;
|
|
|
-
|
|
|
- for (EventTriggerConfig config : configList) {
|
|
|
- try {
|
|
|
- boolean triggered = checkAndExecuteEventTrigger(config, eventData);
|
|
|
- if (triggered) {
|
|
|
- triggeredCount++;
|
|
|
- }
|
|
|
- }
|
|
|
- catch (Exception e) {
|
|
|
- log.error("事件触发器执行异常: strategy={}", config.strategyCode, e);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return triggeredCount;
|
|
|
+ /** 完全清空所有触发器 */
|
|
|
+ public void clearAll() {
|
|
|
+ eventTriggers.clear();
|
|
|
+ attrTriggers.clear();
|
|
|
+ strategyTriggerIndex.clear();
|
|
|
+ log.info("TriggerListener: 所有触发器已清空");
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 检查属性触发条件并执行策略
|
|
|
- * 修复:完善触发信息传递
|
|
|
- *
|
|
|
- * @return 是否触发执行
|
|
|
- */
|
|
|
- private boolean checkAndExecuteAttrTrigger(AttrTriggerConfig config, Object oldValue, Object newValue) {
|
|
|
- // 构建条件评估上下文
|
|
|
- Map<String, Object> context = new HashMap<>();
|
|
|
- context.put("oldValue", oldValue);
|
|
|
- context.put("newValue", newValue);
|
|
|
- context.put(config.attrKey, newValue);
|
|
|
-
|
|
|
- // 评估条件
|
|
|
- boolean shouldTrigger = true;
|
|
|
- if (config.conditionExpr != null && !config.conditionExpr.trim().isEmpty()) {
|
|
|
- shouldTrigger = conditionEvaluator.evaluate(config.conditionExpr, context);
|
|
|
+ private void removeTrigger(Map<String, List<TriggerInfo>> map, String key, TriggerInfo info) {
|
|
|
+ List<TriggerInfo> list = map.get(key);
|
|
|
+ if (list != null) {
|
|
|
+ list.remove(info);
|
|
|
+ if (list.isEmpty()) map.remove(key);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- if (shouldTrigger) {
|
|
|
- log.info("属性触发条件满足,执行策略: strategy={}, obj={}.{}, value={}",
|
|
|
- config.strategyCode, config.objCode, config.attrKey, newValue);
|
|
|
-
|
|
|
- // 异步执行策略
|
|
|
- asyncExecutor.submit(() -> {
|
|
|
- try {
|
|
|
- Map<String, Object> params = new HashMap<>();
|
|
|
|
|
|
- // 触发类型和触发源
|
|
|
- params.put("trigger_type", "ATTR");
|
|
|
- params.put("trigger_source", config.objCode + "." + config.attrKey);
|
|
|
+ /* ============================================================
|
|
|
+ * 触发入口(外部系统调用)
|
|
|
+ * ============================================================ */
|
|
|
|
|
|
- // 执行人(属性变化为系统自动触发)
|
|
|
- params.put("exec_by", "SYSTEM_ATTR_CHANGE");
|
|
|
+ /** 外部系统事件上报 → 事件触发 */
|
|
|
+ public void onEventReceived(String objCode, String eventKey, Map<String, Object> eventData) {
|
|
|
+ String key = objCode + ":" + eventKey;
|
|
|
|
|
|
- // 属性变化信息
|
|
|
- params.put("old_value", oldValue);
|
|
|
- params.put("new_value", newValue);
|
|
|
- params.put("device_code", config.objCode);
|
|
|
- params.put("attr_key", config.attrKey);
|
|
|
+ List<TriggerInfo> list = eventTriggers.get(key);
|
|
|
+ if (list == null || list.isEmpty()) return;
|
|
|
|
|
|
- // 方便上下文变量访问
|
|
|
- params.put(config.attrKey, newValue);
|
|
|
- params.put("current_" + config.attrKey, newValue);
|
|
|
+ for (TriggerInfo info : list) {
|
|
|
+ OpEnergyStrategyTrigger trigger = info.getTrigger();
|
|
|
|
|
|
- getStrategyExecutor().executeStrategy(config.strategyCode, params);
|
|
|
- } catch (Exception e) {
|
|
|
- log.error("策略异步执行失败: strategy={}", config.strategyCode, e);
|
|
|
- }
|
|
|
- });
|
|
|
+ // condition_expr 判断
|
|
|
+ if (!checkCondition(trigger, eventData)) continue;
|
|
|
|
|
|
- return true;
|
|
|
- } else {
|
|
|
- log.debug("属性触发条件不满足: strategy={}, condition={}", config.strategyCode, config.conditionExpr);
|
|
|
- return false;
|
|
|
+ executeTrigger(info, "EVENT", eventData, "EVENT:" + eventKey);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 检查事件触发条件并执行策略
|
|
|
- * 修复:完善触发信息传递
|
|
|
- *
|
|
|
- * @return 是否触发执行
|
|
|
- */
|
|
|
- private boolean checkAndExecuteEventTrigger(EventTriggerConfig config, Map<String, Object> eventData) {
|
|
|
- // 评估条件
|
|
|
- boolean shouldTrigger = true;
|
|
|
- if (config.conditionExpr != null && !config.conditionExpr.trim().isEmpty()) {
|
|
|
- Map<String, Object> context = eventData != null ? eventData : new HashMap<>();
|
|
|
- shouldTrigger = conditionEvaluator.evaluate(config.conditionExpr, context);
|
|
|
- }
|
|
|
+ /** 外部系统属性变化上报 → 属性触发 */
|
|
|
+ public void onAttrChanged(String objCode, String attrKey, Object newVal) {
|
|
|
+ String key = objCode + ":" + attrKey;
|
|
|
|
|
|
- if (shouldTrigger) {
|
|
|
- log.info("事件触发条件满足,执行策略: strategy={}, obj={}.{}",
|
|
|
- config.strategyCode, config.objCode, config.eventKey);
|
|
|
+ List<TriggerInfo> list = attrTriggers.get(key);
|
|
|
+ if (list == null || list.isEmpty()) return;
|
|
|
|
|
|
- // 异步执行策略
|
|
|
- asyncExecutor.submit(() -> {
|
|
|
- try {
|
|
|
- Map<String, Object> params = new HashMap<>();
|
|
|
- if (eventData != null) {
|
|
|
- params.putAll(eventData);
|
|
|
- }
|
|
|
+ Map<String, Object> data = new HashMap<>();
|
|
|
+ data.put(attrKey, newVal);
|
|
|
|
|
|
- // 触发类型和触发源
|
|
|
- params.put("trigger_type", "EVENT");
|
|
|
- params.put("trigger_source", config.objCode + "." + config.eventKey);
|
|
|
+ for (TriggerInfo info : list) {
|
|
|
+ OpEnergyStrategyTrigger trigger = info.getTrigger();
|
|
|
|
|
|
- // 执行人(事件触发为系统自动执行)
|
|
|
- params.put("exec_by", "SYSTEM_EVENT");
|
|
|
+ if (!checkCondition(trigger, data)) continue;
|
|
|
|
|
|
- // 事件信息
|
|
|
- params.put("device_code", config.objCode);
|
|
|
- params.put("event_key", config.eventKey);
|
|
|
+ executeTrigger(info, "ATTR", data, "ATTR:" + attrKey);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- getStrategyExecutor().executeStrategy(config.strategyCode, params);
|
|
|
- } catch (Exception e) {
|
|
|
- log.error("策略异步执行失败: strategy={}", config.strategyCode, e);
|
|
|
- }
|
|
|
- });
|
|
|
+ /* ============================================================
|
|
|
+ * 公共方法
|
|
|
+ * ============================================================ */
|
|
|
|
|
|
+ private boolean checkCondition(OpEnergyStrategyTrigger trigger, Map<String, Object> data) {
|
|
|
+ if (trigger.getConditionExpr() == null || trigger.getConditionExpr().isEmpty()) {
|
|
|
return true;
|
|
|
- } else {
|
|
|
- log.debug("事件触发条件不满足: strategy={}, condition={}", config.strategyCode, config.conditionExpr);
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ return conditionEvaluator.evaluate(trigger.getConditionExpr(), data);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("condition_expr 解析失败: {}", trigger.getConditionExpr(), e);
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // ==================== 统计和调试方法 ====================
|
|
|
+ /** 执行策略 */
|
|
|
+ private void executeTrigger(TriggerInfo info, String type, Map<String, Object> data, String source) {
|
|
|
+ String strategyCode = info.getStrategyCode();
|
|
|
|
|
|
- /**
|
|
|
- * 获取已注册的属性触发器数量
|
|
|
- */
|
|
|
- public int getAttrTriggerCount() {
|
|
|
- int count = 0;
|
|
|
- for (List<AttrTriggerConfig> list : attrTriggers.values()) {
|
|
|
- count += list.size();
|
|
|
- }
|
|
|
- return count;
|
|
|
- }
|
|
|
+ log.info(">>> 触发策略: strategy={}, type={}, source={}", strategyCode, type, source);
|
|
|
|
|
|
- /**
|
|
|
- * 获取已注册的事件触发器数量
|
|
|
- */
|
|
|
- public int getEventTriggerCount() {
|
|
|
- int count = 0;
|
|
|
- for (List<EventTriggerConfig> list : eventTriggers.values()) {
|
|
|
- count += list.size();
|
|
|
+ Map<String, Object> params = new HashMap<>();
|
|
|
+ params.put("trigger_type", type);
|
|
|
+ params.put("trigger_source", source);
|
|
|
+ params.put("trigger_id", info.getTrigger().getId());
|
|
|
+ params.put("event_data", data);
|
|
|
+
|
|
|
+ try {
|
|
|
+ getStrategyExecutor().executeStrategy(strategyCode, params);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("触发策略失败: {}", strategyCode, e);
|
|
|
}
|
|
|
- return count;
|
|
|
}
|
|
|
|
|
|
+ /* ============================================================
|
|
|
+ * Controller 兼容方法(你的控制器中正在使用)
|
|
|
+ * ============================================================ */
|
|
|
+
|
|
|
/**
|
|
|
- * 获取所有已注册的触发器信息(用于调试)
|
|
|
+ * 属性变化入口(兼容 Controller)
|
|
|
*/
|
|
|
- public Map<String, Object> getRegisteredTriggers() {
|
|
|
- Map<String, Object> result = new HashMap<>();
|
|
|
+ public int handleAttrChange(String objCode, String attrKey, Object oldValue, Object newValue) {
|
|
|
+ String key = objCode + ":" + attrKey;
|
|
|
|
|
|
- // 属性触发器列表
|
|
|
- List<String> attrTriggerList = new ArrayList<>(attrTriggers.keySet());
|
|
|
- result.put("attrTriggers", attrTriggerList);
|
|
|
+ List<TriggerInfo> list = attrTriggers.get(key);
|
|
|
+ if (list == null || list.isEmpty()) return 0;
|
|
|
|
|
|
- // 事件触发器列表
|
|
|
- List<String> eventTriggerList = new ArrayList<>(eventTriggers.keySet());
|
|
|
- result.put("eventTriggers", eventTriggerList);
|
|
|
+ Map<String, Object> eventData = new HashMap<>();
|
|
|
+ eventData.put("oldValue", oldValue);
|
|
|
+ eventData.put("newValue", newValue);
|
|
|
|
|
|
- // 数量统计
|
|
|
- result.put("attrTriggerCount", getAttrTriggerCount());
|
|
|
- result.put("eventTriggerCount", getEventTriggerCount());
|
|
|
+ int count = 0;
|
|
|
+ for (TriggerInfo info : list) {
|
|
|
+ OpEnergyStrategyTrigger trigger = info.getTrigger();
|
|
|
|
|
|
- // 策略与触发器的映射关系
|
|
|
- Map<String, List<String>> strategyMappings = new HashMap<>(strategyTriggerKeys);
|
|
|
- result.put("strategyMappings", strategyMappings);
|
|
|
+ // 条件判断
|
|
|
+ if (!checkCondition(trigger, eventData)) continue;
|
|
|
|
|
|
- return result;
|
|
|
- }
|
|
|
+ executeTrigger(info, "ATTR", eventData, "ATTR:" + attrKey);
|
|
|
+ count++;
|
|
|
+ }
|
|
|
|
|
|
- /**
|
|
|
- * 检查某个属性是否有触发器监听
|
|
|
- */
|
|
|
- public boolean hasAttrTrigger(String objCode, String attrKey) {
|
|
|
- String triggerKey = objCode + ":" + attrKey;
|
|
|
- List<AttrTriggerConfig> list = attrTriggers.get(triggerKey);
|
|
|
- return list != null && !list.isEmpty();
|
|
|
+ return count;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 检查某个事件是否有触发器监听
|
|
|
+ * 设备事件入口(兼容 Controller)
|
|
|
*/
|
|
|
- public boolean hasEventTrigger(String objCode, String eventKey) {
|
|
|
- String triggerKey = objCode + ":" + eventKey;
|
|
|
- List<EventTriggerConfig> list = eventTriggers.get(triggerKey);
|
|
|
- return list != null && !list.isEmpty();
|
|
|
- }
|
|
|
-
|
|
|
- // ==================== 内部配置类 ====================
|
|
|
+ public int handleDeviceEvent(String objCode, String eventKey, Map<String, Object> eventData) {
|
|
|
+ String key = objCode + ":" + eventKey;
|
|
|
+ List<TriggerInfo> list = eventTriggers.get(key);
|
|
|
+ if (list == null || list.isEmpty()) return 0;
|
|
|
|
|
|
- /**
|
|
|
- * 属性触发器配置
|
|
|
- */
|
|
|
- private static class AttrTriggerConfig {
|
|
|
- String strategyCode; // 策略代码
|
|
|
+ int count = 0;
|
|
|
+ for (TriggerInfo info : list) {
|
|
|
+ OpEnergyStrategyTrigger trigger = info.getTrigger();
|
|
|
|
|
|
- String objCode; // 设备代码
|
|
|
+ if (!checkCondition(trigger, eventData)) continue;
|
|
|
|
|
|
- String attrKey; // 属性键
|
|
|
+ executeTrigger(info, "EVENT", eventData, "EVENT:" + eventKey);
|
|
|
+ count++;
|
|
|
+ }
|
|
|
|
|
|
- String conditionExpr; // 条件表达式
|
|
|
+ return count;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 事件触发器配置
|
|
|
+ * 获取已注册触发器(用于 /scheduler/status 接口)
|
|
|
*/
|
|
|
- private static class EventTriggerConfig {
|
|
|
- String strategyCode; // 策略代码
|
|
|
+ public Map<String, Object> getRegisteredTriggers() {
|
|
|
+ Map<String, Object> map = new HashMap<>();
|
|
|
+
|
|
|
+ map.put("eventTriggers", eventTriggers.keySet());
|
|
|
+ map.put("attrTriggers", attrTriggers.keySet());
|
|
|
+ map.put("strategyIndex", strategyTriggerIndex.keySet());
|
|
|
+
|
|
|
+ return map;
|
|
|
+ }
|
|
|
|
|
|
- String objCode; // 设备代码
|
|
|
|
|
|
- String eventKey; // 事件键
|
|
|
+ /* ============================================================
|
|
|
+ * 内部结构
|
|
|
+ * ============================================================ */
|
|
|
|
|
|
- String conditionExpr; // 条件表达式
|
|
|
+ @Data
|
|
|
+ private static class TriggerInfo {
|
|
|
+ private final String strategyCode;
|
|
|
+ private final OpEnergyStrategyTrigger trigger;
|
|
|
}
|
|
|
-}
|
|
|
+}
|