Commit dd4027239e9f00917f4125509c38a17fe3aa9cd0

Authored by YunaiV
1 parent d783890b

feat:【IoT 物联网】新增设备序列号唯一性校验,添加序列号查询方法

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<IotDeviceDO> {
81 81 .in(IotDeviceDO::getDeviceName, deviceNames));
82 82 }
83 83  
  84 + default IotDeviceDO selectBySerialNumber(String serialNumber) {
  85 + return selectOne(IotDeviceDO::getSerialNumber, serialNumber);
  86 + }
  87 +
84 88 /**
85 89 * 查询指定产品下的设备数量
86 90 *
... ...
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 {
32 32 ErrorCode DEVICE_NOT_GATEWAY = new ErrorCode(1_050_003_005, "设备不是网关设备");
33 33 ErrorCode DEVICE_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_050_003_006, "导入设备数据不能为空!");
34 34 ErrorCode DEVICE_DOWNSTREAM_FAILED_SERVER_ID_NULL = new ErrorCode(1_050_003_007, "下行设备消息失败,原因:设备未连接网关");
  35 + ErrorCode DEVICE_SERIAL_NUMBER_EXISTS = new ErrorCode(1_050_003_008, "设备序列号已存在,序列号必须全局唯一");
35 36  
36 37 // ========== 产品分类 1-050-004-000 ==========
37 38 ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_050_004_000, "产品分类不存在");
... ...
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;
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*;
5 5 import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceAuthReqDTO;
6   -import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
7 6 import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum;
  7 +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
8 8 import jakarta.validation.Valid;
9   -import jakarta.validation.constraints.NotEmpty;
10 9  
11 10 import javax.annotation.Nullable;
12 11 import java.time.LocalDateTime;
... ... @@ -31,18 +30,6 @@ public interface IotDeviceService {
31 30 Long createDevice(@Valid IotDeviceSaveReqVO createReqVO);
32 31  
33 32 /**
34   - * 【设备注册】创建设备
35   - *
36   - * @param productKey 产品标识
37   - * @param deviceName 设备名称
38   - * @param gatewayId 网关设备 ID
39   - * @return 设备
40   - */
41   - IotDeviceDO createDevice(@NotEmpty(message = "产品标识不能为空") String productKey,
42   - @NotEmpty(message = "设备名称不能为空") String deviceName,
43   - Long gatewayId);
44   -
45   - /**
46 33 * 更新设备
47 34 *
48 35 * @param updateReqVO 更新信息
... ...
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 {
73 73 createReqVO.getGatewayId(), product);
74 74 // 1.3 校验分组存在
75 75 deviceGroupService.validateDeviceGroupExists(createReqVO.getGroupIds());
  76 + // 1.4 校验设备序列号全局唯一
  77 + validateSerialNumberUnique(createReqVO.getSerialNumber(), null);
76 78  
77 79 // 2. 插入到数据库
78 80 IotDeviceDO device = BeanUtils.toBean(createReqVO, IotDeviceDO.class);
... ... @@ -81,34 +83,14 @@ public class IotDeviceServiceImpl implements IotDeviceService {
81 83 return device.getId();
82 84 }
83 85  
84   - @Override
85   - public IotDeviceDO createDevice(String productKey, String deviceName, Long gatewayId) {
86   - // 1.1 校验产品是否存在
87   - IotProductDO product = TenantUtils.executeIgnore(() -> productService.getProductByProductKey(productKey));
88   - if (product == null) {
89   - throw exception(PRODUCT_NOT_EXISTS);
90   - }
91   - return TenantUtils.execute(product.getTenantId(), () -> {
92   - // 1.2 校验设备名称在同一产品下是否唯一
93   - validateCreateDeviceParam(productKey, deviceName, gatewayId, product);
94   -
95   - // 2. 插入到数据库
96   - IotDeviceDO device = new IotDeviceDO().setDeviceName(deviceName).setGatewayId(gatewayId);
97   - initDevice(device, product);
98   - deviceMapper.insert(device);
99   - return device;
100   - });
101   - }
102   -
103 86 private void validateCreateDeviceParam(String productKey, String deviceName,
104 87 Long gatewayId, IotProductDO product) {
  88 + // 校验设备名称在同一产品下是否唯一
105 89 TenantUtils.executeIgnore(() -> {
106   - // 校验设备名称在同一产品下是否唯一
107 90 if (deviceMapper.selectByProductKeyAndDeviceName(productKey, deviceName) != null) {
108 91 throw exception(DEVICE_NAME_EXISTS);
109 92 }
110 93 });
111   -
112 94 // 校验父设备是否为合法网关
113 95 if (IotProductDeviceTypeEnum.isGatewaySub(product.getDeviceType())
114 96 && gatewayId != null) {
... ... @@ -116,6 +98,22 @@ public class IotDeviceServiceImpl implements IotDeviceService {
116 98 }
117 99 }
118 100  
  101 + /**
  102 + * 校验设备序列号全局唯一性
  103 + *
  104 + * @param serialNumber 设备序列号
  105 + * @param excludeId 排除的设备ID(用于更新时排除自身)
  106 + */
  107 + private void validateSerialNumberUnique(String serialNumber, Long excludeId) {
  108 + if (StrUtil.isBlank(serialNumber)) {
  109 + return;
  110 + }
  111 + IotDeviceDO existDevice = deviceMapper.selectBySerialNumber(serialNumber);
  112 + if (existDevice != null && ObjUtil.notEqual(existDevice.getId(), excludeId)) {
  113 + throw exception(DEVICE_SERIAL_NUMBER_EXISTS);
  114 + }
  115 + }
  116 +
119 117 private void initDevice(IotDeviceDO device, IotProductDO product) {
120 118 device.setProductId(product.getId()).setProductKey(product.getProductKey())
121 119 .setDeviceType(product.getDeviceType());
... ... @@ -137,6 +135,8 @@ public class IotDeviceServiceImpl implements IotDeviceService {
137 135 }
138 136 // 1.3 校验分组存在
139 137 deviceGroupService.validateDeviceGroupExists(updateReqVO.getGroupIds());
  138 + // 1.4 校验设备序列号全局唯一
  139 + validateSerialNumberUnique(updateReqVO.getSerialNumber(), updateReqVO.getId());
140 140  
141 141 // 2. 更新到数据库
142 142 IotDeviceDO updateObj = BeanUtils.toBean(updateReqVO, IotDeviceDO.class);
... ... @@ -417,6 +417,7 @@ public class IotDeviceServiceImpl implements IotDeviceService {
417 417 devices.forEach(this::deleteDeviceCache);
418 418 }
419 419  
  420 + @SuppressWarnings("unused")
420 421 @Caching(evict = {
421 422 @CacheEvict(value = RedisKeyConstants.DEVICE, key = "#device.id"),
422 423 @CacheEvict(value = RedisKeyConstants.DEVICE, key = "#device.productKey + '_' + #device.deviceName")
... ...