refactor:【IoT 物联网】重命名 RuleScene => SceneRule

This commit is contained in:
puhui999 2025-08-11 11:53:35 +08:00
parent 2e5aa3d6ec
commit 4c051620b1
22 changed files with 328 additions and 329 deletions

View File

@ -4,12 +4,12 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotSceneRulePageReqVO;
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneRespVO; import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotSceneRuleRespVO;
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO; import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotSceneRuleSaveReqVO;
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneUpdateStatusReqVO; import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotSceneRuleUpdateStatusReqVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.service.rule.scene.IotRuleSceneService; import cn.iocoder.yudao.module.iot.service.rule.scene.IotSceneRuleService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@ -24,71 +24,70 @@ import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
// TODO @puhui999SceneRule 方法名类名等
@Tag(name = "管理后台 - IoT 场景联动") @Tag(name = "管理后台 - IoT 场景联动")
@RestController @RestController
@RequestMapping("/iot/rule-scene") @RequestMapping("/iot/scene-rule")
@Validated @Validated
public class IotRuleSceneController { public class IotSceneRuleController {
@Resource @Resource
private IotRuleSceneService ruleSceneService; private IotSceneRuleService sceneRuleService;
@PostMapping("/create") @PostMapping("/create")
@Operation(summary = "创建场景联动") @Operation(summary = "创建场景联动")
@PreAuthorize("@ss.hasPermission('iot:rule-scene:create')") @PreAuthorize("@ss.hasPermission('iot:scene-rule:create')")
public CommonResult<Long> createRuleScene(@Valid @RequestBody IotRuleSceneSaveReqVO createReqVO) { public CommonResult<Long> createSceneRule(@Valid @RequestBody IotSceneRuleSaveReqVO createReqVO) {
return success(ruleSceneService.createRuleScene(createReqVO)); return success(sceneRuleService.createSceneRule(createReqVO));
} }
@PutMapping("/update") @PutMapping("/update")
@Operation(summary = "更新场景联动") @Operation(summary = "更新场景联动")
@PreAuthorize("@ss.hasPermission('iot:rule-scene:update')") @PreAuthorize("@ss.hasPermission('iot:scene-rule:update')")
public CommonResult<Boolean> updateRuleScene(@Valid @RequestBody IotRuleSceneSaveReqVO updateReqVO) { public CommonResult<Boolean> updateSceneRule(@Valid @RequestBody IotSceneRuleSaveReqVO updateReqVO) {
ruleSceneService.updateRuleScene(updateReqVO); sceneRuleService.updateSceneRule(updateReqVO);
return success(true); return success(true);
} }
@PutMapping("/update-status") @PutMapping("/update-status")
@Operation(summary = "更新场景联动状态") @Operation(summary = "更新场景联动状态")
@PreAuthorize("@ss.hasPermission('iot:rule-scene:update')") @PreAuthorize("@ss.hasPermission('iot:scene-rule:update')")
public CommonResult<Boolean> updateRuleSceneStatus(@Valid @RequestBody IotRuleSceneUpdateStatusReqVO updateReqVO) { public CommonResult<Boolean> updateSceneRuleStatus(@Valid @RequestBody IotSceneRuleUpdateStatusReqVO updateReqVO) {
ruleSceneService.updateRuleSceneStatus(updateReqVO.getId(), updateReqVO.getStatus()); sceneRuleService.updateSceneRuleStatus(updateReqVO.getId(), updateReqVO.getStatus());
return success(true); return success(true);
} }
@DeleteMapping("/delete") @DeleteMapping("/delete")
@Operation(summary = "删除场景联动") @Operation(summary = "删除场景联动")
@Parameter(name = "id", description = "编号", required = true) @Parameter(name = "id", description = "编号", required = true)
@PreAuthorize("@ss.hasPermission('iot:rule-scene:delete')") @PreAuthorize("@ss.hasPermission('iot:scene-rule:delete')")
public CommonResult<Boolean> deleteRuleScene(@RequestParam("id") Long id) { public CommonResult<Boolean> deleteSceneRule(@RequestParam("id") Long id) {
ruleSceneService.deleteRuleScene(id); sceneRuleService.deleteSceneRule(id);
return success(true); return success(true);
} }
@GetMapping("/get") @GetMapping("/get")
@Operation(summary = "获得场景联动") @Operation(summary = "获得场景联动")
@Parameter(name = "id", description = "编号", required = true, example = "1024") @Parameter(name = "id", description = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('iot:rule-scene:query')") @PreAuthorize("@ss.hasPermission('iot:scene-rule:query')")
public CommonResult<IotRuleSceneRespVO> getRuleScene(@RequestParam("id") Long id) { public CommonResult<IotSceneRuleRespVO> getSceneRule(@RequestParam("id") Long id) {
IotSceneRuleDO ruleScene = ruleSceneService.getRuleScene(id); IotSceneRuleDO sceneRule = sceneRuleService.getSceneRule(id);
return success(BeanUtils.toBean(ruleScene, IotRuleSceneRespVO.class)); return success(BeanUtils.toBean(sceneRule, IotSceneRuleRespVO.class));
} }
@GetMapping("/page") @GetMapping("/page")
@Operation(summary = "获得场景联动分页") @Operation(summary = "获得场景联动分页")
@PreAuthorize("@ss.hasPermission('iot:rule-scene:query')") @PreAuthorize("@ss.hasPermission('iot:scene-rule:query')")
public CommonResult<PageResult<IotRuleSceneRespVO>> getRuleScenePage(@Valid IotRuleScenePageReqVO pageReqVO) { public CommonResult<PageResult<IotSceneRuleRespVO>> getSceneRulePage(@Valid IotSceneRulePageReqVO pageReqVO) {
PageResult<IotSceneRuleDO> pageResult = ruleSceneService.getRuleScenePage(pageReqVO); PageResult<IotSceneRuleDO> pageResult = sceneRuleService.getSceneRulePage(pageReqVO);
return success(BeanUtils.toBean(pageResult, IotRuleSceneRespVO.class)); return success(BeanUtils.toBean(pageResult, IotSceneRuleRespVO.class));
} }
@GetMapping("/simple-list") @GetMapping("/simple-list")
@Operation(summary = "获取场景联动的精简信息列表", description = "主要用于前端的下拉选项") @Operation(summary = "获取场景联动的精简信息列表", description = "主要用于前端的下拉选项")
public CommonResult<List<IotRuleSceneRespVO>> getRuleSceneSimpleList() { public CommonResult<List<IotSceneRuleRespVO>> getSceneRuleSimpleList() {
List<IotSceneRuleDO> list = ruleSceneService.getRuleSceneListByStatus(CommonStatusEnum.ENABLE.getStatus()); List<IotSceneRuleDO> list = sceneRuleService.getSceneRuleListByStatus(CommonStatusEnum.ENABLE.getStatus());
return success(convertList(list, scene -> // 只返回 idname 字段 return success(convertList(list, scene -> // 只返回 idname 字段
new IotRuleSceneRespVO().setId(scene.getId()).setName(scene.getName()))); new IotSceneRuleRespVO().setId(scene.getId()).setName(scene.getName())));
} }
} }

View File

