Commit eb7df7157c11c788bf40dd3feb88dceb71b636da

Authored by 芋道源码
Committed by Gitee
2 parents bed73351 895b6c29

!1398 perf:【IoT 物联网】场景联动代码优化

Merge pull request !1398 from puhui999/feature/iot
Showing 18 changed files with 836 additions and 141 deletions
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/IotRuleSceneController.java
@@ -8,13 +8,12 @@ import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePa @@ -8,13 +8,12 @@ import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePa
8 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneRespVO; 8 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneRespVO;
9 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO; 9 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO;
10 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneUpdateStatusReqVO; 10 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneUpdateStatusReqVO;
11 -import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; 11 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
12 import cn.iocoder.yudao.module.iot.service.rule.scene.IotRuleSceneService; 12 import cn.iocoder.yudao.module.iot.service.rule.scene.IotRuleSceneService;
13 import io.swagger.v3.oas.annotations.Operation; 13 import io.swagger.v3.oas.annotations.Operation;
14 import io.swagger.v3.oas.annotations.Parameter; 14 import io.swagger.v3.oas.annotations.Parameter;
15 import io.swagger.v3.oas.annotations.tags.Tag; 15 import io.swagger.v3.oas.annotations.tags.Tag;
16 import jakarta.annotation.Resource; 16 import jakarta.annotation.Resource;
17 -import jakarta.annotation.security.PermitAll;  
18 import jakarta.validation.Valid; 17 import jakarta.validation.Valid;
19 import org.springframework.security.access.prepost.PreAuthorize; 18 import org.springframework.security.access.prepost.PreAuthorize;
20 import org.springframework.validation.annotation.Validated; 19 import org.springframework.validation.annotation.Validated;
@@ -71,7 +70,7 @@ public class IotRuleSceneController { @@ -71,7 +70,7 @@ public class IotRuleSceneController {
71 @Parameter(name = "id", description = "编号", required = true, example = "1024") 70 @Parameter(name = "id", description = "编号", required = true, example = "1024")
72 @PreAuthorize("@ss.hasPermission('iot:rule-scene:query')") 71 @PreAuthorize("@ss.hasPermission('iot:rule-scene:query')")
73 public CommonResult<IotRuleSceneRespVO> getRuleScene(@RequestParam("id") Long id) { 72 public CommonResult<IotRuleSceneRespVO> getRuleScene(@RequestParam("id") Long id) {
74 - IotRuleSceneDO ruleScene = ruleSceneService.getRuleScene(id); 73 + IotSceneRuleDO ruleScene = ruleSceneService.getRuleScene(id);
75 return success(BeanUtils.toBean(ruleScene, IotRuleSceneRespVO.class)); 74 return success(BeanUtils.toBean(ruleScene, IotRuleSceneRespVO.class));
76 } 75 }
77 76
@@ -79,22 +78,16 @@ public class IotRuleSceneController { @@ -79,22 +78,16 @@ public class IotRuleSceneController {
79 @Operation(summary = "获得场景联动分页") 78 @Operation(summary = "获得场景联动分页")
80 @PreAuthorize("@ss.hasPermission('iot:rule-scene:query')") 79 @PreAuthorize("@ss.hasPermission('iot:rule-scene:query')")
81 public CommonResult<PageResult<IotRuleSceneRespVO>> getRuleScenePage(@Valid IotRuleScenePageReqVO pageReqVO) { 80 public CommonResult<PageResult<IotRuleSceneRespVO>> getRuleScenePage(@Valid IotRuleScenePageReqVO pageReqVO) {
82 - PageResult<IotRuleSceneDO> pageResult = ruleSceneService.getRuleScenePage(pageReqVO); 81 + PageResult<IotSceneRuleDO> pageResult = ruleSceneService.getRuleScenePage(pageReqVO);
83 return success(BeanUtils.toBean(pageResult, IotRuleSceneRespVO.class)); 82 return success(BeanUtils.toBean(pageResult, IotRuleSceneRespVO.class));
84 } 83 }
85 84
86 @GetMapping("/simple-list") 85 @GetMapping("/simple-list")
87 @Operation(summary = "获取场景联动的精简信息列表", description = "主要用于前端的下拉选项") 86 @Operation(summary = "获取场景联动的精简信息列表", description = "主要用于前端的下拉选项")
88 public CommonResult<List<IotRuleSceneRespVO>> getRuleSceneSimpleList() { 87 public CommonResult<List<IotRuleSceneRespVO>> getRuleSceneSimpleList() {
89 - List<IotRuleSceneDO> list = ruleSceneService.getRuleSceneListByStatus(CommonStatusEnum.ENABLE.getStatus()); 88 + List<IotSceneRuleDO> list = ruleSceneService.getRuleSceneListByStatus(CommonStatusEnum.ENABLE.getStatus());
90 return success(convertList(list, scene -> // 只返回 id、name 字段 89 return success(convertList(list, scene -> // 只返回 id、name 字段
91 new IotRuleSceneRespVO().setId(scene.getId()).setName(scene.getName()))); 90 new IotRuleSceneRespVO().setId(scene.getId()).setName(scene.getName())));
92 } 91 }
93 92
94 - @GetMapping("/test")  
95 - @PermitAll  
96 - public void test() {  
97 - ruleSceneService.test();  
98 - }  
99 -  
100 } 93 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleSceneRespVO.java
1 package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene; 1 package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene;
2 2
3 -import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; 3 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
4 import io.swagger.v3.oas.annotations.media.Schema; 4 import io.swagger.v3.oas.annotations.media.Schema;
5 import lombok.Data; 5 import lombok.Data;
6 6
@@ -24,10 +24,10 @@ public class IotRuleSceneRespVO { @@ -24,10 +24,10 @@ public class IotRuleSceneRespVO {
24 private Integer status; 24 private Integer status;
25 25
26 @Schema(description = "触发器数组", requiredMode = Schema.RequiredMode.REQUIRED) 26 @Schema(description = "触发器数组", requiredMode = Schema.RequiredMode.REQUIRED)
27 - private List<IotRuleSceneDO.Trigger> triggers; 27 + private List<IotSceneRuleDO.Trigger> triggers;
28 28
29 @Schema(description = "执行器数组", requiredMode = Schema.RequiredMode.REQUIRED) 29 @Schema(description = "执行器数组", requiredMode = Schema.RequiredMode.REQUIRED)
30 - private List<IotRuleSceneDO.Action> actions; 30 + private List<IotSceneRuleDO.Action> actions;
31 31
32 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) 32 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
33 private LocalDateTime createTime; 33 private LocalDateTime createTime;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/scene/IotRuleSceneSaveReqVO.java
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene; @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene;
2 2
3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 import cn.iocoder.yudao.framework.common.validation.InEnum; 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
5 -import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; 5 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
6 import io.swagger.v3.oas.annotations.media.Schema; 6 import io.swagger.v3.oas.annotations.media.Schema;
7 import jakarta.validation.constraints.NotEmpty; 7 import jakarta.validation.constraints.NotEmpty;
8 import jakarta.validation.constraints.NotNull; 8 import jakarta.validation.constraints.NotNull;
@@ -31,10 +31,10 @@ public class IotRuleSceneSaveReqVO { @@ -31,10 +31,10 @@ public class IotRuleSceneSaveReqVO {
31 31
32 @Schema(description = "触发器数组", requiredMode = Schema.RequiredMode.REQUIRED) 32 @Schema(description = "触发器数组", requiredMode = Schema.RequiredMode.REQUIRED)
33 @NotEmpty(message = "触发器数组不能为空") 33 @NotEmpty(message = "触发器数组不能为空")
34 - private List<IotRuleSceneDO.Trigger> triggers; 34 + private List<IotSceneRuleDO.Trigger> triggers;
35 35
36 @Schema(description = "执行器数组", requiredMode = Schema.RequiredMode.REQUIRED) 36 @Schema(description = "执行器数组", requiredMode = Schema.RequiredMode.REQUIRED)
37 @NotEmpty(message = "执行器数组不能为空") 37 @NotEmpty(message = "执行器数组不能为空")
38 - private List<IotRuleSceneDO.Action> actions; 38 + private List<IotSceneRuleDO.Action> actions;
39 39
40 } 40 }
41 \ No newline at end of file 41 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/alert/IotAlertConfigDO.java
@@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
5 import cn.iocoder.yudao.framework.mybatis.core.type.IntegerListTypeHandler; 5 import cn.iocoder.yudao.framework.mybatis.core.type.IntegerListTypeHandler;
6 import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; 6 import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
7 -import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; 7 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
8 import cn.iocoder.yudao.module.iot.enums.DictTypeConstants; 8 import cn.iocoder.yudao.module.iot.enums.DictTypeConstants;
9 import cn.iocoder.yudao.module.iot.enums.alert.IotAlertReceiveTypeEnum; 9 import cn.iocoder.yudao.module.iot.enums.alert.IotAlertReceiveTypeEnum;
10 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; 10 import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
@@ -61,7 +61,7 @@ public class IotAlertConfigDO extends BaseDO { @@ -61,7 +61,7 @@ public class IotAlertConfigDO extends BaseDO {
61 /** 61 /**
62 * 关联的场景联动规则编号数组 62 * 关联的场景联动规则编号数组
63 * 63 *
64 - * 关联 {@link IotRuleSceneDO#getId()} 64 + * 关联 {@link IotSceneRuleDO#getId()}
65 */ 65 */
66 @TableField(typeHandler = LongListTypeHandler.class) 66 @TableField(typeHandler = LongListTypeHandler.class)
67 private List<Long> sceneRuleIds; 67 private List<Long> sceneRuleIds;
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/alert/IotAlertRecordDO.java
@@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; 4 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
5 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; 5 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
6 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; 6 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
7 -import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; 7 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
8 import com.baomidou.mybatisplus.annotation.KeySequence; 8 import com.baomidou.mybatisplus.annotation.KeySequence;
9 import com.baomidou.mybatisplus.annotation.TableField; 9 import com.baomidou.mybatisplus.annotation.TableField;
10 import com.baomidou.mybatisplus.annotation.TableId; 10 import com.baomidou.mybatisplus.annotation.TableId;
@@ -55,7 +55,7 @@ public class IotAlertRecordDO extends BaseDO { @@ -55,7 +55,7 @@ public class IotAlertRecordDO extends BaseDO {
55 /** 55 /**
56 * 场景规则编号 56 * 场景规则编号
57 * 57 *
58 - * 关联 {@link IotRuleSceneDO#getId()} 58 + * 关联 {@link IotSceneRuleDO#getId()}
59 */ 59 */
60 private Long sceneRuleId; 60 private Long sceneRuleId;
61 61
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotRuleSceneDO.java renamed to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/rule/IotSceneRuleDO.java
@@ -23,19 +23,18 @@ import lombok.NoArgsConstructor; @@ -23,19 +23,18 @@ import lombok.NoArgsConstructor;
23 23
24 import java.util.List; 24 import java.util.List;
25 25
26 -// TODO @puhui999:名字改成 IotSceneRuleDO  
27 /** 26 /**
28 * IoT 场景联动规则 DO 27 * IoT 场景联动规则 DO
29 * 28 *
30 * @author 芋道源码 29 * @author 芋道源码
31 */ 30 */
32 -@TableName(value = "iot_rule_scene", autoResultMap = true)  
33 -@KeySequence("iot_rule_scene_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 31 +@TableName(value = "iot_scene_rule", autoResultMap = true)
  32 +@KeySequence("iot_scene_rule_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
34 @Data 33 @Data
35 @Builder 34 @Builder
36 @NoArgsConstructor 35 @NoArgsConstructor
37 @AllArgsConstructor 36 @AllArgsConstructor
38 -public class IotRuleSceneDO extends TenantBaseDO { 37 +public class IotSceneRuleDO extends TenantBaseDO {
39 38
40 /** 39 /**
41 * 场景联动编号 40 * 场景联动编号
@@ -219,12 +218,20 @@ public class IotRuleSceneDO extends TenantBaseDO { @@ -219,12 +218,20 @@ public class IotRuleSceneDO extends TenantBaseDO {
219 * 关联 {@link IotDeviceDO#getId()} 218 * 关联 {@link IotDeviceDO#getId()}
220 */ 219 */
221 private Long deviceId; 220 private Long deviceId;
  221 +
  222 + /**
  223 + * 标识符(服务)
  224 + * <p>
  225 + * 关联 {@link IotThingModelDO#getIdentifier()}
  226 + */
  227 + private String identifier;
  228 +
222 /** 229 /**
223 * 请求参数 230 * 请求参数
224 * 231 *
225 * 一般来说,对应 {@link IotDeviceMessage#getParams()} 请求参数 232 * 一般来说,对应 {@link IotDeviceMessage#getParams()} 请求参数
226 */ 233 */
227 - private Object params; 234 + private String params;
228 235
229 /** 236 /**
230 * 告警配置编号 237 * 告警配置编号
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/rule/IotRuleSceneMapper.java
@@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePageReqVO; 6 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePageReqVO;
7 -import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; 7 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
8 import org.apache.ibatis.annotations.Mapper; 8 import org.apache.ibatis.annotations.Mapper;
9 9
10 import java.util.List; 10 import java.util.List;
@@ -15,19 +15,19 @@ import java.util.List; @@ -15,19 +15,19 @@ import java.util.List;
15 * @author HUIHUI 15 * @author HUIHUI
16 */ 16 */
17 @Mapper 17 @Mapper
18 -public interface IotRuleSceneMapper extends BaseMapperX<IotRuleSceneDO> { 18 +public interface IotRuleSceneMapper extends BaseMapperX<IotSceneRuleDO> {
19 19
20 - default PageResult<IotRuleSceneDO> selectPage(IotRuleScenePageReqVO reqVO) {  
21 - return selectPage(reqVO, new LambdaQueryWrapperX<IotRuleSceneDO>()  
22 - .likeIfPresent(IotRuleSceneDO::getName, reqVO.getName())  
23 - .likeIfPresent(IotRuleSceneDO::getDescription, reqVO.getDescription())  
24 - .eqIfPresent(IotRuleSceneDO::getStatus, reqVO.getStatus())  
25 - .betweenIfPresent(IotRuleSceneDO::getCreateTime, reqVO.getCreateTime())  
26 - .orderByDesc(IotRuleSceneDO::getId)); 20 + default PageResult<IotSceneRuleDO> selectPage(IotRuleScenePageReqVO reqVO) {
  21 + return selectPage(reqVO, new LambdaQueryWrapperX<IotSceneRuleDO>()
  22 + .likeIfPresent(IotSceneRuleDO::getName, reqVO.getName())
  23 + .likeIfPresent(IotSceneRuleDO::getDescription, reqVO.getDescription())
  24 + .eqIfPresent(IotSceneRuleDO::getStatus, reqVO.getStatus())
  25 + .betweenIfPresent(IotSceneRuleDO::getCreateTime, reqVO.getCreateTime())
  26 + .orderByDesc(IotSceneRuleDO::getId));
27 } 27 }
28 28
29 - default List<IotRuleSceneDO> selectListByStatus(Integer status) {  
30 - return selectList(IotRuleSceneDO::getStatus, status); 29 + default List<IotSceneRuleDO> selectListByStatus(Integer status) {
  30 + return selectList(IotSceneRuleDO::getStatus, status);
31 } 31 }
32 32
33 } 33 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/IotRuleSceneService.java
@@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePageReqVO; 4 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePageReqVO;
5 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO; 5 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO;
6 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; 6 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
7 -import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; 7 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
8 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum; 8 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum;
9 import jakarta.validation.Valid; 9 import jakarta.validation.Valid;
10 10
@@ -54,7 +54,7 @@ public interface IotRuleSceneService { @@ -54,7 +54,7 @@ public interface IotRuleSceneService {
54 * @param id 编号 54 * @param id 编号
55 * @return 场景联动 55 * @return 场景联动
56 */ 56 */
57 - IotRuleSceneDO getRuleScene(Long id); 57 + IotSceneRuleDO getRuleScene(Long id);
58 58
59 /** 59 /**
60 * 获得场景联动分页 60 * 获得场景联动分页
@@ -62,7 +62,7 @@ public interface IotRuleSceneService { @@ -62,7 +62,7 @@ public interface IotRuleSceneService {
62 * @param pageReqVO 分页查询 62 * @param pageReqVO 分页查询
63 * @return 场景联动分页 63 * @return 场景联动分页
64 */ 64 */
65 - PageResult<IotRuleSceneDO> getRuleScenePage(IotRuleScenePageReqVO pageReqVO); 65 + PageResult<IotSceneRuleDO> getRuleScenePage(IotRuleScenePageReqVO pageReqVO);
66 66
67 /** 67 /**
68 * 校验规则场景联动规则编号们是否存在。如下情况,视为无效: 68 * 校验规则场景联动规则编号们是否存在。如下情况,视为无效:
@@ -78,7 +78,7 @@ public interface IotRuleSceneService { @@ -78,7 +78,7 @@ public interface IotRuleSceneService {
78 * @param status 状态 78 * @param status 状态
79 * @return 场景联动列表 79 * @return 场景联动列表
80 */ 80 */
81 - List<IotRuleSceneDO> getRuleSceneListByStatus(Integer status); 81 + List<IotSceneRuleDO> getRuleSceneListByStatus(Integer status);
82 82
83 /** 83 /**
84 * 【缓存】获得指定设备的场景列表 84 * 【缓存】获得指定设备的场景列表
@@ -87,7 +87,7 @@ public interface IotRuleSceneService { @@ -87,7 +87,7 @@ public interface IotRuleSceneService {
87 * @param deviceName 设备名称 87 * @param deviceName 设备名称
88 * @return 场景列表 88 * @return 场景列表
89 */ 89 */
90 - List<IotRuleSceneDO> getRuleSceneListByProductKeyAndDeviceNameFromCache(String productKey, String deviceName); 90 + List<IotSceneRuleDO> getRuleSceneListByProductKeyAndDeviceNameFromCache(String productKey, String deviceName);
91 91
92 /** 92 /**
93 * 基于 {@link IotRuleSceneTriggerTypeEnum#DEVICE} 场景,执行规则场景 93 * 基于 {@link IotRuleSceneTriggerTypeEnum#DEVICE} 场景,执行规则场景
@@ -103,9 +103,4 @@ public interface IotRuleSceneService { @@ -103,9 +103,4 @@ public interface IotRuleSceneService {
103 */ 103 */
104 void executeRuleSceneByTimer(Long id); 104 void executeRuleSceneByTimer(Long id);
105 105
106 - /**  
107 - * TODO 芋艿:测试方法,需要删除  
108 - */  
109 - void test();  
110 -  
111 } 106 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/IotRuleSceneServiceImpl.java
@@ -21,29 +21,24 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; @@ -21,29 +21,24 @@ import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
21 import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils; 21 import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils;
22 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; 22 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
23 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; 23 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
24 -import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; 24 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
25 import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotRuleSceneMapper; 25 import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotRuleSceneMapper;
26 -import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;  
27 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneConditionOperatorEnum; 26 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneConditionOperatorEnum;
28 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneConditionTypeEnum; 27 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneConditionTypeEnum;
29 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum; 28 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum;
30 import cn.iocoder.yudao.module.iot.framework.job.core.IotSchedulerManager; 29 import cn.iocoder.yudao.module.iot.framework.job.core.IotSchedulerManager;
31 -import cn.iocoder.yudao.module.iot.job.rule.IotRuleSceneJob;  
32 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; 30 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
33 import cn.iocoder.yudao.module.iot.service.product.IotProductService; 31 import cn.iocoder.yudao.module.iot.service.product.IotProductService;
34 import cn.iocoder.yudao.module.iot.service.rule.scene.action.IotSceneRuleAction; 32 import cn.iocoder.yudao.module.iot.service.rule.scene.action.IotSceneRuleAction;
35 import jakarta.annotation.Resource; 33 import jakarta.annotation.Resource;
36 -import lombok.SneakyThrows;  
37 import lombok.extern.slf4j.Slf4j; 34 import lombok.extern.slf4j.Slf4j;
38 -import org.quartz.JobKey;  
39 -import org.quartz.Scheduler;  
40 -import org.quartz.SchedulerException;  
41 -import org.quartz.TriggerKey;  
42 -import org.quartz.impl.StdSchedulerFactory;  
43 import org.springframework.stereotype.Service; 35 import org.springframework.stereotype.Service;
44 import org.springframework.validation.annotation.Validated; 36 import org.springframework.validation.annotation.Validated;
45 37
46 -import java.util.*; 38 +import java.util.Collection;
  39 +import java.util.HashMap;
  40 +import java.util.List;
  41 +import java.util.Map;
47 42
48 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 43 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
49 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; 44 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
@@ -77,7 +72,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -77,7 +72,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
77 72
78 @Override 73 @Override
79 public Long createRuleScene(IotRuleSceneSaveReqVO createReqVO) { 74 public Long createRuleScene(IotRuleSceneSaveReqVO createReqVO) {
80 - IotRuleSceneDO ruleScene = BeanUtils.toBean(createReqVO, IotRuleSceneDO.class); 75 + IotSceneRuleDO ruleScene = BeanUtils.toBean(createReqVO, IotSceneRuleDO.class);
81 ruleSceneMapper.insert(ruleScene); 76 ruleSceneMapper.insert(ruleScene);
82 return ruleScene.getId(); 77 return ruleScene.getId();
83 } 78 }
@@ -87,7 +82,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -87,7 +82,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
87 // 校验存在 82 // 校验存在
88 validateRuleSceneExists(updateReqVO.getId()); 83 validateRuleSceneExists(updateReqVO.getId());
89 // 更新 84 // 更新
90 - IotRuleSceneDO updateObj = BeanUtils.toBean(updateReqVO, IotRuleSceneDO.class); 85 + IotSceneRuleDO updateObj = BeanUtils.toBean(updateReqVO, IotSceneRuleDO.class);
91 ruleSceneMapper.updateById(updateObj); 86 ruleSceneMapper.updateById(updateObj);
92 } 87 }
93 88
@@ -96,7 +91,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -96,7 +91,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
96 // 校验存在 91 // 校验存在
97 validateRuleSceneExists(id); 92 validateRuleSceneExists(id);
98 // 更新状态 93 // 更新状态
99 - IotRuleSceneDO updateObj = new IotRuleSceneDO().setId(id).setStatus(status); 94 + IotSceneRuleDO updateObj = new IotSceneRuleDO().setId(id).setStatus(status);
100 ruleSceneMapper.updateById(updateObj); 95 ruleSceneMapper.updateById(updateObj);
101 } 96 }
102 97
@@ -115,12 +110,12 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -115,12 +110,12 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
115 } 110 }
116 111
117 @Override 112 @Override
118 - public IotRuleSceneDO getRuleScene(Long id) { 113 + public IotSceneRuleDO getRuleScene(Long id) {
119 return ruleSceneMapper.selectById(id); 114 return ruleSceneMapper.selectById(id);
120 } 115 }
121 116
122 @Override 117 @Override
123 - public PageResult<IotRuleSceneDO> getRuleScenePage(IotRuleScenePageReqVO pageReqVO) { 118 + public PageResult<IotSceneRuleDO> getRuleScenePage(IotRuleScenePageReqVO pageReqVO) {
124 return ruleSceneMapper.selectPage(pageReqVO); 119 return ruleSceneMapper.selectPage(pageReqVO);
125 } 120 }
126 121
@@ -130,27 +125,27 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -130,27 +125,27 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
130 return; 125 return;
131 } 126 }
132 // 批量查询存在的规则场景 127 // 批量查询存在的规则场景
133 - List<IotRuleSceneDO> existingScenes = ruleSceneMapper.selectByIds(ids); 128 + List<IotSceneRuleDO> existingScenes = ruleSceneMapper.selectByIds(ids);
134 if (existingScenes.size() != ids.size()) { 129 if (existingScenes.size() != ids.size()) {
135 throw exception(RULE_SCENE_NOT_EXISTS); 130 throw exception(RULE_SCENE_NOT_EXISTS);
136 } 131 }
137 } 132 }
138 133
139 @Override 134 @Override
140 - public List<IotRuleSceneDO> getRuleSceneListByStatus(Integer status) { 135 + public List<IotSceneRuleDO> getRuleSceneListByStatus(Integer status) {
141 return ruleSceneMapper.selectListByStatus(status); 136 return ruleSceneMapper.selectListByStatus(status);
142 } 137 }
143 138
144 // TODO 芋艿,缓存待实现 139 // TODO 芋艿,缓存待实现
145 @Override 140 @Override
146 @TenantIgnore // 忽略租户隔离:因为 IotRuleSceneMessageHandler 调用时,一般未传递租户,所以需要忽略 141 @TenantIgnore // 忽略租户隔离:因为 IotRuleSceneMessageHandler 调用时,一般未传递租户,所以需要忽略
147 - public List<IotRuleSceneDO> getRuleSceneListByProductKeyAndDeviceNameFromCache(String productKey, String deviceName) { 142 + public List<IotSceneRuleDO> getRuleSceneListByProductKeyAndDeviceNameFromCache(String productKey, String deviceName) {
148 // TODO @puhui999:一些注释,看看要不要优化下; 143 // TODO @puhui999:一些注释,看看要不要优化下;
149 // 注意:旧的测试代码已删除,因为使用了废弃的数据结构 144 // 注意:旧的测试代码已删除,因为使用了废弃的数据结构
150 // 如需测试,请使用上面的新结构测试代码示例 145 // 如需测试,请使用上面的新结构测试代码示例
151 - List<IotRuleSceneDO> list = ruleSceneMapper.selectList(); 146 + List<IotSceneRuleDO> list = ruleSceneMapper.selectList();
152 // 只返回启用状态的规则场景 147 // 只返回启用状态的规则场景
153 - List<IotRuleSceneDO> enabledList = filterList(list, 148 + List<IotSceneRuleDO> enabledList = filterList(list,
154 ruleScene -> CommonStatusEnum.ENABLE.getStatus().equals(ruleScene.getStatus())); 149 ruleScene -> CommonStatusEnum.ENABLE.getStatus().equals(ruleScene.getStatus()));
155 150
156 // 根据 productKey 和 deviceName 进行匹配 151 // 根据 productKey 和 deviceName 进行匹配
@@ -159,7 +154,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -159,7 +154,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
159 return false; 154 return false;
160 } 155 }
161 156
162 - for (IotRuleSceneDO.Trigger trigger : ruleScene.getTriggers()) { 157 + for (IotSceneRuleDO.Trigger trigger : ruleScene.getTriggers()) {
163 // 检查触发器是否匹配指定的产品和设备 158 // 检查触发器是否匹配指定的产品和设备
164 if (isMatchProductAndDevice(trigger, productKey, deviceName)) { 159 if (isMatchProductAndDevice(trigger, productKey, deviceName)) {
165 return true; 160 return true;
@@ -177,7 +172,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -177,7 +172,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
177 * @param deviceName 设备名称 172 * @param deviceName 设备名称
178 * @return 是否匹配 173 * @return 是否匹配
179 */ 174 */
180 - private boolean isMatchProductAndDevice(IotRuleSceneDO.Trigger trigger, String productKey, String deviceName) { 175 + private boolean isMatchProductAndDevice(IotSceneRuleDO.Trigger trigger, String productKey, String deviceName) {
181 try { 176 try {
182 // 1. 检查产品是否匹配 177 // 1. 检查产品是否匹配
183 if (trigger.getProductId() != null) { 178 if (trigger.getProductId() != null) {
@@ -219,7 +214,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -219,7 +214,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
219 // TODO @芋艿:这里的 tenantId,通过设备获取; 214 // TODO @芋艿:这里的 tenantId,通过设备获取;
220 TenantUtils.execute(message.getTenantId(), () -> { 215 TenantUtils.execute(message.getTenantId(), () -> {
221 // 1. 获得设备匹配的规则场景 216 // 1. 获得设备匹配的规则场景
222 - List<IotRuleSceneDO> ruleScenes = getMatchedRuleSceneListByMessage(message); 217 + List<IotSceneRuleDO> ruleScenes = getMatchedRuleSceneListByMessage(message);
223 if (CollUtil.isEmpty(ruleScenes)) { 218 if (CollUtil.isEmpty(ruleScenes)) {
224 return; 219 return;
225 } 220 }
@@ -232,7 +227,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -232,7 +227,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
232 @Override 227 @Override
233 public void executeRuleSceneByTimer(Long id) { 228 public void executeRuleSceneByTimer(Long id) {
234 // 1.1 获得规则场景 229 // 1.1 获得规则场景
235 - IotRuleSceneDO scene = TenantUtils.executeIgnore(() -> ruleSceneMapper.selectById(id)); 230 + IotSceneRuleDO scene = TenantUtils.executeIgnore(() -> ruleSceneMapper.selectById(id));
236 if (scene == null) { 231 if (scene == null) {
237 log.error("[executeRuleSceneByTimer][规则场景({}) 不存在]", id); 232 log.error("[executeRuleSceneByTimer][规则场景({}) 不存在]", id);
238 return; 233 return;
@@ -242,7 +237,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -242,7 +237,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
242 return; 237 return;
243 } 238 }
244 // 1.2 判断是否有定时触发器,避免脏数据 239 // 1.2 判断是否有定时触发器,避免脏数据
245 - IotRuleSceneDO.Trigger config = CollUtil.findOne(scene.getTriggers(), 240 + IotSceneRuleDO.Trigger config = CollUtil.findOne(scene.getTriggers(),
246 trigger -> ObjUtil.equals(trigger.getType(), IotRuleSceneTriggerTypeEnum.TIMER.getType())); 241 trigger -> ObjUtil.equals(trigger.getType(), IotRuleSceneTriggerTypeEnum.TIMER.getType()));
247 if (config == null) { 242 if (config == null) {
248 log.error("[executeRuleSceneByTimer][规则场景({}) 不存在定时触发器]", scene); 243 log.error("[executeRuleSceneByTimer][规则场景({}) 不存在定时触发器]", scene);
@@ -260,7 +255,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -260,7 +255,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
260 * @param message 设备消息 255 * @param message 设备消息
261 * @return 规则场景列表 256 * @return 规则场景列表
262 */ 257 */
263 - private List<IotRuleSceneDO> getMatchedRuleSceneListByMessage(IotDeviceMessage message) { 258 + private List<IotSceneRuleDO> getMatchedRuleSceneListByMessage(IotDeviceMessage message) {
264 // 1. 匹配设备 259 // 1. 匹配设备
265 // TODO @芋艿:可能需要 getSelf(); 缓存 260 // TODO @芋艿:可能需要 getSelf(); 缓存
266 // 1.1 通过 deviceId 获取设备信息 261 // 1.1 通过 deviceId 获取设备信息
@@ -278,7 +273,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -278,7 +273,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
278 } 273 }
279 274
280 // 1.3 获取匹配的规则场景 275 // 1.3 获取匹配的规则场景
281 - List<IotRuleSceneDO> ruleScenes = getRuleSceneListByProductKeyAndDeviceNameFromCache( 276 + List<IotSceneRuleDO> ruleScenes = getRuleSceneListByProductKeyAndDeviceNameFromCache(
282 product.getProductKey(), device.getDeviceName()); 277 product.getProductKey(), device.getDeviceName());
283 if (CollUtil.isEmpty(ruleScenes)) { 278 if (CollUtil.isEmpty(ruleScenes)) {
284 return ruleScenes; 279 return ruleScenes;
@@ -286,7 +281,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -286,7 +281,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
286 281
287 // 2. 匹配 trigger 触发器的条件 282 // 2. 匹配 trigger 触发器的条件
288 return filterList(ruleScenes, ruleScene -> { 283 return filterList(ruleScenes, ruleScene -> {
289 - for (IotRuleSceneDO.Trigger trigger : ruleScene.getTriggers()) { 284 + for (IotSceneRuleDO.Trigger trigger : ruleScene.getTriggers()) {
290 // 2.1 检查触发器类型,根据新的枚举值进行匹配 285 // 2.1 检查触发器类型,根据新的枚举值进行匹配
291 // TODO @芋艿:需要根据新的触发器类型枚举进行适配 286 // TODO @芋艿:需要根据新的触发器类型枚举进行适配
292 // 原来使用 IotRuleSceneTriggerTypeEnum.DEVICE,新结构可能有不同的类型 287 // 原来使用 IotRuleSceneTriggerTypeEnum.DEVICE,新结构可能有不同的类型
@@ -298,14 +293,14 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -298,14 +293,14 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
298 293
299 // 2.3 检查条件分组:分组与分组之间是"或"的关系,条件与条件之间是"且"的关系 294 // 2.3 检查条件分组:分组与分组之间是"或"的关系,条件与条件之间是"且"的关系
300 boolean anyGroupMatched = false; 295 boolean anyGroupMatched = false;
301 - for (List<IotRuleSceneDO.TriggerCondition> conditionGroup : trigger.getConditionGroups()) { 296 + for (List<IotSceneRuleDO.TriggerCondition> conditionGroup : trigger.getConditionGroups()) {
302 if (CollUtil.isEmpty(conditionGroup)) { 297 if (CollUtil.isEmpty(conditionGroup)) {
303 continue; 298 continue;
304 } 299 }
305 300
306 // 检查当前分组中的所有条件是否都匹配(且关系) 301 // 检查当前分组中的所有条件是否都匹配(且关系)
307 boolean allConditionsMatched = true; 302 boolean allConditionsMatched = true;
308 - for (IotRuleSceneDO.TriggerCondition condition : conditionGroup) { 303 + for (IotSceneRuleDO.TriggerCondition condition : conditionGroup) {
309 // TODO @芋艿:这里需要实现具体的条件匹配逻辑 304 // TODO @芋艿:这里需要实现具体的条件匹配逻辑
310 // 根据新的 TriggerCondition 结构进行匹配 305 // 根据新的 TriggerCondition 结构进行匹配
311 if (!isTriggerConditionMatched(message, condition, ruleScene, trigger)) { 306 if (!isTriggerConditionMatched(message, condition, ruleScene, trigger)) {
@@ -338,8 +333,8 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -338,8 +333,8 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
338 * @param trigger 触发器(用于日志,无其它作用) 333 * @param trigger 触发器(用于日志,无其它作用)
339 * @return 是否匹配 334 * @return 是否匹配
340 */ 335 */
341 - private boolean isTriggerConditionMatched(IotDeviceMessage message, IotRuleSceneDO.TriggerCondition condition,  
342 - IotRuleSceneDO ruleScene, IotRuleSceneDO.Trigger trigger) { 336 + private boolean isTriggerConditionMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition,
  337 + IotSceneRuleDO ruleScene, IotSceneRuleDO.Trigger trigger) {
343 try { 338 try {
344 // 1. 根据条件类型进行匹配 339 // 1. 根据条件类型进行匹配
345 if (IotRuleSceneConditionTypeEnum.DEVICE_STATE.getType().equals(condition.getType())) { 340 if (IotRuleSceneConditionTypeEnum.DEVICE_STATE.getType().equals(condition.getType())) {
@@ -370,7 +365,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -370,7 +365,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
370 * @param condition 触发条件 365 * @param condition 触发条件
371 * @return 是否匹配 366 * @return 是否匹配
372 */ 367 */
373 - private boolean matchDeviceStateCondition(IotDeviceMessage message, IotRuleSceneDO.TriggerCondition condition) { 368 + private boolean matchDeviceStateCondition(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) {
374 // TODO @芋艿:需要根据设备状态进行匹配 369 // TODO @芋艿:需要根据设备状态进行匹配
375 // 这里需要检查消息中的设备状态是否符合条件中定义的状态 370 // 这里需要检查消息中的设备状态是否符合条件中定义的状态
376 log.debug("[matchDeviceStateCondition][设备状态条件匹配逻辑待实现] condition: {}", condition); 371 log.debug("[matchDeviceStateCondition][设备状态条件匹配逻辑待实现] condition: {}", condition);
@@ -384,7 +379,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -384,7 +379,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
384 * @param condition 触发条件 379 * @param condition 触发条件
385 * @return 是否匹配 380 * @return 是否匹配
386 */ 381 */
387 - private boolean matchDevicePropertyCondition(IotDeviceMessage message, IotRuleSceneDO.TriggerCondition condition) { 382 + private boolean matchDevicePropertyCondition(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition) {
388 // 1. 检查标识符是否匹配 383 // 1. 检查标识符是否匹配
389 String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message); 384 String messageIdentifier = IotDeviceMessageUtils.getIdentifier(message);
390 if (StrUtil.isBlank(condition.getIdentifier()) || !condition.getIdentifier().equals(messageIdentifier)) { 385 if (StrUtil.isBlank(condition.getIdentifier()) || !condition.getIdentifier().equals(messageIdentifier)) {
@@ -407,7 +402,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -407,7 +402,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
407 * @param condition 触发条件 402 * @param condition 触发条件
408 * @return 是否匹配 403 * @return 是否匹配
409 */ 404 */
410 - private boolean matchCurrentTimeCondition(IotRuleSceneDO.TriggerCondition condition) { 405 + private boolean matchCurrentTimeCondition(IotSceneRuleDO.TriggerCondition condition) {
411 // TODO @芋艿:需要根据当前时间进行匹配 406 // TODO @芋艿:需要根据当前时间进行匹配
412 // 这里需要检查当前时间是否符合条件中定义的时间范围 407 // 这里需要检查当前时间是否符合条件中定义的时间范围
413 log.debug("[matchCurrentTimeCondition][当前时间条件匹配逻辑待实现] condition: {}", condition); 408 log.debug("[matchCurrentTimeCondition][当前时间条件匹配逻辑待实现] condition: {}", condition);
@@ -474,8 +469,8 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -474,8 +469,8 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
474 * @return 是否匹配 469 * @return 是否匹配
475 */ 470 */
476 @SuppressWarnings({"unchecked", "DataFlowIssue"}) 471 @SuppressWarnings({"unchecked", "DataFlowIssue"})
477 - private boolean isTriggerConditionParameterMatched(IotDeviceMessage message, IotRuleSceneDO.TriggerCondition condition,  
478 - IotRuleSceneDO ruleScene, IotRuleSceneDO.Trigger trigger) { 472 + private boolean isTriggerConditionParameterMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition,
  473 + IotSceneRuleDO ruleScene, IotSceneRuleDO.Trigger trigger) {
479 // 1.1 校验操作符是否合法 474 // 1.1 校验操作符是否合法
480 IotRuleSceneConditionOperatorEnum operator = 475 IotRuleSceneConditionOperatorEnum operator =
481 IotRuleSceneConditionOperatorEnum.operatorOf(condition.getOperator()); 476 IotRuleSceneConditionOperatorEnum.operatorOf(condition.getOperator());
@@ -528,7 +523,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -528,7 +523,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
528 * @param message 设备消息 523 * @param message 设备消息
529 * @param ruleScenes 规则场景列表 524 * @param ruleScenes 规则场景列表
530 */ 525 */
531 - private void executeRuleSceneAction(IotDeviceMessage message, List<IotRuleSceneDO> ruleScenes) { 526 + private void executeRuleSceneAction(IotDeviceMessage message, List<IotSceneRuleDO> ruleScenes) {
532 // 1. 遍历规则场景 527 // 1. 遍历规则场景
533 ruleScenes.forEach(ruleScene -> { 528 ruleScenes.forEach(ruleScene -> {
534 // 2. 遍历规则场景的动作 529 // 2. 遍历规则场景的动作
@@ -554,50 +549,4 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService { @@ -554,50 +549,4 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
554 }); 549 });
555 } 550 }
556 551
557 - @Override  
558 - @SneakyThrows  
559 - public void test() {  
560 - // TODO @芋艿:测试思路代码,记得删除!!!  
561 - // 1. Job 类:IotRuleSceneJob DONE  
562 - // 2. 参数:id DONE  
563 - // 3. jobHandlerName:IotRuleSceneJob + id DONE  
564 -  
565 - // 新增:addJob  
566 - // 修改:不存在 addJob、存在 updateJob  
567 - // 有 + 禁用:1)存在、停止;2)不存在:不处理;TODO 测试:直接暂停,是否可以???(结论:可以)pauseJob  
568 - // 有 + 开启:1)存在,更新;2)不存在,新增;结论:使用 save(addOrUpdateJob)  
569 - // 无 + 禁用、开启:1)存在,删除;TODO 测试:直接删除???(结论:可以)deleteJob  
570 -  
571 - //  
572 - if (false) {  
573 - Long id = 1L;  
574 - Map<String, Object> jobDataMap = IotRuleSceneJob.buildJobDataMap(id);  
575 - schedulerManager.addOrUpdateJob(IotRuleSceneJob.class,  
576 - IotRuleSceneJob.buildJobName(id),  
577 - "0/10 * * * * ?",  
578 - jobDataMap);  
579 - }  
580 - if (false) {  
581 - Long id = 1L;  
582 - schedulerManager.pauseJob(IotRuleSceneJob.buildJobName(id));  
583 - }  
584 - if (true) {  
585 - Long id = 1L;  
586 - schedulerManager.deleteJob(IotRuleSceneJob.buildJobName(id));  
587 - }  
588 - }  
589 -  
590 - public static void main2(String[] args) throws SchedulerException {  
591 -// System.out.println(QuartzJobBean.class);  
592 - Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();  
593 - scheduler.start();  
594 -  
595 - String jobHandlerName = "123";  
596 - // 暂停 Trigger 对象  
597 - scheduler.pauseTrigger(new TriggerKey(jobHandlerName));  
598 - // 取消并删除 Job 调度  
599 - scheduler.unscheduleJob(new TriggerKey(jobHandlerName));  
600 - scheduler.deleteJob(new JobKey(jobHandlerName));  
601 - }  
602 -  
603 } 552 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/action/IotAlertRecoverSceneRuleAction.java
@@ -4,7 +4,7 @@ import cn.hutool.core.collection.CollUtil; @@ -4,7 +4,7 @@ import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
5 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; 5 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
6 import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertRecordDO; 6 import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertRecordDO;
7 -import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; 7 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
8 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; 8 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
9 import cn.iocoder.yudao.module.iot.service.alert.IotAlertRecordService; 9 import cn.iocoder.yudao.module.iot.service.alert.IotAlertRecordService;
10 import jakarta.annotation.Resource; 10 import jakarta.annotation.Resource;
@@ -30,7 +30,7 @@ public class IotAlertRecoverSceneRuleAction implements IotSceneRuleAction { @@ -30,7 +30,7 @@ public class IotAlertRecoverSceneRuleAction implements IotSceneRuleAction {
30 30
31 @Override 31 @Override
32 public void execute(IotDeviceMessage message, 32 public void execute(IotDeviceMessage message,
33 - IotRuleSceneDO rule, IotRuleSceneDO.Action actionConfig) throws Exception { 33 + IotSceneRuleDO rule, IotSceneRuleDO.Action actionConfig) throws Exception {
34 Long deviceId = message != null ? message.getDeviceId() : null; 34 Long deviceId = message != null ? message.getDeviceId() : null;
35 List<IotAlertRecordDO> alertRecords = alertRecordService.getAlertRecordListBySceneRuleId( 35 List<IotAlertRecordDO> alertRecords = alertRecordService.getAlertRecordListBySceneRuleId(
36 rule.getId(), deviceId, false); 36 rule.getId(), deviceId, false);
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/action/IotAlertTriggerSceneRuleAction.java
@@ -4,7 +4,7 @@ import cn.hutool.core.collection.CollUtil; @@ -4,7 +4,7 @@ import cn.hutool.core.collection.CollUtil;
4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; 5 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
6 import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertConfigDO; 6 import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertConfigDO;
7 -import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; 7 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
8 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; 8 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
9 import cn.iocoder.yudao.module.iot.service.alert.IotAlertConfigService; 9 import cn.iocoder.yudao.module.iot.service.alert.IotAlertConfigService;
10 import cn.iocoder.yudao.module.iot.service.alert.IotAlertRecordService; 10 import cn.iocoder.yudao.module.iot.service.alert.IotAlertRecordService;
@@ -40,7 +40,7 @@ public class IotAlertTriggerSceneRuleAction implements IotSceneRuleAction { @@ -40,7 +40,7 @@ public class IotAlertTriggerSceneRuleAction implements IotSceneRuleAction {
40 40
41 @Override 41 @Override
42 public void execute(@Nullable IotDeviceMessage message, 42 public void execute(@Nullable IotDeviceMessage message,
43 - IotRuleSceneDO rule, IotRuleSceneDO.Action actionConfig) throws Exception { 43 + IotSceneRuleDO rule, IotSceneRuleDO.Action actionConfig) throws Exception {
44 List<IotAlertConfigDO> alertConfigs = alertConfigService.getAlertConfigListBySceneRuleIdAndStatus( 44 List<IotAlertConfigDO> alertConfigs = alertConfigService.getAlertConfigListBySceneRuleIdAndStatus(
45 rule.getId(), CommonStatusEnum.ENABLE.getStatus()); 45 rule.getId(), CommonStatusEnum.ENABLE.getStatus());
46 if (CollUtil.isEmpty(alertConfigs)) { 46 if (CollUtil.isEmpty(alertConfigs)) {
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/action/IotDeviceControlRuleSceneAction.java
1 package cn.iocoder.yudao.module.iot.service.rule.scene.action; 1 package cn.iocoder.yudao.module.iot.service.rule.scene.action;
2 2
3 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; 3 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
4 -import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; 4 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
5 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; 5 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
6 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; 6 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
7 import cn.iocoder.yudao.module.iot.service.device.message.IotDeviceMessageService; 7 import cn.iocoder.yudao.module.iot.service.device.message.IotDeviceMessageService;
@@ -26,8 +26,8 @@ public class IotDeviceControlRuleSceneAction implements IotSceneRuleAction { @@ -26,8 +26,8 @@ public class IotDeviceControlRuleSceneAction implements IotSceneRuleAction {
26 // TODO @puhui999:这里 26 // TODO @puhui999:这里
27 @Override 27 @Override
28 public void execute(IotDeviceMessage message, 28 public void execute(IotDeviceMessage message,
29 - IotRuleSceneDO rule, IotRuleSceneDO.Action actionConfig) {  
30 - //IotRuleSceneDO.ActionDeviceControl control = actionConfig.getDeviceControl(); 29 + IotSceneRuleDO rule, IotSceneRuleDO.Action actionConfig) {
  30 + //IotSceneRuleDO.ActionDeviceControl control = actionConfig.getDeviceControl();
31 //Assert.notNull(control, "设备控制配置不能为空"); 31 //Assert.notNull(control, "设备控制配置不能为空");
32 //// 遍历每个设备,下发消息 32 //// 遍历每个设备,下发消息
33 //control.getDeviceNames().forEach(deviceName -> { 33 //control.getDeviceNames().forEach(deviceName -> {
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/scene/action/IotSceneRuleAction.java
1 package cn.iocoder.yudao.module.iot.service.rule.scene.action; 1 package cn.iocoder.yudao.module.iot.service.rule.scene.action;
2 2
3 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; 3 import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
4 -import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO; 4 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
5 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; 5 import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
6 6
7 import javax.annotation.Nullable; 7 import javax.annotation.Nullable;
@@ -23,8 +23,8 @@ public interface IotSceneRuleAction { @@ -23,8 +23,8 @@ public interface IotSceneRuleAction {
23 * @param actionConfig 执行配置(实际对应规则里的哪条执行配置) 23 * @param actionConfig 执行配置(实际对应规则里的哪条执行配置)
24 */ 24 */
25 void execute(@Nullable IotDeviceMessage message, 25 void execute(@Nullable IotDeviceMessage message,
26 - IotRuleSceneDO rule,  
27 - IotRuleSceneDO.Action actionConfig) throws Exception; 26 + IotSceneRuleDO rule,
  27 + IotSceneRuleDO.Action actionConfig) throws Exception;
28 28
29 /** 29 /**
30 * 获得类型 30 * 获得类型
yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/rule/scene/IotRuleSceneServiceSimpleTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.service.rule.scene;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  4 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  5 +import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO;
  6 +import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
  7 +import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotRuleSceneMapper;
  8 +import cn.iocoder.yudao.module.iot.framework.job.core.IotSchedulerManager;
  9 +import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
  10 +import cn.iocoder.yudao.module.iot.service.product.IotProductService;
  11 +import cn.iocoder.yudao.module.iot.service.rule.scene.action.IotSceneRuleAction;
  12 +import org.junit.jupiter.api.Test;
  13 +import org.mockito.InjectMocks;
  14 +import org.mockito.Mock;
  15 +
  16 +import java.util.Collections;
  17 +import java.util.List;
  18 +
  19 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
  20 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  21 +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
  22 +import static org.junit.jupiter.api.Assertions.assertEquals;
  23 +import static org.mockito.ArgumentMatchers.any;
  24 +import static org.mockito.Mockito.*;
  25 +
  26 +/**
  27 + * {@link IotRuleSceneServiceImpl} 的简化单元测试类
  28 + * 使用 Mockito 进行纯单元测试,不依赖 Spring 容器
  29 + *
  30 + * @author 芋道源码
  31 + */
  32 +public class IotRuleSceneServiceSimpleTest extends BaseMockitoUnitTest {
  33 +
  34 + @InjectMocks
  35 + private IotRuleSceneServiceImpl ruleSceneService;
  36 +
  37 + @Mock
  38 + private IotRuleSceneMapper ruleSceneMapper;
  39 +
  40 + @Mock
  41 + private List<IotSceneRuleAction> ruleSceneActions;
  42 +
  43 + @Mock
  44 + private IotSchedulerManager schedulerManager;
  45 +
  46 + @Mock
  47 + private IotProductService productService;
  48 +
  49 + @Mock
  50 + private IotDeviceService deviceService;
  51 +
  52 + @Test
  53 + public void testCreateRuleScene_success() {
  54 + // 准备参数
  55 + IotRuleSceneSaveReqVO createReqVO = randomPojo(IotRuleSceneSaveReqVO.class, o -> {
  56 + o.setId(null);
  57 + o.setStatus(CommonStatusEnum.ENABLE.getStatus());
  58 + o.setTriggers(Collections.singletonList(randomPojo(IotSceneRuleDO.Trigger.class)));
  59 + o.setActions(Collections.singletonList(randomPojo(IotSceneRuleDO.Action.class)));
  60 + });
  61 +
  62 + // Mock 行为
  63 + Long expectedId = randomLongId();
  64 + when(ruleSceneMapper.insert(any(IotSceneRuleDO.class))).thenAnswer(invocation -> {
  65 + IotSceneRuleDO ruleScene = invocation.getArgument(0);
  66 + ruleScene.setId(expectedId);
  67 + return 1;
  68 + });
  69 +
  70 + // 调用
  71 + Long ruleSceneId = ruleSceneService.createRuleScene(createReqVO);
  72 +
  73 + // 断言
  74 + assertEquals(expectedId, ruleSceneId);
  75 + verify(ruleSceneMapper, times(1)).insert(any(IotSceneRuleDO.class));
  76 + }
  77 +
  78 + @Test
  79 + public void testUpdateRuleScene_success() {
  80 + // 准备参数
  81 + Long id = randomLongId();
  82 + IotRuleSceneSaveReqVO updateReqVO = randomPojo(IotRuleSceneSaveReqVO.class, o -> {
  83 + o.setId(id);
  84 + o.setStatus(CommonStatusEnum.ENABLE.getStatus());
  85 + o.setTriggers(Collections.singletonList(randomPojo(IotSceneRuleDO.Trigger.class)));
  86 + o.setActions(Collections.singletonList(randomPojo(IotSceneRuleDO.Action.class)));
  87 + });
  88 +
  89 + // Mock 行为
  90 + IotSceneRuleDO existingRuleScene = randomPojo(IotSceneRuleDO.class, o -> o.setId(id));
  91 + when(ruleSceneMapper.selectById(id)).thenReturn(existingRuleScene);
  92 + when(ruleSceneMapper.updateById(any(IotSceneRuleDO.class))).thenReturn(1);
  93 +
  94 + // 调用
  95 + assertDoesNotThrow(() -> ruleSceneService.updateRuleScene(updateReqVO));
  96 +
  97 + // 验证
  98 + verify(ruleSceneMapper, times(1)).selectById(id);
  99 + verify(ruleSceneMapper, times(1)).updateById(any(IotSceneRuleDO.class));
  100 + }
  101 +
  102 + @Test
  103 + public void testDeleteRuleScene_success() {
  104 + // 准备参数
  105 + Long id = randomLongId();
  106 +
  107 + // Mock 行为
  108 + IotSceneRuleDO existingRuleScene = randomPojo(IotSceneRuleDO.class, o -> o.setId(id));
  109 + when(ruleSceneMapper.selectById(id)).thenReturn(existingRuleScene);
  110 + when(ruleSceneMapper.deleteById(id)).thenReturn(1);
  111 +
  112 + // 调用
  113 + assertDoesNotThrow(() -> ruleSceneService.deleteRuleScene(id));
  114 +
  115 + // 验证
  116 + verify(ruleSceneMapper, times(1)).selectById(id);
  117 + verify(ruleSceneMapper, times(1)).deleteById(id);
  118 + }
  119 +
  120 + @Test
  121 + public void testGetRuleScene() {
  122 + // 准备参数
  123 + Long id = randomLongId();
  124 + IotSceneRuleDO expectedRuleScene = randomPojo(IotSceneRuleDO.class, o -> o.setId(id));
  125 +
  126 + // Mock 行为
  127 + when(ruleSceneMapper.selectById(id)).thenReturn(expectedRuleScene);
  128 +
  129 + // 调用
  130 + IotSceneRuleDO result = ruleSceneService.getRuleScene(id);
  131 +
  132 + // 断言
  133 + assertEquals(expectedRuleScene, result);
  134 + verify(ruleSceneMapper, times(1)).selectById(id);
  135 + }
  136 +
  137 + @Test
  138 + public void testUpdateRuleSceneStatus_success() {
  139 + // 准备参数
  140 + Long id = randomLongId();
  141 + Integer status = CommonStatusEnum.DISABLE.getStatus();
  142 +
  143 + // Mock 行为
  144 + IotSceneRuleDO existingRuleScene = randomPojo(IotSceneRuleDO.class, o -> {
  145 + o.setId(id);
  146 + o.setStatus(CommonStatusEnum.ENABLE.getStatus());
  147 + });
  148 + when(ruleSceneMapper.selectById(id)).thenReturn(existingRuleScene);
  149 + when(ruleSceneMapper.updateById(any(IotSceneRuleDO.class))).thenReturn(1);
  150 +
  151 + // 调用
  152 + assertDoesNotThrow(() -> ruleSceneService.updateRuleSceneStatus(id, status));
  153 +
  154 + // 验证
  155 + verify(ruleSceneMapper, times(1)).selectById(id);
  156 + verify(ruleSceneMapper, times(1)).updateById(any(IotSceneRuleDO.class));
  157 + }
  158 +
  159 + @Test
  160 + public void testExecuteRuleSceneByTimer_success() {
  161 + // 准备参数
  162 + Long id = randomLongId();
  163 +
  164 + // Mock 行为
  165 + IotSceneRuleDO ruleScene = randomPojo(IotSceneRuleDO.class, o -> {
  166 + o.setId(id);
  167 + o.setStatus(CommonStatusEnum.ENABLE.getStatus());
  168 + });
  169 + when(ruleSceneMapper.selectById(id)).thenReturn(ruleScene);
  170 +
  171 + // 调用
  172 + assertDoesNotThrow(() -> ruleSceneService.executeRuleSceneByTimer(id));
  173 +
  174 + // 验证
  175 + verify(ruleSceneMapper, times(1)).selectById(id);
  176 + }
  177 +
  178 + @Test
  179 + public void testExecuteRuleSceneByTimer_notExists() {
  180 + // 准备参数
  181 + Long id = randomLongId();
  182 +
  183 + // Mock 行为
  184 + when(ruleSceneMapper.selectById(id)).thenReturn(null);
  185 +
  186 + // 调用 - 不存在的场景规则应该不会抛异常,只是记录日志
  187 + assertDoesNotThrow(() -> ruleSceneService.executeRuleSceneByTimer(id));
  188 +
  189 + // 验证
  190 + verify(ruleSceneMapper, times(1)).selectById(id);
  191 + }
  192 +
  193 + @Test
  194 + public void testExecuteRuleSceneByTimer_disabled() {
  195 + // 准备参数
  196 + Long id = randomLongId();
  197 +
  198 + // Mock 行为
  199 + IotSceneRuleDO ruleScene = randomPojo(IotSceneRuleDO.class, o -> {
  200 + o.setId(id);
  201 + o.setStatus(CommonStatusEnum.DISABLE.getStatus());
  202 + });
  203 + when(ruleSceneMapper.selectById(id)).thenReturn(ruleScene);
  204 +
  205 + // 调用 - 禁用的场景规则应该不会执行,只是记录日志
  206 + assertDoesNotThrow(() -> ruleSceneService.executeRuleSceneByTimer(id));
  207 +
  208 + // 验证
  209 + verify(ruleSceneMapper, times(1)).selectById(id);
  210 + }
  211 +}
yudao-module-iot/yudao-module-iot-biz/src/test/resources/application-unit-test.yaml 0 → 100644
  1 +spring:
  2 + main:
  3 + lazy-initialization: true # 开启懒加载,加快速度
  4 + banner-mode: off # 单元测试,禁用 Banner
  5 + # 数据源配置项
  6 + datasource:
  7 + name: ruoyi-vue-pro
  8 + url: jdbc:h2:mem:testdb;MODE=MYSQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=value; # MODE 使用 MySQL 模式;DATABASE_TO_UPPER 配置表和字段使用小写
  9 + driver-class-name: org.h2.Driver
  10 + username: sa
  11 + password:
  12 + druid:
  13 + async-init: true # 单元测试,异步初始化 Druid 连接池,提升启动速度
  14 + initial-size: 1 # 单元测试,配置为 1,提升启动速度
  15 + sql:
  16 + init:
  17 + schema-locations: classpath:/sql/create_tables.sql
  18 +
  19 +mybatis-plus:
  20 + lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
  21 + type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject
  22 +
  23 +--- #################### 定时任务相关配置 ####################
  24 +
  25 +--- #################### 配置中心相关配置 ####################
  26 +
  27 +--- #################### 服务保障相关配置 ####################
  28 +
  29 +# Lock4j 配置项(单元测试,禁用 Lock4j)
  30 +
  31 +--- #################### 监控相关配置 ####################
  32 +
  33 +--- #################### 芋道相关配置 ####################
  34 +
  35 +# 芋道配置项,设置当前项目所有自定义的配置
  36 +yudao:
  37 + info:
  38 + base-package: cn.iocoder.yudao
  39 + tenant: # 多租户相关配置项
  40 + enable: true
  41 + xss:
  42 + enable: false
  43 + demo: false # 关闭演示模式
yudao-module-iot/yudao-module-iot-biz/src/test/resources/logback.xml 0 → 100644
  1 +<configuration>
  2 + <!-- 引用 Spring Boot 的 logback 基础配置 -->
  3 + <include resource="org/springframework/boot/logging/logback/defaults.xml"/>
  4 +</configuration>
yudao-module-iot/yudao-module-iot-biz/src/test/resources/sql/clean.sql 0 → 100644
  1 +-- IoT 模块测试数据清理脚本
  2 +DELETE
  3 +FROM "iot_scene_rule";
  4 +DELETE
  5 +FROM "iot_product";
  6 +DELETE
  7 +FROM "iot_device";
  8 +DELETE
  9 +FROM "iot_thing_model";
  10 +DELETE
  11 +FROM "iot_device_data";
  12 +DELETE
  13 +FROM "iot_alert_config";
  14 +DELETE
  15 +FROM "iot_alert_record";
  16 +DELETE
  17 +FROM "iot_ota_firmware";
  18 +DELETE
  19 +FROM "iot_ota_task";
  20 +DELETE
  21 +FROM "iot_ota_record";
yudao-module-iot/yudao-module-iot-biz/src/test/resources/sql/create_tables.sql 0 → 100644
  1 +-- IoT 模块测试数据库表结构
  2 +-- 基于 H2 数据库语法,兼容 MySQL 模式
  3 +
  4 +-- IoT 场景联动规则表
  5 +CREATE TABLE IF NOT EXISTS "iot_scene_rule"
  6 +(
  7 + "id"
  8 + bigint
  9 + NOT
  10 + NULL
  11 + GENERATED
  12 + BY
  13 + DEFAULT AS
  14 + IDENTITY,
  15 + "name"
  16 + varchar
  17 +(
  18 + 255
  19 +) NOT NULL DEFAULT '',
  20 + "description" varchar
  21 +(
  22 + 500
  23 +) DEFAULT NULL,
  24 + "status" tinyint NOT NULL DEFAULT '0',
  25 + "triggers" text,
  26 + "actions" text,
  27 + "creator" varchar
  28 +(
  29 + 64
  30 +) DEFAULT '',
  31 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  32 + "updater" varchar
  33 +(
  34 + 64
  35 +) DEFAULT '',
  36 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  37 + "deleted" bit NOT NULL DEFAULT FALSE,
  38 + "tenant_id" bigint NOT NULL DEFAULT '0',
  39 + PRIMARY KEY
  40 +(
  41 + "id"
  42 +)
  43 + ) COMMENT 'IoT 场景联动规则表';
  44 +
  45 +-- IoT 产品表
  46 +CREATE TABLE IF NOT EXISTS "iot_product"
  47 +(
  48 + "id"
  49 + bigint
  50 + NOT
  51 + NULL
  52 + GENERATED
  53 + BY
  54 + DEFAULT AS
  55 + IDENTITY,
  56 + "name"
  57 + varchar
  58 +(
  59 + 255
  60 +) NOT NULL DEFAULT '',
  61 + "product_key" varchar
  62 +(
  63 + 100
  64 +) NOT NULL DEFAULT '',
  65 + "protocol_type" tinyint NOT NULL DEFAULT '0',
  66 + "category_id" bigint DEFAULT NULL,
  67 + "description" varchar
  68 +(
  69 + 500
  70 +) DEFAULT NULL,
  71 + "data_format" tinyint NOT NULL DEFAULT '0',
  72 + "device_type" tinyint NOT NULL DEFAULT '0',
  73 + "net_type" tinyint NOT NULL DEFAULT '0',
  74 + "validate_type" tinyint NOT NULL DEFAULT '0',
  75 + "status" tinyint NOT NULL DEFAULT '0',
  76 + "creator" varchar
  77 +(
  78 + 64
  79 +) DEFAULT '',
  80 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  81 + "updater" varchar
  82 +(
  83 + 64
  84 +) DEFAULT '',
  85 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  86 + "deleted" bit NOT NULL DEFAULT FALSE,
  87 + "tenant_id" bigint NOT NULL DEFAULT '0',
  88 + PRIMARY KEY
  89 +(
  90 + "id"
  91 +)
  92 + ) COMMENT 'IoT 产品表';
  93 +
  94 +-- IoT 设备表
  95 +CREATE TABLE IF NOT EXISTS "iot_device"
  96 +(
  97 + "id"
  98 + bigint
  99 + NOT
  100 + NULL
  101 + GENERATED
  102 + BY
  103 + DEFAULT AS
  104 + IDENTITY,
  105 + "device_name"
  106 + varchar
  107 +(
  108 + 255
  109 +) NOT NULL DEFAULT '',
  110 + "product_id" bigint NOT NULL,
  111 + "device_key" varchar
  112 +(
  113 + 100
  114 +) NOT NULL DEFAULT '',
  115 + "device_secret" varchar
  116 +(
  117 + 100
  118 +) NOT NULL DEFAULT '',
  119 + "nickname" varchar
  120 +(
  121 + 255
  122 +) DEFAULT NULL,
  123 + "status" tinyint NOT NULL DEFAULT '0',
  124 + "status_last_update_time" timestamp DEFAULT NULL,
  125 + "last_online_time" timestamp DEFAULT NULL,
  126 + "last_offline_time" timestamp DEFAULT NULL,
  127 + "active_time" timestamp DEFAULT NULL,
  128 + "ip" varchar
  129 +(
  130 + 50
  131 +) DEFAULT NULL,
  132 + "firmware_version" varchar
  133 +(
  134 + 50
  135 +) DEFAULT NULL,
  136 + "device_type" tinyint NOT NULL DEFAULT '0',
  137 + "gateway_id" bigint DEFAULT NULL,
  138 + "sub_device_count" int NOT NULL DEFAULT '0',
  139 + "creator" varchar
  140 +(
  141 + 64
  142 +) DEFAULT '',
  143 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  144 + "updater" varchar
  145 +(
  146 + 64
  147 +) DEFAULT '',
  148 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  149 + "deleted" bit NOT NULL DEFAULT FALSE,
  150 + "tenant_id" bigint NOT NULL DEFAULT '0',
  151 + PRIMARY KEY
  152 +(
  153 + "id"
  154 +)
  155 + ) COMMENT 'IoT 设备表';
  156 +
  157 +-- IoT 物模型表
  158 +CREATE TABLE IF NOT EXISTS "iot_thing_model"
  159 +(
  160 + "id"
  161 + bigint
  162 + NOT
  163 + NULL
  164 + GENERATED
  165 + BY
  166 + DEFAULT AS
  167 + IDENTITY,
  168 + "product_id"
  169 + bigint
  170 + NOT
  171 + NULL,
  172 + "identifier"
  173 + varchar
  174 +(
  175 + 100
  176 +) NOT NULL DEFAULT '',
  177 + "name" varchar
  178 +(
  179 + 255
  180 +) NOT NULL DEFAULT '',
  181 + "description" varchar
  182 +(
  183 + 500
  184 +) DEFAULT NULL,
  185 + "type" tinyint NOT NULL DEFAULT '1',
  186 + "property" text,
  187 + "creator" varchar
  188 +(
  189 + 64
  190 +) DEFAULT '',
  191 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  192 + "updater" varchar
  193 +(
  194 + 64
  195 +) DEFAULT '',
  196 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  197 + "deleted" bit NOT NULL DEFAULT FALSE,
  198 + "tenant_id" bigint NOT NULL DEFAULT '0',
  199 + PRIMARY KEY
  200 +(
  201 + "id"
  202 +)
  203 + ) COMMENT 'IoT 物模型表';
  204 +
  205 +-- IoT 设备数据表
  206 +CREATE TABLE IF NOT EXISTS "iot_device_data"
  207 +(
  208 + "id"
  209 + bigint
  210 + NOT
  211 + NULL
  212 + GENERATED
  213 + BY
  214 + DEFAULT AS
  215 + IDENTITY,
  216 + "device_id"
  217 + bigint
  218 + NOT
  219 + NULL,
  220 + "product_id"
  221 + bigint
  222 + NOT
  223 + NULL,
  224 + "identifier"
  225 + varchar
  226 +(
  227 + 100
  228 +) NOT NULL DEFAULT '',
  229 + "type" tinyint NOT NULL DEFAULT '1',
  230 + "data" text,
  231 + "ts" bigint NOT NULL DEFAULT '0',
  232 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  233 + PRIMARY KEY
  234 +(
  235 + "id"
  236 +)
  237 + ) COMMENT 'IoT 设备数据表';
  238 +
  239 +-- IoT 告警配置表
  240 +CREATE TABLE IF NOT EXISTS "iot_alert_config"
  241 +(
  242 + "id"
  243 + bigint
  244 + NOT
  245 + NULL
  246 + GENERATED
  247 + BY
  248 + DEFAULT AS
  249 + IDENTITY,
  250 + "name"
  251 + varchar
  252 +(
  253 + 255
  254 +) NOT NULL DEFAULT '',
  255 + "product_id" bigint NOT NULL,
  256 + "device_id" bigint DEFAULT NULL,
  257 + "rule_id" bigint DEFAULT NULL,
  258 + "status" tinyint NOT NULL DEFAULT '0',
  259 + "creator" varchar
  260 +(
  261 + 64
  262 +) DEFAULT '',
  263 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  264 + "updater" varchar
  265 +(
  266 + 64
  267 +) DEFAULT '',
  268 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  269 + "deleted" bit NOT NULL DEFAULT FALSE,
  270 + "tenant_id" bigint NOT NULL DEFAULT '0',
  271 + PRIMARY KEY
  272 +(
  273 + "id"
  274 +)
  275 + ) COMMENT 'IoT 告警配置表';
  276 +
  277 +-- IoT 告警记录表
  278 +CREATE TABLE IF NOT EXISTS "iot_alert_record"
  279 +(
  280 + "id"
  281 + bigint
  282 + NOT
  283 + NULL
  284 + GENERATED
  285 + BY
  286 + DEFAULT AS
  287 + IDENTITY,
  288 + "alert_config_id"
  289 + bigint
  290 + NOT
  291 + NULL,
  292 + "alert_name"
  293 + varchar
  294 +(
  295 + 255
  296 +) NOT NULL DEFAULT '',
  297 + "product_id" bigint NOT NULL,
  298 + "device_id" bigint DEFAULT NULL,
  299 + "rule_id" bigint DEFAULT NULL,
  300 + "alert_data" text,
  301 + "alert_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  302 + "deal_status" tinyint NOT NULL DEFAULT '0',
  303 + "deal_time" timestamp DEFAULT NULL,
  304 + "deal_user_id" bigint DEFAULT NULL,
  305 + "deal_remark" varchar
  306 +(
  307 + 500
  308 +) DEFAULT NULL,
  309 + "creator" varchar
  310 +(
  311 + 64
  312 +) DEFAULT '',
  313 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  314 + "updater" varchar
  315 +(
  316 + 64
  317 +) DEFAULT '',
  318 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  319 + "deleted" bit NOT NULL DEFAULT FALSE,
  320 + "tenant_id" bigint NOT NULL DEFAULT '0',
  321 + PRIMARY KEY
  322 +(
  323 + "id"
  324 +)
  325 + ) COMMENT 'IoT 告警记录表';
  326 +
  327 +-- IoT OTA 固件表
  328 +CREATE TABLE IF NOT EXISTS "iot_ota_firmware"
  329 +(
  330 + "id"
  331 + bigint
  332 + NOT
  333 + NULL
  334 + GENERATED
  335 + BY
  336 + DEFAULT AS
  337 + IDENTITY,
  338 + "name"
  339 + varchar
  340 +(
  341 + 255
  342 +) NOT NULL DEFAULT '',
  343 + "product_id" bigint NOT NULL,
  344 + "version" varchar
  345 +(
  346 + 50
  347 +) NOT NULL DEFAULT '',
  348 + "description" varchar
  349 +(
  350 + 500
  351 +) DEFAULT NULL,
  352 + "file_url" varchar
  353 +(
  354 + 500
  355 +) DEFAULT NULL,
  356 + "file_size" bigint NOT NULL DEFAULT '0',
  357 + "status" tinyint NOT NULL DEFAULT '0',
  358 + "creator" varchar
  359 +(
  360 + 64
  361 +) DEFAULT '',
  362 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  363 + "updater" varchar
  364 +(
  365 + 64
  366 +) DEFAULT '',
  367 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  368 + "deleted" bit NOT NULL DEFAULT FALSE,
  369 + "tenant_id" bigint NOT NULL DEFAULT '0',
  370 + PRIMARY KEY
  371 +(
  372 + "id"
  373 +)
  374 + ) COMMENT 'IoT OTA 固件表';
  375 +
  376 +-- IoT OTA 升级任务表
  377 +CREATE TABLE IF NOT EXISTS "iot_ota_task"
  378 +(
  379 + "id"
  380 + bigint
  381 + NOT
  382 + NULL
  383 + GENERATED
  384 + BY
  385 + DEFAULT AS
  386 + IDENTITY,
  387 + "name"
  388 + varchar
  389 +(
  390 + 255
  391 +) NOT NULL DEFAULT '',
  392 + "firmware_id" bigint NOT NULL,
  393 + "product_id" bigint NOT NULL,
  394 + "upgrade_type" tinyint NOT NULL DEFAULT '0',
  395 + "status" tinyint NOT NULL DEFAULT '0',
  396 + "creator" varchar
  397 +(
  398 + 64
  399 +) DEFAULT '',
  400 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  401 + "updater" varchar
  402 +(
  403 + 64
  404 +) DEFAULT '',
  405 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  406 + "deleted" bit NOT NULL DEFAULT FALSE,
  407 + "tenant_id" bigint NOT NULL DEFAULT '0',
  408 + PRIMARY KEY
  409 +(
  410 + "id"
  411 +)
  412 + ) COMMENT 'IoT OTA 升级任务表';
  413 +
  414 +-- IoT OTA 升级记录表
  415 +CREATE TABLE IF NOT EXISTS "iot_ota_record"
  416 +(
  417 + "id"
  418 + bigint
  419 + NOT
  420 + NULL
  421 + GENERATED
  422 + BY
  423 + DEFAULT AS
  424 + IDENTITY,
  425 + "task_id"
  426 + bigint
  427 + NOT
  428 + NULL,
  429 + "firmware_id"
  430 + bigint
  431 + NOT
  432 + NULL,
  433 + "device_id"
  434 + bigint
  435 + NOT
  436 + NULL,
  437 + "status"
  438 + tinyint
  439 + NOT
  440 + NULL
  441 + DEFAULT
  442 + '0',
  443 + "progress"
  444 + int
  445 + NOT
  446 + NULL
  447 + DEFAULT
  448 + '0',
  449 + "error_msg"
  450 + varchar
  451 +(
  452 + 500
  453 +) DEFAULT NULL,
  454 + "start_time" timestamp DEFAULT NULL,
  455 + "end_time" timestamp DEFAULT NULL,
  456 + "creator" varchar
  457 +(
  458 + 64
  459 +) DEFAULT '',
  460 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  461 + "updater" varchar
  462 +(
  463 + 64
  464 +) DEFAULT '',
  465 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  466 + "deleted" bit NOT NULL DEFAULT FALSE,
  467 + "tenant_id" bigint NOT NULL DEFAULT '0',
  468 + PRIMARY KEY
  469 +(
  470 + "id"
  471 +)
  472 + ) COMMENT 'IoT OTA 升级记录表';