Commit ea1f0cb462520cc0a3bd1633e02672a6c0ebac97

Authored by YunaiV
1 parent 2a04bdc3

feat:【IoT 物联网】实现“数据流转”功能的执行(80%)

Showing 19 changed files with 272 additions and 148 deletions
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/device/IotDeviceMessageIdentifierEnum.java
@@ -7,6 +7,7 @@ import lombok.RequiredArgsConstructor; @@ -7,6 +7,7 @@ import lombok.RequiredArgsConstructor;
7 /** 7 /**
8 * IoT 设备消息标识符枚举 8 * IoT 设备消息标识符枚举
9 */ 9 */
  10 +@Deprecated
10 @Getter 11 @Getter
11 @RequiredArgsConstructor 12 @RequiredArgsConstructor
12 public enum IotDeviceMessageIdentifierEnum { 13 public enum IotDeviceMessageIdentifierEnum {
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/rule/IotRuleSceneActionTypeEnum.java
@@ -40,9 +40,7 @@ public enum IotRuleSceneActionTypeEnum implements ArrayValuable<Integer> { @@ -40,9 +40,7 @@ public enum IotRuleSceneActionTypeEnum implements ArrayValuable<Integer> {
40 40
41 @Deprecated 41 @Deprecated
42 ALERT(2), // 告警执行 42 ALERT(2), // 告警执行
43 -  
44 - @Deprecated  
45 - DATA_BRIDGE(3); // 桥接执行 43 + ;
46 44
47 private final Integer type; 45 private final Integer type;
48 46
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/rule/IotDataRuleMapper.java
@@ -31,4 +31,8 @@ public interface IotDataRuleMapper extends BaseMapperX<IotDataRuleDO> { @@ -31,4 +31,8 @@ public interface IotDataRuleMapper extends BaseMapperX<IotDataRuleDO> {
31 .apply(MyBatisUtils.findInSet("sink_ids", sinkId))); 31 .apply(MyBatisUtils.findInSet("sink_ids", sinkId)));
32 } 32 }
33 33
  34 + default List<IotDataRuleDO> selectListByStatus(Integer status) {
  35 + return selectList(IotDataRuleDO::getStatus, status);
  36 + }
  37 +
34 } 38 }
35 \ No newline at end of file 39 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/RedisKeyConstants.java
@@ -60,4 +60,20 @@ public interface RedisKeyConstants { @@ -60,4 +60,20 @@ public interface RedisKeyConstants {
60 */ 60 */
61 String THING_MODEL_LIST = "iot:thing_model_list"; 61 String THING_MODEL_LIST = "iot:thing_model_list";
62 62
  63 + /**
  64 + * 数据流转规则的数据缓存,使用 Spring Cache 操作
  65 + *
  66 + * KEY 格式:data_rule_list_${deviceId}_${method}_${identifier}
  67 + * VALUE 数据类型:String 数组(JSON),即 {@link cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataRuleDO} 列表
  68 + */
  69 + String DATA_RULE_LIST = "iot:data_rule_list";
  70 +
  71 + /**
  72 + * 数据目的的数据缓存,使用 Spring Cache 操作
  73 + *
  74 + * KEY 格式:data_sink_${id}
  75 + * VALUE 数据类型:String(JSON),即 {@link cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataSinkDO}
  76 + */
  77 + String DATA_SINK = "iot:data_sink";
  78 +
63 } 79 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/mq/consumer/rule/IotDataRuleMessageHandler.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.mq.consumer.rule;
  2 +
  3 +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
  4 +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
  5 +import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber;
  6 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
  7 +import cn.iocoder.yudao.module.iot.service.rule.data.IotDataRuleService;
  8 +import jakarta.annotation.PostConstruct;
  9 +import jakarta.annotation.Resource;
  10 +import lombok.extern.slf4j.Slf4j;
  11 +import org.springframework.stereotype.Component;
  12 +
  13 +// TODO @puhui999:后面重构哈
  14 +
  15 +/**
  16 + * 针对 {@link IotDeviceMessage} 的消费者,处理数据流转
  17 + *
  18 + * @author 芋道源码
  19 + */
  20 +@Component
  21 +@Slf4j
  22 +public class IotDataRuleMessageHandler implements IotMessageSubscriber<IotDeviceMessage> {
  23 +
  24 + @Resource
  25 + private IotDataRuleService dataRuleService;
  26 +
  27 + @Resource
  28 + private IotMessageBus messageBus;
  29 +
  30 + @PostConstruct
  31 + public void init() {
  32 + messageBus.register(this);
  33 + }
  34 +
  35 + @Override
  36 + public String getTopic() {
  37 + return IotDeviceMessage.MESSAGE_BUS_DEVICE_MESSAGE_TOPIC;
  38 + }
  39 +
  40 + @Override
  41 + public String getGroup() {
  42 + return "iot_data_rule_consumer";
  43 + }
  44 +
  45 + @Override
  46 + public void onMessage(IotDeviceMessage message) {
  47 + TenantUtils.execute(message.getTenantId(), () -> dataRuleService.executeDataRule(message));
  48 + }
  49 +
  50 +}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataRuleService.java
1 package cn.iocoder.yudao.module.iot.service.rule.data; 1 package cn.iocoder.yudao.module.iot.service.rule.data;
2 2
3 -import java.util.List;  
4 -  
5 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRulePageReqVO; 4 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRulePageReqVO;
7 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRuleSaveReqVO; 5 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRuleSaveReqVO;
  6 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
8 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataRuleDO; 7 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataRuleDO;
9 import jakarta.validation.Valid; 8 import jakarta.validation.Valid;
10 9
  10 +import java.util.List;
  11 +
11 /** 12 /**
12 * IoT 数据流转规则 Service 接口 13 * IoT 数据流转规则 Service 接口
13 * 14 *
@@ -59,6 +60,13 @@ public interface IotDataRuleService { @@ -59,6 +60,13 @@ public interface IotDataRuleService {
59 * @param sinkId 数据目的编号 60 * @param sinkId 数据目的编号
60 * @return 是否被使用 61 * @return 是否被使用
61 */ 62 */
62 - List<IotDataRuleDO> getDataRuleBySinkId(Long sinkId); 63 + List<IotDataRuleDO> getDataRuleListBySinkId(Long sinkId);
  64 +
  65 + /**
  66 + * 执行数据流转规则
  67 + *
  68 + * @param message 消息
  69 + */
  70 + void executeDataRule(IotDeviceMessage message);
63 71
64 } 72 }
65 \ No newline at end of file 73 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataRuleServiceImpl.java
@@ -3,17 +3,28 @@ package cn.iocoder.yudao.module.iot.service.rule.data; @@ -3,17 +3,28 @@ package cn.iocoder.yudao.module.iot.service.rule.data;
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.ObjUtil; 4 import cn.hutool.core.util.ObjUtil;
5 import cn.hutool.core.util.StrUtil; 5 import cn.hutool.core.util.StrUtil;
  6 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 8 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
  9 +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
  10 +import cn.iocoder.yudao.framework.common.util.spring.SpringUtils;
8 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRulePageReqVO; 11 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRulePageReqVO;
9 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRuleSaveReqVO; 12 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRuleSaveReqVO;
  13 +import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
  14 +import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils;
10 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; 15 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
11 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataRuleDO; 16 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataRuleDO;
  17 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataSinkDO;
12 import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotDataRuleMapper; 18 import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotDataRuleMapper;
  19 +import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants;
13 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; 20 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
14 import cn.iocoder.yudao.module.iot.service.product.IotProductService; 21 import cn.iocoder.yudao.module.iot.service.product.IotProductService;
  22 +import cn.iocoder.yudao.module.iot.service.rule.data.action.IotDataRuleAction;
15 import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService; 23 import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService;
16 import jakarta.annotation.Resource; 24 import jakarta.annotation.Resource;
  25 +import lombok.extern.slf4j.Slf4j;
  26 +import org.springframework.cache.annotation.CacheEvict;
  27 +import org.springframework.cache.annotation.Cacheable;
17 import org.springframework.stereotype.Service; 28 import org.springframework.stereotype.Service;
18 import org.springframework.validation.annotation.Validated; 29 import org.springframework.validation.annotation.Validated;
19 30
@@ -30,6 +41,7 @@ import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DATA_RULE_NOT @@ -30,6 +41,7 @@ import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DATA_RULE_NOT
30 */ 41 */
31 @Service 42 @Service
32 @Validated 43 @Validated
  44 +@Slf4j
