diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java index 8c939f45e..fd6660b2b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.iot.service.device; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.DeviceConnectionStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -144,6 +145,9 @@ public class DeviceServiceImpl implements DeviceService { throw exception(DEVICE_CODE_ALREADY_EXISTS); } + if (StrUtil.isNotBlank(createReqVO.getDeviceCode())) { + tdengineService.validateTableName(createReqVO.getDeviceCode()); + } DeviceModelDO deviceModelDO = deviceModelMapper.selectById(createReqVO.getDeviceModelId()); @@ -154,11 +158,13 @@ public class DeviceServiceImpl implements DeviceService { device.setTenantId("1"); device.setProtocol(StringUtils.isBlank(device.getProtocol()) || device.getProtocol() == null ? "MQTT":device.getProtocol()); - deviceMapper.insert(device); - insertTemplatePoint(createReqVO, device); + deviceMapper.insert(device); + + //新增点位规则模板 + insertTemplatePoint(createReqVO, device); return device; } @@ -197,6 +203,13 @@ public class DeviceServiceImpl implements DeviceService { List devicePointRulesDOList = new ArrayList<>(); DeviceModelDO deviceModelDO = deviceModelMapper.selectById(deviceModelId); if(deviceModelDO == null){ + DevicePointRulesDO devicePointRulesDO = new DevicePointRulesDO(); + devicePointRulesDO.setIdentifier("RUNNING"); + devicePointRulesDO.setFieldName("运行"); + devicePointRulesDO.setDefaultValue("运行"); + devicePointRulesDO.setDeviceId(deviceId); + devicePointRulesDOList.add(devicePointRulesDO); + devicePointRulesMapper.insert(devicePointRulesDO); return; } List deviceModelRulesDOList = deviceModelRulesMapper.selectList(Wrappers.lambdaQuery() diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java index 8ebade904..9859d8262 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/TDengineService.java @@ -1264,6 +1264,53 @@ public class TDengineService { } + /** + * 验证表名是否符合TDengine规则 + */ + public void validateTableName(String tableName) { + if (StrUtil.isBlank(tableName)) { + throw exception(DEVICE_MODEL_POINT_CODE_EXISTS, "表名不能为空"); + } + + // TDengine 表名规则验证 + // 1. 不能是保留关键字 + Set reservedKeywords = new HashSet<>(Arrays.asList( + "value", "timestamp", "current", "database", "table", "user", "password", + "select", "insert", "update", "delete", "create", "drop", "alter", + "show", "describe", "use", "ts", "now", "current_timestamp" + )); + + if (reservedKeywords.contains(tableName.toLowerCase())) { + throw exception(DEVICE_MODEL_POINT_CODE_EXISTS, + "表名不能使用保留关键字: " + tableName); + } + + // 2. 必须以字母开头 + if (!Character.isLetter(tableName.charAt(0))) { + throw exception(DEVICE_MODEL_POINT_CODE_EXISTS, + "表名必须以字母开头: " + tableName); + } + + // 3. 只能包含字母、数字、下划线 + if (!tableName.matches("^[a-zA-Z][a-zA-Z0-9_]*$")) { + throw exception(DEVICE_MODEL_POINT_CODE_EXISTS, + "表名只能包含字母、数字和下划线: " + tableName); + } + + // 4. 长度限制(TDengine表名最大长度通常为192) + if (tableName.length() > 192) { + throw exception(DEVICE_MODEL_POINT_CODE_EXISTS, + "表名长度不能超过192个字符: " + tableName); + } + + // 5. 不能以下划线开头(与列名策略保持一致) + if (tableName.startsWith("_")) { + throw exception(DEVICE_MODEL_POINT_CODE_EXISTS, + "表名不能以下划线开头: " + tableName); + } + } + + /** * 根据deviceId批量查询最新时间 * @param deviceIds diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/devicemodelattribute/DeviceModelAttributeServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/devicemodelattribute/DeviceModelAttributeServiceImpl.java index 7b334303f..f59f74a23 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/devicemodelattribute/DeviceModelAttributeServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/devicemodelattribute/DeviceModelAttributeServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.iot.service.devicemodelattribute; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; @@ -68,6 +69,10 @@ import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*; @Resource private ErpProductUnitService productUnitService; + @Resource + @Lazy + private TDengineService tDengineService; + @Override public Long createDeviceModelAttribute(DeviceModelAttributeSaveReqVO createReqVO) { @@ -82,9 +87,15 @@ import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*; throw exception(DEVICE_MODEL_ATTRIBUTE_POTIN_CODE_EXISTS); } - // 插入 + // 插入 DeviceModelAttributeDO deviceModelAttribute = BeanUtils.toBean(createReqVO, DeviceModelAttributeDO.class); // deviceModelAttribute.setTypeName(deviceAttributeTypeMapper.selectById(createReqVO.getAttributeCode()).getName()); + + //检查attributeCode是否符合TDengine列名规则 + if (StrUtil.isNotBlank(createReqVO.getAttributeCode())) { + tDengineService.validateColumnName(createReqVO.getAttributeCode()); + } + deviceModelAttributeMapper.insert(deviceModelAttribute); // 返回 return deviceModelAttribute.getId();