Pre Merge pull request !1302 from puhui999/iot
This commit is contained in:
commit
42c794747d
|
@ -72,8 +72,8 @@ public interface ErrorCodeConstants {
|
||||||
// ========== IoT 数据桥梁 1-050-010-000 ==========
|
// ========== IoT 数据桥梁 1-050-010-000 ==========
|
||||||
ErrorCode DATA_BRIDGE_NOT_EXISTS = new ErrorCode(1_050_010_000, "IoT 数据桥梁不存在");
|
ErrorCode DATA_BRIDGE_NOT_EXISTS = new ErrorCode(1_050_010_000, "IoT 数据桥梁不存在");
|
||||||
|
|
||||||
// ========== IoT 规则场景(场景联动) 1-050-011-000 ==========
|
// ========== IoT 场景联动 1-050-011-000 ==========
|
||||||
ErrorCode RULE_SCENE_NOT_EXISTS = new ErrorCode(1_050_011_000, "IoT 规则场景(场景联动)不存在");
|
ErrorCode RULE_SCENE_NOT_EXISTS = new ErrorCode(1_050_011_000, "IoT 场景联动不存在");
|
||||||
|
|
||||||
// ========== IoT 产品脚本信息 1-050-012-000 ==========
|
// ========== IoT 产品脚本信息 1-050-012-000 ==========
|
||||||
ErrorCode PRODUCT_SCRIPT_NOT_EXISTS = new ErrorCode(1_050_012_000, "IoT 产品脚本信息不存在");
|
ErrorCode PRODUCT_SCRIPT_NOT_EXISTS = new ErrorCode(1_050_012_000, "IoT 产品脚本信息不存在");
|
||||||
|
|
|
@ -20,8 +20,7 @@ import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
// TODO @芋艿:规则场景 要不要,统一改成 场景联动
|
@Tag(name = "管理后台 - IoT 场景联动")
|
||||||
@Tag(name = "管理后台 - IoT 规则场景")
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/iot/rule-scene")
|
@RequestMapping("/iot/rule-scene")
|
||||||
@Validated
|
@Validated
|
||||||
|
@ -31,14 +30,14 @@ public class IotRuleSceneController {
|
||||||
private IotRuleSceneService ruleSceneService;
|
private IotRuleSceneService ruleSceneService;
|
||||||
|
|
||||||
@PostMapping("/create")
|
@PostMapping("/create")
|
||||||
@Operation(summary = "创建规则场景(场景联动)")
|
@Operation(summary = "创建场景联动")
|
||||||
@PreAuthorize("@ss.hasPermission('iot:rule-scene:create')")
|
@PreAuthorize("@ss.hasPermission('iot:rule-scene:create')")
|
||||||
public CommonResult<Long> createRuleScene(@Valid @RequestBody IotRuleSceneSaveReqVO createReqVO) {
|
public CommonResult<Long> createRuleScene(@Valid @RequestBody IotRuleSceneSaveReqVO createReqVO) {
|
||||||
return success(ruleSceneService.createRuleScene(createReqVO));
|
return success(ruleSceneService.createRuleScene(createReqVO));
|
||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping("/update")
|
@PutMapping("/update")
|
||||||
@Operation(summary = "更新规则场景(场景联动)")
|
@Operation(summary = "更新场景联动")
|
||||||
@PreAuthorize("@ss.hasPermission('iot:rule-scene:update')")
|
@PreAuthorize("@ss.hasPermission('iot:rule-scene:update')")
|
||||||
public CommonResult<Boolean> updateRuleScene(@Valid @RequestBody IotRuleSceneSaveReqVO updateReqVO) {
|
public CommonResult<Boolean> updateRuleScene(@Valid @RequestBody IotRuleSceneSaveReqVO updateReqVO) {
|
||||||
ruleSceneService.updateRuleScene(updateReqVO);
|
ruleSceneService.updateRuleScene(updateReqVO);
|
||||||
|
@ -46,7 +45,7 @@ public class IotRuleSceneController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@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:rule-scene:delete')")
|
||||||
public CommonResult<Boolean> deleteRuleScene(@RequestParam("id") Long id) {
|
public CommonResult<Boolean> deleteRuleScene(@RequestParam("id") Long id) {
|
||||||
|
@ -55,7 +54,7 @@ public class IotRuleSceneController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@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:rule-scene:query')")
|
||||||
public CommonResult<IotRuleSceneRespVO> getRuleScene(@RequestParam("id") Long id) {
|
public CommonResult<IotRuleSceneRespVO> getRuleScene(@RequestParam("id") Long id) {
|
||||||
|
@ -64,7 +63,7 @@ public class IotRuleSceneController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/page")
|
@GetMapping("/page")
|
||||||
@Operation(summary = "获得规则场景(场景联动)分页")
|
@Operation(summary = "获得场景联动分页")
|
||||||
@PreAuthorize("@ss.hasPermission('iot:rule-scene:query')")
|
@PreAuthorize("@ss.hasPermission('iot:rule-scene:query')")
|
||||||
public CommonResult<PageResult<IotRuleSceneRespVO>> getRuleScenePage(@Valid IotRuleScenePageReqVO pageReqVO) {
|
public CommonResult<PageResult<IotRuleSceneRespVO>> getRuleScenePage(@Valid IotRuleScenePageReqVO pageReqVO) {
|
||||||
PageResult<IotRuleSceneDO> pageResult = ruleSceneService.getRuleScenePage(pageReqVO);
|
PageResult<IotRuleSceneDO> pageResult = ruleSceneService.getRuleScenePage(pageReqVO);
|
||||||
|
|
|
@ -18,7 +18,7 @@ import lombok.Data;
|
||||||
@JsonSubTypes({
|
@JsonSubTypes({
|
||||||
@JsonSubTypes.Type(value = IotDataBridgeHttpConfig.class, name = "1"),
|
@JsonSubTypes.Type(value = IotDataBridgeHttpConfig.class, name = "1"),
|
||||||
@JsonSubTypes.Type(value = IotDataBridgeMqttConfig.class, name = "10"),
|
@JsonSubTypes.Type(value = IotDataBridgeMqttConfig.class, name = "10"),
|
||||||
@JsonSubTypes.Type(value = IotDataBridgeRedisStreamMQConfig.class, name = "21"),
|
@JsonSubTypes.Type(value = IotDataBridgeRedisStreamConfig.class, name = "21"),
|
||||||
@JsonSubTypes.Type(value = IotDataBridgeRocketMQConfig.class, name = "30"),
|
@JsonSubTypes.Type(value = IotDataBridgeRocketMQConfig.class, name = "30"),
|
||||||
@JsonSubTypes.Type(value = IotDataBridgeRabbitMQConfig.class, name = "31"),
|
@JsonSubTypes.Type(value = IotDataBridgeRabbitMQConfig.class, name = "31"),
|
||||||
@JsonSubTypes.Type(value = IotDataBridgeKafkaMQConfig.class, name = "32"),
|
@JsonSubTypes.Type(value = IotDataBridgeKafkaMQConfig.class, name = "32"),
|
||||||
|
|
|
@ -2,14 +2,13 @@ package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
// TODO @puhui999:MQ 可以去掉哈。stream 更精准
|
|
||||||
/**
|
/**
|
||||||
* IoT Redis Stream 配置 {@link IotDataBridgeAbstractConfig} 实现类
|
* IoT Redis Stream 配置 {@link IotDataBridgeAbstractConfig} 实现类
|
||||||
*
|
*
|
||||||
* @author HUIHUI
|
* @author HUIHUI
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class IotDataBridgeRedisStreamMQConfig extends IotDataBridgeAbstractConfig {
|
public class IotDataBridgeRedisStreamConfig extends IotDataBridgeAbstractConfig {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redis 服务器地址
|
* Redis 服务器地址
|
|
@ -1,2 +0,0 @@
|
||||||
// TODO @芋艿:占位
|
|
||||||
package cn.iocoder.yudao.module.iot.controller.admin.rule.vo;
|
|
|
@ -13,7 +13,7 @@ import java.time.LocalDateTime;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||||
|
|
||||||
@Schema(description = "管理后台 - IoT 规则场景(场景联动)分页 Request VO")
|
@Schema(description = "管理后台 - IoT 场景联动分页 Request VO")
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@ToString(callSuper = true)
|
@ToString(callSuper = true)
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene;
|
package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene;
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneTriggerConfig;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Schema(description = "管理后台 - IoT 规则场景(场景联动) Response VO")
|
@Schema(description = "管理后台 - IoT 场景联动 Response VO")
|
||||||
@Data
|
@Data
|
||||||
public class IotRuleSceneRespVO {
|
public class IotRuleSceneRespVO {
|
||||||
|
|
||||||
|
@ -25,10 +24,10 @@ public class IotRuleSceneRespVO {
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
|
||||||
@Schema(description = "触发器数组", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "触发器数组", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private List<IotRuleSceneTriggerConfig> triggers;
|
private List<IotRuleSceneDO.TriggerConfig> triggers;
|
||||||
|
|
||||||
@Schema(description = "执行器数组", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "执行器数组", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private List<IotRuleSceneActionConfig> actions;
|
private List<IotRuleSceneDO.ActionConfig> actions;
|
||||||
|
|
||||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
|
|
|
@ -2,8 +2,7 @@ package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneTriggerConfig;
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
@ -11,7 +10,7 @@ import lombok.Data;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Schema(description = "管理后台 - IoT 规则场景(场景联动)新增/修改 Request VO")
|
@Schema(description = "管理后台 - IoT 场景联动新增/修改 Request VO")
|
||||||
@Data
|
@Data
|
||||||
public class IotRuleSceneSaveReqVO {
|
public class IotRuleSceneSaveReqVO {
|
||||||
|
|
||||||
|
@ -32,10 +31,10 @@ public class IotRuleSceneSaveReqVO {
|
||||||
|
|
||||||
@Schema(description = "触发器数组", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "触发器数组", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
@NotEmpty(message = "触发器数组不能为空")
|
@NotEmpty(message = "触发器数组不能为空")
|
||||||
private List<IotRuleSceneTriggerConfig> triggers;
|
private List<IotRuleSceneDO.TriggerConfig> triggers;
|
||||||
|
|
||||||
@Schema(description = "执行器数组", requiredMode = Schema.RequiredMode.REQUIRED)
|
@Schema(description = "执行器数组", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||||
@NotEmpty(message = "执行器数组不能为空")
|
@NotEmpty(message = "执行器数组不能为空")
|
||||||
private List<IotRuleSceneActionConfig> actions;
|
private List<IotRuleSceneDO.ActionConfig> actions;
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,38 +0,0 @@
|
||||||
package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO;
|
|
||||||
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
// TODO @puhui999:这个要不内嵌到 IoTRuleSceneDO 里面?
|
|
||||||
/**
|
|
||||||
* 执行器配置
|
|
||||||
*
|
|
||||||
* @author 芋道源码
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class IotRuleSceneActionConfig {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行类型
|
|
||||||
*
|
|
||||||
* 枚举 {@link IotRuleSceneActionTypeEnum}
|
|
||||||
*/
|
|
||||||
private Integer type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设备控制
|
|
||||||
*
|
|
||||||
* 必填:当 {@link #type} 为 {@link IotRuleSceneActionTypeEnum#DEVICE_CONTROL} 时
|
|
||||||
*/
|
|
||||||
private IotRuleSceneActionDeviceControl deviceControl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数据桥接编号
|
|
||||||
*
|
|
||||||
* 必填:当 {@link #type} 为 {@link IotRuleSceneActionTypeEnum#DATA_BRIDGE} 时
|
|
||||||
* 关联:{@link IotDataBridgeDO#getId()}
|
|
||||||
*/
|
|
||||||
private Long dataBridgeId;
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,58 +0,0 @@
|
||||||
package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config;
|
|
||||||
|
|
||||||
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.enums.device.IotDeviceMessageIdentifierEnum;
|
|
||||||
import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
// TODO @puhui999:这个要不内嵌到 IoTRuleSceneDO 里面?
|
|
||||||
/**
|
|
||||||
* 执行设备控制
|
|
||||||
*
|
|
||||||
* @author 芋道源码
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class IotRuleSceneActionDeviceControl {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 产品标识
|
|
||||||
*
|
|
||||||
* 关联 {@link IotProductDO#getProductKey()}
|
|
||||||
*/
|
|
||||||
private String productKey;
|
|
||||||
/**
|
|
||||||
* 设备名称数组
|
|
||||||
*
|
|
||||||
* 关联 {@link IotDeviceDO#getDeviceName()}
|
|
||||||
*/
|
|
||||||
private List<String> deviceNames;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 消息类型
|
|
||||||
*
|
|
||||||
* 枚举 {@link IotDeviceMessageTypeEnum#PROPERTY}、{@link IotDeviceMessageTypeEnum#SERVICE}
|
|
||||||
*/
|
|
||||||
private String type;
|
|
||||||
/**
|
|
||||||
* 消息标识符
|
|
||||||
*
|
|
||||||
* 枚举 {@link IotDeviceMessageIdentifierEnum}
|
|
||||||
*
|
|
||||||
* 1. 属性设置:对应 {@link IotDeviceMessageIdentifierEnum#PROPERTY_SET}
|
|
||||||
* 2. 服务调用:对应 {@link IotDeviceMessageIdentifierEnum#SERVICE_INVOKE}
|
|
||||||
*/
|
|
||||||
private String identifier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 具体数据
|
|
||||||
*
|
|
||||||
* 1. 属性设置:在 {@link #type} 是 {@link IotDeviceMessageTypeEnum#PROPERTY} 时,对应 properties
|
|
||||||
* 2. 服务调用:在 {@link #type} 是 {@link IotDeviceMessageTypeEnum#SERVICE} 时,对应 params
|
|
||||||
*/
|
|
||||||
private Map<String, Object> data;
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum;
|
|
||||||
import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
// TODO @puhui999:这个要不内嵌到 IoTRuleSceneDO 里面?
|
|
||||||
/**
|
|
||||||
* 触发条件
|
|
||||||
*
|
|
||||||
* @author 芋道源码
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class IotRuleSceneTriggerCondition {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 消息类型
|
|
||||||
*
|
|
||||||
* 枚举 {@link IotDeviceMessageTypeEnum}
|
|
||||||
*/
|
|
||||||
private String type;
|
|
||||||
/**
|
|
||||||
* 消息标识符
|
|
||||||
*
|
|
||||||
* 枚举 {@link IotDeviceMessageIdentifierEnum}
|
|
||||||
*/
|
|
||||||
private String identifier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 参数数组
|
|
||||||
*
|
|
||||||
* 参数与参数之间,是“或”的关系
|
|
||||||
*/
|
|
||||||
private List<IotRuleSceneTriggerConditionParameter> parameters;
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config;
|
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
|
|
||||||
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerConditionParameterOperatorEnum;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
// TODO @puhui999:这个要不内嵌到 IoTRuleSceneDO 里面?
|
|
||||||
/**
|
|
||||||
* 触发条件参数
|
|
||||||
*
|
|
||||||
* @author 芋道源码
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class IotRuleSceneTriggerConditionParameter {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 标识符(属性、事件、服务)
|
|
||||||
*
|
|
||||||
* 关联 {@link IotThingModelDO#getIdentifier()}
|
|
||||||
*/
|
|
||||||
private String identifier;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 操作符
|
|
||||||
*
|
|
||||||
* 枚举 {@link IotRuleSceneTriggerConditionParameterOperatorEnum}
|
|
||||||
*/
|
|
||||||
private String operator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 比较值
|
|
||||||
*
|
|
||||||
* 如果有多个值,则使用 "," 分隔,类似 "1,2,3"。
|
|
||||||
* 例如说,{@link IotRuleSceneTriggerConditionParameterOperatorEnum#IN}、{@link IotRuleSceneTriggerConditionParameterOperatorEnum#BETWEEN}
|
|
||||||
*/
|
|
||||||
private String value;
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
package cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config;
|
|
||||||
|
|
||||||
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.enums.rule.IotRuleSceneTriggerTypeEnum;
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
// TODO @puhui999:这个要不内嵌到 IoTRuleSceneDO 里面?
|
|
||||||
/**
|
|
||||||
* 触发器配置
|
|
||||||
*
|
|
||||||
* @author 芋道源码
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class IotRuleSceneTriggerConfig {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 触发类型
|
|
||||||
*
|
|
||||||
* 枚举 {@link IotRuleSceneTriggerTypeEnum}
|
|
||||||
*/
|
|
||||||
private Integer type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 产品标识
|
|
||||||
*
|
|
||||||
* 关联 {@link IotProductDO#getProductKey()}
|
|
||||||
*/
|
|
||||||
private String productKey;
|
|
||||||
/**
|
|
||||||
* 设备名称数组
|
|
||||||
*
|
|
||||||
* 关联 {@link IotDeviceDO#getDeviceName()}
|
|
||||||
*/
|
|
||||||
private List<String> deviceNames;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 触发条件数组
|
|
||||||
*
|
|
||||||
* 必填:当 {@link #type} 为 {@link IotRuleSceneTriggerTypeEnum#DEVICE} 时
|
|
||||||
* 条件与条件之间,是“或”的关系
|
|
||||||
*/
|
|
||||||
private List<IotRuleSceneTriggerCondition> conditions;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CRON 表达式
|
|
||||||
*
|
|
||||||
* 必填:当 {@link #type} 为 {@link IotRuleSceneTriggerTypeEnum#TIMER} 时
|
|
||||||
*/
|
|
||||||
private String cronExpression;
|
|
||||||
|
|
||||||
}
|
|
|
@ -174,7 +174,7 @@ GET {{baseUrl}}/iot/product-thing-model/get?id=67
|
||||||
tenant-id: {{adminTenentId}}
|
tenant-id: {{adminTenentId}}
|
||||||
Authorization: Bearer {{token}}
|
Authorization: Bearer {{token}}
|
||||||
|
|
||||||
### 请求 /iot/product-thing-model/tsl-by-product-id 接口 => 成功
|
### 请求 /iot/product-thing-model/get-tsl 接口 => 成功
|
||||||
GET {{baseUrl}}/iot/product-thing-model/tsl-by-product-id?productId=1001
|
GET {{baseUrl}}/iot/product-thing-model/get-tsl?productId=1001
|
||||||
tenant-id: {{adminTenentId}}
|
tenant-id: {{adminTenentId}}
|
||||||
Authorization: Bearer {{token}}
|
Authorization: Bearer {{token}}
|
|
@ -1,10 +1,13 @@
|
||||||
package cn.iocoder.yudao.module.iot.controller.admin.thingmodel;
|
package cn.iocoder.yudao.module.iot.controller.admin.thingmodel;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.util.ObjUtil;
|
||||||
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.thingmodel.vo.*;
|
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.*;
|
||||||
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.thingmodel.IotThingModelTypeEnum;
|
||||||
import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService;
|
import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService;
|
||||||
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;
|
||||||
|
@ -18,6 +21,8 @@ import org.springframework.web.bind.annotation.*;
|
||||||
import java.util.List;
|
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.filterList;
|
||||||
|
|
||||||
@Tag(name = "管理后台 - IoT 产品物模型")
|
@Tag(name = "管理后台 - IoT 产品物模型")
|
||||||
@RestController
|
@RestController
|
||||||
|
@ -61,13 +66,31 @@ public class IotThingModelController {
|
||||||
return success(BeanUtils.toBean(thingModel, IotThingModelRespVO.class));
|
return success(BeanUtils.toBean(thingModel, IotThingModelRespVO.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @puhui999:要不叫 get-tsl,去掉 product-id;后续,把
|
@GetMapping("/get-tsl")
|
||||||
@GetMapping("/tsl-by-product-id")
|
|
||||||
@Operation(summary = "获得产品物模型 TSL")
|
@Operation(summary = "获得产品物模型 TSL")
|
||||||
@Parameter(name = "productId", description = "产品 ID", required = true, example = "1024")
|
@Parameter(name = "productId", description = "产品 ID", required = true, example = "1024")
|
||||||
@PreAuthorize("@ss.hasPermission('iot:thing-model:query')")
|
@PreAuthorize("@ss.hasPermission('iot:thing-model:query')")
|
||||||
public CommonResult<IotThingModelTSLRespVO> getThingModelTslByProductId(@RequestParam("productId") Long productId) {
|
public CommonResult<IotThingModelTSLRespVO> getThingModelTsl(@RequestParam("productId") Long productId) {
|
||||||
return success(thingModelService.getThingModelTslByProductId(productId));
|
IotThingModelTSLRespVO tslRespVO = new IotThingModelTSLRespVO();
|
||||||
|
// 1. 获得产品所有物模型定义
|
||||||
|
List<IotThingModelDO> thingModels = thingModelService.getThingModelListByProductId(productId);
|
||||||
|
if (CollUtil.isEmpty(thingModels)) {
|
||||||
|
return success(tslRespVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.1 设置公共部分参数
|
||||||
|
IotThingModelDO thingModel = thingModels.get(0);
|
||||||
|
tslRespVO.setProductId(thingModel.getProductId()).setProductKey(thingModel.getProductKey());
|
||||||
|
// 2.2 处理属性列表
|
||||||
|
tslRespVO.setProperties(convertList(filterList(thingModels, item ->
|
||||||
|
ObjUtil.equal(IotThingModelTypeEnum.PROPERTY.getType(), item.getType())), IotThingModelDO::getProperty));
|
||||||
|
// 2.3 处理服务列表
|
||||||
|
tslRespVO.setServices(convertList(filterList(thingModels, item ->
|
||||||
|
ObjUtil.equal(IotThingModelTypeEnum.SERVICE.getType(), item.getType())), IotThingModelDO::getService));
|
||||||
|
// 2.4 处理事件列表
|
||||||
|
tslRespVO.setEvents(convertList(filterList(thingModels, item ->
|
||||||
|
ObjUtil.equal(IotThingModelTypeEnum.EVENT.getType(), item.getType())), IotThingModelDO::getEvent));
|
||||||
|
return success(tslRespVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/list")
|
@GetMapping("/list")
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType;
|
package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Pattern;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@ -16,18 +20,17 @@ import java.util.List;
|
||||||
@JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复
|
@JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复
|
||||||
public class ThingModelArrayDataSpecs extends ThingModelDataSpecs {
|
public class ThingModelArrayDataSpecs extends ThingModelDataSpecs {
|
||||||
|
|
||||||
/**
|
@NotNull(message = "数组元素个数不能为空")
|
||||||
* 数组中的元素个数
|
|
||||||
*/
|
|
||||||
private Integer size;
|
private Integer size;
|
||||||
/**
|
|
||||||
* 数组中的元素的数据类型。可选值:struct、int、float、double 或 text
|
@NotEmpty(message = "数组元素的数据类型不能为空")
|
||||||
*/
|
@Pattern(regexp = "^(struct|int|float|double|text)$", message = "数组元素的数据类型必须为:struct、int、float、double 或 text")
|
||||||
private String childDataType;
|
private String childDataType;
|
||||||
/**
|
/**
|
||||||
* 数据类型(childDataType)为列表型 struct 的数据规范存储在 dataSpecsList 中
|
* 数据类型(childDataType)为列表型 struct 的数据规范存储在 dataSpecsList 中
|
||||||
* 此时 struct 取值范围为:int、float、double、text、date、enum、bool
|
* 此时 struct 取值范围为:int、float、double、text、date、enum、bool
|
||||||
*/
|
*/
|
||||||
|
@Valid
|
||||||
private List<ThingModelDataSpecs> dataSpecsList;
|
private List<ThingModelDataSpecs> dataSpecsList;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType;
|
package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Pattern;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@ -16,16 +19,12 @@ import lombok.EqualsAndHashCode;
|
||||||
@JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复
|
@JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复
|
||||||
public class ThingModelBoolOrEnumDataSpecs extends ThingModelDataSpecs {
|
public class ThingModelBoolOrEnumDataSpecs extends ThingModelDataSpecs {
|
||||||
|
|
||||||
// TODO @puhui999:要不写下参数校验?这样,注释可以简洁一点
|
@NotEmpty(message = "枚举项的名称不能为空")
|
||||||
/**
|
@Pattern(regexp = "^[\\u4e00-\\u9fa5a-zA-Z0-9][\\u4e00-\\u9fa5a-zA-Z0-9_-]{0,19}$",
|
||||||
* 枚举项的名称。
|
message = "枚举项的名称只能包含中文、大小写英文字母、数字、下划线和短划线,必须以中文、英文字母或数字开头,长度不超过 20 个字符")
|
||||||
* 可包含中文、大小写英文字母、数字、下划线(_)和短划线(-)
|
|
||||||
* 必须以中文、英文字母或数字开头,长度不超过 20 个字符
|
|
||||||
*/
|
|
||||||
private String name;
|
private String name;
|
||||||
/**
|
|
||||||
* 枚举值。
|
@NotNull(message = "枚举值不能为空")
|
||||||
*/
|
|
||||||
private Integer value;
|
private Integer value;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType;
|
package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import jakarta.validation.constraints.Max;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@ -20,6 +21,7 @@ public class ThingModelDateOrTextDataSpecs extends ThingModelDataSpecs {
|
||||||
* 数据长度,单位为字节。取值不能超过 2048。
|
* 数据长度,单位为字节。取值不能超过 2048。
|
||||||
* 当 dataType 为 text 时,需传入该参数。
|
* 当 dataType 为 text 时,需传入该参数。
|
||||||
*/
|
*/
|
||||||
|
@Max(value = 2048, message = "数据长度不能超过 2048")
|
||||||
private Integer length;
|
private Integer length;
|
||||||
/**
|
/**
|
||||||
* 默认值,可选参数,用于存储默认值。
|
* 默认值,可选参数,用于存储默认值。
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType;
|
package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.Pattern;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@ -18,18 +20,21 @@ public class ThingModelNumericDataSpec extends ThingModelDataSpecs {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 最大值,需转为字符串类型。值必须与 dataType 类型一致。
|
* 最大值,需转为字符串类型。值必须与 dataType 类型一致。
|
||||||
* 例如,当 dataType 为 int 时,取值为 "200",而不是 200。
|
|
||||||
*/
|
*/
|
||||||
|
@NotEmpty(message = "最大值不能为空")
|
||||||
|
@Pattern(regexp = "^-?\\d+(\\.\\d+)?$", message = "最大值必须为数值类型")
|
||||||
private String max;
|
private String max;
|
||||||
/**
|
/**
|
||||||
* 最小值,需转为字符串类型。值必须与 dataType 类型一致。
|
* 最小值,需转为字符串类型。值必须与 dataType 类型一致。
|
||||||
* 例如,当 dataType 为 int 时,取值为 "0",而不是 0。
|
|
||||||
*/
|
*/
|
||||||
|
@NotEmpty(message = "最小值不能为空")
|
||||||
|
@Pattern(regexp = "^-?\\d+(\\.\\d+)?$", message = "最小值必须为数值类型")
|
||||||
private String min;
|
private String min;
|
||||||
/**
|
/**
|
||||||
* 步长,需转为字符串类型。值必须与 dataType 类型一致。
|
* 步长,需转为字符串类型。值必须与 dataType 类型一致。
|
||||||
* 例如,当 dataType 为 int 时,取值为 "10",而不是 10。
|
|
||||||
*/
|
*/
|
||||||
|
@NotEmpty(message = "步长不能为空")
|
||||||
|
@Pattern(regexp = "^-?\\d+(\\.\\d+)?$", message = "步长必须为数值类型")
|
||||||
private String step;
|
private String step;
|
||||||
/**
|
/**
|
||||||
* 精度。当 dataType 为 float 或 double 时可选传入。
|
* 精度。当 dataType 为 float 或 double 时可选传入。
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType;
|
package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.dataType;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||||
import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelAccessModeEnum;
|
import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelAccessModeEnum;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.Pattern;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@ -17,35 +21,36 @@ import java.util.List;
|
||||||
@JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复
|
@JsonIgnoreProperties({"dataType"}) // 忽略子类中的 dataType 字段,从而避免重复
|
||||||
public class ThingModelStructDataSpecs extends ThingModelDataSpecs {
|
public class ThingModelStructDataSpecs extends ThingModelDataSpecs {
|
||||||
|
|
||||||
/**
|
@NotEmpty(message = "属性标识符不能为空")
|
||||||
* 属性标识符
|
@Pattern(regexp = "^[a-zA-Z][a-zA-Z0-9_]{0,31}$", message = "属性标识符只能由字母、数字和下划线组成,必须以字母开头,长度不超过 32 个字符")
|
||||||
*/
|
|
||||||
private String identifier;
|
private String identifier;
|
||||||
/**
|
|
||||||
* 属性名称
|
@NotEmpty(message = "属性名称不能为空")
|
||||||
*/
|
|
||||||
private String name;
|
private String name;
|
||||||
/**
|
|
||||||
* 云端可以对该属性进行的操作类型
|
@NotEmpty(message = "操作类型不能为空")
|
||||||
*
|
@InEnum(IotThingModelAccessModeEnum.class)
|
||||||
* 枚举 {@link IotThingModelAccessModeEnum}
|
|
||||||
*/
|
|
||||||
private String accessMode;
|
private String accessMode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否是标准品类的必选服务
|
* 是否是标准品类的必选服务
|
||||||
*/
|
*/
|
||||||
private Boolean required;
|
private Boolean required;
|
||||||
/**
|
|
||||||
* struct 数据的数据类型
|
@NotEmpty(message = "数据类型不能为空")
|
||||||
*/
|
@Pattern(regexp = "^(int|float|double|text|date|enum|bool)$", message = "数据类型必须为:int、float、double、text、date、enum、bool")
|
||||||
private String childDataType;
|
private String childDataType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据类型(dataType)为非列表型(int、float、double、text、date、array)的数据规范存储在 dataSpecs 中
|
* 数据类型(dataType)为非列表型(int、float、double、text、date、array)的数据规范存储在 dataSpecs 中
|
||||||
*/
|
*/
|
||||||
|
@Valid
|
||||||
private ThingModelDataSpecs dataSpecs;
|
private ThingModelDataSpecs dataSpecs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 数据类型(dataType)为列表型(enum、bool、struct)的数据规范存储在 dataSpecsList 中
|
* 数据类型(dataType)为列表型(enum、bool、struct)的数据规范存储在 dataSpecsList 中
|
||||||
*/
|
*/
|
||||||
|
@Valid
|
||||||
private List<ThingModelDataSpecs> dataSpecsList;
|
private List<ThingModelDataSpecs> dataSpecsList;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
package cn.iocoder.yudao.module.iot.dal.dataobject.rule;
|
package cn.iocoder.yudao.module.iot.dal.dataobject.rule;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
|
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneTriggerConfig;
|
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.enums.device.IotDeviceMessageIdentifierEnum;
|
||||||
|
import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageTypeEnum;
|
||||||
|
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
|
||||||
|
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerConditionParameterOperatorEnum;
|
||||||
|
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneTriggerTypeEnum;
|
||||||
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;
|
||||||
|
@ -14,13 +20,14 @@ import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IoT 规则场景(场景联动) DO
|
* IoT 场景联动 DO
|
||||||
*
|
*
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@TableName("iot_rule_scene")
|
@TableName(value = "iot_rule_scene", autoResultMap = true)
|
||||||
@KeySequence("iot_rule_scene_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
@KeySequence("iot_rule_scene_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||||
@Data
|
@Data
|
||||||
@Builder
|
@Builder
|
||||||
|
@ -52,12 +59,188 @@ public class IotRuleSceneDO extends TenantBaseDO {
|
||||||
* 触发器数组
|
* 触发器数组
|
||||||
*/
|
*/
|
||||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||||
private List<IotRuleSceneTriggerConfig> triggers;
|
private List<TriggerConfig> triggers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行器数组
|
* 执行器数组
|
||||||
*/
|
*/
|
||||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||||
private List<IotRuleSceneActionConfig> actions;
|
private List<ActionConfig> actions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发器配置
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class TriggerConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发类型
|
||||||
|
*
|
||||||
|
* 枚举 {@link IotRuleSceneTriggerTypeEnum}
|
||||||
|
*/
|
||||||
|
private Integer type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 产品标识
|
||||||
|
*
|
||||||
|
* 关联 {@link IotProductDO#getProductKey()}
|
||||||
|
*/
|
||||||
|
private String productKey;
|
||||||
|
/**
|
||||||
|
* 设备名称数组
|
||||||
|
*
|
||||||
|
* 关联 {@link IotDeviceDO#getDeviceName()}
|
||||||
|
*/
|
||||||
|
private List<String> deviceNames;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发条件数组
|
||||||
|
*
|
||||||
|
* 必填:当 {@link #type} 为 {@link IotRuleSceneTriggerTypeEnum#DEVICE} 时
|
||||||
|
* 条件与条件之间,是“或”的关系
|
||||||
|
*/
|
||||||
|
private List<TriggerCondition> conditions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CRON 表达式
|
||||||
|
*
|
||||||
|
* 必填:当 {@link #type} 为 {@link IotRuleSceneTriggerTypeEnum#TIMER} 时
|
||||||
|
*/
|
||||||
|
private String cronExpression;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发条件
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class TriggerCondition {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型
|
||||||
|
*
|
||||||
|
* 枚举 {@link IotDeviceMessageTypeEnum}
|
||||||
|
*/
|
||||||
|
private String type;
|
||||||
|
/**
|
||||||
|
* 消息标识符
|
||||||
|
*
|
||||||
|
* 枚举 {@link IotDeviceMessageIdentifierEnum}
|
||||||
|
*/
|
||||||
|
private String identifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数数组
|
||||||
|
*
|
||||||
|
* 参数与参数之间,是“或”的关系
|
||||||
|
*/
|
||||||
|
private List<TriggerConditionParameter> parameters;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发条件参数
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class TriggerConditionParameter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标识符(属性、事件、服务)
|
||||||
|
*
|
||||||
|
* 关联 {@link IotThingModelDO#getIdentifier()}
|
||||||
|
*/
|
||||||
|
private String identifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作符
|
||||||
|
*
|
||||||
|
* 枚举 {@link IotRuleSceneTriggerConditionParameterOperatorEnum}
|
||||||
|
*/
|
||||||
|
private String operator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 比较值
|
||||||
|
*
|
||||||
|
* 如果有多个值,则使用 "," 分隔,类似 "1,2,3"。
|
||||||
|
* 例如说,{@link IotRuleSceneTriggerConditionParameterOperatorEnum#IN}、{@link IotRuleSceneTriggerConditionParameterOperatorEnum#BETWEEN}
|
||||||
|
*/
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行器配置
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class ActionConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行类型
|
||||||
|
*
|
||||||
|
* 枚举 {@link IotRuleSceneActionTypeEnum}
|
||||||
|
*/
|
||||||
|
private Integer type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备控制
|
||||||
|
*
|
||||||
|
* 必填:当 {@link #type} 为 {@link IotRuleSceneActionTypeEnum#DEVICE_CONTROL} 时
|
||||||
|
*/
|
||||||
|
private ActionDeviceControl deviceControl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据桥接编号
|
||||||
|
*
|
||||||
|
* 必填:当 {@link #type} 为 {@link IotRuleSceneActionTypeEnum#DATA_BRIDGE} 时
|
||||||
|
* 关联:{@link IotDataBridgeDO#getId()}
|
||||||
|
*/
|
||||||
|
private Long dataBridgeId;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行设备控制
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class ActionDeviceControl {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 产品标识
|
||||||
|
*
|
||||||
|
* 关联 {@link IotProductDO#getProductKey()}
|
||||||
|
*/
|
||||||
|
private String productKey;
|
||||||
|
/**
|
||||||
|
* 设备名称数组
|
||||||
|
*
|
||||||
|
* 关联 {@link IotDeviceDO#getDeviceName()}
|
||||||
|
*/
|
||||||
|
private List<String> deviceNames;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型
|
||||||
|
*
|
||||||
|
* 枚举 {@link IotDeviceMessageTypeEnum#PROPERTY}、{@link IotDeviceMessageTypeEnum#SERVICE}
|
||||||
|
*/
|
||||||
|
private String type;
|
||||||
|
/**
|
||||||
|
* 消息标识符
|
||||||
|
*
|
||||||
|
* 枚举 {@link IotDeviceMessageIdentifierEnum}
|
||||||
|
*
|
||||||
|
* 1. 属性设置:对应 {@link IotDeviceMessageIdentifierEnum#PROPERTY_SET}
|
||||||
|
* 2. 服务调用:对应 {@link IotDeviceMessageIdentifierEnum#SERVICE_INVOKE}
|
||||||
|
*/
|
||||||
|
private String identifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 具体数据
|
||||||
|
*
|
||||||
|
* 1. 属性设置:在 {@link #type} 是 {@link IotDeviceMessageTypeEnum#PROPERTY} 时,对应 properties
|
||||||
|
* 2. 服务调用:在 {@link #type} 是 {@link IotDeviceMessageTypeEnum#SERVICE} 时,对应 params
|
||||||
|
*/
|
||||||
|
private Map<String, Object> data;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IoT 规则场景(场景联动) Mapper
|
* IoT 场景联动 Mapper
|
||||||
*
|
*
|
||||||
* @author HUIHUI
|
* @author HUIHUI
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -18,7 +18,7 @@ import java.util.List;
|
||||||
public interface IotRuleSceneService {
|
public interface IotRuleSceneService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建规则场景(场景联动)
|
* 创建场景联动
|
||||||
*
|
*
|
||||||
* @param createReqVO 创建信息
|
* @param createReqVO 创建信息
|
||||||
* @return 编号
|
* @return 编号
|
||||||
|
@ -26,32 +26,32 @@ public interface IotRuleSceneService {
|
||||||
Long createRuleScene(@Valid IotRuleSceneSaveReqVO createReqVO);
|
Long createRuleScene(@Valid IotRuleSceneSaveReqVO createReqVO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新规则场景(场景联动)
|
* 更新场景联动
|
||||||
*
|
*
|
||||||
* @param updateReqVO 更新信息
|
* @param updateReqVO 更新信息
|
||||||
*/
|
*/
|
||||||
void updateRuleScene(@Valid IotRuleSceneSaveReqVO updateReqVO);
|
void updateRuleScene(@Valid IotRuleSceneSaveReqVO updateReqVO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除规则场景(场景联动)
|
* 删除场景联动
|
||||||
*
|
*
|
||||||
* @param id 编号
|
* @param id 编号
|
||||||
*/
|
*/
|
||||||
void deleteRuleScene(Long id);
|
void deleteRuleScene(Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得规则场景(场景联动)
|
* 获得场景联动
|
||||||
*
|
*
|
||||||
* @param id 编号
|
* @param id 编号
|
||||||
* @return 规则场景(场景联动)
|
* @return 场景联动
|
||||||
*/
|
*/
|
||||||
IotRuleSceneDO getRuleScene(Long id);
|
IotRuleSceneDO getRuleScene(Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得规则场景(场景联动)分页
|
* 获得场景联动分页
|
||||||
*
|
*
|
||||||
* @param pageReqVO 分页查询
|
* @param pageReqVO 分页查询
|
||||||
* @return 规则场景(场景联动)分页
|
* @return 场景联动分页
|
||||||
*/
|
*/
|
||||||
PageResult<IotRuleSceneDO> getRuleScenePage(IotRuleScenePageReqVO pageReqVO);
|
PageResult<IotRuleSceneDO> getRuleScenePage(IotRuleScenePageReqVO pageReqVO);
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ 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.IotRuleScenePageReqVO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO;
|
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.IotRuleSceneSaveReqVO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.*;
|
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
|
||||||
import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotRuleSceneMapper;
|
import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotRuleSceneMapper;
|
||||||
import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum;
|
import cn.iocoder.yudao.module.iot.enums.device.IotDeviceMessageIdentifierEnum;
|
||||||
|
@ -118,82 +117,82 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
|
||||||
if (true) {
|
if (true) {
|
||||||
IotRuleSceneDO ruleScene01 = new IotRuleSceneDO();
|
IotRuleSceneDO ruleScene01 = new IotRuleSceneDO();
|
||||||
ruleScene01.setTriggers(CollUtil.newArrayList());
|
ruleScene01.setTriggers(CollUtil.newArrayList());
|
||||||
IotRuleSceneTriggerConfig trigger01 = new IotRuleSceneTriggerConfig();
|
IotRuleSceneDO.TriggerConfig trigger01 = new IotRuleSceneDO.TriggerConfig();
|
||||||
trigger01.setType(IotRuleSceneTriggerTypeEnum.DEVICE.getType());
|
trigger01.setType(IotRuleSceneTriggerTypeEnum.DEVICE.getType());
|
||||||
trigger01.setConditions(CollUtil.newArrayList());
|
trigger01.setConditions(CollUtil.newArrayList());
|
||||||
// 属性
|
// 属性
|
||||||
IotRuleSceneTriggerCondition condition01 = new IotRuleSceneTriggerCondition();
|
IotRuleSceneDO.TriggerCondition condition01 = new IotRuleSceneDO.TriggerCondition();
|
||||||
condition01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType());
|
condition01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType());
|
||||||
condition01.setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_REPORT.getIdentifier());
|
condition01.setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_REPORT.getIdentifier());
|
||||||
condition01.setParameters(CollUtil.newArrayList());
|
condition01.setParameters(CollUtil.newArrayList());
|
||||||
// IotRuleSceneTriggerConditionParameter parameter010 = new IotRuleSceneTriggerConditionParameter();
|
// IotRuleSceneDO.TriggerConditionParameter parameter010 = new IotRuleSceneDO.TriggerConditionParameter();
|
||||||
// parameter010.setIdentifier("width");
|
// parameter010.setIdentifier("width");
|
||||||
// parameter010.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator());
|
// parameter010.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator());
|
||||||
// parameter010.setValue("abc");
|
// parameter010.setValue("abc");
|
||||||
// condition01.getParameters().add(parameter010);
|
// condition01.getParameters().add(parameter010);
|
||||||
IotRuleSceneTriggerConditionParameter parameter011 = new IotRuleSceneTriggerConditionParameter();
|
IotRuleSceneDO.TriggerConditionParameter parameter011 = new IotRuleSceneDO.TriggerConditionParameter();
|
||||||
parameter011.setIdentifier("width");
|
parameter011.setIdentifier("width");
|
||||||
parameter011.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator());
|
parameter011.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator());
|
||||||
parameter011.setValue("1");
|
parameter011.setValue("1");
|
||||||
condition01.getParameters().add(parameter011);
|
condition01.getParameters().add(parameter011);
|
||||||
IotRuleSceneTriggerConditionParameter parameter012 = new IotRuleSceneTriggerConditionParameter();
|
IotRuleSceneDO.TriggerConditionParameter parameter012 = new IotRuleSceneDO.TriggerConditionParameter();
|
||||||
parameter012.setIdentifier("width");
|
parameter012.setIdentifier("width");
|
||||||
parameter012.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_EQUALS.getOperator());
|
parameter012.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_EQUALS.getOperator());
|
||||||
parameter012.setValue("2");
|
parameter012.setValue("2");
|
||||||
condition01.getParameters().add(parameter012);
|
condition01.getParameters().add(parameter012);
|
||||||
IotRuleSceneTriggerConditionParameter parameter013 = new IotRuleSceneTriggerConditionParameter();
|
IotRuleSceneDO.TriggerConditionParameter parameter013 = new IotRuleSceneDO.TriggerConditionParameter();
|
||||||
parameter013.setIdentifier("width");
|
parameter013.setIdentifier("width");
|
||||||
parameter013.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.GREATER_THAN.getOperator());
|
parameter013.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.GREATER_THAN.getOperator());
|
||||||
parameter013.setValue("0");
|
parameter013.setValue("0");
|
||||||
condition01.getParameters().add(parameter013);
|
condition01.getParameters().add(parameter013);
|
||||||
IotRuleSceneTriggerConditionParameter parameter014 = new IotRuleSceneTriggerConditionParameter();
|
IotRuleSceneDO.TriggerConditionParameter parameter014 = new IotRuleSceneDO.TriggerConditionParameter();
|
||||||
parameter014.setIdentifier("width");
|
parameter014.setIdentifier("width");
|
||||||
parameter014.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.GREATER_THAN_OR_EQUALS.getOperator());
|
parameter014.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.GREATER_THAN_OR_EQUALS.getOperator());
|
||||||
parameter014.setValue("0");
|
parameter014.setValue("0");
|
||||||
condition01.getParameters().add(parameter014);
|
condition01.getParameters().add(parameter014);
|
||||||
IotRuleSceneTriggerConditionParameter parameter015 = new IotRuleSceneTriggerConditionParameter();
|
IotRuleSceneDO.TriggerConditionParameter parameter015 = new IotRuleSceneDO.TriggerConditionParameter();
|
||||||
parameter015.setIdentifier("width");
|
parameter015.setIdentifier("width");
|
||||||
parameter015.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.LESS_THAN.getOperator());
|
parameter015.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.LESS_THAN.getOperator());
|
||||||
parameter015.setValue("2");
|
parameter015.setValue("2");
|
||||||
condition01.getParameters().add(parameter015);
|
condition01.getParameters().add(parameter015);
|
||||||
IotRuleSceneTriggerConditionParameter parameter016 = new IotRuleSceneTriggerConditionParameter();
|
IotRuleSceneDO.TriggerConditionParameter parameter016 = new IotRuleSceneDO.TriggerConditionParameter();
|
||||||
parameter016.setIdentifier("width");
|
parameter016.setIdentifier("width");
|
||||||
parameter016.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.LESS_THAN_OR_EQUALS.getOperator());
|
parameter016.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.LESS_THAN_OR_EQUALS.getOperator());
|
||||||
parameter016.setValue("2");
|
parameter016.setValue("2");
|
||||||
condition01.getParameters().add(parameter016);
|
condition01.getParameters().add(parameter016);
|
||||||
IotRuleSceneTriggerConditionParameter parameter017 = new IotRuleSceneTriggerConditionParameter();
|
IotRuleSceneDO.TriggerConditionParameter parameter017 = new IotRuleSceneDO.TriggerConditionParameter();
|
||||||
parameter017.setIdentifier("width");
|
parameter017.setIdentifier("width");
|
||||||
parameter017.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.IN.getOperator());
|
parameter017.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.IN.getOperator());
|
||||||
parameter017.setValue("1,2,3");
|
parameter017.setValue("1,2,3");
|
||||||
condition01.getParameters().add(parameter017);
|
condition01.getParameters().add(parameter017);
|
||||||
IotRuleSceneTriggerConditionParameter parameter018 = new IotRuleSceneTriggerConditionParameter();
|
IotRuleSceneDO.TriggerConditionParameter parameter018 = new IotRuleSceneDO.TriggerConditionParameter();
|
||||||
parameter018.setIdentifier("width");
|
parameter018.setIdentifier("width");
|
||||||
parameter018.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_IN.getOperator());
|
parameter018.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_IN.getOperator());
|
||||||
parameter018.setValue("0,2,3");
|
parameter018.setValue("0,2,3");
|
||||||
condition01.getParameters().add(parameter018);
|
condition01.getParameters().add(parameter018);
|
||||||
IotRuleSceneTriggerConditionParameter parameter019 = new IotRuleSceneTriggerConditionParameter();
|
IotRuleSceneDO.TriggerConditionParameter parameter019 = new IotRuleSceneDO.TriggerConditionParameter();
|
||||||
parameter019.setIdentifier("width");
|
parameter019.setIdentifier("width");
|
||||||
parameter019.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.BETWEEN.getOperator());
|
parameter019.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.BETWEEN.getOperator());
|
||||||
parameter019.setValue("1,3");
|
parameter019.setValue("1,3");
|
||||||
condition01.getParameters().add(parameter019);
|
condition01.getParameters().add(parameter019);
|
||||||
IotRuleSceneTriggerConditionParameter parameter020 = new IotRuleSceneTriggerConditionParameter();
|
IotRuleSceneDO.TriggerConditionParameter parameter020 = new IotRuleSceneDO.TriggerConditionParameter();
|
||||||
parameter020.setIdentifier("width");
|
parameter020.setIdentifier("width");
|
||||||
parameter020.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_BETWEEN.getOperator());
|
parameter020.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.NOT_BETWEEN.getOperator());
|
||||||
parameter020.setValue("2,3");
|
parameter020.setValue("2,3");
|
||||||
condition01.getParameters().add(parameter020);
|
condition01.getParameters().add(parameter020);
|
||||||
trigger01.getConditions().add(condition01);
|
trigger01.getConditions().add(condition01);
|
||||||
// 状态
|
// 状态
|
||||||
IotRuleSceneTriggerCondition condition02 = new IotRuleSceneTriggerCondition();
|
IotRuleSceneDO.TriggerCondition condition02 = new IotRuleSceneDO.TriggerCondition();
|
||||||
condition02.setType(IotDeviceMessageTypeEnum.STATE.getType());
|
condition02.setType(IotDeviceMessageTypeEnum.STATE.getType());
|
||||||
condition02.setIdentifier(IotDeviceMessageIdentifierEnum.STATE_ONLINE.getIdentifier());
|
condition02.setIdentifier(IotDeviceMessageIdentifierEnum.STATE_ONLINE.getIdentifier());
|
||||||
condition02.setParameters(CollUtil.newArrayList());
|
condition02.setParameters(CollUtil.newArrayList());
|
||||||
trigger01.getConditions().add(condition02);
|
trigger01.getConditions().add(condition02);
|
||||||
// 事件
|
// 事件
|
||||||
IotRuleSceneTriggerCondition condition03 = new IotRuleSceneTriggerCondition();
|
IotRuleSceneDO.TriggerCondition condition03 = new IotRuleSceneDO.TriggerCondition();
|
||||||
condition03.setType(IotDeviceMessageTypeEnum.EVENT.getType());
|
condition03.setType(IotDeviceMessageTypeEnum.EVENT.getType());
|
||||||
condition03.setIdentifier("xxx");
|
condition03.setIdentifier("xxx");
|
||||||
condition03.setParameters(CollUtil.newArrayList());
|
condition03.setParameters(CollUtil.newArrayList());
|
||||||
IotRuleSceneTriggerConditionParameter parameter030 = new IotRuleSceneTriggerConditionParameter();
|
IotRuleSceneDO.TriggerConditionParameter parameter030 = new IotRuleSceneDO.TriggerConditionParameter();
|
||||||
parameter030.setIdentifier("width");
|
parameter030.setIdentifier("width");
|
||||||
parameter030.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator());
|
parameter030.setOperator(IotRuleSceneTriggerConditionParameterOperatorEnum.EQUALS.getOperator());
|
||||||
parameter030.setValue("1");
|
parameter030.setValue("1");
|
||||||
|
@ -202,21 +201,21 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
|
||||||
// 动作
|
// 动作
|
||||||
ruleScene01.setActions(CollUtil.newArrayList());
|
ruleScene01.setActions(CollUtil.newArrayList());
|
||||||
// 设备控制
|
// 设备控制
|
||||||
IotRuleSceneActionConfig action01 = new IotRuleSceneActionConfig();
|
IotRuleSceneDO.ActionConfig action01 = new IotRuleSceneDO.ActionConfig();
|
||||||
action01.setType(IotRuleSceneActionTypeEnum.DEVICE_CONTROL.getType());
|
action01.setType(IotRuleSceneActionTypeEnum.DEVICE_CONTROL.getType());
|
||||||
IotRuleSceneActionDeviceControl iotRuleSceneActionDeviceControl01 = new IotRuleSceneActionDeviceControl();
|
IotRuleSceneDO.ActionDeviceControl actionDeviceControl01 = new IotRuleSceneDO.ActionDeviceControl();
|
||||||
iotRuleSceneActionDeviceControl01.setProductKey("4aymZgOTOOCrDKRT");
|
actionDeviceControl01.setProductKey("4aymZgOTOOCrDKRT");
|
||||||
iotRuleSceneActionDeviceControl01.setDeviceNames(ListUtil.of("small"));
|
actionDeviceControl01.setDeviceNames(ListUtil.of("small"));
|
||||||
iotRuleSceneActionDeviceControl01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType());
|
actionDeviceControl01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType());
|
||||||
iotRuleSceneActionDeviceControl01.setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_SET.getIdentifier());
|
actionDeviceControl01.setIdentifier(IotDeviceMessageIdentifierEnum.PROPERTY_SET.getIdentifier());
|
||||||
iotRuleSceneActionDeviceControl01.setData(MapUtil.<String, Object>builder()
|
actionDeviceControl01.setData(MapUtil.<String, Object>builder()
|
||||||
.put("power", 1)
|
.put("power", 1)
|
||||||
.put("color", "red")
|
.put("color", "red")
|
||||||
.build());
|
.build());
|
||||||
action01.setDeviceControl(iotRuleSceneActionDeviceControl01);
|
action01.setDeviceControl(actionDeviceControl01);
|
||||||
// ruleScene01.getActions().add(action01); // TODO 芋艿:先不测试了
|
// ruleScene01.getActions().add(action01); // TODO 芋艿:先不测试了
|
||||||
// 数据桥接(http)
|
// 数据桥接(http)
|
||||||
IotRuleSceneActionConfig action02 = new IotRuleSceneActionConfig();
|
IotRuleSceneDO.ActionConfig action02 = new IotRuleSceneDO.ActionConfig();
|
||||||
action02.setType(IotRuleSceneActionTypeEnum.DATA_BRIDGE.getType());
|
action02.setType(IotRuleSceneActionTypeEnum.DATA_BRIDGE.getType());
|
||||||
action02.setDataBridgeId(1L);
|
action02.setDataBridgeId(1L);
|
||||||
ruleScene01.getActions().add(action02);
|
ruleScene01.getActions().add(action02);
|
||||||
|
@ -226,7 +225,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
|
||||||
List<IotRuleSceneDO> list = ruleSceneMapper.selectList();
|
List<IotRuleSceneDO> list = ruleSceneMapper.selectList();
|
||||||
// TODO @芋艿:需要考虑开启状态
|
// TODO @芋艿:需要考虑开启状态
|
||||||
return filterList(list, ruleScene -> {
|
return filterList(list, ruleScene -> {
|
||||||
for (IotRuleSceneTriggerConfig trigger : ruleScene.getTriggers()) {
|
for (IotRuleSceneDO.TriggerConfig trigger : ruleScene.getTriggers()) {
|
||||||
if (ObjUtil.notEqual(trigger.getProductKey(), productKey)) {
|
if (ObjUtil.notEqual(trigger.getProductKey(), productKey)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -261,13 +260,13 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
|
||||||
IotRuleSceneDO scene = new IotRuleSceneDO().setStatus(CommonStatusEnum.ENABLE.getStatus());
|
IotRuleSceneDO scene = new IotRuleSceneDO().setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
if (true) {
|
if (true) {
|
||||||
scene.setTenantId(1L);
|
scene.setTenantId(1L);
|
||||||
IotRuleSceneTriggerConfig iotRuleSceneTriggerConfig = new IotRuleSceneTriggerConfig();
|
IotRuleSceneDO.TriggerConfig triggerConfig = new IotRuleSceneDO.TriggerConfig();
|
||||||
iotRuleSceneTriggerConfig.setType(IotRuleSceneTriggerTypeEnum.TIMER.getType());
|
triggerConfig.setType(IotRuleSceneTriggerTypeEnum.TIMER.getType());
|
||||||
scene.setTriggers(ListUtil.toList(iotRuleSceneTriggerConfig));
|
scene.setTriggers(ListUtil.toList(triggerConfig));
|
||||||
// 动作
|
// 动作
|
||||||
IotRuleSceneActionConfig action01 = new IotRuleSceneActionConfig();
|
IotRuleSceneDO.ActionConfig action01 = new IotRuleSceneDO.ActionConfig();
|
||||||
action01.setType(IotRuleSceneActionTypeEnum.DEVICE_CONTROL.getType());
|
action01.setType(IotRuleSceneActionTypeEnum.DEVICE_CONTROL.getType());
|
||||||
IotRuleSceneActionDeviceControl iotRuleSceneActionDeviceControl01 = new IotRuleSceneActionDeviceControl();
|
IotRuleSceneDO.ActionDeviceControl iotRuleSceneActionDeviceControl01 = new IotRuleSceneDO.ActionDeviceControl();
|
||||||
iotRuleSceneActionDeviceControl01.setProductKey("4aymZgOTOOCrDKRT");
|
iotRuleSceneActionDeviceControl01.setProductKey("4aymZgOTOOCrDKRT");
|
||||||
iotRuleSceneActionDeviceControl01.setDeviceNames(ListUtil.of("small"));
|
iotRuleSceneActionDeviceControl01.setDeviceNames(ListUtil.of("small"));
|
||||||
iotRuleSceneActionDeviceControl01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType());
|
iotRuleSceneActionDeviceControl01.setType(IotDeviceMessageTypeEnum.PROPERTY.getType());
|
||||||
|
@ -288,7 +287,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 1.2 判断是否有定时触发器,避免脏数据
|
// 1.2 判断是否有定时触发器,避免脏数据
|
||||||
IotRuleSceneTriggerConfig config = CollUtil.findOne(scene.getTriggers(),
|
IotRuleSceneDO.TriggerConfig config = CollUtil.findOne(scene.getTriggers(),
|
||||||
trigger -> ObjUtil.equals(trigger.getType(), IotRuleSceneTriggerTypeEnum.TIMER.getType()));
|
trigger -> ObjUtil.equals(trigger.getType(), IotRuleSceneTriggerTypeEnum.TIMER.getType()));
|
||||||
if (config == null) {
|
if (config == null) {
|
||||||
log.error("[executeRuleSceneByTimer][规则场景({}) 不存在定时触发器]", scene);
|
log.error("[executeRuleSceneByTimer][规则场景({}) 不存在定时触发器]", scene);
|
||||||
|
@ -317,7 +316,7 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
|
||||||
|
|
||||||
// 2. 匹配 trigger 触发器的条件
|
// 2. 匹配 trigger 触发器的条件
|
||||||
return filterList(ruleScenes, ruleScene -> {
|
return filterList(ruleScenes, ruleScene -> {
|
||||||
for (IotRuleSceneTriggerConfig trigger : ruleScene.getTriggers()) {
|
for (IotRuleSceneDO.TriggerConfig trigger : ruleScene.getTriggers()) {
|
||||||
// 2.1 非设备触发,不匹配
|
// 2.1 非设备触发,不匹配
|
||||||
if (ObjUtil.notEqual(trigger.getType(), IotRuleSceneTriggerTypeEnum.DEVICE.getType())) {
|
if (ObjUtil.notEqual(trigger.getType(), IotRuleSceneTriggerTypeEnum.DEVICE.getType())) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -328,13 +327,13 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 2.3 多个条件,只需要满足一个即可
|
// 2.3 多个条件,只需要满足一个即可
|
||||||
IotRuleSceneTriggerCondition matchedCondition = CollUtil.findOne(trigger.getConditions(), condition -> {
|
IotRuleSceneDO.TriggerCondition matchedCondition = CollUtil.findOne(trigger.getConditions(), condition -> {
|
||||||
if (ObjUtil.notEqual(message.getType(), condition.getType())
|
if (ObjUtil.notEqual(message.getType(), condition.getType())
|
||||||
|| ObjUtil.notEqual(message.getIdentifier(), condition.getIdentifier())) {
|
|| ObjUtil.notEqual(message.getIdentifier(), condition.getIdentifier())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 多个条件参数,必须全部满足。所以,下面的逻辑就是找到一个不满足的条件参数
|
// 多个条件参数,必须全部满足。所以,下面的逻辑就是找到一个不满足的条件参数
|
||||||
IotRuleSceneTriggerConditionParameter notMatchedParameter = CollUtil.findOne(condition.getParameters(),
|
IotRuleSceneDO.TriggerConditionParameter notMatchedParameter = CollUtil.findOne(condition.getParameters(),
|
||||||
parameter -> !isTriggerConditionParameterMatched(message, parameter, ruleScene, trigger));
|
parameter -> !isTriggerConditionParameterMatched(message, parameter, ruleScene, trigger));
|
||||||
return notMatchedParameter == null;
|
return notMatchedParameter == null;
|
||||||
});
|
});
|
||||||
|
@ -360,8 +359,8 @@ public class IotRuleSceneServiceImpl implements IotRuleSceneService {
|
||||||
* @return 是否匹配
|
* @return 是否匹配
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({"unchecked", "DataFlowIssue"})
|
@SuppressWarnings({"unchecked", "DataFlowIssue"})
|
||||||
private boolean isTriggerConditionParameterMatched(IotDeviceMessage message, IotRuleSceneTriggerConditionParameter parameter,
|
private boolean isTriggerConditionParameterMatched(IotDeviceMessage message, IotRuleSceneDO.TriggerConditionParameter parameter,
|
||||||
IotRuleSceneDO ruleScene, IotRuleSceneTriggerConfig trigger) {
|
IotRuleSceneDO ruleScene, IotRuleSceneDO.TriggerConfig trigger) {
|
||||||
// 1.1 校验操作符是否合法
|
// 1.1 校验操作符是否合法
|
||||||
IotRuleSceneTriggerConditionParameterOperatorEnum operator =
|
IotRuleSceneTriggerConditionParameterOperatorEnum operator =
|
||||||
IotRuleSceneTriggerConditionParameterOperatorEnum.operatorOf(parameter.getOperator());
|
IotRuleSceneTriggerConditionParameterOperatorEnum.operatorOf(parameter.getOperator());
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.iot.service.rule.action;
|
package cn.iocoder.yudao.module.iot.service.rule.action;
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
|
||||||
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
|
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
|
||||||
import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
|
import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ public interface IotRuleSceneAction {
|
||||||
* 2. 非空的情况:设备触发
|
* 2. 非空的情况:设备触发
|
||||||
* @param config 配置
|
* @param config 配置
|
||||||
*/
|
*/
|
||||||
void execute(@Nullable IotDeviceMessage message, IotRuleSceneActionConfig config) throws Exception;
|
void execute(@Nullable IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) throws Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得类型
|
* 获得类型
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.iot.service.rule.action;
|
package cn.iocoder.yudao.module.iot.service.rule.action;
|
||||||
|
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
|
||||||
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
|
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
|
||||||
import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
|
import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
@ -16,7 +16,7 @@ import javax.annotation.Nullable;
|
||||||
public class IotRuleSceneAlertAction implements IotRuleSceneAction {
|
public class IotRuleSceneAlertAction implements IotRuleSceneAction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(@Nullable IotDeviceMessage message, IotRuleSceneActionConfig config) {
|
public void execute(@Nullable IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) {
|
||||||
// TODO @芋艿:待实现
|
// TODO @芋艿:待实现
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.iot.service.rule.action;
|
||||||
|
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig;
|
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataBridgeDO;
|
||||||
|
import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotRuleSceneDO;
|
||||||
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
|
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
|
||||||
import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
|
import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
|
||||||
import cn.iocoder.yudao.module.iot.service.rule.IotDataBridgeService;
|
import cn.iocoder.yudao.module.iot.service.rule.IotDataBridgeService;
|
||||||
|
@ -29,7 +29,7 @@ public class IotRuleSceneDataBridgeAction implements IotRuleSceneAction {
|
||||||
private List<IotDataBridgeExecute<?>> dataBridgeExecutes;
|
private List<IotDataBridgeExecute<?>> dataBridgeExecutes;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(IotDeviceMessage message, IotRuleSceneActionConfig config) throws Exception {
|
public void execute(IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) throws Exception {
|
||||||
// 1.1 如果消息为空,直接返回
|
// 1.1 如果消息为空,直接返回
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -2,9 +2,8 @@ package cn.iocoder.yudao.module.iot.service.rule.action;
|
||||||
|
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceDownstreamReqVO;
|
import cn.iocoder.yudao.module.iot.controller.admin.device.vo.control.IotDeviceDownstreamReqVO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionConfig;
|
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.scene.config.IotRuleSceneActionDeviceControl;
|
|
||||||
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.rule.IotRuleSceneDO;
|
||||||
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
|
import cn.iocoder.yudao.module.iot.enums.rule.IotRuleSceneActionTypeEnum;
|
||||||
import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
|
import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
|
||||||
import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
|
import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
|
||||||
|
@ -28,8 +27,8 @@ public class IotRuleSceneDeviceControlAction implements IotRuleSceneAction {
|
||||||
private IotDeviceService deviceService;
|
private IotDeviceService deviceService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(IotDeviceMessage message, IotRuleSceneActionConfig config) {
|
public void execute(IotDeviceMessage message, IotRuleSceneDO.ActionConfig config) {
|
||||||
IotRuleSceneActionDeviceControl control = config.getDeviceControl();
|
IotRuleSceneDO.ActionDeviceControl control = config.getDeviceControl();
|
||||||
Assert.notNull(control, "设备控制配置不能为空");
|
Assert.notNull(control, "设备控制配置不能为空");
|
||||||
// 遍历每个设备,下发消息
|
// 遍历每个设备,下发消息
|
||||||
control.getDeviceNames().forEach(deviceName -> {
|
control.getDeviceNames().forEach(deviceName -> {
|
||||||
|
|
|
@ -101,7 +101,7 @@ public abstract class AbstractCacheableDataBridgeExecute<Config, Producer> imple
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings({"unchecked"})
|
@SuppressWarnings({"unchecked"})
|
||||||
public void execute(IotDeviceMessage message, IotDataBridgeDO dataBridge) {
|
public void execute(IotDeviceMessage message, IotDataBridgeDO dataBridge) {
|
||||||
if (ObjUtil.notEqual(message.getType(), getType())) {
|
if (ObjUtil.notEqual(dataBridge.getType(), getType())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
package cn.iocoder.yudao.module.iot.service.rule.action.databridge;
|
package cn.iocoder.yudao.module.iot.service.rule.action.databridge;
|
||||||
|
|
||||||
import cn.hutool.core.util.ReflectUtil;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeRedisStreamMQConfig;
|
import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.databridge.config.IotDataBridgeRedisStreamConfig;
|
||||||
import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeTypeEnum;
|
import cn.iocoder.yudao.module.iot.enums.rule.IotDataBridgeTypeEnum;
|
||||||
import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
|
import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.redisson.Redisson;
|
import org.redisson.Redisson;
|
||||||
import org.redisson.api.RedissonClient;
|
import org.redisson.api.RedissonClient;
|
||||||
|
@ -21,14 +18,14 @@ import org.springframework.data.redis.serializer.RedisSerializer;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redis Stream MQ 的 {@link IotDataBridgeExecute} 实现类
|
* Redis Stream 的 {@link IotDataBridgeExecute} 实现类
|
||||||
*
|
*
|
||||||
* @author HUIHUI
|
* @author HUIHUI
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class IotRedisStreamMQDataBridgeExecute extends
|
public class IotRedisStreamDataBridgeExecute extends
|
||||||
AbstractCacheableDataBridgeExecute<IotDataBridgeRedisStreamMQConfig, RedisTemplate<String, Object>> {
|
AbstractCacheableDataBridgeExecute<IotDataBridgeRedisStreamConfig, RedisTemplate<String, Object>> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Integer getType() {
|
public Integer getType() {
|
||||||
|
@ -36,7 +33,7 @@ public class IotRedisStreamMQDataBridgeExecute extends
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute0(IotDeviceMessage message, IotDataBridgeRedisStreamMQConfig config) throws Exception {
|
public void execute0(IotDeviceMessage message, IotDataBridgeRedisStreamConfig config) throws Exception {
|
||||||
// 1. 获取 RedisTemplate
|
// 1. 获取 RedisTemplate
|
||||||
RedisTemplate<String, Object> redisTemplate = getProducer(config);
|
RedisTemplate<String, Object> redisTemplate = getProducer(config);
|
||||||
|
|
||||||
|
@ -48,7 +45,7 @@ public class IotRedisStreamMQDataBridgeExecute extends
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RedisTemplate<String, Object> initProducer(IotDataBridgeRedisStreamMQConfig config) {
|
protected RedisTemplate<String, Object> initProducer(IotDataBridgeRedisStreamConfig config) {
|
||||||
// 1.1 创建 Redisson 配置
|
// 1.1 创建 Redisson 配置
|
||||||
Config redissonConfig = new Config();
|
Config redissonConfig = new Config();
|
||||||
SingleServerConfig serverConfig = redissonConfig.useSingleServer()
|
SingleServerConfig serverConfig = redissonConfig.useSingleServer()
|
||||||
|
@ -59,20 +56,17 @@ public class IotRedisStreamMQDataBridgeExecute extends
|
||||||
serverConfig.setPassword(config.getPassword());
|
serverConfig.setPassword(config.getPassword());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @huihui:看看能不能简化一些。按道理说,不用这么多的哈。
|
// TODO @芋艿:看看怎么优化
|
||||||
// 2.1 创建 RedissonClient
|
// 创建 RedisTemplate 并配置
|
||||||
RedissonClient redisson = Redisson.create(redissonConfig);
|
RedissonClient redisson = Redisson.create(redissonConfig);
|
||||||
// 2.2 创建并配置 RedisTemplate
|
|
||||||
RedisTemplate<String, Object> template = new RedisTemplate<>();
|
RedisTemplate<String, Object> template = new RedisTemplate<>();
|
||||||
// 设置 RedisConnection 工厂。😈 它就是实现多种 Java Redis 客户端接入的秘密工厂。感兴趣的胖友,可以自己去撸下。
|
|
||||||
template.setConnectionFactory(new RedissonConnectionFactory(redisson));
|
template.setConnectionFactory(new RedissonConnectionFactory(redisson));
|
||||||
// 使用 String 序列化方式,序列化 KEY 。
|
// 设置序列化器
|
||||||
template.setKeySerializer(RedisSerializer.string());
|
template.setKeySerializer(RedisSerializer.string());
|
||||||
template.setHashKeySerializer(RedisSerializer.string());
|
template.setHashKeySerializer(RedisSerializer.string());
|
||||||
// 使用 JSON 序列化方式(库是 Jackson ),序列化 VALUE 。
|
template.setValueSerializer(RedisSerializer.json());
|
||||||
template.setValueSerializer(buildRedisSerializer());
|
template.setHashValueSerializer(RedisSerializer.json());
|
||||||
template.setHashValueSerializer(buildRedisSerializer());
|
template.afterPropertiesSet();
|
||||||
template.afterPropertiesSet();// 初始化
|
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,13 +78,4 @@ public class IotRedisStreamMQDataBridgeExecute extends
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @huihui:看看能不能简化一些。按道理说,不用这么多的哈。
|
|
||||||
public static RedisSerializer<?> buildRedisSerializer() {
|
|
||||||
RedisSerializer<Object> json = RedisSerializer.json();
|
|
||||||
// 解决 LocalDateTime 的序列化
|
|
||||||
ObjectMapper objectMapper = (ObjectMapper) ReflectUtil.getFieldValue(json, "mapper");
|
|
||||||
objectMapper.registerModules(new JavaTimeModule());
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO;
|
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO;
|
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO;
|
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelTSLRespVO;
|
|
||||||
import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
|
import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
|
|
||||||
|
@ -91,12 +90,4 @@ public interface IotThingModelService {
|
||||||
*/
|
*/
|
||||||
Long getThingModelCount(LocalDateTime createTime);
|
Long getThingModelCount(LocalDateTime createTime);
|
||||||
|
|
||||||
/**
|
|
||||||
* 通过产品 ID 获取产品物模型 TSL
|
|
||||||
*
|
|
||||||
* @param productId 产品 ID
|
|
||||||
* @return 产品物模型 TSL
|
|
||||||
*/
|
|
||||||
IotThingModelTSLRespVO getThingModelTslByProductId(Long productId);
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package cn.iocoder.yudao.module.iot.service.thingmodel;
|
package cn.iocoder.yudao.module.iot.service.thingmodel;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.util.ObjUtil;
|
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.extra.spring.SpringUtil;
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
|
@ -14,7 +13,6 @@ import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelS
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO;
|
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelListReqVO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO;
|
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelPageReqVO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO;
|
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelSaveReqVO;
|
||||||
import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelTSLRespVO;
|
|
||||||
import cn.iocoder.yudao.module.iot.convert.thingmodel.IotThingModelConvert;
|
import cn.iocoder.yudao.module.iot.convert.thingmodel.IotThingModelConvert;
|
||||||
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;
|
||||||
|
@ -151,31 +149,6 @@ public class IotThingModelServiceImpl implements IotThingModelService {
|
||||||
return thingModelMapper.selectList(reqVO);
|
return thingModelMapper.selectList(reqVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO @puhui999:这个转换,放在 controller 貌似也行?
|
|
||||||
@Override
|
|
||||||
public IotThingModelTSLRespVO getThingModelTslByProductId(Long productId) {
|
|
||||||
IotThingModelTSLRespVO tslRespVO = new IotThingModelTSLRespVO();
|
|
||||||
// 1. 获得产品所有物模型定义
|
|
||||||
List<IotThingModelDO> thingModels = thingModelMapper.selectListByProductId(productId);
|
|
||||||
if (CollUtil.isEmpty(thingModels)) {
|
|
||||||
return tslRespVO;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2.1 设置公共部分参数
|
|
||||||
IotThingModelDO thingModel = thingModels.get(0);
|
|
||||||
tslRespVO.setProductId(thingModel.getProductId()).setProductKey(thingModel.getProductKey());
|
|
||||||
// 2.2 处理属性列表
|
|
||||||
tslRespVO.setProperties(convertList(filterList(thingModels, item ->
|
|
||||||
ObjUtil.equal(IotThingModelTypeEnum.PROPERTY.getType(), item.getType())), IotThingModelDO::getProperty));
|
|
||||||
// 2.3 处理服务列表
|
|
||||||
tslRespVO.setServices(convertList(filterList(thingModels, item ->
|
|
||||||
ObjUtil.equal(IotThingModelTypeEnum.SERVICE.getType(), item.getType())), IotThingModelDO::getService));
|
|
||||||
// 2.4 处理事件列表
|
|
||||||
tslRespVO.setEvents(convertList(filterList(thingModels, item ->
|
|
||||||
ObjUtil.equal(IotThingModelTypeEnum.EVENT.getType(), item.getType())), IotThingModelDO::getEvent));
|
|
||||||
return tslRespVO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验功能是否存在
|
* 校验功能是否存在
|
||||||
*
|
*
|
||||||
|
|
|
@ -22,7 +22,7 @@ import static org.mockito.ArgumentMatchers.anyString;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link IotDataBridgeExecute} 实现类的测试
|
* {@link IotDataBridgeExecute} 实现类的单元测试
|
||||||
*
|
*
|
||||||
* @author HUIHUI
|
* @author HUIHUI
|
||||||
*/
|
*/
|
||||||
|
@ -41,114 +41,125 @@ public class IotDataBridgeExecuteTest extends BaseMockitoUnitTest {
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
// 创建共享的测试消息
|
// 创建共享的测试消息
|
||||||
message = IotDeviceMessage.builder().requestId("TEST-001").reportTime(LocalDateTime.now()).tenantId(1L)
|
message = IotDeviceMessage.builder()
|
||||||
.productKey("testProduct").deviceName("testDevice").deviceKey("testDeviceKey")
|
.requestId("TEST-001")
|
||||||
.type("property").identifier("temperature").data("{\"value\": 60}")
|
.reportTime(LocalDateTime.now())
|
||||||
|
.tenantId(1L)
|
||||||
|
.productKey("testProduct")
|
||||||
|
.deviceName("testDevice")
|
||||||
|
.deviceKey("testDeviceKey")
|
||||||
|
.type("property")
|
||||||
|
.identifier("temperature")
|
||||||
|
.data("{\"value\": 60}")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// 配置 RestTemplate mock 返回成功响应
|
|
||||||
// TODO @puhui999:这个应该放到 testHttpDataBridge 里
|
|
||||||
when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(), any(Class.class)))
|
|
||||||
.thenReturn(new ResponseEntity<>("Success", HttpStatus.OK));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testKafkaMQDataBridge() {
|
public void testKafkaMQDataBridge() throws Exception {
|
||||||
// 1. 创建执行器实例
|
// 1. 创建执行器实例
|
||||||
IotKafkaMQDataBridgeExecute action = new IotKafkaMQDataBridgeExecute();
|
IotKafkaMQDataBridgeExecute action = new IotKafkaMQDataBridgeExecute();
|
||||||
|
|
||||||
// 2. 创建配置
|
// 2. 创建配置
|
||||||
// TODO @puhui999:可以改成链式哈。
|
IotDataBridgeKafkaMQConfig config = new IotDataBridgeKafkaMQConfig()
|
||||||
IotDataBridgeKafkaMQConfig config = new IotDataBridgeKafkaMQConfig();
|
.setBootstrapServers("127.0.0.1:9092")
|
||||||
config.setBootstrapServers("127.0.0.1:9092");
|
.setTopic("test-topic")
|
||||||
config.setTopic("test-topic");
|
.setSsl(false)
|
||||||
config.setSsl(false);
|
.setUsername(null)
|
||||||
config.setUsername(null);
|
.setPassword(null);
|
||||||
config.setPassword(null);
|
|
||||||
|
|
||||||
// 3. 执行两次测试,验证缓存
|
// 3. 执行测试并验证缓存
|
||||||
log.info("[testKafkaMQDataBridge][第一次执行,应该会创建新的 producer]");
|
executeAndVerifyCache(action, config, "KafkaMQ");
|
||||||
action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config));
|
|
||||||
|
|
||||||
log.info("[testKafkaMQDataBridge][第二次执行,应该会复用缓存的 producer]");
|
|
||||||
action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRabbitMQDataBridge() {
|
public void testRabbitMQDataBridge() throws Exception {
|
||||||
// 1. 创建执行器实例
|
// 1. 创建执行器实例
|
||||||
IotRabbitMQDataBridgeExecute action = new IotRabbitMQDataBridgeExecute();
|
IotRabbitMQDataBridgeExecute action = new IotRabbitMQDataBridgeExecute();
|
||||||
|
|
||||||
// 2. 创建配置
|
// 2. 创建配置
|
||||||
IotDataBridgeRabbitMQConfig config = new IotDataBridgeRabbitMQConfig();
|
IotDataBridgeRabbitMQConfig config = new IotDataBridgeRabbitMQConfig()
|
||||||
config.setHost("localhost");
|
.setHost("localhost")
|
||||||
config.setPort(5672);
|
.setPort(5672)
|
||||||
config.setVirtualHost("/");
|
.setVirtualHost("/")
|
||||||
config.setUsername("admin");
|
.setUsername("admin")
|
||||||
config.setPassword("123456");
|
.setPassword("123456")
|
||||||
config.setExchange("test-exchange");
|
.setExchange("test-exchange")
|
||||||
config.setRoutingKey("test-key");
|
.setRoutingKey("test-key")
|
||||||
config.setQueue("test-queue");
|
.setQueue("test-queue");
|
||||||
|
|
||||||
// 3. 执行两次测试,验证缓存
|
// 3. 执行测试并验证缓存
|
||||||
log.info("[testRabbitMQDataBridge][第一次执行,应该会创建新的 producer]");
|
executeAndVerifyCache(action, config, "RabbitMQ");
|
||||||
action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config));
|
|
||||||
|
|
||||||
log.info("[testRabbitMQDataBridge][第二次执行,应该会复用缓存的 producer]");
|
|
||||||
action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRedisStreamMQDataBridge() {
|
public void testRedisStreamDataBridge() throws Exception {
|
||||||
// 1. 创建执行器实例
|
// 1. 创建执行器实例
|
||||||
IotRedisStreamMQDataBridgeExecute action = new IotRedisStreamMQDataBridgeExecute();
|
IotRedisStreamDataBridgeExecute action = new IotRedisStreamDataBridgeExecute();
|
||||||
|
|
||||||
// 2. 创建配置
|
// 2. 创建配置
|
||||||
IotDataBridgeRedisStreamMQConfig config = new IotDataBridgeRedisStreamMQConfig();
|
IotDataBridgeRedisStreamConfig config = new IotDataBridgeRedisStreamConfig()
|
||||||
config.setHost("127.0.0.1");
|
.setHost("127.0.0.1")
|
||||||
config.setPort(6379);
|
.setPort(6379)
|
||||||
config.setDatabase(0);
|
.setDatabase(0)
|
||||||
config.setPassword("123456");
|
.setPassword("123456")
|
||||||
config.setTopic("test-stream");
|
.setTopic("test-stream");
|
||||||
|
|
||||||
// 3. 执行两次测试,验证缓存
|
// 3. 执行测试并验证缓存
|
||||||
log.info("[testRedisStreamMQDataBridge][第一次执行,应该会创建新的 producer]");
|
executeAndVerifyCache(action, config, "RedisStream");
|
||||||
action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config));
|
|
||||||
|
|
||||||
log.info("[testRedisStreamMQDataBridge][第二次执行,应该会复用缓存的 producer]");
|
|
||||||
action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRocketMQDataBridge() {
|
public void testRocketMQDataBridge() throws Exception {
|
||||||
// 1. 创建执行器实例
|
// 1. 创建执行器实例
|
||||||
IotRocketMQDataBridgeExecute action = new IotRocketMQDataBridgeExecute();
|
IotRocketMQDataBridgeExecute action = new IotRocketMQDataBridgeExecute();
|
||||||
|
|
||||||
// 2. 创建配置
|
// 2. 创建配置
|
||||||
IotDataBridgeRocketMQConfig config = new IotDataBridgeRocketMQConfig();
|
IotDataBridgeRocketMQConfig config = new IotDataBridgeRocketMQConfig()
|
||||||
config.setNameServer("127.0.0.1:9876");
|
.setNameServer("127.0.0.1:9876")
|
||||||
config.setGroup("test-group");
|
.setGroup("test-group")
|
||||||
config.setTopic("test-topic");
|
.setTopic("test-topic")
|
||||||
config.setTags("test-tag");
|
.setTags("test-tag");
|
||||||
|
|
||||||
// 3. 执行两次测试,验证缓存
|
// 3. 执行测试并验证缓存
|
||||||
log.info("[testRocketMQDataBridge][第一次执行,应该会创建新的 producer]");
|
executeAndVerifyCache(action, config, "RocketMQ");
|
||||||
action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config));
|
|
||||||
|
|
||||||
log.info("[testRocketMQDataBridge][第二次执行,应该会复用缓存的 producer]");
|
|
||||||
action.execute(message, new IotDataBridgeDO().setType(action.getType()).setConfig(config));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHttpDataBridge() throws Exception {
|
public void testHttpDataBridge() throws Exception {
|
||||||
// 创建配置
|
// 1. 配置 RestTemplate mock 返回成功响应
|
||||||
IotDataBridgeHttpConfig config = new IotDataBridgeHttpConfig();
|
when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(), any(Class.class)))
|
||||||
config.setUrl("https://doc.iocoder.cn/");
|
.thenReturn(new ResponseEntity<>("Success", HttpStatus.OK));
|
||||||
config.setMethod(HttpMethod.GET.name());
|
|
||||||
|
|
||||||
// 执行测试
|
// 2. 创建配置
|
||||||
|
IotDataBridgeHttpConfig config = new IotDataBridgeHttpConfig()
|
||||||
|
.setUrl("https://doc.iocoder.cn/")
|
||||||
|
.setMethod(HttpMethod.GET.name());
|
||||||
|
|
||||||
|
// 3. 执行测试
|
||||||
log.info("[testHttpDataBridge][执行HTTP数据桥接测试]");
|
log.info("[testHttpDataBridge][执行HTTP数据桥接测试]");
|
||||||
httpDataBridgeExecute.execute(message, new IotDataBridgeDO().setType(httpDataBridgeExecute.getType()).setConfig(config));
|
httpDataBridgeExecute.execute(message, new IotDataBridgeDO()
|
||||||
|
.setType(httpDataBridgeExecute.getType())
|
||||||
|
.setConfig(config));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行测试并验证缓存的通用方法
|
||||||
|
*
|
||||||
|
* @param action 执行器实例
|
||||||
|
* @param config 配置对象
|
||||||
|
* @param mqType MQ类型
|
||||||
|
* @throws Exception 如果执行过程中发生异常
|
||||||
|
*/
|
||||||
|
private void executeAndVerifyCache(IotDataBridgeExecute<?> action, IotDataBridgeAbstractConfig config, String mqType) throws Exception {
|
||||||
|
log.info("[test{}DataBridge][第一次执行,应该会创建新的 producer]", mqType);
|
||||||
|
action.execute(message, new IotDataBridgeDO()
|
||||||
|
.setType(action.getType())
|
||||||
|
.setConfig(config));
|
||||||
|
|
||||||
|
log.info("[test{}DataBridge][第二次执行,应该会复用缓存的 producer]", mqType);
|
||||||
|
action.execute(message, new IotDataBridgeDO()
|
||||||
|
.setType(action.getType())
|
||||||
|
.setConfig(config));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue