From dd4027239e9f00917f4125509c38a17fe3aa9cd0 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 29 Jun 2025 20:50:56 +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=E6=96=B0=E5=A2=9E=E8=AE=BE=E5=A4=87=E5=BA=8F?= =?UTF-8?q?=E5=88=97=E5=8F=B7=E5=94=AF=E4=B8=80=E6=80=A7=E6=A0=A1=E9=AA=8C?= =?UTF-8?q?=EF=BC=8C=E6=B7=BB=E5=8A=A0=E5=BA=8F=E5=88=97=E5=8F=B7=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/dal/mysql/device/IotDeviceMapper.java | 4 ++ .../module/iot/enums/ErrorCodeConstants.java | 1 + .../iot/service/device/IotDeviceService.java | 15 +------ .../service/device/IotDeviceServiceImpl.java | 43 ++++++++++--------- 4 files changed, 28 insertions(+), 35 deletions(-) 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 7cc7d5de81..5f3dc56e04 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 @@ -81,6 +81,10 @@ public interface IotDeviceMapper extends BaseMapperX { .in(IotDeviceDO::getDeviceName, deviceNames)); } + default IotDeviceDO selectBySerialNumber(String serialNumber) { + return selectOne(IotDeviceDO::getSerialNumber, serialNumber); + } + /** * 查询指定产品下的设备数量 * diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java index 1546f8a043..8e445bf540 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java @@ -32,6 +32,7 @@ public interface ErrorCodeConstants { ErrorCode DEVICE_NOT_GATEWAY = new ErrorCode(1_050_003_005, "设备不是网关设备"); ErrorCode DEVICE_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_050_003_006, "导入设备数据不能为空!"); ErrorCode DEVICE_DOWNSTREAM_FAILED_SERVER_ID_NULL = new ErrorCode(1_050_003_007, "下行设备消息失败,原因:设备未连接网关"); + ErrorCode DEVICE_SERIAL_NUMBER_EXISTS = new ErrorCode(1_050_003_008, "设备序列号已存在,序列号必须全局唯一"); // ========== 产品分类 1-050-004-000 ========== ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_050_004_000, "产品分类不存在"); 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 c3a6868945..7bfb9800d0 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 @@ -3,10 +3,9 @@ package cn.iocoder.yudao.module.iot.service.device; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*; import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceAuthReqDTO; -import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import jakarta.validation.Valid; -import jakarta.validation.constraints.NotEmpty; import javax.annotation.Nullable; import java.time.LocalDateTime; @@ -30,18 +29,6 @@ public interface IotDeviceService { */ Long createDevice(@Valid IotDeviceSaveReqVO createReqVO); - /** - * 【设备注册】创建设备 - * - * @param productKey 产品标识 - * @param deviceName 设备名称 - * @param gatewayId 网关设备 ID - * @return 设备 - */ - IotDeviceDO createDevice(@NotEmpty(message = "产品标识不能为空") String productKey, - @NotEmpty(message = "设备名称不能为空") String deviceName, - Long gatewayId); - /** * 更新设备 * 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 ccbd652d6e..be0762e725 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 @@ -73,6 +73,8 @@ public class IotDeviceServiceImpl implements IotDeviceService { createReqVO.getGatewayId(), product); // 1.3 校验分组存在 deviceGroupService.validateDeviceGroupExists(createReqVO.getGroupIds()); + // 1.4 校验设备序列号全局唯一 + validateSerialNumberUnique(createReqVO.getSerialNumber(), null); // 2. 插入到数据库 IotDeviceDO device = BeanUtils.toBean(createReqVO, IotDeviceDO.class); @@ -81,34 +83,14 @@ public class IotDeviceServiceImpl implements IotDeviceService { return device.getId(); } - @Override - public IotDeviceDO createDevice(String productKey, String deviceName, Long gatewayId) { - // 1.1 校验产品是否存在 - IotProductDO product = TenantUtils.executeIgnore(() -> productService.getProductByProductKey(productKey)); - if (product == null) { - throw exception(PRODUCT_NOT_EXISTS); - } - return TenantUtils.execute(product.getTenantId(), () -> { - // 1.2 校验设备名称在同一产品下是否唯一 - validateCreateDeviceParam(productKey, deviceName, gatewayId, product); - - // 2. 插入到数据库 - IotDeviceDO device = new IotDeviceDO().setDeviceName(deviceName).setGatewayId(gatewayId); - initDevice(device, product); - deviceMapper.insert(device); - return device; - }); - } - private void validateCreateDeviceParam(String productKey, String deviceName, Long gatewayId, IotProductDO product) { + // 校验设备名称在同一产品下是否唯一 TenantUtils.executeIgnore(() -> { - // 校验设备名称在同一产品下是否唯一 if (deviceMapper.selectByProductKeyAndDeviceName(productKey, deviceName) != null) { throw exception(DEVICE_NAME_EXISTS); } }); - // 校验父设备是否为合法网关 if (IotProductDeviceTypeEnum.isGatewaySub(product.getDeviceType()) && gatewayId != null) { @@ -116,6 +98,22 @@ public class IotDeviceServiceImpl implements IotDeviceService { } } + /** + * 校验设备序列号全局唯一性 + * + * @param serialNumber 设备序列号 + * @param excludeId 排除的设备ID(用于更新时排除自身) + */ + private void validateSerialNumberUnique(String serialNumber, Long excludeId) { + if (StrUtil.isBlank(serialNumber)) { + return; + } + IotDeviceDO existDevice = deviceMapper.selectBySerialNumber(serialNumber); + if (existDevice != null && ObjUtil.notEqual(existDevice.getId(), excludeId)) { + throw exception(DEVICE_SERIAL_NUMBER_EXISTS); + } + } + private void initDevice(IotDeviceDO device, IotProductDO product) { device.setProductId(product.getId()).setProductKey(product.getProductKey()) .setDeviceType(product.getDeviceType()); @@ -137,6 +135,8 @@ public class IotDeviceServiceImpl implements IotDeviceService { } // 1.3 校验分组存在 deviceGroupService.validateDeviceGroupExists(updateReqVO.getGroupIds()); + // 1.4 校验设备序列号全局唯一 + validateSerialNumberUnique(updateReqVO.getSerialNumber(), updateReqVO.getId()); // 2. 更新到数据库 IotDeviceDO updateObj = BeanUtils.toBean(updateReqVO, IotDeviceDO.class); @@ -417,6 +417,7 @@ public class IotDeviceServiceImpl implements IotDeviceService { devices.forEach(this::deleteDeviceCache); } + @SuppressWarnings("unused") @Caching(evict = { @CacheEvict(value = RedisKeyConstants.DEVICE, key = "#device.id"), @CacheEvict(value = RedisKeyConstants.DEVICE, key = "#device.productKey + '_' + #device.deviceName")