Commit 2a04bdc3fe8998c02ea12477deeb251923e0083c

Authored by YunaiV
1 parent 956418d3

feat:【IoT 物联网】完整实现“数据流转”功能(后台管理)

Showing 18 changed files with 216 additions and 25 deletions
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java
@@ -58,7 +58,8 @@ public interface ErrorCodeConstants { @@ -58,7 +58,8 @@ public interface ErrorCodeConstants {
58 ErrorCode DATA_RULE_NOT_EXISTS = new ErrorCode(1_050_010_000, "数据流转规则不存在"); 58 ErrorCode DATA_RULE_NOT_EXISTS = new ErrorCode(1_050_010_000, "数据流转规则不存在");
59 59
60 // ========== IoT 数据流转目的 1-050-011-000 ========== 60 // ========== IoT 数据流转目的 1-050-011-000 ==========
61 - ErrorCode DATA_BRIDGE_NOT_EXISTS = new ErrorCode(1_050_011_000, "数据桥梁不存在"); 61 + ErrorCode DATA_SINK_NOT_EXISTS = new ErrorCode(1_050_011_000, "数据桥梁不存在");
  62 + ErrorCode DATA_SINK_DELETE_FAIL_USED_BY_RULE = new ErrorCode(1_050_011_001, "数据流转目的正在被数据流转规则使用,无法删除");
62 63
63 // ========== IoT 场景联动 1-050-012-000 ========== 64 // ========== IoT 场景联动 1-050-012-000 ==========
64 ErrorCode RULE_SCENE_NOT_EXISTS = new ErrorCode(1_050_012_000, "场景联动不存在"); 65 ErrorCode RULE_SCENE_NOT_EXISTS = new ErrorCode(1_050_012_000, "场景联动不存在");
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceController.java
@@ -9,7 +9,6 @@ import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; @@ -9,7 +9,6 @@ import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
9 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*; 9 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*;
10 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; 10 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
11 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; 11 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
12 -import cn.iocoder.yudao.module.iot.service.device.message.IotDeviceMessageService;  
13 import io.swagger.v3.oas.annotations.Operation; 12 import io.swagger.v3.oas.annotations.Operation;
14 import io.swagger.v3.oas.annotations.Parameter; 13 import io.swagger.v3.oas.annotations.Parameter;
15 import io.swagger.v3.oas.annotations.tags.Tag; 14 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -38,8 +37,6 @@ public class IotDeviceController { @@ -38,8 +37,6 @@ public class IotDeviceController {
38 37
39 @Resource 38 @Resource
40 private IotDeviceService deviceService; 39 private IotDeviceService deviceService;
41 - @Resource  
42 - private IotDeviceMessageService deviceMessageService;  
43 40
44 @PostMapping("/create") 41 @PostMapping("/create")
45 @Operation(summary = "创建设备") 42 @Operation(summary = "创建设备")
@@ -125,11 +122,12 @@ public class IotDeviceController { @@ -125,11 +122,12 @@ public class IotDeviceController {
125 @GetMapping("/simple-list") 122 @GetMapping("/simple-list")
126 @Operation(summary = "获取设备的精简信息列表", description = "主要用于前端的下拉选项") 123 @Operation(summary = "获取设备的精简信息列表", description = "主要用于前端的下拉选项")
127 @Parameter(name = "deviceType", description = "设备类型", example = "1") 124 @Parameter(name = "deviceType", description = "设备类型", example = "1")
128 - public CommonResult<List<IotDeviceRespVO>> getSimpleDeviceList( 125 + public CommonResult<List<IotDeviceRespVO>> getDeviceSimpleList(
129 @RequestParam(value = "deviceType", required = false) Integer deviceType) { 126 @RequestParam(value = "deviceType", required = false) Integer deviceType) {
130 List<IotDeviceDO> list = deviceService.getDeviceListByDeviceType(deviceType); 127 List<IotDeviceDO> list = deviceService.getDeviceListByDeviceType(deviceType);
131 - return success(convertList(list, device -> // 只返回 id、name 字段  
132 - new IotDeviceRespVO().setId(device.getId()).setDeviceName(device.getDeviceName()))); 128 + return success(convertList(list, device -> // 只返回 id、name、productId 字段
  129 + new IotDeviceRespVO().setId(device.getId()).setDeviceName(device.getDeviceName())
  130 + .setProductId(device.getProductId())));
133 } 131 }
134 132
135 @PostMapping("/import") 133 @PostMapping("/import")
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductController.java
@@ -143,7 +143,7 @@ public class IotProductController { @@ -143,7 +143,7 @@ public class IotProductController {
143 143
144 @GetMapping("/simple-list") 144 @GetMapping("/simple-list")
145 @Operation(summary = "获取产品的精简信息列表", description = "主要用于前端的下拉选项") 145 @Operation(summary = "获取产品的精简信息列表", description = "主要用于前端的下拉选项")
146 - public CommonResult<List<IotProductRespVO>> getSimpleProductList() { 146 + public CommonResult<List<IotProductRespVO>> getProductSimpleList() {
147 List<IotProductDO> list = productService.getProductList(); 147 List<IotProductDO> list = productService.getProductList();
148 return success(convertList(list, product -> // 只返回 id、name 字段 148 return success(convertList(list, product -> // 只返回 id、name 字段
149 new IotProductRespVO().setId(product.getId()).setName(product.getName()) 149 new IotProductRespVO().setId(product.getId()).setName(product.getName())
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/data/rule/IotDataRulePageReqVO.java
@@ -13,10 +13,10 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @@ -13,10 +13,10 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
13 @Data 13 @Data
14 public class IotDataRulePageReqVO extends PageParam { 14 public class IotDataRulePageReqVO extends PageParam {
15 15
16 - @Schema(description = "场景名称", example = "芋艿") 16 + @Schema(description = "数据流转规则名称", example = "芋艿")
17 private String name; 17 private String name;
18 18
19 - @Schema(description = "场景状态", example = "1") 19 + @Schema(description = "数据流转规则状态", example = "1")
20 private Integer status; 20 private Integer status;
21 21
22 @Schema(description = "创建时间") 22 @Schema(description = "创建时间")
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/data/rule/IotDataRuleRespVO.java
@@ -11,16 +11,16 @@ import java.util.List; @@ -11,16 +11,16 @@ import java.util.List;
11 @Data 11 @Data
12 public class IotDataRuleRespVO { 12 public class IotDataRuleRespVO {
13 13
14 - @Schema(description = "场景编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8540") 14 + @Schema(description = "数据流转规则编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8540")
15 private Long id; 15 private Long id;
16 16
17 - @Schema(description = "场景名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") 17 + @Schema(description = "数据流转规则名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
18 private String name; 18 private String name;
19 19
20 - @Schema(description = "场景描述", example = "你猜") 20 + @Schema(description = "数据流转规则描述", example = "你猜")
21 private String description; 21 private String description;
22 22
23 - @Schema(description = "场景状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") 23 + @Schema(description = "数据流转规则状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
24 private Integer status; 24 private Integer status;
25 25
26 @Schema(description = "数据源配置数组", requiredMode = Schema.RequiredMode.REQUIRED) 26 @Schema(description = "数据源配置数组", requiredMode = Schema.RequiredMode.REQUIRED)
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/data/rule/IotDataRuleSaveReqVO.java
@@ -14,18 +14,18 @@ import java.util.List; @@ -14,18 +14,18 @@ import java.util.List;
14 @Data 14 @Data
15 public class IotDataRuleSaveReqVO { 15 public class IotDataRuleSaveReqVO {
16 16
17 - @Schema(description = "场景编号", example = "8540") 17 + @Schema(description = "数据流转规则编号", example = "8540")
18 private Long id; 18 private Long id;
19 19
20 - @Schema(description = "场景名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")  
21 - @NotEmpty(message = "场景名称不能为空") 20 + @Schema(description = "数据流转规则名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
  21 + @NotEmpty(message = "数据流转规则名称不能为空")
22 private String name; 22 private String name;
23 23
24 - @Schema(description = "场景描述", example = "你猜") 24 + @Schema(description = "数据流转规则描述", example = "你猜")
25 private String description; 25 private String description;
26 26
27 - @Schema(description = "场景状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")  
28 - @NotNull(message = "场景状态不能为空") 27 + @Schema(description = "数据流转规则状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  28 + @NotNull(message = "数据流转规则状态不能为空")
29 @InEnum(CommonStatusEnum.class) 29 @InEnum(CommonStatusEnum.class)
30 private Integer status; 30 private Integer status;
31 31
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/IotDeviceMapper.java
@@ -6,9 +6,9 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; @@ -6,9 +6,9 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
7 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDevicePageReqVO; 7 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDevicePageReqVO;
8 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; 8 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
  9 +import jakarta.annotation.Nullable;
9 import org.apache.ibatis.annotations.Mapper; 10 import org.apache.ibatis.annotations.Mapper;
10 11
11 -import javax.annotation.Nullable;  
12 import java.time.LocalDateTime; 12 import java.time.LocalDateTime;
13 import java.util.Collection; 13 import java.util.Collection;
14 import java.util.List; 14 import java.util.List;
@@ -50,8 +50,9 @@ public interface IotDeviceMapper extends BaseMapperX&lt;IotDeviceDO&gt; { @@ -50,8 +50,9 @@ public interface IotDeviceMapper extends BaseMapperX&lt;IotDeviceDO&gt; {
50 return selectCount(IotDeviceDO::getProductId, productId); 50 return selectCount(IotDeviceDO::getProductId, productId);
51 } 51 }
52 52
53 - default List<IotDeviceDO> selectListByDeviceType(Integer deviceType) {  
54 - return selectList(IotDeviceDO::getDeviceType, deviceType); 53 + default List<IotDeviceDO> selectListByDeviceType(@Nullable Integer deviceType) {
  54 + return selectList(new LambdaQueryWrapperX<IotDeviceDO>()
  55 + .geIfPresent(IotDeviceDO::getDeviceType, deviceType));
55 } 56 }
56 57
57 default List<IotDeviceDO> selectListByState(Integer state) { 58 default List<IotDeviceDO> selectListByState(Integer state) {
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/rule/IotDataRuleMapper.java
@@ -3,10 +3,13 @@ package cn.iocoder.yudao.module.iot.dal.mysql.rule; @@ -3,10 +3,13 @@ package cn.iocoder.yudao.module.iot.dal.mysql.rule;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  6 +import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
6 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRulePageReqVO; 7 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRulePageReqVO;
7 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataRuleDO; 8 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataRuleDO;
8 import org.apache.ibatis.annotations.Mapper; 9 import org.apache.ibatis.annotations.Mapper;
9 10
  11 +import java.util.List;
  12 +
10 /** 13 /**
11 * IoT 数据流转规则 Mapper 14 * IoT 数据流转规则 Mapper
12 * 15 *
@@ -23,4 +26,9 @@ public interface IotDataRuleMapper extends BaseMapperX&lt;IotDataRuleDO&gt; { @@ -23,4 +26,9 @@ public interface IotDataRuleMapper extends BaseMapperX&lt;IotDataRuleDO&gt; {
23 .orderByDesc(IotDataRuleDO::getId)); 26 .orderByDesc(IotDataRuleDO::getId));
24 } 27 }
25 28
  29 + default List<IotDataRuleDO> selectListBySinkId(Long sinkId) {
  30 + return selectList(new LambdaQueryWrapperX<IotDataRuleDO>()
  31 + .apply(MyBatisUtils.findInSet("sink_ids", sinkId)));
  32 + }
  33 +
26 } 34 }
27 \ No newline at end of file 35 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceService.java
@@ -13,6 +13,7 @@ import java.time.LocalDateTime; @@ -13,6 +13,7 @@ import java.time.LocalDateTime;
13 import java.util.Collection; 13 import java.util.Collection;
14 import java.util.List; 14 import java.util.List;
15 import java.util.Map; 15 import java.util.Map;
  16 +import java.util.Set;
16 17
17 /** 18 /**
18 * IoT 设备 Service 接口 19 * IoT 设备 Service 接口
@@ -255,4 +256,11 @@ public interface IotDeviceService { @@ -255,4 +256,11 @@ public interface IotDeviceService {
255 */ 256 */
256 boolean authDevice(@Valid IotDeviceAuthReqDTO authReqDTO); 257 boolean authDevice(@Valid IotDeviceAuthReqDTO authReqDTO);
257 258
  259 + /**
  260 + * 校验设备是否存在
  261 + *
  262 + * @param ids 设备编号数组
  263 + */
  264 + void validateDevicesExist(Set<Long> ids);
  265 +
258 } 266 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java
@@ -483,6 +483,17 @@ public class IotDeviceServiceImpl implements IotDeviceService { @@ -483,6 +483,17 @@ public class IotDeviceServiceImpl implements IotDeviceService {
483 return true; 483 return true;
484 } 484 }
485 485
  486 + @Override
  487 + public void validateDevicesExist(Set<Long> ids) {
  488 + if (CollUtil.isEmpty(ids)) {
  489 + return;
  490 + }
  491 + List<IotDeviceDO> deviceIds = deviceMapper.selectByIds(ids);
  492 + if (deviceIds.size() != ids.size()) {
  493 + throw exception(DEVICE_NOT_EXISTS);
  494 + }
  495 + }
  496 +
486 private IotDeviceServiceImpl getSelf() { 497 private IotDeviceServiceImpl getSelf() {
487 return SpringUtil.getBean(getClass()); 498 return SpringUtil.getBean(getClass());
488 } 499 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductService.java
@@ -8,6 +8,7 @@ import jakarta.validation.Valid; @@ -8,6 +8,7 @@ import jakarta.validation.Valid;
8 8
9 import javax.annotation.Nullable; 9 import javax.annotation.Nullable;
10 import java.time.LocalDateTime; 10 import java.time.LocalDateTime;
  11 +import java.util.Collection;
11 import java.util.List; 12 import java.util.List;
12 13
13 /** 14 /**
@@ -112,5 +113,11 @@ public interface IotProductService { @@ -112,5 +113,11 @@ public interface IotProductService {
112 */ 113 */
113 Long getProductCount(@Nullable LocalDateTime createTime); 114 Long getProductCount(@Nullable LocalDateTime createTime);
114 115
  116 + /**
  117 + * 批量校验产品存在
  118 + *
  119 + * @param ids 产品编号集合
  120 + */
  121 + void validateProductsExist(Collection<Long> ids);
115 122
116 } 123 }
117 \ No newline at end of file 124 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java
1 package cn.iocoder.yudao.module.iot.service.product; 1 package cn.iocoder.yudao.module.iot.service.product;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; 6 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
@@ -20,6 +21,7 @@ import org.springframework.stereotype.Service; @@ -20,6 +21,7 @@ import org.springframework.stereotype.Service;
20 import org.springframework.validation.annotation.Validated; 21 import org.springframework.validation.annotation.Validated;
21 22
22 import java.time.LocalDateTime; 23 import java.time.LocalDateTime;
  24 +import java.util.Collection;
23 import java.util.List; 25 import java.util.List;
24 import java.util.Objects; 26 import java.util.Objects;
25 27
@@ -157,4 +159,15 @@ public class IotProductServiceImpl implements IotProductService { @@ -157,4 +159,15 @@ public class IotProductServiceImpl implements IotProductService {
157 return productMapper.selectCountByCreateTime(createTime); 159 return productMapper.selectCountByCreateTime(createTime);
158 } 160 }
159 161
  162 + @Override
  163 + public void validateProductsExist(Collection<Long> ids) {
  164 + if (CollUtil.isEmpty(ids)) {
  165 + return;
  166 + }
  167 + List<IotProductDO> products = productMapper.selectByIds(ids);
  168 + if (products.size() != ids.size()) {
  169 + throw exception(PRODUCT_NOT_EXISTS);
  170 + }
  171 + }
  172 +
160 } 173 }
161 \ No newline at end of file 174 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataRuleService.java
1 package cn.iocoder.yudao.module.iot.service.rule.data; 1 package cn.iocoder.yudao.module.iot.service.rule.data;
2 2
  3 +import java.util.List;
  4 +
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRulePageReqVO; 6 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRulePageReqVO;
5 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRuleSaveReqVO; 7 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRuleSaveReqVO;
@@ -51,4 +53,12 @@ public interface IotDataRuleService { @@ -51,4 +53,12 @@ public interface IotDataRuleService {
51 */ 53 */
52 PageResult<IotDataRuleDO> getDataRulePage(IotDataRulePageReqVO pageReqVO); 54 PageResult<IotDataRuleDO> getDataRulePage(IotDataRulePageReqVO pageReqVO);
53 55
  56 + /**
  57 + * 根据数据目的编号,获得数据流转规则列表
  58 + *
  59 + * @param sinkId 数据目的编号
  60 + * @return 是否被使用
  61 + */
  62 + List<IotDataRuleDO> getDataRuleBySinkId(Long sinkId);
  63 +
54 } 64 }
55 \ No newline at end of file 65 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataRuleServiceImpl.java
1 package cn.iocoder.yudao.module.iot.service.rule.data; 1 package cn.iocoder.yudao.module.iot.service.rule.data;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.hutool.core.util.ObjUtil;
  5 +import cn.hutool.core.util.StrUtil;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 7 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRulePageReqVO; 8 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRulePageReqVO;
6 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRuleSaveReqVO; 9 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRuleSaveReqVO;
  10 +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
7 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataRuleDO; 11 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataRuleDO;
8 import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotDataRuleMapper; 12 import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotDataRuleMapper;
  13 +import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
  14 +import cn.iocoder.yudao.module.iot.service.product.IotProductService;
  15 +import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService;
9 import jakarta.annotation.Resource; 16 import jakarta.annotation.Resource;
10 import org.springframework.stereotype.Service; 17 import org.springframework.stereotype.Service;
11 import org.springframework.validation.annotation.Validated; 18 import org.springframework.validation.annotation.Validated;
12 19
  20 +import java.util.*;
  21 +
13 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 22 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  23 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
14 import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DATA_RULE_NOT_EXISTS; 24 import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DATA_RULE_NOT_EXISTS;
15 25
16 /** 26 /**
@@ -25,8 +35,20 @@ public class IotDataRuleServiceImpl implements IotDataRuleService { @@ -25,8 +35,20 @@ public class IotDataRuleServiceImpl implements IotDataRuleService {
25 @Resource 35 @Resource
26 private IotDataRuleMapper dataRuleMapper; 36 private IotDataRuleMapper dataRuleMapper;
27 37
  38 + @Resource
  39 + private IotProductService productService;
  40 + @Resource
  41 + private IotDeviceService deviceService;
  42 + @Resource
  43 + private IotThingModelService thingModelService;
  44 + @Resource
  45 + private IotDataSinkService dataSinkService;
  46 +
28 @Override 47 @Override
29 public Long createDataRule(IotDataRuleSaveReqVO createReqVO) { 48 public Long createDataRule(IotDataRuleSaveReqVO createReqVO) {
  49 + // 校验数据源配置和数据目的
  50 + validateDataRuleConfig(createReqVO);
  51 + // 新增
30 IotDataRuleDO dataRule = BeanUtils.toBean(createReqVO, IotDataRuleDO.class); 52 IotDataRuleDO dataRule = BeanUtils.toBean(createReqVO, IotDataRuleDO.class);
31 dataRuleMapper.insert(dataRule); 53 dataRuleMapper.insert(dataRule);
32 return dataRule.getId(); 54 return dataRule.getId();
@@ -36,6 +58,9 @@ public class IotDataRuleServiceImpl implements IotDataRuleService { @@ -36,6 +58,9 @@ public class IotDataRuleServiceImpl implements IotDataRuleService {
36 public void updateDataRule(IotDataRuleSaveReqVO updateReqVO) { 58 public void updateDataRule(IotDataRuleSaveReqVO updateReqVO) {
37 // 校验存在 59 // 校验存在
38 validateDataRuleExists(updateReqVO.getId()); 60 validateDataRuleExists(updateReqVO.getId());
  61 + // 校验数据源配置和数据目的
  62 + validateDataRuleConfig(updateReqVO);
  63 +
39 // 更新 64 // 更新
40 IotDataRuleDO updateObj = BeanUtils.toBean(updateReqVO, IotDataRuleDO.class); 65 IotDataRuleDO updateObj = BeanUtils.toBean(updateReqVO, IotDataRuleDO.class);
41 dataRuleMapper.updateById(updateObj); 66 dataRuleMapper.updateById(updateObj);
@@ -55,6 +80,55 @@ public class IotDataRuleServiceImpl implements IotDataRuleService { @@ -55,6 +80,55 @@ public class IotDataRuleServiceImpl implements IotDataRuleService {
55 } 80 }
56 } 81 }
57 82
  83 + /**
  84 + * 校验数据流转规则配置
  85 + *
  86 + * @param reqVO 数据流转规则保存请求VO
  87 + */
  88 + private void validateDataRuleConfig(IotDataRuleSaveReqVO reqVO) {
  89 + // 1. 校验数据源配置
  90 + validateSourceConfigs(reqVO.getSourceConfigs());
  91 + // 2. 校验数据目的
  92 + dataSinkService.validateDataSinksExist(reqVO.getSinkIds());
  93 + }
  94 +
  95 + /**
  96 + * 校验数据源配置
  97 + *
  98 + * @param sourceConfigs 数据源配置列表
  99 + */
  100 + private void validateSourceConfigs(List<IotDataRuleDO.SourceConfig> sourceConfigs) {
  101 + // 1. 校验产品
  102 + productService.validateProductsExist(
  103 + convertSet(sourceConfigs, IotDataRuleDO.SourceConfig::getProductId));
  104 +
  105 + // 2. 校验设备
  106 + deviceService.validateDevicesExist(convertSet(sourceConfigs, IotDataRuleDO.SourceConfig::getDeviceId,
  107 + config -> ObjUtil.notEqual(config.getDeviceId(), IotDeviceDO.DEVICE_ID_ALL)));
  108 +
  109 + // 3. 校验物模型存在
  110 + validateThingModelsExist(sourceConfigs);
  111 + }
  112 +
  113 + /**
  114 + * 校验物模型存在
  115 + *
  116 + * @param sourceConfigs 数据源配置列表
  117 + */
  118 + private void validateThingModelsExist(List<IotDataRuleDO.SourceConfig> sourceConfigs) {
  119 + Map<Long, Set<String>> productIdToIdentifiers = new HashMap<>();
  120 + for (IotDataRuleDO.SourceConfig config : sourceConfigs) {
  121 + if (StrUtil.isEmpty(config.getIdentifier())) {
  122 + continue;
  123 + }
  124 + productIdToIdentifiers.computeIfAbsent(config.getProductId(),
  125 + productId -> new HashSet<>()).add(config.getIdentifier());
  126 + }
  127 + for (Map.Entry<Long, Set<String>> entry : productIdToIdentifiers.entrySet()) {
  128 + thingModelService.validateThingModelsExist(entry.getKey(), entry.getValue());
  129 + }
  130 + }
  131 +
58 @Override 132 @Override
59 public IotDataRuleDO getDataRule(Long id) { 133 public IotDataRuleDO getDataRule(Long id) {
60 return dataRuleMapper.selectById(id); 134 return dataRuleMapper.selectById(id);
@@ -65,4 +139,9 @@ public class IotDataRuleServiceImpl implements IotDataRuleService { @@ -65,4 +139,9 @@ public class IotDataRuleServiceImpl implements IotDataRuleService {
65 return dataRuleMapper.selectPage(pageReqVO); 139 return dataRuleMapper.selectPage(pageReqVO);
66 } 140 }
67 141
  142 + @Override
  143 + public List<IotDataRuleDO> getDataRuleBySinkId(Long sinkId) {
  144 + return dataRuleMapper.selectListBySinkId(sinkId);
  145 + }
  146 +
68 } 147 }
69 \ No newline at end of file 148 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataSinkService.java
@@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.sink.IotDataSin @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.sink.IotDataSin
6 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataSinkDO; 6 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataSinkDO;
7 import jakarta.validation.Valid; 7 import jakarta.validation.Valid;
8 8
  9 +import java.util.Collection;
9 import java.util.List; 10 import java.util.List;
10 11
11 /** 12 /**
@@ -61,4 +62,11 @@ public interface IotDataSinkService { @@ -61,4 +62,11 @@ public interface IotDataSinkService {
61 */ 62 */
62 List<IotDataSinkDO> getDataSinkListByStatus(Integer status); 63 List<IotDataSinkDO> getDataSinkListByStatus(Integer status);
63 64
  65 + /**
  66 + * 批量校验数据目的存在
  67 + *
  68 + * @param ids 数据目的编号集合
  69 + */
  70 + void validateDataSinksExist(Collection<Long> ids);
  71 +
64 } 72 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataSinkServiceImpl.java
1 package cn.iocoder.yudao.module.iot.service.rule.data; 1 package cn.iocoder.yudao.module.iot.service.rule.data;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
5 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.sink.IotDataSinkPageReqVO; 6 import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.sink.IotDataSinkPageReqVO;
@@ -7,13 +8,16 @@ import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.sink.IotDataSin @@ -7,13 +8,16 @@ import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.sink.IotDataSin
7 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataSinkDO; 8 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataSinkDO;
8 import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotDataSinkMapper; 9 import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotDataSinkMapper;
9 import jakarta.annotation.Resource; 10 import jakarta.annotation.Resource;
  11 +import org.springframework.context.annotation.Lazy;
10 import org.springframework.stereotype.Service; 12 import org.springframework.stereotype.Service;
11 import org.springframework.validation.annotation.Validated; 13 import org.springframework.validation.annotation.Validated;
12 14
  15 +import java.util.Collection;
13 import java.util.List; 16 import java.util.List;
14 17
15 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 18 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
16 -import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DATA_BRIDGE_NOT_EXISTS; 19 +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DATA_SINK_NOT_EXISTS;
  20 +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DATA_SINK_DELETE_FAIL_USED_BY_RULE;
17 21
18 /** 22 /**
19 * IoT 数据流转目的 Service 实现类 23 * IoT 数据流转目的 Service 实现类
@@ -27,6 +31,10 @@ public class IotDataSinkServiceImpl implements IotDataSinkService { @@ -27,6 +31,10 @@ public class IotDataSinkServiceImpl implements IotDataSinkService {
27 @Resource 31 @Resource
28 private IotDataSinkMapper dataSinkMapper; 32 private IotDataSinkMapper dataSinkMapper;
29 33
  34 + @Resource
  35 + @Lazy // 延迟,避免循环依赖报错
  36 + private IotDataRuleService dataRuleService;
  37 +
30 @Override 38 @Override
31 public Long createDataSink(IotDataSinkSaveReqVO createReqVO) { 39 public Long createDataSink(IotDataSinkSaveReqVO createReqVO) {
32 IotDataSinkDO dataBridge = BeanUtils.toBean(createReqVO, IotDataSinkDO.class); 40 IotDataSinkDO dataBridge = BeanUtils.toBean(createReqVO, IotDataSinkDO.class);
@@ -47,13 +55,17 @@ public class IotDataSinkServiceImpl implements IotDataSinkService { @@ -47,13 +55,17 @@ public class IotDataSinkServiceImpl implements IotDataSinkService {
47 public void deleteDataSink(Long id) { 55 public void deleteDataSink(Long id) {
48 // 校验存在 56 // 校验存在
49 validateDataBridgeExists(id); 57 validateDataBridgeExists(id);
  58 + // 校验是否被数据流转规则使用
  59 + if (CollUtil.isNotEmpty(dataRuleService.getDataRuleBySinkId(id))) {
  60 + throw exception(DATA_SINK_DELETE_FAIL_USED_BY_RULE);
  61 + }
50 // 删除 62 // 删除
51 dataSinkMapper.deleteById(id); 63 dataSinkMapper.deleteById(id);
52 } 64 }
53 65
54 private void validateDataBridgeExists(Long id) { 66 private void validateDataBridgeExists(Long id) {
55 if (dataSinkMapper.selectById(id) == null) { 67 if (dataSinkMapper.selectById(id) == null) {
56 - throw exception(DATA_BRIDGE_NOT_EXISTS); 68 + throw exception(DATA_SINK_NOT_EXISTS);
57 } 69 }
58 } 70 }
59 71
@@ -72,4 +84,15 @@ public class IotDataSinkServiceImpl implements IotDataSinkService { @@ -72,4 +84,15 @@ public class IotDataSinkServiceImpl implements IotDataSinkService {
72 return dataSinkMapper.selectListByStatus(status); 84 return dataSinkMapper.selectListByStatus(status);
73 } 85 }
74 86
  87 + @Override
  88 + public void validateDataSinksExist(Collection<Long> ids) {
  89 + if (CollUtil.isEmpty(ids)) {
  90 + return;
  91 + }
  92 + List<IotDataSinkDO> sinks = dataSinkMapper.selectByIds(ids);
  93 + if (sinks.size() != ids.size()) {
  94 + throw exception(DATA_SINK_NOT_EXISTS);
  95 + }
  96 + }
  97 +
75 } 98 }
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java
@@ -9,6 +9,7 @@ import jakarta.validation.Valid; @@ -9,6 +9,7 @@ import jakarta.validation.Valid;
9 9
10 import java.util.Collection; 10 import java.util.Collection;
11 import java.util.List; 11 import java.util.List;
  12 +import java.util.Set;
12 13
13 /** 14 /**
14 * IoT 产品物模型 Service 接口 15 * IoT 产品物模型 Service 接口
@@ -99,4 +100,12 @@ public interface IotThingModelService { @@ -99,4 +100,12 @@ public interface IotThingModelService {
99 */ 100 */
100 List<IotThingModelDO> getThingModelList(IotThingModelListReqVO reqVO); 101 List<IotThingModelDO> getThingModelList(IotThingModelListReqVO reqVO);
101 102
  103 + /**
  104 + * 批量校验物模型存在
  105 + *
  106 + * @param productId 产品编号
  107 + * @param identifiers 标识符集合
  108 + */
  109 + void validateThingModelsExist(Long productId, Set<String> identifiers);
  110 +
102 } 111 }
103 \ No newline at end of file 112 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java
@@ -158,6 +158,21 @@ public class IotThingModelServiceImpl implements IotThingModelService { @@ -158,6 +158,21 @@ public class IotThingModelServiceImpl implements IotThingModelService {
158 return thingModelMapper.selectList(reqVO); 158 return thingModelMapper.selectList(reqVO);
159 } 159 }
160 160
  161 + @Override
  162 + public void validateThingModelsExist(Long productId, Set<String> identifiers) {
  163 + if (CollUtil.isEmpty(identifiers)) {
  164 + return;
  165 + }
  166 + List<IotThingModelDO> thingModels = thingModelMapper.selectListByProductIdAndIdentifiers(
  167 + productId, identifiers);
  168 + Set<String> foundIdentifiers = convertSet(thingModels, IotThingModelDO::getIdentifier);
  169 + for (String identifier : identifiers) {
  170 + if (!foundIdentifiers.contains(identifier)) {
  171 + throw exception(THING_MODEL_NOT_EXISTS);
  172 + }
  173 + }
  174 + }
  175 +
161 /** 176 /**
162 * 校验功能是否存在 177 * 校验功能是否存在
163 * 178 *