refactor: 【IoT 物联网】统一场景联动 ‘IoT’ 前缀

This commit is contained in:
puhui999
2025-09-19 10:59:32 +08:00
parent e639dbfeb7
commit 057f924bd1
18 changed files with 175 additions and 63 deletions

View File

@@ -16,7 +16,6 @@ import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
// TODO @puhui999是不是 IoT 的前缀都加下哈
/**
* 当前时间条件匹配器处理时间相关的子条件匹配逻辑
*
@@ -24,7 +23,7 @@ import java.util.List;
*/
@Component
@Slf4j
public class CurrentTimeConditionMatcher implements IotSceneRuleConditionMatcher {
public class IotCurrentTimeConditionMatcher implements IotSceneRuleConditionMatcher {
/**
* 时间格式化器 - HH:mm:ss

View File

@@ -15,7 +15,7 @@ import org.springframework.stereotype.Component;
* @author HUIHUI
*/
@Component
public class DevicePropertyConditionMatcher implements IotSceneRuleConditionMatcher {
public class IotDevicePropertyConditionMatcher implements IotSceneRuleConditionMatcher {
@Override
public IotSceneRuleConditionTypeEnum getSupportedConditionType() {

View File

@@ -13,7 +13,7 @@ import org.springframework.stereotype.Component;
* @author HUIHUI
*/
@Component
public class DeviceStateConditionMatcher implements IotSceneRuleConditionMatcher {
public class IotDeviceStateConditionMatcher implements IotSceneRuleConditionMatcher {
@Override
public IotSceneRuleConditionTypeEnum getSupportedConditionType() {

View File

@@ -15,7 +15,7 @@ import org.springframework.stereotype.Component;
* @author HUIHUI
*/
@Component
public class DeviceEventPostTriggerMatcher implements IotSceneRuleTriggerMatcher {
public class IotDeviceEventPostTriggerMatcher implements IotSceneRuleTriggerMatcher {
@Override
public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() {

View File

@@ -14,7 +14,7 @@ import org.springframework.stereotype.Component;
* @author HUIHUI
*/
@Component
public class DevicePropertyPostTriggerMatcher implements IotSceneRuleTriggerMatcher {
public class IotDevicePropertyPostTriggerMatcher implements IotSceneRuleTriggerMatcher {
@Override
public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() {

View File

@@ -14,7 +14,7 @@ import org.springframework.stereotype.Component;
* @author HUIHUI
*/
@Component
public class DeviceServiceInvokeTriggerMatcher implements IotSceneRuleTriggerMatcher {
public class IotDeviceServiceInvokeTriggerMatcher implements IotSceneRuleTriggerMatcher {
@Override
public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() {

View File

@@ -14,7 +14,7 @@ import org.springframework.stereotype.Component;
* @author HUIHUI
*/
@Component
public class DeviceStateUpdateTriggerMatcher implements IotSceneRuleTriggerMatcher {
public class IotDeviceStateUpdateTriggerMatcher implements IotSceneRuleTriggerMatcher {
@Override
public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() {

View File

@@ -16,7 +16,7 @@ import org.springframework.stereotype.Component;
* @author HUIHUI
*/
@Component
public class TimerTriggerMatcher implements IotSceneRuleTriggerMatcher {
public class IotTimerTriggerMatcher implements IotSceneRuleTriggerMatcher {
@Override
public IotSceneRuleTriggerTypeEnum getSupportedTriggerType() {

View File

@@ -6,7 +6,6 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
// TODO @puhui999建议改成 IotBaseConditionMatcherTest
/**
* Matcher 测试基类
* 提供通用的 Spring 测试配置
@@ -14,7 +13,7 @@ import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
* @author HUIHUI
*/
@SpringJUnitConfig
public abstract class BaseMatcherTest {
public abstract class IotBaseConditionMatcherTest {
/**
* 注入一下 SpringUtil解析 EL 表达式时需要

View File

@@ -4,7 +4,7 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
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.rule.scene.matcher.BaseMatcherTest;
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotBaseConditionMatcherTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -16,17 +16,17 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link CurrentTimeConditionMatcher} 的单元测试
* {@link IotCurrentTimeConditionMatcher} 的单元测试
*
* @author HUIHUI
*/
public class CurrentTimeConditionMatcherTest extends BaseMatcherTest {
public class IotCurrentTimeConditionMatcherTest extends IotBaseConditionMatcherTest {
private CurrentTimeConditionMatcher matcher;
private IotCurrentTimeConditionMatcher matcher;
@BeforeEach
public void setUp() {
matcher = new CurrentTimeConditionMatcher();
matcher = new IotCurrentTimeConditionMatcher();
}
@Test

View File

@@ -4,7 +4,7 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
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.rule.scene.matcher.BaseMatcherTest;
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotBaseConditionMatcherTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -15,17 +15,17 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link DevicePropertyConditionMatcher} 的单元测试
* {@link IotDevicePropertyConditionMatcher} 的单元测试
*
* @author HUIHUI
*/
public class DevicePropertyConditionMatcherTest extends BaseMatcherTest {
public class IotDevicePropertyConditionMatcherTest extends IotBaseConditionMatcherTest {
private DevicePropertyConditionMatcher matcher;
private IotDevicePropertyConditionMatcher matcher;
@BeforeEach
public void setUp() {
matcher = new DevicePropertyConditionMatcher();
matcher = new IotDevicePropertyConditionMatcher();
}
@Test

View File

@@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
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.rule.scene.matcher.BaseMatcherTest;
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotBaseConditionMatcherTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -14,17 +14,17 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link DeviceStateConditionMatcher} 的单元测试
* {@link IotDeviceStateConditionMatcher} 的单元测试
*
* @author HUIHUI
*/
public class DeviceStateConditionMatcherTest extends BaseMatcherTest {
public class IotDeviceStateConditionMatcherTest extends IotBaseConditionMatcherTest {
private DeviceStateConditionMatcher matcher;
private IotDeviceStateConditionMatcher matcher;
@BeforeEach
public void setUp() {
matcher = new DeviceStateConditionMatcher();
matcher = new IotDeviceStateConditionMatcher();
}
@Test

View File

@@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.BaseMatcherTest;
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotBaseConditionMatcherTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -18,17 +18,17 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link DeviceEventPostTriggerMatcher} 的单元测试
* {@link IotDeviceEventPostTriggerMatcher} 的单元测试
*
* @author HUIHUI
*/
public class DeviceEventPostTriggerMatcherTest extends BaseMatcherTest {
public class IotDeviceEventPostTriggerMatcherTest extends IotBaseConditionMatcherTest {
private DeviceEventPostTriggerMatcher matcher;
private IotDeviceEventPostTriggerMatcher matcher;
@BeforeEach
public void setUp() {
matcher = new DeviceEventPostTriggerMatcher();
matcher = new IotDeviceEventPostTriggerMatcher();
}
@Test

View File

@@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
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.IotSceneRuleTriggerTypeEnum;
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.BaseMatcherTest;
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotBaseConditionMatcherTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -20,17 +20,17 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link DevicePropertyPostTriggerMatcher} 的单元测试
* {@link IotDevicePropertyPostTriggerMatcher} 的单元测试
*
* @author HUIHUI
*/
public class DevicePropertyPostTriggerMatcherTest extends BaseMatcherTest {
public class IotDevicePropertyPostTriggerMatcherTest extends IotBaseConditionMatcherTest {
private DevicePropertyPostTriggerMatcher matcher;
private IotDevicePropertyPostTriggerMatcher matcher;
@BeforeEach
public void setUp() {
matcher = new DevicePropertyPostTriggerMatcher();
matcher = new IotDevicePropertyPostTriggerMatcher();
}
@Test

View File

@@ -5,7 +5,7 @@ import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.BaseMatcherTest;
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotBaseConditionMatcherTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -18,17 +18,17 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link DeviceServiceInvokeTriggerMatcher} 的单元测试
* {@link IotDeviceServiceInvokeTriggerMatcher} 的单元测试
*
* @author HUIHUI
*/
public class DeviceServiceInvokeTriggerMatcherTest extends BaseMatcherTest {
public class IotDeviceServiceInvokeTriggerMatcherTest extends IotBaseConditionMatcherTest {
private DeviceServiceInvokeTriggerMatcher matcher;
private IotDeviceServiceInvokeTriggerMatcher matcher;
@BeforeEach
public void setUp() {
matcher = new DeviceServiceInvokeTriggerMatcher();
matcher = new IotDeviceServiceInvokeTriggerMatcher();
}
@Test

View File

@@ -1,42 +1,30 @@
package cn.iocoder.yudao.module.iot.service.rule.scene.matcher.trigger;
import cn.hutool.extra.spring.SpringUtil;
import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum;
import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
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.IotSceneRuleTriggerTypeEnum;
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotBaseConditionMatcherTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link DeviceStateUpdateTriggerMatcher} 的单元测试
* {@link IotDeviceStateUpdateTriggerMatcher} 的单元测试
*
* @author HUIHUI
*/
@SpringJUnitConfig(DeviceStateUpdateTriggerMatcherTest.TestConfig.class)
public class DeviceStateUpdateTriggerMatcherTest {
public class IotDeviceStateUpdateTriggerMatcherTest extends IotBaseConditionMatcherTest {
@Configuration
static class TestConfig {
@Bean
public SpringUtil springUtil() {
return new SpringUtil();
}
}
private DeviceStateUpdateTriggerMatcher matcher;
private IotDeviceStateUpdateTriggerMatcher matcher;
@BeforeEach
public void setUp() {
matcher = new DeviceStateUpdateTriggerMatcher();
matcher = new IotDeviceStateUpdateTriggerMatcher();
}
@Test

View File

@@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.service.rule.scene.matcher.trigger;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.BaseMatcherTest;
import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotBaseConditionMatcherTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -12,17 +12,17 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString
import static org.junit.jupiter.api.Assertions.*;
/**
* {@link TimerTriggerMatcher} 的单元测试
* {@link IotTimerTriggerMatcher} 的单元测试
*
* @author HUIHUI
*/
public class TimerTriggerMatcherTest extends BaseMatcherTest {
public class IotTimerTriggerMatcherTest extends IotBaseConditionMatcherTest {
private TimerTriggerMatcher matcher;
private IotTimerTriggerMatcher matcher;
@BeforeEach
public void setUp() {
matcher = new TimerTriggerMatcher();
matcher = new IotTimerTriggerMatcher();
}
@Test

View File

@@ -0,0 +1,126 @@
package cn.iocoder.yudao.module.iot.service.rule.scene.timer;
import cn.hutool.core.collection.ListUtil;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
import cn.iocoder.yudao.module.iot.framework.job.core.IotSchedulerManager;
import cn.iocoder.yudao.module.iot.job.rule.IotSceneRuleJob;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.quartz.SchedulerException;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;
/**
* {@link IotSceneRuleTimerHandler} 的单元测试类
*
* @author HUIHUI
*/
@ExtendWith(MockitoExtension.class)
public class IotSceneRuleTimerHandlerTest {
@Mock
private IotSchedulerManager schedulerManager;
@InjectMocks
private IotSceneRuleTimerHandler timerHandler;
@BeforeEach
void setUp() {
// 重置 Mock 对象
reset(schedulerManager);
}
@Test
public void testRegisterTimerTriggers_success() throws SchedulerException {
// 准备参数
Long sceneRuleId = 1L;
IotSceneRuleDO sceneRule = new IotSceneRuleDO();
sceneRule.setId(sceneRuleId);
sceneRule.setStatus(0); // 0 表示启用
// 创建定时触发器
IotSceneRuleDO.Trigger timerTrigger = new IotSceneRuleDO.Trigger();
timerTrigger.setType(IotSceneRuleTriggerTypeEnum.TIMER.getType());
timerTrigger.setCronExpression("0 0 12 * * ?"); // 每天中午12点
sceneRule.setTriggers(ListUtil.toList(timerTrigger));
// 调用
timerHandler.registerTimerTriggers(sceneRule);
// 验证
verify(schedulerManager, times(1)).addOrUpdateJob(
eq(IotSceneRuleJob.class),
eq("iot_scene_rule_timer_" + sceneRuleId),
eq("0 0 12 * * ?"),
eq(IotSceneRuleJob.buildJobDataMap(sceneRuleId))
);
}
@Test
public void testRegisterTimerTriggers_noTimerTrigger() throws SchedulerException {
// 准备参数 - 没有定时触发器
IotSceneRuleDO sceneRule = new IotSceneRuleDO();
sceneRule.setStatus(0); // 0 表示启用
// 创建非定时触发器
IotSceneRuleDO.Trigger deviceTrigger = new IotSceneRuleDO.Trigger();
deviceTrigger.setType(IotSceneRuleTriggerTypeEnum.DEVICE_PROPERTY_POST.getType());
sceneRule.setTriggers(ListUtil.toList(deviceTrigger));
// 调用
timerHandler.registerTimerTriggers(sceneRule);
// 验证 - 不应该调用调度器
verify(schedulerManager, never()).addOrUpdateJob(any(), any(), any(), any());
}
@Test
public void testRegisterTimerTriggers_emptyCronExpression() throws SchedulerException {
// 准备参数 - CRON 表达式为空
Long sceneRuleId = 2L;
IotSceneRuleDO sceneRule = new IotSceneRuleDO();
sceneRule.setId(sceneRuleId);
sceneRule.setStatus(0); // 0 表示启用
// 创建定时触发器但没有 CRON 表达式
IotSceneRuleDO.Trigger timerTrigger = new IotSceneRuleDO.Trigger();
timerTrigger.setType(IotSceneRuleTriggerTypeEnum.TIMER.getType());
timerTrigger.setCronExpression(""); // 空的 CRON 表达式
sceneRule.setTriggers(ListUtil.toList(timerTrigger));
// 调用
timerHandler.registerTimerTriggers(sceneRule);
// 验证 - 不应该调用调度器
verify(schedulerManager, never()).addOrUpdateJob(any(), any(), any(), any());
}
@Test
public void testUnregisterTimerTriggers_success() throws SchedulerException {
// 准备参数
Long sceneRuleId = 3L;
// 调用
timerHandler.unregisterTimerTriggers(sceneRuleId);
// 验证
verify(schedulerManager, times(1)).deleteJob("iot_scene_rule_timer_" + sceneRuleId);
}
@Test
public void testPauseTimerTriggers_success() throws SchedulerException {
// 准备参数
Long sceneRuleId = 4L;
// 调用
timerHandler.pauseTimerTriggers(sceneRuleId);
// 验证
verify(schedulerManager, times(1)).pauseJob("iot_scene_rule_timer_" + sceneRuleId);
}
}