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

This commit is contained in:
YunaiV
2025-06-29 20:50:56 +08:00
parent d783890b7c
commit dd4027239e
4 changed files with 28 additions and 35 deletions

View File

@@ -81,6 +81,10 @@ public interface IotDeviceMapper extends BaseMapperX<IotDeviceDO> {
.in(IotDeviceDO::getDeviceName, deviceNames));
}
default IotDeviceDO selectBySerialNumber(String serialNumber) {
return selectOne(IotDeviceDO::getSerialNumber, serialNumber);
}
/**
* 查询指定产品下的设备数量
*

View File

@@ -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, "产品分类不存在");

View File

@@ -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);
/**
* 更新设备
*

View File

@@ -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")