33 public class IotDataRuleServiceImpl implements IotDataRuleService { 45 public class IotDataRuleServiceImpl implements IotDataRuleService {
34 46
35 @Resource 47 @Resource
@@ -44,7 +56,11 @@ public class IotDataRuleServiceImpl implements IotDataRuleService { @@ -44,7 +56,11 @@ public class IotDataRuleServiceImpl implements IotDataRuleService {
44 @Resource 56 @Resource
45 private IotDataSinkService dataSinkService; 57 private IotDataSinkService dataSinkService;
46 58
  59 + @Resource
  60 + private List<IotDataRuleAction> dataRuleActions;
  61 +
47 @Override 62 @Override
  63 + @CacheEvict(value = RedisKeyConstants.DATA_RULE_LIST, allEntries = true)
48 public Long createDataRule(IotDataRuleSaveReqVO createReqVO) { 64 public Long createDataRule(IotDataRuleSaveReqVO createReqVO) {
49 // 校验数据源配置和数据目的 65 // 校验数据源配置和数据目的
50 validateDataRuleConfig(createReqVO); 66 validateDataRuleConfig(createReqVO);
@@ -55,6 +71,7 @@ public class IotDataRuleServiceImpl implements IotDataRuleService { @@ -55,6 +71,7 @@ public class IotDataRuleServiceImpl implements IotDataRuleService {
55 } 71 }
56 72
57 @Override 73 @Override
  74 + @CacheEvict(value = RedisKeyConstants.DATA_RULE_LIST, allEntries = true)
58 public void updateDataRule(IotDataRuleSaveReqVO updateReqVO) { 75 public void updateDataRule(IotDataRuleSaveReqVO updateReqVO) {
59 // 校验存在 76 // 校验存在
60 validateDataRuleExists(updateReqVO.getId()); 77 validateDataRuleExists(updateReqVO.getId());
@@ -67,6 +84,7 @@ public class IotDataRuleServiceImpl implements IotDataRuleService { @@ -67,6 +84,7 @@ public class IotDataRuleServiceImpl implements IotDataRuleService {
67 } 84 }
68 85
69 @Override 86 @Override
  87 + @CacheEvict(value = RedisKeyConstants.DATA_RULE_LIST, allEntries = true)
70 public void deleteDataRule(Long id) { 88 public void deleteDataRule(Long id) {
71 // 校验存在 89 // 校验存在
72 validateDataRuleExists(id); 90 validateDataRuleExists(id);
@@ -116,15 +134,15 @@ public class IotDataRuleServiceImpl implements IotDataRuleService { @@ -116,15 +134,15 @@ public class IotDataRuleServiceImpl implements IotDataRuleService {
116 * @param sourceConfigs 数据源配置列表 134 * @param sourceConfigs 数据源配置列表
117 */ 135 */
118 private void validateThingModelsExist(List<IotDataRuleDO.SourceConfig> sourceConfigs) { 136 private void validateThingModelsExist(List<IotDataRuleDO.SourceConfig> sourceConfigs) {
119 - Map<Long, Set<String>> productIdToIdentifiers = new HashMap<>(); 137 + Map<Long, Set<String>> productIdIdentifiers = new HashMap<>();
120 for (IotDataRuleDO.SourceConfig config : sourceConfigs) { 138 for (IotDataRuleDO.SourceConfig config : sourceConfigs) {
121 if (StrUtil.isEmpty(config.getIdentifier())) { 139 if (StrUtil.isEmpty(config.getIdentifier())) {
122 continue; 140 continue;
123 } 141 }
124 - productIdToIdentifiers.computeIfAbsent(config.getProductId(), 142 + productIdIdentifiers.computeIfAbsent(config.getProductId(),
125 productId -> new HashSet<>()).add(config.getIdentifier()); 143 productId -> new HashSet<>()).add(config.getIdentifier());
126 } 144 }
127 - for (Map.Entry<Long, Set<String>> entry : productIdToIdentifiers.entrySet()) { 145 + for (Map.Entry<Long, Set<String>> entry : productIdIdentifiers.entrySet()) {
128 thingModelService.validateThingModelsExist(entry.getKey(), entry.getValue()); 146 thingModelService.validateThingModelsExist(entry.getKey(), entry.getValue());
129 } 147 }
130 } 148 }
@@ -140,8 +158,102 @@ public class IotDataRuleServiceImpl implements IotDataRuleService { @@ -140,8 +158,102 @@ public class IotDataRuleServiceImpl implements IotDataRuleService {
140 } 158 }
141 159
142 @Override 160 @Override
143 - public List<IotDataRuleDO> getDataRuleBySinkId(Long sinkId) { 161 + public List<IotDataRuleDO> getDataRuleListBySinkId(Long sinkId) {
144 return dataRuleMapper.selectListBySinkId(sinkId); 162 return dataRuleMapper.selectListBySinkId(sinkId);
145 } 163 }
146 164
  165 + @Cacheable(value = RedisKeyConstants.DATA_RULE_LIST,
  166 + key = "#deviceId + '_' + #method + '_' + (#identifier ?: '')")
  167 + public List<IotDataRuleDO> getDataRuleListByConditionFromCache(Long deviceId, String method, String identifier) {
  168 + // 1. 查询所有开启的数据流转规则
  169 + List<IotDataRuleDO> rules = dataRuleMapper.selectListByStatus(CommonStatusEnum.ENABLE.getStatus());
  170 + // 2. 内存里过滤匹配的规则
  171 + List<IotDataRuleDO> matchedRules = new ArrayList<>();
  172 + for (IotDataRuleDO rule : rules) {
  173 + IotDataRuleDO.SourceConfig found = CollUtil.findOne(rule.getSourceConfigs(),
  174 + config -> ObjectUtils.equalsAny(config.getDeviceId(), deviceId, IotDeviceDO.DEVICE_ID_ALL)
  175 + && (StrUtil.isNotEmpty(config.getMethod()) || ObjUtil.equal(config.getMethod(), method))
  176 + && (StrUtil.isEmpty(config.getIdentifier()) || ObjUtil.equal(config.getIdentifier(), identifier)));
  177 + if (found != null) {
  178 + matchedRules.add(new IotDataRuleDO().setId(rule.getId()).setSinkIds(rule.getSinkIds()));
  179 + }
  180 + }
  181 + return matchedRules;
  182 + }
  183 +
  184 + @Override
  185 + public void executeDataRule(IotDeviceMessage message) {
  186 + try {
  187 + // 1. 获取匹配的数据流转规则
  188 + Long deviceId = message.getDeviceId();
  189 + String method = message.getMethod();
  190 + String identifier = IotDeviceMessageUtils.getIdentifier(message);
  191 + List<IotDataRuleDO> rules = getSelf().getDataRuleListByConditionFromCache(deviceId, method, identifier);
  192 + if (CollUtil.isEmpty(rules)) {
  193 + log.debug("[executeDataRule][设备({}) 方法({}) 标识符({}) 没有匹配的数据流转规则]",
  194 + deviceId, method, identifier);
  195 + return;
  196 + }
  197 + log.info("[executeDataRule][设备({}) 方法({}) 标识符({}) 匹配到 {} 条数据流转规则]",
  198 + deviceId, method, identifier, rules.size());
  199 +
  200 + // 2. 遍历规则,执行数据流转
  201 + rules.forEach(rule -> executeDataRule(message, rule));
  202 + } catch (Exception e) {
  203 + log.error("[executeDataRule][消息({}) 执行数据流转规则异常]", message, e);
  204 + }
  205 + }
  206 +
  207 + /**
  208 + * 为指定规则的所有数据目的执行数据流转
  209 + *
  210 + * @param message 设备消息
  211 + * @param rule 数据流转规则
  212 + */
  213 + private void executeDataRule(IotDeviceMessage message, IotDataRuleDO rule) {
  214 + rule.getSinkIds().forEach(sinkId -> {
  215 + try {
  216 + // 获取数据目的配置
  217 + IotDataSinkDO dataSink = dataSinkService.getDataSinkFromCache(sinkId);
  218 + if (dataSink == null) {
  219 + log.error("[executeDataRule][规则({}) 对应的数据目的({}) 不存在]", rule.getId(), sinkId);
  220 + return;
  221 + }
  222 + if (CommonStatusEnum.isDisable(dataSink.getStatus())) {
  223 + log.info("[executeDataRule][规则({}) 对应的数据目的({}) 状态为禁用]", rule.getId(), sinkId);
  224 + return;
  225 + }
  226 +
  227 + // 执行数据桥接操作
  228 + executeDataRuleAction(message, dataSink);
  229 + } catch (Exception e) {
  230 + log.error("[executeDataRule][规则({}) 数据目的({}) 执行异常]", rule.getId(), sinkId, e);
  231 + }
  232 + });
  233 + }
  234 +
  235 + /**
  236 + * 执行数据流转操作
  237 + *
  238 + * @param message 设备消息
  239 + * @param dataSink 数据目的
  240 + */
  241 + private void executeDataRuleAction(IotDeviceMessage message, IotDataSinkDO dataSink) {
  242 + dataRuleActions.forEach(action -> {
  243 + if (ObjUtil.notEqual(action.getType(), dataSink.getType())) {
  244 + return;
  245 + }
  246 + try {
  247 + action.execute(message, dataSink);
  248 + log.info("[executeDataRuleAction][消息({}) 数据目的({}) 执行成功]", message.getId(), dataSink.getId());
  249 + } catch (Exception e) {
  250 + log.error("[executeDataRuleAction][消息({}) 数据目的({}) 执行异常]", message.getId(), dataSink.getId(), e);
  251 + }
  252 + });
  253 + }
  254 +
  255 + private IotDataRuleServiceImpl getSelf() {
  256 + return SpringUtils.getBean(IotDataRuleServiceImpl.class);
  257 + }
  258 +
147 } 259 }
148 \ No newline at end of file 260 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataSinkService.java
@@ -47,6 +47,14 @@ public interface IotDataSinkService { @@ -47,6 +47,14 @@ public interface IotDataSinkService {
47 IotDataSinkDO getDataSink(Long id); 47 IotDataSinkDO getDataSink(Long id);
48 48
49 /** 49 /**
  50 + * 从缓存中获得数据流转目的
  51 + *
  52 + * @param id 编号
  53 + * @return 数据流转目的
  54 + */
  55 + IotDataSinkDO getDataSinkFromCache(Long id);
  56 +
  57 + /**
50 * 获得数据流转目的分页 58 * 获得数据流转目的分页
51 * 59 *
52 * @param pageReqVO 分页查询 60 * @param pageReqVO 分页查询
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataSinkServiceImpl.java
@@ -7,7 +7,9 @@ import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.sink.IotDataSin @@ -7,7 +7,9 @@ import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.sink.IotDataSin
7 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.sink.IotDataSinkSaveReqVO; 7 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.sink.IotDataSinkSaveReqVO;
8 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataSinkDO; 8 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataSinkDO;
9 import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotDataSinkMapper; 9 import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotDataSinkMapper;
  10 +import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants;
10 import jakarta.annotation.Resource; 11 import jakarta.annotation.Resource;
  12 +import org.springframework.cache.annotation.Cacheable;
11 import org.springframework.context.annotation.Lazy; 13 import org.springframework.context.annotation.Lazy;
12 import org.springframework.stereotype.Service; 14 import org.springframework.stereotype.Service;
13 import org.springframework.validation.annotation.Validated; 15 import org.springframework.validation.annotation.Validated;
@@ -16,8 +18,8 @@ import java.util.Collection; @@ -16,8 +18,8 @@ import java.util.Collection;
16 import java.util.List; 18 import java.util.List;
17 19
18 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 20 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
19 -import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DATA_SINK_NOT_EXISTS;  
20 import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DATA_SINK_DELETE_FAIL_USED_BY_RULE; 21 import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DATA_SINK_DELETE_FAIL_USED_BY_RULE;
  22 +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DATA_SINK_NOT_EXISTS;
21 23
22 /** 24 /**
23 * IoT 数据流转目的 Service 实现类 25 * IoT 数据流转目的 Service 实现类
@@ -56,7 +58,7 @@ public class IotDataSinkServiceImpl implements IotDataSinkService { @@ -56,7 +58,7 @@ public class IotDataSinkServiceImpl implements IotDataSinkService {
56 // 校验存在 58 // 校验存在
57 validateDataBridgeExists(id); 59 validateDataBridgeExists(id);
58 // 校验是否被数据流转规则使用 60 // 校验是否被数据流转规则使用
59 - if (CollUtil.isNotEmpty(dataRuleService.getDataRuleBySinkId(id))) { 61 + if (CollUtil.isNotEmpty(dataRuleService.getDataRuleListBySinkId(id))) {
60 throw exception(DATA_SINK_DELETE_FAIL_USED_BY_RULE); 62 throw exception(DATA_SINK_DELETE_FAIL_USED_BY_RULE);
61 } 63 }
62 // 删除 64 // 删除
@@ -75,6 +77,12 @@ public class IotDataSinkServiceImpl implements IotDataSinkService { @@ -75,6 +77,12 @@ public class IotDataSinkServiceImpl implements IotDataSinkService {
75 } 77 }
76 78
77 @Override 79 @Override
  80 + @Cacheable(value = RedisKeyConstants.DATA_SINK, key = "#id")
  81 + public IotDataSinkDO getDataSinkFromCache(Long id) {
  82 + return dataSinkMapper.selectById(id);
  83 + }
  84 +
  85 + @Override
78 public PageResult<IotDataSinkDO> getDataSinkPage(IotDataSinkPageReqVO pageReqVO) { 86 public PageResult<IotDataSinkDO> getDataSinkPage(IotDataSinkPageReqVO pageReqVO) {
79 return dataSinkMapper.selectPage(pageReqVO); 87 return dataSinkMapper.selectPage(pageReqVO);
80 } 88 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotRuleSceneDataBridgeAction.java deleted
1 -package cn.iocoder.yudao.module.iot.service.rule.data;  
2 -  
3 -import cn.hutool.core.lang.Assert;  
4 -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;  
5 -import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;  
6 -import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataSinkDO;  
7 -import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;  
8 -import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;  
9 -import cn.iocoder.yudao.module.iot.service.rule.data.action.IotDataBridgeExecute;  
10 -import cn.iocoder.yudao.module.iot.service.rule.scene.action.IotRuleSceneAction;  
11 -import jakarta.annotation.Resource;  
12 -import lombok.extern.slf4j.Slf4j;  
13 -import org.springframework.stereotype.Component;  
14 -  
15 -import java.util.List;  
16 -  
17 -/**  
18 - * IoT 数据流转目的的 {@link IotRuleSceneAction} 实现类  
19 - *  
20 - * @author 芋道源码  
21 - */  
22 -@Deprecated  
23 -@Component  
24 -@Slf4j  
25 -public class IotRuleSceneDataBridgeAction implements IotRuleSceneAction {  
26 -  
27 - @Resource  
28 - private IotDataSinkService dataBridgeService;  
29 - @Resource  
30 - private List<IotDataBridgeExecute<?>> dataBridgeExecutes;  
31 -  
32 - @Override  
33 - public void execute(IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) throws Exception {  
34 - // 1.1 如果消息为空,直接返回  
35 - if (message == null) {  
36 - return;  
37 - }  
38 - // 1.2 获得数据流转目的  
39 - Assert.notNull(config.getDataBridgeId(), "数据流转目的编号不能为空");  
40 - IotDataSinkDO dataBridge = dataBridgeService.getDataSink(config.getDataBridgeId());  
41 - if (dataBridge == null || dataBridge.getConfig() == null) {  
42 - log.error("[execute][message({}) config({}) 对应的数据流转目的不存在]", message, config);  
43 - return;  
44 - }  
45 - if (CommonStatusEnum.isDisable(dataBridge.getStatus())) {  
46 - log.info("[execute][message({}) config({}) 对应的数据流转目的({}) 状态为禁用]", message, config, dataBridge);  
47 - return;  
48 - }  
49 -  
50 - // 2. 执行数据桥接操作  
51 - for (IotDataBridgeExecute<?> execute : dataBridgeExecutes) {  
52 - execute.execute(message, dataBridge);  
53 - }  
54 - }  
55 -  
56 - @Override  
57 - public IotRuleSceneActionTypeEnum getType() {  
58 - return IotRuleSceneActionTypeEnum.DATA_BRIDGE;  
59 - }  
60 -  
61 -}  
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/action/IotDataBridgeExecute.java renamed to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/action/IotDataRuleAction.java
@@ -4,11 +4,11 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; @@ -4,11 +4,11 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
4 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataSinkDO; 4 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataSinkDO;
5 5
6 /** 6 /**
7 - * IoT 数据流转目的的执行器 execute 接口 7 + * IoT 数据流转目的的执行器 action 接口
8 * 8 *
9 * @author HUIHUI 9 * @author HUIHUI
10 */ 10 */
11 -public interface IotDataBridgeExecute<Config> { 11 +public interface IotDataRuleAction {
12 12
13 /** 13 /**
14 * 获取数据流转目的类型 14 * 获取数据流转目的类型
@@ -21,25 +21,8 @@ public interface IotDataBridgeExecute&lt;Config&gt; { @@ -21,25 +21,8 @@ public interface IotDataBridgeExecute&lt;Config&gt; {
21 * 执行数据流转目的操作 21 * 执行数据流转目的操作
22 * 22 *
23 * @param message 设备消息 23 * @param message 设备消息
24 - * @param dataBridge 数据流转目的 24 + * @param dataSink 数据流转目的
25 */ 25 */
26 - @SuppressWarnings({"unchecked"})  
27 - default void execute(IotDeviceMessage message, IotDataSinkDO dataBridge) throws Exception {  
28 - // 1.1 校验数据流转目的类型  
29 - if (!getType().equals(dataBridge.getType())) {  
30 - return;  
31 - }  
32 -  
33 - // 1.2 执行对应的数据流转目的发送消息  
34 - execute0(message, (Config) dataBridge.getConfig());  
35 - }  
36 -  
37 - /**  
38 - * 【真正】执行数据流转目的操作  
39 - *  
40 - * @param message 设备消息  
41 - * @param config 桥梁配置  
42 - */  
43 - void execute0(IotDeviceMessage message, Config config) throws Exception; 26 + void execute(IotDeviceMessage message, IotDataSinkDO dataSink);
44 27
45 } 28 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/action/AbstractCacheableDataBridgeExecute.java renamed to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/action/IotDataRuleCacheableAction.java
1 package cn.iocoder.yudao.module.iot.service.rule.data.action; 1 package cn.iocoder.yudao.module.iot.service.rule.data.action;
2 2
  3 +import cn.hutool.core.lang.Assert;
3 import cn.hutool.core.util.ObjUtil; 4 import cn.hutool.core.util.ObjUtil;
4 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; 5 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
5 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataSinkDO; 6 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataSinkDO;
@@ -17,14 +18,14 @@ import java.time.Duration; @@ -17,14 +18,14 @@ import java.time.Duration;
17 // TODO @芋艿:websocket 18 // TODO @芋艿:websocket
18 19
19 /** 20 /**
20 - * 带缓存功能的数据流转目的执行器抽象类 21 + * 可缓存的 {@link IotDataRuleAction} 抽象实现
21 * 22 *
22 * 该类提供了一个通用的缓存机制,用于管理各类数据桥接的生产者(Producer)实例。 23 * 该类提供了一个通用的缓存机制,用于管理各类数据桥接的生产者(Producer)实例。
23 * 24 *
24 * 主要特点: 25 * 主要特点:
25 * - 基于Guava Cache实现高效的生产者实例缓存管理 26 * - 基于Guava Cache实现高效的生产者实例缓存管理
26 * - 自动处理生产者的生命周期(创建、获取、关闭) 27 * - 自动处理生产者的生命周期(创建、获取、关闭)
27 - * - 支持30分钟未访问自动过期清理机制 28 + * - 支持 30 分钟未访问自动过期清理机制
28 * - 异常处理与日志记录,便于问题排查 29 * - 异常处理与日志记录,便于问题排查
29 * 30 *
30 * 子类需要实现: 31 * 子类需要实现:
@@ -36,7 +37,7 @@ import java.time.Duration; @@ -36,7 +37,7 @@ import java.time.Duration;
36 * @author HUIHUI 37 * @author HUIHUI
37 */ 38 */
38 @Slf4j 39 @Slf4j
39 -public abstract class AbstractCacheableDataBridgeExecute<Config, Producer> implements IotDataBridgeExecute<Config> { 40 +public abstract class IotDataRuleCacheableAction<Config, Producer> implements IotDataRuleAction {
40 41
41 /** 42 /**
42 * Producer 缓存 43 * Producer 缓存
@@ -45,10 +46,6 @@ public abstract class AbstractCacheableDataBridgeExecute&lt;Config, Producer&gt; imple @@ -45,10 +46,6 @@ public abstract class AbstractCacheableDataBridgeExecute&lt;Config, Producer&gt; imple
45 .expireAfterAccess(Duration.ofMinutes(30)) // 30 分钟未访问就提前过期 46 .expireAfterAccess(Duration.ofMinutes(30)) // 30 分钟未访问就提前过期
46 .removalListener((RemovalListener<Config, Producer>) notification -> { 47 .removalListener((RemovalListener<Config, Producer>) notification -> {
47 Producer producer = notification.getValue(); 48 Producer producer = notification.getValue();
48 - if (producer == null) {  
49 - return;  
50 - }  
51 -  
52 try { 49 try {
53 closeProducer(producer); 50 closeProducer(producer);
54 log.info("[PRODUCER_CACHE][配置({}) 对应的 producer 已关闭]", notification.getKey()); 51 log.info("[PRODUCER_CACHE][配置({}) 对应的 producer 已关闭]", notification.getKey());
@@ -100,15 +97,21 @@ public abstract class AbstractCacheableDataBridgeExecute&lt;Config, Producer&gt; imple @@ -100,15 +97,21 @@ public abstract class AbstractCacheableDataBridgeExecute&lt;Config, Producer&gt; imple
100 97
101 @Override 98 @Override
102 @SuppressWarnings({"unchecked"}) 99 @SuppressWarnings({"unchecked"})
103 - public void execute(IotDeviceMessage message, IotDataSinkDO dataBridge) {  
104 - if (ObjUtil.notEqual(dataBridge.getType(), getType())) {  
105 - return;  
106 - } 100 + public void execute(IotDeviceMessage message, IotDataSinkDO dataSink) {
  101 + Assert.isTrue(ObjUtil.equal(dataSink.getType(), getType()), "类型({})不匹配", dataSink.getType());
107 try { 102 try {
108 - execute0(message, (Config) dataBridge.getConfig()); 103 + execute(message, (Config) dataSink.getConfig());
109 } catch (Exception e) { 104 } catch (Exception e) {
110 - log.error("[execute][桥梁配置 config({}) 对应的 message({}) 发送异常]", dataBridge.getConfig(), message, e); 105 + log.error("[execute][桥梁配置 config({}) 对应的 message({}) 发送异常]", dataSink.getConfig(), message, e);
111 } 106 }
112 } 107 }
113 108
  109 + /**
  110 + * 执行数据流转
  111 + *
  112 + * @param message 设备消息
  113 + * @param config 配置信息
  114 + */
  115 + protected abstract void execute(IotDeviceMessage message, Config config) throws Exception;
  116 +
114 } 117 }
115 \ No newline at end of file 118 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/action/IotHttpDataBridgeExecute.java renamed to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/action/IotHttpDataSinkAction.java
1 package cn.iocoder.yudao.module.iot.service.rule.data.action; 1 package cn.iocoder.yudao.module.iot.service.rule.data.action;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.lang.Assert;
4 import cn.iocoder.yudao.framework.common.util.http.HttpUtils; 5 import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
5 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 6 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
6 -import cn.iocoder.yudao.module.iot.dal.dataobject.rule.config.IotDataSinkHttpConfig;  
7 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; 7 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
  8 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataSinkDO;
  9 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.config.IotDataSinkHttpConfig;
8 import cn.iocoder.yudao.module.iot.enums.rule.IotDataSinkTypeEnum; 10 import cn.iocoder.yudao.module.iot.enums.rule.IotDataSinkTypeEnum;
9 import jakarta.annotation.Resource; 11 import jakarta.annotation.Resource;
10 import lombok.extern.slf4j.Slf4j; 12 import lombok.extern.slf4j.Slf4j;
@@ -17,13 +19,13 @@ import java.util.HashMap; @@ -17,13 +19,13 @@ import java.util.HashMap;
17 import java.util.Map; 19 import java.util.Map;
18 20
19 /** 21 /**
20 - * Http 的 {@link IotDataBridgeExecute} 实现类 22 + * HTTP 的 {@link IotDataRuleAction} 实现类
21 * 23 *
22 * @author HUIHUI 24 * @author HUIHUI
23 */ 25 */
24 @Component 26 @Component
25 @Slf4j 27 @Slf4j
26 -public class IotHttpDataBridgeExecute implements IotDataBridgeExecute<IotDataSinkHttpConfig> { 28 +public class IotHttpDataSinkAction implements IotDataRuleAction {
27 29
28 @Resource 30 @Resource
29 private RestTemplate restTemplate; 31 private RestTemplate restTemplate;
@@ -34,8 +36,9 @@ public class IotHttpDataBridgeExecute implements IotDataBridgeExecute&lt;IotDataSin @@ -34,8 +36,9 @@ public class IotHttpDataBridgeExecute implements IotDataBridgeExecute&lt;IotDataSin
34 } 36 }
35 37
36 @Override 38 @Override
37 - @SuppressWarnings({"unchecked", "deprecation"})  
38 - public void execute0(IotDeviceMessage message, IotDataSinkHttpConfig config) { 39 + public void execute(IotDeviceMessage message, IotDataSinkDO dataSink) {
  40 + IotDataSinkHttpConfig config = (IotDataSinkHttpConfig) dataSink.getConfig();
  41 + Assert.notNull(config, "配置({})不能为空", dataSink.getId());
39 String url = null; 42 String url = null;
40 HttpMethod method = HttpMethod.valueOf(config.getMethod().toUpperCase()); 43 HttpMethod method = HttpMethod.valueOf(config.getMethod().toUpperCase());
41 HttpEntity<String> requestEntity = null; 44 HttpEntity<String> requestEntity = null;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/action/IotKafkaMQDataBridgeExecute.java renamed to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/action/IotKafkaDataRuleAction.java
@@ -17,17 +17,17 @@ import java.util.Map; @@ -17,17 +17,17 @@ import java.util.Map;
17 import java.util.concurrent.TimeUnit; 17 import java.util.concurrent.TimeUnit;
18 18
19 /** 19 /**
20 - * Kafka 的 {@link IotDataBridgeExecute} 实现类 20 + * Kafka 的 {@link IotDataRuleAction} 实现类
21 * 21 *
22 * @author HUIHUI 22 * @author HUIHUI
23 */ 23 */
24 @ConditionalOnClass(name = "org.springframework.kafka.core.KafkaTemplate") 24 @ConditionalOnClass(name = "org.springframework.kafka.core.KafkaTemplate")
25 @Component 25 @Component
26 @Slf4j 26 @Slf4j
27 -public class IotKafkaMQDataBridgeExecute extends  
28 - AbstractCacheableDataBridgeExecute<IotDataSinkKafkaConfig, KafkaTemplate<String, String>> { 27 +public class IotKafkaDataRuleAction extends
  28 + IotDataRuleCacheableAction<IotDataSinkKafkaConfig, KafkaTemplate<String, String>> {
29 29
30 - private static final Duration SEND_TIMEOUT = Duration.ofMillis(10000); // 10 秒超时时间 30 + private static final Duration SEND_TIMEOUT = Duration.ofSeconds(10);
31 31
32 @Override 32 @Override
33 public Integer getType() { 33 public Integer getType() {
@@ -35,7 +35,7 @@ public class IotKafkaMQDataBridgeExecute extends @@ -35,7 +35,7 @@ public class IotKafkaMQDataBridgeExecute extends
35 } 35 }
36 36
37 @Override 37 @Override
38 - public void execute0(IotDeviceMessage message, IotDataSinkKafkaConfig config) throws Exception { 38 + public void execute(IotDeviceMessage message, IotDataSinkKafkaConfig config) throws Exception {
39 // 1. 获取或创建 KafkaTemplate 39 // 1. 获取或创建 KafkaTemplate
40 KafkaTemplate<String, String> kafkaTemplate = getProducer(config); 40 KafkaTemplate<String, String> kafkaTemplate = getProducer(config);
41 41
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/action/IotRabbitMQDataBridgeExecute.java renamed to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/action/IotRabbitMQDataRuleAction.java
@@ -13,16 +13,15 @@ import org.springframework.stereotype.Component; @@ -13,16 +13,15 @@ import org.springframework.stereotype.Component;
13 import java.nio.charset.StandardCharsets; 13 import java.nio.charset.StandardCharsets;
14 14
15 /** 15 /**
16 - * RabbitMQ 的 {@link IotDataBridgeExecute} 实现类 16 + * RabbitMQ 的 {@link IotDataRuleAction} 实现类
17 * 17 *
18 * @author HUIHUI 18 * @author HUIHUI
19 */ 19 */
20 @ConditionalOnClass(name = "com.rabbitmq.client.Channel") 20 @ConditionalOnClass(name = "com.rabbitmq.client.Channel")
21 @Component 21 @Component
22 @Slf4j 22 @Slf4j
23 -public class IotRabbitMQDataBridgeExecute extends  
24 - AbstractCacheableDataBridgeExecute<IotDataSinkRabbitMQConfig, Channel> {  
25 - 23 +public class IotRabbitMQDataRuleAction extends
  24 + IotDataRuleCacheableAction<IotDataSinkRabbitMQConfig, Channel> {
26 25
27 @Override 26 @Override
28 public Integer getType() { 27 public Integer getType() {
@@ -30,16 +29,15 @@ public class IotRabbitMQDataBridgeExecute extends @@ -30,16 +29,15 @@ public class IotRabbitMQDataBridgeExecute extends
30 } 29 }
31 30
32 @Override 31 @Override
33 - public void execute0(IotDeviceMessage message, IotDataSinkRabbitMQConfig config) throws Exception {  
34 - // 1. 获取或创建 Channel 32 + public void execute(IotDeviceMessage message, IotDataSinkRabbitMQConfig config) throws Exception {
  33 + // 1.1 获取或创建 Channel
35 Channel channel = getProducer(config); 34 Channel channel = getProducer(config);
36 -  
37 - // 2.1 声明交换机、队列和绑定关系 35 + // 1.2 声明交换机、队列和绑定关系
38 channel.exchangeDeclare(config.getExchange(), "direct", true); 36 channel.exchangeDeclare(config.getExchange(), "direct", true);
39 channel.queueDeclare(config.getQueue(), true, false, false, null); 37 channel.queueDeclare(config.getQueue(), true, false, false, null);
40 channel.queueBind(config.getQueue(), config.getExchange(), config.getRoutingKey()); 38 channel.queueBind(config.getQueue(), config.getExchange(), config.getRoutingKey());
41 39
42 - // 2.2 发送消息 40 + // 2. 发送消息
43 channel.basicPublish(config.getExchange(), config.getRoutingKey(), null, 41 channel.basicPublish(config.getExchange(), config.getRoutingKey(), null,
44 message.toString().getBytes(StandardCharsets.UTF_8)); 42 message.toString().getBytes(StandardCharsets.UTF_8));
45 log.info("[executeRabbitMQ][message({}) config({}) 发送成功]", message, config); 43 log.info("[executeRabbitMQ][message({}) config({}) 发送成功]", message, config);
@@ -55,10 +53,8 @@ public class IotRabbitMQDataBridgeExecute extends @@ -55,10 +53,8 @@ public class IotRabbitMQDataBridgeExecute extends
55 factory.setVirtualHost(config.getVirtualHost()); 53 factory.setVirtualHost(config.getVirtualHost());
56 factory.setUsername(config.getUsername()); 54 factory.setUsername(config.getUsername());
57 factory.setPassword(config.getPassword()); 55 factory.setPassword(config.getPassword());
58 -  
59 // 2. 创建连接 56 // 2. 创建连接
60 Connection connection = factory.newConnection(); 57 Connection connection = factory.newConnection();
61 -  
62 // 3. 创建信道 58 // 3. 创建信道
63 return connection.createChannel(); 59 return connection.createChannel();
64 } 60 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/action/IotRedisStreamDataBridgeExecute.java renamed to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/action/IotRedisStreamRuleAction.java
@@ -18,14 +18,14 @@ import org.springframework.data.redis.serializer.RedisSerializer; @@ -18,14 +18,14 @@ import org.springframework.data.redis.serializer.RedisSerializer;
18 import org.springframework.stereotype.Component; 18 import org.springframework.stereotype.Component;
19 19
20 /** 20 /**
21 - * Redis Stream 的 {@link IotDataBridgeExecute} 实现类 21 + * Redis Stream 的 {@link IotDataRuleAction} 实现类
22 * 22 *
23 * @author HUIHUI 23 * @author HUIHUI
24 */ 24 */
25 @Component 25 @Component
26 @Slf4j 26 @Slf4j
27 -public class IotRedisStreamDataBridgeExecute extends  
28 - AbstractCacheableDataBridgeExecute<IotDataSinkRedisStreamConfig, RedisTemplate<String, Object>> { 27 +public class IotRedisStreamRuleAction extends
  28 + IotDataRuleCacheableAction<IotDataSinkRedisStreamConfig, RedisTemplate<String, Object>> {
29 29
30 @Override 30 @Override
31 public Integer getType() { 31 public Integer getType() {
@@ -33,7 +33,7 @@ public class IotRedisStreamDataBridgeExecute extends @@ -33,7 +33,7 @@ public class IotRedisStreamDataBridgeExecute extends
33 } 33 }
34 34
35 @Override 35 @Override
36 - public void execute0(IotDeviceMessage message, IotDataSinkRedisStreamConfig config) throws Exception { 36 + public void execute(IotDeviceMessage message, IotDataSinkRedisStreamConfig config) throws Exception {
37 // 1. 获取 RedisTemplate 37 // 1. 获取 RedisTemplate
38 RedisTemplate<String, Object> redisTemplate = getProducer(config); 38 RedisTemplate<String, Object> redisTemplate = getProducer(config);
39 39
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/action/IotRocketMQDataBridgeExecute.java renamed to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/action/IotRocketMQDataRuleAction.java
@@ -13,15 +13,15 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; @@ -13,15 +13,15 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
13 import org.springframework.stereotype.Component; 13 import org.springframework.stereotype.Component;
14 14
15 /** 15 /**
16 - * RocketMQ 的 {@link IotDataBridgeExecute} 实现类 16 + * RocketMQ 的 {@link IotDataRuleAction} 实现类
17 * 17 *
18 * @author HUIHUI 18 * @author HUIHUI
19 */ 19 */
20 @ConditionalOnClass(name = "org.apache.rocketmq.client.producer.DefaultMQProducer") 20 @ConditionalOnClass(name = "org.apache.rocketmq.client.producer.DefaultMQProducer")
21 @Component 21 @Component
22 @Slf4j 22 @Slf4j
23 -public class IotRocketMQDataBridgeExecute extends  
24 - AbstractCacheableDataBridgeExecute<IotDataSinkRocketMQConfig, DefaultMQProducer> { 23 +public class IotRocketMQDataRuleAction extends
  24 + IotDataRuleCacheableAction<IotDataSinkRocketMQConfig, DefaultMQProducer> {
25 25
26 @Override 26 @Override
27 public Integer getType() { 27 public Integer getType() {
@@ -29,7 +29,7 @@ public class IotRocketMQDataBridgeExecute extends @@ -29,7 +29,7 @@ public class IotRocketMQDataBridgeExecute extends
29 } 29 }
30 30
31 @Override 31 @Override
32 - public void execute0(IotDeviceMessage message, IotDataSinkRocketMQConfig config) throws Exception { 32 + public void execute(IotDeviceMessage message, IotDataSinkRocketMQConfig config) throws Exception {
33 // 1. 获取或创建 Producer 33 // 1. 获取或创建 Producer
34 DefaultMQProducer producer = getProducer(config); 34 DefaultMQProducer producer = getProducer(config);
35 35
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/IotRuleSceneServiceImpl.java
@@ -214,11 +214,6 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -214,11 +214,6 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
214 .build()); 214 .build());
215 action01.setDeviceControl(actionDeviceControl01); 215 action01.setDeviceControl(actionDeviceControl01);
216 // ruleScene01.getActions().add(action01); // TODO 芋艿:先不测试了 216 // ruleScene01.getActions().add(action01); // TODO 芋艿:先不测试了
217 - // 数据桥接(http)  
218 - IotRuleSceneDO.ActionConfig action02 = new IotRuleSceneDO.ActionConfig();  
219 - action02.setType(IotRuleSceneActionTypeEnum.DATA_BRIDGE.getType());  
220 - action02.setDataBridgeId(1L);  
221 - ruleScene01.getActions().add(action02);  
222 return ListUtil.toList(ruleScene01); 217 return ListUtil.toList(ruleScene01);
223 } 218 }
224 219
yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/rule/action/databridge/IotDataBridgeExecuteTest.java
@@ -23,7 +23,7 @@ import static org.mockito.ArgumentMatchers.anyString; @@ -23,7 +23,7 @@ import static org.mockito.ArgumentMatchers.anyString;
23 import static org.mockito.Mockito.when; 23 import static org.mockito.Mockito.when;
24 24
25 /** 25 /**
26 - * {@link IotDataBridgeExecute} 实现类的单元测试 26 + * {@link IotDataRuleAction} 实现类的单元测试
27 * 27 *
28 * @author HUIHUI 28 * @author HUIHUI
29 */ 29 */
@@ -37,7 +37,7 @@ public class IotDataBridgeExecuteTest extends BaseMockitoUnitTest { @@ -37,7 +37,7 @@ public class IotDataBridgeExecuteTest extends BaseMockitoUnitTest {
37 private RestTemplate restTemplate; 37 private RestTemplate restTemplate;
38 38
39 @InjectMocks 39 @InjectMocks
40 - private IotHttpDataBridgeExecute httpDataBridgeExecute; 40 + private IotHttpDataSinkAction httpDataBridgeExecute;
41 41
42 @BeforeEach 42 @BeforeEach
43 public void setUp() { 43 public void setUp() {
@@ -51,7 +51,7 @@ public class IotDataBridgeExecuteTest extends BaseMockitoUnitTest { @@ -51,7 +51,7 @@ public class IotDataBridgeExecuteTest extends BaseMockitoUnitTest {
51 @Test 51 @Test
52 public void testKafkaMQDataBridge() throws Exception { 52 public void testKafkaMQDataBridge() throws Exception {
53 // 1. 创建执行器实例 53 // 1. 创建执行器实例
54 - IotKafkaMQDataBridgeExecute action = new IotKafkaMQDataBridgeExecute(); 54 + IotKafkaDataRuleAction action = new IotKafkaDataRuleAction();
55 55
56 // 2. 创建配置 56 // 2. 创建配置
57 IotDataSinkKafkaConfig config = new IotDataSinkKafkaConfig() 57 IotDataSinkKafkaConfig config = new IotDataSinkKafkaConfig()
@@ -68,7 +68,7 @@ public class IotDataBridgeExecuteTest extends BaseMockitoUnitTest { @@ -68,7 +68,7 @@ public class IotDataBridgeExecuteTest extends BaseMockitoUnitTest {
68 @Test 68 @Test
69 public void testRabbitMQDataBridge() throws Exception { 69 public void testRabbitMQDataBridge() throws Exception {
70 // 1. 创建执行器实例 70 // 1. 创建执行器实例
71 - IotRabbitMQDataBridgeExecute action = new IotRabbitMQDataBridgeExecute(); 71 + IotRabbitMQDataRuleAction action = new IotRabbitMQDataRuleAction();
72 72
73 // 2. 创建配置 73 // 2. 创建配置
74 IotDataSinkRabbitMQConfig config = new IotDataSinkRabbitMQConfig() 74 IotDataSinkRabbitMQConfig config = new IotDataSinkRabbitMQConfig()
@@ -88,7 +88,7 @@ public class IotDataBridgeExecuteTest extends BaseMockitoUnitTest { @@ -88,7 +88,7 @@ public class IotDataBridgeExecuteTest extends BaseMockitoUnitTest {
88 @Test 88 @Test
89 public void testRedisStreamDataBridge() throws Exception { 89 public void testRedisStreamDataBridge() throws Exception {
90 // 1. 创建执行器实例 90 // 1. 创建执行器实例
91 - IotRedisStreamDataBridgeExecute action = new IotRedisStreamDataBridgeExecute(); 91 + IotRedisStreamRuleAction action = new IotRedisStreamRuleAction();
92 92
93 // 2. 创建配置 93 // 2. 创建配置
94 IotDataSinkRedisStreamConfig config = new IotDataSinkRedisStreamConfig() 94 IotDataSinkRedisStreamConfig config = new IotDataSinkRedisStreamConfig()
@@ -105,7 +105,7 @@ public class IotDataBridgeExecuteTest extends BaseMockitoUnitTest { @@ -105,7 +105,7 @@ public class IotDataBridgeExecuteTest extends BaseMockitoUnitTest {
105 @Test 105 @Test
106 public void testRocketMQDataBridge() throws Exception { 106 public void testRocketMQDataBridge() throws Exception {
107 // 1. 创建执行器实例 107 // 1. 创建执行器实例
108 - IotRocketMQDataBridgeExecute action = new IotRocketMQDataBridgeExecute(); 108 + IotRocketMQDataRuleAction action = new IotRocketMQDataRuleAction();
109 109
110 // 2. 创建配置 110 // 2. 创建配置
111 IotDataSinkRocketMQConfig config = new IotDataSinkRocketMQConfig() 111 IotDataSinkRocketMQConfig config = new IotDataSinkRocketMQConfig()
@@ -142,7 +142,7 @@ public class IotDataBridgeExecuteTest extends BaseMockitoUnitTest { @@ -142,7 +142,7 @@ public class IotDataBridgeExecuteTest extends BaseMockitoUnitTest {
142 * @param type MQ 类型 142 * @param type MQ 类型
143 * @throws Exception 如果执行过程中发生异常 143 * @throws Exception 如果执行过程中发生异常
144 */ 144 */
145 - private void executeAndVerifyCache(IotDataBridgeExecute<?> action, IotAbstractDataSinkConfig config, String type) 145 + private void executeAndVerifyCache(IotDataRuleAction<?> action, IotAbstractDataSinkConfig config, String type)
146 throws Exception { 146 throws Exception {
147 log.info("[test{}DataBridge][第一次执行,应该会创建新的 producer]", type); 147 log.info("[test{}DataBridge][第一次执行,应该会创建新的 producer]", type);
148 action.execute(message, new IotDataSinkDO().setType(action.getType()).setConfig(config)); 148 action.execute(message, new IotDataSinkDO().setType(action.getType()).setConfig(config));