mirror of
				https://github.com/YunaiV/ruoyi-vue-pro.git
				synced 2025-11-04 08:06:12 +08:00 
			
		
		
		
	feat: 【IoT 物联网】场景联动规则的数据缓存,使用 Spring Cache 操作
This commit is contained in:
		@ -76,4 +76,12 @@ public interface RedisKeyConstants {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    String DATA_SINK = "iot:data_sink";
 | 
					    String DATA_SINK = "iot:data_sink";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * 场景联动规则的数据缓存,使用 Spring Cache 操作
 | 
				
			||||||
 | 
					     * <p>
 | 
				
			||||||
 | 
					     * KEY 格式:scene_rule_list_${productId}_${deviceId}
 | 
				
			||||||
 | 
					     * VALUE 数据类型:String 数组(JSON),即 {@link cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO} 列表
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    String SCENE_RULE_LIST = "iot:scene_rule_list";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
 | 
				
			|||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
 | 
					import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
 | 
				
			||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
 | 
					import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
 | 
				
			||||||
import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotSceneRuleMapper;
 | 
					import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotSceneRuleMapper;
 | 
				
			||||||
 | 
					import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants;
 | 
				
			||||||
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
 | 
					import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
 | 
				
			||||||
import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
 | 
					import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
 | 
				
			||||||
import cn.iocoder.yudao.module.iot.service.product.IotProductService;
 | 
					import cn.iocoder.yudao.module.iot.service.product.IotProductService;
 | 
				
			||||||
@ -24,6 +25,8 @@ import cn.iocoder.yudao.module.iot.service.rule.scene.matcher.IotSceneRuleMatche
 | 
				
			|||||||
import cn.iocoder.yudao.module.iot.service.rule.scene.timer.IotSceneRuleTimerHandler;
 | 
					import cn.iocoder.yudao.module.iot.service.rule.scene.timer.IotSceneRuleTimerHandler;
 | 
				
			||||||
import jakarta.annotation.Resource;
 | 
					import jakarta.annotation.Resource;
 | 
				
			||||||
import lombok.extern.slf4j.Slf4j;
 | 
					import lombok.extern.slf4j.Slf4j;
 | 
				
			||||||
 | 
					import org.springframework.cache.annotation.CacheEvict;
 | 
				
			||||||
 | 
					import org.springframework.cache.annotation.Cacheable;
 | 
				
			||||||
import org.springframework.stereotype.Service;
 | 
					import org.springframework.stereotype.Service;
 | 
				
			||||||
import org.springframework.validation.annotation.Validated;
 | 
					import org.springframework.validation.annotation.Validated;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -60,6 +63,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
 | 
				
			|||||||
    private IotSceneRuleTimerHandler timerHandler;
 | 
					    private IotSceneRuleTimerHandler timerHandler;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 | 
					    @CacheEvict(value = RedisKeyConstants.SCENE_RULE_LIST, allEntries = true)
 | 
				
			||||||
    public Long createSceneRule(IotSceneRuleSaveReqVO createReqVO) {
 | 
					    public Long createSceneRule(IotSceneRuleSaveReqVO createReqVO) {
 | 
				
			||||||
        IotSceneRuleDO sceneRule = BeanUtils.toBean(createReqVO, IotSceneRuleDO.class);
 | 
					        IotSceneRuleDO sceneRule = BeanUtils.toBean(createReqVO, IotSceneRuleDO.class);
 | 
				
			||||||
        sceneRuleMapper.insert(sceneRule);
 | 
					        sceneRuleMapper.insert(sceneRule);
 | 
				
			||||||
@ -71,6 +75,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 | 
					    @CacheEvict(value = RedisKeyConstants.SCENE_RULE_LIST, allEntries = true)
 | 
				
			||||||
    public void updateSceneRule(IotSceneRuleSaveReqVO updateReqVO) {
 | 
					    public void updateSceneRule(IotSceneRuleSaveReqVO updateReqVO) {
 | 
				
			||||||
        // 校验存在
 | 
					        // 校验存在
 | 
				
			||||||
        validateSceneRuleExists(updateReqVO.getId());
 | 
					        validateSceneRuleExists(updateReqVO.getId());
 | 
				
			||||||
@ -83,6 +88,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 | 
					    @CacheEvict(value = RedisKeyConstants.SCENE_RULE_LIST, allEntries = true)
 | 
				
			||||||
    public void updateSceneRuleStatus(Long id, Integer status) {
 | 
					    public void updateSceneRuleStatus(Long id, Integer status) {
 | 
				
			||||||
        // 1. 校验存在
 | 
					        // 1. 校验存在
 | 
				
			||||||
        validateSceneRuleExists(id);
 | 
					        validateSceneRuleExists(id);
 | 
				
			||||||
@ -105,6 +111,7 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 | 
					    @CacheEvict(value = RedisKeyConstants.SCENE_RULE_LIST, allEntries = true)
 | 
				
			||||||
    public void deleteSceneRule(Long id) {
 | 
					    public void deleteSceneRule(Long id) {
 | 
				
			||||||
        // 1. 校验存在
 | 
					        // 1. 校验存在
 | 
				
			||||||
        validateSceneRuleExists(id);
 | 
					        validateSceneRuleExists(id);
 | 
				
			||||||
@ -149,15 +156,12 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
 | 
				
			|||||||
        return sceneRuleMapper.selectListByStatus(status);
 | 
					        return sceneRuleMapper.selectListByStatus(status);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // TODO @puhui999:缓存待实现
 | 
					 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
 | 
					    @Cacheable(value = RedisKeyConstants.SCENE_RULE_LIST, key = "#productId + '_' + #deviceId ")
 | 
				
			||||||
    @TenantIgnore // 忽略租户隔离:因为 IotSceneRuleMessageHandler 调用时,一般未传递租户,所以需要忽略
 | 
					    @TenantIgnore // 忽略租户隔离:因为 IotSceneRuleMessageHandler 调用时,一般未传递租户,所以需要忽略
 | 
				
			||||||
    public List<IotSceneRuleDO> getSceneRuleListByProductIdAndDeviceIdFromCache(Long productId, Long deviceId) {
 | 
					    public List<IotSceneRuleDO> getSceneRuleListByProductIdAndDeviceIdFromCache(Long productId, Long deviceId) {
 | 
				
			||||||
        // 1. 查询启用状态的规则场景
 | 
					        // 1. 查询启用状态的规则场景
 | 
				
			||||||
        // TODO @puhui999:这里查询 enable 的;
 | 
					        List<IotSceneRuleDO> enabledList = sceneRuleMapper.selectList(IotSceneRuleDO::getStatus, CommonStatusEnum.ENABLE.getStatus());
 | 
				
			||||||
        List<IotSceneRuleDO> list = sceneRuleMapper.selectList();
 | 
					 | 
				
			||||||
        List<IotSceneRuleDO> enabledList = filterList(list,
 | 
					 | 
				
			||||||
                sceneRule -> CommonStatusEnum.isEnable(sceneRule.getStatus()));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 2. 根据 productKey 和 deviceName 进行匹配
 | 
					        // 2. 根据 productKey 和 deviceName 进行匹配
 | 
				
			||||||
        return filterList(enabledList, sceneRule -> {
 | 
					        return filterList(enabledList, sceneRule -> {
 | 
				
			||||||
@ -190,9 +194,10 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void executeSceneRuleByDevice(IotDeviceMessage message) {
 | 
					    public void executeSceneRuleByDevice(IotDeviceMessage message) {
 | 
				
			||||||
        // TODO @puhui999:这里的 tenantId,通过设备获取;
 | 
					        // 1.1 这里的 tenantId,通过设备获取;
 | 
				
			||||||
        TenantUtils.execute(message.getTenantId(), () -> {
 | 
					        IotDeviceDO device = deviceService.getDeviceFromCache(message.getDeviceId());
 | 
				
			||||||
            // 1. 获得设备匹配的规则场景
 | 
					        TenantUtils.execute(device.getTenantId(), () -> {
 | 
				
			||||||
 | 
					            // 1.2 获得设备匹配的规则场景
 | 
				
			||||||
            List<IotSceneRuleDO> sceneRules = getMatchedSceneRuleListByMessage(message);
 | 
					            List<IotSceneRuleDO> sceneRules = getMatchedSceneRuleListByMessage(message);
 | 
				
			||||||
            if (CollUtil.isEmpty(sceneRules)) {
 | 
					            if (CollUtil.isEmpty(sceneRules)) {
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
@ -238,14 +243,14 @@ public class IotSceneRuleServiceImpl implements IotSceneRuleService {
 | 
				
			|||||||
        // 1. 匹配设备
 | 
					        // 1. 匹配设备
 | 
				
			||||||
        // TODO 缓存 @puhui999:可能需要 getSelf()
 | 
					        // TODO 缓存 @puhui999:可能需要 getSelf()
 | 
				
			||||||
        // 1.1 通过 deviceId 获取设备信息
 | 
					        // 1.1 通过 deviceId 获取设备信息
 | 
				
			||||||
        IotDeviceDO device = deviceService.getDeviceFromCache(message.getDeviceId());
 | 
					        IotDeviceDO device = getSelf().deviceService.getDeviceFromCache(message.getDeviceId());
 | 
				
			||||||
        if (device == null) {
 | 
					        if (device == null) {
 | 
				
			||||||
            log.warn("[getMatchedSceneRuleListByMessage][设备({}) 不存在]", message.getDeviceId());
 | 
					            log.warn("[getMatchedSceneRuleListByMessage][设备({}) 不存在]", message.getDeviceId());
 | 
				
			||||||
            return List.of();
 | 
					            return List.of();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // 1.2 通过 productId 获取产品信息
 | 
					        // 1.2 通过 productId 获取产品信息
 | 
				
			||||||
        IotProductDO product = productService.getProductFromCache(device.getProductId());
 | 
					        IotProductDO product = getSelf().productService.getProductFromCache(device.getProductId());
 | 
				
			||||||
        if (product == null) {
 | 
					        if (product == null) {
 | 
				
			||||||
            log.warn("[getMatchedSceneRuleListByMessage][产品({}) 不存在]", device.getProductId());
 | 
					            log.warn("[getMatchedSceneRuleListByMessage][产品({}) 不存在]", device.getProductId());
 | 
				
			||||||
            return List.of();
 | 
					            return List.of();
 | 
				
			||||||
 | 
				
			|||||||
@ -44,7 +44,7 @@ public class IotDeviceServiceInvokeTriggerMatcher implements IotSceneRuleTrigger
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // 2. 对于服务调用触发器,通常只需要匹配服务标识符即可
 | 
					        // 2. 对于服务调用触发器,通常只需要匹配服务标识符即可
 | 
				
			||||||
        // 不需要检查操作符和值,因为服务调用本身就是触发条件
 | 
					        // 不需要检查操作符和值,因为服务调用本身就是触发条件
 | 
				
			||||||
        // TODO @puhui999: 服务调用时校验输入参数是否匹配条件
 | 
					        // TODO @puhui999: 服务调用时校验输入参数是否匹配条件?
 | 
				
			||||||
        IotSceneRuleMatcherHelper.logTriggerMatchSuccess(message, trigger);
 | 
					        IotSceneRuleMatcherHelper.logTriggerMatchSuccess(message, trigger);
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user