@ -17,7 +17,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true) @ToString(callSuper = true)
public class IotRuleScenePageReqVO extends PageParam { public class IotSceneRulePageReqVO extends PageParam {
@Schema(description = "场景名称", example = "赵六") @Schema(description = "场景名称", example = "赵六")
private String name; private String name;

View File

@ -9,7 +9,7 @@ import java.util.List;
@Schema(description = "管理后台 - IoT 场景联动 Response VO") @Schema(description = "管理后台 - IoT 场景联动 Response VO")
@Data @Data
public class IotRuleSceneRespVO { public class IotSceneRuleRespVO {
@Schema(description = "场景编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15865") @Schema(description = "场景编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15865")
private Long id; private Long id;

View File

@ -12,7 +12,7 @@ import java.util.List;
@Schema(description = "管理后台 - IoT 场景联动新增/修改 Request VO") @Schema(description = "管理后台 - IoT 场景联动新增/修改 Request VO")
@Data @Data
public class IotRuleSceneSaveReqVO { public class IotSceneRuleSaveReqVO {
@Schema(description = "场景编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15865") @Schema(description = "场景编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15865")
private Long id; private Long id;

View File

@ -8,7 +8,7 @@ import lombok.Data;
@Schema(description = "管理后台 - IoT 场景联动更新状态 Request VO") @Schema(description = "管理后台 - IoT 场景联动更新状态 Request VO")
@Data @Data
public class IotRuleSceneUpdateStatusReqVO { public class IotSceneRuleUpdateStatusReqVO {
@Schema(description = "场景联动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @Schema(description = "场景联动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "场景联动编号不能为空") @NotNull(message = "场景联动编号不能为空")

View File

@ -7,10 +7,10 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertConfigDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleActionTypeEnum;
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneConditionOperatorEnum; import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionOperatorEnum;
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneConditionTypeEnum; import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum;
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum; import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
@ -79,13 +79,13 @@ public class IotSceneRuleDO extends TenantBaseDO {
/** /**
* 场景事件类型 * 场景事件类型
* *
* 枚举 {@link IotRuleSceneTriggerTypeEnum} * 枚举 {@link IotSceneRuleTriggerTypeEnum}
* 1. {@link IotRuleSceneTriggerTypeEnum#DEVICE_STATE_UPDATE} operator 非空并且 value 为在线状态 * 1. {@link IotSceneRuleTriggerTypeEnum#DEVICE_STATE_UPDATE} operator 非空并且 value 为在线状态
* 2. {@link IotRuleSceneTriggerTypeEnum#DEVICE_PROPERTY_POST} * 2. {@link IotSceneRuleTriggerTypeEnum#DEVICE_PROPERTY_POST}
* {@link IotRuleSceneTriggerTypeEnum#DEVICE_EVENT_POST} identifieroperator 非空并且 value 为属性值 * {@link IotSceneRuleTriggerTypeEnum#DEVICE_EVENT_POST} identifieroperator 非空并且 value 为属性值
* 3. {@link IotRuleSceneTriggerTypeEnum#DEVICE_EVENT_POST} * 3. {@link IotSceneRuleTriggerTypeEnum#DEVICE_EVENT_POST}
* {@link IotRuleSceneTriggerTypeEnum#DEVICE_SERVICE_INVOKE} identifier 非空但是 operatorvalue 为空 * {@link IotSceneRuleTriggerTypeEnum#DEVICE_SERVICE_INVOKE} identifier 非空但是 operatorvalue 为空
* 4. {@link IotRuleSceneTriggerTypeEnum#TIMER} conditions 非空并且设备无关无需 productIddeviceId 字段 * 4. {@link IotSceneRuleTriggerTypeEnum#TIMER} conditions 非空并且设备无关无需 productIddeviceId 字段
*/ */
private Integer type; private Integer type;
@ -111,14 +111,14 @@ public class IotSceneRuleDO extends TenantBaseDO {
/** /**
* 操作符 * 操作符
* *
* 枚举 {@link IotRuleSceneConditionOperatorEnum} * 枚举 {@link IotSceneRuleConditionOperatorEnum}
*/ */
private String operator; private String operator;
/** /**
* 参数属性值在线状态 * 参数属性值在线状态
* <p> * <p>
* 如果有多个值则使用 "," 分隔类似 "1,2,3" * 如果有多个值则使用 "," 分隔类似 "1,2,3"
* 例如说{@link IotRuleSceneConditionOperatorEnum#IN}{@link IotRuleSceneConditionOperatorEnum#BETWEEN} * 例如说{@link IotSceneRuleConditionOperatorEnum#IN}{@link IotSceneRuleConditionOperatorEnum#BETWEEN}
*/ */
private String value; private String value;
@ -148,10 +148,10 @@ public class IotSceneRuleDO extends TenantBaseDO {
/** /**
* 触发条件类型 * 触发条件类型
* *
* 枚举 {@link IotRuleSceneConditionTypeEnum} * 枚举 {@link IotSceneRuleConditionTypeEnum}
* 1. {@link IotRuleSceneConditionTypeEnum#DEVICE_STATE} operator 非空并且 value 为在线状态 * 1. {@link IotSceneRuleConditionTypeEnum#DEVICE_STATE} operator 非空并且 value 为在线状态
* 2. {@link IotRuleSceneConditionTypeEnum#DEVICE_PROPERTY} identifieroperator 非空并且 value 为属性值 * 2. {@link IotSceneRuleConditionTypeEnum#DEVICE_PROPERTY} identifieroperator 非空并且 value 为属性值
* 3. {@link IotRuleSceneConditionTypeEnum#CURRENT_TIME} operator 非空使用 DATE_TIME_ TIME_ 部分并且 value 非空 * 3. {@link IotSceneRuleConditionTypeEnum#CURRENT_TIME} operator 非空使用 DATE_TIME_ TIME_ 部分并且 value 非空
*/ */
private Integer type; private Integer type;
@ -176,14 +176,14 @@ public class IotSceneRuleDO extends TenantBaseDO {
/** /**
* 操作符 * 操作符
* *
* 枚举 {@link IotRuleSceneConditionOperatorEnum} * 枚举 {@link IotSceneRuleConditionOperatorEnum}
*/ */
private String operator; private String operator;
/** /**
* 参数 * 参数
* *
* 如果有多个值则使用 "," 分隔类似 "1,2,3" * 如果有多个值则使用 "," 分隔类似 "1,2,3"
* 例如说{@link IotRuleSceneConditionOperatorEnum#IN}{@link IotRuleSceneConditionOperatorEnum#BETWEEN} * 例如说{@link IotSceneRuleConditionOperatorEnum#IN}{@link IotSceneRuleConditionOperatorEnum#BETWEEN}
*/ */
private String param; private String param;
@ -198,11 +198,11 @@ public class IotSceneRuleDO extends TenantBaseDO {
/** /**
* 执行类型 * 执行类型
* *
* 枚举 {@link IotRuleSceneActionTypeEnum} * 枚举 {@link IotSceneRuleActionTypeEnum}
* 1. {@link IotRuleSceneActionTypeEnum#DEVICE_PROPERTY_SET} params 非空 * 1. {@link IotSceneRuleActionTypeEnum#DEVICE_PROPERTY_SET} params 非空
* {@link IotRuleSceneActionTypeEnum#DEVICE_SERVICE_INVOKE} params 非空 * {@link IotSceneRuleActionTypeEnum#DEVICE_SERVICE_INVOKE} params 非空
* 2. {@link IotRuleSceneActionTypeEnum#ALERT_TRIGGER} alertConfigId 为空因为是 {@link IotAlertConfigDO} 里面关联它 * 2. {@link IotSceneRuleActionTypeEnum#ALERT_TRIGGER} alertConfigId 为空因为是 {@link IotAlertConfigDO} 里面关联它
* 3. {@link IotRuleSceneActionTypeEnum#ALERT_RECOVER} alertConfigId 非空 * 3. {@link IotSceneRuleActionTypeEnum#ALERT_RECOVER} alertConfigId 非空
*/ */
private Integer type; private Integer type;

View File

@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.dal.mysql.rule;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotSceneRulePageReqVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
@ -15,9 +15,9 @@ import java.util.List;
* @author HUIHUI * @author HUIHUI
*/ */
@Mapper @Mapper
public interface IotRuleSceneMapper extends BaseMapperX<IotSceneRuleDO> { public interface IotSceneRuleMapper extends BaseMapperX<IotSceneRuleDO> {
default PageResult<IotSceneRuleDO> selectPage(IotRuleScenePageReqVO reqVO) { default PageResult<IotSceneRuleDO> selectPage(IotSceneRulePageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<IotSceneRuleDO>() return selectPage(reqVO, new LambdaQueryWrapperX<IotSceneRuleDO>()
.likeIfPresent(IotSceneRuleDO::getName, reqVO.getName()) .likeIfPresent(IotSceneRuleDO::getName, reqVO.getName())
.likeIfPresent(IotSceneRuleDO::getDescription, reqVO.getDescription()) .likeIfPresent(IotSceneRuleDO::getDescription, reqVO.getDescription())

View File

@ -14,7 +14,7 @@ import java.util.Arrays;
*/ */
@RequiredArgsConstructor @RequiredArgsConstructor
@Getter @Getter
public enum IotRuleSceneActionTypeEnum implements ArrayValuable<Integer> { public enum IotSceneRuleActionTypeEnum implements ArrayValuable<Integer> {
/** /**
* 设备属性设置 * 设备属性设置
@ -42,7 +42,7 @@ public enum IotRuleSceneActionTypeEnum implements ArrayValuable<Integer> {
private final Integer type; private final Integer type;
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotRuleSceneActionTypeEnum::getType).toArray(Integer[]::new); public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotSceneRuleActionTypeEnum::getType).toArray(Integer[]::new);
@Override @Override
public Integer[] array() { public Integer[] array() {

View File

@ -14,7 +14,7 @@ import java.util.Arrays;
*/ */
@RequiredArgsConstructor @RequiredArgsConstructor
@Getter @Getter
public enum IotRuleSceneConditionOperatorEnum implements ArrayValuable<String> { public enum IotSceneRuleConditionOperatorEnum implements ArrayValuable<String> {
EQUALS("=", "#source == #value"), EQUALS("=", "#source == #value"),
NOT_EQUALS("!=", "!(#source == #value)"), NOT_EQUALS("!=", "!(#source == #value)"),
@ -53,7 +53,7 @@ public enum IotRuleSceneConditionOperatorEnum implements ArrayValuable<String> {
private final String operator; private final String operator;
private final String springExpression; private final String springExpression;
public static final String[] ARRAYS = Arrays.stream(values()).map(IotRuleSceneConditionOperatorEnum::getOperator).toArray(String[]::new); public static final String[] ARRAYS = Arrays.stream(values()).map(IotSceneRuleConditionOperatorEnum::getOperator).toArray(String[]::new);
/** /**
* Spring 表达式 - 原始值 * Spring 表达式 - 原始值
@ -68,7 +68,7 @@ public enum IotRuleSceneConditionOperatorEnum implements ArrayValuable<String> {
*/ */
public static final String SPRING_EXPRESSION_VALUE_LIST = "values"; public static final String SPRING_EXPRESSION_VALUE_LIST = "values";
public static IotRuleSceneConditionOperatorEnum operatorOf(String operator) { public static IotSceneRuleConditionOperatorEnum operatorOf(String operator) {
return ArrayUtil.firstMatch(item -> item.getOperator().equals(operator), values()); return ArrayUtil.firstMatch(item -> item.getOperator().equals(operator), values());
} }

View File

@ -13,7 +13,7 @@ import java.util.Arrays;
*/ */
@RequiredArgsConstructor @RequiredArgsConstructor
@Getter @Getter
public enum IotRuleSceneConditionTypeEnum implements ArrayValuable<Integer> { public enum IotSceneRuleConditionTypeEnum implements ArrayValuable<Integer> {
DEVICE_STATE(1, "设备状态"), DEVICE_STATE(1, "设备状态"),
DEVICE_PROPERTY(2, "设备属性"), DEVICE_PROPERTY(2, "设备属性"),
@ -25,7 +25,7 @@ public enum IotRuleSceneConditionTypeEnum implements ArrayValuable<Integer> {
private final Integer type; private final Integer type;
private final String name; private final String name;
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotRuleSceneConditionTypeEnum::getType).toArray(Integer[]::new); public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotSceneRuleConditionTypeEnum::getType).toArray(Integer[]::new);
@Override @Override
public Integer[] array() { public Integer[] array() {

View File

@ -16,7 +16,7 @@ import java.util.Arrays;
*/ */
@RequiredArgsConstructor @RequiredArgsConstructor
@Getter @Getter
public enum IotRuleSceneTriggerTypeEnum implements ArrayValuable<Integer> { public enum IotSceneRuleTriggerTypeEnum implements ArrayValuable<Integer> {
@Deprecated @Deprecated
DEVICE(1), // 设备触发 // TODO @puhui999@芋艿这个可以作废 DEVICE(1), // 设备触发 // TODO @puhui999@芋艿这个可以作废
@ -56,7 +56,7 @@ public enum IotRuleSceneTriggerTypeEnum implements ArrayValuable<Integer> {
private final Integer type; private final Integer type;
public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotRuleSceneTriggerTypeEnum::getType).toArray(Integer[]::new); public static final Integer[] ARRAYS = Arrays.stream(values()).map(IotSceneRuleTriggerTypeEnum::getType).toArray(Integer[]::new);
@Override @Override
public Integer[] array() { public Integer[] array() {

View File

@ -1,58 +0,0 @@
package cn.iocoder.yudao.module.iot.job.rule;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum;
import cn.iocoder.yudao.module.iot.service.rule.scene.IotRuleSceneService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.util.Map;
/**
* IoT 规则场景 Job用于执行 {@link IotRuleSceneTriggerTypeEnum#TIMER} 类型的规则场景
*
* @author 芋道源码
*/
@Slf4j
public class IotRuleSceneJob extends QuartzJobBean {
/**
* JobData Key - 规则场景编号
*/
public static final String JOB_DATA_KEY_RULE_SCENE_ID = "ruleSceneId";
@Resource
private IotRuleSceneService ruleSceneService;
@Override
protected void executeInternal(JobExecutionContext context) {
// 获得规则场景编号
Long ruleSceneId = context.getMergedJobDataMap().getLong(JOB_DATA_KEY_RULE_SCENE_ID);
// 执行规则场景
ruleSceneService.executeRuleSceneByTimer(ruleSceneId);
}
/**
* 创建 JobData Map
*
* @param ruleSceneId 规则场景编号
* @return JobData Map
*/
public static Map<String, Object> buildJobDataMap(Long ruleSceneId) {
return MapUtil.of(JOB_DATA_KEY_RULE_SCENE_ID, ruleSceneId);
}
/**
* 创建 Job 名字
*
* @param ruleSceneId 规则场景编号
* @return Job 名字
*/
public static String buildJobName(Long ruleSceneId) {
return String.format("%s_%d", IotRuleSceneJob.class.getSimpleName(), ruleSceneId);
}
}

View File

@ -0,0 +1,58 @@
package cn.iocoder.yudao.module.iot.job.rule;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
import cn.iocoder.yudao.module.iot.service.rule.scene.IotSceneRuleService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobExecutionContext;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.util.Map;
/**
* IoT 规则场景 Job用于执行 {@link IotSceneRuleTriggerTypeEnum#TIMER} 类型的规则场景
*
* @author 芋道源码
*/
@Slf4j
public class IotSceneRuleJob extends QuartzJobBean {
/**
* JobData Key - 规则场景编号
*/
public static final String JOB_DATA_KEY_RULE_SCENE_ID = "sceneRuleId";
@Resource
private IotSceneRuleService sceneRuleService;
@Override
protected void executeInternal(JobExecutionContext context) {
// 获得规则场景编号
Long sceneRuleId = context.getMergedJobDataMap().getLong(JOB_DATA_KEY_RULE_SCENE_ID);
// 执行规则场景
sceneRuleService.executeSceneRuleByTimer(sceneRuleId);
}
/**
* 创建 JobData Map
*
* @param sceneRuleId 规则场景编号
* @return JobData Map
*/
public static Map<String, Object> buildJobDataMap(Long sceneRuleId) {
return MapUtil.of(JOB_DATA_KEY_RULE_SCENE_ID, sceneRuleId);
}
/**
* 创建 Job 名字
*
* @param sceneRuleId 规则场景编号
* @return Job 名字
*/
public static String buildJobName(Long sceneRuleId) {
return String.format("%s_%d", IotSceneRuleJob.class.getSimpleName(), sceneRuleId);
}
}

View File

@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.mq.consumer.rule;
import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus; import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageBus;
import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber; import cn.iocoder.yudao.module.iot.core.messagebus.core.IotMessageSubscriber;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.service.rule.scene.IotRuleSceneService; import cn.iocoder.yudao.module.iot.service.rule.scene.IotSceneRuleService;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -17,10 +17,10 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@Slf4j @Slf4j
public class IotRuleSceneMessageHandler implements IotMessageSubscriber<IotDeviceMessage> { public class IotSceneRuleMessageHandler implements IotMessageSubscriber<IotDeviceMessage> {
@Resource @Resource
private IotRuleSceneService ruleSceneService; private IotSceneRuleService sceneRuleService;
@Resource @Resource
private IotMessageBus messageBus; private IotMessageBus messageBus;
@ -46,7 +46,7 @@ public class IotRuleSceneMessageHandler implements IotMessageSubscriber<IotDevic
return; return;
} }
log.info("[onMessage][消息内容({})]", message); log.info("[onMessage][消息内容({})]", message);
ruleSceneService.executeRuleSceneByDevice(message); sceneRuleService.executeSceneRuleByDevice(message);
} }
} }

View File

@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.iot.controller.admin.alert.vo.config.IotAlertConf
import cn.iocoder.yudao.module.iot.controller.admin.alert.vo.config.IotAlertConfigSaveReqVO; import cn.iocoder.yudao.module.iot.controller.admin.alert.vo.config.IotAlertConfigSaveReqVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertConfigDO; import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertConfigDO;
import cn.iocoder.yudao.module.iot.dal.mysql.alert.IotAlertConfigMapper; import cn.iocoder.yudao.module.iot.dal.mysql.alert.IotAlertConfigMapper;
import cn.iocoder.yudao.module.iot.service.rule.scene.IotRuleSceneService; import cn.iocoder.yudao.module.iot.service.rule.scene.IotSceneRuleService;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
@ -32,7 +32,7 @@ public class IotAlertConfigServiceImpl implements IotAlertConfigService {
@Resource @Resource
@Lazy // 延迟避免循环依赖报错 @Lazy // 延迟避免循环依赖报错
private IotRuleSceneService ruleSceneService; private IotSceneRuleService sceneRuleService;
@Resource @Resource
private AdminUserApi adminUserApi; private AdminUserApi adminUserApi;
@ -40,7 +40,7 @@ public class IotAlertConfigServiceImpl implements IotAlertConfigService {
@Override @Override
public Long createAlertConfig(IotAlertConfigSaveReqVO createReqVO) { public Long createAlertConfig(IotAlertConfigSaveReqVO createReqVO) {
// 校验关联数据是否存在 // 校验关联数据是否存在
ruleSceneService.validateRuleSceneList(createReqVO.getSceneRuleIds()); sceneRuleService.validateSceneRuleList(createReqVO.getSceneRuleIds());
adminUserApi.validateUserList(createReqVO.getReceiveUserIds()); adminUserApi.validateUserList(createReqVO.getReceiveUserIds());
// 插入 // 插入
@ -54,7 +54,7 @@ public class IotAlertConfigServiceImpl implements IotAlertConfigService {
// 校验存在 // 校验存在
validateAlertConfigExists(updateReqVO.getId()); validateAlertConfigExists(updateReqVO.getId());
// 校验关联数据是否存在 // 校验关联数据是否存在
ruleSceneService.validateRuleSceneList(updateReqVO.getSceneRuleIds()); sceneRuleService.validateSceneRuleList(updateReqVO.getSceneRuleIds());
adminUserApi.validateUserList(updateReqVO.getReceiveUserIds()); adminUserApi.validateUserList(updateReqVO.getReceiveUserIds());
// 更新 // 更新

View File

@ -1,11 +1,11 @@
package cn.iocoder.yudao.module.iot.service.rule.scene; package cn.iocoder.yudao.module.iot.service.rule.scene;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotSceneRulePageReqVO;
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO; import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotSceneRuleSaveReqVO;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum; import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import java.util.Collection; import java.util.Collection;
@ -16,7 +16,7 @@ import java.util.List;
* *
* @author 芋道源码 * @author 芋道源码
*/ */
public interface IotRuleSceneService { public interface IotSceneRuleService {
/** /**
* 创建场景联动 * 创建场景联动
@ -24,14 +24,14 @@ public interface IotRuleSceneService {
* @param createReqVO 创建信息 * @param createReqVO 创建信息
* @return 编号 * @return 编号
*/ */
Long createRuleScene(@Valid IotRuleSceneSaveReqVO createReqVO); Long createSceneRule(@Valid IotSceneRuleSaveReqVO createReqVO);
/** /**
* 更新场景联动 * 更新场景联动
* *
* @param updateReqVO 更新信息 * @param updateReqVO 更新信息
*/ */
void updateRuleScene(@Valid IotRuleSceneSaveReqVO updateReqVO); void updateSceneRule(@Valid IotSceneRuleSaveReqVO updateReqVO);
/** /**
* 更新场景联动状态 * 更新场景联动状态
@ -39,14 +39,14 @@ public interface IotRuleSceneService {
* @param id 场景联动编号 * @param id 场景联动编号
* @param status 状态 * @param status 状态
*/ */
void updateRuleSceneStatus(Long id, Integer status); void updateSceneRuleStatus(Long id, Integer status);
/** /**
* 删除场景联动 * 删除场景联动
* *
* @param id 编号 * @param id 编号
*/ */
void deleteRuleScene(Long id); void deleteSceneRule(Long id);
/** /**
* 获得场景联动 * 获得场景联动
@ -54,7 +54,7 @@ public interface IotRuleSceneService {
* @param id 编号 * @param id 编号
* @return 场景联动 * @return 场景联动
*/ */
IotSceneRuleDO getRuleScene(Long id); IotSceneRuleDO getSceneRule(Long id);
/** /**
* 获得场景联动分页 * 获得场景联动分页
@ -62,7 +62,7 @@ public interface IotRuleSceneService {
* @param pageReqVO 分页查询 * @param pageReqVO 分页查询
* @return 场景联动分页 * @return 场景联动分页
*/ */
PageResult<IotSceneRuleDO> getRuleScenePage(IotRuleScenePageReqVO pageReqVO); PageResult<IotSceneRuleDO> getSceneRulePage(IotSceneRulePageReqVO pageReqVO);
/** /**
* 校验规则场景联动规则编号们是否存在如下情况视为无效 * 校验规则场景联动规则编号们是否存在如下情况视为无效
@ -70,7 +70,7 @@ public interface IotRuleSceneService {
* *
* @param ids 场景联动规则编号数组 * @param ids 场景联动规则编号数组
*/ */
void validateRuleSceneList(Collection<Long> ids); void validateSceneRuleList(Collection<Long> ids);
/** /**
* 获得指定状态的场景联动列表 * 获得指定状态的场景联动列表
@ -78,7 +78,7 @@ public interface IotRuleSceneService {
* @param status 状态 * @param status 状态
* @return 场景联动列表 * @return 场景联动列表
*/ */
List<IotSceneRuleDO> getRuleSceneListByStatus(Integer status); List<IotSceneRuleDO> getSceneRuleListByStatus(Integer status);
/** /**
* 缓存获得指定设备的场景列表 * 缓存获得指定设备的场景列表
@ -87,20 +87,20 @@ public interface IotRuleSceneService {
* @param deviceName 设备名称 * @param deviceName 设备名称
* @return 场景列表 * @return 场景列表
*/ */
List<IotSceneRuleDO> getRuleSceneListByProductKeyAndDeviceNameFromCache(String productKey, String deviceName); List<IotSceneRuleDO> getSceneRuleListByProductKeyAndDeviceNameFromCache(String productKey, String deviceName);
/** /**
* 基于 {@link IotRuleSceneTriggerTypeEnum#DEVICE} 场景执行规则场景 * 基于 {@link IotSceneRuleTriggerTypeEnum#DEVICE} 场景执行规则场景
* *
* @param message 消息 * @param message 消息
*/ */
void executeRuleSceneByDevice(IotDeviceMessage message); void executeSceneRuleByDevice(IotDeviceMessage message);
/** /**
* 基于 {@link IotRuleSceneTriggerTypeEnum#TIMER} 场景执行规则场景 * 基于 {@link IotSceneRuleTriggerTypeEnum#TIMER} 场景执行规则场景
* *
* @param id 场景联动规则编号 * @param id 场景联动规则编号
*/ */
void executeRuleSceneByTimer(Long id); void executeSceneRuleByTimer(Long id);
} }

View File

@ -15,17 +15,17 @@ import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils; import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleScenePageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotSceneRulePageReqVO;
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO; import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotSceneRuleSaveReqVO;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils; import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils;
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotRuleSceneMapper; import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotSceneRuleMapper;
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneConditionOperatorEnum; import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionOperatorEnum;
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneConditionTypeEnum; import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleConditionTypeEnum;
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum; import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleTriggerTypeEnum;
import cn.iocoder.yudao.module.iot.framework.job.core.IotSchedulerManager; import cn.iocoder.yudao.module.iot.framework.job.core.IotSchedulerManager;
import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
import cn.iocoder.yudao.module.iot.service.product.IotProductService; import cn.iocoder.yudao.module.iot.service.product.IotProductService;
@ -53,13 +53,13 @@ import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.RULE_SCENE_NO
@Service @Service
@Validated @Validated
@Slf4j @Slf4j
public class IotRuleSceneServiceImpl implements IotRuleSceneService { public class IotSceneRuleServiceImpl implements IotSceneRuleService {
@Resource @Resource
private IotRuleSceneMapper ruleSceneMapper; private IotSceneRuleMapper sceneRuleMapper;
@Resource @Resource
private List<IotSceneRuleAction> ruleSceneActions; private List<IotSceneRuleAction> sceneRuleActions;
@Resource(name = "iotSchedulerManager") @Resource(name = "iotSchedulerManager")
private IotSchedulerManager schedulerManager; private IotSchedulerManager schedulerManager;
@ -71,90 +71,90 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
private IotDeviceService deviceService; private IotDeviceService deviceService;
@Override @Override
public Long createRuleScene(IotRuleSceneSaveReqVO createReqVO) { public Long createSceneRule(IotSceneRuleSaveReqVO createReqVO) {
IotSceneRuleDO ruleScene = BeanUtils.toBean(createReqVO, IotSceneRuleDO.class); IotSceneRuleDO sceneRule = BeanUtils.toBean(createReqVO, IotSceneRuleDO.class);
ruleSceneMapper.insert(ruleScene); sceneRuleMapper.insert(sceneRule);
return ruleScene.getId(); return sceneRule.getId();
} }
@Override @Override
public void updateRuleScene(IotRuleSceneSaveReqVO updateReqVO) { public void updateSceneRule(IotSceneRuleSaveReqVO updateReqVO) {
// 校验存在 // 校验存在
validateRuleSceneExists(updateReqVO.getId()); validateSceneRuleExists(updateReqVO.getId());
// 更新 // 更新
IotSceneRuleDO updateObj = BeanUtils.toBean(updateReqVO, IotSceneRuleDO.class); IotSceneRuleDO updateObj = BeanUtils.toBean(updateReqVO, IotSceneRuleDO.class);
ruleSceneMapper.updateById(updateObj); sceneRuleMapper.updateById(updateObj);
} }
@Override @Override
public void updateRuleSceneStatus(Long id, Integer status) { public void updateSceneRuleStatus(Long id, Integer status) {
// 校验存在 // 校验存在
validateRuleSceneExists(id); validateSceneRuleExists(id);
// 更新状态 // 更新状态
IotSceneRuleDO updateObj = new IotSceneRuleDO().setId(id).setStatus(status); IotSceneRuleDO updateObj = new IotSceneRuleDO().setId(id).setStatus(status);
ruleSceneMapper.updateById(updateObj); sceneRuleMapper.updateById(updateObj);
} }
@Override @Override
public void deleteRuleScene(Long id) { public void deleteSceneRule(Long id) {
// 校验存在 // 校验存在
validateRuleSceneExists(id); validateSceneRuleExists(id);
// 删除 // 删除
ruleSceneMapper.deleteById(id); sceneRuleMapper.deleteById(id);
} }
private void validateRuleSceneExists(Long id) { private void validateSceneRuleExists(Long id) {
if (ruleSceneMapper.selectById(id) == null) { if (sceneRuleMapper.selectById(id) == null) {
throw exception(RULE_SCENE_NOT_EXISTS); throw exception(RULE_SCENE_NOT_EXISTS);
} }
} }
@Override @Override
public IotSceneRuleDO getRuleScene(Long id) { public IotSceneRuleDO getSceneRule(Long id) {
return ruleSceneMapper.selectById(id); return sceneRuleMapper.selectById(id);
} }
@Override @Override
public PageResult<IotSceneRuleDO> getRuleScenePage(IotRuleScenePageReqVO pageReqVO) { public PageResult<IotSceneRuleDO> getSceneRulePage(IotSceneRulePageReqVO pageReqVO) {
return ruleSceneMapper.selectPage(pageReqVO); return sceneRuleMapper.selectPage(pageReqVO);
} }
@Override @Override
public void validateRuleSceneList(Collection<Long> ids) { public void validateSceneRuleList(Collection<Long> ids) {
if (CollUtil.isEmpty(ids)) { if (CollUtil.isEmpty(ids)) {
return; return;
} }
// 批量查询存在的规则场景 // 批量查询存在的规则场景
List<IotSceneRuleDO> existingScenes = ruleSceneMapper.selectByIds(ids); List<IotSceneRuleDO> existingScenes = sceneRuleMapper.selectByIds(ids);
if (existingScenes.size() != ids.size()) { if (existingScenes.size() != ids.size()) {
throw exception(RULE_SCENE_NOT_EXISTS); throw exception(RULE_SCENE_NOT_EXISTS);
} }
} }
@Override @Override
public List<IotSceneRuleDO> getRuleSceneListByStatus(Integer status) { public List<IotSceneRuleDO> getSceneRuleListByStatus(Integer status) {
return ruleSceneMapper.selectListByStatus(status); return sceneRuleMapper.selectListByStatus(status);
} }
// TODO 芋艿缓存待实现 // TODO 芋艿缓存待实现
@Override @Override
@TenantIgnore // 忽略租户隔离因为 IotRuleSceneMessageHandler 调用时一般未传递租户所以需要忽略 @TenantIgnore // 忽略租户隔离因为 IotSceneRuleMessageHandler 调用时一般未传递租户所以需要忽略
public List<IotSceneRuleDO> getRuleSceneListByProductKeyAndDeviceNameFromCache(String productKey, String deviceName) { public List<IotSceneRuleDO> getSceneRuleListByProductKeyAndDeviceNameFromCache(String productKey, String deviceName) {
// TODO @puhui999一些注释看看要不要优化下 // TODO @puhui999一些注释看看要不要优化下
// 注意旧的测试代码已删除因为使用了废弃的数据结构 // 注意旧的测试代码已删除因为使用了废弃的数据结构
// 如需测试请使用上面的新结构测试代码示例 // 如需测试请使用上面的新结构测试代码示例
List<IotSceneRuleDO> list = ruleSceneMapper.selectList(); List<IotSceneRuleDO> list = sceneRuleMapper.selectList();
// 只返回启用状态的规则场景 // 只返回启用状态的规则场景
List<IotSceneRuleDO> enabledList = filterList(list, List<IotSceneRuleDO> enabledList = filterList(list,
ruleScene -> CommonStatusEnum.ENABLE.getStatus().equals(ruleScene.getStatus())); sceneRule -> CommonStatusEnum.ENABLE.getStatus().equals(sceneRule.getStatus()));
// 根据 productKey deviceName 进行匹配 // 根据 productKey deviceName 进行匹配
return filterList(enabledList, ruleScene -> { return filterList(enabledList, sceneRule -> {
if (CollUtil.isEmpty(ruleScene.getTriggers())) { if (CollUtil.isEmpty(sceneRule.getTriggers())) {
return false; return false;
} }
for (IotSceneRuleDO.Trigger trigger : ruleScene.getTriggers()) { for (IotSceneRuleDO.Trigger trigger : sceneRule.getTriggers()) {
// 检查触发器是否匹配指定的产品和设备 // 检查触发器是否匹配指定的产品和设备
if (isMatchProductAndDevice(trigger, productKey, deviceName)) { if (isMatchProductAndDevice(trigger, productKey, deviceName)) {
return true; return true;
@ -210,43 +210,43 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
} }
@Override @Override
public void executeRuleSceneByDevice(IotDeviceMessage message) { public void executeSceneRuleByDevice(IotDeviceMessage message) {
// TODO @芋艿这里的 tenantId通过设备获取 // TODO @芋艿这里的 tenantId通过设备获取
TenantUtils.execute(message.getTenantId(), () -> { TenantUtils.execute(message.getTenantId(), () -> {
// 1. 获得设备匹配的规则场景 // 1. 获得设备匹配的规则场景
List<IotSceneRuleDO> ruleScenes = getMatchedRuleSceneListByMessage(message); List<IotSceneRuleDO> sceneRules = getMatchedSceneRuleListByMessage(message);
if (CollUtil.isEmpty(ruleScenes)) { if (CollUtil.isEmpty(sceneRules)) {
return; return;
} }
// 2. 执行规则场景 // 2. 执行规则场景
executeRuleSceneAction(message, ruleScenes); executeSceneRuleAction(message, sceneRules);
}); });
} }
@Override @Override
public void executeRuleSceneByTimer(Long id) { public void executeSceneRuleByTimer(Long id) {
// 1.1 获得规则场景 // 1.1 获得规则场景
IotSceneRuleDO scene = TenantUtils.executeIgnore(() -> ruleSceneMapper.selectById(id)); IotSceneRuleDO scene = TenantUtils.executeIgnore(() -> sceneRuleMapper.selectById(id));
if (scene == null) { if (scene == null) {
log.error("[executeRuleSceneByTimer][规则场景({}) 不存在]", id); log.error("[executeSceneRuleByTimer][规则场景({}) 不存在]", id);
return; return;
} }
if (CommonStatusEnum.isDisable(scene.getStatus())) { if (CommonStatusEnum.isDisable(scene.getStatus())) {
log.info("[executeRuleSceneByTimer][规则场景({}) 已被禁用]", id); log.info("[executeSceneRuleByTimer][规则场景({}) 已被禁用]", id);
return; return;
} }
// 1.2 判断是否有定时触发器避免脏数据 // 1.2 判断是否有定时触发器避免脏数据
IotSceneRuleDO.Trigger config = CollUtil.findOne(scene.getTriggers(), IotSceneRuleDO.Trigger config = CollUtil.findOne(scene.getTriggers(),
trigger -> ObjUtil.equals(trigger.getType(), IotRuleSceneTriggerTypeEnum.TIMER.getType())); trigger -> ObjUtil.equals(trigger.getType(), IotSceneRuleTriggerTypeEnum.TIMER.getType()));
if (config == null) { if (config == null) {
log.error("[executeRuleSceneByTimer][规则场景({}) 不存在定时触发器]", scene); log.error("[executeSceneRuleByTimer][规则场景({}) 不存在定时触发器]", scene);
return; return;
} }
// 2. 执行规则场景 // 2. 执行规则场景
TenantUtils.execute(scene.getTenantId(), TenantUtils.execute(scene.getTenantId(),
() -> executeRuleSceneAction(null, ListUtil.toList(scene))); () -> executeSceneRuleAction(null, ListUtil.toList(scene)));
} }
/** /**
@ -255,36 +255,36 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
* @param message 设备消息 * @param message 设备消息
* @return 规则场景列表 * @return 规则场景列表
*/ */
private List<IotSceneRuleDO> getMatchedRuleSceneListByMessage(IotDeviceMessage message) { private List<IotSceneRuleDO> getMatchedSceneRuleListByMessage(IotDeviceMessage message) {
// 1. 匹配设备 // 1. 匹配设备
// TODO @芋艿可能需要 getSelf(); 缓存 // TODO @芋艿可能需要 getSelf(); 缓存
// 1.1 通过 deviceId 获取设备信息 // 1.1 通过 deviceId 获取设备信息
IotDeviceDO device = deviceService.getDeviceFromCache(message.getDeviceId()); IotDeviceDO device = deviceService.getDeviceFromCache(message.getDeviceId());
if (device == null) { if (device == null) {
log.warn("[getMatchedRuleSceneListByMessage][设备({}) 不存在]", message.getDeviceId()); log.warn("[getMatchedSceneRuleListByMessage][设备({}) 不存在]", message.getDeviceId());
return List.of(); return List.of();
} }
// 1.2 通过 productId 获取产品信息 // 1.2 通过 productId 获取产品信息
IotProductDO product = productService.getProductFromCache(device.getProductId()); IotProductDO product = productService.getProductFromCache(device.getProductId());
if (product == null) { if (product == null) {
log.warn("[getMatchedRuleSceneListByMessage][产品({}) 不存在]", device.getProductId()); log.warn("[getMatchedSceneRuleListByMessage][产品({}) 不存在]", device.getProductId());
return List.of(); return List.of();
} }
// 1.3 获取匹配的规则场景 // 1.3 获取匹配的规则场景
List<IotSceneRuleDO> ruleScenes = getRuleSceneListByProductKeyAndDeviceNameFromCache( List<IotSceneRuleDO> sceneRules = getSceneRuleListByProductKeyAndDeviceNameFromCache(
product.getProductKey(), device.getDeviceName()); product.getProductKey(), device.getDeviceName());
if (CollUtil.isEmpty(ruleScenes)) { if (CollUtil.isEmpty(sceneRules)) {
return ruleScenes; return sceneRules;
} }
// 2. 匹配 trigger 触发器的条件 // 2. 匹配 trigger 触发器的条件
return filterList(ruleScenes, ruleScene -> { return filterList(sceneRules, sceneRule -> {
for (IotSceneRuleDO.Trigger trigger : ruleScene.getTriggers()) { for (IotSceneRuleDO.Trigger trigger : sceneRule.getTriggers()) {
// 2.1 检查触发器类型根据新的枚举值进行匹配 // 2.1 检查触发器类型根据新的枚举值进行匹配
// TODO @芋艿需要根据新的触发器类型枚举进行适配 // TODO @芋艿需要根据新的触发器类型枚举进行适配
// 原来使用 IotRuleSceneTriggerTypeEnum.DEVICE新结构可能有不同的类型 // 原来使用 IotSceneRuleTriggerTypeEnum.DEVICE新结构可能有不同的类型
// 2.2 条件分组为空说明没有匹配的条件因此不匹配 // 2.2 条件分组为空说明没有匹配的条件因此不匹配
if (CollUtil.isEmpty(trigger.getConditionGroups())) { if (CollUtil.isEmpty(trigger.getConditionGroups())) {
@ -303,7 +303,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
for (IotSceneRuleDO.TriggerCondition condition : conditionGroup) { for (IotSceneRuleDO.TriggerCondition condition : conditionGroup) {
// TODO @芋艿这里需要实现具体的条件匹配逻辑 // TODO @芋艿这里需要实现具体的条件匹配逻辑
// 根据新的 TriggerCondition 结构进行匹配 // 根据新的 TriggerCondition 结构进行匹配
if (!isTriggerConditionMatched(message, condition, ruleScene, trigger)) { if (!isTriggerConditionMatched(message, condition, sceneRule, trigger)) {
allConditionsMatched = false; allConditionsMatched = false;
break; break;
} }
@ -316,7 +316,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
} }
if (anyGroupMatched) { if (anyGroupMatched) {
log.info("[getMatchedRuleSceneList][消息({}) 匹配到规则场景编号({}) 的触发器({})]", message, ruleScene.getId(), trigger); log.info("[getMatchedSceneRuleList][消息({}) 匹配到规则场景编号({}) 的触发器({})]", message, sceneRule.getId(), trigger);
return true; return true;
} }
} }
@ -329,31 +329,31 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
* *
* @param message 设备消息 * @param message 设备消息
* @param condition 触发条件 * @param condition 触发条件
* @param ruleScene 规则场景用于日志无其它作用 * @param sceneRule 规则场景用于日志无其它作用
* @param trigger 触发器用于日志无其它作用 * @param trigger 触发器用于日志无其它作用
* @return 是否匹配 * @return 是否匹配
*/ */
private boolean isTriggerConditionMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition, private boolean isTriggerConditionMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition,
IotSceneRuleDO ruleScene, IotSceneRuleDO.Trigger trigger) { IotSceneRuleDO sceneRule, IotSceneRuleDO.Trigger trigger) {
try { try {
// 1. 根据条件类型进行匹配 // 1. 根据条件类型进行匹配
if (IotRuleSceneConditionTypeEnum.DEVICE_STATE.getType().equals(condition.getType())) { if (IotSceneRuleConditionTypeEnum.DEVICE_STATE.getType().equals(condition.getType())) {
// 设备状态条件匹配 // 设备状态条件匹配
return matchDeviceStateCondition(message, condition); return matchDeviceStateCondition(message, condition);
} else if (IotRuleSceneConditionTypeEnum.DEVICE_PROPERTY.getType().equals(condition.getType())) { } else if (IotSceneRuleConditionTypeEnum.DEVICE_PROPERTY.getType().equals(condition.getType())) {
// 设备属性条件匹配 // 设备属性条件匹配
return matchDevicePropertyCondition(message, condition); return matchDevicePropertyCondition(message, condition);
} else if (IotRuleSceneConditionTypeEnum.CURRENT_TIME.getType().equals(condition.getType())) { } else if (IotSceneRuleConditionTypeEnum.CURRENT_TIME.getType().equals(condition.getType())) {
// 当前时间条件匹配 // 当前时间条件匹配
return matchCurrentTimeCondition(condition); return matchCurrentTimeCondition(condition);
} else { } else {
log.warn("[isTriggerConditionMatched][规则场景编号({}) 的触发器({}) 存在未知的条件类型({})]", log.warn("[isTriggerConditionMatched][规则场景编号({}) 的触发器({}) 存在未知的条件类型({})]",
ruleScene.getId(), trigger, condition.getType()); sceneRule.getId(), trigger, condition.getType());
return false; return false;
} }
} catch (Exception e) { } catch (Exception e) {
log.error("[isTriggerConditionMatched][规则场景编号({}) 的触发器({}) 条件匹配异常]", log.error("[isTriggerConditionMatched][规则场景编号({}) 的触发器({}) 条件匹配异常]",
ruleScene.getId(), trigger, e); sceneRule.getId(), trigger, e);
return false; return false;
} }
} }
@ -420,7 +420,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
private boolean evaluateCondition(Object sourceValue, String operator, String paramValue) { private boolean evaluateCondition(Object sourceValue, String operator, String paramValue) {
try { try {
// 1. 校验操作符是否合法 // 1. 校验操作符是否合法
IotRuleSceneConditionOperatorEnum operatorEnum = IotRuleSceneConditionOperatorEnum.operatorOf(operator); IotSceneRuleConditionOperatorEnum operatorEnum = IotSceneRuleConditionOperatorEnum.operatorOf(operator);
if (operatorEnum == null) { if (operatorEnum == null) {
log.warn("[evaluateCondition][存在错误的操作符({})]", operator); log.warn("[evaluateCondition][存在错误的操作符({})]", operator);
return false; return false;
@ -428,22 +428,22 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
// 2.1 构建 Spring 表达式的变量 // 2.1 构建 Spring 表达式的变量
Map<String, Object> springExpressionVariables = MapUtil.<String, Object>builder() Map<String, Object> springExpressionVariables = MapUtil.<String, Object>builder()
.put(IotRuleSceneConditionOperatorEnum.SPRING_EXPRESSION_SOURCE, sourceValue) .put(IotSceneRuleConditionOperatorEnum.SPRING_EXPRESSION_SOURCE, sourceValue)
.build(); .build();
// 2.2 根据操作符类型处理参数值 // 2.2 根据操作符类型处理参数值
if (StrUtil.isNotBlank(paramValue)) { if (StrUtil.isNotBlank(paramValue)) {
// TODO @puhui999这里是不是在 IotRuleSceneConditionOperatorEnum 加个属性 // TODO @puhui999这里是不是在 IotSceneRuleConditionOperatorEnum 加个属性
if (operatorEnum == IotRuleSceneConditionOperatorEnum.IN if (operatorEnum == IotSceneRuleConditionOperatorEnum.IN
|| operatorEnum == IotRuleSceneConditionOperatorEnum.NOT_IN || operatorEnum == IotSceneRuleConditionOperatorEnum.NOT_IN
|| operatorEnum == IotRuleSceneConditionOperatorEnum.BETWEEN || operatorEnum == IotSceneRuleConditionOperatorEnum.BETWEEN
|| operatorEnum == IotRuleSceneConditionOperatorEnum.NOT_BETWEEN) { || operatorEnum == IotSceneRuleConditionOperatorEnum.NOT_BETWEEN) {
// 处理多值情况 // 处理多值情况
List<String> paramValues = StrUtil.split(paramValue, CharPool.COMMA); List<String> paramValues = StrUtil.split(paramValue, CharPool.COMMA);
springExpressionVariables.put(IotRuleSceneConditionOperatorEnum.SPRING_EXPRESSION_VALUE_LIST, springExpressionVariables.put(IotSceneRuleConditionOperatorEnum.SPRING_EXPRESSION_VALUE_LIST,
convertList(paramValues, NumberUtil::parseDouble)); convertList(paramValues, NumberUtil::parseDouble));
} else { } else {
// 处理单值情况 // 处理单值情况
springExpressionVariables.put(IotRuleSceneConditionOperatorEnum.SPRING_EXPRESSION_VALUE, springExpressionVariables.put(IotSceneRuleConditionOperatorEnum.SPRING_EXPRESSION_VALUE,
NumberUtil.parseDouble(paramValue)); NumberUtil.parseDouble(paramValue));
} }
} }
@ -464,19 +464,19 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
* *
* @param message 设备消息 * @param message 设备消息
* @param condition 触发条件 * @param condition 触发条件
* @param ruleScene 规则场景用于日志无其它作用 * @param sceneRule 规则场景用于日志无其它作用
* @param trigger 触发器用于日志无其它作用 * @param trigger 触发器用于日志无其它作用
* @return 是否匹配 * @return 是否匹配
*/ */
@SuppressWarnings({"unchecked", "DataFlowIssue"}) @SuppressWarnings({"unchecked", "DataFlowIssue"})
private boolean isTriggerConditionParameterMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition, private boolean isTriggerConditionParameterMatched(IotDeviceMessage message, IotSceneRuleDO.TriggerCondition condition,
IotSceneRuleDO ruleScene, IotSceneRuleDO.Trigger trigger) { IotSceneRuleDO sceneRule, IotSceneRuleDO.Trigger trigger) {
// 1.1 校验操作符是否合法 // 1.1 校验操作符是否合法
IotRuleSceneConditionOperatorEnum operator = IotSceneRuleConditionOperatorEnum operator =
IotRuleSceneConditionOperatorEnum.operatorOf(condition.getOperator()); IotSceneRuleConditionOperatorEnum.operatorOf(condition.getOperator());
if (operator == null) { if (operator == null) {
log.error("[isTriggerConditionParameterMatched][规则场景编号({}) 的触发器({}) 存在错误的操作符({})]", log.error("[isTriggerConditionParameterMatched][规则场景编号({}) 的触发器({}) 存在错误的操作符({})]",
ruleScene.getId(), trigger, condition.getOperator()); sceneRule.getId(), trigger, condition.getOperator());
return false; return false;
} }
// 1.2 校验消息是否包含对应的值 // 1.2 校验消息是否包含对应的值
@ -488,31 +488,31 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
// 2.1 构建 Spring 表达式的变量 // 2.1 构建 Spring 表达式的变量
Map<String, Object> springExpressionVariables = new HashMap<>(); Map<String, Object> springExpressionVariables = new HashMap<>();
try { try {
springExpressionVariables.put(IotRuleSceneConditionOperatorEnum.SPRING_EXPRESSION_SOURCE, messageValue); springExpressionVariables.put(IotSceneRuleConditionOperatorEnum.SPRING_EXPRESSION_SOURCE, messageValue);
springExpressionVariables.put(IotRuleSceneConditionOperatorEnum.SPRING_EXPRESSION_VALUE, condition.getParam()); springExpressionVariables.put(IotSceneRuleConditionOperatorEnum.SPRING_EXPRESSION_VALUE, condition.getParam());
List<String> parameterValues = StrUtil.splitTrim(condition.getParam(), CharPool.COMMA); List<String> parameterValues = StrUtil.splitTrim(condition.getParam(), CharPool.COMMA);
springExpressionVariables.put(IotRuleSceneConditionOperatorEnum.SPRING_EXPRESSION_VALUE_LIST, parameterValues); springExpressionVariables.put(IotSceneRuleConditionOperatorEnum.SPRING_EXPRESSION_VALUE_LIST, parameterValues);
// 特殊解决数字的比较因为 Spring 是基于它的 compareTo 方法对数字的比较存在问题 // 特殊解决数字的比较因为 Spring 是基于它的 compareTo 方法对数字的比较存在问题
if (ObjectUtils.equalsAny(operator, IotRuleSceneConditionOperatorEnum.BETWEEN, if (ObjectUtils.equalsAny(operator, IotSceneRuleConditionOperatorEnum.BETWEEN,
IotRuleSceneConditionOperatorEnum.NOT_BETWEEN, IotSceneRuleConditionOperatorEnum.NOT_BETWEEN,
IotRuleSceneConditionOperatorEnum.GREATER_THAN, IotSceneRuleConditionOperatorEnum.GREATER_THAN,
IotRuleSceneConditionOperatorEnum.GREATER_THAN_OR_EQUALS, IotSceneRuleConditionOperatorEnum.GREATER_THAN_OR_EQUALS,
IotRuleSceneConditionOperatorEnum.LESS_THAN, IotSceneRuleConditionOperatorEnum.LESS_THAN,
IotRuleSceneConditionOperatorEnum.LESS_THAN_OR_EQUALS) IotSceneRuleConditionOperatorEnum.LESS_THAN_OR_EQUALS)
&& NumberUtil.isNumber(messageValue) && NumberUtil.isNumber(messageValue)
&& NumberUtils.isAllNumber(parameterValues)) { && NumberUtils.isAllNumber(parameterValues)) {
springExpressionVariables.put(IotRuleSceneConditionOperatorEnum.SPRING_EXPRESSION_SOURCE, springExpressionVariables.put(IotSceneRuleConditionOperatorEnum.SPRING_EXPRESSION_SOURCE,
NumberUtil.parseDouble(messageValue)); NumberUtil.parseDouble(messageValue));
springExpressionVariables.put(IotRuleSceneConditionOperatorEnum.SPRING_EXPRESSION_VALUE, springExpressionVariables.put(IotSceneRuleConditionOperatorEnum.SPRING_EXPRESSION_VALUE,
NumberUtil.parseDouble(condition.getParam())); NumberUtil.parseDouble(condition.getParam()));
springExpressionVariables.put(IotRuleSceneConditionOperatorEnum.SPRING_EXPRESSION_VALUE_LIST, springExpressionVariables.put(IotSceneRuleConditionOperatorEnum.SPRING_EXPRESSION_VALUE_LIST,
convertList(parameterValues, NumberUtil::parseDouble)); convertList(parameterValues, NumberUtil::parseDouble));
} }
// 2.2 计算 Spring 表达式 // 2.2 计算 Spring 表达式
return (Boolean) SpringExpressionUtils.parseExpression(operator.getSpringExpression(), springExpressionVariables); return (Boolean) SpringExpressionUtils.parseExpression(operator.getSpringExpression(), springExpressionVariables);
} catch (Exception e) { } catch (Exception e) {
log.error("[isTriggerConditionParameterMatched][消息({}) 规则场景编号({}) 的触发器({}) 的匹配表达式({}/{}) 计算异常]", log.error("[isTriggerConditionParameterMatched][消息({}) 规则场景编号({}) 的触发器({}) 的匹配表达式({}/{}) 计算异常]",
message, ruleScene.getId(), trigger, operator, springExpressionVariables, e); message, sceneRule.getId(), trigger, operator, springExpressionVariables, e);
return false; return false;
} }
} }
@ -521,15 +521,15 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
* 执行规则场景的动作 * 执行规则场景的动作
* *
* @param message 设备消息 * @param message 设备消息
* @param ruleScenes 规则场景列表 * @param sceneRules 规则场景列表
*/ */
private void executeRuleSceneAction(IotDeviceMessage message, List<IotSceneRuleDO> ruleScenes) { private void executeSceneRuleAction(IotDeviceMessage message, List<IotSceneRuleDO> sceneRules) {
// 1. 遍历规则场景 // 1. 遍历规则场景
ruleScenes.forEach(ruleScene -> { sceneRules.forEach(sceneRule -> {
// 2. 遍历规则场景的动作 // 2. 遍历规则场景的动作
ruleScene.getActions().forEach(actionConfig -> { sceneRule.getActions().forEach(actionConfig -> {
// 3.1 获取对应的动作 Action 数组 // 3.1 获取对应的动作 Action 数组
List<IotSceneRuleAction> actions = filterList(ruleSceneActions, List<IotSceneRuleAction> actions = filterList(sceneRuleActions,
action -> action.getType().getType().equals(actionConfig.getType())); action -> action.getType().getType().equals(actionConfig.getType()));
if (CollUtil.isEmpty(actions)) { if (CollUtil.isEmpty(actions)) {
return; return;
@ -537,12 +537,12 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
// 3.2 执行动作 // 3.2 执行动作
actions.forEach(action -> { actions.forEach(action -> {
try { try {
action.execute(message, ruleScene, actionConfig); action.execute(message, sceneRule, actionConfig);
log.info("[executeRuleSceneAction][消息({}) 规则场景编号({}) 的执行动作({}) 成功]", log.info("[executeSceneRuleAction][消息({}) 规则场景编号({}) 的执行动作({}) 成功]",
message, ruleScene.getId(), actionConfig); message, sceneRule.getId(), actionConfig);
} catch (Exception e) { } catch (Exception e) {
log.error("[executeRuleSceneAction][消息({}) 规则场景编号({}) 的执行动作({}) 执行异常]", log.error("[executeSceneRuleAction][消息({}) 规则场景编号({}) 的执行动作({}) 执行异常]",
message, ruleScene.getId(), actionConfig, e); message, sceneRule.getId(), actionConfig, e);
} }
}); });
}); });

View File

@ -5,7 +5,7 @@ import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertRecordDO; import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertRecordDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleActionTypeEnum;
import cn.iocoder.yudao.module.iot.service.alert.IotAlertRecordService; import cn.iocoder.yudao.module.iot.service.alert.IotAlertRecordService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -42,8 +42,8 @@ public class IotAlertRecoverSceneRuleAction implements IotSceneRuleAction {
} }
@Override @Override
public IotRuleSceneActionTypeEnum getType() { public IotSceneRuleActionTypeEnum getType() {
return IotRuleSceneActionTypeEnum.ALERT_RECOVER; return IotSceneRuleActionTypeEnum.ALERT_RECOVER;
} }
} }

View File

@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertConfigDO; import cn.iocoder.yudao.module.iot.dal.dataobject.alert.IotAlertConfigDO;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleActionTypeEnum;
import cn.iocoder.yudao.module.iot.service.alert.IotAlertConfigService; import cn.iocoder.yudao.module.iot.service.alert.IotAlertConfigService;
import cn.iocoder.yudao.module.iot.service.alert.IotAlertRecordService; import cn.iocoder.yudao.module.iot.service.alert.IotAlertRecordService;
import cn.iocoder.yudao.module.system.api.mail.MailSendApi; import cn.iocoder.yudao.module.system.api.mail.MailSendApi;
@ -62,8 +62,8 @@ public class IotAlertTriggerSceneRuleAction implements IotSceneRuleAction {
} }
@Override @Override
public IotRuleSceneActionTypeEnum getType() { public IotSceneRuleActionTypeEnum getType() {
return IotRuleSceneActionTypeEnum.ALERT_TRIGGER; return IotSceneRuleActionTypeEnum.ALERT_TRIGGER;
} }
} }

View File

@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.iot.service.rule.scene.action;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleActionTypeEnum;
import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
import cn.iocoder.yudao.module.iot.service.device.message.IotDeviceMessageService; import cn.iocoder.yudao.module.iot.service.device.message.IotDeviceMessageService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@ -16,7 +16,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@Slf4j @Slf4j
public class IotDeviceControlRuleSceneAction implements IotSceneRuleAction { public class IotDeviceControlSceneRuleAction implements IotSceneRuleAction {
@Resource @Resource
private IotDeviceService deviceService; private IotDeviceService deviceService;
@ -48,8 +48,8 @@ public class IotDeviceControlRuleSceneAction implements IotSceneRuleAction {
} }
@Override @Override
public IotRuleSceneActionTypeEnum getType() { public IotSceneRuleActionTypeEnum getType() {
return IotRuleSceneActionTypeEnum.DEVICE_PROPERTY_SET; return IotSceneRuleActionTypeEnum.DEVICE_PROPERTY_SET;
} }
} }

View File

@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.iot.service.rule.scene.action;
import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum; import cn.iocoder.yudao.module.iot.enums.rule.IotSceneRuleActionTypeEnum;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -31,6 +31,6 @@ public interface IotSceneRuleAction {
* *
* @return 类型 * @return 类型
*/ */
IotRuleSceneActionTypeEnum getType(); IotSceneRuleActionTypeEnum getType();
} }

View File

@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.iot.service.rule.scene;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO; import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotSceneRuleSaveReqVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO; import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotSceneRuleDO;
import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotRuleSceneMapper; import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotSceneRuleMapper;
import cn.iocoder.yudao.module.iot.framework.job.core.IotSchedulerManager; import cn.iocoder.yudao.module.iot.framework.job.core.IotSchedulerManager;
import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
import cn.iocoder.yudao.module.iot.service.product.IotProductService; import cn.iocoder.yudao.module.iot.service.product.IotProductService;
@ -24,21 +24,21 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*; import static org.mockito.Mockito.*;
/** /**
* {@link IotRuleSceneServiceImpl} 的简化单元测试类 * {@link IotSceneRuleServiceImpl} 的简化单元测试类
* 使用 Mockito 进行纯单元测试不依赖 Spring 容器 * 使用 Mockito 进行纯单元测试不依赖 Spring 容器
* *
* @author 芋道源码 * @author 芋道源码
*/ */
public class IotRuleSceneServiceSimpleTest extends BaseMockitoUnitTest { public class IotSceneRuleServiceSimpleTest extends BaseMockitoUnitTest {
@InjectMocks @InjectMocks
private IotRuleSceneServiceImpl ruleSceneService; private IotSceneRuleServiceImpl sceneRuleService;
@Mock @Mock
private IotRuleSceneMapper ruleSceneMapper; private IotSceneRuleMapper sceneRuleMapper;
@Mock @Mock
private List<IotSceneRuleAction> ruleSceneActions; private List<IotSceneRuleAction> sceneRuleActions;
@Mock @Mock
private IotSchedulerManager schedulerManager; private IotSchedulerManager schedulerManager;
@ -50,9 +50,9 @@ public class IotRuleSceneServiceSimpleTest extends BaseMockitoUnitTest {
private IotDeviceService deviceService; private IotDeviceService deviceService;
@Test @Test
public void testCreateRuleScene_success() { public void testCreateScene_Rule_success() {
// 准备参数 // 准备参数
IotRuleSceneSaveReqVO createReqVO = randomPojo(IotRuleSceneSaveReqVO.class, o -> { IotSceneRuleSaveReqVO createReqVO = randomPojo(IotSceneRuleSaveReqVO.class, o -> {
o.setId(null); o.setId(null);
o.setStatus(CommonStatusEnum.ENABLE.getStatus()); o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setTriggers(Collections.singletonList(randomPojo(IotSceneRuleDO.Trigger.class))); o.setTriggers(Collections.singletonList(randomPojo(IotSceneRuleDO.Trigger.class)));
@ -61,25 +61,25 @@ public class IotRuleSceneServiceSimpleTest extends BaseMockitoUnitTest {
// Mock 行为 // Mock 行为
Long expectedId = randomLongId(); Long expectedId = randomLongId();
when(ruleSceneMapper.insert(any(IotSceneRuleDO.class))).thenAnswer(invocation -> { when(sceneRuleMapper.insert(any(IotSceneRuleDO.class))).thenAnswer(invocation -> {
IotSceneRuleDO ruleScene = invocation.getArgument(0); IotSceneRuleDO sceneRule = invocation.getArgument(0);
ruleScene.setId(expectedId); sceneRule.setId(expectedId);
return 1; return 1;
}); });
// 调用 // 调用
Long ruleSceneId = ruleSceneService.createRuleScene(createReqVO); Long sceneRuleId = sceneRuleService.createSceneRule(createReqVO);
// 断言 // 断言
assertEquals(expectedId, ruleSceneId); assertEquals(expectedId, sceneRuleId);
verify(ruleSceneMapper, times(1)).insert(any(IotSceneRuleDO.class)); verify(sceneRuleMapper, times(1)).insert(any(IotSceneRuleDO.class));
} }
@Test @Test
public void testUpdateRuleScene_success() { public void testUpdateScene_Rule_success() {
// 准备参数 // 准备参数
Long id = randomLongId(); Long id = randomLongId();
IotRuleSceneSaveReqVO updateReqVO = randomPojo(IotRuleSceneSaveReqVO.class, o -> { IotSceneRuleSaveReqVO updateReqVO = randomPojo(IotSceneRuleSaveReqVO.class, o -> {
o.setId(id); o.setId(id);
o.setStatus(CommonStatusEnum.ENABLE.getStatus()); o.setStatus(CommonStatusEnum.ENABLE.getStatus());
o.setTriggers(Collections.singletonList(randomPojo(IotSceneRuleDO.Trigger.class))); o.setTriggers(Collections.singletonList(randomPojo(IotSceneRuleDO.Trigger.class)));
@ -87,125 +87,125 @@ public class IotRuleSceneServiceSimpleTest extends BaseMockitoUnitTest {
}); });
// Mock 行为 // Mock 行为
IotSceneRuleDO existingRuleScene = randomPojo(IotSceneRuleDO.class, o -> o.setId(id)); IotSceneRuleDO existingSceneRule = randomPojo(IotSceneRuleDO.class, o -> o.setId(id));
when(ruleSceneMapper.selectById(id)).thenReturn(existingRuleScene); when(sceneRuleMapper.selectById(id)).thenReturn(existingSceneRule);
when(ruleSceneMapper.updateById(any(IotSceneRuleDO.class))).thenReturn(1); when(sceneRuleMapper.updateById(any(IotSceneRuleDO.class))).thenReturn(1);
// 调用 // 调用
assertDoesNotThrow(() -> ruleSceneService.updateRuleScene(updateReqVO)); assertDoesNotThrow(() -> sceneRuleService.updateSceneRule(updateReqVO));
// 验证 // 验证
verify(ruleSceneMapper, times(1)).selectById(id); verify(sceneRuleMapper, times(1)).selectById(id);
verify(ruleSceneMapper, times(1)).updateById(any(IotSceneRuleDO.class)); verify(sceneRuleMapper, times(1)).updateById(any(IotSceneRuleDO.class));
} }
@Test @Test
public void testDeleteRuleScene_success() { public void testDeleteSceneRule_success() {
// 准备参数 // 准备参数
Long id = randomLongId(); Long id = randomLongId();
// Mock 行为 // Mock 行为
IotSceneRuleDO existingRuleScene = randomPojo(IotSceneRuleDO.class, o -> o.setId(id)); IotSceneRuleDO existingSceneRule = randomPojo(IotSceneRuleDO.class, o -> o.setId(id));
when(ruleSceneMapper.selectById(id)).thenReturn(existingRuleScene); when(sceneRuleMapper.selectById(id)).thenReturn(existingSceneRule);
when(ruleSceneMapper.deleteById(id)).thenReturn(1); when(sceneRuleMapper.deleteById(id)).thenReturn(1);
// 调用 // 调用
assertDoesNotThrow(() -> ruleSceneService.deleteRuleScene(id)); assertDoesNotThrow(() -> sceneRuleService.deleteSceneRule(id));
// 验证 // 验证
verify(ruleSceneMapper, times(1)).selectById(id); verify(sceneRuleMapper, times(1)).selectById(id);
verify(ruleSceneMapper, times(1)).deleteById(id); verify(sceneRuleMapper, times(1)).deleteById(id);
} }
@Test @Test
public void testGetRuleScene() { public void testGetSceneRule() {
// 准备参数 // 准备参数
Long id = randomLongId(); Long id = randomLongId();
IotSceneRuleDO expectedRuleScene = randomPojo(IotSceneRuleDO.class, o -> o.setId(id)); IotSceneRuleDO expectedSceneRule = randomPojo(IotSceneRuleDO.class, o -> o.setId(id));
// Mock 行为 // Mock 行为
when(ruleSceneMapper.selectById(id)).thenReturn(expectedRuleScene); when(sceneRuleMapper.selectById(id)).thenReturn(expectedSceneRule);
// 调用 // 调用
IotSceneRuleDO result = ruleSceneService.getRuleScene(id); IotSceneRuleDO result = sceneRuleService.getSceneRule(id);
// 断言 // 断言
assertEquals(expectedRuleScene, result); assertEquals(expectedSceneRule, result);
verify(ruleSceneMapper, times(1)).selectById(id); verify(sceneRuleMapper, times(1)).selectById(id);
} }
@Test @Test
public void testUpdateRuleSceneStatus_success() { public void testUpdateSceneRuleStatus_success() {
// 准备参数 // 准备参数
Long id = randomLongId(); Long id = randomLongId();
Integer status = CommonStatusEnum.DISABLE.getStatus(); Integer status = CommonStatusEnum.DISABLE.getStatus();
// Mock 行为 // Mock 行为
IotSceneRuleDO existingRuleScene = randomPojo(IotSceneRuleDO.class, o -> { IotSceneRuleDO existingSceneRule = randomPojo(IotSceneRuleDO.class, o -> {
o.setId(id); o.setId(id);
o.setStatus(CommonStatusEnum.ENABLE.getStatus()); o.setStatus(CommonStatusEnum.ENABLE.getStatus());
}); });
when(ruleSceneMapper.selectById(id)).thenReturn(existingRuleScene); when(sceneRuleMapper.selectById(id)).thenReturn(existingSceneRule);
when(ruleSceneMapper.updateById(any(IotSceneRuleDO.class))).thenReturn(1); when(sceneRuleMapper.updateById(any(IotSceneRuleDO.class))).thenReturn(1);
// 调用 // 调用
assertDoesNotThrow(() -> ruleSceneService.updateRuleSceneStatus(id, status)); assertDoesNotThrow(() -> sceneRuleService.updateSceneRuleStatus(id, status));
// 验证 // 验证
verify(ruleSceneMapper, times(1)).selectById(id); verify(sceneRuleMapper, times(1)).selectById(id);
verify(ruleSceneMapper, times(1)).updateById(any(IotSceneRuleDO.class)); verify(sceneRuleMapper, times(1)).updateById(any(IotSceneRuleDO.class));
} }
@Test @Test
public void testExecuteRuleSceneByTimer_success() { public void testExecuteSceneRuleByTimer_success() {
// 准备参数 // 准备参数
Long id = randomLongId(); Long id = randomLongId();
// Mock 行为 // Mock 行为
IotSceneRuleDO ruleScene = randomPojo(IotSceneRuleDO.class, o -> { IotSceneRuleDO sceneRule = randomPojo(IotSceneRuleDO.class, o -> {
o.setId(id); o.setId(id);
o.setStatus(CommonStatusEnum.ENABLE.getStatus()); o.setStatus(CommonStatusEnum.ENABLE.getStatus());
}); });
when(ruleSceneMapper.selectById(id)).thenReturn(ruleScene); when(sceneRuleMapper.selectById(id)).thenReturn(sceneRule);
// 调用 // 调用
assertDoesNotThrow(() -> ruleSceneService.executeRuleSceneByTimer(id)); assertDoesNotThrow(() -> sceneRuleService.executeSceneRuleByTimer(id));
// 验证 // 验证
verify(ruleSceneMapper, times(1)).selectById(id); verify(sceneRuleMapper, times(1)).selectById(id);
} }
@Test @Test
public void testExecuteRuleSceneByTimer_notExists() { public void testExecuteSceneRuleByTimer_notExists() {
// 准备参数 // 准备参数
Long id = randomLongId(); Long id = randomLongId();
// Mock 行为 // Mock 行为
when(ruleSceneMapper.selectById(id)).thenReturn(null); when(sceneRuleMapper.selectById(id)).thenReturn(null);
// 调用 - 不存在的场景规则应该不会抛异常只是记录日志 // 调用 - 不存在的场景规则应该不会抛异常只是记录日志
assertDoesNotThrow(() -> ruleSceneService.executeRuleSceneByTimer(id)); assertDoesNotThrow(() -> sceneRuleService.executeSceneRuleByTimer(id));
// 验证 // 验证
verify(ruleSceneMapper, times(1)).selectById(id); verify(sceneRuleMapper, times(1)).selectById(id);
} }
@Test @Test
public void testExecuteRuleSceneByTimer_disabled() { public void testExecuteSceneRuleByTimer_disabled() {
// 准备参数 // 准备参数
Long id = randomLongId(); Long id = randomLongId();
// Mock 行为 // Mock 行为
IotSceneRuleDO ruleScene = randomPojo(IotSceneRuleDO.class, o -> { IotSceneRuleDO sceneRule = randomPojo(IotSceneRuleDO.class, o -> {
o.setId(id); o.setId(id);
o.setStatus(CommonStatusEnum.DISABLE.getStatus()); o.setStatus(CommonStatusEnum.DISABLE.getStatus());
}); });
when(ruleSceneMapper.selectById(id)).thenReturn(ruleScene); when(sceneRuleMapper.selectById(id)).thenReturn(sceneRule);
// 调用 - 禁用的场景规则应该不会执行只是记录日志 // 调用 - 禁用的场景规则应该不会执行只是记录日志
assertDoesNotThrow(() -> ruleSceneService.executeRuleSceneByTimer(id)); assertDoesNotThrow(() -> sceneRuleService.executeSceneRuleByTimer(id));
// 验证 // 验证
verify(ruleSceneMapper, times(1)).selectById(id); verify(sceneRuleMapper, times(1)).selectById(id);
} }
} }