review:【iot 物联网】场景联动
This commit is contained in:
parent
67a44fd334
commit
e639dbfeb7
@ -19,7 +19,6 @@ import java.util.Arrays;
|
|||||||
@Getter
|
@Getter
|
||||||
public enum IotSceneRuleTriggerTypeEnum implements ArrayValuable<Integer> {
|
public enum IotSceneRuleTriggerTypeEnum implements ArrayValuable<Integer> {
|
||||||
|
|
||||||
// TODO @芋艿:后续“对应”部分,要 @下,等包结构梳理完;
|
|
||||||
/**
|
/**
|
||||||
* 设备上下线变更
|
* 设备上下线变更
|
||||||
*
|
*
|
||||||
|
|||||||
@ -84,13 +84,14 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateSceneRuleStatus(Long id, Integer status) {
|
public void updateSceneRuleStatus(Long id, Integer status) {
|
||||||
// 校验存在
|
// 1. 校验存在
|
||||||
validateSceneRuleExists(id);
|
validateSceneRuleExists(id);
|
||||||
// 更新状态
|
|
||||||
|
// 2. 更新状态
|
||||||
IotSceneRuleDO updateObj = new IotSceneRuleDO().setId(id).setStatus(status);
|
IotSceneRuleDO updateObj = new IotSceneRuleDO().setId(id).setStatus(status);
|
||||||
sceneRuleMapper.updateById(updateObj);
|
sceneRuleMapper.updateById(updateObj);
|
||||||
|
|
||||||
// 根据状态管理定时触发器
|
// 3. 根据状态管理定时触发器
|
||||||
if (CommonStatusEnum.isEnable(status)) {
|
if (CommonStatusEnum.isEnable(status)) {
|
||||||
// 启用时,获取完整的场景规则信息并注册定时触发器
|
// 启用时,获取完整的场景规则信息并注册定时触发器
|
||||||
IotSceneRuleDO sceneRule = sceneRuleMapper.selectById(id);
|
IotSceneRuleDO sceneRule = sceneRuleMapper.selectById(id);
|
||||||
@ -105,12 +106,14 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void deleteSceneRule(Long id) {
|
public void deleteSceneRule(Long id) {
|
||||||
// 校验存在
|
// 1. 校验存在
|
||||||
validateSceneRuleExists(id);
|
validateSceneRuleExists(id);
|
||||||
// 删除定时触发器
|
|
||||||
timerHandler.unregisterTimerTriggers(id);
|
// 2. 删除
|
||||||
// 删除
|
|
||||||
sceneRuleMapper.deleteById(id);
|
sceneRuleMapper.deleteById(id);
|
||||||
|
|
||||||
|
// 3. 删除定时触发器
|
||||||
|
timerHandler.unregisterTimerTriggers(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateSceneRuleExists(Long id) {
|
private void validateSceneRuleExists(Long id) {
|
||||||
@ -146,16 +149,17 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
|
|||||||
return sceneRuleMapper.selectListByStatus(status);
|
return sceneRuleMapper.selectListByStatus(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO 芋艿,缓存待实现 @puhui999
|
// TODO @puhui999:缓存待实现
|
||||||
@Override
|
@Override
|
||||||
@TenantIgnore // 忽略租户隔离:因为 IotSceneRuleMessageHandler 调用时,一般未传递租户,所以需要忽略
|
@TenantIgnore // 忽略租户隔离:因为 IotSceneRuleMessageHandler 调用时,一般未传递租户,所以需要忽略
|
||||||
public List<IotSceneRuleDO> getSceneRuleListByProductIdAndDeviceIdFromCache(Long productId, Long deviceId) {
|
public List<IotSceneRuleDO> getSceneRuleListByProductIdAndDeviceIdFromCache(Long productId, Long deviceId) {
|
||||||
|
// 1. 查询启用状态的规则场景
|
||||||
|
// TODO @puhui999:这里查询 enable 的;
|
||||||
List<IotSceneRuleDO> list = sceneRuleMapper.selectList();
|
List<IotSceneRuleDO> list = sceneRuleMapper.selectList();
|
||||||
// 只返回启用状态的规则场景
|
|
||||||
List<IotSceneRuleDO> enabledList = filterList(list,
|
List<IotSceneRuleDO> enabledList = filterList(list,
|
||||||
sceneRule -> CommonStatusEnum.isEnable(sceneRule.getStatus()));
|
sceneRule -> CommonStatusEnum.isEnable(sceneRule.getStatus()));
|
||||||
|
|
||||||
// 根据 productKey 和 deviceName 进行匹配
|
// 2. 根据 productKey 和 deviceName 进行匹配
|
||||||
return filterList(enabledList, sceneRule -> {
|
return filterList(enabledList, sceneRule -> {
|
||||||
if (CollUtil.isEmpty(sceneRule.getTriggers())) {
|
if (CollUtil.isEmpty(sceneRule.getTriggers())) {
|
||||||
return false;
|
return false;
|
||||||
@ -164,21 +168,19 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
|
|||||||
for (IotSceneRuleDO.Trigger trigger : sceneRule.getTriggers()) {
|
for (IotSceneRuleDO.Trigger trigger : sceneRule.getTriggers()) {
|
||||||
// 检查触发器是否匹配指定的产品和设备
|
// 检查触发器是否匹配指定的产品和设备
|
||||||
try {
|
try {
|
||||||
// 1. 检查产品是否匹配
|
// 检查产品是否匹配
|
||||||
if (trigger.getProductId() == null) {
|
if (trigger.getProductId() == null || trigger.getDeviceId() == null) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (trigger.getDeviceId() == null) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 检查是否是全部设备的特殊标识
|
// 检查是否是全部设备的特殊标识
|
||||||
if (IotDeviceDO.DEVICE_ID_ALL.equals(trigger.getDeviceId())) {
|
if (IotDeviceDO.DEVICE_ID_ALL.equals(trigger.getDeviceId())) {
|
||||||
return true; // 匹配所有设备
|
return true;
|
||||||
}
|
}
|
||||||
// 检查具体设备 ID 是否匹配
|
// 检查具体设备 ID 是否匹配
|
||||||
return ObjUtil.equal(productId, trigger.getProductId()) && ObjUtil.equal(deviceId, trigger.getDeviceId());
|
return ObjUtil.equal(productId, trigger.getProductId()) && ObjUtil.equal(deviceId, trigger.getDeviceId());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.warn("[isMatchProductAndDevice][产品({}) 设备({}) 匹配触发器异常]", productId, deviceId, e);
|
log.warn("[getSceneRuleListByProductIdAndDeviceIdFromCache][产品({}) 设备({}) 匹配触发器异常]",
|
||||||
|
productId, deviceId, e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -188,7 +190,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void executeSceneRuleByDevice(IotDeviceMessage message) {
|
public void executeSceneRuleByDevice(IotDeviceMessage message) {
|
||||||
// TODO @芋艿:这里的 tenantId,通过设备获取;@puhui999:
|
// TODO @puhui999:这里的 tenantId,通过设备获取;
|
||||||
TenantUtils.execute(message.getTenantId(), () -> {
|
TenantUtils.execute(message.getTenantId(), () -> {
|
||||||
// 1. 获得设备匹配的规则场景
|
// 1. 获得设备匹配的规则场景
|
||||||
List<IotSceneRuleDO> sceneRules = getMatchedSceneRuleListByMessage(message);
|
List<IotSceneRuleDO> sceneRules = getMatchedSceneRuleListByMessage(message);
|
||||||
@ -234,7 +236,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
|
|||||||
*/
|
*/
|
||||||
private List<IotSceneRuleDO> getMatchedSceneRuleListByMessage(IotDeviceMessage message) {
|
private List<IotSceneRuleDO> getMatchedSceneRuleListByMessage(IotDeviceMessage message) {
|
||||||
// 1. 匹配设备
|
// 1. 匹配设备
|
||||||
// TODO @芋艿:可能需要 getSelf(); 缓存 @puhui999;
|
// TODO 缓存 @puhui999:可能需要 getSelf()
|
||||||
// 1.1 通过 deviceId 获取设备信息
|
// 1.1 通过 deviceId 获取设备信息
|
||||||
IotDeviceDO device = deviceService.getDeviceFromCache(message.getDeviceId());
|
IotDeviceDO device = deviceService.getDeviceFromCache(message.getDeviceId());
|
||||||
if (device == null) {
|
if (device == null) {
|
||||||
@ -293,7 +295,6 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
|
|||||||
*/
|
*/
|
||||||
private boolean matchSingleTrigger(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger, IotSceneRuleDO sceneRule) {
|
private boolean matchSingleTrigger(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger, IotSceneRuleDO sceneRule) {
|
||||||
try {
|
try {
|
||||||
// 2. 检查触发器的条件分组
|
|
||||||
return sceneRuleMatcherManager.isMatched(message, trigger) && isTriggerConditionGroupsMatched(message, trigger, sceneRule);
|
return sceneRuleMatcherManager.isMatched(message, trigger) && isTriggerConditionGroupsMatched(message, trigger, sceneRule);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("[matchSingleTrigger][触发器匹配异常] sceneRuleId: {}, triggerType: {}, message: {}",
|
log.error("[matchSingleTrigger][触发器匹配异常] sceneRuleId: {}, triggerType: {}, message: {}",
|
||||||
@ -310,18 +311,19 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
|
|||||||
* @param sceneRule 场景规则(用于日志)
|
* @param sceneRule 场景规则(用于日志)
|
||||||
* @return 是否匹配
|
* @return 是否匹配
|
||||||
*/
|
*/
|
||||||
private boolean isTriggerConditionGroupsMatched(IotDeviceMessage message, IotSceneRuleDO.Trigger trigger, IotSceneRuleDO sceneRule) {
|
private boolean isTriggerConditionGroupsMatched(IotDeviceMessage message,
|
||||||
// 如果没有条件分组,则认为匹配成功(只依赖基础触发器匹配)
|
IotSceneRuleDO.Trigger trigger,
|
||||||
|
IotSceneRuleDO sceneRule) {
|
||||||
|
// 1. 如果没有条件分组,则认为匹配成功(只依赖基础触发器匹配)
|
||||||
if (CollUtil.isEmpty(trigger.getConditionGroups())) {
|
if (CollUtil.isEmpty(trigger.getConditionGroups())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查条件分组:分组与分组之间是"或"的关系,条件与条件之间是"且"的关系
|
// 2. 检查条件分组:分组与分组之间是"或"的关系,条件与条件之间是"且"的关系
|
||||||
for (List<IotSceneRuleDO.TriggerCondition> conditionGroup : trigger.getConditionGroups()) {
|
for (List<IotSceneRuleDO.TriggerCondition> conditionGroup : trigger.getConditionGroups()) {
|
||||||
if (CollUtil.isEmpty(conditionGroup)) {
|
if (CollUtil.isEmpty(conditionGroup)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查当前分组中的所有条件是否都匹配(且关系)
|
// 检查当前分组中的所有条件是否都匹配(且关系)
|
||||||
boolean allConditionsMatched = true;
|
boolean allConditionsMatched = true;
|
||||||
for (IotSceneRuleDO.TriggerCondition condition : conditionGroup) {
|
for (IotSceneRuleDO.TriggerCondition condition : conditionGroup) {
|
||||||
@ -330,14 +332,13 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果当前分组的所有条件都匹配,则整个触发器匹配成功
|
// 如果当前分组的所有条件都匹配,则整个触发器匹配成功
|
||||||
if (allConditionsMatched) {
|
if (allConditionsMatched) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 所有分组都不匹配
|
// 3. 所有分组都不匹配
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,13 +373,13 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
|
|||||||
sceneRules.forEach(sceneRule -> {
|
sceneRules.forEach(sceneRule -> {
|
||||||
// 2. 遍历规则场景的动作
|
// 2. 遍历规则场景的动作
|
||||||
sceneRule.getActions().forEach(actionConfig -> {
|
sceneRule.getActions().forEach(actionConfig -> {
|
||||||
// 3.1 获取对应的动作 Action 数组
|
// 2.1 获取对应的动作 Action 数组
|
||||||
List<IotSceneRuleAction> actions = filterList(sceneRuleActions,
|
List<IotSceneRuleAction> actions = filterList(sceneRuleActions,
|
||||||
action -> action.getType().getType().equals(actionConfig.getType()));
|
action -> action.getType().getType().equals(actionConfig.getType()));
|
||||||
if (CollUtil.isEmpty(actions)) {
|
if (CollUtil.isEmpty(actions)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 3.2 执行动作
|
// 2.2 执行动作
|
||||||
actions.forEach(action -> {
|
actions.forEach(action -> {
|
||||||
try {
|
try {
|
||||||
action.execute(message, sceneRule, actionConfig);
|
action.execute(message, sceneRule, actionConfig);
|
||||||
|
|||||||
@ -14,7 +14,6 @@ import java.util.List;
|
|||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||||
|
|
||||||
// TODO @puhui999、@芋艿:未测试;需要场景联动开发完
|
|
||||||
/**
|
/**
|
||||||
* IoT 告警恢复的 {@link IotSceneRuleAction} 实现类
|
* IoT 告警恢复的 {@link IotSceneRuleAction} 实现类
|
||||||
*
|
*
|
||||||
|
|||||||
@ -17,7 +17,6 @@ import org.springframework.stereotype.Component;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
// TODO @puhui999、@芋艿:未测试;需要场景联动开发完
|
|
||||||
/**
|
/**
|
||||||
* IoT 告警触发的 {@link IotSceneRuleAction} 实现类
|
* IoT 告警触发的 {@link IotSceneRuleAction} 实现类
|
||||||
*
|
*
|
||||||
|
|||||||
@ -4,10 +4,8 @@ import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.condition.IotScene
|
|||||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.trigger.IotSceneRuleTriggerMatcher;
|
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.trigger.IotSceneRuleTriggerMatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IoT 场景规则匹配器基础接口
|
* IoT 场景规则匹配器基础接口:定义所有匹配器的通用行为,包括优先级、名称和启用状态
|
||||||
* <p>
|
*
|
||||||
* 定义所有匹配器的通用行为,包括优先级、名称和启用状态
|
|
||||||
* <p>
|
|
||||||
* - {@link IotSceneRuleTriggerMatcher} 触发器匹配器
|
* - {@link IotSceneRuleTriggerMatcher} 触发器匹配器
|
||||||
* - {@link IotSceneRuleConditionMatcher} 条件匹配器
|
* - {@link IotSceneRuleConditionMatcher} 条件匹配器
|
||||||
*
|
*
|
||||||
|
|||||||
@ -18,10 +18,8 @@ import java.util.Map;
|
|||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IoT 场景规则匹配器工具类
|
* IoT 场景规则匹配器工具类:提供通用的条件评估逻辑和工具方法,供触发器和条件匹配器使用
|
||||||
* <p>
|
*
|
||||||
* 提供通用的条件评估逻辑和工具方法,供触发器和条件匹配器使用
|
|
||||||
* <p>
|
|
||||||
* 该类包含了匹配器实现中常用的工具方法,如条件评估、参数校验、日志记录等
|
* 该类包含了匹配器实现中常用的工具方法,如条件评估、参数校验、日志记录等
|
||||||
*
|
*
|
||||||
* @author HUIHUI
|
* @author HUIHUI
|
||||||
|
|||||||
@ -16,9 +16,7 @@ import java.util.function.Function;
|
|||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IoT 场景规则匹配器统一管理器
|
* IoT 场景规则匹配器统一管理器:负责管理所有匹配器(触发器匹配器和条件匹配器),并提供统一的匹配入口
|
||||||
* <p>
|
|
||||||
* 负责管理所有匹配器(触发器匹配器和条件匹配器),并提供统一的匹配入口
|
|
||||||
*
|
*
|
||||||
* @author HUIHUI
|
* @author HUIHUI
|
||||||
*/
|
*/
|
||||||
@ -44,13 +42,12 @@ public class IotSceneRuleMatcherManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 按优先级排序并过滤启用的匹配器
|
// 1.1 按优先级排序并过滤启用的匹配器
|
||||||
List<IotSceneRuleMatcher> allMatchers = matchers.stream()
|
List<IotSceneRuleMatcher> allMatchers = matchers.stream()
|
||||||
.filter(IotSceneRuleMatcher::isEnabled)
|
.filter(IotSceneRuleMatcher::isEnabled)
|
||||||
.sorted(Comparator.comparing(IotSceneRuleMatcher::getPriority))
|
.sorted(Comparator.comparing(IotSceneRuleMatcher::getPriority))
|
||||||
.toList();
|
.toList();
|
||||||
|
// 1.2 分离触发器匹配器和条件匹配器
|
||||||
// 分离触发器匹配器和条件匹配器
|
|
||||||
List<IotSceneRuleTriggerMatcher> triggerMatchers = allMatchers.stream()
|
List<IotSceneRuleTriggerMatcher> triggerMatchers = allMatchers.stream()
|
||||||
.filter(matcher -> matcher instanceof IotSceneRuleTriggerMatcher)
|
.filter(matcher -> matcher instanceof IotSceneRuleTriggerMatcher)
|
||||||
.map(matcher -> (IotSceneRuleTriggerMatcher) matcher)
|
.map(matcher -> (IotSceneRuleTriggerMatcher) matcher)
|
||||||
@ -60,7 +57,7 @@ public class IotSceneRuleMatcherManager {
|
|||||||
.map(matcher -> (IotSceneRuleConditionMatcher) matcher)
|
.map(matcher -> (IotSceneRuleConditionMatcher) matcher)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
// 构建触发器匹配器映射表
|
// 2.1 构建触发器匹配器映射表
|
||||||
this.triggerMatchers = convertMap(triggerMatchers, IotSceneRuleTriggerMatcher::getSupportedTriggerType,
|
this.triggerMatchers = convertMap(triggerMatchers, IotSceneRuleTriggerMatcher::getSupportedTriggerType,
|
||||||
Function.identity(),
|
Function.identity(),
|
||||||
(existing, replacement) -> {
|
(existing, replacement) -> {
|
||||||
@ -70,7 +67,7 @@ public class IotSceneRuleMatcherManager {
|
|||||||
existing.getSupportedTriggerType() : replacement.getSupportedTriggerType());
|
existing.getSupportedTriggerType() : replacement.getSupportedTriggerType());
|
||||||
return existing.getPriority() <= replacement.getPriority() ? existing : replacement;
|
return existing.getPriority() <= replacement.getPriority() ? existing : replacement;
|
||||||
}, LinkedHashMap::new);
|
}, LinkedHashMap::new);
|
||||||
// 构建条件匹配器映射表
|
// 2.2 构建条件匹配器映射表
|
||||||
this.conditionMatchers = convertMap(conditionMatchers, IotSceneRuleConditionMatcher::getSupportedConditionType,
|
this.conditionMatchers = convertMap(conditionMatchers, IotSceneRuleConditionMatcher::getSupportedConditionType,
|
||||||
Function.identity(),
|
Function.identity(),
|
||||||
(existing, replacement) -> {
|
(existing, replacement) -> {
|
||||||
@ -82,7 +79,7 @@ public class IotSceneRuleMatcherManager {
|
|||||||
},
|
},
|
||||||
LinkedHashMap::new);
|
LinkedHashMap::new);
|
||||||
|
|
||||||
// 日志输出初始化信息
|
// 3. 日志输出初始化信息
|
||||||
log.info("[IotSceneRuleMatcherManager][初始化完成,共加载({})个匹配器,其中触发器匹配器({})个,条件匹配器({})个]",
|
log.info("[IotSceneRuleMatcherManager][初始化完成,共加载({})个匹配器,其中触发器匹配器({})个,条件匹配器({})个]",
|
||||||
allMatchers.size(), this.triggerMatchers.size(), this.conditionMatchers.size());
|
allMatchers.size(), this.triggerMatchers.size(), this.conditionMatchers.size());
|
||||||
this.triggerMatchers.forEach((type, matcher) ->
|
this.triggerMatchers.forEach((type, matcher) ->
|
||||||
@ -135,7 +132,7 @@ public class IotSceneRuleMatcherManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据条件类型查找对应的匹配器
|
// 1. 根据条件类型查找对应的匹配器
|
||||||
IotSceneRuleConditionTypeEnum conditionType = IotSceneRuleConditionTypeEnum.typeOf(condition.getType());
|
IotSceneRuleConditionTypeEnum conditionType = IotSceneRuleConditionTypeEnum.typeOf(condition.getType());
|
||||||
if (conditionType == null) {
|
if (conditionType == null) {
|
||||||
log.warn("[isConditionMatched][conditionType({}) 未知的条件类型]", condition.getType());
|
log.warn("[isConditionMatched][conditionType({}) 未知的条件类型]", condition.getType());
|
||||||
@ -147,7 +144,7 @@ public class IotSceneRuleMatcherManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行匹配逻辑
|
// 2. 执行匹配逻辑
|
||||||
try {
|
try {
|
||||||
return matcher.matches(message, condition);
|
return matcher.matches(message, condition);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@ -16,10 +16,9 @@ import java.time.LocalTime;
|
|||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
// TODO @puhui999:是不是 IoT 的前缀,都加下哈;
|
||||||
/**
|
/**
|
||||||
* 当前时间条件匹配器
|
* 当前时间条件匹配器:处理时间相关的子条件匹配逻辑
|
||||||
* <p>
|
|
||||||
* 处理时间相关的子条件匹配逻辑
|
|
||||||
*
|
*
|
||||||
* @author HUIHUI
|
* @author HUIHUI
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -10,9 +10,7 @@ import org.springframework.stereotype.Component;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设备属性条件匹配器
|
* 设备属性条件匹配器:处理设备属性相关的子条件匹配逻辑
|
||||||
* <p>
|
|
||||||
* 处理设备属性相关的子条件匹配逻辑
|
|
||||||
*
|
*
|
||||||
* @author HUIHUI
|
* @author HUIHUI
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -8,9 +8,7 @@ import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatche
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设备状态条件匹配器
|
* 设备状态条件匹配器:处理设备状态相关的子条件匹配逻辑
|
||||||
* <p>
|
|
||||||
* 处理设备状态相关的子条件匹配逻辑
|
|
||||||
*
|
*
|
||||||
* @author HUIHUI
|
* @author HUIHUI
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -6,12 +6,9 @@ import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum;
|
|||||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcher;
|
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IoT 场景规则条件匹配器接口
|
* IoT 场景规则条件匹配器接口:专门处理子条件的匹配逻辑,如设备状态、属性值、时间条件等
|
||||||
* <p>
|
*
|
||||||
* 专门处理子条件的匹配逻辑,如设备状态、属性值、时间条件等
|
* 条件匹配器负责判断设备消息是否满足场景规则的附加条件,在触发器匹配成功后进行进一步的条件筛选
|
||||||
* <p>
|
|
||||||
* 条件匹配器负责判断设备消息是否满足场景规则的附加条件,
|
|
||||||
* 在触发器匹配成功后进行进一步的条件筛选
|
|
||||||
*
|
*
|
||||||
* @author HUIHUI
|
* @author HUIHUI
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -10,9 +10,7 @@ import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatche
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设备事件上报触发器匹配器
|
* 设备事件上报触发器匹配器:处理设备事件上报的触发器匹配逻辑
|
||||||
* <p>
|
|
||||||
* 处理设备事件上报的触发器匹配逻辑
|
|
||||||
*
|
*
|
||||||
* @author HUIHUI
|
* @author HUIHUI
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -9,9 +9,7 @@ import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatche
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设备属性上报触发器匹配器
|
* 设备属性上报触发器匹配器:处理设备属性数据上报的触发器匹配逻辑
|
||||||
* <p>
|
|
||||||
* 处理设备属性数据上报的触发器匹配逻辑
|
|
||||||
*
|
*
|
||||||
* @author HUIHUI
|
* @author HUIHUI
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -9,9 +9,7 @@ import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatche
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设备服务调用触发器匹配器
|
* 设备服务调用触发器匹配器:处理设备服务调用的触发器匹配逻辑
|
||||||
* <p>
|
|
||||||
* 处理设备服务调用的触发器匹配逻辑
|
|
||||||
*
|
*
|
||||||
* @author HUIHUI
|
* @author HUIHUI
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -9,9 +9,7 @@ import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatche
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设备状态更新触发器匹配器
|
* 设备状态更新触发器匹配器:处理设备上下线状态变更的触发器匹配逻辑
|
||||||
* <p>
|
|
||||||
* 处理设备上下线状态变更的触发器匹配逻辑
|
|
||||||
*
|
*
|
||||||
* @author HUIHUI
|
* @author HUIHUI
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -6,12 +6,9 @@ import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
|
|||||||
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcher;
|
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IoT 场景规则触发器匹配器接口
|
* IoT 场景规则触发器匹配器接口:专门处理主触发条件的匹配逻辑,如设备消息类型、定时器等
|
||||||
* <p>
|
*
|
||||||
* 专门处理主触发条件的匹配逻辑,如设备消息类型、定时器等
|
* 触发器匹配器负责判断设备消息是否满足场景规则的主触发条件,是场景规则执行的第一道门槛
|
||||||
* <p>
|
|
||||||
* 触发器匹配器负责判断设备消息是否满足场景规则的主触发条件,
|
|
||||||
* 是场景规则执行的第一道门槛
|
|
||||||
*
|
*
|
||||||
* @author HUIHUI
|
* @author HUIHUI
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -9,9 +9,8 @@ import org.quartz.CronExpression;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 定时触发器匹配器
|
* 定时触发器匹配器:处理定时触发的触发器匹配逻辑
|
||||||
* <p>
|
*
|
||||||
* 处理定时触发的触发器匹配逻辑
|
|
||||||
* 注意:定时触发器不依赖设备消息,主要用于定时任务场景
|
* 注意:定时触发器不依赖设备消息,主要用于定时任务场景
|
||||||
*
|
*
|
||||||
* @author HUIHUI
|
* @author HUIHUI
|
||||||
|
|||||||
@ -18,9 +18,7 @@ import java.util.List;
|
|||||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
|
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IoT 场景规则定时触发器处理器
|
* IoT 场景规则定时触发器处理器:负责管理定时触发器的注册、更新、删除等操作
|
||||||
* <p>
|
|
||||||
* 负责管理定时触发器的注册、更新、删除等操作
|
|
||||||
*
|
*
|
||||||
* @author HUIHUI
|
* @author HUIHUI
|
||||||
*/
|
*/
|
||||||
@ -37,19 +35,17 @@ public class IotSceneRuleTimerHandler {
|
|||||||
* @param sceneRule 场景规则
|
* @param sceneRule 场景规则
|
||||||
*/
|
*/
|
||||||
public void registerTimerTriggers(IotSceneRuleDO sceneRule) {
|
public void registerTimerTriggers(IotSceneRuleDO sceneRule) {
|
||||||
|
// 1. 过滤出定时触发器
|
||||||
if (sceneRule == null || CollUtil.isEmpty(sceneRule.getTriggers())) {
|
if (sceneRule == null || CollUtil.isEmpty(sceneRule.getTriggers())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 过滤出定时触发器
|
|
||||||
List<IotSceneRuleDO.Trigger> timerTriggers = filterList(sceneRule.getTriggers(),
|
List<IotSceneRuleDO.Trigger> timerTriggers = filterList(sceneRule.getTriggers(),
|
||||||
trigger -> ObjUtil.equals(trigger.getType(), IotSceneRuleTriggerTypeEnum.TIMER.getType()));
|
trigger -> ObjUtil.equals(trigger.getType(), IotSceneRuleTriggerTypeEnum.TIMER.getType()));
|
||||||
|
|
||||||
if (CollUtil.isEmpty(timerTriggers)) {
|
if (CollUtil.isEmpty(timerTriggers)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 注册每个定时触发器
|
// 2. 注册每个定时触发器
|
||||||
timerTriggers.forEach(trigger -> registerSingleTimerTrigger(sceneRule, trigger));
|
timerTriggers.forEach(trigger -> registerSingleTimerTrigger(sceneRule, trigger));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,23 +59,23 @@ public class IotSceneRuleTimerHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 先删除旧的定时任务
|
// 1. 先删除旧的定时任务
|
||||||
unregisterTimerTriggers(sceneRule.getId());
|
unregisterTimerTriggers(sceneRule.getId());
|
||||||
|
|
||||||
// 如果场景规则已禁用,则不重新注册
|
// 2.1 如果场景规则已禁用,则不重新注册
|
||||||
if (CommonStatusEnum.isDisable(sceneRule.getStatus())) {
|
if (CommonStatusEnum.isDisable(sceneRule.getStatus())) {
|
||||||
log.info("[updateTimerTriggers][场景规则({}) 已禁用,不注册定时触发器]", sceneRule.getId());
|
log.info("[updateTimerTriggers][场景规则({}) 已禁用,不注册定时触发器]", sceneRule.getId());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重新注册定时触发器
|
// 2.2 重新注册定时触发器
|
||||||
registerTimerTriggers(sceneRule);
|
registerTimerTriggers(sceneRule);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注销场景规则的定时触发器
|
* 注销场景规则的定时触发器
|
||||||
*
|
*
|
||||||
* @param sceneRuleId 场景规则ID
|
* @param sceneRuleId 场景规则 ID
|
||||||
*/
|
*/
|
||||||
public void unregisterTimerTriggers(Long sceneRuleId) {
|
public void unregisterTimerTriggers(Long sceneRuleId) {
|
||||||
if (sceneRuleId == null) {
|
if (sceneRuleId == null) {
|
||||||
@ -98,7 +94,7 @@ public class IotSceneRuleTimerHandler {
|
|||||||
/**
|
/**
|
||||||
* 暂停场景规则的定时触发器
|
* 暂停场景规则的定时触发器
|
||||||
*
|
*
|
||||||
* @param sceneRuleId 场景规则ID
|
* @param sceneRuleId 场景规则 ID
|
||||||
*/
|
*/
|
||||||
public void pauseTimerTriggers(Long sceneRuleId) {
|
public void pauseTimerTriggers(Long sceneRuleId) {
|
||||||
if (sceneRuleId == null) {
|
if (sceneRuleId == null) {
|
||||||
@ -114,25 +110,6 @@ public class IotSceneRuleTimerHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 恢复场景规则的定时触发器
|
|
||||||
*
|
|
||||||
* @param sceneRuleId 场景规则ID
|
|
||||||
*/
|
|
||||||
public void resumeTimerTriggers(Long sceneRuleId) {
|
|
||||||
if (sceneRuleId == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String jobName = buildJobName(sceneRuleId);
|
|
||||||
try {
|
|
||||||
schedulerManager.resumeJob(jobName);
|
|
||||||
log.info("[resumeTimerTriggers][场景规则({}) 定时触发器恢复成功]", sceneRuleId);
|
|
||||||
} catch (SchedulerException e) {
|
|
||||||
log.error("[resumeTimerTriggers][场景规则({}) 定时触发器恢复失败]", sceneRuleId, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册单个定时触发器
|
* 注册单个定时触发器
|
||||||
*
|
*
|
||||||
@ -146,18 +123,16 @@ public class IotSceneRuleTimerHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 构建任务名称和数据
|
|
||||||
String jobName = buildJobName(sceneRule.getId());
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 3. 注册定时任务
|
// 2.1 构建任务名称和数据
|
||||||
|
String jobName = buildJobName(sceneRule.getId());
|
||||||
|
// 2.2 注册定时任务
|
||||||
schedulerManager.addOrUpdateJob(
|
schedulerManager.addOrUpdateJob(
|
||||||
IotSceneRuleJob.class,
|
IotSceneRuleJob.class,
|
||||||
jobName,
|
jobName,
|
||||||
trigger.getCronExpression(),
|
trigger.getCronExpression(),
|
||||||
IotSceneRuleJob.buildJobDataMap(sceneRule.getId())
|
IotSceneRuleJob.buildJobDataMap(sceneRule.getId())
|
||||||
);
|
);
|
||||||
|
|
||||||
log.info("[registerSingleTimerTrigger][场景规则({}) 定时触发器注册成功,CRON: {}]",
|
log.info("[registerSingleTimerTrigger][场景规则({}) 定时触发器注册成功,CRON: {}]",
|
||||||
sceneRule.getId(), trigger.getCronExpression());
|
sceneRule.getId(), trigger.getCronExpression());
|
||||||
} catch (SchedulerException e) {
|
} catch (SchedulerException e) {
|
||||||
@ -169,10 +144,11 @@ public class IotSceneRuleTimerHandler {
|
|||||||
/**
|
/**
|
||||||
* 构建任务名称
|
* 构建任务名称
|
||||||
*
|
*
|
||||||
* @param sceneRuleId 场景规则ID
|
* @param sceneRuleId 场景规则 ID
|
||||||
* @return 任务名称
|
* @return 任务名称
|
||||||
*/
|
*/
|
||||||
private String buildJobName(Long sceneRuleId) {
|
private String buildJobName(Long sceneRuleId) {
|
||||||
return "iot_scene_rule_timer_" + sceneRuleId;
|
return "iot_scene_rule_timer_" + sceneRuleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import org.springframework.context.annotation.Bean;
|
|||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||||
|
|
||||||
|
// TODO @puhui999:建议改成 IotBaseConditionMatcherTest
|
||||||
/**
|
/**
|
||||||
* Matcher 测试基类
|
* Matcher 测试基类
|
||||||
* 提供通用的 Spring 测试配置
|
* 提供通用的 Spring 测试配置
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user