From 2a04bdc3fe8998c02ea12477deeb251923e0083c Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 25 Jun 2025 21:45:02 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E3=80=90IoT=20=E7=89=A9=E8=81=94?= =?UTF-8?q?=E7=BD=91=E3=80=91=E5=AE=8C=E6=95=B4=E5=AE=9E=E7=8E=B0=E2=80=9C?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=B5=81=E8=BD=AC=E2=80=9D=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=88=E5=90=8E=E5=8F=B0=E7=AE=A1=E7=90=86=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/iot/enums/ErrorCodeConstants.java | 3 +- .../admin/device/IotDeviceController.java | 10 +-- .../admin/product/IotProductController.java | 2 +- .../vo/data/rule/IotDataRulePageReqVO.java | 4 +- .../rule/vo/data/rule/IotDataRuleRespVO.java | 8 +- .../vo/data/rule/IotDataRuleSaveReqVO.java | 12 +-- .../iot/dal/mysql/device/IotDeviceMapper.java | 7 +- .../iot/dal/mysql/rule/IotDataRuleMapper.java | 8 ++ .../iot/service/device/IotDeviceService.java | 8 ++ .../service/device/IotDeviceServiceImpl.java | 11 +++ .../service/product/IotProductService.java | 7 ++ .../product/IotProductServiceImpl.java | 13 +++ .../service/rule/data/IotDataRuleService.java | 10 +++ .../rule/data/IotDataRuleServiceImpl.java | 79 +++++++++++++++++++ .../service/rule/data/IotDataSinkService.java | 8 ++ .../rule/data/IotDataSinkServiceImpl.java | 27 ++++++- .../thingmodel/IotThingModelService.java | 9 +++ .../thingmodel/IotThingModelServiceImpl.java | 15 ++++ 18 files changed, 216 insertions(+), 25 deletions(-) diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java index 4bacac016d..8217a5b2ae 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java +++ b/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 { ErrorCode DATA_RULE_NOT_EXISTS = new ErrorCode(1_050_010_000, "数据流转规则不存在"); // ========== IoT 数据流转目的 1-050-011-000 ========== - ErrorCode DATA_BRIDGE_NOT_EXISTS = new ErrorCode(1_050_011_000, "数据桥梁不存在"); + ErrorCode DATA_SINK_NOT_EXISTS = new ErrorCode(1_050_011_000, "数据桥梁不存在"); + ErrorCode DATA_SINK_DELETE_FAIL_USED_BY_RULE = new ErrorCode(1_050_011_001, "数据流转目的正在被数据流转规则使用,无法删除"); // ========== IoT 场景联动 1-050-012-000 ========== ErrorCode RULE_SCENE_NOT_EXISTS = new ErrorCode(1_050_012_000, "场景联动不存在"); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceController.java index 60ae9eb87f..052d34edc4 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceController.java +++ b/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; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; -import cn.iocoder.yudao.module.iot.service.device.message.IotDeviceMessageService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -38,8 +37,6 @@ public class IotDeviceController { @Resource private IotDeviceService deviceService; - @Resource - private IotDeviceMessageService deviceMessageService; @PostMapping("/create") @Operation(summary = "创建设备") @@ -125,11 +122,12 @@ public class IotDeviceController { @GetMapping("/simple-list") @Operation(summary = "获取设备的精简信息列表", description = "主要用于前端的下拉选项") @Parameter(name = "deviceType", description = "设备类型", example = "1") - public CommonResult> getSimpleDeviceList( + public CommonResult> getDeviceSimpleList( @RequestParam(value = "deviceType", required = false) Integer deviceType) { List list = deviceService.getDeviceListByDeviceType(deviceType); - return success(convertList(list, device -> // 只返回 id、name 字段 - new IotDeviceRespVO().setId(device.getId()).setDeviceName(device.getDeviceName()))); + return success(convertList(list, device -> // 只返回 id、name、productId 字段 + new IotDeviceRespVO().setId(device.getId()).setDeviceName(device.getDeviceName()) + .setProductId(device.getProductId()))); } @PostMapping("/import") diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductController.java index 17f7e2d3ec..adcc4d2e0a 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductController.java +++ b/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 { @GetMapping("/simple-list") @Operation(summary = "获取产品的精简信息列表", description = "主要用于前端的下拉选项") - public CommonResult> getSimpleProductList() { + public CommonResult> getProductSimpleList() { List list = productService.getProductList(); return success(convertList(list, product -> // 只返回 id、name 字段 new IotProductRespVO().setId(product.getId()).setName(product.getName()) diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/data/rule/IotDataRulePageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/data/rule/IotDataRulePageReqVO.java index 9cbb747db4..8e21c7992c 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/data/rule/IotDataRulePageReqVO.java +++ b/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_ @Data public class IotDataRulePageReqVO extends PageParam { - @Schema(description = "场景名称", example = "芋艿") + @Schema(description = "数据流转规则名称", example = "芋艿") private String name; - @Schema(description = "场景状态", example = "1") + @Schema(description = "数据流转规则状态", example = "1") private Integer status; @Schema(description = "创建时间") diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/data/rule/IotDataRuleRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/data/rule/IotDataRuleRespVO.java index 374b08a7cd..3427370f7c 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/data/rule/IotDataRuleRespVO.java +++ b/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; @Data public class IotDataRuleRespVO { - @Schema(description = "场景编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8540") + @Schema(description = "数据流转规则编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8540") private Long id; - @Schema(description = "场景名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @Schema(description = "数据流转规则名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") private String name; - @Schema(description = "场景描述", example = "你猜") + @Schema(description = "数据流转规则描述", example = "你猜") private String description; - @Schema(description = "场景状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @Schema(description = "数据流转规则状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Integer status; @Schema(description = "数据源配置数组", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/data/rule/IotDataRuleSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/data/rule/IotDataRuleSaveReqVO.java index 2928861169..47748c6eb1 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/rule/vo/data/rule/IotDataRuleSaveReqVO.java +++ b/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; @Data public class IotDataRuleSaveReqVO { - @Schema(description = "场景编号", example = "8540") + @Schema(description = "数据流转规则编号", example = "8540") private Long id; - @Schema(description = "场景名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") - @NotEmpty(message = "场景名称不能为空") + @Schema(description = "数据流转规则名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @NotEmpty(message = "数据流转规则名称不能为空") private String name; - @Schema(description = "场景描述", example = "你猜") + @Schema(description = "数据流转规则描述", example = "你猜") private String description; - @Schema(description = "场景状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @NotNull(message = "场景状态不能为空") + @Schema(description = "数据流转规则状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "数据流转规则状态不能为空") @InEnum(CommonStatusEnum.class) private Integer status; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/IotDeviceMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/IotDeviceMapper.java index 4746107122..32477221ac 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/IotDeviceMapper.java +++ b/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; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDevicePageReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; +import jakarta.annotation.Nullable; import org.apache.ibatis.annotations.Mapper; -import javax.annotation.Nullable; import java.time.LocalDateTime; import java.util.Collection; import java.util.List; @@ -50,8 +50,9 @@ public interface IotDeviceMapper extends BaseMapperX { return selectCount(IotDeviceDO::getProductId, productId); } - default List selectListByDeviceType(Integer deviceType) { - return selectList(IotDeviceDO::getDeviceType, deviceType); + default List selectListByDeviceType(@Nullable Integer deviceType) { + return selectList(new LambdaQueryWrapperX() + .geIfPresent(IotDeviceDO::getDeviceType, deviceType)); } default List selectListByState(Integer state) { diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/rule/IotDataRuleMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/rule/IotDataRuleMapper.java index 6f8d7b860a..d59023290a 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/rule/IotDataRuleMapper.java +++ b/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; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRulePageReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataRuleDO; import org.apache.ibatis.annotations.Mapper; +import java.util.List; + /** * IoT 数据流转规则 Mapper * @@ -23,4 +26,9 @@ public interface IotDataRuleMapper extends BaseMapperX { .orderByDesc(IotDataRuleDO::getId)); } + default List selectListBySinkId(Long sinkId) { + return selectList(new LambdaQueryWrapperX() + .apply(MyBatisUtils.findInSet("sink_ids", sinkId))); + } + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceService.java index e2258e3d66..c3a6868945 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceService.java +++ b/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; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Set; /** * IoT 设备 Service 接口 @@ -255,4 +256,11 @@ public interface IotDeviceService { */ boolean authDevice(@Valid IotDeviceAuthReqDTO authReqDTO); + /** + * 校验设备是否存在 + * + * @param ids 设备编号数组 + */ + void validateDevicesExist(Set ids); + } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java index d7543cd2c4..604a8ae9b5 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java +++ b/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 { return true; } + @Override + public void validateDevicesExist(Set ids) { + if (CollUtil.isEmpty(ids)) { + return; + } + List deviceIds = deviceMapper.selectByIds(ids); + if (deviceIds.size() != ids.size()) { + throw exception(DEVICE_NOT_EXISTS); + } + } + private IotDeviceServiceImpl getSelf() { return SpringUtil.getBean(getClass()); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductService.java index 9d94219c50..70e6afd03a 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductService.java +++ b/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; import javax.annotation.Nullable; import java.time.LocalDateTime; +import java.util.Collection; import java.util.List; /** @@ -112,5 +113,11 @@ public interface IotProductService { */ Long getProductCount(@Nullable LocalDateTime createTime); + /** + * 批量校验产品存在 + * + * @param ids 产品编号集合 + */ + void validateProductsExist(Collection ids); } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java index 44e4819938..fb198c8a3b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.iot.service.product; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; @@ -20,6 +21,7 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import java.time.LocalDateTime; +import java.util.Collection; import java.util.List; import java.util.Objects; @@ -157,4 +159,15 @@ public class IotProductServiceImpl implements IotProductService { return productMapper.selectCountByCreateTime(createTime); } + @Override + public void validateProductsExist(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return; + } + List products = productMapper.selectByIds(ids); + if (products.size() != ids.size()) { + throw exception(PRODUCT_NOT_EXISTS); + } + } + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataRuleService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataRuleService.java index a51e384139..42fdf3099b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataRuleService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataRuleService.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.iot.service.rule.data; +import java.util.List; + import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRulePageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRuleSaveReqVO; @@ -51,4 +53,12 @@ public interface IotDataRuleService { */ PageResult getDataRulePage(IotDataRulePageReqVO pageReqVO); + /** + * 根据数据目的编号,获得数据流转规则列表 + * + * @param sinkId 数据目的编号 + * @return 是否被使用 + */ + List getDataRuleBySinkId(Long sinkId); + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataRuleServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataRuleServiceImpl.java index df6d3e11f4..65c7a393ea 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataRuleServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataRuleServiceImpl.java @@ -1,16 +1,26 @@ package cn.iocoder.yudao.module.iot.service.rule.data; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRulePageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.rule.vo.data.rule.IotDataRuleSaveReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataRuleDO; import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotDataRuleMapper; +import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; +import cn.iocoder.yudao.module.iot.service.product.IotProductService; +import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import java.util.*; + import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DATA_RULE_NOT_EXISTS; /** @@ -25,8 +35,20 @@ public class IotDataRuleServiceImpl implements IotDataRuleService { @Resource private IotDataRuleMapper dataRuleMapper; + @Resource + private IotProductService productService; + @Resource + private IotDeviceService deviceService; + @Resource + private IotThingModelService thingModelService; + @Resource + private IotDataSinkService dataSinkService; + @Override public Long createDataRule(IotDataRuleSaveReqVO createReqVO) { + // 校验数据源配置和数据目的 + validateDataRuleConfig(createReqVO); + // 新增 IotDataRuleDO dataRule = BeanUtils.toBean(createReqVO, IotDataRuleDO.class); dataRuleMapper.insert(dataRule); return dataRule.getId(); @@ -36,6 +58,9 @@ public class IotDataRuleServiceImpl implements IotDataRuleService { public void updateDataRule(IotDataRuleSaveReqVO updateReqVO) { // 校验存在 validateDataRuleExists(updateReqVO.getId()); + // 校验数据源配置和数据目的 + validateDataRuleConfig(updateReqVO); + // 更新 IotDataRuleDO updateObj = BeanUtils.toBean(updateReqVO, IotDataRuleDO.class); dataRuleMapper.updateById(updateObj); @@ -55,6 +80,55 @@ public class IotDataRuleServiceImpl implements IotDataRuleService { } } + /** + * 校验数据流转规则配置 + * + * @param reqVO 数据流转规则保存请求VO + */ + private void validateDataRuleConfig(IotDataRuleSaveReqVO reqVO) { + // 1. 校验数据源配置 + validateSourceConfigs(reqVO.getSourceConfigs()); + // 2. 校验数据目的 + dataSinkService.validateDataSinksExist(reqVO.getSinkIds()); + } + + /** + * 校验数据源配置 + * + * @param sourceConfigs 数据源配置列表 + */ + private void validateSourceConfigs(List sourceConfigs) { + // 1. 校验产品 + productService.validateProductsExist( + convertSet(sourceConfigs, IotDataRuleDO.SourceConfig::getProductId)); + + // 2. 校验设备 + deviceService.validateDevicesExist(convertSet(sourceConfigs, IotDataRuleDO.SourceConfig::getDeviceId, + config -> ObjUtil.notEqual(config.getDeviceId(), IotDeviceDO.DEVICE_ID_ALL))); + + // 3. 校验物模型存在 + validateThingModelsExist(sourceConfigs); + } + + /** + * 校验物模型存在 + * + * @param sourceConfigs 数据源配置列表 + */ + private void validateThingModelsExist(List sourceConfigs) { + Map> productIdToIdentifiers = new HashMap<>(); + for (IotDataRuleDO.SourceConfig config : sourceConfigs) { + if (StrUtil.isEmpty(config.getIdentifier())) { + continue; + } + productIdToIdentifiers.computeIfAbsent(config.getProductId(), + productId -> new HashSet<>()).add(config.getIdentifier()); + } + for (Map.Entry> entry : productIdToIdentifiers.entrySet()) { + thingModelService.validateThingModelsExist(entry.getKey(), entry.getValue()); + } + } + @Override public IotDataRuleDO getDataRule(Long id) { return dataRuleMapper.selectById(id); @@ -65,4 +139,9 @@ public class IotDataRuleServiceImpl implements IotDataRuleService { return dataRuleMapper.selectPage(pageReqVO); } + @Override + public List getDataRuleBySinkId(Long sinkId) { + return dataRuleMapper.selectListBySinkId(sinkId); + } + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataSinkService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataSinkService.java index 4c325f0a24..307163a8ec 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataSinkService.java +++ b/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 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataSinkDO; import jakarta.validation.Valid; +import java.util.Collection; import java.util.List; /** @@ -61,4 +62,11 @@ public interface IotDataSinkService { */ List getDataSinkListByStatus(Integer status); + /** + * 批量校验数据目的存在 + * + * @param ids 数据目的编号集合 + */ + void validateDataSinksExist(Collection ids); + } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataSinkServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataSinkServiceImpl.java index fba06cac69..2b964c9952 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataSinkServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataSinkServiceImpl.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.iot.service.rule.data; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 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 import cn.iocoder.yudao.module.iot.dal.dataobject.rule.IotDataSinkDO; import cn.iocoder.yudao.module.iot.dal.mysql.rule.IotDataSinkMapper; import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import java.util.Collection; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DATA_BRIDGE_NOT_EXISTS; +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DATA_SINK_NOT_EXISTS; +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DATA_SINK_DELETE_FAIL_USED_BY_RULE; /** * IoT 数据流转目的 Service 实现类 @@ -27,6 +31,10 @@ public class IotDataSinkServiceImpl implements IotDataSinkService { @Resource private IotDataSinkMapper dataSinkMapper; + @Resource + @Lazy // 延迟,避免循环依赖报错 + private IotDataRuleService dataRuleService; + @Override public Long createDataSink(IotDataSinkSaveReqVO createReqVO) { IotDataSinkDO dataBridge = BeanUtils.toBean(createReqVO, IotDataSinkDO.class); @@ -47,13 +55,17 @@ public class IotDataSinkServiceImpl implements IotDataSinkService { public void deleteDataSink(Long id) { // 校验存在 validateDataBridgeExists(id); + // 校验是否被数据流转规则使用 + if (CollUtil.isNotEmpty(dataRuleService.getDataRuleBySinkId(id))) { + throw exception(DATA_SINK_DELETE_FAIL_USED_BY_RULE); + } // 删除 dataSinkMapper.deleteById(id); } private void validateDataBridgeExists(Long id) { if (dataSinkMapper.selectById(id) == null) { - throw exception(DATA_BRIDGE_NOT_EXISTS); + throw exception(DATA_SINK_NOT_EXISTS); } } @@ -72,4 +84,15 @@ public class IotDataSinkServiceImpl implements IotDataSinkService { return dataSinkMapper.selectListByStatus(status); } + @Override + public void validateDataSinksExist(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return; + } + List sinks = dataSinkMapper.selectByIds(ids); + if (sinks.size() != ids.size()) { + throw exception(DATA_SINK_NOT_EXISTS); + } + } + } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java index feae3b8adc..b4af6f663d 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelService.java +++ b/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; import java.util.Collection; import java.util.List; +import java.util.Set; /** * IoT 产品物模型 Service 接口 @@ -99,4 +100,12 @@ public interface IotThingModelService { */ List getThingModelList(IotThingModelListReqVO reqVO); + /** + * 批量校验物模型存在 + * + * @param productId 产品编号 + * @param identifiers 标识符集合 + */ + void validateThingModelsExist(Long productId, Set identifiers); + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java index b56063e265..1de8dd5cc8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java +++ b/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 { return thingModelMapper.selectList(reqVO); } + @Override + public void validateThingModelsExist(Long productId, Set identifiers) { + if (CollUtil.isEmpty(identifiers)) { + return; + } + List thingModels = thingModelMapper.selectListByProductIdAndIdentifiers( + productId, identifiers); + Set foundIdentifiers = convertSet(thingModels, IotThingModelDO::getIdentifier); + for (String identifier : identifiers) { + if (!foundIdentifiers.contains(identifier)) { + throw exception(THING_MODEL_NOT_EXISTS); + } + } + } + /** * 校验功能是否存在 *