From 05c54827152157983661a391c73d04b2615638c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Wed, 23 Oct 2024 23:23:40 +0800 Subject: [PATCH 001/228] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E3=80=91=20=E9=9B=86=E6=88=90=20tdengine?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 7 + .../yudao-spring-boot-starter-mybatis/pom.xml | 4 + .../yudao/module/iot/domain/BaseEntity.java | 25 ++ .../iot/domain/DeviceDataExportExcelDto.java | 35 ++ .../yudao/module/iot/domain/DeviceDataVo.java | 19 + .../yudao/module/iot/domain/Fields.java | 72 ++++ .../yudao/module/iot/domain/FieldsVo.java | 68 ++++ .../module/iot/domain/IotSequential.java | 71 ++++ .../module/iot/domain/MessageCountVo.java | 25 ++ .../iot/domain/ProductSuperTableModel.java | 39 +++ .../yudao/module/iot/domain/SelectDto.java | 37 ++ .../module/iot/domain/SuperTableDto.java | 38 ++ .../yudao/module/iot/domain/TableDto.java | 33 ++ .../module/iot/domain/TagsSelectDao.java | 33 ++ .../yudao/module/iot/domain/Weather.java | 73 ++++ .../iot/domain/visual/SelectVisualDto.java | 58 ++++ .../product/IotProductFunctionTypeEnum.java | 9 + yudao-module-iot/yudao-module-iot-biz/pom.xml | 5 + .../admin/product/IotProductController.java | 5 +- .../thingModel/ThingModelRespVO.java | 51 +++ .../dal/dataobject/tdengine/FieldParser.java | 80 +++++ .../dal/dataobject/tdengine/TableData.java | 36 ++ .../dal/dataobject/tdengine/TableManager.java | 155 +++++++++ .../iot/dal/dataobject/tdengine/TdField.java | 29 ++ .../dal/dataobject/tdengine/TdResponse.java | 26 ++ .../dal/dataobject/tdengine/TdRestApi.java | 55 +++ .../iot/dal/dataobject/tdengine/TimeData.java | 25 ++ .../iot/dal/tdengine/TdEngineMapper.java | 74 ++++ .../iot/framework/aspect/TaosAspect.java | 38 ++ .../product/IotProductServiceImpl.java | 15 + .../tdengine/IotDbStructureDataService.java | 29 ++ .../IotDbStructureDataServiceImpl.java | 168 +++++++++ .../iot/service/tdengine/TdEngineService.java | 141 ++++++++ .../service/tdengine/TdEngineServiceImpl.java | 93 +++++ .../IotThinkModelFunctionService.java | 6 + .../IotThinkModelFunctionServiceImpl.java | 18 + .../mapper/tdengine/TdEngineMapper.xml | 324 ++++++++++++++++++ 37 files changed, 2016 insertions(+), 3 deletions(-) create mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/BaseEntity.java create mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/DeviceDataExportExcelDto.java create mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/DeviceDataVo.java create mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/Fields.java create mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/FieldsVo.java create mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/IotSequential.java create mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/MessageCountVo.java create mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/ProductSuperTableModel.java create mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SelectDto.java create mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SuperTableDto.java create mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TableDto.java create mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TagsSelectDao.java create mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/Weather.java create mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/visual/SelectVisualDto.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelRespVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/FieldParser.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdField.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdResponse.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TimeData.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/aspect/TaosAspect.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataService.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineService.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineServiceImpl.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 924e52eed..486fe124b 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -33,6 +33,7 @@ 8.1.3.62 8.6.0 5.0.2 + 3.3.3 2.3.0 @@ -253,6 +254,12 @@ ${kingbase.jdbc.version} + + com.taosdata.jdbc + taos-jdbcdriver + ${taos.version} + + cn.iocoder.boot diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml index 1f04e4a63..e907a2de4 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml @@ -63,6 +63,10 @@ opengauss-jdbc true + + com.taosdata.jdbc + taos-jdbcdriver + com.alibaba diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/BaseEntity.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/BaseEntity.java new file mode 100644 index 000000000..74a4c8494 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/BaseEntity.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.iot.domain; + +import lombok.Data; + +/** + * @ClassDescription: tdEngine的基础实体类 + * @ClassName: BaseEntity + * @Author: fxlinks + * @Date: 2021-12-30 14:39:25 + * @Version 1.0 + */ +@Data +public class BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 数据库名称 + */ + private String dataBaseName; + + /** + * 超级表名称 + */ + private String superTableName; +} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/DeviceDataExportExcelDto.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/DeviceDataExportExcelDto.java new file mode 100644 index 000000000..cedb4d119 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/DeviceDataExportExcelDto.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.iot.domain; + +import lombok.Data; + +/** + * 设备数据导出 excel DTO + */ +@Data +public class DeviceDataExportExcelDto { + + /** + * 设备标识 + */ + private String deviceKey; + + /** + * 导出形式 1 单个参数导出 2 全部参数导出 + */ + private String exportType; + + /** + * 导出开始时间 + */ + private String exportBeginTime; + + /** + * 导出结束时间 + */ + private String exportEndTime; + + /** + * 导出参数,空则导出全部 + */ + private String exportParameter; +} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/DeviceDataVo.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/DeviceDataVo.java new file mode 100644 index 000000000..b9f6fc412 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/DeviceDataVo.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.iot.domain; + +import lombok.Data; + +/** + * @ClassDescription: 查询可视化所需入参对象 + * @ClassName: SelectDto + * @Author: andyz + * @Date: 2022-07-29 14:12:26 + * @Version 1.0 + */ +@Data +public class DeviceDataVo { + + + private String deviceId; + + private Long lastTime; +} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/Fields.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/Fields.java new file mode 100644 index 000000000..bbd7bb74e --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/Fields.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.iot.domain; + +import lombok.Data; + +/** + * @ClassDescription: 建表的字段实体类 + * @ClassName: Fields + * @Author: fxlinks + * @Date: 2021-12-28 09:09:04 + * @Version 1.0 + */ +@Data +public class Fields { + private static final long serialVersionUID = 1L; + + /** + * 字段名称 + */ + private String fieldName; + + /** + * 字段值 + */ + private Object fieldValue; + + /** + * 字段数据类型 + */ +// private DataTypeEnum dataType; + + /** + * 字段字节大小 + */ + private Integer size; + + public Fields() { + } + + public Fields(String fieldName, String dataType, Integer size) { +// this.fieldName = fieldName; +// //根据规则匹配字段数据类型 +// switch (dataType.toLowerCase()) { +// case ("json"): +// this.dataType = DataTypeEnum.JSON; +// this.size = size; +// break; +// case ("string"): +// this.dataType = DataTypeEnum.NCHAR; +// this.size = size; +// break; +// case ("binary"): +// this.dataType = DataTypeEnum.BINARY; +// this.size = size; +// break; +// case ("int"): +// this.dataType = DataTypeEnum.INT; +// break; +// case ("bool"): +// this.dataType = DataTypeEnum.BOOL; +// break; +// case ("decimal"): +// this.dataType = DataTypeEnum.DOUBLE; +// break; +// case ("timestamp"): +// if ("eventTime".equals(fieldName)) { +// this.fieldName = "eventTime"; +// } +// this.dataType = DataTypeEnum.TIMESTAMP; +// break; +// } + } +} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/FieldsVo.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/FieldsVo.java new file mode 100644 index 000000000..554d52149 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/FieldsVo.java @@ -0,0 +1,68 @@ +package cn.iocoder.yudao.module.iot.domain; + +import lombok.Data; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +/** + * @ClassDescription: 建表的字段实体类的vo类 + * @ClassName: FieldsVo + * @Author: fxlinks + * @Date: 2021-12-28 11:30:06 + * @Version 1.0 + */ +@Data +public class FieldsVo { + private static final long serialVersionUID = 1L; + + /** + * 字段名称 + */ + private String fieldName; + + /** + * 字段数据类型 + */ + private String dataType; + + /** + * 字段字节大小 + */ + private Integer size; + + /** + * @param fields 字段实体类 + * @return FieldsVo 字段实体vo类 + * @MethodDescription 字段实体类转为vo类 + * @author fx + * @Date 2021/12/28 13:48 + */ + public static FieldsVo fieldsTranscoding(Fields fields) throws SQLException { +// if (StringUtils.isBlank(fields.getFieldName()) || fields.getDataType() == null) { +// throw new SQLException("invalid operation: fieldName or dataType can not be null"); +// } +// FieldsVo fieldsVo = new FieldsVo(); +// fieldsVo.setFieldName(fields.getFieldName()); +// fieldsVo.setDataType(fields.getDataType().getDataType()); +// fieldsVo.setSize(fields.getSize()); +// return fieldsVo; + return null; + } + + /** + * @param fieldsList 字段实体类集合 + * @return List 字段实体vo类集合 + * @MethodDescription 字段实体类集合转为vo类集合 + * @author fx + * @Date 2021/12/28 14:00 + */ + public static List fieldsTranscoding(List fieldsList) throws SQLException { + List fieldsVoList = new ArrayList<>(); + for (Fields fields : fieldsList) { + fieldsVoList.add(fieldsTranscoding(fields)); + } + return fieldsVoList; + } +} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/IotSequential.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/IotSequential.java new file mode 100644 index 000000000..349d6d137 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/IotSequential.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.iot.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.sql.Timestamp; + +public class IotSequential extends BaseEntity { + private static final long serialVersionUID = 1L; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS" , timezone = "GMT+8") + private Timestamp statetime; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS" , timezone = "GMT+8") + private Timestamp endtime; + + private String deviceid; + + private String eventtime; + + private String serviceid; + + private String devices; + + public String getDeviceid() { + return deviceid; + } + + public void setDeviceid(String deviceid) { + this.deviceid = deviceid; + } + + public String getEventtime() { + return eventtime; + } + + public void setEventtime(String eventtime) { + this.eventtime = eventtime; + } + + public String getServiceid() { + return serviceid; + } + + public void setServiceid(String serviceid) { + this.serviceid = serviceid; + } + + public String getDevices() { + return devices; + } + + public void setDevices(String devices) { + this.devices = devices; + } + + public Timestamp getStatetime() { + return statetime; + } + + public void setStatetime(Timestamp statetime) { + this.statetime = statetime; + } + + public Timestamp getEndtime() { + return endtime; + } + + public void setEndtime(Timestamp endtime) { + this.endtime = endtime; + } +} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/MessageCountVo.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/MessageCountVo.java new file mode 100644 index 000000000..e9e93cac0 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/MessageCountVo.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.iot.domain; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 统计的时间数据 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class MessageCountVo { + + /** + * 时间 + */ + private String time; + + /** + * 数据值 + */ + private Object data; + +} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/ProductSuperTableModel.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/ProductSuperTableModel.java new file mode 100644 index 000000000..49887415c --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/ProductSuperTableModel.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.iot.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.sql.Timestamp; +import java.util.HashMap; +import java.util.Optional; + +/** + * @Description: 产品超级表模型 + * @Author: fx + * @Website: http://www.sxfxck.com + * @CreateDate: 2022/1/1$ 19:37$ + * @UpdateUser: fx + * @UpdateDate: 2022/1/1$ 19:37$ + * @UpdateRemark: 修改内容 + * @Version: V1.0 + */ +@Data +public class ProductSuperTableModel { + private static final long serialVersionUID = 1L; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS" , timezone = "GMT+8") + private Timestamp ts; + + private String superTableName; + + /** + * columnsName,columnsProperty + */ + private HashMap columns; + + /** + * tagsName,tagsProperty + */ + private HashMap tags; + +} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SelectDto.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SelectDto.java new file mode 100644 index 000000000..381ef3d6f --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SelectDto.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.iot.domain; + +import lombok.Data; + +import java.util.Set; + +/** + * @ClassDescription: 查询所需入参对象 + * @ClassName: SelectDto + * @Author: fxlinks + * @Date: 2022-01-07 14:12:26 + * @Version 1.0 + */ +@Data +public class SelectDto { + + // @NotBlank(message = "invalid operation: dataBaseName can not be empty") + private String dataBaseName; + +// @NotBlank(message = "invalid operation: tableName can not be empty") + private String tableName; + + // @NotBlank(message = "invalid operation: fieldName can not be empty") + private String fieldName; + + // @NotNull(message = "invalid operation: startTime can not be null") + private Long startTime; + + // @NotNull(message = "invalid operation: endTime can not be null") + private Long endTime; + + private String type; + + private Set orgIds; + + private String deviceId; +} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SuperTableDto.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SuperTableDto.java new file mode 100644 index 000000000..ee80d42cf --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SuperTableDto.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.iot.domain; + +import lombok.Data; + +import java.util.List; + +/** + * @ClassDescription: 创建超级表需要的入参的实体类 + * @ClassName: SuperTableDto + * @Author: fxlinks + * @Date: 2021-12-28 15:03:45 + * @Version 1.0 + */ +@Data +public class SuperTableDto extends BaseEntity { + + /** + * 超级表的表结构(业务相关) + * 第一个字段的数据类型必须为timestamp + * 字符相关数据类型必须指定大小 + * 字段名称和字段数据类型不能为空 + */ +// @NotEmpty(message = "invalid operation: schemaFields can not be empty") + private List schemaFields; + + /** + * 超级表的标签字段,可以作为子表在超级表里的标识 + * 字符相关数据类型必须指定大小 + * 字段名称和字段数据类型不能为空 + */ +// @NotEmpty(message = "invalid operation: tagsFields can not be empty") + private List tagsFields; + + /** + * 字段信息对象,超级表添加列时使用该属性 + */ + private Fields fields; +} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TableDto.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TableDto.java new file mode 100644 index 000000000..f27beb1a6 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TableDto.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.iot.domain; + +import lombok.Data; + +import java.util.List; + +/** + * @ClassDescription: 创建超级表的子表需要的入参的实体类 + * @ClassName: TableDto + * @Author: fxlinks + * @Date: 2021-12-30 14:42:47 + * @Version 1.0 + */ +@Data +public class TableDto extends BaseEntity { + + /** + * 超级表普通列字段的值 + * 值需要与创建超级表时普通列字段的数据类型对应上 + */ + private List schemaFieldValues; + + /** + * 超级表标签字段的值 + * 值需要与创建超级表时标签字段的数据类型对应上 + */ + private List tagsFieldValues; + + /** + * 表名称 + */ + private String tableName; +} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TagsSelectDao.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TagsSelectDao.java new file mode 100644 index 000000000..5cb9c5ed9 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TagsSelectDao.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.iot.domain; + +import lombok.Data; + + +/** + * @program: fxlinks + * @description: 标签查询模型 + * @packagename: com.fx.tdengine.api.domain.rule + * @author: fx + * @e-mainl: 13733918655@163.com + * @date: 2022-07-27 18:40 + **/ +@Data +public class TagsSelectDao { + +// @NotBlank(message = "invalid operation: dataBaseName can not be empty") + private String dataBaseName; + +// @NotBlank(message = "invalid operation: stableName can not be empty") + private String stableName; + +// @NotBlank(message = "invalid operation: tagsName can not be empty") + private String tagsName; + + // @NotNull(message = "invalid operation: startTime can not be null") + private Long startTime; + + // @NotNull(message = "invalid operation: endTime can not be null") + private Long endTime; + + +} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/Weather.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/Weather.java new file mode 100644 index 000000000..a4a1e983b --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/Weather.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.iot.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; + +import java.sql.Timestamp; + +public class Weather { + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS" , timezone = "GMT+8") + private Timestamp ts; + private Float temperature; + private Float humidity; + private String location; + private String note; + private int groupId; + + public Weather() { + } + + public Weather(Timestamp ts, float temperature, float humidity) { + this.ts = ts; + this.temperature = temperature; + this.humidity = humidity; + } + + public Timestamp getTs() { + return ts; + } + + public void setTs(Timestamp ts) { + this.ts = ts; + } + + public Float getTemperature() { + return temperature; + } + + public void setTemperature(Float temperature) { + this.temperature = temperature; + } + + public Float getHumidity() { + return humidity; + } + + public void setHumidity(Float humidity) { + this.humidity = humidity; + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public int getGroupId() { + return groupId; + } + + public void setGroupId(int groupId) { + this.groupId = groupId; + } + + public String getNote() { + return note; + } + + public void setNote(String note) { + this.note = note; + } +} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/visual/SelectVisualDto.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/visual/SelectVisualDto.java new file mode 100644 index 000000000..1444da972 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/visual/SelectVisualDto.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.iot.domain.visual; + +import lombok.Data; + +import java.util.Map; + +/** + * @ClassDescription: 查询可视化所需入参对象 + * @ClassName: SelectDto + * @Author: andyz + * @Date: 2022-07-29 14:12:26 + * @Version 1.0 + */ +@Data +public class SelectVisualDto { + +// @NotBlank(message = "invalid operation: tableName can not be empty") + private String dataBaseName; + +// @NotBlank(message = "invalid operation: tableName can not be empty") + private String tableName; + +// @NotBlank(message = "invalid operation: fieldName can not be empty") //属性 + private String fieldName; + /** + * 查询类型,0历史数据,1实时数据,2聚合数据 + */ + private int type; + /** + * 查询的数据量 + */ + private int num; + /** + * 聚合函数 + */ + private String aggregate; + /** + * 统计间隔数字+s/m/h/d + * 比如1s,1m,1h,1d代表1秒,1分钟,1小时,1天 + */ + private String interval; + // @NotNull(message = "invalid operation: startTime can not be null") + private Long startTime; + + // @NotNull(message = "invalid operation: endTime can not be null") + private Long endTime; + + /** + * 请求参数 + */ + private Map params; + + private String sql; + + private String deviceId; + + private Long lastTime; +} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductFunctionTypeEnum.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductFunctionTypeEnum.java index 7a924997a..b99d2b093 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductFunctionTypeEnum.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductFunctionTypeEnum.java @@ -30,6 +30,15 @@ public enum IotProductFunctionTypeEnum implements IntArrayValuable { */ private final String description; + public static IotProductFunctionTypeEnum valueOf(Integer type) { + for (IotProductFunctionTypeEnum value : values()) { + if (value.getType().equals(type)) { + return value; + } + } + return null; + } + @Override public int[] array() { return ARRAYS; diff --git a/yudao-module-iot/yudao-module-iot-biz/pom.xml b/yudao-module-iot/yudao-module-iot-biz/pom.xml index e3f93086a..cb2fd818f 100644 --- a/yudao-module-iot/yudao-module-iot-biz/pom.xml +++ b/yudao-module-iot/yudao-module-iot-biz/pom.xml @@ -42,6 +42,11 @@ yudao-spring-boot-starter-mybatis + + cn.iocoder.boot + yudao-spring-boot-starter-redis + + cn.iocoder.boot 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 5b0ecb27a..e7f41d91d 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 @@ -83,11 +83,10 @@ public class IotProductController { return success(BeanUtils.toBean(pageResult, IotProductRespVO.class)); } - // TODO @haohao:改成 simple-list 哈 - @GetMapping("/list-all-simple") + @GetMapping("/simple-list") @Operation(summary = "获得所有产品列表") @PreAuthorize("@ss.hasPermission('iot:product:query')") - public CommonResult> listAllSimpleProducts() { + public CommonResult> getSimpleProductList() { List list = productService.getProductList(); return success(BeanUtils.toBean(list, IotProductSimpleRespVO.class)); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelRespVO.java new file mode 100644 index 000000000..6fc48ef4f --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelRespVO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel; + +import lombok.*; + +import java.util.List; +import java.util.Map; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@ToString +public class ThingModelRespVO { + + /** + * 产品编号 + */ + private Long id; + + /** + * 产品标识 + */ + private String productKey; + + /** + * 物模型 + */ + private Model model; + + /** + * 物模型 + */ + @Data + public static class Model { + + /** + * 属性列表 + */ + private List properties; + + /** + * 服务列表 + */ + private List services; + + /** + * 事件列表 + */ + private List events; + } +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/FieldParser.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/FieldParser.java new file mode 100644 index 000000000..0a91e7cf1 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/FieldParser.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; + + +import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty; +import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelRespVO; +import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType.ThingModelDataType; + +import java.util.HashMap; +import java.util.List; +import java.util.stream.Collectors; + +public class FieldParser { + + /** + * 物模型到td数据类型映射 + */ + private static final HashMap TYPE_MAPPING = new HashMap<>() {{ + put("INT", "INT"); + put("FLOAT", "FLOAT"); + put("DOUBLE", "DOUBLE"); + put("BOOL", "BOOL"); + put("ENUM", "NCHAR"); + put("TEXT", "NCHAR"); + put("DATE", "NCHAR"); + }}; + + + /** + * 将物模型字段转换为td字段 + * + * @param property 物模型属性 + * @return TdField对象 + */ + public static TdField parse(ThingModelProperty property) { + String fieldName = property.getIdentifier().toLowerCase(); + ThingModelDataType type = property.getDataType(); + + // 将物模型字段类型映射为td字段类型 + String fType = TYPE_MAPPING.get(type.getType().toUpperCase()); + + int len = -1; + // 如果字段类型为NCHAR,默认长度为64 + if ("NCHAR".equals(fType)) { + len = 64; + } + + return new TdField(fieldName, fType, len); + } + + /** + * 获取物模型中的字段列表 + */ + public static List parse(ThingModelRespVO thingModel) { + return thingModel.getModel().getProperties().stream().map(FieldParser::parse).collect(Collectors.toList()); + } + + /** + * 将从库中查出来的字段信息转换为td字段对象 + */ + public static List parse(List rows) { + return (List) rows.stream().map((r) -> { + List row = (List) r; + String type = row.get(1).toString().toUpperCase(); + return new TdField( + row.get(0).toString(), + type, + type.equals("NCHAR") ? Integer.parseInt(row.get(2).toString()) : -1); + }).collect(Collectors.toList()); + } + + /** + * 获取字段字义 + */ + public static String getFieldDefine(TdField field) { + return "`" + field.getName() + "`" + " " + (field.getLength() > 0 ? + String.format("%s(%d)", field.getType(), field.getLength()) + : field.getType()); + } + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java new file mode 100644 index 000000000..1d42933d4 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; + +import lombok.Data; + +import java.util.List; + +@Data +public class TableData { + + /** + * 超级表普通列字段的名称 + */ + private List schemaFieldList; + + /** + * 超级表标签字段的值 + * 值需要与创建超级表时标签字段的数据类型对应上 + */ + private List tagsValueList; + + /** + * 超级表普通列字段的值 + * 值需要与创建超级表时普通列字段的数据类型对应上 + */ + private List schemaValueList; + + /** + * 表名称 + */ + private String tableName; + + /** + * 超级表名称 + */ + private String superTableName; +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java new file mode 100644 index 000000000..1bf4ecf64 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java @@ -0,0 +1,155 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; + +import java.util.List; + +public class TableManager { + + /** + * 创建超级表模板(含存在判断) + */ + private static final String CREATE_STABLE_INE_TPL = "CREATE STABLE IF NOT EXISTS %s (%s) TAGS (%s);"; + + /** + * 删除超级表 + */ + private static final String DROP_STABLE_TPL = "DROP STABLE IF EXISTS %s;"; + + /** + * 获取表的结构信息 + */ + private static final String DESC_TB_TPL = "DESCRIBE %s;"; + + /** + * 超级表增加列 + */ + private static final String ALTER_STABLE_ADD_COL_TPL = "ALTER STABLE %s ADD COLUMN %s;"; + + /** + * 超级表修改列 + */ + private static final String ALTER_STABLE_MODIFY_COL_TPL = "ALTER STABLE %s MODIFY COLUMN %s;"; + + /** + * 超级表删除列 + */ + private static final String ALTER_STABLE_DROP_COL_TPL = "ALTER STABLE %s DROP COLUMN %s;"; + + /** + * 创建普通表模板(含存在判断) + */ + private static final String CREATE_CTABLE_INE_TPL = "CREATE TABLE IF NOT EXISTS %s (%s)"; + + /** + * 获取创建表sql + */ + public static String getCreateSTableSql(String tbName, List fields, TdField... tags) { + if (fields.isEmpty()) { + return null; + } + + // 生成字段片段 + StringBuilder sbField = new StringBuilder("time TIMESTAMP,"); + + for (TdField field : fields) { + sbField.append(FieldParser.getFieldDefine(field)); + sbField.append(","); + } + sbField.deleteCharAt(sbField.length() - 1); + + String fieldFrag = sbField.toString(); + + // 生成tag + StringBuilder sbTag = new StringBuilder(); + for (TdField tag : tags) { + sbTag.append(FieldParser.getFieldDefine(tag)) + .append(","); + } + sbTag.deleteCharAt(sbTag.length() - 1); + + return String.format(CREATE_STABLE_INE_TPL, tbName, fieldFrag, sbTag); + + } + + /** + * 获取创建普通表sql + */ + public static String getCreateCTableSql(String tbName, List fields) { + if (fields.size() == 0) { + return null; + } + + //生成字段片段 + StringBuilder sbField = new StringBuilder("time timestamp,"); + + for (TdField field : fields) { + sbField.append(FieldParser.getFieldDefine(field)); + sbField.append(","); + } + sbField.deleteCharAt(sbField.length() - 1); + + String fieldFrag = sbField.toString(); + + return String.format(CREATE_CTABLE_INE_TPL, tbName, fieldFrag); + + } + + + /** + * 取正确的表名 + * + * @param name 表象 + */ + public static String rightTbName(String name) { + return name.toLowerCase().replace("-" , "_"); + } + + /** + * 获取表详情的sql + */ + public static String getDescTableSql(String tbName) { + return String.format(DESC_TB_TPL, tbName); + } + + /** + * 获取添加字段sql + */ + public static String getAddSTableColumnSql(String tbName, List fields) { + StringBuilder sbAdd = new StringBuilder(); + for (TdField field : fields) { + sbAdd.append(String.format(ALTER_STABLE_ADD_COL_TPL, + tbName, + FieldParser.getFieldDefine(field) + )); + } + return sbAdd.toString(); + } + + /** + * 获取修改字段sql + */ + public static String getModifySTableColumnSql(String tbName, List fields) { + StringBuilder sbModify = new StringBuilder(); + for (TdField field : fields) { + sbModify.append(String.format(ALTER_STABLE_MODIFY_COL_TPL, + tbName, + FieldParser.getFieldDefine(field) + )); + } + return sbModify.toString(); + } + + /** + * 获取删除字段sql + */ + public static String getDropSTableColumnSql(String tbName, List fields) { + StringBuilder sbDrop = new StringBuilder(); + for (TdField field : fields) { + sbDrop.append(String.format(ALTER_STABLE_DROP_COL_TPL, + tbName, + field.getName() + )); + } + return sbDrop.toString(); + } + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdField.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdField.java new file mode 100644 index 000000000..f040a017a --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdField.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * TD 引擎的字段 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class TdField { + + /** + * 字段名称 + */ + private String name; + + /** + * 字段类型 + */ + private String type; + + /** + * 字段长度 + */ + private int length; +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdResponse.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdResponse.java new file mode 100644 index 000000000..380807a1b --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdResponse.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class TdResponse { + + public static final int CODE_SUCCESS = 0; + public static final int CODE_TB_NOT_EXIST = 866; + + private String status; + + private int code; + + private String desc; + + //[["time","TIMESTAMP",8,""],["powerstate","TINYINT",1,""],["brightness","INT",4,""],["deviceid","NCHAR",32,"TAG"]] + private List data; + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java new file mode 100644 index 000000000..4506383f6 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; + +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +public class TdRestApi { + + @Value("${spring.datasource.dynamic.datasource.master.url}") + private String url; + + @Value("${spring.datasource.dynamic.datasource.master.username}") + private String username; + + @Value("${spring.datasource.dynamic.datasource.master.password}") + private String password; + + private String getRestApiUrl() { + //jdbc:TAOS-RS://127.0.0.1:6041/iotkit?xxxx + String restUrl = url.replace("jdbc:TAOS-RS://" , "") + .replaceAll("\\?.*" , ""); + // /rest/sql/iotkit + int idx = restUrl.lastIndexOf("/"); + //127.0.0.1:6041/rest/sql/iotkit + return String.format("%s/rest/sql/%s" , restUrl.substring(0, idx), restUrl.substring(idx + 1)); + } + + + /** + * 新建td api请求对象 + */ + public HttpRequest newApiRequest(String sql) { + return HttpRequest + .post(getRestApiUrl()) + .body(sql) + .basicAuth(username, password); + } + + /** + * 执行sql + */ + public TdResponse execSql(String sql) { + log.info("exec td sql:{}" , sql); + HttpRequest request = newApiRequest(sql); + HttpResponse response = request.execute(); + return JSONUtil.toBean(response.body(), TdResponse.class); + } + + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TimeData.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TimeData.java new file mode 100644 index 000000000..f7e251ea8 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TimeData.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 统计的时间数据 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class TimeData { + + /** + * 时间 + */ + private long time; + + /** + * 数据值 + */ + private Object data; + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java new file mode 100644 index 000000000..6a925f4e5 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.iot.dal.tdengine; + +import cn.iocoder.yudao.module.iot.domain.FieldsVo; +import cn.iocoder.yudao.module.iot.domain.SelectDto; +import cn.iocoder.yudao.module.iot.domain.TableDto; +import cn.iocoder.yudao.module.iot.domain.TagsSelectDao; +import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +@Mapper +@DS("tdengine") +public interface TdEngineMapper { + + void createDatabase(@Param("dataBaseName") String dataBaseName); + + void createSuperTable(@Param("schemaFields") List schemaFields, + @Param("tagsFields") List tagsFields, + @Param("dataBaseName") String dataBaseName, + @Param("superTableName") String superTableName); + + void createTable(TableDto tableDto); + + void insertData(TableDto tableDto); + + List> selectByTimestamp(SelectDto selectDto); + + void addColumnForSuperTable(@Param("superTableName") String superTableName, + @Param("fieldsVo") FieldsVo fieldsVo); + + void dropColumnForSuperTable(@Param("superTableName") String superTableName, + @Param("fieldsVo") FieldsVo fieldsVo); + + void addTagForSuperTable(@Param("superTableName") String superTableName, + @Param("fieldsVo") FieldsVo fieldsVo); + + void dropTagForSuperTable(@Param("superTableName") String superTableName, + @Param("fieldsVo") FieldsVo fieldsVo); + + Map getCountByTimestamp(SelectDto selectDto); + + /** + * 检查表是否存在 + * + * @param dataBaseName 数据库名称 + * @param tableName 表名称 + */ + Integer checkTableExists(@Param("dataBaseName") String dataBaseName, @Param("tableName") String tableName); + + Map getLastData(SelectDto selectDto); + + List> getHistoryData(SelectVisualDto selectVisualDto); + + List> getRealtimeData(SelectVisualDto selectVisualDto); + + List> getAggregateData(SelectVisualDto selectVisualDto); + + List> getLastDataByTags(TagsSelectDao tagsSelectDao); + + /** + * 创建超级表 + * + * @param sql sql + * @return 返回值 + */ + @InterceptorIgnore(tenantLine = "true") + Integer createSuperTableDevice(String sql); + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/aspect/TaosAspect.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/aspect/TaosAspect.java new file mode 100644 index 000000000..7c9fe7000 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/aspect/TaosAspect.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.iot.framework.aspect; + +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.stereotype.Component; + +import java.sql.Timestamp; +import java.util.Map; + +/** + * TaosAspect 是一个处理 Taos 数据库返回值的切面。 + */ +@Aspect +@Component +@Slf4j +public class TaosAspect { + + @Around("execution(java.util.Map cn.iocoder.yudao.module.iot.dal.tdengine.*.*(..))") + public Object handleType(ProceedingJoinPoint joinPoint) { + Map result = null; + try { + result = (Map) joinPoint.proceed(); + result.replaceAll((key, value) -> { + if (value instanceof byte[]) { + return new String((byte[]) value); + } else if (value instanceof Timestamp) { + return ((Timestamp) value).getTime(); + } + return value; + }); + } catch (Throwable e) { + log.error("TaosAspect handleType error", e); + } + return result; + } +} 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 15391f70b..d0ca09288 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 @@ -8,8 +8,13 @@ import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReq import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductMapper; import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum; +import cn.iocoder.yudao.module.iot.service.thinkmodelfunction.IotThinkModelFunctionService; +import com.baomidou.dynamic.datasource.annotation.DSTransactional; import jakarta.annotation.Resource; + +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.util.List; @@ -31,6 +36,10 @@ public class IotProductServiceImpl implements IotProductService { @Resource private IotProductMapper productMapper; + @Resource + @Lazy + private IotThinkModelFunctionService thinkModelFunctionService; + @Override public Long createProduct(IotProductSaveReqVO createReqVO) { // 1. 生成 ProductKey @@ -106,11 +115,17 @@ public class IotProductServiceImpl implements IotProductService { } @Override + @DSTransactional(rollbackFor = Exception.class) public void updateProductStatus(Long id, Integer status) { // 1. 校验存在 validateProductExists(id); // 2. 更新 IotProductDO updateObj = IotProductDO.builder().id(id).status(status).build(); + // 3. 产品是发布状态 + if (Objects.equals(status, IotProductStatusEnum.PUBLISHED.getType())) { + // 3.1 创建超级表数据模型 + thinkModelFunctionService.createSuperTableDataModel(id); + } productMapper.updateById(updateObj); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataService.java new file mode 100644 index 000000000..42439e25a --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataService.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + + +import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelRespVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; + +import java.util.List; + +/** + * 数据结构接口 + */ +public interface IotDbStructureDataService { + + /** + * 创建物模型定义 + */ + void createSuperTable(ThingModelRespVO thingModel, Integer deviceType); + + /** + * 更新物模型定义 + */ + void updateSuperTable(ThingModelRespVO thingModel, Integer deviceType); + + /** + * 创建超级表数据模型 + */ + void createSuperTableDataModel(IotProductDO product, List functionList); +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java new file mode 100644 index 000000000..f8dd6feb5 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java @@ -0,0 +1,168 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.hutool.json.JSONUtil; +import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty; +import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelRespVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.*; +import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineMapper; +import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +@Service +@Slf4j +public class IotDbStructureDataServiceImpl implements IotDbStructureDataService { + + @Resource + private TdEngineMapper tdEngineMapper; + + @Resource + private TdRestApi tdRestApi; + + @Override + public void createSuperTable(ThingModelRespVO thingModel, Integer deviceType) { + // 获取物模型中的属性定义 + List fields = FieldParser.parse(thingModel); + String tbName = getProductPropertySTableName(deviceType, thingModel.getProductKey()); + + // 生成创建超级表的 SQL + String sql = TableManager.getCreateSTableSql(tbName, fields, new TdField("device_id", "NCHAR", 64)); + if (sql == null) { + log.warn("生成的 SQL 为空,无法创建超级表"); + return; + } + log.info("执行 SQL: {}", sql); + + // 执行 SQL 创建超级表 + tdEngineMapper.createSuperTableDevice(sql); + } + + @Override + public void updateSuperTable(ThingModelRespVO thingModel, Integer deviceType) { + try { + // 获取旧字段信息 + String tbName = getProductPropertySTableName(deviceType, thingModel.getProductKey()); + String sql = TableManager.getDescTableSql(tbName); + TdResponse response = tdRestApi.execSql(sql); + if (response.getCode() != TdResponse.CODE_SUCCESS) { + throw new RuntimeException("获取表描述错误: " + JSONUtil.toJsonStr(response)); + } + + List oldFields = FieldParser.parse(response.getData()); + List newFields = FieldParser.parse(thingModel); + + // 找出新增的字段 + List addFields = newFields.stream() + .filter(f -> oldFields.stream().noneMatch(old -> old.getName().equals(f.getName()))) + .collect(Collectors.toList()); + if (!addFields.isEmpty()) { + sql = TableManager.getAddSTableColumnSql(tbName, addFields); + response = tdRestApi.execSql(sql); + if (response.getCode() != TdResponse.CODE_SUCCESS) { + throw new RuntimeException("添加表字段错误: " + JSONUtil.toJsonStr(response)); + } + } + + // 找出修改的字段 + List modifyFields = newFields.stream() + .filter(f -> oldFields.stream().anyMatch(old -> + old.getName().equals(f.getName()) && + (!old.getType().equals(f.getType()) || old.getLength() != f.getLength()))) + .collect(Collectors.toList()); + if (!modifyFields.isEmpty()) { + sql = TableManager.getModifySTableColumnSql(tbName, modifyFields); + response = tdRestApi.execSql(sql); + if (response.getCode() != TdResponse.CODE_SUCCESS) { + throw new RuntimeException("修改表字段错误: " + JSONUtil.toJsonStr(response)); + } + } + + // 找出删除的字段 + List dropFields = oldFields.stream() + .filter(f -> !"time".equals(f.getName()) && !"device_id".equals(f.getName()) && + newFields.stream().noneMatch(n -> n.getName().equals(f.getName()))) + .collect(Collectors.toList()); + if (!dropFields.isEmpty()) { + sql = TableManager.getDropSTableColumnSql(tbName, dropFields); + response = tdRestApi.execSql(sql); + if (response.getCode() != TdResponse.CODE_SUCCESS) { + throw new RuntimeException("删除表字段错误: " + JSONUtil.toJsonStr(response)); + } + } + } catch (Throwable e) { + log.error("更新物模型超级表失败", e); + } + } + + @Override + public void createSuperTableDataModel(IotProductDO product, List functionList) { + // 1. 生成 ThingModelRespVO + ThingModelRespVO thingModel = new ThingModelRespVO(); + thingModel.setId(product.getId()); + thingModel.setProductKey(product.getProductKey()); + + // 1.1 设置属性、服务和事件 + ThingModelRespVO.Model model = new ThingModelRespVO.Model(); + List properties = new ArrayList<>(); + + // 1.2 遍历功能列表并分类 + for (IotThinkModelFunctionDO function : functionList) { + if (Objects.requireNonNull(IotProductFunctionTypeEnum.valueOf(function.getType())) == IotProductFunctionTypeEnum.PROPERTY) { + ThingModelProperty property = new ThingModelProperty(); + property.setIdentifier(function.getIdentifier()); + property.setName(function.getName()); + property.setDescription(function.getDescription()); + property.setDataType(function.getProperty().getDataType()); + properties.add(property); + } + } + + // 1.3 判断属性列表是否为空 + if (properties.isEmpty()) { + log.warn("物模型属性列表为空,不创建超级表"); + return; + } + + model.setProperties(properties); + thingModel.setModel(model); + + // 2. 判断是否已经创建,如果已经创建则进行更新 + String tbName = getProductPropertySTableName(product.getDeviceType(), product.getProductKey()); + Integer iot = tdEngineMapper.checkTableExists("ruoyi_vue_pro", tbName); + if (iot != null && iot > 0) { + // 3. 更新 + updateSuperTable(thingModel, product.getDeviceType()); + } else { + // 4. 创建 + createSuperTable(thingModel, product.getDeviceType()); + } + } + + /** + * 根据产品key获取产品属性超级表名 + */ + static String getProductPropertySTableName(Integer deviceType, String productKey) { + if (deviceType == 1) { + return String.format("gateway_sub_" + productKey).toLowerCase(); + } else if (deviceType == 2) { + return String.format("gateway_" + productKey).toLowerCase(); + } else { + return String.format("device_" + productKey).toLowerCase(); + } + } + + /** + * 根据deviceId获取设备属性表名 + */ + static String getDevicePropertyTableName(String deviceType, String productKey, String deviceKey) { + return String.format(deviceType + "_" + productKey + "_" + deviceKey).toLowerCase(); + } +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineService.java new file mode 100644 index 000000000..b3ae6f818 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineService.java @@ -0,0 +1,141 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.domain.FieldsVo; +import cn.iocoder.yudao.module.iot.domain.SelectDto; +import cn.iocoder.yudao.module.iot.domain.TableDto; +import cn.iocoder.yudao.module.iot.domain.TagsSelectDao; +import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; + +import java.util.List; +import java.util.Map; + +/** + * TdEngineService + */ +public interface TdEngineService { + + /** + * 创建数据库 + * + * @param dataBaseName 数据库名称 + * @throws Exception 异常 + */ + void createDateBase(String dataBaseName) throws Exception; + + /** + * 创建超级表 + * + * @param schemaFields schema字段 + * @param tagsFields tags字段 + * @param dataBaseName 数据库名称 + * @param superTableName 超级表名称 + * @throws Exception 异常 + */ + void createSuperTable(List schemaFields, List tagsFields, String dataBaseName, + String superTableName) throws Exception; + + /** + * 创建表 + * + * @param tableDto 表信息 + * @throws Exception 异常 + */ + void createTable(TableDto tableDto) throws Exception; + + /** + * 插入数据 + * + * @param tableDto 表信息 + * @throws Exception 异常 + */ + void insertData(TableDto tableDto) throws Exception; + + /** + * 根据时间戳查询数据 + * + * @param selectDto 查询条件 + * @return 数据 + * @throws Exception 异常 + */ + List> selectByTimesTamp(SelectDto selectDto) throws Exception; + + /** + * 为超级表添加列 + * + * @param superTableName 超级表名称 + * @param fieldsVo 字段信息 + * @throws Exception 异常 + */ + void addColumnForSuperTable(String superTableName, FieldsVo fieldsVo) throws Exception; + + /** + * 为超级表删除列 + * + * @param superTableName 超级表名称 + * @param fieldsVo 字段信息 + * @throws Exception 异常 + */ + void dropColumnForSuperTable(String superTableName, FieldsVo fieldsVo) throws Exception; + + /** + * 为超级表添加tag + */ + Long getCountByTimesTamp(SelectDto selectDto) throws Exception; + + /** + * 检查表是否存在 + * + * @return 1存在 0不存在 + * @throws Exception 异常 + */ + Integer checkTableExists(SelectDto selectDto) throws Exception; + + /** + * 初始化超级表 + * + * @param msg 消息 + * @throws Exception 异常 + */ + void initSTableFrame(String msg) throws Exception; + + /** + * 获取最新数据 + * + * @param selectDto 查询条件 + * @return 数据 + * @throws Exception 异常 + */ + Map getLastData(SelectDto selectDto) throws Exception; + + /** + * 根据tag查询最新数据 + * + * @param tagsSelectDao 查询条件 + * @return 数据 + */ + Map> getLastDataByTags(TagsSelectDao tagsSelectDao); + + /** + * 获取历史数据 + * + * @param selectVisualDto 查询条件 + * @return 数据 + */ + List> getHistoryData(SelectVisualDto selectVisualDto); + + /** + * 获取实时数据 + * + * @param selectVisualDto 查询条件 + * @return 数据 + */ + List> getRealtimeData(SelectVisualDto selectVisualDto); + + /** + * 获取聚合数据 + * + * @param selectVisualDto 查询条件 + * @return 数据 + */ + List> getAggregateData(SelectVisualDto selectVisualDto); +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineServiceImpl.java new file mode 100644 index 000000000..70933617f --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineServiceImpl.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.domain.FieldsVo; +import cn.iocoder.yudao.module.iot.domain.SelectDto; +import cn.iocoder.yudao.module.iot.domain.TableDto; +import cn.iocoder.yudao.module.iot.domain.TagsSelectDao; +import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +@Service +@Slf4j +public class TdEngineServiceImpl implements TdEngineService { + + + @Override + public void createDateBase(String dataBaseName) { + + } + + @Override + public void createSuperTable(List schemaFields, List tagsFields, String dataBaseName, String superTableName) { + + } + + @Override + public void createTable(TableDto tableDto) { + + } + + @Override + public void insertData(TableDto tableDto) { + + } + + @Override + public List> selectByTimesTamp(SelectDto selectDto) { + return List.of(); + } + + @Override + public void addColumnForSuperTable(String superTableName, FieldsVo fieldsVo) { + + } + + @Override + public void dropColumnForSuperTable(String superTableName, FieldsVo fieldsVo) { + + } + + @Override + public Long getCountByTimesTamp(SelectDto selectDto) { + return 0L; + } + + @Override + public Integer checkTableExists(SelectDto selectDto) { + return 0; + } + + @Override + public void initSTableFrame(String msg) { + + } + + @Override + public Map getLastData(SelectDto selectDto) { + return Map.of(); + } + + @Override + public Map> getLastDataByTags(TagsSelectDao tagsSelectDao) { + return Map.of(); + } + + @Override + public List> getHistoryData(SelectVisualDto selectVisualDto) { + return List.of(); + } + + @Override + public List> getRealtimeData(SelectVisualDto selectVisualDto) { + return List.of(); + } + + @Override + public List> getAggregateData(SelectVisualDto selectVisualDto) { + return List.of(); + } +} \ 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/thinkmodelfunction/IotThinkModelFunctionService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java index ce8e472f5..3067772e6 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java @@ -62,4 +62,10 @@ public interface IotThinkModelFunctionService { */ PageResult getThinkModelFunctionPage(IotThinkModelFunctionPageReqVO pageReqVO); + /** + * 创建超级表数据模型 + * + * @param productId 产品编号 + */ + void createSuperTableDataModel(Long productId); } \ 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/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java index 793786944..1e356c6b7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java @@ -15,10 +15,13 @@ import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingMode import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionPageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionSaveReqVO; import cn.iocoder.yudao.module.iot.convert.thinkmodelfunction.IotThinkModelFunctionConvert; +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import cn.iocoder.yudao.module.iot.dal.mysql.thinkmodelfunction.IotThinkModelFunctionMapper; import cn.iocoder.yudao.module.iot.enums.product.IotAccessModeEnum; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; +import cn.iocoder.yudao.module.iot.service.product.IotProductService; +import cn.iocoder.yudao.module.iot.service.tdengine.IotDbStructureDataService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -45,6 +48,11 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe @Resource private IotThinkModelFunctionMapper thinkModelFunctionMapper; + @Resource + private IotProductService productService; + @Resource + private IotDbStructureDataService dbStructureDataService; + @Override @Transactional(rollbackFor = Exception.class) public Long createThinkModelFunction(IotThinkModelFunctionSaveReqVO createReqVO) { @@ -162,6 +170,16 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe return thinkModelFunctionMapper.selectPage(pageReqVO); } + @Override + public void createSuperTableDataModel(Long productId) { + // 1. 查询产品 + IotProductDO product = productService.getProduct(productId); + // 2. 查询产品的物模型功能列表 + List functionList = thinkModelFunctionMapper.selectListByProductId(productId); + // 3. 生成 TDengine 的数据模型 + dbStructureDataService.createSuperTableDataModel(product, functionList); + } + /** * 创建默认的事件和服务 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml new file mode 100644 index 000000000..f722e0130 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml @@ -0,0 +1,324 @@ + + + + + + + create database if not exists #{dataBaseName} + + + + create table if not exists #{dataBaseName}.#{superTableName} + + + ${item.fieldName} + + + + + timestamp + + + tinyint + + + smallint + + + int + + + bigint + + + float + + + double + + + binary + + + nchar + + + bool + + + json + + + + + (#{item.size}) + + + tags + + + + ${item.fieldName} + + + + + timestamp + + + tinyint + + + smallint + + + int + + + bigint + + + float + + + double + + + binary + + + nchar + + + bool + + + json + + + + + (#{item.size}) + + + + + + create table + if not exists #{dataBaseName}.#{tableName} + using #{dataBaseName}.#{superTableName} + tags + + #{item.fieldValue} + + + + + insert into #{dataBaseName}.#{tableName} + + #{item.fieldName} + + using #{dataBaseName}.#{superTableName} + tags + + #{item.fieldValue} + + values + + #{item.fieldValue} + + + + + + select * from #{dataBaseName}.#{tableName} + + + where ${fieldName} + between #{startTime} and #{endTime} + + + + ALTER + STABLE + #{superTableName} + ADD + COLUMN + + #{fieldsVo.fieldName} + + + + + timestamp + + + tinyint + + + smallint + + + int + + + bigint + + + float + + + double + + + binary + + + nchar + + + bool + + + json + + + + + ( + #{fieldsVo.size} + ) + + + + + ALTER + STABLE + #{superTableName} + DROP + COLUMN + + #{fieldsVo.fieldName} + + + + + ALTER + STABLE + #{superTableName} + ADD + TAG + + #{fieldsVo.fieldName} + + + + + timestamp + + + tinyint + + + smallint + + + int + + + bigint + + + float + + + double + + + binary + + + nchar + + + bool + + + json + + + + + ( + #{fieldsVo.size} + ) + + + + + ALTER + STABLE + #{superTableName} + DROP + TAG + + #{fieldsVo.fieldName} + + + + + SELECT count(0) AS count + FROM #{dataBaseName}.#{tableName} WHERE ${fieldName} BETWEEN #{startTime} AND #{endTime} + + + + SELECT COUNT(0) + FROM information_schema.ins_tables + WHERE db_name = #{dataBaseName} + AND table_name = #{tableName} + + + + select last(time), * + from #{tableName} + where device_id = #{deviceId} + + + + select last(*) + from #{dataBaseName}.#{stableName} group by ${tagsName} + + + + SELECT #{fieldName}, ts + FROM #{dataBaseName}.#{tableName} WHERE ts BETWEEN #{startTime} AND #{endTime} + LIMIT #{num} + + + SELECT #{fieldName}, ts + FROM #{dataBaseName}.#{tableName} LIMIT #{num} + + + SELECT #{aggregate}(${fieldName}) + FROM #{dataBaseName}.#{tableName} WHERE ts BETWEEN #{startTime} AND #{endTime} interval (${interval}) + LIMIT #{num} + + + + + ${sql} + + + From 61a0c05279613e6b9a95ef4ecc80cce7b2d3dc44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Wed, 23 Oct 2024 23:26:24 +0800 Subject: [PATCH 002/228] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E3=80=91=20=E9=9B=86=E6=88=90=20tdengine?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/iot/domain/BaseEntity.java | 7 ------- .../yudao/module/iot/domain/Fields.java | 7 ------- .../yudao/module/iot/domain/FieldsVo.java | 21 ------------------- .../iot/domain/ProductSuperTableModel.java | 12 +---------- .../yudao/module/iot/domain/SelectDto.java | 7 ------- .../module/iot/domain/SuperTableDto.java | 7 ------- .../yudao/module/iot/domain/TableDto.java | 7 ------- .../module/iot/domain/TagsSelectDao.java | 14 +++---------- 8 files changed, 4 insertions(+), 78 deletions(-) diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/BaseEntity.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/BaseEntity.java index 74a4c8494..496be9a24 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/BaseEntity.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/BaseEntity.java @@ -2,13 +2,6 @@ package cn.iocoder.yudao.module.iot.domain; import lombok.Data; -/** - * @ClassDescription: tdEngine的基础实体类 - * @ClassName: BaseEntity - * @Author: fxlinks - * @Date: 2021-12-30 14:39:25 - * @Version 1.0 - */ @Data public class BaseEntity { private static final long serialVersionUID = 1L; diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/Fields.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/Fields.java index bbd7bb74e..ec0a7f148 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/Fields.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/Fields.java @@ -2,13 +2,6 @@ package cn.iocoder.yudao.module.iot.domain; import lombok.Data; -/** - * @ClassDescription: 建表的字段实体类 - * @ClassName: Fields - * @Author: fxlinks - * @Date: 2021-12-28 09:09:04 - * @Version 1.0 - */ @Data public class Fields { private static final long serialVersionUID = 1L; diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/FieldsVo.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/FieldsVo.java index 554d52149..07aede29d 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/FieldsVo.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/FieldsVo.java @@ -6,13 +6,6 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -/** - * @ClassDescription: 建表的字段实体类的vo类 - * @ClassName: FieldsVo - * @Author: fxlinks - * @Date: 2021-12-28 11:30:06 - * @Version 1.0 - */ @Data public class FieldsVo { private static final long serialVersionUID = 1L; @@ -32,13 +25,6 @@ public class FieldsVo { */ private Integer size; - /** - * @param fields 字段实体类 - * @return FieldsVo 字段实体vo类 - * @MethodDescription 字段实体类转为vo类 - * @author fx - * @Date 2021/12/28 13:48 - */ public static FieldsVo fieldsTranscoding(Fields fields) throws SQLException { // if (StringUtils.isBlank(fields.getFieldName()) || fields.getDataType() == null) { // throw new SQLException("invalid operation: fieldName or dataType can not be null"); @@ -51,13 +37,6 @@ public class FieldsVo { return null; } - /** - * @param fieldsList 字段实体类集合 - * @return List 字段实体vo类集合 - * @MethodDescription 字段实体类集合转为vo类集合 - * @author fx - * @Date 2021/12/28 14:00 - */ public static List fieldsTranscoding(List fieldsList) throws SQLException { List fieldsVoList = new ArrayList<>(); for (Fields fields : fieldsList) { diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/ProductSuperTableModel.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/ProductSuperTableModel.java index 49887415c..c5989811f 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/ProductSuperTableModel.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/ProductSuperTableModel.java @@ -7,21 +7,11 @@ import java.sql.Timestamp; import java.util.HashMap; import java.util.Optional; -/** - * @Description: 产品超级表模型 - * @Author: fx - * @Website: http://www.sxfxck.com - * @CreateDate: 2022/1/1$ 19:37$ - * @UpdateUser: fx - * @UpdateDate: 2022/1/1$ 19:37$ - * @UpdateRemark: 修改内容 - * @Version: V1.0 - */ @Data public class ProductSuperTableModel { private static final long serialVersionUID = 1L; - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS" , timezone = "GMT+8") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS", timezone = "GMT+8") private Timestamp ts; private String superTableName; diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SelectDto.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SelectDto.java index 381ef3d6f..c20e5ab5e 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SelectDto.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SelectDto.java @@ -4,13 +4,6 @@ import lombok.Data; import java.util.Set; -/** - * @ClassDescription: 查询所需入参对象 - * @ClassName: SelectDto - * @Author: fxlinks - * @Date: 2022-01-07 14:12:26 - * @Version 1.0 - */ @Data public class SelectDto { diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SuperTableDto.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SuperTableDto.java index ee80d42cf..a15f135cf 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SuperTableDto.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SuperTableDto.java @@ -4,13 +4,6 @@ import lombok.Data; import java.util.List; -/** - * @ClassDescription: 创建超级表需要的入参的实体类 - * @ClassName: SuperTableDto - * @Author: fxlinks - * @Date: 2021-12-28 15:03:45 - * @Version 1.0 - */ @Data public class SuperTableDto extends BaseEntity { diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TableDto.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TableDto.java index f27beb1a6..5ffe9f84e 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TableDto.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TableDto.java @@ -4,13 +4,6 @@ import lombok.Data; import java.util.List; -/** - * @ClassDescription: 创建超级表的子表需要的入参的实体类 - * @ClassName: TableDto - * @Author: fxlinks - * @Date: 2021-12-30 14:42:47 - * @Version 1.0 - */ @Data public class TableDto extends BaseEntity { diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TagsSelectDao.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TagsSelectDao.java index 5cb9c5ed9..8833b0b50 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TagsSelectDao.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TagsSelectDao.java @@ -3,24 +3,16 @@ package cn.iocoder.yudao.module.iot.domain; import lombok.Data; -/** - * @program: fxlinks - * @description: 标签查询模型 - * @packagename: com.fx.tdengine.api.domain.rule - * @author: fx - * @e-mainl: 13733918655@163.com - * @date: 2022-07-27 18:40 - **/ @Data public class TagsSelectDao { -// @NotBlank(message = "invalid operation: dataBaseName can not be empty") + // @NotBlank(message = "invalid operation: dataBaseName can not be empty") private String dataBaseName; -// @NotBlank(message = "invalid operation: stableName can not be empty") + // @NotBlank(message = "invalid operation: stableName can not be empty") private String stableName; -// @NotBlank(message = "invalid operation: tagsName can not be empty") + // @NotBlank(message = "invalid operation: tagsName can not be empty") private String tagsName; // @NotNull(message = "invalid operation: startTime can not be null") From ea8dd67e9ecc34e7e8af3402f00c819d53f5130a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Wed, 23 Oct 2024 23:38:55 +0800 Subject: [PATCH 003/228] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91=E5=A2=9E=E5=8A=A0=E6=B3=A8=E8=A7=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/device/vo/IotDevicePageReqVO.java | 1 - .../admin/device/vo/IotDeviceRespVO.java | 1 - .../thingModel/ThingModelRespVO.java | 1 - .../vo/IotThinkModelFunctionRespVO.java | 1 - .../dal/dataobject/tdengine/FieldParser.java | 37 ++++++++++--------- .../dal/dataobject/tdengine/TableData.java | 3 ++ .../dal/dataobject/tdengine/TableManager.java | 3 ++ .../dal/dataobject/tdengine/TdResponse.java | 5 ++- .../dal/dataobject/tdengine/TdRestApi.java | 3 ++ 9 files changed, 33 insertions(+), 22 deletions(-) diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDevicePageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDevicePageReqVO.java index 26bdaca05..1c29f9f81 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDevicePageReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDevicePageReqVO.java @@ -10,7 +10,6 @@ import lombok.EqualsAndHashCode; import lombok.ToString; import org.springframework.format.annotation.DateTimeFormat; -import java.math.BigDecimal; import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDeviceRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDeviceRespVO.java index 488f6b907..0b2cf25f5 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDeviceRespVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDeviceRespVO.java @@ -5,7 +5,6 @@ import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import java.math.BigDecimal; import java.time.LocalDateTime; @Schema(description = "管理后台 - IoT 设备 Response VO") diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelRespVO.java index 6fc48ef4f..d7478e54a 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelRespVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelRespVO.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingMod import lombok.*; import java.util.List; -import java.util.Map; @Data @Builder diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionRespVO.java index 9ef3f58d8..e2f3d2ddc 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionRespVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionRespVO.java @@ -9,7 +9,6 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.time.LocalDateTime; -import java.util.List; @Schema(description = "管理后台 - IoT 产品物模型 Response VO") @Data diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/FieldParser.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/FieldParser.java index 0a91e7cf1..e045e5ea3 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/FieldParser.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/FieldParser.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; - import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty; import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelRespVO; import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType.ThingModelDataType; @@ -9,21 +8,26 @@ import java.util.HashMap; import java.util.List; import java.util.stream.Collectors; +/** + * FieldParser 类用于解析和转换物模型字段到 TDengine 字段 + * + */ public class FieldParser { /** * 物模型到td数据类型映射 */ - private static final HashMap TYPE_MAPPING = new HashMap<>() {{ - put("INT", "INT"); - put("FLOAT", "FLOAT"); - put("DOUBLE", "DOUBLE"); - put("BOOL", "BOOL"); - put("ENUM", "NCHAR"); - put("TEXT", "NCHAR"); - put("DATE", "NCHAR"); - }}; - + private static final HashMap TYPE_MAPPING = new HashMap<>() { + { + put("INT", "INT"); + put("FLOAT", "FLOAT"); + put("DOUBLE", "DOUBLE"); + put("BOOL", "BOOL"); + put("ENUM", "NCHAR"); + put("TEXT", "NCHAR"); + put("DATE", "NCHAR"); + } + }; /** * 将物模型字段转换为td字段 @@ -57,9 +61,8 @@ public class FieldParser { /** * 将从库中查出来的字段信息转换为td字段对象 */ - public static List parse(List rows) { - return (List) rows.stream().map((r) -> { - List row = (List) r; + public static List parse(List> rows) { + return rows.stream().map(row -> { String type = row.get(1).toString().toUpperCase(); return new TdField( row.get(0).toString(), @@ -72,9 +75,9 @@ public class FieldParser { * 获取字段字义 */ public static String getFieldDefine(TdField field) { - return "`" + field.getName() + "`" + " " + (field.getLength() > 0 ? - String.format("%s(%d)", field.getType(), field.getLength()) - : field.getType()); + return "`" + field.getName() + "`" + " " + + (field.getLength() > 0 ? String.format("%s(%d)", field.getType(), field.getLength()) + : field.getType()); } } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java index 1d42933d4..5c3c585e7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java @@ -4,6 +4,9 @@ import lombok.Data; import java.util.List; +/** + * TableData 类用于存储和操作 TDengine 表数据 + */ @Data public class TableData { diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java index 1bf4ecf64..b2762f6ed 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java @@ -2,6 +2,9 @@ package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; import java.util.List; +/** + * TableManager 类用于管理 TDengine 表的创建、删除和结构信息获取 + */ public class TableManager { /** diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdResponse.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdResponse.java index 380807a1b..9353565be 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdResponse.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdResponse.java @@ -6,6 +6,9 @@ import lombok.NoArgsConstructor; import java.util.List; +/** + * TdResponse 类用于处理 TDengine 的响应 + */ @Data @NoArgsConstructor @AllArgsConstructor @@ -21,6 +24,6 @@ public class TdResponse { private String desc; //[["time","TIMESTAMP",8,""],["powerstate","TINYINT",1,""],["brightness","INT",4,""],["deviceid","NCHAR",32,"TAG"]] - private List data; + private List data; } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java index 4506383f6..ef6b8b5b4 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java @@ -7,6 +7,9 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +/** + * TdRestApi 类用于处理 TDengine 的 REST API 请求 + */ @Slf4j @Service public class TdRestApi { From 7b5aa23d5cdc55779ff3048d6cc2e04e82b24b3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Sat, 26 Oct 2024 23:15:31 +0800 Subject: [PATCH 004/228] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91=20=E4=BA=A7=E5=93=81=E5=8F=91=E5=B8=83?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E8=B6=85=E7=BA=A7=E8=A1=A8=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/iot/domain/FieldsVo.java | 26 +- .../dal/dataobject/tdengine/FieldParser.java | 44 +-- .../dal/dataobject/tdengine/TableData.java | 2 +- .../dal/dataobject/tdengine/TableManager.java | 26 +- .../tdengine/{TdField.java => TdFieldDO.java} | 10 +- .../dal/dataobject/tdengine/TdResponse.java | 18 +- .../dal/dataobject/tdengine/TdRestApi.java | 23 +- .../iot/dal/tdengine/TdEngineMapper.java | 87 ++++-- .../IotDbStructureDataServiceImpl.java | 282 +++++++++++------- .../iot/service/tdengine/TdEngineService.java | 75 ++--- .../service/tdengine/TdEngineServiceImpl.java | 44 ++- .../IotThinkModelFunctionServiceImpl.java | 2 + .../mapper/tdengine/TdEngineMapper.xml | 223 +++++++------- 13 files changed, 491 insertions(+), 371 deletions(-) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/{TdField.java => TdFieldDO.java} (68%) diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/FieldsVo.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/FieldsVo.java index 07aede29d..fc86a8f7e 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/FieldsVo.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/FieldsVo.java @@ -1,14 +1,18 @@ package cn.iocoder.yudao.module.iot.domain; +import lombok.Builder; import lombok.Data; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +/** + * 字段信息 VO + */ @Data +@Builder public class FieldsVo { - private static final long serialVersionUID = 1L; /** * 字段名称 @@ -24,24 +28,4 @@ public class FieldsVo { * 字段字节大小 */ private Integer size; - - public static FieldsVo fieldsTranscoding(Fields fields) throws SQLException { -// if (StringUtils.isBlank(fields.getFieldName()) || fields.getDataType() == null) { -// throw new SQLException("invalid operation: fieldName or dataType can not be null"); -// } -// FieldsVo fieldsVo = new FieldsVo(); -// fieldsVo.setFieldName(fields.getFieldName()); -// fieldsVo.setDataType(fields.getDataType().getDataType()); -// fieldsVo.setSize(fields.getSize()); -// return fieldsVo; - return null; - } - - public static List fieldsTranscoding(List fieldsList) throws SQLException { - List fieldsVoList = new ArrayList<>(); - for (Fields fields : fieldsList) { - fieldsVoList.add(fieldsTranscoding(fields)); - } - return fieldsVoList; - } } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/FieldParser.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/FieldParser.java index e045e5ea3..344d65c9a 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/FieldParser.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/FieldParser.java @@ -10,7 +10,6 @@ import java.util.stream.Collectors; /** * FieldParser 类用于解析和转换物模型字段到 TDengine 字段 - * */ public class FieldParser { @@ -35,49 +34,58 @@ public class FieldParser { * @param property 物模型属性 * @return TdField对象 */ - public static TdField parse(ThingModelProperty property) { + public static TdFieldDO parse(ThingModelProperty property) { String fieldName = property.getIdentifier().toLowerCase(); ThingModelDataType type = property.getDataType(); // 将物模型字段类型映射为td字段类型 String fType = TYPE_MAPPING.get(type.getType().toUpperCase()); - int len = -1; // 如果字段类型为NCHAR,默认长度为64 + int dataLength = 0; if ("NCHAR".equals(fType)) { - len = 64; + dataLength = 64; } - - return new TdField(fieldName, fType, len); + return new TdFieldDO(fieldName, fType, dataLength); } /** - * 获取物模型中的字段列表 + * 从物模型中获取字段列表 + * + * @param thingModel 物模型响应对象 + * @return 字段列表 */ - public static List parse(ThingModelRespVO thingModel) { - return thingModel.getModel().getProperties().stream().map(FieldParser::parse).collect(Collectors.toList()); + public static List parse(ThingModelRespVO thingModel) { + return thingModel.getModel().getProperties().stream() + .map(FieldParser::parse) + .collect(Collectors.toList()); } /** - * 将从库中查出来的字段信息转换为td字段对象 + * 将从库中查出来的字段信息转换为 TDengine 字段对象 + * + * @param rows 从库中查出的字段信息列表 + * @return 转换后的 TDengine 字段对象列表 */ - public static List parse(List> rows) { + public static List parse(List> rows) { return rows.stream().map(row -> { String type = row.get(1).toString().toUpperCase(); - return new TdField( + int dataLength = "NCHAR".equals(type) ? Integer.parseInt(row.get(2).toString()) : -1; + return new TdFieldDO( row.get(0).toString(), type, - type.equals("NCHAR") ? Integer.parseInt(row.get(2).toString()) : -1); + dataLength + ); }).collect(Collectors.toList()); } /** * 获取字段字义 */ - public static String getFieldDefine(TdField field) { - return "`" + field.getName() + "`" + " " - + (field.getLength() > 0 ? String.format("%s(%d)", field.getType(), field.getLength()) - : field.getType()); + public static String getFieldDefine(TdFieldDO field) { + return "`" + field.getFieldName() + "`" + " " + + (field.getDataLength() > 0 ? String.format("%s(%d)", field.getDataType(), field.getDataLength()) + : field.getDataType()); } -} +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java index 5c3c585e7..e9acbb7f0 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java @@ -36,4 +36,4 @@ public class TableData { * 超级表名称 */ private String superTableName; -} +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java index b2762f6ed..65663d805 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java @@ -45,7 +45,7 @@ public class TableManager { /** * 获取创建表sql */ - public static String getCreateSTableSql(String tbName, List fields, TdField... tags) { + public static String getCreateSTableSql(String tbName, List fields, TdFieldDO... tags) { if (fields.isEmpty()) { return null; } @@ -53,7 +53,7 @@ public class TableManager { // 生成字段片段 StringBuilder sbField = new StringBuilder("time TIMESTAMP,"); - for (TdField field : fields) { + for (TdFieldDO field : fields) { sbField.append(FieldParser.getFieldDefine(field)); sbField.append(","); } @@ -63,7 +63,7 @@ public class TableManager { // 生成tag StringBuilder sbTag = new StringBuilder(); - for (TdField tag : tags) { + for (TdFieldDO tag : tags) { sbTag.append(FieldParser.getFieldDefine(tag)) .append(","); } @@ -76,7 +76,7 @@ public class TableManager { /** * 获取创建普通表sql */ - public static String getCreateCTableSql(String tbName, List fields) { + public static String getCreateCTableSql(String tbName, List fields) { if (fields.size() == 0) { return null; } @@ -84,7 +84,7 @@ public class TableManager { //生成字段片段 StringBuilder sbField = new StringBuilder("time timestamp,"); - for (TdField field : fields) { + for (TdFieldDO field : fields) { sbField.append(FieldParser.getFieldDefine(field)); sbField.append(","); } @@ -116,9 +116,9 @@ public class TableManager { /** * 获取添加字段sql */ - public static String getAddSTableColumnSql(String tbName, List fields) { + public static String getAddSTableColumnSql(String tbName, List fields) { StringBuilder sbAdd = new StringBuilder(); - for (TdField field : fields) { + for (TdFieldDO field : fields) { sbAdd.append(String.format(ALTER_STABLE_ADD_COL_TPL, tbName, FieldParser.getFieldDefine(field) @@ -130,9 +130,9 @@ public class TableManager { /** * 获取修改字段sql */ - public static String getModifySTableColumnSql(String tbName, List fields) { + public static String getModifySTableColumnSql(String tbName, List fields) { StringBuilder sbModify = new StringBuilder(); - for (TdField field : fields) { + for (TdFieldDO field : fields) { sbModify.append(String.format(ALTER_STABLE_MODIFY_COL_TPL, tbName, FieldParser.getFieldDefine(field) @@ -144,15 +144,15 @@ public class TableManager { /** * 获取删除字段sql */ - public static String getDropSTableColumnSql(String tbName, List fields) { + public static String getDropSTableColumnSql(String tbName, List fields) { StringBuilder sbDrop = new StringBuilder(); - for (TdField field : fields) { + for (TdFieldDO field : fields) { sbDrop.append(String.format(ALTER_STABLE_DROP_COL_TPL, tbName, - field.getName() + field.getFieldName() )); } return sbDrop.toString(); } -} +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdField.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdFieldDO.java similarity index 68% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdField.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdFieldDO.java index f040a017a..d9cf28f1b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdField.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdFieldDO.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; @@ -10,20 +11,21 @@ import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor -public class TdField { +@Builder +public class TdFieldDO { /** * 字段名称 */ - private String name; + private String fieldName; /** * 字段类型 */ - private String type; + private String dataType; /** * 字段长度 */ - private int length; + private Integer dataLength = 0; } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdResponse.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdResponse.java index 9353565be..aca5cece5 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdResponse.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdResponse.java @@ -17,13 +17,25 @@ public class TdResponse { public static final int CODE_SUCCESS = 0; public static final int CODE_TB_NOT_EXIST = 866; + /** + * 状态 + */ private String status; + /** + * 错误码 + */ private int code; + /** + * 错误信息 + */ private String desc; - //[["time","TIMESTAMP",8,""],["powerstate","TINYINT",1,""],["brightness","INT",4,""],["deviceid","NCHAR",32,"TAG"]] - private List data; + /** + * 列信息 + * [["time","TIMESTAMP",8,""],["powerstate","TINYINT",1,""],["brightness","INT",4,""],["deviceid","NCHAR",32,"TAG"]] + */ + private List data; -} +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java index ef6b8b5b4..6653ece40 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java @@ -14,23 +14,23 @@ import org.springframework.stereotype.Service; @Service public class TdRestApi { - @Value("${spring.datasource.dynamic.datasource.master.url}") + @Value("${spring.datasource.dynamic.datasource.tdengine.url}") private String url; - @Value("${spring.datasource.dynamic.datasource.master.username}") + @Value("${spring.datasource.dynamic.datasource.tdengine.username}") private String username; - @Value("${spring.datasource.dynamic.datasource.master.password}") + @Value("${spring.datasource.dynamic.datasource.tdengine.password}") private String password; + /** + * 获取 REST API URL + */ private String getRestApiUrl() { - //jdbc:TAOS-RS://127.0.0.1:6041/iotkit?xxxx - String restUrl = url.replace("jdbc:TAOS-RS://" , "") - .replaceAll("\\?.*" , ""); - // /rest/sql/iotkit + String restUrl = url.replace("jdbc:TAOS-RS://", "") + .replaceAll("\\?.*", ""); int idx = restUrl.lastIndexOf("/"); - //127.0.0.1:6041/rest/sql/iotkit - return String.format("%s/rest/sql/%s" , restUrl.substring(0, idx), restUrl.substring(idx + 1)); + return String.format("%s/rest/sql/%s", restUrl.substring(0, idx), restUrl.substring(idx + 1)); } @@ -48,11 +48,10 @@ public class TdRestApi { * 执行sql */ public TdResponse execSql(String sql) { - log.info("exec td sql:{}" , sql); + log.info("exec td sql:{}", sql); HttpRequest request = newApiRequest(sql); HttpResponse response = request.execute(); return JSONUtil.toBean(response.body(), TdResponse.class); } - -} +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java index 6a925f4e5..85e324a77 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.iot.dal.tdengine; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; import cn.iocoder.yudao.module.iot.domain.FieldsVo; import cn.iocoder.yudao.module.iot.domain.SelectDto; import cn.iocoder.yudao.module.iot.domain.TableDto; @@ -17,24 +18,80 @@ import java.util.Map; @DS("tdengine") public interface TdEngineMapper { + /** + * 创建数据库 + * + * @param dataBaseName 数据库名称 + */ + @InterceptorIgnore(tenantLine = "true") void createDatabase(@Param("dataBaseName") String dataBaseName); - void createSuperTable(@Param("schemaFields") List schemaFields, - @Param("tagsFields") List tagsFields, + /** + * 创建超级表 + * + * @param schemaFields schema字段 + * @param tagsFields tags字段 + * @param dataBaseName 数据库名称 + * @param superTableName 超级表名称 + */ + @InterceptorIgnore(tenantLine = "true") + void createSuperTable(@Param("schemaFields") List schemaFields, + @Param("tagsFields") List tagsFields, @Param("dataBaseName") String dataBaseName, @Param("superTableName") String superTableName); + /** + * 查看超级表 - 显示当前数据库下的所有超级表信息 + * SQL:SHOW STABLES [LIKE tb_name_wildcard]; + * + * @param dataBaseName 数据库名称 + * @param superTableName 超级表名称 + */ + @InterceptorIgnore(tenantLine = "true") + List> showSuperTables(@Param("dataBaseName") String dataBaseName, + @Param("superTableName") String superTableName); + + /** + * 查看超级表 - 获取超级表的结构信息 + * SQL:DESCRIBE [db_name.]stb_name; + * + * * @param dataBaseName 数据库名称 + * * @param superTableName 超级表名称 + */ + @InterceptorIgnore(tenantLine = "true") + List> describeSuperTable(@Param("dataBaseName") String dataBaseName, + @Param("superTableName") String superTableName); + + /** + * 为超级表添加列 + * + * @param dataBaseName 数据库名称 + * @param superTableName 超级表名称 + * @param field 字段信息 + */ + @InterceptorIgnore(tenantLine = "true") + void addColumnForSuperTable(@Param("dataBaseName") String dataBaseName, + @Param("superTableName") String superTableName, + @Param("field") TdFieldDO field); + + /** + * 为超级表删除列 + * + * @param dataBaseName 数据库名称 + * @param superTableName 超级表名称 + * @param field 字段信息 + */ + @InterceptorIgnore(tenantLine = "true") + void dropColumnForSuperTable(@Param("dataBaseName") String dataBaseName, + @Param("superTableName") String superTableName, + @Param("field") TdFieldDO field); + void createTable(TableDto tableDto); void insertData(TableDto tableDto); List> selectByTimestamp(SelectDto selectDto); - void addColumnForSuperTable(@Param("superTableName") String superTableName, - @Param("fieldsVo") FieldsVo fieldsVo); - - void dropColumnForSuperTable(@Param("superTableName") String superTableName, - @Param("fieldsVo") FieldsVo fieldsVo); void addTagForSuperTable(@Param("superTableName") String superTableName, @Param("fieldsVo") FieldsVo fieldsVo); @@ -44,14 +101,6 @@ public interface TdEngineMapper { Map getCountByTimestamp(SelectDto selectDto); - /** - * 检查表是否存在 - * - * @param dataBaseName 数据库名称 - * @param tableName 表名称 - */ - Integer checkTableExists(@Param("dataBaseName") String dataBaseName, @Param("tableName") String tableName); - Map getLastData(SelectDto selectDto); List> getHistoryData(SelectVisualDto selectVisualDto); @@ -62,13 +111,5 @@ public interface TdEngineMapper { List> getLastDataByTags(TagsSelectDao tagsSelectDao); - /** - * 创建超级表 - * - * @param sql sql - * @return 返回值 - */ - @InterceptorIgnore(tenantLine = "true") - Integer createSuperTableDevice(String sql); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java index f8dd6feb5..d42fd72fc 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java @@ -1,19 +1,22 @@ package cn.iocoder.yudao.module.iot.service.tdengine; -import cn.hutool.json.JSONUtil; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty; import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelRespVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.*; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdRestApi; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineMapper; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; @@ -22,147 +25,206 @@ import java.util.stream.Collectors; public class IotDbStructureDataServiceImpl implements IotDbStructureDataService { @Resource - private TdEngineMapper tdEngineMapper; + private TdEngineService tdEngineService; @Resource private TdRestApi tdRestApi; + @Value("${spring.datasource.dynamic.datasource.tdengine.url}") + private String url; + @Override public void createSuperTable(ThingModelRespVO thingModel, Integer deviceType) { - // 获取物模型中的属性定义 - List fields = FieldParser.parse(thingModel); - String tbName = getProductPropertySTableName(deviceType, thingModel.getProductKey()); + // 1. 解析物模型,获得字段列表 + List schemaFields = new ArrayList<>(); + schemaFields.add(TdFieldDO.builder(). + fieldName("time"). + dataType("TIMESTAMP"). + build()); + schemaFields.addAll(FieldParser.parse(thingModel)); - // 生成创建超级表的 SQL - String sql = TableManager.getCreateSTableSql(tbName, fields, new TdField("device_id", "NCHAR", 64)); - if (sql == null) { - log.warn("生成的 SQL 为空,无法创建超级表"); - return; - } - log.info("执行 SQL: {}", sql); + // 3. 设置超级表的标签 + List tagsFields = new ArrayList<>(); + tagsFields.add(TdFieldDO.builder(). + fieldName("product_key"). + dataType("NCHAR"). + dataLength(64). + build()); + tagsFields.add(TdFieldDO.builder(). + fieldName("device_key"). + dataType("NCHAR"). + dataLength(64). + build()); + tagsFields.add(TdFieldDO.builder(). + fieldName("device_name"). + dataType("NCHAR"). + dataLength(64). + build()); + // 年 + tagsFields.add(TdFieldDO.builder(). + fieldName("year"). + dataType("INT"). + build()); + // 月 + tagsFields.add(TdFieldDO.builder(). + fieldName("month"). + dataType("INT"). + build()); + // 日 + tagsFields.add(TdFieldDO.builder(). + fieldName("day"). + dataType("INT"). + build()); + // 时 + tagsFields.add(TdFieldDO.builder(). + fieldName("hour"). + dataType("INT"). + build()); - // 执行 SQL 创建超级表 - tdEngineMapper.createSuperTableDevice(sql); + + // 4. 获取超级表的名称 + String superTableName = getProductPropertySTableName(deviceType, thingModel.getProductKey()); + + // 5. 创建超级表 + String dataBaseName = url.substring(url.lastIndexOf("/") + 1); + tdEngineService.createSuperTable(schemaFields, tagsFields, dataBaseName, superTableName); } @Override public void updateSuperTable(ThingModelRespVO thingModel, Integer deviceType) { try { - // 获取旧字段信息 String tbName = getProductPropertySTableName(deviceType, thingModel.getProductKey()); - String sql = TableManager.getDescTableSql(tbName); - TdResponse response = tdRestApi.execSql(sql); - if (response.getCode() != TdResponse.CODE_SUCCESS) { - throw new RuntimeException("获取表描述错误: " + JSONUtil.toJsonStr(response)); - } + List oldFields = getTableFields(tbName); + List newFields = FieldParser.parse(thingModel); - List oldFields = FieldParser.parse(response.getData()); - List newFields = FieldParser.parse(thingModel); - - // 找出新增的字段 - List addFields = newFields.stream() - .filter(f -> oldFields.stream().noneMatch(old -> old.getName().equals(f.getName()))) - .collect(Collectors.toList()); - if (!addFields.isEmpty()) { - sql = TableManager.getAddSTableColumnSql(tbName, addFields); - response = tdRestApi.execSql(sql); - if (response.getCode() != TdResponse.CODE_SUCCESS) { - throw new RuntimeException("添加表字段错误: " + JSONUtil.toJsonStr(response)); - } - } - - // 找出修改的字段 - List modifyFields = newFields.stream() - .filter(f -> oldFields.stream().anyMatch(old -> - old.getName().equals(f.getName()) && - (!old.getType().equals(f.getType()) || old.getLength() != f.getLength()))) - .collect(Collectors.toList()); - if (!modifyFields.isEmpty()) { - sql = TableManager.getModifySTableColumnSql(tbName, modifyFields); - response = tdRestApi.execSql(sql); - if (response.getCode() != TdResponse.CODE_SUCCESS) { - throw new RuntimeException("修改表字段错误: " + JSONUtil.toJsonStr(response)); - } - } - - // 找出删除的字段 - List dropFields = oldFields.stream() - .filter(f -> !"time".equals(f.getName()) && !"device_id".equals(f.getName()) && - newFields.stream().noneMatch(n -> n.getName().equals(f.getName()))) - .collect(Collectors.toList()); - if (!dropFields.isEmpty()) { - sql = TableManager.getDropSTableColumnSql(tbName, dropFields); - response = tdRestApi.execSql(sql); - if (response.getCode() != TdResponse.CODE_SUCCESS) { - throw new RuntimeException("删除表字段错误: " + JSONUtil.toJsonStr(response)); - } - } + updateTableFields(tbName, oldFields, newFields); } catch (Throwable e) { log.error("更新物模型超级表失败", e); } } + // 获取表字段 + private List getTableFields(String tableName) { + List fields = new ArrayList<>(); + // 获取超级表的描述信息 + List> maps = tdEngineService.describeSuperTable(url.substring(url.lastIndexOf("/") + 1), tableName); + if (maps != null) { + // 过滤掉 note 字段为 TAG 的记录 + maps = maps.stream().filter(map -> !"TAG".equals(map.get("note"))).toList(); + // 过滤掉 time 字段 + maps = maps.stream().filter(map -> !"time".equals(map.get("field"))).toList(); + // 解析字段信息 + fields = FieldParser.parse(maps.stream() + .map(map -> List.of(map.get("field"), map.get("type"), map.get("length"))) + .collect(Collectors.toList())); + } + return fields; + } + + // 更新表字段 + private void updateTableFields(String tableName, List oldFields, List newFields) { + // 获取新增字段 + List addFields = getAddFields(oldFields, newFields); + // 获取修改字段 + List modifyFields = getModifyFields(oldFields, newFields); + // 获取删除字段 + List dropFields = getDropFields(oldFields, newFields); + + String dataBaseName = url.substring(url.lastIndexOf("/") + 1); + // 添加新增字段 + if (CollUtil.isNotEmpty(addFields)) { + tdEngineService.addColumnForSuperTable(dataBaseName,tableName, addFields); + } + // 删除旧字段 + if (CollUtil.isNotEmpty(dropFields)) { + tdEngineService.dropColumnForSuperTable(dataBaseName,tableName, dropFields); + } + // 修改字段(先删除再添加) + if (CollUtil.isNotEmpty(modifyFields)) { + tdEngineService.dropColumnForSuperTable(dataBaseName,tableName, modifyFields); + tdEngineService.addColumnForSuperTable(dataBaseName,tableName, modifyFields); + } + } + + // 获取新增字段 + private List getAddFields(List oldFields, List newFields) { + return newFields.stream() + .filter(f -> oldFields.stream().noneMatch(old -> old.getFieldName().equals(f.getFieldName()))) + .collect(Collectors.toList()); + } + + // 获取修改字段 + private List getModifyFields(List oldFields, List newFields) { + return newFields.stream() + .filter(f -> oldFields.stream().anyMatch(old -> + old.getFieldName().equals(f.getFieldName()) && + (!old.getDataType().equals(f.getDataType()) || !Objects.equals(old.getDataLength(), f.getDataLength())))) + .collect(Collectors.toList()); + } + + // 获取删除字段 + private List getDropFields(List oldFields, List newFields) { + return oldFields.stream() + .filter(f -> !"time".equals(f.getFieldName()) && !"device_id".equals(f.getFieldName()) && + newFields.stream().noneMatch(n -> n.getFieldName().equals(f.getFieldName()))) + .collect(Collectors.toList()); + } + @Override public void createSuperTableDataModel(IotProductDO product, List functionList) { - // 1. 生成 ThingModelRespVO - ThingModelRespVO thingModel = new ThingModelRespVO(); - thingModel.setId(product.getId()); - thingModel.setProductKey(product.getProductKey()); + ThingModelRespVO thingModel = buildThingModel(product, functionList); - // 1.1 设置属性、服务和事件 - ThingModelRespVO.Model model = new ThingModelRespVO.Model(); - List properties = new ArrayList<>(); - - // 1.2 遍历功能列表并分类 - for (IotThinkModelFunctionDO function : functionList) { - if (Objects.requireNonNull(IotProductFunctionTypeEnum.valueOf(function.getType())) == IotProductFunctionTypeEnum.PROPERTY) { - ThingModelProperty property = new ThingModelProperty(); - property.setIdentifier(function.getIdentifier()); - property.setName(function.getName()); - property.setDescription(function.getDescription()); - property.setDataType(function.getProperty().getDataType()); - properties.add(property); - } - } - - // 1.3 判断属性列表是否为空 - if (properties.isEmpty()) { + if (thingModel.getModel().getProperties().isEmpty()) { log.warn("物模型属性列表为空,不创建超级表"); return; } - model.setProperties(properties); - thingModel.setModel(model); + String superTableName = getProductPropertySTableName(product.getDeviceType(), product.getProductKey()); + String dataBaseName = url.substring(url.lastIndexOf("/") + 1); + Integer tableExists = tdEngineService.checkSuperTableExists(dataBaseName, superTableName); - // 2. 判断是否已经创建,如果已经创建则进行更新 - String tbName = getProductPropertySTableName(product.getDeviceType(), product.getProductKey()); - Integer iot = tdEngineMapper.checkTableExists("ruoyi_vue_pro", tbName); - if (iot != null && iot > 0) { - // 3. 更新 + if (tableExists != null && tableExists > 0) { updateSuperTable(thingModel, product.getDeviceType()); } else { - // 4. 创建 createSuperTable(thingModel, product.getDeviceType()); } } - /** - * 根据产品key获取产品属性超级表名 - */ - static String getProductPropertySTableName(Integer deviceType, String productKey) { - if (deviceType == 1) { - return String.format("gateway_sub_" + productKey).toLowerCase(); - } else if (deviceType == 2) { - return String.format("gateway_" + productKey).toLowerCase(); - } else { - return String.format("device_" + productKey).toLowerCase(); - } + private ThingModelRespVO buildThingModel(IotProductDO product, List functionList) { + ThingModelRespVO thingModel = new ThingModelRespVO(); + thingModel.setId(product.getId()); + thingModel.setProductKey(product.getProductKey()); + + ThingModelRespVO.Model model = new ThingModelRespVO.Model(); + List properties = functionList.stream() + .filter(function -> IotProductFunctionTypeEnum.PROPERTY.equals(IotProductFunctionTypeEnum.valueOf(function.getType()))) + .map(this::buildThingModelProperty) + .collect(Collectors.toList()); + + model.setProperties(properties); + thingModel.setModel(model); + + return thingModel; } - /** - * 根据deviceId获取设备属性表名 - */ - static String getDevicePropertyTableName(String deviceType, String productKey, String deviceKey) { - return String.format(deviceType + "_" + productKey + "_" + deviceKey).toLowerCase(); + private ThingModelProperty buildThingModelProperty(IotThinkModelFunctionDO function) { + ThingModelProperty property = new ThingModelProperty(); + property.setIdentifier(function.getIdentifier()); + property.setName(function.getName()); + property.setDescription(function.getDescription()); + property.setDataType(function.getProperty().getDataType()); + return property; } -} + + static String getProductPropertySTableName(Integer deviceType, String productKey) { + return switch (deviceType) { + case 1 -> String.format("gateway_sub_%s", productKey).toLowerCase(); + case 2 -> String.format("gateway_%s", productKey).toLowerCase(); + default -> String.format("device_%s", productKey).toLowerCase(); + }; + } + + static String getDevicePropertyTableName(String deviceType, String productKey, String deviceKey) { + return String.format("%s_%s_%s", deviceType, productKey, deviceKey).toLowerCase(); + } +} \ 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/tdengine/TdEngineService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineService.java index b3ae6f818..9319adbd7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineService.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.iot.service.tdengine; -import cn.iocoder.yudao.module.iot.domain.FieldsVo; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; import cn.iocoder.yudao.module.iot.domain.SelectDto; import cn.iocoder.yudao.module.iot.domain.TableDto; import cn.iocoder.yudao.module.iot.domain.TagsSelectDao; @@ -27,12 +27,44 @@ public interface TdEngineService { * * @param schemaFields schema字段 * @param tagsFields tags字段 - * @param dataBaseName 数据库名称 * @param superTableName 超级表名称 - * @throws Exception 异常 */ - void createSuperTable(List schemaFields, List tagsFields, String dataBaseName, - String superTableName) throws Exception; + void createSuperTable(List schemaFields, List tagsFields, String dataBaseName, String superTableName); + + /** + * 检查超级表是否存在 + */ + Integer checkSuperTableExists(String dataBaseName, String superTableName); + + + /** + * 获取超级表的结构信息 + */ + List> describeSuperTable(String dataBaseName, String superTableName); + + /** + * 为超级表添加列 + * + * @param dataBaseName 数据库名称 + * @param superTableName 超级表名称 + * @param fieldsVo 字段信息 + */ + void addColumnForSuperTable(String dataBaseName,String superTableName, List fieldsVo); + + /** + * 为超级表删除列 + * + * @param dataBaseName 数据库名称 + * @param superTableName 超级表名称 + * @param fieldsVo 字段信息 + */ + void dropColumnForSuperTable(String dataBaseName,String superTableName, List fieldsVo); + + /** + * 为超级表添加tag + */ + Long getCountByTimesTamp(SelectDto selectDto) throws Exception; + /** * 创建表 @@ -59,37 +91,6 @@ public interface TdEngineService { */ List> selectByTimesTamp(SelectDto selectDto) throws Exception; - /** - * 为超级表添加列 - * - * @param superTableName 超级表名称 - * @param fieldsVo 字段信息 - * @throws Exception 异常 - */ - void addColumnForSuperTable(String superTableName, FieldsVo fieldsVo) throws Exception; - - /** - * 为超级表删除列 - * - * @param superTableName 超级表名称 - * @param fieldsVo 字段信息 - * @throws Exception 异常 - */ - void dropColumnForSuperTable(String superTableName, FieldsVo fieldsVo) throws Exception; - - /** - * 为超级表添加tag - */ - Long getCountByTimesTamp(SelectDto selectDto) throws Exception; - - /** - * 检查表是否存在 - * - * @return 1存在 0不存在 - * @throws Exception 异常 - */ - Integer checkTableExists(SelectDto selectDto) throws Exception; - /** * 初始化超级表 * @@ -138,4 +139,6 @@ public interface TdEngineService { * @return 数据 */ List> getAggregateData(SelectVisualDto selectVisualDto); + + } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineServiceImpl.java index 70933617f..d61b78922 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineServiceImpl.java @@ -1,10 +1,12 @@ package cn.iocoder.yudao.module.iot.service.tdengine; -import cn.iocoder.yudao.module.iot.domain.FieldsVo; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineMapper; import cn.iocoder.yudao.module.iot.domain.SelectDto; import cn.iocoder.yudao.module.iot.domain.TableDto; import cn.iocoder.yudao.module.iot.domain.TagsSelectDao; import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; +import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -15,25 +17,27 @@ import java.util.Map; @Slf4j public class TdEngineServiceImpl implements TdEngineService { + @Resource + private TdEngineMapper tdEngineMapper; @Override public void createDateBase(String dataBaseName) { - + tdEngineMapper.createDatabase(dataBaseName); } @Override - public void createSuperTable(List schemaFields, List tagsFields, String dataBaseName, String superTableName) { - + public void createSuperTable(List schemaFields, List tagsFields, String dataBaseName, String superTableName) { + tdEngineMapper.createSuperTable(schemaFields, tagsFields, dataBaseName, superTableName); } @Override public void createTable(TableDto tableDto) { - + tdEngineMapper.createTable(tableDto); } @Override public void insertData(TableDto tableDto) { - + tdEngineMapper.insertData(tableDto); } @Override @@ -42,13 +46,17 @@ public class TdEngineServiceImpl implements TdEngineService { } @Override - public void addColumnForSuperTable(String superTableName, FieldsVo fieldsVo) { - + public void addColumnForSuperTable(String dataBaseName,String superTableName, List fields) { + for (TdFieldDO field : fields) { + tdEngineMapper.addColumnForSuperTable(dataBaseName,superTableName, field); + } } @Override - public void dropColumnForSuperTable(String superTableName, FieldsVo fieldsVo) { - + public void dropColumnForSuperTable(String dataBaseName,String superTableName, List fields) { + for (TdFieldDO field : fields) { + tdEngineMapper.dropColumnForSuperTable(dataBaseName,superTableName, field); + } } @Override @@ -56,11 +64,6 @@ public class TdEngineServiceImpl implements TdEngineService { return 0L; } - @Override - public Integer checkTableExists(SelectDto selectDto) { - return 0; - } - @Override public void initSTableFrame(String msg) { @@ -90,4 +93,15 @@ public class TdEngineServiceImpl implements TdEngineService { public List> getAggregateData(SelectVisualDto selectVisualDto) { return List.of(); } + + @Override + public Integer checkSuperTableExists(String dataBaseName, String superTableName) { + List> results = tdEngineMapper.showSuperTables(dataBaseName, superTableName); + return results == null || results.isEmpty() ? 0 : results.size(); + } + + @Override + public List> describeSuperTable(String dataBaseName, String superTableName) { + return tdEngineMapper.describeSuperTable(dataBaseName, superTableName); + } } \ 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/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java index 1e356c6b7..3f698999c 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java @@ -174,8 +174,10 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe public void createSuperTableDataModel(Long productId) { // 1. 查询产品 IotProductDO product = productService.getProduct(productId); + // 2. 查询产品的物模型功能列表 List functionList = thinkModelFunctionMapper.selectListByProductId(productId); + // 3. 生成 TDengine 的数据模型 dbStructureDataService.createSuperTableDataModel(product, functionList); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml index f722e0130..f1d748198 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml @@ -8,7 +8,7 @@ - create table if not exists #{dataBaseName}.#{superTableName} + CREATE STABLE IF NOT EXISTS ${dataBaseName}.${superTableName} @@ -16,46 +16,48 @@ - - timestamp + + TIMESTAMP - - tinyint + + TINYINT - - smallint + + SMALLINT - - int + + INT - - bigint + + BIGINT - - float + + FLOAT - - double + + DOUBLE - - binary + + BINARY - - nchar + + NCHAR - - bool + + BOOL - - json + + JSON - - (#{item.size}) + + ( + ${item.dataLength} + ) - tags + TAGS @@ -64,43 +66,45 @@ - - timestamp + + TIMESTAMP - - tinyint + + TINYINT - - smallint + + SMALLINT - - int + + INT - - bigint + + BIGINT - - float + + FLOAT - - double + + DOUBLE - - binary + + BINARY - - nchar + + NCHAR - - bool + + BOOL - - json + + JSON - - (#{item.size}) + + ( + ${item.dataLength} + ) @@ -135,7 +139,6 @@ - select * from #{dataBaseName}.#{tableName} @@ -146,66 +149,58 @@ - ALTER - STABLE - #{superTableName} - ADD - COLUMN - - #{fieldsVo.fieldName} + ALTER STABLE ${dataBaseName}.${superTableName} ADD COLUMN + + #{field.fieldName} - + - - timestamp + + TIMESTAMP - - tinyint + + TINYINT - - smallint + + SMALLINT - - int + + INT - - bigint + + BIGINT - - float + + FLOAT - - double + + DOUBLE - - binary + + BINARY - - nchar + + NCHAR - - bool + + BOOL - - json + + JSON - + ( - #{fieldsVo.size} + #{field.dataLength} ) - ALTER - STABLE - #{superTableName} - DROP - COLUMN - - #{fieldsVo.fieldName} + ALTER STABLE ${dataBaseName}.${superTableName} DROP COLUMN + + #{field.fieldName} @@ -215,49 +210,49 @@ #{superTableName} ADD TAG - - #{fieldsVo.fieldName} + + #{fieldDO.fieldName} - + - + timestamp - + tinyint - + smallint - + int - + bigint - + float - + double - + binary - + nchar - + bool - + json - + ( - #{fieldsVo.size} + #{fieldDO.dataLength} ) @@ -279,11 +274,8 @@ FROM #{dataBaseName}.#{tableName} WHERE ${fieldName} BETWEEN #{startTime} AND #{endTime} - - SELECT COUNT(0) - FROM information_schema.ins_tables - WHERE db_name = #{dataBaseName} - AND table_name = #{tableName} + + SHOW ${dataBaseName}.STABLES LIKE '${superTableName}' @@ -304,11 +296,13 @@ FROM #{dataBaseName}.#{tableName} WHERE ts BETWEEN #{startTime} AND #{endTime} LIMIT #{num} + SELECT #{fieldName}, ts FROM #{dataBaseName}.#{tableName} LIMIT #{num} + SELECT #{aggregate}(${fieldName}) @@ -316,9 +310,8 @@ LIMIT #{num} - - - ${sql} - + + DESCRIBE ${dataBaseName}.${superTableName} + From 88088c798799bfebd00439199914f2fb08a7a8a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Sat, 26 Oct 2024 23:26:26 +0800 Subject: [PATCH 005/228] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91=20=E4=BA=A7=E5=93=81=E5=8F=91=E5=B8=83?= =?UTF-8?q?=E5=90=8E=E7=89=A9=E6=A8=A1=E5=9E=8B=E4=B8=8D=E5=8F=AF=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/iot/enums/ErrorCodeConstants.java | 1 + .../IotThinkModelFunctionServiceImpl.java | 25 ++++++++++++++++--- 2 files changed, 22 insertions(+), 4 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 31702e1e6..be9d28ecb 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 @@ -13,6 +13,7 @@ public interface ErrorCodeConstants { ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_050_001_000, "产品不存在"); ErrorCode PRODUCT_IDENTIFICATION_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在"); ErrorCode PRODUCT_STATUS_NOT_DELETE = new ErrorCode(1_050_001_002, "产品状是发布状态,不允许删除"); + ErrorCode PRODUCT_STATUS_NOT_ALLOW_FUNCTION = new ErrorCode(1_050_001_003, "产品状是发布状态,不允许操作物模型"); // ========== IoT 产品物模型 1-050-002-000 ============ ErrorCode THINK_MODEL_FUNCTION_NOT_EXISTS = new ErrorCode(1_050_002_000, "产品物模型不存在"); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java index 3f698999c..dd7a51786 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java @@ -20,6 +20,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkMod import cn.iocoder.yudao.module.iot.dal.mysql.thinkmodelfunction.IotThinkModelFunctionMapper; import cn.iocoder.yudao.module.iot.enums.product.IotAccessModeEnum; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; +import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum; import cn.iocoder.yudao.module.iot.service.product.IotProductService; import cn.iocoder.yudao.module.iot.service.tdengine.IotDbStructureDataService; import jakarta.annotation.Resource; @@ -65,17 +66,27 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe // 3. 系统保留字段,不能用于标识符定义 validateNotDefaultEventAndService(createReqVO.getIdentifier()); - // 3. 插入数据库 + // 4. 校验产品状态,发布状态下,不允许新增功能 + validateProductStatus(createReqVO.getProductId()); + + // 5. 插入数据库 IotThinkModelFunctionDO function = IotThinkModelFunctionConvert.INSTANCE.convert(createReqVO); thinkModelFunctionMapper.insert(function); - // 4. 如果创建的是属性,需要更新默认的事件和服务 + // 6. 如果创建的是属性,需要更新默认的事件和服务 if (Objects.equals(createReqVO.getType(), IotProductFunctionTypeEnum.PROPERTY.getType())) { createDefaultEventsAndServices(createReqVO.getProductId(), createReqVO.getProductKey()); } return function.getId(); } + private void validateProductStatus(Long createReqVO) { + IotProductDO product = productService.getProduct(createReqVO); + if (Objects.equals(product.getStatus(), IotProductStatusEnum.PUBLISHED.getType())) { + throw exception(PRODUCT_STATUS_NOT_ALLOW_FUNCTION); + } + } + private void validateNotDefaultEventAndService(String identifier) { // set, get, post, property, event, time, value 是系统保留字段,不能用于标识符定义 if (CollUtil.containsAny(Arrays.asList("set", "get", "post", "property", "event", "time", "value"), Collections.singletonList(identifier))) { @@ -109,11 +120,14 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe // 2. 校验功能标识符是否唯一 validateIdentifierUniqueForUpdate(updateReqVO.getId(), updateReqVO.getProductId(), updateReqVO.getIdentifier()); - // 3. 更新数据库 + // 3. 校验产品状态,发布状态下,不允许操作功能 + validateProductStatus(updateReqVO.getProductId()); + + // 4. 更新数据库 IotThinkModelFunctionDO thinkModelFunction = IotThinkModelFunctionConvert.INSTANCE.convert(updateReqVO); thinkModelFunctionMapper.updateById(thinkModelFunction); - // 4. 如果更新的是属性,需要更新默认的事件和服务 + // 5. 如果更新的是属性,需要更新默认的事件和服务 if (Objects.equals(updateReqVO.getType(), IotProductFunctionTypeEnum.PROPERTY.getType())) { createDefaultEventsAndServices(updateReqVO.getProductId(), updateReqVO.getProductKey()); } @@ -135,6 +149,9 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe throw exception(THINK_MODEL_FUNCTION_NOT_EXISTS); } + // 3. 校验产品状态,发布状态下,不允许操作功能 + validateProductStatus(functionDO.getProductId()); + // 2. 删除功能 thinkModelFunctionMapper.deleteById(id); From 8c84ac9d8a88dd73d03746274f4f6e2de7004668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Sun, 27 Oct 2024 21:26:35 +0800 Subject: [PATCH 006/228] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E3=80=91=20mqtt=20=E6=95=B0=E6=8D=AE=E6=8E=A5?= =?UTF-8?q?=E6=94=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-iot/yudao-module-iot-biz/pom.xml | 5 ++ .../tdengine/ThingModelMessage.java | 70 +++++++++++++++++++ .../iot/emq/service/EmqxServiceImpl.java | 14 +++- .../service/device/IotDeviceDataService.java | 26 +++++++ .../device/IotDeviceDataServiceImpl.java | 39 +++++++++++ .../iot/service/device/IotDeviceService.java | 9 +++ ...iceImpl.java => IotDeviceServiceImpl.java} | 9 ++- .../IotDbStructureDataServiceImpl.java | 16 ++--- ...neService.java => IotTdEngineService.java} | 10 +-- ...eImpl.java => IotTdEngineServiceImpl.java} | 2 +- .../tdengine/IotThingModelMessageService.java | 16 +++++ .../IotThingModelMessageServiceImpl.java | 13 ++++ .../mapper/tdengine/TdEngineMapper.xml | 18 +++-- 13 files changed, 224 insertions(+), 23 deletions(-) create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/ThingModelMessage.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/{DeviceServiceImpl.java => IotDeviceServiceImpl.java} (95%) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/{TdEngineService.java => IotTdEngineService.java} (91%) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/{TdEngineServiceImpl.java => IotTdEngineServiceImpl.java} (97%) create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java diff --git a/yudao-module-iot/yudao-module-iot-biz/pom.xml b/yudao-module-iot/yudao-module-iot-biz/pom.xml index cb2fd818f..013287d2b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/pom.xml +++ b/yudao-module-iot/yudao-module-iot-biz/pom.xml @@ -25,6 +25,11 @@ ${revision} + + cn.iocoder.boot + yudao-spring-boot-starter-biz-tenant + + cn.iocoder.boot diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/ThingModelMessage.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/ThingModelMessage.java new file mode 100644 index 000000000..d5009dc24 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/ThingModelMessage.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.HashMap; +import java.util.Map; + +/** + * 物模型消息 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class ThingModelMessage { + + /** + * 消息ID + */ + private String id; + + /** + * 扩展功能的参数 + */ + private Object sys; + + /** + * 请求方法 例如:thing.event.property.post + */ + private String method; + + /** + * 请求参数 + */ + private Object params; + + /** + * 属性上报时间戳 + */ + private Long time; + + /** + * 设备信息 + */ + private String productKey; + + /** + * 设备名称 + */ + private String deviceName; + + /** + * 设备 key + */ + private String deviceKey; + + /** + * 转换为 Map 类型 + */ + public Map dataToMap() { + Map mapData = new HashMap<>(); + if (params instanceof Map) { + ((Map, ?>) params).forEach((key, value) -> mapData.put(key.toString(), value)); + } + return mapData; + } +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java index 0c1a87f7f..c82d0d305 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java @@ -1,5 +1,8 @@ package cn.iocoder.yudao.module.iot.emq.service; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.module.iot.service.device.IotDeviceDataService; +import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttMessage; @@ -16,13 +19,20 @@ import org.springframework.stereotype.Service; @Service public class EmqxServiceImpl implements EmqxService { + @Resource + private IotDeviceDataService iotDeviceDataService; + // TODO 多线程处理消息 @Override public void subscribeCallback(String topic, MqttMessage mqttMessage) { log.info("收到消息,主题: {}, 内容: {}", topic, new String(mqttMessage.getPayload())); // 根据不同的主题,处理不同的业务逻辑 if (topic.contains("/property/post")) { - // 设备上报数据 + // 设备上报数据 topic /sys/f13f57c63e9/dianbiao1/thing/event/property/post + String productKey = topic.split("/")[2]; + String deviceName = topic.split("/")[3]; + String message = new String(mqttMessage.getPayload()); + iotDeviceDataService.saveDeviceData(productKey, deviceName, message); } } @@ -30,7 +40,7 @@ public class EmqxServiceImpl implements EmqxService { public void subscribe(MqttClient client) { try { // 订阅默认主题,可以根据需要修改 -// client.subscribe("$share/yudao/+/+/#", 1); + client.subscribe("/sys/+/+/#", 1); log.info("订阅默认主题成功"); } catch (Exception e) { log.error("订阅默认主题失败", e); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java new file mode 100644 index 000000000..4f3ef37d6 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java @@ -0,0 +1,26 @@ +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.IotDevicePageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceSaveReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceStatusUpdateReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; +import jakarta.validation.Valid; + +/** + * IoT 设备数据 Service 接口 + * + * @author 芋道源码 + */ +public interface IotDeviceDataService { + + + /** + * 保存设备数据 + * + * @param productKey 产品 key + * @param deviceName 设备名称 + * @param message 消息 + */ + void saveDeviceData(String productKey, String deviceName, String message); +} \ 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/IotDeviceDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java new file mode 100644 index 000000000..8f0c859ad --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.iot.service.device; + +import cn.hutool.json.JSONObject; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; +import cn.iocoder.yudao.module.iot.service.tdengine.IotThingModelMessageService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +public class IotDeviceDataServiceImpl implements IotDeviceDataService { + + @Resource + private IotDeviceService deviceService; + @Resource + private IotThingModelMessageService thingModelMessageService; + + @Override + public void saveDeviceData(String productKey, String deviceName, String message) { + // 1. 根据产品 key 和设备名称,获得设备信息 + IotDeviceDO device = deviceService.getDeviceByProductKeyAndDeviceName(productKey, deviceName); + // 2. 解析消息,保存数据 + JSONObject jsonObject = new JSONObject(message); + log.info("[saveDeviceData][productKey({}) deviceName({}) data({})]", productKey, deviceName, jsonObject); + ThingModelMessage thingModelMessage = ThingModelMessage.builder() + .id(jsonObject.getStr("id")) + .sys(jsonObject.get("sys")) + .method(jsonObject.getStr("method")) + .params(jsonObject.get("params")) + .time(jsonObject.getLong("time") == null ? System.currentTimeMillis() : jsonObject.getLong("time")) + .productKey(productKey) + .deviceName(deviceName) + .deviceKey(device.getDeviceKey()) + .build(); + thingModelMessageService.saveThingModelMessage(thingModelMessage); + } +} 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 032a7478e..c967a957e 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 @@ -64,4 +64,13 @@ public interface IotDeviceService { * @return 设备数量 */ Long getDeviceCountByProductId(Long productId); + + /** + * 根据产品 key 和设备名称,获得设备信息 + * + * @param productKey 产品 key + * @param deviceName 设备名称 + * @return 设备信息 + */ + IotDeviceDO getDeviceByProductKeyAndDeviceName(String productKey, String deviceName); } \ 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/DeviceServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java similarity index 95% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/DeviceServiceImpl.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java index 2ae08bb94..d24975b72 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/IotDeviceServiceImpl.java @@ -4,6 +4,7 @@ import cn.hutool.core.util.IdUtil; 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.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDevicePageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceSaveReqVO; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceStatusUpdateReqVO; @@ -32,7 +33,7 @@ import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*; @Service @Validated @Slf4j -public class DeviceServiceImpl implements IotDeviceService { +public class IotDeviceServiceImpl implements IotDeviceService { @Resource private IotDeviceMapper deviceMapper; @@ -224,4 +225,10 @@ public class DeviceServiceImpl implements IotDeviceService { return deviceMapper.selectCountByProductId(productId); } + @Override + @TenantIgnore + public IotDeviceDO getDeviceByProductKeyAndDeviceName(String productKey, String deviceName) { + return deviceMapper.selectByProductKeyAndDeviceName(productKey, deviceName); + } + } \ 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/tdengine/IotDbStructureDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java index d42fd72fc..0506546be 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java @@ -25,7 +25,7 @@ import java.util.stream.Collectors; public class IotDbStructureDataServiceImpl implements IotDbStructureDataService { @Resource - private TdEngineService tdEngineService; + private IotTdEngineService iotTdEngineService; @Resource private TdRestApi tdRestApi; @@ -87,7 +87,7 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService // 5. 创建超级表 String dataBaseName = url.substring(url.lastIndexOf("/") + 1); - tdEngineService.createSuperTable(schemaFields, tagsFields, dataBaseName, superTableName); + iotTdEngineService.createSuperTable(schemaFields, tagsFields, dataBaseName, superTableName); } @Override @@ -107,7 +107,7 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService private List getTableFields(String tableName) { List fields = new ArrayList<>(); // 获取超级表的描述信息 - List> maps = tdEngineService.describeSuperTable(url.substring(url.lastIndexOf("/") + 1), tableName); + List> maps = iotTdEngineService.describeSuperTable(url.substring(url.lastIndexOf("/") + 1), tableName); if (maps != null) { // 过滤掉 note 字段为 TAG 的记录 maps = maps.stream().filter(map -> !"TAG".equals(map.get("note"))).toList(); @@ -133,16 +133,16 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService String dataBaseName = url.substring(url.lastIndexOf("/") + 1); // 添加新增字段 if (CollUtil.isNotEmpty(addFields)) { - tdEngineService.addColumnForSuperTable(dataBaseName,tableName, addFields); + iotTdEngineService.addColumnForSuperTable(dataBaseName, tableName, addFields); } // 删除旧字段 if (CollUtil.isNotEmpty(dropFields)) { - tdEngineService.dropColumnForSuperTable(dataBaseName,tableName, dropFields); + iotTdEngineService.dropColumnForSuperTable(dataBaseName, tableName, dropFields); } // 修改字段(先删除再添加) if (CollUtil.isNotEmpty(modifyFields)) { - tdEngineService.dropColumnForSuperTable(dataBaseName,tableName, modifyFields); - tdEngineService.addColumnForSuperTable(dataBaseName,tableName, modifyFields); + iotTdEngineService.dropColumnForSuperTable(dataBaseName, tableName, modifyFields); + iotTdEngineService.addColumnForSuperTable(dataBaseName, tableName, modifyFields); } } @@ -181,7 +181,7 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService String superTableName = getProductPropertySTableName(product.getDeviceType(), product.getProductKey()); String dataBaseName = url.substring(url.lastIndexOf("/") + 1); - Integer tableExists = tdEngineService.checkSuperTableExists(dataBaseName, superTableName); + Integer tableExists = iotTdEngineService.checkSuperTableExists(dataBaseName, superTableName); if (tableExists != null && tableExists > 0) { updateSuperTable(thingModel, product.getDeviceType()); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineService.java similarity index 91% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineService.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineService.java index 9319adbd7..3175d2839 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineService.java @@ -12,7 +12,7 @@ import java.util.Map; /** * TdEngineService */ -public interface TdEngineService { +public interface IotTdEngineService { /** * 创建数据库 @@ -45,20 +45,20 @@ public interface TdEngineService { /** * 为超级表添加列 * - * @param dataBaseName 数据库名称 + * @param dataBaseName 数据库名称 * @param superTableName 超级表名称 * @param fieldsVo 字段信息 */ - void addColumnForSuperTable(String dataBaseName,String superTableName, List fieldsVo); + void addColumnForSuperTable(String dataBaseName, String superTableName, List fieldsVo); /** * 为超级表删除列 * - * @param dataBaseName 数据库名称 + * @param dataBaseName 数据库名称 * @param superTableName 超级表名称 * @param fieldsVo 字段信息 */ - void dropColumnForSuperTable(String dataBaseName,String superTableName, List fieldsVo); + void dropColumnForSuperTable(String dataBaseName, String superTableName, List fieldsVo); /** * 为超级表添加tag diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineServiceImpl.java similarity index 97% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineServiceImpl.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineServiceImpl.java index d61b78922..3c87f624d 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineServiceImpl.java @@ -15,7 +15,7 @@ import java.util.Map; @Service @Slf4j -public class TdEngineServiceImpl implements TdEngineService { +public class IotTdEngineServiceImpl implements IotTdEngineService { @Resource private TdEngineMapper tdEngineMapper; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java new file mode 100644 index 000000000..937338544 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; + +/** + * 物模型消息 Service + */ +public interface IotThingModelMessageService { + + /** + * 保存物模型消息 + * + * @param thingModelMessage 物模型消息 + */ + void saveThingModelMessage(ThingModelMessage thingModelMessage); +} \ 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/tdengine/IotThingModelMessageServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java new file mode 100644 index 000000000..d47756423 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; +import org.springframework.stereotype.Service; + +@Service +public class IotThingModelMessageServiceImpl implements IotThingModelMessageService { + + @Override + public void saveThingModelMessage(ThingModelMessage thingModelMessage) { + // TODO 芋艿,后续实现 + } +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml index f1d748198..d3f1088a1 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml @@ -2,9 +2,10 @@ + - create database if not exists #{dataBaseName} + CREATE DATABASE IF NOT EXISTS ${dataBaseName} @@ -271,7 +272,8 @@ SELECT count(0) AS count - FROM #{dataBaseName}.#{tableName} WHERE ${fieldName} BETWEEN #{startTime} AND #{endTime} + FROM #{dataBaseName}.#{tableName} + WHERE ${fieldName} BETWEEN #{startTime} AND #{endTime} @@ -287,26 +289,30 @@ select last(*) - from #{dataBaseName}.#{stableName} group by ${tagsName} + from #{dataBaseName}.#{stableName} + group by ${tagsName} SELECT #{fieldName}, ts - FROM #{dataBaseName}.#{tableName} WHERE ts BETWEEN #{startTime} AND #{endTime} + FROM #{dataBaseName}.#{tableName} + WHERE ts BETWEEN #{startTime} AND #{endTime} LIMIT #{num} SELECT #{fieldName}, ts - FROM #{dataBaseName}.#{tableName} LIMIT #{num} + FROM #{dataBaseName}.#{tableName} + LIMIT #{num} SELECT #{aggregate}(${fieldName}) - FROM #{dataBaseName}.#{tableName} WHERE ts BETWEEN #{startTime} AND #{endTime} interval (${interval}) + FROM #{dataBaseName}.#{tableName} + WHERE ts BETWEEN #{startTime} AND #{endTime} interval (${interval}) LIMIT #{num} From 3dafd31da6ba6dad4beba2954ca5ed689a209699 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Thu, 31 Oct 2024 21:47:54 +0800 Subject: [PATCH 007/228] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E3=80=91=20=E6=95=B0=E6=8D=AE=E6=8E=A5=E6=94=B6?= =?UTF-8?q?=EF=BC=8CJSON=20=E6=A0=87=E5=87=86=E6=A0=BC=E5=BC=8F=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=8E=A5=E6=94=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/dal/dataobject/tdengine/TableDO.java | 27 ++++ .../dal/dataobject/tdengine/TableData.java | 17 ++- .../dal/dataobject/tdengine/TdFieldDO.java | 16 +++ .../IotThinkModelFunctionMapper.java | 3 + .../iot/dal/tdengine/TdEngineMapper.java | 17 ++- .../iot/emq/service/EmqxServiceImpl.java | 2 + .../device/IotDeviceDataServiceImpl.java | 2 +- .../service/device/IotDeviceServiceImpl.java | 23 +++- .../IotDbStructureDataServiceImpl.java | 19 +-- .../service/tdengine/IotTdEngineService.java | 8 +- .../tdengine/IotTdEngineServiceImpl.java | 6 +- .../tdengine/IotThingModelMessageService.java | 4 +- .../IotThingModelMessageServiceImpl.java | 118 +++++++++++++++++- .../IotThinkModelFunctionService.java | 8 ++ .../IotThinkModelFunctionServiceImpl.java | 5 + .../mapper/tdengine/TdEngineMapper.xml | 27 ++-- 16 files changed, 247 insertions(+), 55 deletions(-) create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableDO.java diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableDO.java new file mode 100644 index 000000000..11751ff64 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableDO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; + +import cn.iocoder.yudao.module.iot.domain.BaseEntity; +import lombok.Data; + +import java.util.List; + +@Data +public class TableDO extends BaseEntity { + + /** + * 超级表普通列字段的值 + * 值需要与创建超级表时普通列字段的数据类型对应上 + */ + private List schemaFieldValues; + + /** + * 超级表标签字段的值 + * 值需要与创建超级表时标签字段的数据类型对应上 + */ + private List tagsFieldValues; + + /** + * 表名称 + */ + private String tableName; +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java index e9acbb7f0..dfb3ed212 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java @@ -15,18 +15,23 @@ public class TableData { */ private List schemaFieldList; - /** - * 超级表标签字段的值 - * 值需要与创建超级表时标签字段的数据类型对应上 - */ - private List tagsValueList; - /** * 超级表普通列字段的值 * 值需要与创建超级表时普通列字段的数据类型对应上 */ private List schemaValueList; + /** + * 超级表标签字段的名称 + */ + private List tagsFieldList; + + /** + * 超级表标签字段的值 + * 值需要与创建超级表时标签字段的数据类型对应上 + */ + private List tagsValueList; + /** * 表名称 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdFieldDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdFieldDO.java index d9cf28f1b..765652748 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdFieldDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdFieldDO.java @@ -19,6 +19,11 @@ public class TdFieldDO { */ private String fieldName; + /** + * 字段值 + */ + private Object fieldValue; + /** * 字段类型 */ @@ -28,4 +33,15 @@ public class TdFieldDO { * 字段长度 */ private Integer dataLength = 0; + + public TdFieldDO(String fieldName, String dataType, Integer dataLength) { + this.fieldName = fieldName; + this.dataType = dataType; + this.dataLength = dataLength; + } + + public TdFieldDO(String fieldName, Object fieldValue) { + this.fieldName = fieldName; + this.fieldValue = fieldValue; + } } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java index e8b96e022..2883abe4e 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java @@ -55,4 +55,7 @@ public interface IotThinkModelFunctionMapper extends BaseMapperX selectListByProductKey(String productKey){ + return selectList(IotThinkModelFunctionDO::getProductKey, productKey); + } } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java index 85e324a77..94db527c2 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.iot.dal.tdengine; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; import cn.iocoder.yudao.module.iot.domain.FieldsVo; import cn.iocoder.yudao.module.iot.domain.SelectDto; -import cn.iocoder.yudao.module.iot.domain.TableDto; import cn.iocoder.yudao.module.iot.domain.TagsSelectDao; import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; import com.baomidou.dynamic.datasource.annotation.DS; @@ -86,9 +86,20 @@ public interface TdEngineMapper { @Param("superTableName") String superTableName, @Param("field") TdFieldDO field); - void createTable(TableDto tableDto); + /** + * 创建表 - 创建超级表的子表 + * @param tableDO 表信息 + */ + @InterceptorIgnore(tenantLine = "true") + void createTable(TableDO tableDO); - void insertData(TableDto tableDto); + /** + * 插入数据 - 指定列插入数据 + * + * @param tableDto 数据 + */ + @InterceptorIgnore(tenantLine = "true") + void insertData(TableDO tableDto); List> selectByTimestamp(SelectDto selectDto); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java index c82d0d305..f338d6249 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java @@ -6,6 +6,7 @@ import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttMessage; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; // TODO @芋艿:在瞅瞅 @@ -24,6 +25,7 @@ public class EmqxServiceImpl implements EmqxService { // TODO 多线程处理消息 @Override + @Async public void subscribeCallback(String topic, MqttMessage mqttMessage) { log.info("收到消息,主题: {}, 内容: {}", topic, new String(mqttMessage.getPayload())); // 根据不同的主题,处理不同的业务逻辑 diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java index 8f0c859ad..6b7aac21f 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java @@ -34,6 +34,6 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { .deviceName(deviceName) .deviceKey(device.getDeviceKey()) .build(); - thingModelMessageService.saveThingModelMessage(thingModelMessage); + thingModelMessageService.saveThingModelMessage(device,thingModelMessage); } } 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 d24975b72..f3243900e 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 @@ -20,6 +20,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.time.LocalDateTime; +import java.util.Objects; import java.util.UUID; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -213,10 +214,30 @@ public class IotDeviceServiceImpl implements IotDeviceService { @Override public void updateDeviceStatus(IotDeviceStatusUpdateReqVO updateReqVO) { // 校验存在 - validateDeviceExists(updateReqVO.getId()); + IotDeviceDO iotDeviceDO = validateDeviceExists(updateReqVO.getId()); // 更新状态和更新时间 IotDeviceDO updateObj = BeanUtils.toBean(updateReqVO, IotDeviceDO.class); + + // 以前是未激活,现在是上线,设置设备激活时间 + if (Objects.equals(iotDeviceDO.getStatus(), IotDeviceStatusEnum.INACTIVE.getStatus()) + && Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { + updateObj.setActiveTime(LocalDateTime.now()); + } + + // 如果是上线,设置上线时间 + if (Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { + updateObj.setLastOnlineTime(LocalDateTime.now()); + } + + // 如果是离线,设置离线时间 + if (Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.OFFLINE.getStatus())) { + updateObj.setLastOfflineTime(LocalDateTime.now()); + } + + // 设置状态更新时间 + updateObj.setStatusLastUpdateTime(LocalDateTime.now()); + deviceMapper.updateById(updateObj); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java index 0506546be..b7de8882a 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java @@ -60,27 +60,10 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService dataType("NCHAR"). dataLength(64). build()); - // 年 tagsFields.add(TdFieldDO.builder(). - fieldName("year"). + fieldName("device_type"). dataType("INT"). build()); - // 月 - tagsFields.add(TdFieldDO.builder(). - fieldName("month"). - dataType("INT"). - build()); - // 日 - tagsFields.add(TdFieldDO.builder(). - fieldName("day"). - dataType("INT"). - build()); - // 时 - tagsFields.add(TdFieldDO.builder(). - fieldName("hour"). - dataType("INT"). - build()); - // 4. 获取超级表的名称 String superTableName = getProductPropertySTableName(deviceType, thingModel.getProductKey()); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineService.java index 3175d2839..753284aca 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineService.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.iot.service.tdengine; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; import cn.iocoder.yudao.module.iot.domain.SelectDto; -import cn.iocoder.yudao.module.iot.domain.TableDto; import cn.iocoder.yudao.module.iot.domain.TagsSelectDao; import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; @@ -70,17 +70,15 @@ public interface IotTdEngineService { * 创建表 * * @param tableDto 表信息 - * @throws Exception 异常 */ - void createTable(TableDto tableDto) throws Exception; + void createTable(TableDO tableDto); /** * 插入数据 * * @param tableDto 表信息 - * @throws Exception 异常 */ - void insertData(TableDto tableDto) throws Exception; + void insertData(TableDO tableDto); /** * 根据时间戳查询数据 diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineServiceImpl.java index 3c87f624d..c7f7e7309 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineServiceImpl.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.iot.service.tdengine; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineMapper; import cn.iocoder.yudao.module.iot.domain.SelectDto; -import cn.iocoder.yudao.module.iot.domain.TableDto; import cn.iocoder.yudao.module.iot.domain.TagsSelectDao; import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; import jakarta.annotation.Resource; @@ -31,12 +31,12 @@ public class IotTdEngineServiceImpl implements IotTdEngineService { } @Override - public void createTable(TableDto tableDto) { + public void createTable(TableDO tableDto) { tdEngineMapper.createTable(tableDto); } @Override - public void insertData(TableDto tableDto) { + public void insertData(TableDO tableDto) { tdEngineMapper.insertData(tableDto); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java index 937338544..b2f51a7f8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.iot.service.tdengine; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; /** @@ -10,7 +11,8 @@ public interface IotThingModelMessageService { /** * 保存物模型消息 * + * @param device 设备 * @param thingModelMessage 物模型消息 */ - void saveThingModelMessage(ThingModelMessage thingModelMessage); + void saveThingModelMessage(IotDeviceDO device,ThingModelMessage thingModelMessage); } \ 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/tdengine/IotThingModelMessageServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java index d47756423..ae7fa51ee 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java @@ -1,13 +1,127 @@ package cn.iocoder.yudao.module.iot.service.tdengine; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceStatusUpdateReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; +import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; +import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; +import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; +import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; +import cn.iocoder.yudao.module.iot.service.thinkmodelfunction.IotThinkModelFunctionService; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Slf4j @Service public class IotThingModelMessageServiceImpl implements IotThingModelMessageService { + @Value("${spring.datasource.dynamic.datasource.tdengine.url}") + private String url; + + @Resource + private IotThinkModelFunctionService iotThinkModelFunctionService; + @Resource + private IotDeviceService iotDeviceService; + @Resource + private IotTdEngineService iotTdEngineService; + @Override - public void saveThingModelMessage(ThingModelMessage thingModelMessage) { - // TODO 芋艿,后续实现 + @TenantIgnore + public void saveThingModelMessage(IotDeviceDO device, ThingModelMessage thingModelMessage) { + // 判断设备状态,如果为未激活状态,创建数据表 + if (device.getStatus().equals(0)) { + // 创建设备数据表 + createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); + // 更新设备状态 + IotDeviceStatusUpdateReqVO updateReqVO = new IotDeviceStatusUpdateReqVO(); + updateReqVO.setId(device.getId()); + updateReqVO.setStatus(IotDeviceStatusEnum.ONLINE.getStatus()); + iotDeviceService.updateDeviceStatus(updateReqVO); + } + + // 1. 获取设备属性 + Map params = thingModelMessage.dataToMap(); + + // 2. 物模型校验,过滤非物模型属性 + List thinkModelFunctionListByProductKey = iotThinkModelFunctionService.getThinkModelFunctionListByProductKey(thingModelMessage.getProductKey()); + + // 2.1 筛选是属性 IotProductFunctionTypeEnum + thinkModelFunctionListByProductKey.removeIf(iotThinkModelFunctionDO -> !iotThinkModelFunctionDO.getType().equals(IotProductFunctionTypeEnum.PROPERTY.getType())); + if (thinkModelFunctionListByProductKey.isEmpty()) { + return; + } + // 2.2 获取属性名称 + Map thingModelProperties = thinkModelFunctionListByProductKey.stream().collect(Collectors.toMap(IotThinkModelFunctionDO::getIdentifier, IotThinkModelFunctionDO::getName)); + + // 4. 保存属性记录 + List schemaFieldValues = new ArrayList<>(); + + // 1. 设置字段名 + schemaFieldValues.add(new TdFieldDO("time", thingModelMessage.getTime())); + + // 2. 遍历新属性 + params.forEach((key, val) -> { + if (thingModelProperties.containsKey(key)) { + schemaFieldValues.add(new TdFieldDO(key.toLowerCase(), val)); + } + }); + + // 3. 保存设备属性 + TableDO tableData = new TableDO(); + tableData.setDataBaseName(url.substring(url.lastIndexOf("/") + 1)); + tableData.setSuperTableName(getProductPropertySTableName(device.getDeviceType(), device.getProductKey())); + tableData.setTableName("device_" + device.getProductKey().toLowerCase() + "_" + device.getDeviceName().toLowerCase()); + tableData.setSchemaFieldValues(schemaFieldValues); + + // 4. 保存数据 + iotTdEngineService.insertData(tableData); + } + + private void createDeviceTable(Integer deviceType, String productKey, String deviceName, String deviceKey) { + List tagsFieldValues = new ArrayList<>(); + String SuperTableName = getProductPropertySTableName(deviceType, productKey); + List> maps = iotTdEngineService.describeSuperTable(url.substring(url.lastIndexOf("/") + 1), SuperTableName); + if (maps != null) { + List> taggedNotesList = maps.stream().filter(map -> "TAG".equals(map.get("note"))).toList(); + tagsFieldValues = FieldParser.parse(taggedNotesList.stream() + .map(map -> List.of(map.get("field"), map.get("type"), map.get("length"))) + .collect(Collectors.toList())); + for (TdFieldDO tagsFieldValue : tagsFieldValues) { + switch (tagsFieldValue.getFieldName()) { + case "product_key" -> tagsFieldValue.setFieldValue(productKey); + case "device_key" -> tagsFieldValue.setFieldValue(deviceKey); + case "device_name" -> tagsFieldValue.setFieldValue(deviceName); + case "device_type" -> tagsFieldValue.setFieldValue(deviceType); + } + } + } + + // 1. 创建设备数据表 + String tableName = "device_" + productKey.toLowerCase() + "_" + deviceName.toLowerCase(); + TableDO tableDto = new TableDO(); + tableDto.setDataBaseName(url.substring(url.lastIndexOf("/") + 1)); + tableDto.setSuperTableName(SuperTableName); + tableDto.setTableName(tableName); + tableDto.setTagsFieldValues(tagsFieldValues); + iotTdEngineService.createTable(tableDto); + } + + static String getProductPropertySTableName(Integer deviceType, String productKey) { + return switch (deviceType) { + case 1 -> String.format("gateway_sub_%s", productKey).toLowerCase(); + case 2 -> String.format("gateway_%s", productKey).toLowerCase(); + default -> String.format("device_%s", productKey).toLowerCase(); + }; } } \ 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/thinkmodelfunction/IotThinkModelFunctionService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java index 3067772e6..a6bf7b458 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java @@ -68,4 +68,12 @@ public interface IotThinkModelFunctionService { * @param productId 产品编号 */ void createSuperTableDataModel(Long productId); + + /** + * 获得产品物模型列表 + * + * @param productKey 产品 Key + * @return 产品物模型列表 + */ + List getThinkModelFunctionListByProductKey(String productKey); } \ 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/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java index dd7a51786..25cfe7b46 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java @@ -199,6 +199,11 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe dbStructureDataService.createSuperTableDataModel(product, functionList); } + @Override + public List getThinkModelFunctionListByProductKey(String productKey) { + return thinkModelFunctionMapper.selectListByProductKey(productKey); + } + /** * 创建默认的事件和服务 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml index d3f1088a1..9d5cf2a43 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml @@ -110,30 +110,27 @@ + - create table - if not exists #{dataBaseName}.#{tableName} - using #{dataBaseName}.#{superTableName} - tags - + CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} + USING ${dataBaseName}.${superTableName} + + ${item.fieldName} + + TAGS + #{item.fieldValue} + - insert into #{dataBaseName}.#{tableName} + INSERT INTO ${dataBaseName}.${tableName} - #{item.fieldName} + ${item.fieldName} - using #{dataBaseName}.#{superTableName} - tags - - #{item.fieldValue} - - values + VALUES #{item.fieldValue} From 624f5283b3ec89295f3562a068bd009881b1c487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Sun, 3 Nov 2024 00:16:46 +0800 Subject: [PATCH 008/228] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E3=80=91=20=E8=AE=BE=E5=A4=87=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=AD=98=E5=82=A8=E5=92=8C=E5=B1=95=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../product/IotProductFunctionTypeEnum.java | 2 +- .../admin/device/IotDeviceController.java | 8 +- .../admin/device/IotDeviceDataController.java | 38 +++++ .../vo/{ => device}/IotDevicePageReqVO.java | 2 +- .../vo/{ => device}/IotDeviceRespVO.java | 2 +- .../vo/{ => device}/IotDeviceSaveReqVO.java | 2 +- .../IotDeviceStatusUpdateReqVO.java | 2 +- .../vo/deviceData/IotDeviceDataReqVO.java | 21 +++ .../vo/deviceData/IotDeviceDataRespVO.java | 42 ++++++ .../convert/device/IotDeviceDataConvert.java | 46 ++++++ .../dataobject/device/IotDeviceDataDO.java | 71 +++++++++ .../iot/dal/mysql/device/IotDeviceMapper.java | 2 +- .../iot/dal/redis/RedisKeyConstants.java | 20 +++ .../redis/deviceData/DeviceDataRedisDAO.java | 43 ++++++ .../service/device/IotDeviceDataService.java | 17 ++- .../device/IotDeviceDataServiceImpl.java | 57 ++++++- .../iot/service/device/IotDeviceService.java | 4 +- .../service/device/IotDeviceServiceImpl.java | 6 +- .../IotDbStructureDataServiceImpl.java | 106 ++++++------- .../IotThingModelMessageServiceImpl.java | 140 ++++++++++++++---- 20 files changed, 523 insertions(+), 108 deletions(-) create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/{ => device}/IotDevicePageReqVO.java (97%) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/{ => device}/IotDeviceRespVO.java (97%) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/{ => device}/IotDeviceSaveReqVO.java (89%) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/{ => device}/IotDeviceStatusUpdateReqVO.java (91%) create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataRespVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/convert/device/IotDeviceDataConvert.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/RedisKeyConstants.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/deviceData/DeviceDataRedisDAO.java diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductFunctionTypeEnum.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductFunctionTypeEnum.java index b99d2b093..c8a03a4d3 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductFunctionTypeEnum.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductFunctionTypeEnum.java @@ -30,7 +30,7 @@ public enum IotProductFunctionTypeEnum implements IntArrayValuable { */ private final String description; - public static IotProductFunctionTypeEnum valueOf(Integer type) { + public static IotProductFunctionTypeEnum valueOfType(Integer type) { for (IotProductFunctionTypeEnum value : values()) { if (value.getType().equals(type)) { return value; 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 6d75f1cdd..ba68e0232 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 @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.iot.controller.admin.device; import cn.iocoder.yudao.framework.common.pojo.CommonResult; 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.device.vo.IotDevicePageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceRespVO; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceSaveReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceStatusUpdateReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDevicePageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceRespVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceSaveReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceStatusUpdateReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; import io.swagger.v3.oas.annotations.Operation; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java new file mode 100644 index 000000000..93b368bd8 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.iot.controller.admin.device; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataRespVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; +import cn.iocoder.yudao.module.iot.service.device.IotDeviceDataService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - IoT 设备数据") +@RestController +@RequestMapping("/iot/device/data") +@Validated +public class IotDeviceDataController { + + @Resource + private IotDeviceDataService deviceDataService; + + @GetMapping("/latest-data") + @Operation(summary = "获取设备属性最新数据") + public CommonResult> getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceDataReqVO) { + List list = deviceDataService.getDevicePropertiesLatestData(deviceDataReqVO); + return success(BeanUtils.toBean(list, IotDeviceDataRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDevicePageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDevicePageReqVO.java similarity index 97% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDevicePageReqVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDevicePageReqVO.java index 1c29f9f81..90ded8089 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDevicePageReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDevicePageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.iot.controller.admin.device.vo; +package cn.iocoder.yudao.module.iot.controller.admin.device.vo.device; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.validation.InEnum; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDeviceRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceRespVO.java similarity index 97% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDeviceRespVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceRespVO.java index 0b2cf25f5..fd2fbaa68 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDeviceRespVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.iot.controller.admin.device.vo; +package cn.iocoder.yudao.module.iot.controller.admin.device.vo.device; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDeviceSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceSaveReqVO.java similarity index 89% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDeviceSaveReqVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceSaveReqVO.java index 620e5310f..85fde9d3d 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDeviceSaveReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceSaveReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.iot.controller.admin.device.vo; +package cn.iocoder.yudao.module.iot.controller.admin.device.vo.device; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDeviceStatusUpdateReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceStatusUpdateReqVO.java similarity index 91% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDeviceStatusUpdateReqVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceStatusUpdateReqVO.java index a91a58690..daa1efde8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/IotDeviceStatusUpdateReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceStatusUpdateReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.iot.controller.admin.device.vo; +package cn.iocoder.yudao.module.iot.controller.admin.device.vo.device; import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java new file mode 100644 index 000000000..b8a95f607 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - IoT 设备数据 Request VO") +@Data +public class IotDeviceDataReqVO { + + @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "177") + private Long deviceId; + + @Schema(description = "属性标识符", requiredMode = Schema.RequiredMode.REQUIRED) + private String identifier; + + @Schema(description = "属性名称", requiredMode = Schema.RequiredMode.REQUIRED) + private String name; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataRespVO.java new file mode 100644 index 000000000..256bf84fa --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataRespVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - IoT 设备数据 Response VO") +@Data +public class IotDeviceDataRespVO { + + @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "177") + private Long deviceId; + + @Schema(description = "物模型编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "21816") + private Long thinkModelFunctionId; + + @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED) + private String productKey; + + @Schema(description = "设备名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") + private String deviceName; + + @Schema(description = "属性标识符", requiredMode = Schema.RequiredMode.REQUIRED) + private String identifier; + + @Schema(description = "属性名称", requiredMode = Schema.RequiredMode.REQUIRED) + private String name; + + @Schema(description = "数据类型", requiredMode = Schema.RequiredMode.REQUIRED) + private String dataType; + + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime updateTime; + + @Schema(description = "最新值", requiredMode = Schema.RequiredMode.REQUIRED) + private String value; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/convert/device/IotDeviceDataConvert.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/convert/device/IotDeviceDataConvert.java new file mode 100644 index 000000000..3bad54ba0 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/convert/device/IotDeviceDataConvert.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.iot.convert.device; + +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataRespVO; +import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelEvent; +import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty; +import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelService; +import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionRespVO; +import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionSaveReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; +import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +@Mapper +public interface IotDeviceDataConvert { + + IotDeviceDataConvert INSTANCE = Mappers.getMapper(IotDeviceDataConvert.class); + +// default List convert(Map deviceData, IotDeviceDO device){ +// List list = new ArrayList<>(); +// deviceData.forEach((identifier, value) -> { +//// ThingModelProperty property = ThingModelService.INSTANCE.getProperty(device.getProductId(), identifier); +//// if (Objects.isNull(property)) { +//// return; +//// } +// IotDeviceDataRespVO vo = new IotDeviceDataRespVO(); +// vo.setDeviceId(device.getId()); +// vo.setProductKey(device.getProductKey()); +// vo.setDeviceName(device.getDeviceName()); +// vo.setIdentifier(identifier); +//// vo.setName(property.getName()); +//// vo.setDataType(property.getDataType().getType()); +// vo.setUpdateTime(device.getUpdateTime()); +// vo.setValue(value.toString()); +// list.add(vo); +// }); +// return list; +// } +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java new file mode 100644 index 000000000..5d8051172 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.device; + +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; +import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; +import com.baomidou.mybatisplus.annotation.TableId; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * IoT 设备数据 DO + * + * @author haohao + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class IotDeviceDataDO { + + /** + * 设备编号 + */ + private Long deviceId; + + /** + * 物模型编号 + */ + private Long thinkModelFunctionId; + + /** + * 产品标识 + */ + private String productKey; + + /** + * 设备名称 + */ + private String deviceName; + + /** + * 属性标识符 + */ + private String identifier; + + /** + * 属性名称 + */ + private String name; + + /** + * 数据类型 + */ + private String dataType; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 最新值 + */ + private String value; + +} \ No newline at end of file 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 0e5552f83..3129f400c 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 @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.dal.mysql.device; 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.module.iot.controller.admin.device.vo.IotDevicePageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDevicePageReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import org.apache.ibatis.annotations.Mapper; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/RedisKeyConstants.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/RedisKeyConstants.java new file mode 100644 index 000000000..25ea7a292 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/RedisKeyConstants.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.iot.dal.redis; + + + +/** + * Iot Redis Key 枚举类 + * + * @author 芋道源码 + */ +public interface RedisKeyConstants { + + /** + * 设备属性数据缓存 + * + * KEY 格式:device_property_data:{deviceId} + * VALUE 数据类型:String 设备属性数据 + */ + String DEVICE_PROPERTY_DATA = "device_property_data:%s_%s_%s"; + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/deviceData/DeviceDataRedisDAO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/deviceData/DeviceDataRedisDAO.java new file mode 100644 index 000000000..b1b69f8dc --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/deviceData/DeviceDataRedisDAO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.iot.dal.redis.deviceData; + +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; +import jakarta.annotation.Resource; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Collection; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import static cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants.DEVICE_PROPERTY_DATA; + +/** + * {@link IotDeviceDataDO} 的 Redis DAO + */ +@Repository +public class DeviceDataRedisDAO { + + @Resource + private StringRedisTemplate stringRedisTemplate; + + public IotDeviceDataDO get(String productKey, String deviceName, String identifier) { + String redisKey = formatKey(productKey, deviceName, identifier); + return JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(redisKey), IotDeviceDataDO.class); + } + + public void set(IotDeviceDataDO deviceData) { + String redisKey = formatKey(deviceData.getProductKey(), deviceData.getDeviceName(), deviceData.getIdentifier()); + stringRedisTemplate.opsForValue().set(redisKey, JsonUtils.toJsonString(deviceData)); + } + + public void delete(String productKey, String deviceName, String identifier) { + String redisKey = formatKey(productKey, deviceName, identifier); + stringRedisTemplate.delete(redisKey); + } + + private static String formatKey(String productKey, String deviceName, String identifier) { + return String.format(DEVICE_PROPERTY_DATA, productKey, deviceName, identifier); + } +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java index 4f3ef37d6..f67f42685 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java @@ -1,12 +1,11 @@ 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.IotDevicePageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceSaveReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceStatusUpdateReqVO; -import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import jakarta.validation.Valid; +import java.util.List; + /** * IoT 设备数据 Service 接口 * @@ -23,4 +22,12 @@ public interface IotDeviceDataService { * @param message 消息 */ void saveDeviceData(String productKey, String deviceName, String message); + + /** + * 获得设备属性最新数据 + * + * @param deviceId 设备编号 + * @return 设备属性最新数据 + */ + List getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceId); } \ 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/IotDeviceDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java index 6b7aac21f..86ac630c6 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java @@ -1,13 +1,23 @@ package cn.iocoder.yudao.module.iot.service.device; import cn.hutool.json.JSONObject; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; +import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; +import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; +import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import cn.iocoder.yudao.module.iot.service.tdengine.IotThingModelMessageService; +import cn.iocoder.yudao.module.iot.service.thinkmodelfunction.IotThinkModelFunctionService; import jakarta.annotation.Resource; +import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.util.ArrayList; +import java.util.List; + @Slf4j @Service public class IotDeviceDataServiceImpl implements IotDeviceDataService { @@ -16,6 +26,11 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { private IotDeviceService deviceService; @Resource private IotThingModelMessageService thingModelMessageService; + @Resource + private IotThinkModelFunctionService thinkModelFunctionService; + + @Resource + private DeviceDataRedisDAO deviceDataRedisDAO; @Override public void saveDeviceData(String productKey, String deviceName, String message) { @@ -34,6 +49,46 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { .deviceName(deviceName) .deviceKey(device.getDeviceKey()) .build(); - thingModelMessageService.saveThingModelMessage(device,thingModelMessage); + thingModelMessageService.saveThingModelMessage(device, thingModelMessage); + } + + @Override + public List getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceDataReqVO) { + List list = new ArrayList<>(); + // 1. 获取设备信息 + IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId()); + // 2. 获取设备属性最新数据 + List thinkModelFunctionList = thinkModelFunctionService.getThinkModelFunctionListByProductKey(device.getProductKey()); + thinkModelFunctionList = thinkModelFunctionList.stream() + .filter(function -> IotProductFunctionTypeEnum.PROPERTY.getType() + .equals(function.getType())).toList(); + + // 3. 过滤标识符和属性名称 + if (deviceDataReqVO.getIdentifier() != null) { + thinkModelFunctionList = thinkModelFunctionList.stream() + .filter(function -> function.getIdentifier().toLowerCase().contains(deviceDataReqVO.getIdentifier().toLowerCase())) + .toList(); + } + if (deviceDataReqVO.getName() != null) { + thinkModelFunctionList = thinkModelFunctionList.stream() + .filter(function -> function.getName().toLowerCase().contains(deviceDataReqVO.getName().toLowerCase())) + .toList(); + } + // 4. 获取设备属性最新数据 + thinkModelFunctionList.forEach(function -> { + IotDeviceDataDO deviceData = deviceDataRedisDAO.get(device.getProductKey(), device.getDeviceName(), function.getIdentifier()); + if (deviceData == null) { + deviceData = new IotDeviceDataDO(); + deviceData.setProductKey(device.getProductKey()); + deviceData.setDeviceName(device.getDeviceName()); + deviceData.setIdentifier(function.getIdentifier()); + deviceData.setDeviceId(deviceDataReqVO.getDeviceId()); + deviceData.setThinkModelFunctionId(function.getId()); + deviceData.setName(function.getName()); + deviceData.setDataType(function.getProperty().getDataType().getType()); + } + list.add(deviceData); + }); + return list; } } 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 c967a957e..ed4c6a60c 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 @@ -1,7 +1,9 @@ package cn.iocoder.yudao.module.iot.service.device; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDevicePageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceSaveReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceStatusUpdateReqVO; import jakarta.validation.*; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.*; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; 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 f3243900e..60743f671 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 @@ -5,9 +5,9 @@ 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.framework.tenant.core.aop.TenantIgnore; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDevicePageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceSaveReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceStatusUpdateReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDevicePageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceSaveReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceStatusUpdateReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.mysql.device.IotDeviceMapper; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java index b7de8882a..947178102 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java @@ -1,12 +1,12 @@ package cn.iocoder.yudao.module.iot.service.tdengine; +import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty; import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelRespVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdRestApi; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import jakarta.annotation.Resource; @@ -14,10 +14,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.stream.Collectors; @Service @@ -27,9 +24,6 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService @Resource private IotTdEngineService iotTdEngineService; - @Resource - private TdRestApi tdRestApi; - @Value("${spring.datasource.dynamic.datasource.tdengine.url}") private String url; @@ -37,39 +31,25 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService public void createSuperTable(ThingModelRespVO thingModel, Integer deviceType) { // 1. 解析物模型,获得字段列表 List schemaFields = new ArrayList<>(); - schemaFields.add(TdFieldDO.builder(). - fieldName("time"). - dataType("TIMESTAMP"). - build()); + schemaFields.add(TdFieldDO.builder() + .fieldName("time") + .dataType("TIMESTAMP") + .build()); schemaFields.addAll(FieldParser.parse(thingModel)); // 3. 设置超级表的标签 - List tagsFields = new ArrayList<>(); - tagsFields.add(TdFieldDO.builder(). - fieldName("product_key"). - dataType("NCHAR"). - dataLength(64). - build()); - tagsFields.add(TdFieldDO.builder(). - fieldName("device_key"). - dataType("NCHAR"). - dataLength(64). - build()); - tagsFields.add(TdFieldDO.builder(). - fieldName("device_name"). - dataType("NCHAR"). - dataLength(64). - build()); - tagsFields.add(TdFieldDO.builder(). - fieldName("device_type"). - dataType("INT"). - build()); + List tagsFields = Arrays.asList( + TdFieldDO.builder().fieldName("product_key").dataType("NCHAR").dataLength(64).build(), + TdFieldDO.builder().fieldName("device_key").dataType("NCHAR").dataLength(64).build(), + TdFieldDO.builder().fieldName("device_name").dataType("NCHAR").dataLength(64).build(), + TdFieldDO.builder().fieldName("device_type").dataType("INT").build() + ); // 4. 获取超级表的名称 String superTableName = getProductPropertySTableName(deviceType, thingModel.getProductKey()); // 5. 创建超级表 - String dataBaseName = url.substring(url.lastIndexOf("/") + 1); + String dataBaseName = getDatabaseName(); iotTdEngineService.createSuperTable(schemaFields, tagsFields, dataBaseName, superTableName); } @@ -81,7 +61,7 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService List newFields = FieldParser.parse(thingModel); updateTableFields(tbName, oldFields, newFields); - } catch (Throwable e) { + } catch (Exception e) { log.error("更新物模型超级表失败", e); } } @@ -90,14 +70,15 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService private List getTableFields(String tableName) { List fields = new ArrayList<>(); // 获取超级表的描述信息 - List> maps = iotTdEngineService.describeSuperTable(url.substring(url.lastIndexOf("/") + 1), tableName); + List> maps = iotTdEngineService.describeSuperTable(getDatabaseName(), tableName); if (maps != null) { - // 过滤掉 note 字段为 TAG 的记录 - maps = maps.stream().filter(map -> !"TAG".equals(map.get("note"))).toList(); - // 过滤掉 time 字段 - maps = maps.stream().filter(map -> !"time".equals(map.get("field"))).toList(); + // 过滤掉 note 字段为 TAG 的记录和 time 字段 + List> filteredMaps = maps.stream() + .filter(map -> !"TAG".equals(map.get("note"))) + .filter(map -> !"time".equals(map.get("field"))) + .toList(); // 解析字段信息 - fields = FieldParser.parse(maps.stream() + fields = FieldParser.parse(filteredMaps.stream() .map(map -> List.of(map.get("field"), map.get("type"), map.get("length"))) .collect(Collectors.toList())); } @@ -113,7 +94,7 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService // 获取删除字段 List dropFields = getDropFields(oldFields, newFields); - String dataBaseName = url.substring(url.lastIndexOf("/") + 1); + String dataBaseName = getDatabaseName(); // 添加新增字段 if (CollUtil.isNotEmpty(addFields)) { iotTdEngineService.addColumnForSuperTable(dataBaseName, tableName, addFields); @@ -131,25 +112,37 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService // 获取新增字段 private List getAddFields(List oldFields, List newFields) { + Set oldFieldNames = oldFields.stream() + .map(TdFieldDO::getFieldName) + .collect(Collectors.toSet()); return newFields.stream() - .filter(f -> oldFields.stream().noneMatch(old -> old.getFieldName().equals(f.getFieldName()))) + .filter(f -> !oldFieldNames.contains(f.getFieldName())) .collect(Collectors.toList()); } // 获取修改字段 private List getModifyFields(List oldFields, List newFields) { + Map oldFieldMap = oldFields.stream() + .collect(Collectors.toMap(TdFieldDO::getFieldName, f -> f)); + return newFields.stream() - .filter(f -> oldFields.stream().anyMatch(old -> - old.getFieldName().equals(f.getFieldName()) && - (!old.getDataType().equals(f.getDataType()) || !Objects.equals(old.getDataLength(), f.getDataLength())))) + .filter(f -> { + TdFieldDO oldField = oldFieldMap.get(f.getFieldName()); + return oldField != null && + (!oldField.getDataType().equals(f.getDataType()) || + !Objects.equals(oldField.getDataLength(), f.getDataLength())); + }) .collect(Collectors.toList()); } // 获取删除字段 private List getDropFields(List oldFields, List newFields) { + Set newFieldNames = newFields.stream() + .map(TdFieldDO::getFieldName) + .collect(Collectors.toSet()); return oldFields.stream() - .filter(f -> !"time".equals(f.getFieldName()) && !"device_id".equals(f.getFieldName()) && - newFields.stream().noneMatch(n -> n.getFieldName().equals(f.getFieldName()))) + .filter(f -> !"time".equals(f.getFieldName()) && !"device_id".equals(f.getFieldName())) + .filter(f -> !newFieldNames.contains(f.getFieldName())) .collect(Collectors.toList()); } @@ -157,13 +150,13 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService public void createSuperTableDataModel(IotProductDO product, List functionList) { ThingModelRespVO thingModel = buildThingModel(product, functionList); - if (thingModel.getModel().getProperties().isEmpty()) { + if (thingModel.getModel() == null || CollUtil.isEmpty(thingModel.getModel().getProperties())) { log.warn("物模型属性列表为空,不创建超级表"); return; } String superTableName = getProductPropertySTableName(product.getDeviceType(), product.getProductKey()); - String dataBaseName = url.substring(url.lastIndexOf("/") + 1); + String dataBaseName = getDatabaseName(); Integer tableExists = iotTdEngineService.checkSuperTableExists(dataBaseName, superTableName); if (tableExists != null && tableExists > 0) { @@ -180,7 +173,8 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService ThingModelRespVO.Model model = new ThingModelRespVO.Model(); List properties = functionList.stream() - .filter(function -> IotProductFunctionTypeEnum.PROPERTY.equals(IotProductFunctionTypeEnum.valueOf(function.getType()))) + .filter(function -> IotProductFunctionTypeEnum.PROPERTY.equals( + IotProductFunctionTypeEnum.valueOfType(function.getType()))) .map(this::buildThingModelProperty) .collect(Collectors.toList()); @@ -191,14 +185,15 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService } private ThingModelProperty buildThingModelProperty(IotThinkModelFunctionDO function) { - ThingModelProperty property = new ThingModelProperty(); - property.setIdentifier(function.getIdentifier()); - property.setName(function.getName()); - property.setDescription(function.getDescription()); + ThingModelProperty property = BeanUtil.copyProperties(function, ThingModelProperty.class); property.setDataType(function.getProperty().getDataType()); return property; } + private String getDatabaseName() { + return url.substring(url.lastIndexOf("/") + 1); + } + static String getProductPropertySTableName(Integer deviceType, String productKey) { return switch (deviceType) { case 1 -> String.format("gateway_sub_%s", productKey).toLowerCase(); @@ -207,7 +202,4 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService }; } - static String getDevicePropertyTableName(String deviceType, String productKey, String deviceKey) { - return String.format("%s_%s_%s", deviceType, productKey, deviceKey).toLowerCase(); - } } \ 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/tdengine/IotThingModelMessageServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java index ae7fa51ee..9bad7613e 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java @@ -1,13 +1,16 @@ package cn.iocoder.yudao.module.iot.service.tdengine; +import cn.hutool.core.date.DateUtil; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceStatusUpdateReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceStatusUpdateReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; +import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; @@ -17,9 +20,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; @Slf4j @@ -36,11 +37,14 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @Resource private IotTdEngineService iotTdEngineService; + @Resource + private DeviceDataRedisDAO deviceDataRedisDAO; + @Override @TenantIgnore public void saveThingModelMessage(IotDeviceDO device, ThingModelMessage thingModelMessage) { // 判断设备状态,如果为未激活状态,创建数据表 - if (device.getStatus().equals(0)) { + if (IotDeviceStatusEnum.INACTIVE.getStatus().equals(device.getStatus())) { // 创建设备数据表 createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); // 更新设备状态 @@ -50,53 +54,99 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ iotDeviceService.updateDeviceStatus(updateReqVO); } - // 1. 获取设备属性 + // 获取设备属性 Map params = thingModelMessage.dataToMap(); - // 2. 物模型校验,过滤非物模型属性 - List thinkModelFunctionListByProductKey = iotThinkModelFunctionService.getThinkModelFunctionListByProductKey(thingModelMessage.getProductKey()); + // 物模型校验,过滤非物模型属性 + List functionList = iotThinkModelFunctionService + .getThinkModelFunctionListByProductKey(thingModelMessage.getProductKey()) + .stream() + .filter(function -> IotProductFunctionTypeEnum.PROPERTY.getType().equals(function.getType())) + .toList(); - // 2.1 筛选是属性 IotProductFunctionTypeEnum - thinkModelFunctionListByProductKey.removeIf(iotThinkModelFunctionDO -> !iotThinkModelFunctionDO.getType().equals(IotProductFunctionTypeEnum.PROPERTY.getType())); - if (thinkModelFunctionListByProductKey.isEmpty()) { + if (functionList.isEmpty()) { return; } - // 2.2 获取属性名称 - Map thingModelProperties = thinkModelFunctionListByProductKey.stream().collect(Collectors.toMap(IotThinkModelFunctionDO::getIdentifier, IotThinkModelFunctionDO::getName)); - // 4. 保存属性记录 + // 获取属性标识符集合 + Set propertyIdentifiers = functionList.stream() + .map(IotThinkModelFunctionDO::getIdentifier) + .collect(Collectors.toSet()); + + Map functionMap = functionList.stream() + .collect(Collectors.toMap(IotThinkModelFunctionDO::getIdentifier, function -> function)); + + // 过滤并收集有效的属性字段 List schemaFieldValues = new ArrayList<>(); - - // 1. 设置字段名 schemaFieldValues.add(new TdFieldDO("time", thingModelMessage.getTime())); - - // 2. 遍历新属性 params.forEach((key, val) -> { - if (thingModelProperties.containsKey(key)) { + if (propertyIdentifiers.contains(key)) { schemaFieldValues.add(new TdFieldDO(key.toLowerCase(), val)); + // 缓存设备属性 + setDeviceDataCache(device, functionMap.get(key), val, thingModelMessage.getTime()); } }); + if (schemaFieldValues.size() == 1) { + return; + } - // 3. 保存设备属性 + // 构建并保存设备属性 TableDO tableData = new TableDO(); - tableData.setDataBaseName(url.substring(url.lastIndexOf("/") + 1)); + tableData.setDataBaseName(getDatabaseName()); tableData.setSuperTableName(getProductPropertySTableName(device.getDeviceType(), device.getProductKey())); - tableData.setTableName("device_" + device.getProductKey().toLowerCase() + "_" + device.getDeviceName().toLowerCase()); + tableData.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())); tableData.setSchemaFieldValues(schemaFieldValues); - // 4. 保存数据 iotTdEngineService.insertData(tableData); } + /** + * 缓存设备属性 + * + * @param device 设备信息 + * @param iotThinkModelFunctionDO 物模型属性 + * @param val 属性值 + * @param time 时间 + */ + private void setDeviceDataCache(IotDeviceDO device, IotThinkModelFunctionDO iotThinkModelFunctionDO, Object val, Long time) { + IotDeviceDataDO deviceData = IotDeviceDataDO.builder() + .productKey(device.getProductKey()) + .deviceName(device.getDeviceName()) + .identifier(iotThinkModelFunctionDO.getIdentifier()) + .value(val != null ? val.toString() : null) + .updateTime(DateUtil.toLocalDateTime(new Date(time))) + .deviceId(device.getId()) + .thinkModelFunctionId(iotThinkModelFunctionDO.getId()) + .name(iotThinkModelFunctionDO.getName()) + .dataType(iotThinkModelFunctionDO.getProperty().getDataType().getType()) + .build(); + deviceDataRedisDAO.set(deviceData); + } + + /** + * 创建设备数据表 + * + * @param deviceType 设备类型 + * @param productKey 产品 Key + * @param deviceName 设备名称 + * @param deviceKey 设备 Key + */ private void createDeviceTable(Integer deviceType, String productKey, String deviceName, String deviceKey) { + String superTableName = getProductPropertySTableName(deviceType, productKey); + String dataBaseName = getDatabaseName(); + + List> maps = iotTdEngineService.describeSuperTable(dataBaseName, superTableName); List tagsFieldValues = new ArrayList<>(); - String SuperTableName = getProductPropertySTableName(deviceType, productKey); - List> maps = iotTdEngineService.describeSuperTable(url.substring(url.lastIndexOf("/") + 1), SuperTableName); + if (maps != null) { - List> taggedNotesList = maps.stream().filter(map -> "TAG".equals(map.get("note"))).toList(); + List> taggedNotesList = maps.stream() + .filter(map -> "TAG".equals(map.get("note"))) + .toList(); + tagsFieldValues = FieldParser.parse(taggedNotesList.stream() .map(map -> List.of(map.get("field"), map.get("type"), map.get("length"))) .collect(Collectors.toList())); + for (TdFieldDO tagsFieldValue : tagsFieldValues) { switch (tagsFieldValue.getFieldName()) { case "product_key" -> tagsFieldValue.setFieldValue(productKey); @@ -107,21 +157,49 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ } } - // 1. 创建设备数据表 - String tableName = "device_" + productKey.toLowerCase() + "_" + deviceName.toLowerCase(); + // 创建设备数据表 + String tableName = getDeviceTableName(productKey, deviceName); TableDO tableDto = new TableDO(); - tableDto.setDataBaseName(url.substring(url.lastIndexOf("/") + 1)); - tableDto.setSuperTableName(SuperTableName); + tableDto.setDataBaseName(dataBaseName); + tableDto.setSuperTableName(superTableName); tableDto.setTableName(tableName); tableDto.setTagsFieldValues(tagsFieldValues); + iotTdEngineService.createTable(tableDto); } - static String getProductPropertySTableName(Integer deviceType, String productKey) { + /** + * 获取数据库名称 + * + * @return 数据库名称 + */ + private String getDatabaseName() { + return url.substring(url.lastIndexOf("/") + 1); + } + + /** + * 获取产品属性表名 + * + * @param deviceType 设备类型 + * @param productKey 产品 Key + * @return 产品属性表名 + */ + private static String getProductPropertySTableName(Integer deviceType, String productKey) { return switch (deviceType) { case 1 -> String.format("gateway_sub_%s", productKey).toLowerCase(); case 2 -> String.format("gateway_%s", productKey).toLowerCase(); default -> String.format("device_%s", productKey).toLowerCase(); }; } + + /** + * 获取设备表名 + * + * @param productKey 产品 Key + * @param deviceName 设备名称 + * @return 设备表名 + */ + private static String getDeviceTableName(String productKey, String deviceName) { + return String.format("device_%s_%s", productKey.toLowerCase(), deviceName.toLowerCase()); + } } \ No newline at end of file From d7b8cf547f4d96b49c3371fbbf4535a1c4dfab3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Tue, 5 Nov 2024 23:26:34 +0800 Subject: [PATCH 009/228] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E3=80=91=20=E8=AE=BE=E5=A4=87=E5=8E=86=E5=8F=B2?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=B1=95=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/domain/visual/SelectVisualDto.java | 29 +++++++------ .../admin/device/IotDeviceDataController.java | 10 +++++ .../vo/deviceData/IotDeviceDataReqVO.java | 12 +++++- .../vo/deviceData/IotTimeDataRespVO.java} | 8 ++-- .../iot/dal/tdengine/TdEngineMapper.java | 7 ++- .../service/device/IotDeviceDataService.java | 10 +++++ .../device/IotDeviceDataServiceImpl.java | 43 +++++++++++++++++++ .../mapper/tdengine/TdEngineMapper.xml | 19 +++++--- 8 files changed, 112 insertions(+), 26 deletions(-) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/{dal/dataobject/tdengine/TimeData.java => controller/admin/device/vo/deviceData/IotTimeDataRespVO.java} (67%) diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/visual/SelectVisualDto.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/visual/SelectVisualDto.java index 1444da972..071c76303 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/visual/SelectVisualDto.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/visual/SelectVisualDto.java @@ -4,24 +4,24 @@ import lombok.Data; import java.util.Map; -/** - * @ClassDescription: 查询可视化所需入参对象 - * @ClassName: SelectDto - * @Author: andyz - * @Date: 2022-07-29 14:12:26 - * @Version 1.0 - */ @Data public class SelectVisualDto { -// @NotBlank(message = "invalid operation: tableName can not be empty") + /** + * 数据库名称 + */ private String dataBaseName; -// @NotBlank(message = "invalid operation: tableName can not be empty") + /** + * 表名 + */ private String tableName; -// @NotBlank(message = "invalid operation: fieldName can not be empty") //属性 + /** + * 属性 + */ private String fieldName; + /** * 查询类型,0历史数据,1实时数据,2聚合数据 */ @@ -39,10 +39,15 @@ public class SelectVisualDto { * 比如1s,1m,1h,1d代表1秒,1分钟,1小时,1天 */ private String interval; - // @NotNull(message = "invalid operation: startTime can not be null") + + /** + * 开始时间 + */ private Long startTime; - // @NotNull(message = "invalid operation: endTime can not be null") + /** + * 结束时间 + */ private Long endTime; /** diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java index 93b368bd8..e710d0ea8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java @@ -1,10 +1,12 @@ package cn.iocoder.yudao.module.iot.controller.admin.device; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +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.device.vo.deviceData.IotDeviceDataReqVO; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataRespVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotTimeDataRespVO; import cn.iocoder.yudao.module.iot.service.device.IotDeviceDataService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -16,6 +18,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; +import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -35,4 +38,11 @@ public class IotDeviceDataController { return success(BeanUtils.toBean(list, IotDeviceDataRespVO.class)); } + @GetMapping("/history-data") + @Operation(summary = "获取设备属性历史数据") + public CommonResult> getDevicePropertiesHistoryData(@Valid IotDeviceDataReqVO deviceDataReqVO) { + PageResult> list = deviceDataService.getDevicePropertiesHistoryData(deviceDataReqVO); + return success(BeanUtils.toBean(list, IotTimeDataRespVO.class)); + } + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java index b8a95f607..5f87a1cb8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java @@ -1,13 +1,18 @@ package cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Size; import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + @Schema(description = "管理后台 - IoT 设备数据 Request VO") @Data -public class IotDeviceDataReqVO { +public class IotDeviceDataReqVO extends PageParam { @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "177") private Long deviceId; @@ -18,4 +23,9 @@ public class IotDeviceDataReqVO { @Schema(description = "属性名称", requiredMode = Schema.RequiredMode.REQUIRED) private String name; + @Schema(description = "时间范围", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @Size(min = 2, max = 2, message = "请选择时间范围") + private LocalDateTime[] times; + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TimeData.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotTimeDataRespVO.java similarity index 67% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TimeData.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotTimeDataRespVO.java index f7e251ea8..1bf085c54 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TimeData.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotTimeDataRespVO.java @@ -1,16 +1,14 @@ -package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; +package cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -/** - * 统计的时间数据 - */ + @Data @NoArgsConstructor @AllArgsConstructor -public class TimeData { +public class IotTimeDataRespVO { /** * 时间 diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java index 94db527c2..c126946f1 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java @@ -88,6 +88,7 @@ public interface TdEngineMapper { /** * 创建表 - 创建超级表的子表 + * * @param tableDO 表信息 */ @InterceptorIgnore(tenantLine = "true") @@ -114,6 +115,7 @@ public interface TdEngineMapper { Map getLastData(SelectDto selectDto); + @InterceptorIgnore(tenantLine = "true") List> getHistoryData(SelectVisualDto selectVisualDto); List> getRealtimeData(SelectVisualDto selectVisualDto); @@ -122,5 +124,6 @@ public interface TdEngineMapper { List> getLastDataByTags(TagsSelectDao tagsSelectDao); - -} + @InterceptorIgnore(tenantLine = "true") + Long getHistoryCount(SelectVisualDto selectVisualDto); +} \ 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/IotDeviceDataService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java index f67f42685..96181fd26 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java @@ -1,10 +1,12 @@ 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.deviceData.IotDeviceDataReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import jakarta.validation.Valid; import java.util.List; +import java.util.Map; /** * IoT 设备数据 Service 接口 @@ -30,4 +32,12 @@ public interface IotDeviceDataService { * @return 设备属性最新数据 */ List getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceId); + + /** + * 获得设备属性历史数据 + * + * @param deviceDataReqVO 设备属性历史数据 Request VO + * @return 设备属性历史数据 + */ + PageResult> getDevicePropertiesHistoryData(@Valid IotDeviceDataReqVO deviceDataReqVO); } \ 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/IotDeviceDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java index 86ac630c6..1b44bd5d0 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java @@ -1,27 +1,38 @@ package cn.iocoder.yudao.module.iot.service.device; +import cn.hutool.core.date.DateUtil; import cn.hutool.json.JSONObject; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineMapper; +import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import cn.iocoder.yudao.module.iot.service.tdengine.IotThingModelMessageService; import cn.iocoder.yudao.module.iot.service.thinkmodelfunction.IotThinkModelFunctionService; import jakarta.annotation.Resource; import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import java.time.ZoneId; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; @Slf4j @Service public class IotDeviceDataServiceImpl implements IotDeviceDataService { + @Value("${spring.datasource.dynamic.datasource.tdengine.url}") + private String url; + @Resource private IotDeviceService deviceService; @Resource @@ -32,6 +43,9 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { @Resource private DeviceDataRedisDAO deviceDataRedisDAO; + @Resource + private TdEngineMapper tdEngineMapper; + @Override public void saveDeviceData(String productKey, String deviceName, String message) { // 1. 根据产品 key 和设备名称,获得设备信息 @@ -91,4 +105,33 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { }); return list; } + + @Override + public PageResult> getDevicePropertiesHistoryData(IotDeviceDataReqVO deviceDataReqVO) { + PageResult> pageResult = new PageResult<>(); + // 1. 获取设备信息 + IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId()); + // 2. 获取设备属性历史数据 + SelectVisualDto selectVisualDto = new SelectVisualDto(); + selectVisualDto.setDataBaseName(getDatabaseName()); + selectVisualDto.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())); + selectVisualDto.setFieldName(deviceDataReqVO.getIdentifier()); + selectVisualDto.setStartTime(DateUtil.date(deviceDataReqVO.getTimes()[0].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime()); + selectVisualDto.setEndTime(DateUtil.date(deviceDataReqVO.getTimes()[1].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime()); + Map params = new HashMap<>(); + params.put("rows", deviceDataReqVO.getPageSize()); + params.put("page", (deviceDataReqVO.getPageNo() - 1) * deviceDataReqVO.getPageSize()); + selectVisualDto.setParams(params); + pageResult.setList(tdEngineMapper.getHistoryData(selectVisualDto)); + pageResult.setTotal(tdEngineMapper.getHistoryCount(selectVisualDto)); + return pageResult; + } + + private String getDatabaseName() { + return url.substring(url.lastIndexOf("/") + 1); + } + + private static String getDeviceTableName(String productKey, String deviceName) { + return String.format("device_%s_%s", productKey.toLowerCase(), deviceName.toLowerCase()); + } } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml index 9d5cf2a43..4e127e44b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml @@ -292,17 +292,18 @@ - SELECT #{fieldName}, ts - FROM #{dataBaseName}.#{tableName} - WHERE ts BETWEEN #{startTime} AND #{endTime} - LIMIT #{num} + SELECT ${fieldName} as data, time + FROM ${dataBaseName}.${tableName} + WHERE time BETWEEN #{startTime} AND #{endTime} + AND ${fieldName} IS NOT NULL + ORDER BY time DESC + LIMIT #{params.rows} offset #{params.page} - SELECT #{fieldName}, ts + SELECT #{fieldName}, time FROM #{dataBaseName}.#{tableName} - LIMIT #{num} DESCRIBE ${dataBaseName}.${superTableName} + + SELECT count(time) + FROM ${dataBaseName}.${tableName} + WHERE time BETWEEN #{startTime} AND #{endTime} + AND ${fieldName} IS NOT NULL + From e3dcea9cb3792bfebb489c3ccfb568bcec6bf7da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Fri, 8 Nov 2024 23:07:37 +0800 Subject: [PATCH 010/228] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E3=80=91=20=E4=BC=98=E5=8C=96=20tdengine=20=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E6=95=B0=E6=8D=AE=E5=BA=93=E7=9B=B8=E5=85=B3=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/iot/domain/BaseEntity.java | 18 - .../iot/domain/DeviceDataExportExcelDto.java | 35 -- .../yudao/module/iot/domain/DeviceDataVo.java | 19 - .../yudao/module/iot/domain/Fields.java | 65 ---- .../yudao/module/iot/domain/FieldsVo.java | 31 -- .../module/iot/domain/IotSequential.java | 71 ---- .../module/iot/domain/MessageCountVo.java | 25 -- .../iot/domain/ProductSuperTableModel.java | 29 -- .../yudao/module/iot/domain/SelectDto.java | 30 -- .../module/iot/domain/SuperTableDto.java | 31 -- .../yudao/module/iot/domain/TableDto.java | 26 -- .../module/iot/domain/TagsSelectDao.java | 25 -- .../yudao/module/iot/domain/Weather.java | 73 ---- .../iot/dal/dataobject/tdengine/SelectDO.java | 51 +++ .../dataobject/tdengine/SelectVisualDO.java} | 4 +- .../iot/dal/dataobject/tdengine/TableDO.java | 27 -- .../dal/dataobject/tdengine/TableData.java | 44 --- .../dal/dataobject/tdengine/TagsSelectDO.java | 36 ++ .../dal/dataobject/tdengine/TdFieldDO.java | 10 +- .../dal/dataobject/tdengine/TdTableDO.java | 65 ++++ .../tdengine/TdEngineDataWriterMapper.java | 25 ++ .../dal/tdengine/TdEngineDatabaseMapper.java | 23 ++ .../iot/dal/tdengine/TdEngineMapper.java | 129 ------- .../iot/dal/tdengine/TdEngineQueryMapper.java | 85 +++++ .../tdengine/TdEngineSuperTableMapper.java | 111 ++++++ .../iot/dal/tdengine/TdEngineTableMapper.java | 41 +++ .../device/IotDeviceDataServiceImpl.java | 27 +- ...Service.java => IotSuperTableService.java} | 15 +- ...mpl.java => IotSuperTableServiceImpl.java} | 309 ++++++++++------- .../service/tdengine/IotTdEngineService.java | 142 -------- .../tdengine/IotTdEngineServiceImpl.java | 107 ------ .../tdengine/IotThingModelMessageService.java | 4 +- .../IotThingModelMessageServiceImpl.java | 38 +- .../tdengine/TdEngineDataWriterService.java | 19 + .../TdEngineDataWriterServiceImpl.java | 21 ++ .../tdengine/TdEngineDatabaseService.java | 14 + .../tdengine/TdEngineDatabaseServiceImpl.java | 22 ++ .../tdengine/TdEngineQueryService.java | 28 ++ .../tdengine/TdEngineQueryServiceImpl.java | 26 ++ .../tdengine/TdEngineSuperTableService.java | 123 +++++++ .../TdEngineSuperTableServiceImpl.java | 90 +++++ .../tdengine/TdEngineTableService.java | 21 ++ .../tdengine/TdEngineTableServiceImpl.java | 23 ++ .../IotThinkModelFunctionService.java | 2 +- .../IotThinkModelFunctionServiceImpl.java | 4 +- .../tdengine/TdEngineDataWriterMapper.xml | 22 ++ .../tdengine/TdEngineDatabaseMapper.xml | 13 + .../mapper/tdengine/TdEngineMapper.xml | 327 ------------------ .../mapper/tdengine/TdEngineQueryMapper.xml | 73 ++++ .../tdengine/TdEngineSuperTableMapper.xml | 72 ++++ .../mapper/tdengine/TdEngineTableMapper.xml | 33 ++ 51 files changed, 1262 insertions(+), 1442 deletions(-) delete mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/BaseEntity.java delete mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/DeviceDataExportExcelDto.java delete mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/DeviceDataVo.java delete mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/Fields.java delete mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/FieldsVo.java delete mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/IotSequential.java delete mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/MessageCountVo.java delete mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/ProductSuperTableModel.java delete mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SelectDto.java delete mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SuperTableDto.java delete mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TableDto.java delete mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TagsSelectDao.java delete mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/Weather.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java rename yudao-module-iot/{yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/visual/SelectVisualDto.java => yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java} (90%) delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableDO.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TagsSelectDO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdTableDO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDataWriterMapper.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineSuperTableMapper.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/{IotDbStructureDataService.java => IotSuperTableService.java} (50%) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/{IotDbStructureDataServiceImpl.java => IotSuperTableServiceImpl.java} (55%) delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineService.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineServiceImpl.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterService.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseServiceImpl.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryService.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableService.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/BaseEntity.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/BaseEntity.java deleted file mode 100644 index 496be9a24..000000000 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/BaseEntity.java +++ /dev/null @@ -1,18 +0,0 @@ -package cn.iocoder.yudao.module.iot.domain; - -import lombok.Data; - -@Data -public class BaseEntity { - private static final long serialVersionUID = 1L; - - /** - * 数据库名称 - */ - private String dataBaseName; - - /** - * 超级表名称 - */ - private String superTableName; -} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/DeviceDataExportExcelDto.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/DeviceDataExportExcelDto.java deleted file mode 100644 index cedb4d119..000000000 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/DeviceDataExportExcelDto.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.module.iot.domain; - -import lombok.Data; - -/** - * 设备数据导出 excel DTO - */ -@Data -public class DeviceDataExportExcelDto { - - /** - * 设备标识 - */ - private String deviceKey; - - /** - * 导出形式 1 单个参数导出 2 全部参数导出 - */ - private String exportType; - - /** - * 导出开始时间 - */ - private String exportBeginTime; - - /** - * 导出结束时间 - */ - private String exportEndTime; - - /** - * 导出参数,空则导出全部 - */ - private String exportParameter; -} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/DeviceDataVo.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/DeviceDataVo.java deleted file mode 100644 index b9f6fc412..000000000 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/DeviceDataVo.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.module.iot.domain; - -import lombok.Data; - -/** - * @ClassDescription: 查询可视化所需入参对象 - * @ClassName: SelectDto - * @Author: andyz - * @Date: 2022-07-29 14:12:26 - * @Version 1.0 - */ -@Data -public class DeviceDataVo { - - - private String deviceId; - - private Long lastTime; -} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/Fields.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/Fields.java deleted file mode 100644 index ec0a7f148..000000000 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/Fields.java +++ /dev/null @@ -1,65 +0,0 @@ -package cn.iocoder.yudao.module.iot.domain; - -import lombok.Data; - -@Data -public class Fields { - private static final long serialVersionUID = 1L; - - /** - * 字段名称 - */ - private String fieldName; - - /** - * 字段值 - */ - private Object fieldValue; - - /** - * 字段数据类型 - */ -// private DataTypeEnum dataType; - - /** - * 字段字节大小 - */ - private Integer size; - - public Fields() { - } - - public Fields(String fieldName, String dataType, Integer size) { -// this.fieldName = fieldName; -// //根据规则匹配字段数据类型 -// switch (dataType.toLowerCase()) { -// case ("json"): -// this.dataType = DataTypeEnum.JSON; -// this.size = size; -// break; -// case ("string"): -// this.dataType = DataTypeEnum.NCHAR; -// this.size = size; -// break; -// case ("binary"): -// this.dataType = DataTypeEnum.BINARY; -// this.size = size; -// break; -// case ("int"): -// this.dataType = DataTypeEnum.INT; -// break; -// case ("bool"): -// this.dataType = DataTypeEnum.BOOL; -// break; -// case ("decimal"): -// this.dataType = DataTypeEnum.DOUBLE; -// break; -// case ("timestamp"): -// if ("eventTime".equals(fieldName)) { -// this.fieldName = "eventTime"; -// } -// this.dataType = DataTypeEnum.TIMESTAMP; -// break; -// } - } -} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/FieldsVo.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/FieldsVo.java deleted file mode 100644 index fc86a8f7e..000000000 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/FieldsVo.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.module.iot.domain; - -import lombok.Builder; -import lombok.Data; - -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -/** - * 字段信息 VO - */ -@Data -@Builder -public class FieldsVo { - - /** - * 字段名称 - */ - private String fieldName; - - /** - * 字段数据类型 - */ - private String dataType; - - /** - * 字段字节大小 - */ - private Integer size; -} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/IotSequential.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/IotSequential.java deleted file mode 100644 index 349d6d137..000000000 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/IotSequential.java +++ /dev/null @@ -1,71 +0,0 @@ -package cn.iocoder.yudao.module.iot.domain; - -import com.fasterxml.jackson.annotation.JsonFormat; - -import java.sql.Timestamp; - -public class IotSequential extends BaseEntity { - private static final long serialVersionUID = 1L; - - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS" , timezone = "GMT+8") - private Timestamp statetime; - - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS" , timezone = "GMT+8") - private Timestamp endtime; - - private String deviceid; - - private String eventtime; - - private String serviceid; - - private String devices; - - public String getDeviceid() { - return deviceid; - } - - public void setDeviceid(String deviceid) { - this.deviceid = deviceid; - } - - public String getEventtime() { - return eventtime; - } - - public void setEventtime(String eventtime) { - this.eventtime = eventtime; - } - - public String getServiceid() { - return serviceid; - } - - public void setServiceid(String serviceid) { - this.serviceid = serviceid; - } - - public String getDevices() { - return devices; - } - - public void setDevices(String devices) { - this.devices = devices; - } - - public Timestamp getStatetime() { - return statetime; - } - - public void setStatetime(Timestamp statetime) { - this.statetime = statetime; - } - - public Timestamp getEndtime() { - return endtime; - } - - public void setEndtime(Timestamp endtime) { - this.endtime = endtime; - } -} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/MessageCountVo.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/MessageCountVo.java deleted file mode 100644 index e9e93cac0..000000000 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/MessageCountVo.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.iocoder.yudao.module.iot.domain; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -/** - * 统计的时间数据 - */ -@Data -@NoArgsConstructor -@AllArgsConstructor -public class MessageCountVo { - - /** - * 时间 - */ - private String time; - - /** - * 数据值 - */ - private Object data; - -} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/ProductSuperTableModel.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/ProductSuperTableModel.java deleted file mode 100644 index c5989811f..000000000 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/ProductSuperTableModel.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.module.iot.domain; - -import com.fasterxml.jackson.annotation.JsonFormat; -import lombok.Data; - -import java.sql.Timestamp; -import java.util.HashMap; -import java.util.Optional; - -@Data -public class ProductSuperTableModel { - private static final long serialVersionUID = 1L; - - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS", timezone = "GMT+8") - private Timestamp ts; - - private String superTableName; - - /** - * columnsName,columnsProperty - */ - private HashMap columns; - - /** - * tagsName,tagsProperty - */ - private HashMap tags; - -} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SelectDto.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SelectDto.java deleted file mode 100644 index c20e5ab5e..000000000 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SelectDto.java +++ /dev/null @@ -1,30 +0,0 @@ -package cn.iocoder.yudao.module.iot.domain; - -import lombok.Data; - -import java.util.Set; - -@Data -public class SelectDto { - - // @NotBlank(message = "invalid operation: dataBaseName can not be empty") - private String dataBaseName; - -// @NotBlank(message = "invalid operation: tableName can not be empty") - private String tableName; - - // @NotBlank(message = "invalid operation: fieldName can not be empty") - private String fieldName; - - // @NotNull(message = "invalid operation: startTime can not be null") - private Long startTime; - - // @NotNull(message = "invalid operation: endTime can not be null") - private Long endTime; - - private String type; - - private Set orgIds; - - private String deviceId; -} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SuperTableDto.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SuperTableDto.java deleted file mode 100644 index a15f135cf..000000000 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/SuperTableDto.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.module.iot.domain; - -import lombok.Data; - -import java.util.List; - -@Data -public class SuperTableDto extends BaseEntity { - - /** - * 超级表的表结构(业务相关) - * 第一个字段的数据类型必须为timestamp - * 字符相关数据类型必须指定大小 - * 字段名称和字段数据类型不能为空 - */ -// @NotEmpty(message = "invalid operation: schemaFields can not be empty") - private List schemaFields; - - /** - * 超级表的标签字段,可以作为子表在超级表里的标识 - * 字符相关数据类型必须指定大小 - * 字段名称和字段数据类型不能为空 - */ -// @NotEmpty(message = "invalid operation: tagsFields can not be empty") - private List tagsFields; - - /** - * 字段信息对象,超级表添加列时使用该属性 - */ - private Fields fields; -} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TableDto.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TableDto.java deleted file mode 100644 index 5ffe9f84e..000000000 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TableDto.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.iot.domain; - -import lombok.Data; - -import java.util.List; - -@Data -public class TableDto extends BaseEntity { - - /** - * 超级表普通列字段的值 - * 值需要与创建超级表时普通列字段的数据类型对应上 - */ - private List schemaFieldValues; - - /** - * 超级表标签字段的值 - * 值需要与创建超级表时标签字段的数据类型对应上 - */ - private List tagsFieldValues; - - /** - * 表名称 - */ - private String tableName; -} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TagsSelectDao.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TagsSelectDao.java deleted file mode 100644 index 8833b0b50..000000000 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/TagsSelectDao.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.iocoder.yudao.module.iot.domain; - -import lombok.Data; - - -@Data -public class TagsSelectDao { - - // @NotBlank(message = "invalid operation: dataBaseName can not be empty") - private String dataBaseName; - - // @NotBlank(message = "invalid operation: stableName can not be empty") - private String stableName; - - // @NotBlank(message = "invalid operation: tagsName can not be empty") - private String tagsName; - - // @NotNull(message = "invalid operation: startTime can not be null") - private Long startTime; - - // @NotNull(message = "invalid operation: endTime can not be null") - private Long endTime; - - -} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/Weather.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/Weather.java deleted file mode 100644 index a4a1e983b..000000000 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/Weather.java +++ /dev/null @@ -1,73 +0,0 @@ -package cn.iocoder.yudao.module.iot.domain; - -import com.fasterxml.jackson.annotation.JsonFormat; - -import java.sql.Timestamp; - -public class Weather { - - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS" , timezone = "GMT+8") - private Timestamp ts; - private Float temperature; - private Float humidity; - private String location; - private String note; - private int groupId; - - public Weather() { - } - - public Weather(Timestamp ts, float temperature, float humidity) { - this.ts = ts; - this.temperature = temperature; - this.humidity = humidity; - } - - public Timestamp getTs() { - return ts; - } - - public void setTs(Timestamp ts) { - this.ts = ts; - } - - public Float getTemperature() { - return temperature; - } - - public void setTemperature(Float temperature) { - this.temperature = temperature; - } - - public Float getHumidity() { - return humidity; - } - - public void setHumidity(Float humidity) { - this.humidity = humidity; - } - - public String getLocation() { - return location; - } - - public void setLocation(String location) { - this.location = location; - } - - public int getGroupId() { - return groupId; - } - - public void setGroupId(int groupId) { - this.groupId = groupId; - } - - public String getNote() { - return note; - } - - public void setNote(String note) { - this.note = note; - } -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java new file mode 100644 index 000000000..503b26310 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; + +import lombok.Data; + +import java.util.Set; +/** + * 查询DO + */ +@Data +public class SelectDO { + + /** + * 数据库名称 + */ + private String dataBaseName; + + /** + * 超级表名称 + */ + private String tableName; + + /** + * 查询字段 + */ + private String fieldName; + + /** + * 开始时间 + */ + private Long startTime; + + /** + * 结束时间 + */ + private Long endTime; + + /** + * 查询类型 + */ + private String type; + + /** + * 查询条件 + */ + private Set orgIds; + + /** + * 设备ID + */ + private String deviceId; +} diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/visual/SelectVisualDto.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java similarity index 90% rename from yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/visual/SelectVisualDto.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java index 071c76303..d5faf45a9 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/visual/SelectVisualDto.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.module.iot.domain.visual; +package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; import lombok.Data; import java.util.Map; @Data -public class SelectVisualDto { +public class SelectVisualDO { /** * 数据库名称 diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableDO.java deleted file mode 100644 index 11751ff64..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableDO.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; - -import cn.iocoder.yudao.module.iot.domain.BaseEntity; -import lombok.Data; - -import java.util.List; - -@Data -public class TableDO extends BaseEntity { - - /** - * 超级表普通列字段的值 - * 值需要与创建超级表时普通列字段的数据类型对应上 - */ - private List schemaFieldValues; - - /** - * 超级表标签字段的值 - * 值需要与创建超级表时标签字段的数据类型对应上 - */ - private List tagsFieldValues; - - /** - * 表名称 - */ - private String tableName; -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java deleted file mode 100644 index dfb3ed212..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableData.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; - -import lombok.Data; - -import java.util.List; - -/** - * TableData 类用于存储和操作 TDengine 表数据 - */ -@Data -public class TableData { - - /** - * 超级表普通列字段的名称 - */ - private List schemaFieldList; - - /** - * 超级表普通列字段的值 - * 值需要与创建超级表时普通列字段的数据类型对应上 - */ - private List schemaValueList; - - /** - * 超级表标签字段的名称 - */ - private List tagsFieldList; - - /** - * 超级表标签字段的值 - * 值需要与创建超级表时标签字段的数据类型对应上 - */ - private List tagsValueList; - - /** - * 表名称 - */ - private String tableName; - - /** - * 超级表名称 - */ - private String superTableName; -} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TagsSelectDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TagsSelectDO.java new file mode 100644 index 000000000..9fae91599 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TagsSelectDO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; + +import lombok.Data; + +/** + * tags查询DO + */ +@Data +public class TagsSelectDO { + + /** + * 数据库名称 + */ + private String dataBaseName; + + /** + * 超级表名称 + */ + private String stableName; + + /** + * tags名称 + */ + private String tagsName; + + /** + * tags值 + */ + private Long startTime; + + /** + * tags值 + */ + private Long endTime; + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdFieldDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdFieldDO.java index 765652748..2e1751509 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdFieldDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdFieldDO.java @@ -19,11 +19,6 @@ public class TdFieldDO { */ private String fieldName; - /** - * 字段值 - */ - private Object fieldValue; - /** * 字段类型 */ @@ -34,6 +29,11 @@ public class TdFieldDO { */ private Integer dataLength = 0; + /** + * 字段值 + */ + private Object fieldValue; + public TdFieldDO(String fieldName, String dataType, Integer dataLength) { this.fieldName = fieldName; this.dataType = dataType; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdTableDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdTableDO.java new file mode 100644 index 000000000..314c51de3 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdTableDO.java @@ -0,0 +1,65 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * TD 引擎的数据库 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TdTableDO { + + /** + * 数据库名称 + */ + private String dataBaseName; + + /** + * 超级表名称 + */ + private String superTableName; + + /** + * 表名称 + */ + private String tableName; + + /** + * COLUMN 字段 + */ + private TdFieldDO column; + + /** + * TAG 字段 + */ + private TdFieldDO tag; + + /** + * COLUMN 字段 - 列表 + */ + private List columns; + + /** + * TAG 字段 - 列表 + */ + private List tags; + + public TdTableDO(String dataBaseName, String superTableName, List columns, List tags) { + this.dataBaseName = dataBaseName; + this.superTableName = superTableName; + this.columns = columns; + this.tags = tags; + } + + public TdTableDO(String dataBaseName, String superTableName) { + this.dataBaseName = dataBaseName; + this.superTableName = superTableName; + } +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDataWriterMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDataWriterMapper.java new file mode 100644 index 000000000..51f4229a0 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDataWriterMapper.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.iot.dal.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import org.apache.ibatis.annotations.Mapper; + +/** + * TD 引擎的数据写入 Mapper + */ +@Mapper +@DS("tdengine") +public interface TdEngineDataWriterMapper { + + /** + * 插入数据 - 指定列插入数据 + * + * @param table 数据 + * dataBaseName 数据库名 + * tableName 表名 + * columns 列 + */ + @InterceptorIgnore(tenantLine = "true") + void insertData(TdTableDO table); +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java new file mode 100644 index 000000000..bc562ccca --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.iot.dal.tdengine; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * TD 引擎的数据库 Mapper + */ +@Mapper +@DS("tdengine") +public interface TdEngineDatabaseMapper { + + /** + * 创建数据库 + * SQL:CREATE DATABASE [IF NOT EXISTS] db_name [database_options]; + * + * @param dataBaseName 数据库名称 + */ + @InterceptorIgnore(tenantLine = "true") + void createDatabase(@Param("dataBaseName") String dataBaseName); +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java deleted file mode 100644 index c126946f1..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java +++ /dev/null @@ -1,129 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; -import cn.iocoder.yudao.module.iot.domain.FieldsVo; -import cn.iocoder.yudao.module.iot.domain.SelectDto; -import cn.iocoder.yudao.module.iot.domain.TagsSelectDao; -import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; -import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -import java.util.List; -import java.util.Map; - -@Mapper -@DS("tdengine") -public interface TdEngineMapper { - - /** - * 创建数据库 - * - * @param dataBaseName 数据库名称 - */ - @InterceptorIgnore(tenantLine = "true") - void createDatabase(@Param("dataBaseName") String dataBaseName); - - /** - * 创建超级表 - * - * @param schemaFields schema字段 - * @param tagsFields tags字段 - * @param dataBaseName 数据库名称 - * @param superTableName 超级表名称 - */ - @InterceptorIgnore(tenantLine = "true") - void createSuperTable(@Param("schemaFields") List schemaFields, - @Param("tagsFields") List tagsFields, - @Param("dataBaseName") String dataBaseName, - @Param("superTableName") String superTableName); - - /** - * 查看超级表 - 显示当前数据库下的所有超级表信息 - * SQL:SHOW STABLES [LIKE tb_name_wildcard]; - * - * @param dataBaseName 数据库名称 - * @param superTableName 超级表名称 - */ - @InterceptorIgnore(tenantLine = "true") - List> showSuperTables(@Param("dataBaseName") String dataBaseName, - @Param("superTableName") String superTableName); - - /** - * 查看超级表 - 获取超级表的结构信息 - * SQL:DESCRIBE [db_name.]stb_name; - * - * * @param dataBaseName 数据库名称 - * * @param superTableName 超级表名称 - */ - @InterceptorIgnore(tenantLine = "true") - List> describeSuperTable(@Param("dataBaseName") String dataBaseName, - @Param("superTableName") String superTableName); - - /** - * 为超级表添加列 - * - * @param dataBaseName 数据库名称 - * @param superTableName 超级表名称 - * @param field 字段信息 - */ - @InterceptorIgnore(tenantLine = "true") - void addColumnForSuperTable(@Param("dataBaseName") String dataBaseName, - @Param("superTableName") String superTableName, - @Param("field") TdFieldDO field); - - /** - * 为超级表删除列 - * - * @param dataBaseName 数据库名称 - * @param superTableName 超级表名称 - * @param field 字段信息 - */ - @InterceptorIgnore(tenantLine = "true") - void dropColumnForSuperTable(@Param("dataBaseName") String dataBaseName, - @Param("superTableName") String superTableName, - @Param("field") TdFieldDO field); - - /** - * 创建表 - 创建超级表的子表 - * - * @param tableDO 表信息 - */ - @InterceptorIgnore(tenantLine = "true") - void createTable(TableDO tableDO); - - /** - * 插入数据 - 指定列插入数据 - * - * @param tableDto 数据 - */ - @InterceptorIgnore(tenantLine = "true") - void insertData(TableDO tableDto); - - List> selectByTimestamp(SelectDto selectDto); - - - void addTagForSuperTable(@Param("superTableName") String superTableName, - @Param("fieldsVo") FieldsVo fieldsVo); - - void dropTagForSuperTable(@Param("superTableName") String superTableName, - @Param("fieldsVo") FieldsVo fieldsVo); - - Map getCountByTimestamp(SelectDto selectDto); - - Map getLastData(SelectDto selectDto); - - @InterceptorIgnore(tenantLine = "true") - List> getHistoryData(SelectVisualDto selectVisualDto); - - List> getRealtimeData(SelectVisualDto selectVisualDto); - - List> getAggregateData(SelectVisualDto selectVisualDto); - - List> getLastDataByTags(TagsSelectDao tagsSelectDao); - - @InterceptorIgnore(tenantLine = "true") - Long getHistoryCount(SelectVisualDto selectVisualDto); -} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java new file mode 100644 index 000000000..e5353f7ee --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.iot.dal.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TagsSelectDO; +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; +import java.util.Map; + +/** + * TD 引擎的查询 Mapper + */ +@Mapper +@DS("tdengine") +public interface TdEngineQueryMapper { + + /** + * 根据时间戳查询数据 + * + * @param selectDO 查询条件 + * @return 查询结果 + */ + List> selectByTimestamp(SelectDO selectDO); + + /** + * 根据时间戳获取数据条数 + * + * @param selectDO 查询条件 + * @return 数据条数 + */ + Map getCountByTimestamp(SelectDO selectDO); + + /** + * 获取最新数据 + * + * @param selectDO 查询条件 + * @return 最新数据 + */ + Map getLastData(SelectDO selectDO); + + /** + * 获取历史数据 + * + * @param selectVisualDO 查询条件 + * @return 历史数据列表 + */ + @InterceptorIgnore(tenantLine = "true") + List> getHistoryData(SelectVisualDO selectVisualDO); + + /** + * 获取实时数据 + * + * @param selectVisualDO 查询条件 + * @return 实时数据列表 + */ + List> getRealtimeData(SelectVisualDO selectVisualDO); + + /** + * 获取聚合数据 + * + * @param selectVisualDO 查询条件 + * @return 聚合数据列表 + */ + List> getAggregateData(SelectVisualDO selectVisualDO); + + /** + * 根据标签获取最新数据 + * + * @param tagsSelectDO 查询条件 + * @return 最新数据列表 + */ + List> getLastDataByTags(TagsSelectDO tagsSelectDO); + + /** + * 获取历史数据条数 + * + * @param selectVisualDO 查询条件 + * @return 数据条数 + */ + @InterceptorIgnore(tenantLine = "true") + Long getHistoryCount(SelectVisualDO selectVisualDO); +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineSuperTableMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineSuperTableMapper.java new file mode 100644 index 000000000..e688563d5 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineSuperTableMapper.java @@ -0,0 +1,111 @@ +package cn.iocoder.yudao.module.iot.dal.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; +import java.util.Map; + +/** + * TD 引擎的超级表 Mapper + */ +@Mapper +@DS("tdengine") +public interface TdEngineSuperTableMapper { + + /** + * 创建超级表 + * SQL:CREATE STABLE [IF NOT EXISTS] stb_name (create_definition [, create_definition] ...) TAGS (create_definition [, create_definition] ...) [table_options]; + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * columns 列信息 + * tags 标签信息 + */ + @InterceptorIgnore(tenantLine = "true") + void createSuperTable(TdTableDO superTable); + + /** + * 查看超级表 - 显示当前数据库下的所有超级表信息 + * SQL:SHOW STABLES [LIKE tb_name_wildcard]; + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + */ + @InterceptorIgnore(tenantLine = "true") + List> showSuperTables(TdTableDO superTable); + + /** + * 查看超级表 - 获取超级表的结构信息 + * SQL:DESCRIBE [db_name.]stb_name; + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + */ + @InterceptorIgnore(tenantLine = "true") + List> describeSuperTable(TdTableDO superTable); + + /** + * 修改超级表 - 增加列 + * SQL:ALTER STABLE stb_name ADD COLUMN col_name column_type; + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * column 列信息 + */ + @InterceptorIgnore(tenantLine = "true") + void addColumnForSuperTable(TdTableDO superTable); + + /** + * 修改超级表 - 删除列 + * SQL:ALTER STABLE stb_name DROP COLUMN col_name; + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * column 列信息 + */ + @InterceptorIgnore(tenantLine = "true") + void dropColumnForSuperTable(TdTableDO superTable); + + /** + * 修改超级表 - 修改列宽 + * SQL:ALTER STABLE stb_name MODIFY COLUMN col_name data_type(length); + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * column 列信息 + */ + @InterceptorIgnore(tenantLine = "true") + void modifyColumnWidthForSuperTable(TdTableDO superTable); + + + /** + * 修改超级表 - 为超级表添加标签 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tag 标签信息 + */ + @InterceptorIgnore(tenantLine = "true") + void addTagForSuperTable(TdTableDO superTable); + + /** + * 修改超级表 - 为超级表删除标签 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tag 标签信息 + */ + @InterceptorIgnore(tenantLine = "true") + void dropTagForSuperTable(TdTableDO superTable); +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java new file mode 100644 index 000000000..72517bcab --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.iot.dal.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import org.apache.ibatis.annotations.Mapper; + +/** + * TD 引擎的表 Mapper + */ +@Mapper +@DS("tdengine") +public interface TdEngineTableMapper { + + /** + * 创建子表 - 创建子表 + * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name TAGS (tag_value1, ...); + * + * @param table 表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tableName 子表名称 + * tags TAG 字段 + */ + @InterceptorIgnore(tenantLine = "true") + void createTable(TdTableDO table); + + /** + * 创建子表 - 创建子表并指定标签的值 + * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name (tag_name1, ...) TAGS (tag_value1, ...); + * + * @param table 表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tableName 子表名称 + * tags TAG 字段 + */ + @InterceptorIgnore(tenantLine = "true") + void createTableWithTags(TdTableDO table); + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java index 1b44bd5d0..4179075df 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java @@ -6,13 +6,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineMapper; -import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import cn.iocoder.yudao.module.iot.service.tdengine.IotThingModelMessageService; +import cn.iocoder.yudao.module.iot.service.tdengine.TdEngineQueryService; import cn.iocoder.yudao.module.iot.service.thinkmodelfunction.IotThinkModelFunctionService; import jakarta.annotation.Resource; import jakarta.validation.Valid; @@ -39,13 +39,12 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { private IotThingModelMessageService thingModelMessageService; @Resource private IotThinkModelFunctionService thinkModelFunctionService; + @Resource + private TdEngineQueryService tdEngineQueryService; @Resource private DeviceDataRedisDAO deviceDataRedisDAO; - @Resource - private TdEngineMapper tdEngineMapper; - @Override public void saveDeviceData(String productKey, String deviceName, String message) { // 1. 根据产品 key 和设备名称,获得设备信息 @@ -112,18 +111,18 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { // 1. 获取设备信息 IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId()); // 2. 获取设备属性历史数据 - SelectVisualDto selectVisualDto = new SelectVisualDto(); - selectVisualDto.setDataBaseName(getDatabaseName()); - selectVisualDto.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())); - selectVisualDto.setFieldName(deviceDataReqVO.getIdentifier()); - selectVisualDto.setStartTime(DateUtil.date(deviceDataReqVO.getTimes()[0].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime()); - selectVisualDto.setEndTime(DateUtil.date(deviceDataReqVO.getTimes()[1].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime()); + SelectVisualDO selectVisualDO = new SelectVisualDO(); + selectVisualDO.setDataBaseName(getDatabaseName()); + selectVisualDO.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())); + selectVisualDO.setFieldName(deviceDataReqVO.getIdentifier()); + selectVisualDO.setStartTime(DateUtil.date(deviceDataReqVO.getTimes()[0].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime()); + selectVisualDO.setEndTime(DateUtil.date(deviceDataReqVO.getTimes()[1].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime()); Map params = new HashMap<>(); params.put("rows", deviceDataReqVO.getPageSize()); params.put("page", (deviceDataReqVO.getPageNo() - 1) * deviceDataReqVO.getPageSize()); - selectVisualDto.setParams(params); - pageResult.setList(tdEngineMapper.getHistoryData(selectVisualDto)); - pageResult.setTotal(tdEngineMapper.getHistoryCount(selectVisualDto)); + selectVisualDO.setParams(params); + pageResult.setList(tdEngineQueryService.getHistoryData(selectVisualDO)); + pageResult.setTotal(tdEngineQueryService.getHistoryCount(selectVisualDO)); return pageResult; } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java similarity index 50% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataService.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java index 42439e25a..7c88b83aa 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java @@ -1,26 +1,15 @@ package cn.iocoder.yudao.module.iot.service.tdengine; -import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelRespVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import java.util.List; /** - * 数据结构接口 + * IoT 超级表服务,负责根据物模型创建和更新超级表,以及创建超级表的子表等操作。 */ -public interface IotDbStructureDataService { - - /** - * 创建物模型定义 - */ - void createSuperTable(ThingModelRespVO thingModel, Integer deviceType); - - /** - * 更新物模型定义 - */ - void updateSuperTable(ThingModelRespVO thingModel, Integer deviceType); +public interface IotSuperTableService { /** * 创建超级表数据模型 diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableServiceImpl.java similarity index 55% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableServiceImpl.java index 947178102..3be324c4e 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableServiceImpl.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingMode import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import jakarta.annotation.Resource; @@ -17,135 +18,19 @@ import org.springframework.stereotype.Service; import java.util.*; import java.util.stream.Collectors; +/** + * IoT 超级表服务实现类,负责根据物模型创建和更新超级表,以及创建超级表的子表等操作。 + */ @Service @Slf4j -public class IotDbStructureDataServiceImpl implements IotDbStructureDataService { +public class IotSuperTableServiceImpl implements IotSuperTableService { @Resource - private IotTdEngineService iotTdEngineService; + private TdEngineSuperTableService tdEngineSuperTableService; @Value("${spring.datasource.dynamic.datasource.tdengine.url}") private String url; - @Override - public void createSuperTable(ThingModelRespVO thingModel, Integer deviceType) { - // 1. 解析物模型,获得字段列表 - List schemaFields = new ArrayList<>(); - schemaFields.add(TdFieldDO.builder() - .fieldName("time") - .dataType("TIMESTAMP") - .build()); - schemaFields.addAll(FieldParser.parse(thingModel)); - - // 3. 设置超级表的标签 - List tagsFields = Arrays.asList( - TdFieldDO.builder().fieldName("product_key").dataType("NCHAR").dataLength(64).build(), - TdFieldDO.builder().fieldName("device_key").dataType("NCHAR").dataLength(64).build(), - TdFieldDO.builder().fieldName("device_name").dataType("NCHAR").dataLength(64).build(), - TdFieldDO.builder().fieldName("device_type").dataType("INT").build() - ); - - // 4. 获取超级表的名称 - String superTableName = getProductPropertySTableName(deviceType, thingModel.getProductKey()); - - // 5. 创建超级表 - String dataBaseName = getDatabaseName(); - iotTdEngineService.createSuperTable(schemaFields, tagsFields, dataBaseName, superTableName); - } - - @Override - public void updateSuperTable(ThingModelRespVO thingModel, Integer deviceType) { - try { - String tbName = getProductPropertySTableName(deviceType, thingModel.getProductKey()); - List oldFields = getTableFields(tbName); - List newFields = FieldParser.parse(thingModel); - - updateTableFields(tbName, oldFields, newFields); - } catch (Exception e) { - log.error("更新物模型超级表失败", e); - } - } - - // 获取表字段 - private List getTableFields(String tableName) { - List fields = new ArrayList<>(); - // 获取超级表的描述信息 - List> maps = iotTdEngineService.describeSuperTable(getDatabaseName(), tableName); - if (maps != null) { - // 过滤掉 note 字段为 TAG 的记录和 time 字段 - List> filteredMaps = maps.stream() - .filter(map -> !"TAG".equals(map.get("note"))) - .filter(map -> !"time".equals(map.get("field"))) - .toList(); - // 解析字段信息 - fields = FieldParser.parse(filteredMaps.stream() - .map(map -> List.of(map.get("field"), map.get("type"), map.get("length"))) - .collect(Collectors.toList())); - } - return fields; - } - - // 更新表字段 - private void updateTableFields(String tableName, List oldFields, List newFields) { - // 获取新增字段 - List addFields = getAddFields(oldFields, newFields); - // 获取修改字段 - List modifyFields = getModifyFields(oldFields, newFields); - // 获取删除字段 - List dropFields = getDropFields(oldFields, newFields); - - String dataBaseName = getDatabaseName(); - // 添加新增字段 - if (CollUtil.isNotEmpty(addFields)) { - iotTdEngineService.addColumnForSuperTable(dataBaseName, tableName, addFields); - } - // 删除旧字段 - if (CollUtil.isNotEmpty(dropFields)) { - iotTdEngineService.dropColumnForSuperTable(dataBaseName, tableName, dropFields); - } - // 修改字段(先删除再添加) - if (CollUtil.isNotEmpty(modifyFields)) { - iotTdEngineService.dropColumnForSuperTable(dataBaseName, tableName, modifyFields); - iotTdEngineService.addColumnForSuperTable(dataBaseName, tableName, modifyFields); - } - } - - // 获取新增字段 - private List getAddFields(List oldFields, List newFields) { - Set oldFieldNames = oldFields.stream() - .map(TdFieldDO::getFieldName) - .collect(Collectors.toSet()); - return newFields.stream() - .filter(f -> !oldFieldNames.contains(f.getFieldName())) - .collect(Collectors.toList()); - } - - // 获取修改字段 - private List getModifyFields(List oldFields, List newFields) { - Map oldFieldMap = oldFields.stream() - .collect(Collectors.toMap(TdFieldDO::getFieldName, f -> f)); - - return newFields.stream() - .filter(f -> { - TdFieldDO oldField = oldFieldMap.get(f.getFieldName()); - return oldField != null && - (!oldField.getDataType().equals(f.getDataType()) || - !Objects.equals(oldField.getDataLength(), f.getDataLength())); - }) - .collect(Collectors.toList()); - } - - // 获取删除字段 - private List getDropFields(List oldFields, List newFields) { - Set newFieldNames = newFields.stream() - .map(TdFieldDO::getFieldName) - .collect(Collectors.toSet()); - return oldFields.stream() - .filter(f -> !"time".equals(f.getFieldName()) && !"device_id".equals(f.getFieldName())) - .filter(f -> !newFieldNames.contains(f.getFieldName())) - .collect(Collectors.toList()); - } - @Override public void createSuperTableDataModel(IotProductDO product, List functionList) { ThingModelRespVO thingModel = buildThingModel(product, functionList); @@ -155,9 +40,9 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService return; } - String superTableName = getProductPropertySTableName(product.getDeviceType(), product.getProductKey()); - String dataBaseName = getDatabaseName(); - Integer tableExists = iotTdEngineService.checkSuperTableExists(dataBaseName, superTableName); + String superTableName = getSuperTableName(product.getDeviceType(), product.getProductKey()); + String databaseName = getDatabaseName(); + Integer tableExists = tdEngineSuperTableService.checkSuperTableExists(new TdTableDO(databaseName, superTableName)); if (tableExists != null && tableExists > 0) { updateSuperTable(thingModel, product.getDeviceType()); @@ -166,40 +51,202 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService } } + /** + * 创建超级表 + */ + private void createSuperTable(ThingModelRespVO thingModel, Integer deviceType) { + // 解析物模型,获取字段列表 + List schemaFields = new ArrayList<>(); + schemaFields.add(TdFieldDO.builder() + .fieldName("time") + .dataType("TIMESTAMP") + .build()); + schemaFields.addAll(FieldParser.parse(thingModel)); + + // 设置超级表的标签 + List tagsFields = List.of( + TdFieldDO.builder().fieldName("product_key").dataType("NCHAR").dataLength(64).build(), + TdFieldDO.builder().fieldName("device_key").dataType("NCHAR").dataLength(64).build(), + TdFieldDO.builder().fieldName("device_name").dataType("NCHAR").dataLength(64).build(), + TdFieldDO.builder().fieldName("device_type").dataType("INT").build() + ); + + // 获取超级表的名称和数据库名称 + String superTableName = getSuperTableName(deviceType, thingModel.getProductKey()); + String databaseName = getDatabaseName(); + + // 创建超级表 + tdEngineSuperTableService.createSuperTable(new TdTableDO(databaseName, superTableName, schemaFields, tagsFields)); + } + + /** + * 更新超级表 + */ + private void updateSuperTable(ThingModelRespVO thingModel, Integer deviceType) { + String superTableName = getSuperTableName(deviceType, thingModel.getProductKey()); + try { + List oldFields = getTableFields(superTableName); + List newFields = FieldParser.parse(thingModel); + + updateTableFields(superTableName, oldFields, newFields); + } catch (Exception e) { + log.error("更新物模型超级表失败: {}", e.getMessage(), e); + } + } + + /** + * 获取表的字段信息 + */ + private List getTableFields(String tableName) { + List> tableDescription = tdEngineSuperTableService.describeSuperTable(new TdTableDO(getDatabaseName(), tableName)); + if (CollUtil.isEmpty(tableDescription)) { + return Collections.emptyList(); + } + + return tableDescription.stream() + .filter(map -> !"TAG".equals(map.get("note"))) + .filter(map -> !"time".equals(map.get("field"))) + .map(map -> TdFieldDO.builder() + .fieldName((String) map.get("field")) + .dataType((String) map.get("type")) + .dataLength((Integer) map.get("length")) + .build()) + .collect(Collectors.toList()); + } + + /** + * 更新表的字段,包括新增、修改和删除字段 + */ + private void updateTableFields(String tableName, List oldFields, List newFields) { + String databaseName = getDatabaseName(); + + // 获取新增、修改、删除的字段 + List addFields = getAddFields(oldFields, newFields); + List modifyFields = getModifyFields(oldFields, newFields); + List dropFields = getDropFields(oldFields, newFields); + + // 添加新增字段 + if (CollUtil.isNotEmpty(addFields)) { + tdEngineSuperTableService.addColumnsForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .columns(addFields) + .build()); + } + // 删除旧字段 + if (CollUtil.isNotEmpty(dropFields)) { + tdEngineSuperTableService.dropColumnsForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .columns(dropFields) + .build()); + } + // 修改字段(先删除再添加) + if (CollUtil.isNotEmpty(modifyFields)) { + tdEngineSuperTableService.dropColumnsForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .columns(modifyFields) + .build()); + tdEngineSuperTableService.addColumnsForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .columns(addFields) + .build()); + } + } + + /** + * 获取需要新增的字段 + */ + private List getAddFields(List oldFields, List newFields) { + Set oldFieldNames = oldFields.stream() + .map(TdFieldDO::getFieldName) + .collect(Collectors.toSet()); + return newFields.stream() + .filter(f -> !oldFieldNames.contains(f.getFieldName())) + .collect(Collectors.toList()); + } + + /** + * 获取需要修改的字段 + */ + private List getModifyFields(List oldFields, List newFields) { + Map oldFieldMap = oldFields.stream() + .collect(Collectors.toMap(TdFieldDO::getFieldName, f -> f)); + + return newFields.stream() + .filter(f -> { + TdFieldDO oldField = oldFieldMap.get(f.getFieldName()); + return oldField != null && ( + !oldField.getDataType().equals(f.getDataType()) || + !Objects.equals(oldField.getDataLength(), f.getDataLength()) + ); + }) + .collect(Collectors.toList()); + } + + /** + * 获取需要删除的字段 + */ + private List getDropFields(List oldFields, List newFields) { + Set newFieldNames = newFields.stream() + .map(TdFieldDO::getFieldName) + .collect(Collectors.toSet()); + return oldFields.stream() + .filter(f -> !"time".equals(f.getFieldName())) + .filter(f -> !newFieldNames.contains(f.getFieldName())) + .collect(Collectors.toList()); + } + + /** + * 构建物模型 + */ private ThingModelRespVO buildThingModel(IotProductDO product, List functionList) { ThingModelRespVO thingModel = new ThingModelRespVO(); thingModel.setId(product.getId()); thingModel.setProductKey(product.getProductKey()); - ThingModelRespVO.Model model = new ThingModelRespVO.Model(); List properties = functionList.stream() .filter(function -> IotProductFunctionTypeEnum.PROPERTY.equals( IotProductFunctionTypeEnum.valueOfType(function.getType()))) .map(this::buildThingModelProperty) .collect(Collectors.toList()); + ThingModelRespVO.Model model = new ThingModelRespVO.Model(); model.setProperties(properties); thingModel.setModel(model); return thingModel; } + /** + * 构建物模型属性 + */ private ThingModelProperty buildThingModelProperty(IotThinkModelFunctionDO function) { ThingModelProperty property = BeanUtil.copyProperties(function, ThingModelProperty.class); property.setDataType(function.getProperty().getDataType()); return property; } + /** + * 获取数据库名称 + */ private String getDatabaseName() { - return url.substring(url.lastIndexOf("/") + 1); + int index = url.lastIndexOf("/"); + return index != -1 ? url.substring(index + 1) : url; } - static String getProductPropertySTableName(Integer deviceType, String productKey) { - return switch (deviceType) { - case 1 -> String.format("gateway_sub_%s", productKey).toLowerCase(); - case 2 -> String.format("gateway_%s", productKey).toLowerCase(); - default -> String.format("device_%s", productKey).toLowerCase(); + /** + * 获取超级表名称 + */ + private String getSuperTableName(Integer deviceType, String productKey) { + String prefix = switch (deviceType) { + case 1 -> "gateway_sub_"; + case 2 -> "gateway_"; + default -> "device_"; }; + return (prefix + productKey).toLowerCase(); } } \ 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/tdengine/IotTdEngineService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineService.java deleted file mode 100644 index 753284aca..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineService.java +++ /dev/null @@ -1,142 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; -import cn.iocoder.yudao.module.iot.domain.SelectDto; -import cn.iocoder.yudao.module.iot.domain.TagsSelectDao; -import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; - -import java.util.List; -import java.util.Map; - -/** - * TdEngineService - */ -public interface IotTdEngineService { - - /** - * 创建数据库 - * - * @param dataBaseName 数据库名称 - * @throws Exception 异常 - */ - void createDateBase(String dataBaseName) throws Exception; - - /** - * 创建超级表 - * - * @param schemaFields schema字段 - * @param tagsFields tags字段 - * @param superTableName 超级表名称 - */ - void createSuperTable(List schemaFields, List tagsFields, String dataBaseName, String superTableName); - - /** - * 检查超级表是否存在 - */ - Integer checkSuperTableExists(String dataBaseName, String superTableName); - - - /** - * 获取超级表的结构信息 - */ - List> describeSuperTable(String dataBaseName, String superTableName); - - /** - * 为超级表添加列 - * - * @param dataBaseName 数据库名称 - * @param superTableName 超级表名称 - * @param fieldsVo 字段信息 - */ - void addColumnForSuperTable(String dataBaseName, String superTableName, List fieldsVo); - - /** - * 为超级表删除列 - * - * @param dataBaseName 数据库名称 - * @param superTableName 超级表名称 - * @param fieldsVo 字段信息 - */ - void dropColumnForSuperTable(String dataBaseName, String superTableName, List fieldsVo); - - /** - * 为超级表添加tag - */ - Long getCountByTimesTamp(SelectDto selectDto) throws Exception; - - - /** - * 创建表 - * - * @param tableDto 表信息 - */ - void createTable(TableDO tableDto); - - /** - * 插入数据 - * - * @param tableDto 表信息 - */ - void insertData(TableDO tableDto); - - /** - * 根据时间戳查询数据 - * - * @param selectDto 查询条件 - * @return 数据 - * @throws Exception 异常 - */ - List> selectByTimesTamp(SelectDto selectDto) throws Exception; - - /** - * 初始化超级表 - * - * @param msg 消息 - * @throws Exception 异常 - */ - void initSTableFrame(String msg) throws Exception; - - /** - * 获取最新数据 - * - * @param selectDto 查询条件 - * @return 数据 - * @throws Exception 异常 - */ - Map getLastData(SelectDto selectDto) throws Exception; - - /** - * 根据tag查询最新数据 - * - * @param tagsSelectDao 查询条件 - * @return 数据 - */ - Map> getLastDataByTags(TagsSelectDao tagsSelectDao); - - /** - * 获取历史数据 - * - * @param selectVisualDto 查询条件 - * @return 数据 - */ - List> getHistoryData(SelectVisualDto selectVisualDto); - - /** - * 获取实时数据 - * - * @param selectVisualDto 查询条件 - * @return 数据 - */ - List> getRealtimeData(SelectVisualDto selectVisualDto); - - /** - * 获取聚合数据 - * - * @param selectVisualDto 查询条件 - * @return 数据 - */ - List> getAggregateData(SelectVisualDto selectVisualDto); - - -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineServiceImpl.java deleted file mode 100644 index c7f7e7309..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineServiceImpl.java +++ /dev/null @@ -1,107 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineMapper; -import cn.iocoder.yudao.module.iot.domain.SelectDto; -import cn.iocoder.yudao.module.iot.domain.TagsSelectDao; -import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Map; - -@Service -@Slf4j -public class IotTdEngineServiceImpl implements IotTdEngineService { - - @Resource - private TdEngineMapper tdEngineMapper; - - @Override - public void createDateBase(String dataBaseName) { - tdEngineMapper.createDatabase(dataBaseName); - } - - @Override - public void createSuperTable(List schemaFields, List tagsFields, String dataBaseName, String superTableName) { - tdEngineMapper.createSuperTable(schemaFields, tagsFields, dataBaseName, superTableName); - } - - @Override - public void createTable(TableDO tableDto) { - tdEngineMapper.createTable(tableDto); - } - - @Override - public void insertData(TableDO tableDto) { - tdEngineMapper.insertData(tableDto); - } - - @Override - public List> selectByTimesTamp(SelectDto selectDto) { - return List.of(); - } - - @Override - public void addColumnForSuperTable(String dataBaseName,String superTableName, List fields) { - for (TdFieldDO field : fields) { - tdEngineMapper.addColumnForSuperTable(dataBaseName,superTableName, field); - } - } - - @Override - public void dropColumnForSuperTable(String dataBaseName,String superTableName, List fields) { - for (TdFieldDO field : fields) { - tdEngineMapper.dropColumnForSuperTable(dataBaseName,superTableName, field); - } - } - - @Override - public Long getCountByTimesTamp(SelectDto selectDto) { - return 0L; - } - - @Override - public void initSTableFrame(String msg) { - - } - - @Override - public Map getLastData(SelectDto selectDto) { - return Map.of(); - } - - @Override - public Map> getLastDataByTags(TagsSelectDao tagsSelectDao) { - return Map.of(); - } - - @Override - public List> getHistoryData(SelectVisualDto selectVisualDto) { - return List.of(); - } - - @Override - public List> getRealtimeData(SelectVisualDto selectVisualDto) { - return List.of(); - } - - @Override - public List> getAggregateData(SelectVisualDto selectVisualDto) { - return List.of(); - } - - @Override - public Integer checkSuperTableExists(String dataBaseName, String superTableName) { - List> results = tdEngineMapper.showSuperTables(dataBaseName, superTableName); - return results == null || results.isEmpty() ? 0 : results.size(); - } - - @Override - public List> describeSuperTable(String dataBaseName, String superTableName) { - return tdEngineMapper.describeSuperTable(dataBaseName, superTableName); - } -} \ 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/tdengine/IotThingModelMessageService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java index b2f51a7f8..ffcb3063c 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java @@ -11,8 +11,8 @@ public interface IotThingModelMessageService { /** * 保存物模型消息 * - * @param device 设备 + * @param device 设备 * @param thingModelMessage 物模型消息 */ - void saveThingModelMessage(IotDeviceDO device,ThingModelMessage thingModelMessage); + void saveThingModelMessage(IotDeviceDO device, ThingModelMessage thingModelMessage); } \ 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/tdengine/IotThingModelMessageServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java index 9bad7613e..69c417839 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java @@ -6,8 +6,8 @@ import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceSt import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; @@ -23,6 +23,9 @@ import org.springframework.stereotype.Service; import java.util.*; import java.util.stream.Collectors; +/** + * 物模型消息 Service 实现类 + */ @Slf4j @Service public class IotThingModelMessageServiceImpl implements IotThingModelMessageService { @@ -35,7 +38,11 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @Resource private IotDeviceService iotDeviceService; @Resource - private IotTdEngineService iotTdEngineService; + private TdEngineTableService tdEngineTableService; + @Resource + private TdEngineSuperTableService tdEngineSuperTableService; + @Resource + private TdEngineDataWriterService tdEngineDataWriterService; @Resource private DeviceDataRedisDAO deviceDataRedisDAO; @@ -90,14 +97,11 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ return; } - // 构建并保存设备属性 - TableDO tableData = new TableDO(); - tableData.setDataBaseName(getDatabaseName()); - tableData.setSuperTableName(getProductPropertySTableName(device.getDeviceType(), device.getProductKey())); - tableData.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())); - tableData.setSchemaFieldValues(schemaFieldValues); - - iotTdEngineService.insertData(tableData); + // 构建并保存设备属性数据 + tdEngineDataWriterService.insertData(TdTableDO.builder().build() + .setDataBaseName(getDatabaseName()) + .setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())) + .setColumns(schemaFieldValues)); } /** @@ -135,7 +139,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ String superTableName = getProductPropertySTableName(deviceType, productKey); String dataBaseName = getDatabaseName(); - List> maps = iotTdEngineService.describeSuperTable(dataBaseName, superTableName); + List> maps = tdEngineSuperTableService.describeSuperTable(new TdTableDO(dataBaseName, superTableName)); List tagsFieldValues = new ArrayList<>(); if (maps != null) { @@ -159,13 +163,11 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ // 创建设备数据表 String tableName = getDeviceTableName(productKey, deviceName); - TableDO tableDto = new TableDO(); - tableDto.setDataBaseName(dataBaseName); - tableDto.setSuperTableName(superTableName); - tableDto.setTableName(tableName); - tableDto.setTagsFieldValues(tagsFieldValues); - - iotTdEngineService.createTable(tableDto); + tdEngineTableService.createTable(TdTableDO.builder().build() + .setDataBaseName(dataBaseName) + .setSuperTableName(superTableName) + .setTableName(tableName) + .setTags(tagsFieldValues)); } /** diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterService.java new file mode 100644 index 000000000..0995b0797 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterService.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; + +/** + * TD 引擎的数据写入 Service 接口 + */ +public interface TdEngineDataWriterService { + + /** + * 插入数据 - 指定列插入数据 + * + * @param table 数据 + * dataBaseName 数据库名 + * tableName 表名 + * columns 列 + */ + void insertData(TdTableDO table); +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java new file mode 100644 index 000000000..f4dd2c8fd --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDataWriterMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * TD 引擎的数据写入 Service 实现类 + */ +@Service +public class TdEngineDataWriterServiceImpl implements TdEngineDataWriterService { + + @Resource + private TdEngineDataWriterMapper tdEngineDataWriterMapper; + + @Override + public void insertData(TdTableDO table) { + tdEngineDataWriterMapper.insertData(table); + } +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java new file mode 100644 index 000000000..d895262cc --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +/** + * TD 引擎的数据库 Service 接口 + */ +public interface TdEngineDatabaseService { + + /** + * 创建数据库 + * + * @param dataBaseName 数据库名称 + */ + void createDatabase(String dataBaseName); +} \ 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/tdengine/TdEngineDatabaseServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseServiceImpl.java new file mode 100644 index 000000000..c880db8a9 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseServiceImpl.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDatabaseMapper; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * TD 引擎的数据库 Service 实现类 + */ +@Service +@Slf4j +public class TdEngineDatabaseServiceImpl implements TdEngineDatabaseService { + + @Resource + private TdEngineDatabaseMapper tdEngineDatabaseMapper; + + @Override + public void createDatabase(String dataBaseName) { + tdEngineDatabaseMapper.createDatabase(dataBaseName); + } +} \ 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/tdengine/TdEngineQueryService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryService.java new file mode 100644 index 000000000..8d07b4334 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryService.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; + +import java.util.List; +import java.util.Map; + +/** + * TD 引擎的查询 Service 接口 + */ +public interface TdEngineQueryService { + + /** + * 获取历史数据 + * + * @param selectVisualDO 查询条件 + * @return 历史数据列表 + */ + List> getHistoryData(SelectVisualDO selectVisualDO); + + /** + * 获取历史数据条数 + * + * @param selectVisualDO 查询条件 + * @return 数据条数 + */ + Long getHistoryCount(SelectVisualDO selectVisualDO); +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java new file mode 100644 index 000000000..672a58640 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineQueryMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +@Service +public class TdEngineQueryServiceImpl implements TdEngineQueryService { + + @Resource + private TdEngineQueryMapper tdEngineQueryMapper; + + @Override + public List> getHistoryData(SelectVisualDO selectVisualDO) { + return tdEngineQueryMapper.getHistoryData(selectVisualDO); + } + + @Override + public Long getHistoryCount(SelectVisualDO selectVisualDO) { + return tdEngineQueryMapper.getHistoryCount(selectVisualDO); + } +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java new file mode 100644 index 000000000..df6290a98 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java @@ -0,0 +1,123 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; + +import java.util.List; +import java.util.Map; + +/** + * TD 引擎的超级表 Service 接口 + */ +public interface TdEngineSuperTableService { + + /** + * 创建超级表 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * columns 列信息 + * tags 标签信息 + */ + void createSuperTable(TdTableDO superTable); + + /** + * 查看超级表 - 显示当前数据库下的所有超级表信息 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + */ + + List> showSuperTables(TdTableDO superTable); + + /** + * 查看超级表 - 获取超级表的结构信息 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + */ + List> describeSuperTable(TdTableDO superTable); + + /** + * 修改超级表 - 增加列 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * column 列信息 + */ + void addColumnForSuperTable(TdTableDO superTable); + + /** + * 修改超级表 - 删除列 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * column 列信息 + */ + void dropColumnForSuperTable(TdTableDO superTable); + + /** + * 修改超级表 - 修改列宽 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * column 列信息 + */ + void modifyColumnWidthForSuperTable(TdTableDO superTable); + + + /** + * 修改超级表 - 为超级表添加标签 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tag 标签信息 + */ + void addTagForSuperTable(TdTableDO superTable); + + /** + * 修改超级表 - 为超级表删除标签 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tag 标签信息 + */ + void dropTagForSuperTable(TdTableDO superTable); + + /** + * 检查超级表是否存在 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * @return 超级表数量 + */ + Integer checkSuperTableExists(TdTableDO superTable); + + /** + * 为超级表添加列 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * columns 列信息 + */ + void addColumnsForSuperTable(TdTableDO superTable); + + /** + * 为超级表删除列 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * columns 列信息 + */ + void dropColumnsForSuperTable(TdTableDO superTable); +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java new file mode 100644 index 000000000..60436e7bd --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineSuperTableMapper; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +/** + * TD 引擎的超级表 Service 实现类 + */ +@Slf4j +@Service +public class TdEngineSuperTableServiceImpl implements TdEngineSuperTableService { + + @Resource + private TdEngineSuperTableMapper tdEngineSuperTableMapper; + + @Override + public void createSuperTable(TdTableDO superTable) { + tdEngineSuperTableMapper.createSuperTable(superTable); + } + + @Override + public List> showSuperTables(TdTableDO superTable) { + return tdEngineSuperTableMapper.showSuperTables(superTable); + } + + @Override + public List> describeSuperTable(TdTableDO superTable) { + return tdEngineSuperTableMapper.describeSuperTable(superTable); + } + + @Override + public void addColumnForSuperTable(TdTableDO superTable) { + tdEngineSuperTableMapper.addColumnForSuperTable(superTable); + } + + @Override + public void dropColumnForSuperTable(TdTableDO superTable) { + tdEngineSuperTableMapper.dropColumnForSuperTable(superTable); + } + + @Override + public void modifyColumnWidthForSuperTable(TdTableDO superTable) { + tdEngineSuperTableMapper.modifyColumnWidthForSuperTable(superTable); + } + + @Override + public void addTagForSuperTable(TdTableDO superTable) { + tdEngineSuperTableMapper.addTagForSuperTable(superTable); + } + + @Override + public void dropTagForSuperTable(TdTableDO superTable) { + tdEngineSuperTableMapper.dropTagForSuperTable(superTable); + } + + @Override + public Integer checkSuperTableExists(TdTableDO superTable) { + List> results = tdEngineSuperTableMapper.showSuperTables(superTable); + return results == null || results.isEmpty() ? 0 : results.size(); + } + + @Override + public void addColumnsForSuperTable(TdTableDO superTable) { + for (TdFieldDO column : superTable.getColumns()) { + tdEngineSuperTableMapper.addColumnForSuperTable(TdTableDO.builder() + .dataBaseName(superTable.getDataBaseName()) + .superTableName(superTable.getSuperTableName()) + .column(column) + .build()); + } + } + + @Override + public void dropColumnsForSuperTable(TdTableDO superTable) { + for (TdFieldDO column : superTable.getColumns()) { + tdEngineSuperTableMapper.dropColumnForSuperTable(TdTableDO.builder() + .dataBaseName(superTable.getDataBaseName()) + .superTableName(superTable.getSuperTableName()) + .column(column) + .build()); + } + } +} \ 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/tdengine/TdEngineTableService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableService.java new file mode 100644 index 000000000..078159784 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableService.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; + +/** + * TD 引擎的表 Service 接口 + */ +public interface TdEngineTableService { + + /** + * 创建表 - 创建超级表的子表 + * + * @param table 表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tableName 子表名称 + * tags TAG 字段 + */ + void createTable(TdTableDO table); + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java new file mode 100644 index 000000000..cdca47888 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineTableMapper; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * TD 引擎的表 Service 实现类 + */ +@Slf4j +@Service +public class TdEngineTableServiceImpl implements TdEngineTableService { + + @Resource + private TdEngineTableMapper tdEngineTableMapper; + + @Override + public void createTable(TdTableDO table) { + tdEngineTableMapper.createTable(table); + } +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java index a6bf7b458..f60610faf 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java @@ -75,5 +75,5 @@ public interface IotThinkModelFunctionService { * @param productKey 产品 Key * @return 产品物模型列表 */ - List getThinkModelFunctionListByProductKey(String productKey); + List getThinkModelFunctionListByProductKey(String productKey); } \ 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/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java index 25cfe7b46..404a2aaa0 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java @@ -22,7 +22,7 @@ import cn.iocoder.yudao.module.iot.enums.product.IotAccessModeEnum; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum; import cn.iocoder.yudao.module.iot.service.product.IotProductService; -import cn.iocoder.yudao.module.iot.service.tdengine.IotDbStructureDataService; +import cn.iocoder.yudao.module.iot.service.tdengine.IotSuperTableService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -52,7 +52,7 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe @Resource private IotProductService productService; @Resource - private IotDbStructureDataService dbStructureDataService; + private IotSuperTableService dbStructureDataService; @Override @Transactional(rollbackFor = Exception.class) diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml new file mode 100644 index 000000000..b5f044614 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml @@ -0,0 +1,22 @@ + + + + + + + + INSERT INTO ${dataBaseName}.${tableName} + + ${item.fieldName} + + VALUES + + #{item.fieldValue} + + + + \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml new file mode 100644 index 000000000..4d9a125db --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml @@ -0,0 +1,13 @@ + + + + + + + + CREATE DATABASE IF NOT EXISTS ${dataBaseName} + + + \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml deleted file mode 100644 index 4e127e44b..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml +++ /dev/null @@ -1,327 +0,0 @@ - - - - - - - - CREATE DATABASE IF NOT EXISTS ${dataBaseName} - - - - CREATE STABLE IF NOT EXISTS ${dataBaseName}.${superTableName} - - - ${item.fieldName} - - - - - TIMESTAMP - - - TINYINT - - - SMALLINT - - - INT - - - BIGINT - - - FLOAT - - - DOUBLE - - - BINARY - - - NCHAR - - - BOOL - - - JSON - - - - - ( - ${item.dataLength} - ) - - - TAGS - - - - ${item.fieldName} - - - - - TIMESTAMP - - - TINYINT - - - SMALLINT - - - INT - - - BIGINT - - - FLOAT - - - DOUBLE - - - BINARY - - - NCHAR - - - BOOL - - - JSON - - - - - ( - ${item.dataLength} - ) - - - - - - - CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} - USING ${dataBaseName}.${superTableName} - - ${item.fieldName} - - TAGS - - #{item.fieldValue} - - - - - - INSERT INTO ${dataBaseName}.${tableName} - - ${item.fieldName} - - VALUES - - #{item.fieldValue} - - - - - select * from #{dataBaseName}.#{tableName} - - - where ${fieldName} - between #{startTime} and #{endTime} - - - - ALTER STABLE ${dataBaseName}.${superTableName} ADD COLUMN - - #{field.fieldName} - - - - - TIMESTAMP - - - TINYINT - - - SMALLINT - - - INT - - - BIGINT - - - FLOAT - - - DOUBLE - - - BINARY - - - NCHAR - - - BOOL - - - JSON - - - - - ( - #{field.dataLength} - ) - - - - - ALTER STABLE ${dataBaseName}.${superTableName} DROP COLUMN - - #{field.fieldName} - - - - - ALTER - STABLE - #{superTableName} - ADD - TAG - - #{fieldDO.fieldName} - - - - - timestamp - - - tinyint - - - smallint - - - int - - - bigint - - - float - - - double - - - binary - - - nchar - - - bool - - - json - - - - - ( - #{fieldDO.dataLength} - ) - - - - - ALTER - STABLE - #{superTableName} - DROP - TAG - - #{fieldsVo.fieldName} - - - - - SELECT count(0) AS count - FROM #{dataBaseName}.#{tableName} - WHERE ${fieldName} BETWEEN #{startTime} AND #{endTime} - - - - SHOW ${dataBaseName}.STABLES LIKE '${superTableName}' - - - - select last(time), * - from #{tableName} - where device_id = #{deviceId} - - - - select last(*) - from #{dataBaseName}.#{stableName} - group by ${tagsName} - - - - SELECT ${fieldName} as data, time - FROM ${dataBaseName}.${tableName} - WHERE time BETWEEN #{startTime} AND #{endTime} - AND ${fieldName} IS NOT NULL - ORDER BY time DESC - LIMIT #{params.rows} offset #{params.page} - - - - SELECT #{fieldName}, time - FROM #{dataBaseName}.#{tableName} - - - - SELECT #{aggregate}(${fieldName}) - FROM #{dataBaseName}.#{tableName} - WHERE ts BETWEEN #{startTime} AND #{endTime} interval (${interval}) - LIMIT #{num} - - - - DESCRIBE ${dataBaseName}.${superTableName} - - - SELECT count(time) - FROM ${dataBaseName}.${tableName} - WHERE time BETWEEN #{startTime} AND #{endTime} - AND ${fieldName} IS NOT NULL - - - diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml new file mode 100644 index 000000000..9407b371d --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml @@ -0,0 +1,73 @@ + + + + + + + + SELECT * FROM ${dataBaseName}.${tableName} + WHERE ${fieldName} BETWEEN #{startTime} AND #{endTime} + + + + + SELECT COUNT(0) AS count + FROM ${dataBaseName}.${tableName} + WHERE ${fieldName} BETWEEN #{startTime} AND #{endTime} + + + + + SELECT LAST(time), * + FROM ${tableName} + WHERE device_id = #{deviceId} + + + + + SELECT LAST(*) + FROM ${dataBaseName}.${stableName} + GROUP BY ${tagsName} + + + + + SELECT ${fieldName} AS data, time + FROM ${dataBaseName}.${tableName} + WHERE time BETWEEN #{startTime} AND #{endTime} + AND ${fieldName} IS NOT NULL + ORDER BY time DESC + LIMIT #{params.rows} OFFSET #{params.page} + + + + + SELECT ${fieldName}, time + FROM ${dataBaseName}.${tableName} + + + + + SELECT ${aggregate}(${fieldName}) + FROM ${dataBaseName}.${tableName} + WHERE ts BETWEEN #{startTime} AND #{endTime} INTERVAL (${interval}) + LIMIT #{num} + + + + + SELECT COUNT(time) + FROM ${dataBaseName}.${tableName} + WHERE time BETWEEN #{startTime} AND #{endTime} + AND ${fieldName} IS NOT NULL + + + diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml new file mode 100644 index 000000000..1ddbe3b97 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + CREATE STABLE IF NOT EXISTS ${dataBaseName}.${superTableName} + + ${item.fieldName} ${item.dataType} + + (${item.dataLength}) + + + TAGS + + ${item.fieldName} ${item.dataType} + + (${item.dataLength}) + + + + + + + SHOW ${dataBaseName}.STABLES LIKE '${superTableName}' + + + + + DESCRIBE ${dataBaseName}.${superTableName} + + + + + ALTER STABLE ${dataBaseName}.${superTableName} ADD COLUMN ${column.fieldName} ${column.dataType} + + (${column.dataLength}) + + + + + + ALTER STABLE ${dataBaseName}.${superTableName} DROP COLUMN ${column.fieldName} + + + + + ALTER STABLE ${dataBaseName}.${superTableName} MODIFY COLUMN ${column.fieldName} ${column.dataType} + + (${column.dataLength}) + + + + + + ALTER STABLE ${dataBaseName}.${superTableName} ADD TAG ${tag.fieldName} ${tag.dataType} + + (${tag.dataLength}) + + + + + + ALTER STABLE ${dataBaseName}.${superTableName} DROP TAG ${tag.fieldName} + + + diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml new file mode 100644 index 000000000..2d469a390 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml @@ -0,0 +1,33 @@ + + + + + + + + CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} + USING ${dataBaseName}.${superTableName} + TAGS + + #{item.fieldValue} + + + + + + CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} + USING ${dataBaseName}.${superTableName} + + #{item.fieldName} + + TAGS + + #{item.fieldValue} + + + + \ No newline at end of file From 9b30d5d35572dc54646b2c3f3ad2fe04368fcd5d Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 9 Nov 2024 13:39:51 +0800 Subject: [PATCH 011/228] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91IoT=EF=BC=9Atdengine=20=E5=B0=81=E8=A3=85?= =?UTF-8?q?=E7=9A=84=20review?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/device/IotDeviceDataController.java | 2 ++ .../vo/deviceData/IotDeviceDataReqVO.java | 1 + .../dataobject/device/IotDeviceDataDO.java | 1 + .../iot/dal/dataobject/tdengine/SelectDO.java | 4 ++++ .../dataobject/tdengine/SelectVisualDO.java | 1 + .../dal/dataobject/tdengine/TableManager.java | 1 + .../dal/dataobject/tdengine/TdRestApi.java | 1 + .../dal/dataobject/tdengine/TdTableDO.java | 1 + .../iot/dal/mysql/device/IotDeviceMapper.java | 1 + .../IotThinkModelFunctionMapper.java | 5 +++-- .../dal/tdengine/TdEngineDatabaseMapper.java | 1 + .../iot/dal/tdengine/TdEngineQueryMapper.java | 1 + .../iot/emq/service/EmqxServiceImpl.java | 2 ++ .../device/IotDeviceDataServiceImpl.java | 1 + .../service/device/IotDeviceServiceImpl.java | 21 +++++++++---------- .../IotThingModelMessageServiceImpl.java | 13 +++++++++++- .../tdengine/TdEngineDataWriterMapper.xml | 1 - .../tdengine/TdEngineDatabaseMapper.xml | 1 - .../mapper/tdengine/TdEngineQueryMapper.xml | 1 - .../tdengine/TdEngineSuperTableMapper.xml | 1 - .../mapper/tdengine/TdEngineTableMapper.xml | 1 - 21 files changed, 43 insertions(+), 19 deletions(-) diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java index e710d0ea8..ac2ec5cf7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java @@ -31,6 +31,7 @@ public class IotDeviceDataController { @Resource private IotDeviceDataService deviceDataService; + // TODO @haohao:是不是叫 get-latest 就好了。因为 data 已经在 url 里了哈 @GetMapping("/latest-data") @Operation(summary = "获取设备属性最新数据") public CommonResult> getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceDataReqVO) { @@ -38,6 +39,7 @@ public class IotDeviceDataController { return success(BeanUtils.toBean(list, IotDeviceDataRespVO.class)); } + // TODO @haohao:是不是叫 /history-data => page @GetMapping("/history-data") @Operation(summary = "获取设备属性历史数据") public CommonResult> getDevicePropertiesHistoryData(@Valid IotDeviceDataReqVO deviceDataReqVO) { diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java index 5f87a1cb8..21e53aff8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java @@ -10,6 +10,7 @@ import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +// TODO @haohao:IotDeviceDataPageReqVO @Schema(description = "管理后台 - IoT 设备数据 Request VO") @Data public class IotDeviceDataReqVO extends PageParam { diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java index 5d8051172..68370d731 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java @@ -23,6 +23,7 @@ import java.time.LocalDateTime; @AllArgsConstructor public class IotDeviceDataDO { + // TODO @haohao:每个字段的关联关系,可以 @ 下哈。 /** * 设备编号 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java index 503b26310..652c3aee6 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java @@ -3,12 +3,15 @@ package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; import lombok.Data; import java.util.Set; + +// TODO @haohao:类似这个,其实可以参考 mybatis plus,querywrapper,搞个 TdEngineQueryWrapper。这样看起来会更好懂。 /** * 查询DO */ @Data public class SelectDO { + // TODO @haoha:database 是个单词 /** * 数据库名称 */ @@ -39,6 +42,7 @@ public class SelectDO { */ private String type; + // TODO @haohao:这个字段,是啥哈? /** * 查询条件 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java index d5faf45a9..d4c35d66d 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java @@ -4,6 +4,7 @@ import lombok.Data; import java.util.Map; +// TODO @haohao:类似 SelectDO 的想法,只是它是返回。ps:貌似可以在 tdengine 里面,创建一个 query 包,放这种比较特殊的查询和结果对象。dataobject 更多还是实际存储的结构化的 do @Data public class SelectVisualDO { diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java index 65663d805..e11db58e7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; import java.util.List; +// TODO @haohao:这个还有用哇? /** * TableManager 类用于管理 TDengine 表的创建、删除和结构信息获取 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java index 6653ece40..b2d1ac029 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java @@ -7,6 +7,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +// TODO @haohao:有部分非实体的部分,是不是可以搞到 iot 的 framework 包下,搞个 tdengine 包,作为框架级的封装,放在 dataobject,感觉不是很合理哈。【可以微信讨论下】 /** * TdRestApi 类用于处理 TDengine 的 REST API 请求 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdTableDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdTableDO.java index 314c51de3..3b30352e4 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdTableDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdTableDO.java @@ -21,6 +21,7 @@ public class TdTableDO { */ private String dataBaseName; + // TODO @haohao:superTableName 和 tableName 是不是合并。因为每个 mapper 操作的时候,有且只会使用到其中一个。 /** * 超级表名称 */ 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 3129f400c..4d8315eb3 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 @@ -15,6 +15,7 @@ import org.apache.ibatis.annotations.Mapper; @Mapper public interface IotDeviceMapper extends BaseMapperX { + // TODO @haohao:可能多余的查询条件,要去掉哈 default PageResult selectPage(IotDevicePageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() .eqIfPresent(IotDeviceDO::getDeviceKey, reqVO.getDeviceKey()) diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java index 2883abe4e..c8745aab6 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java @@ -43,7 +43,7 @@ public interface IotThinkModelFunctionMapper extends BaseMapperX selectListByProductIdAndIdentifiersAndTypes(Long productId, List identifiers, - List types){ + List types) { return selectList(new LambdaQueryWrapperX() .eq(IotThinkModelFunctionDO::getProductId, productId) .in(IotThinkModelFunctionDO::getIdentifier, identifiers) @@ -55,7 +55,8 @@ public interface IotThinkModelFunctionMapper extends BaseMapperX selectListByProductKey(String productKey){ + default List selectListByProductKey(String productKey) { return selectList(IotThinkModelFunctionDO::getProductKey, productKey); } + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java index bc562ccca..cd3eaa8b9 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.InterceptorIgnore; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; +// TODO @haohao:InterceptorIgnore 忽略租户,可以在每个方法上,添加 @TenantIgnore 哈。 /** * TD 引擎的数据库 Mapper */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java index e5353f7ee..a2408e335 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java @@ -25,6 +25,7 @@ public interface TdEngineQueryMapper { */ List> selectByTimestamp(SelectDO selectDO); + // TODO @haohao:最好方法的命名,和数据库操作的保持一直。get => select。然后 selectList or selectOne /** * 根据时间戳获取数据条数 * diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java index f338d6249..343f9ba21 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java @@ -31,6 +31,7 @@ public class EmqxServiceImpl implements EmqxService { // 根据不同的主题,处理不同的业务逻辑 if (topic.contains("/property/post")) { // 设备上报数据 topic /sys/f13f57c63e9/dianbiao1/thing/event/property/post + // TODO @hao:这块未来可能,搞个 IotTopicUrls 之类?把拼接和解析的逻辑,收敛 String productKey = topic.split("/")[2]; String deviceName = topic.split("/")[3]; String message = new String(mqttMessage.getPayload()); @@ -48,4 +49,5 @@ public class EmqxServiceImpl implements EmqxService { log.error("订阅默认主题失败", e); } } + } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java index 4179075df..8f68989c9 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java @@ -133,4 +133,5 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { private static String getDeviceTableName(String productKey, String deviceName) { return String.format("device_%s_%s", productKey.toLowerCase(), deviceName.toLowerCase()); } + } 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 60743f671..0ec737a30 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 @@ -213,31 +213,30 @@ public class IotDeviceServiceImpl implements IotDeviceService { @Override public void updateDeviceStatus(IotDeviceStatusUpdateReqVO updateReqVO) { - // 校验存在 + // 1. 校验存在 + // TODO @haohao:这里的 iotDeviceDO => device。一个是去掉 iot,一个是去掉 DO 后缀。这样,简洁一点。 IotDeviceDO iotDeviceDO = validateDeviceExists(updateReqVO.getId()); - // 更新状态和更新时间 + // 2.1 更新状态和更新时间 IotDeviceDO updateObj = BeanUtils.toBean(updateReqVO, IotDeviceDO.class); - - // 以前是未激活,现在是上线,设置设备激活时间 + // TODO @haohao:下面几个状态的处理,可以考虑 if else if。这样,看起来会有层次感哈 + // 2.2.1 以前是未激活,现在是上线,设置设备激活时间 + // TODO @haohao:这里可以使用 ObjectUtils.equalsAny 类似这种哈。 if (Objects.equals(iotDeviceDO.getStatus(), IotDeviceStatusEnum.INACTIVE.getStatus()) && Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { updateObj.setActiveTime(LocalDateTime.now()); } - - // 如果是上线,设置上线时间 + // 2.2.2 如果是上线,设置上线时间 if (Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { updateObj.setLastOnlineTime(LocalDateTime.now()); } - - // 如果是离线,设置离线时间 + // 2.2.3 如果是离线,设置离线时间 if (Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.OFFLINE.getStatus())) { updateObj.setLastOfflineTime(LocalDateTime.now()); } - - // 设置状态更新时间 + // 2.3 设置状态更新时间 updateObj.setStatusLastUpdateTime(LocalDateTime.now()); - + // 2.4 更新到数据库 deviceMapper.updateById(updateObj); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java index 69c417839..280b32d9a 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java @@ -47,6 +47,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @Resource private DeviceDataRedisDAO deviceDataRedisDAO; + // TODO @haohao:这个方法,可以考虑加下 1. 2. 3. 更有层次感 @Override @TenantIgnore public void saveThingModelMessage(IotDeviceDO device, ThingModelMessage thingModelMessage) { @@ -55,12 +56,14 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ // 创建设备数据表 createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); // 更新设备状态 + // TODO @haohao:下面可以考虑,链式调用。iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO().setid().setstatus()) IotDeviceStatusUpdateReqVO updateReqVO = new IotDeviceStatusUpdateReqVO(); updateReqVO.setId(device.getId()); updateReqVO.setStatus(IotDeviceStatusEnum.ONLINE.getStatus()); iotDeviceService.updateDeviceStatus(updateReqVO); } + // TODO @haohao:这个变量,可以和 “过滤并收集有效的属性字段” 那块,因为关联度高一点。 // 获取设备属性 Map params = thingModelMessage.dataToMap(); @@ -70,12 +73,12 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ .stream() .filter(function -> IotProductFunctionTypeEnum.PROPERTY.getType().equals(function.getType())) .toList(); - if (functionList.isEmpty()) { return; } // 获取属性标识符集合 + // TODO @haohao:这个变量,可以和 “过滤并收集有效的属性字段” 那块,因为关联度高一点。另外,可以使用 CollectionUtils。convertSet Set propertyIdentifiers = functionList.stream() .map(IotThinkModelFunctionDO::getIdentifier) .collect(Collectors.toSet()); @@ -90,9 +93,11 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ if (propertyIdentifiers.contains(key)) { schemaFieldValues.add(new TdFieldDO(key.toLowerCase(), val)); // 缓存设备属性 + // TODO @haohao:这个缓存的写入,可以使用的时候 cache 么?被动读 setDeviceDataCache(device, functionMap.get(key), val, thingModelMessage.getTime()); } }); + // TODO @haohao:疑问,为什么 1 不继续哈? if (schemaFieldValues.size() == 1) { return; } @@ -127,6 +132,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ deviceDataRedisDAO.set(deviceData); } + // TODO @haohao:实现没问题哈。这个方法的空行有点多,逻辑分块上没这么明显。看看能不能改下。 /** * 创建设备数据表 * @@ -143,6 +149,8 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ List tagsFieldValues = new ArrayList<>(); if (maps != null) { + // TODO @haohao:一些字符串,是不是可以枚举起来哈。 + // TODO @haohao:这种过滤的,常用的,可以考虑用 CollectionUtils.filterList。一些常用的 stream 操作,适合封装哈 List> taggedNotesList = maps.stream() .filter(map -> "TAG".equals(map.get("note"))) .toList(); @@ -176,6 +184,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ * @return 数据库名称 */ private String getDatabaseName() { + // TODO @haohao:可以使用 StrUtil.subAftetLast 这种方法 return url.substring(url.lastIndexOf("/") + 1); } @@ -187,6 +196,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ * @return 产品属性表名 */ private static String getProductPropertySTableName(Integer deviceType, String productKey) { + // TODO @haohao:枚举下,会好点哈。 return switch (deviceType) { case 1 -> String.format("gateway_sub_%s", productKey).toLowerCase(); case 2 -> String.format("gateway_%s", productKey).toLowerCase(); @@ -204,4 +214,5 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ private static String getDeviceTableName(String productKey, String deviceName) { return String.format("device_%s_%s", productKey.toLowerCase(), deviceName.toLowerCase()); } + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml index b5f044614..dd38cd08e 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml @@ -2,7 +2,6 @@ - diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml index 4d9a125db..919c301f7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml @@ -2,7 +2,6 @@ - diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml index 9407b371d..f4361bc67 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml @@ -2,7 +2,6 @@ - diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml index 1ddbe3b97..37cf71910 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml @@ -2,7 +2,6 @@ - diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml index 2d469a390..867ef8f43 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml @@ -2,7 +2,6 @@ - From 89fb71e8573d1f6552d70a699e3a8b1ec8612f02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Sat, 9 Nov 2024 23:44:05 +0800 Subject: [PATCH 012/228] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E3=80=91=20=E4=BC=98=E5=8C=96=20tdengine=20=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E6=95=B0=E6=8D=AE=E5=BA=93=E7=9B=B8=E5=85=B3=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/iot/enums/IotConstants.java | 38 +++++ .../admin/device/IotDeviceDataController.java | 16 +- ...ReqVO.java => IotDeviceDataPageReqVO.java} | 3 +- .../vo/deviceData/IotDeviceDataRespVO.java | 3 - .../dataobject/device/IotDeviceDataDO.java | 20 ++- .../iot/dal/dataobject/tdengine/SelectDO.java | 6 - .../dataobject/tdengine/SelectVisualDO.java | 3 + .../dal/dataobject/tdengine/TableManager.java | 159 ------------------ ...ableMapper.java => TdEngineDDLMapper.java} | 60 +++++-- .../iot/dal/tdengine/TdEngineDMLMapper.java | 103 ++++++++++++ .../tdengine/TdEngineDataWriterMapper.java | 25 --- .../dal/tdengine/TdEngineDatabaseMapper.java | 24 --- .../iot/dal/tdengine/TdEngineQueryMapper.java | 86 ---------- .../iot/dal/tdengine/TdEngineTableMapper.java | 41 ----- .../service/device/IotDeviceDataService.java | 6 +- .../device/IotDeviceDataServiceImpl.java | 22 +-- .../service/device/IotDeviceServiceImpl.java | 45 ++--- .../tdengine/IotSuperTableService.java | 2 +- .../tdengine/IotSuperTableServiceImpl.java | 59 ++++--- .../IotThingModelMessageServiceImpl.java | 130 +++++++------- .../tdengine/TdEngineDataWriterService.java | 19 --- .../TdEngineDataWriterServiceImpl.java | 21 --- .../tdengine/TdEngineDatabaseService.java | 14 -- .../tdengine/TdEngineDatabaseServiceImpl.java | 22 --- .../tdengine/TdEngineQueryService.java | 28 --- .../tdengine/TdEngineQueryServiceImpl.java | 26 --- .../tdengine/TdEngineSuperTableService.java | 123 -------------- .../TdEngineSuperTableServiceImpl.java | 90 ---------- .../tdengine/TdEngineTableService.java | 21 --- .../tdengine/TdEngineTableServiceImpl.java | 23 --- ...rTableMapper.xml => TdEngineDDLMapper.xml} | 34 +++- ...eQueryMapper.xml => TdEngineDMLMapper.xml} | 32 +++- .../tdengine/TdEngineDataWriterMapper.xml | 21 --- .../tdengine/TdEngineDatabaseMapper.xml | 12 -- .../mapper/tdengine/TdEngineTableMapper.xml | 32 ---- 35 files changed, 416 insertions(+), 953 deletions(-) create mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/IotConstants.java rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/{IotDeviceDataReqVO.java => IotDeviceDataPageReqVO.java} (92%) delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/{TdEngineSuperTableMapper.java => TdEngineDDLMapper.java} (68%) create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDMLMapper.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDataWriterMapper.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterService.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseServiceImpl.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryService.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableService.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java rename yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/{TdEngineSuperTableMapper.xml => TdEngineDDLMapper.xml} (70%) rename yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/{TdEngineQueryMapper.xml => TdEngineDMLMapper.xml} (68%) delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/IotConstants.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/IotConstants.java new file mode 100644 index 000000000..5927f44b9 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/IotConstants.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.iot.enums; + +/** + * Iot 常量 + * + * @author 芋道源码 + */ +public interface IotConstants { + + /** + * 获取设备表名 + * + * 格式为 device_{productKey}_{deviceName} + */ + String DEVICE_TABLE_NAME_FORMAT = "device_%s_%s"; + + /** + * 获取产品属性超级表名 - 网关子设备 + * + * 格式为 gateway_sub_{productKey} + */ + String GATEWAY_SUB_STABLE_NAME_FORMAT = "gateway_sub_%s"; + + /** + * 获取产品属性超级表名 - 网关 + * + * 格式为 gateway_{productKey} + */ + String GATEWAY_STABLE_NAME_FORMAT = "gateway_%s"; + + /** + * 获取产品属性超级表名 - 设备 + * + * 格式为 device_{productKey} + */ + String DEVICE_STABLE_NAME_FORMAT = "device_%s"; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java index ac2ec5cf7..72fdda8c8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.controller.admin.device; import cn.iocoder.yudao.framework.common.pojo.CommonResult; 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.device.vo.deviceData.IotDeviceDataReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataRespVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotTimeDataRespVO; @@ -31,19 +31,17 @@ public class IotDeviceDataController { @Resource private IotDeviceDataService deviceDataService; - // TODO @haohao:是不是叫 get-latest 就好了。因为 data 已经在 url 里了哈 - @GetMapping("/latest-data") + @GetMapping("/latest") @Operation(summary = "获取设备属性最新数据") - public CommonResult> getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceDataReqVO) { - List list = deviceDataService.getDevicePropertiesLatestData(deviceDataReqVO); + public CommonResult> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { + List list = deviceDataService.getLatestDeviceProperties(deviceDataReqVO); return success(BeanUtils.toBean(list, IotDeviceDataRespVO.class)); } - // TODO @haohao:是不是叫 /history-data => page - @GetMapping("/history-data") + @GetMapping("/history") @Operation(summary = "获取设备属性历史数据") - public CommonResult> getDevicePropertiesHistoryData(@Valid IotDeviceDataReqVO deviceDataReqVO) { - PageResult> list = deviceDataService.getDevicePropertiesHistoryData(deviceDataReqVO); + public CommonResult> getHistoryDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { + PageResult> list = deviceDataService.getHistoryDeviceProperties(deviceDataReqVO); return success(BeanUtils.toBean(list, IotTimeDataRespVO.class)); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataPageReqVO.java similarity index 92% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataPageReqVO.java index 21e53aff8..da41299d8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataPageReqVO.java @@ -10,10 +10,9 @@ import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -// TODO @haohao:IotDeviceDataPageReqVO @Schema(description = "管理后台 - IoT 设备数据 Request VO") @Data -public class IotDeviceDataReqVO extends PageParam { +public class IotDeviceDataPageReqVO extends PageParam { @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "177") private Long deviceId; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataRespVO.java index 256bf84fa..ad32fb5f9 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataRespVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataRespVO.java @@ -1,9 +1,6 @@ package cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Builder; import lombok.Data; import java.time.LocalDateTime; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java index 68370d731..892a6b8b7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java @@ -1,15 +1,12 @@ package cn.iocoder.yudao.module.iot.dal.dataobject.device; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; -import com.baomidou.mybatisplus.annotation.TableId; -import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import java.math.BigDecimal; import java.time.LocalDateTime; /** @@ -23,39 +20,52 @@ import java.time.LocalDateTime; @AllArgsConstructor public class IotDeviceDataDO { - // TODO @haohao:每个字段的关联关系,可以 @ 下哈。 /** * 设备编号 + * + * 关联 {@link IotDeviceDO#getId()} */ private Long deviceId; /** * 物模型编号 + * + * 关联 {@link IotThinkModelFunctionDO#getId()} */ private Long thinkModelFunctionId; /** * 产品标识 + * + * 关联 {@link IotProductDO#getProductKey()} */ private String productKey; /** * 设备名称 + * + * 冗余 {@link IotDeviceDO#getDeviceName()} */ private String deviceName; /** * 属性标识符 + * + * 关联 {@link IotThinkModelFunctionDO#getIdentifier()} */ private String identifier; /** * 属性名称 + * + * 关联 {@link IotThinkModelFunctionDO#getName()} */ private String name; /** * 数据类型 + * + * 关联 {@link IotThinkModelFunctionDO#getProperty()#getDataType()} */ private String dataType; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java index 652c3aee6..542dd1e7b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java @@ -42,12 +42,6 @@ public class SelectDO { */ private String type; - // TODO @haohao:这个字段,是啥哈? - /** - * 查询条件 - */ - private Set orgIds; - /** * 设备ID */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java index d4c35d66d..44acc3ac5 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java @@ -27,14 +27,17 @@ public class SelectVisualDO { * 查询类型,0历史数据,1实时数据,2聚合数据 */ private int type; + /** * 查询的数据量 */ private int num; + /** * 聚合函数 */ private String aggregate; + /** * 统计间隔数字+s/m/h/d * 比如1s,1m,1h,1d代表1秒,1分钟,1小时,1天 diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java deleted file mode 100644 index e11db58e7..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java +++ /dev/null @@ -1,159 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; - -import java.util.List; - -// TODO @haohao:这个还有用哇? -/** - * TableManager 类用于管理 TDengine 表的创建、删除和结构信息获取 - */ -public class TableManager { - - /** - * 创建超级表模板(含存在判断) - */ - private static final String CREATE_STABLE_INE_TPL = "CREATE STABLE IF NOT EXISTS %s (%s) TAGS (%s);"; - - /** - * 删除超级表 - */ - private static final String DROP_STABLE_TPL = "DROP STABLE IF EXISTS %s;"; - - /** - * 获取表的结构信息 - */ - private static final String DESC_TB_TPL = "DESCRIBE %s;"; - - /** - * 超级表增加列 - */ - private static final String ALTER_STABLE_ADD_COL_TPL = "ALTER STABLE %s ADD COLUMN %s;"; - - /** - * 超级表修改列 - */ - private static final String ALTER_STABLE_MODIFY_COL_TPL = "ALTER STABLE %s MODIFY COLUMN %s;"; - - /** - * 超级表删除列 - */ - private static final String ALTER_STABLE_DROP_COL_TPL = "ALTER STABLE %s DROP COLUMN %s;"; - - /** - * 创建普通表模板(含存在判断) - */ - private static final String CREATE_CTABLE_INE_TPL = "CREATE TABLE IF NOT EXISTS %s (%s)"; - - /** - * 获取创建表sql - */ - public static String getCreateSTableSql(String tbName, List fields, TdFieldDO... tags) { - if (fields.isEmpty()) { - return null; - } - - // 生成字段片段 - StringBuilder sbField = new StringBuilder("time TIMESTAMP,"); - - for (TdFieldDO field : fields) { - sbField.append(FieldParser.getFieldDefine(field)); - sbField.append(","); - } - sbField.deleteCharAt(sbField.length() - 1); - - String fieldFrag = sbField.toString(); - - // 生成tag - StringBuilder sbTag = new StringBuilder(); - for (TdFieldDO tag : tags) { - sbTag.append(FieldParser.getFieldDefine(tag)) - .append(","); - } - sbTag.deleteCharAt(sbTag.length() - 1); - - return String.format(CREATE_STABLE_INE_TPL, tbName, fieldFrag, sbTag); - - } - - /** - * 获取创建普通表sql - */ - public static String getCreateCTableSql(String tbName, List fields) { - if (fields.size() == 0) { - return null; - } - - //生成字段片段 - StringBuilder sbField = new StringBuilder("time timestamp,"); - - for (TdFieldDO field : fields) { - sbField.append(FieldParser.getFieldDefine(field)); - sbField.append(","); - } - sbField.deleteCharAt(sbField.length() - 1); - - String fieldFrag = sbField.toString(); - - return String.format(CREATE_CTABLE_INE_TPL, tbName, fieldFrag); - - } - - - /** - * 取正确的表名 - * - * @param name 表象 - */ - public static String rightTbName(String name) { - return name.toLowerCase().replace("-" , "_"); - } - - /** - * 获取表详情的sql - */ - public static String getDescTableSql(String tbName) { - return String.format(DESC_TB_TPL, tbName); - } - - /** - * 获取添加字段sql - */ - public static String getAddSTableColumnSql(String tbName, List fields) { - StringBuilder sbAdd = new StringBuilder(); - for (TdFieldDO field : fields) { - sbAdd.append(String.format(ALTER_STABLE_ADD_COL_TPL, - tbName, - FieldParser.getFieldDefine(field) - )); - } - return sbAdd.toString(); - } - - /** - * 获取修改字段sql - */ - public static String getModifySTableColumnSql(String tbName, List fields) { - StringBuilder sbModify = new StringBuilder(); - for (TdFieldDO field : fields) { - sbModify.append(String.format(ALTER_STABLE_MODIFY_COL_TPL, - tbName, - FieldParser.getFieldDefine(field) - )); - } - return sbModify.toString(); - } - - /** - * 获取删除字段sql - */ - public static String getDropSTableColumnSql(String tbName, List fields) { - StringBuilder sbDrop = new StringBuilder(); - for (TdFieldDO field : fields) { - sbDrop.append(String.format(ALTER_STABLE_DROP_COL_TPL, - tbName, - field.getFieldName() - )); - } - return sbDrop.toString(); - } - -} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineSuperTableMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java similarity index 68% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineSuperTableMapper.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java index e688563d5..640255940 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineSuperTableMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java @@ -1,19 +1,30 @@ package cn.iocoder.yudao.module.iot.dal.tdengine; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.mybatisplus.annotation.InterceptorIgnore; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; import java.util.List; import java.util.Map; /** - * TD 引擎的超级表 Mapper + * 专门处理 DDL(数据定义语言)操作,包含所有的数据库和表的定义操作,例如创建数据库、创建超级表、创建子表等 */ @Mapper @DS("tdengine") -public interface TdEngineSuperTableMapper { +public interface TdEngineDDLMapper { + + /** + * 创建数据库 + * SQL:CREATE DATABASE [IF NOT EXISTS] db_name [database_options]; + * + * @param dataBaseName 数据库名称 + */ + @TenantIgnore + void createDatabase(@Param("dataBaseName") String dataBaseName); /** * 创建超级表 @@ -25,7 +36,7 @@ public interface TdEngineSuperTableMapper { * columns 列信息 * tags 标签信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void createSuperTable(TdTableDO superTable); /** @@ -36,7 +47,7 @@ public interface TdEngineSuperTableMapper { * dataBaseName 数据库名称 * superTableName 超级表名称 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore List> showSuperTables(TdTableDO superTable); /** @@ -47,7 +58,7 @@ public interface TdEngineSuperTableMapper { * dataBaseName 数据库名称 * superTableName 超级表名称 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore List> describeSuperTable(TdTableDO superTable); /** @@ -59,7 +70,7 @@ public interface TdEngineSuperTableMapper { * superTableName 超级表名称 * column 列信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void addColumnForSuperTable(TdTableDO superTable); /** @@ -71,7 +82,7 @@ public interface TdEngineSuperTableMapper { * superTableName 超级表名称 * column 列信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void dropColumnForSuperTable(TdTableDO superTable); /** @@ -83,7 +94,7 @@ public interface TdEngineSuperTableMapper { * superTableName 超级表名称 * column 列信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void modifyColumnWidthForSuperTable(TdTableDO superTable); @@ -95,7 +106,7 @@ public interface TdEngineSuperTableMapper { * superTableName 超级表名称 * tag 标签信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void addTagForSuperTable(TdTableDO superTable); /** @@ -106,6 +117,33 @@ public interface TdEngineSuperTableMapper { * superTableName 超级表名称 * tag 标签信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void dropTagForSuperTable(TdTableDO superTable); -} \ No newline at end of file + + /** + * 创建子表 - 创建子表 + * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name TAGS (tag_value1, ...); + * + * @param table 表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tableName 子表名称 + * tags TAG 字段 + */ + @TenantIgnore + void createTable(TdTableDO table); + + /** + * 创建子表 - 创建子表并指定标签的值 + * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name (tag_name1, ...) TAGS (tag_value1, ...); + * + * @param table 表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tableName 子表名称 + * tags TAG 字段 + */ + @TenantIgnore + void createTableWithTags(TdTableDO table); + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDMLMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDMLMapper.java new file mode 100644 index 000000000..12b2c232c --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDMLMapper.java @@ -0,0 +1,103 @@ +package cn.iocoder.yudao.module.iot.dal.tdengine; + +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TagsSelectDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; +import com.baomidou.dynamic.datasource.annotation.DS; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; +import java.util.Map; + +/** + * 专门处理 TD Engine 的 DML(数据操作语言)操作,处理所有的数据查询和写入操作,如插入数据、查询数据等 + */ +@Mapper +@DS("tdengine") +public interface TdEngineDMLMapper { + + /** + * 插入数据 - 指定列插入数据 + * + * @param table 数据 + * dataBaseName 数据库名 + * tableName 表名 + * columns 列 + */ + @TenantIgnore + void insertData(TdTableDO table); + + /** + * 根据时间戳查询数据 + * + * @param selectDO 查询条件 + * @return 查询结果列表 + */ + @TenantIgnore + List> selectByTimestamp(SelectDO selectDO); + + /** + * 根据时间戳获取数据条数 + * + * @param selectDO 查询条件 + * @return 数据条数 + */ + @TenantIgnore + Map selectCountByTimestamp(SelectDO selectDO); + + /** + * 获取最新数据 + * + * @param selectDO 查询条件 + * @return 最新数据 + */ + @TenantIgnore + Map selectOneLastData(SelectDO selectDO); + + /** + * 获取历史数据列表 + * + * @param selectVisualDO 查询条件 + * @return 历史数据列表 + */ + @TenantIgnore + List> selectHistoryDataList(SelectVisualDO selectVisualDO); + + /** + * 获取实时数据列表 + * + * @param selectVisualDO 查询条件 + * @return 实时数据列表 + */ + @TenantIgnore + List> selectRealtimeDataList(SelectVisualDO selectVisualDO); + + /** + * 获取聚合数据列表 + * + * @param selectVisualDO 查询条件 + * @return 聚合数据列表 + */ + @TenantIgnore + List> selectAggregateDataList(SelectVisualDO selectVisualDO); + + /** + * 根据标签获取最新数据列表 + * + * @param tagsSelectDO 查询条件 + * @return 最新数据列表 + */ + @TenantIgnore + List> selectLastDataListByTags(TagsSelectDO tagsSelectDO); + + /** + * 获取历史数据条数 + * + * @param selectVisualDO 查询条件 + * @return 数据条数 + */ + @TenantIgnore + Long selectHistoryCount(SelectVisualDO selectVisualDO); +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDataWriterMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDataWriterMapper.java deleted file mode 100644 index 51f4229a0..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDataWriterMapper.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.apache.ibatis.annotations.Mapper; - -/** - * TD 引擎的数据写入 Mapper - */ -@Mapper -@DS("tdengine") -public interface TdEngineDataWriterMapper { - - /** - * 插入数据 - 指定列插入数据 - * - * @param table 数据 - * dataBaseName 数据库名 - * tableName 表名 - * columns 列 - */ - @InterceptorIgnore(tenantLine = "true") - void insertData(TdTableDO table); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java deleted file mode 100644 index cd3eaa8b9..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.tdengine; - -import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -// TODO @haohao:InterceptorIgnore 忽略租户,可以在每个方法上,添加 @TenantIgnore 哈。 -/** - * TD 引擎的数据库 Mapper - */ -@Mapper -@DS("tdengine") -public interface TdEngineDatabaseMapper { - - /** - * 创建数据库 - * SQL:CREATE DATABASE [IF NOT EXISTS] db_name [database_options]; - * - * @param dataBaseName 数据库名称 - */ - @InterceptorIgnore(tenantLine = "true") - void createDatabase(@Param("dataBaseName") String dataBaseName); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java deleted file mode 100644 index a2408e335..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java +++ /dev/null @@ -1,86 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TagsSelectDO; -import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; -import java.util.Map; - -/** - * TD 引擎的查询 Mapper - */ -@Mapper -@DS("tdengine") -public interface TdEngineQueryMapper { - - /** - * 根据时间戳查询数据 - * - * @param selectDO 查询条件 - * @return 查询结果 - */ - List> selectByTimestamp(SelectDO selectDO); - - // TODO @haohao:最好方法的命名,和数据库操作的保持一直。get => select。然后 selectList or selectOne - /** - * 根据时间戳获取数据条数 - * - * @param selectDO 查询条件 - * @return 数据条数 - */ - Map getCountByTimestamp(SelectDO selectDO); - - /** - * 获取最新数据 - * - * @param selectDO 查询条件 - * @return 最新数据 - */ - Map getLastData(SelectDO selectDO); - - /** - * 获取历史数据 - * - * @param selectVisualDO 查询条件 - * @return 历史数据列表 - */ - @InterceptorIgnore(tenantLine = "true") - List> getHistoryData(SelectVisualDO selectVisualDO); - - /** - * 获取实时数据 - * - * @param selectVisualDO 查询条件 - * @return 实时数据列表 - */ - List> getRealtimeData(SelectVisualDO selectVisualDO); - - /** - * 获取聚合数据 - * - * @param selectVisualDO 查询条件 - * @return 聚合数据列表 - */ - List> getAggregateData(SelectVisualDO selectVisualDO); - - /** - * 根据标签获取最新数据 - * - * @param tagsSelectDO 查询条件 - * @return 最新数据列表 - */ - List> getLastDataByTags(TagsSelectDO tagsSelectDO); - - /** - * 获取历史数据条数 - * - * @param selectVisualDO 查询条件 - * @return 数据条数 - */ - @InterceptorIgnore(tenantLine = "true") - Long getHistoryCount(SelectVisualDO selectVisualDO); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java deleted file mode 100644 index 72517bcab..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.apache.ibatis.annotations.Mapper; - -/** - * TD 引擎的表 Mapper - */ -@Mapper -@DS("tdengine") -public interface TdEngineTableMapper { - - /** - * 创建子表 - 创建子表 - * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name TAGS (tag_value1, ...); - * - * @param table 表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * tableName 子表名称 - * tags TAG 字段 - */ - @InterceptorIgnore(tenantLine = "true") - void createTable(TdTableDO table); - - /** - * 创建子表 - 创建子表并指定标签的值 - * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name (tag_name1, ...) TAGS (tag_value1, ...); - * - * @param table 表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * tableName 子表名称 - * tags TAG 字段 - */ - @InterceptorIgnore(tenantLine = "true") - void createTableWithTags(TdTableDO table); - -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java index 96181fd26..4f390ca3b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java @@ -1,7 +1,7 @@ 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.deviceData.IotDeviceDataReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import jakarta.validation.Valid; @@ -31,7 +31,7 @@ public interface IotDeviceDataService { * @param deviceId 设备编号 * @return 设备属性最新数据 */ - List getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceId); + List getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceId); /** * 获得设备属性历史数据 @@ -39,5 +39,5 @@ public interface IotDeviceDataService { * @param deviceDataReqVO 设备属性历史数据 Request VO * @return 设备属性历史数据 */ - PageResult> getDevicePropertiesHistoryData(@Valid IotDeviceDataReqVO deviceDataReqVO); + PageResult> getHistoryDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO); } \ 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/IotDeviceDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java index 8f68989c9..7d10977f9 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java @@ -1,18 +1,20 @@ package cn.iocoder.yudao.module.iot.service.device; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONObject; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper; +import cn.iocoder.yudao.module.iot.enums.IotConstants; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import cn.iocoder.yudao.module.iot.service.tdengine.IotThingModelMessageService; -import cn.iocoder.yudao.module.iot.service.tdengine.TdEngineQueryService; import cn.iocoder.yudao.module.iot.service.thinkmodelfunction.IotThinkModelFunctionService; import jakarta.annotation.Resource; import jakarta.validation.Valid; @@ -40,7 +42,7 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { @Resource private IotThinkModelFunctionService thinkModelFunctionService; @Resource - private TdEngineQueryService tdEngineQueryService; + private TdEngineDMLMapper tdEngineDMLMapper; @Resource private DeviceDataRedisDAO deviceDataRedisDAO; @@ -66,7 +68,7 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { } @Override - public List getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceDataReqVO) { + public List getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { List list = new ArrayList<>(); // 1. 获取设备信息 IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId()); @@ -106,7 +108,7 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { } @Override - public PageResult> getDevicePropertiesHistoryData(IotDeviceDataReqVO deviceDataReqVO) { + public PageResult> getHistoryDeviceProperties(IotDeviceDataPageReqVO deviceDataReqVO) { PageResult> pageResult = new PageResult<>(); // 1. 获取设备信息 IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId()); @@ -121,17 +123,17 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { params.put("rows", deviceDataReqVO.getPageSize()); params.put("page", (deviceDataReqVO.getPageNo() - 1) * deviceDataReqVO.getPageSize()); selectVisualDO.setParams(params); - pageResult.setList(tdEngineQueryService.getHistoryData(selectVisualDO)); - pageResult.setTotal(tdEngineQueryService.getHistoryCount(selectVisualDO)); + pageResult.setList(tdEngineDMLMapper.selectHistoryDataList(selectVisualDO)); + pageResult.setTotal(tdEngineDMLMapper.selectHistoryCount(selectVisualDO)); return pageResult; } private String getDatabaseName() { - return url.substring(url.lastIndexOf("/") + 1); + return StrUtil.subAfter(url, "/", true); } private static String getDeviceTableName(String productKey, String deviceName) { - return String.format("device_%s_%s", productKey.toLowerCase(), deviceName.toLowerCase()); + return String.format(IotConstants.DEVICE_TABLE_NAME_FORMAT, productKey, deviceName); } -} +} \ 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/IotDeviceServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java index 0ec737a30..58918c130 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 @@ -19,7 +19,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import java.security.SecureRandom; import java.time.LocalDateTime; +import java.util.Base64; import java.util.Objects; import java.util.UUID; @@ -137,10 +139,13 @@ public class IotDeviceServiceImpl implements IotDeviceService { * @return 生成的 MQTT Password */ private String generateMqttPassword() { - // TODO @haohao:【后续优化】在实际应用中,建议使用更安全的方法生成 MQTT Password,如加密或哈希 - return UUID.randomUUID().toString(); + SecureRandom secureRandom = new SecureRandom(); + byte[] passwordBytes = new byte[32]; // 256 位的随机数 + secureRandom.nextBytes(passwordBytes); + return Base64.getUrlEncoder().withoutPadding().encodeToString(passwordBytes); } + /** * 生成唯一的 DeviceName * @@ -214,30 +219,28 @@ public class IotDeviceServiceImpl implements IotDeviceService { @Override public void updateDeviceStatus(IotDeviceStatusUpdateReqVO updateReqVO) { // 1. 校验存在 - // TODO @haohao:这里的 iotDeviceDO => device。一个是去掉 iot,一个是去掉 DO 后缀。这样,简洁一点。 - IotDeviceDO iotDeviceDO = validateDeviceExists(updateReqVO.getId()); + IotDeviceDO device = validateDeviceExists(updateReqVO.getId()); // 2.1 更新状态和更新时间 - IotDeviceDO updateObj = BeanUtils.toBean(updateReqVO, IotDeviceDO.class); - // TODO @haohao:下面几个状态的处理,可以考虑 if else if。这样,看起来会有层次感哈 - // 2.2.1 以前是未激活,现在是上线,设置设备激活时间 - // TODO @haohao:这里可以使用 ObjectUtils.equalsAny 类似这种哈。 - if (Objects.equals(iotDeviceDO.getStatus(), IotDeviceStatusEnum.INACTIVE.getStatus()) - && Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { - updateObj.setActiveTime(LocalDateTime.now()); - } - // 2.2.2 如果是上线,设置上线时间 - if (Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { - updateObj.setLastOnlineTime(LocalDateTime.now()); - } - // 2.2.3 如果是离线,设置离线时间 - if (Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.OFFLINE.getStatus())) { - updateObj.setLastOfflineTime(LocalDateTime.now()); + IotDeviceDO updateDevice = BeanUtils.toBean(updateReqVO, IotDeviceDO.class); + // 2.2 更新状态相关时间 + if (Objects.equals(device.getStatus(), IotDeviceStatusEnum.INACTIVE.getStatus()) + && Objects.equals(updateDevice.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { + // 从未激活到在线,设置激活时间和最后上线时间 + updateDevice.setActiveTime(LocalDateTime.now()); + updateDevice.setLastOnlineTime(LocalDateTime.now()); + } else if (Objects.equals(updateDevice.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { + // 如果是上线,设置最后上线时间 + updateDevice.setLastOnlineTime(LocalDateTime.now()); + } else if (Objects.equals(updateDevice.getStatus(), IotDeviceStatusEnum.OFFLINE.getStatus())) { + // 如果是离线,设置最后离线时间 + updateDevice.setLastOfflineTime(LocalDateTime.now()); } + // 2.3 设置状态更新时间 - updateObj.setStatusLastUpdateTime(LocalDateTime.now()); + updateDevice.setStatusLastUpdateTime(LocalDateTime.now()); // 2.4 更新到数据库 - deviceMapper.updateById(updateObj); + deviceMapper.updateById(updateDevice); } @Override diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java index 7c88b83aa..8aec32f32 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java @@ -15,4 +15,4 @@ public interface IotSuperTableService { * 创建超级表数据模型 */ void createSuperTableDataModel(IotProductDO product, List functionList); -} +} \ 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/tdengine/IotSuperTableServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableServiceImpl.java index 3be324c4e..20989181e 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableServiceImpl.java @@ -9,6 +9,8 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -26,7 +28,7 @@ import java.util.stream.Collectors; public class IotSuperTableServiceImpl implements IotSuperTableService { @Resource - private TdEngineSuperTableService tdEngineSuperTableService; + private TdEngineDDLMapper tdEngineDDLMapper; @Value("${spring.datasource.dynamic.datasource.tdengine.url}") private String url; @@ -42,9 +44,10 @@ public class IotSuperTableServiceImpl implements IotSuperTableService { String superTableName = getSuperTableName(product.getDeviceType(), product.getProductKey()); String databaseName = getDatabaseName(); - Integer tableExists = tdEngineSuperTableService.checkSuperTableExists(new TdTableDO(databaseName, superTableName)); - if (tableExists != null && tableExists > 0) { + List> results = tdEngineDDLMapper.showSuperTables(new TdTableDO(databaseName, superTableName)); + int tableExists = results == null || results.isEmpty() ? 0 : results.size(); + if (tableExists > 0) { updateSuperTable(thingModel, product.getDeviceType()); } else { createSuperTable(thingModel, product.getDeviceType()); @@ -76,7 +79,7 @@ public class IotSuperTableServiceImpl implements IotSuperTableService { String databaseName = getDatabaseName(); // 创建超级表 - tdEngineSuperTableService.createSuperTable(new TdTableDO(databaseName, superTableName, schemaFields, tagsFields)); + tdEngineDDLMapper.createSuperTable(new TdTableDO(databaseName, superTableName, schemaFields, tagsFields)); } /** @@ -98,7 +101,7 @@ public class IotSuperTableServiceImpl implements IotSuperTableService { * 获取表的字段信息 */ private List getTableFields(String tableName) { - List> tableDescription = tdEngineSuperTableService.describeSuperTable(new TdTableDO(getDatabaseName(), tableName)); + List> tableDescription = tdEngineDDLMapper.describeSuperTable(new TdTableDO(getDatabaseName(), tableName)); if (CollUtil.isEmpty(tableDescription)) { return Collections.emptyList(); } @@ -127,32 +130,38 @@ public class IotSuperTableServiceImpl implements IotSuperTableService { // 添加新增字段 if (CollUtil.isNotEmpty(addFields)) { - tdEngineSuperTableService.addColumnsForSuperTable(TdTableDO.builder() - .dataBaseName(databaseName) - .superTableName(tableName) - .columns(addFields) - .build()); + for (TdFieldDO addField : addFields) { + tdEngineDDLMapper.addColumnForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .column(addField) + .build()); + } } // 删除旧字段 if (CollUtil.isNotEmpty(dropFields)) { - tdEngineSuperTableService.dropColumnsForSuperTable(TdTableDO.builder() - .dataBaseName(databaseName) - .superTableName(tableName) - .columns(dropFields) - .build()); + for (TdFieldDO dropField : dropFields) { + tdEngineDDLMapper.dropColumnForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .column(dropField) + .build()); + } } // 修改字段(先删除再添加) if (CollUtil.isNotEmpty(modifyFields)) { - tdEngineSuperTableService.dropColumnsForSuperTable(TdTableDO.builder() - .dataBaseName(databaseName) - .superTableName(tableName) - .columns(modifyFields) - .build()); - tdEngineSuperTableService.addColumnsForSuperTable(TdTableDO.builder() - .dataBaseName(databaseName) - .superTableName(tableName) - .columns(addFields) - .build()); + for (TdFieldDO modifyField : modifyFields) { + tdEngineDDLMapper.dropColumnForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .column(modifyField) + .build()); + tdEngineDDLMapper.addColumnForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .column(modifyField) + .build()); + } } } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java index 280b32d9a..92a30ebb0 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.iot.service.tdengine; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceStatusUpdateReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; @@ -11,6 +13,9 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper; +import cn.iocoder.yudao.module.iot.enums.IotConstants; import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; @@ -30,6 +35,14 @@ import java.util.stream.Collectors; @Service public class IotThingModelMessageServiceImpl implements IotThingModelMessageService { + private static final String TAG_NOTE = "TAG"; + private static final String NOTE = "note"; + private static final String TIME = "time"; + private static final String DEVICE_KEY = "device_key"; + private static final String DEVICE_NAME = "device_name"; + private static final String PRODUCT_KEY = "product_key"; + private static final String DEVICE_TYPE = "device_type"; + @Value("${spring.datasource.dynamic.datasource.tdengine.url}") private String url; @@ -38,11 +51,9 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @Resource private IotDeviceService iotDeviceService; @Resource - private TdEngineTableService tdEngineTableService; + private TdEngineDDLMapper tdEngineDDLMapper; @Resource - private TdEngineSuperTableService tdEngineSuperTableService; - @Resource - private TdEngineDataWriterService tdEngineDataWriterService; + private TdEngineDMLMapper tdEngineDMLMapper; @Resource private DeviceDataRedisDAO deviceDataRedisDAO; @@ -51,62 +62,64 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @Override @TenantIgnore public void saveThingModelMessage(IotDeviceDO device, ThingModelMessage thingModelMessage) { - // 判断设备状态,如果为未激活状态,创建数据表 + // 1. 判断设备状态,如果为未激活状态,创建数据表并更新设备状态 if (IotDeviceStatusEnum.INACTIVE.getStatus().equals(device.getStatus())) { - // 创建设备数据表 createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); - // 更新设备状态 - // TODO @haohao:下面可以考虑,链式调用。iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO().setid().setstatus()) - IotDeviceStatusUpdateReqVO updateReqVO = new IotDeviceStatusUpdateReqVO(); - updateReqVO.setId(device.getId()); - updateReqVO.setStatus(IotDeviceStatusEnum.ONLINE.getStatus()); - iotDeviceService.updateDeviceStatus(updateReqVO); + iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO() + .setId(device.getId()) + .setStatus(IotDeviceStatusEnum.ONLINE.getStatus())); } - // TODO @haohao:这个变量,可以和 “过滤并收集有效的属性字段” 那块,因为关联度高一点。 - // 获取设备属性 + // 2. 获取设备属性并进行物模型校验,过滤非物模型属性 Map params = thingModelMessage.dataToMap(); - - // 物模型校验,过滤非物模型属性 - List functionList = iotThinkModelFunctionService - .getThinkModelFunctionListByProductKey(thingModelMessage.getProductKey()) - .stream() - .filter(function -> IotProductFunctionTypeEnum.PROPERTY.getType().equals(function.getType())) - .toList(); + List functionList = getValidFunctionList(thingModelMessage.getProductKey()); if (functionList.isEmpty()) { return; } - // 获取属性标识符集合 - // TODO @haohao:这个变量,可以和 “过滤并收集有效的属性字段” 那块,因为关联度高一点。另外,可以使用 CollectionUtils。convertSet - Set propertyIdentifiers = functionList.stream() - .map(IotThinkModelFunctionDO::getIdentifier) - .collect(Collectors.toSet()); + // 3. 过滤并收集有效的属性字段,缓存设备属性 + List schemaFieldValues = filterAndCollectValidFields(params, functionList, device, thingModelMessage.getTime()); + if (schemaFieldValues.size() == 1) { // 仅有时间字段,无需保存 + return; + } + + // 4. 构建并保存设备属性数据 + tdEngineDMLMapper.insertData(TdTableDO.builder() + .dataBaseName(getDatabaseName()) + .tableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())) + .columns(schemaFieldValues) + .build()); + } + + private List getValidFunctionList(String productKey) { + return iotThinkModelFunctionService + .getThinkModelFunctionListByProductKey(productKey) + .stream() + .filter(function -> IotProductFunctionTypeEnum.PROPERTY.getType().equals(function.getType())) + .toList(); + } + + private List filterAndCollectValidFields(Map params, List functionList, IotDeviceDO device, Long time) { + // 1. 获取属性标识符集合 + Set propertyIdentifiers = CollectionUtils.convertSet(functionList, IotThinkModelFunctionDO::getIdentifier); + + // 2. 构建属性标识符和属性的映射 Map functionMap = functionList.stream() .collect(Collectors.toMap(IotThinkModelFunctionDO::getIdentifier, function -> function)); - // 过滤并收集有效的属性字段 + // 3. 过滤并收集有效的属性字段 List schemaFieldValues = new ArrayList<>(); - schemaFieldValues.add(new TdFieldDO("time", thingModelMessage.getTime())); + schemaFieldValues.add(new TdFieldDO(TIME, time)); params.forEach((key, val) -> { if (propertyIdentifiers.contains(key)) { schemaFieldValues.add(new TdFieldDO(key.toLowerCase(), val)); // 缓存设备属性 // TODO @haohao:这个缓存的写入,可以使用的时候 cache 么?被动读 - setDeviceDataCache(device, functionMap.get(key), val, thingModelMessage.getTime()); + setDeviceDataCache(device, functionMap.get(key), val, time); } }); - // TODO @haohao:疑问,为什么 1 不继续哈? - if (schemaFieldValues.size() == 1) { - return; - } - - // 构建并保存设备属性数据 - tdEngineDataWriterService.insertData(TdTableDO.builder().build() - .setDataBaseName(getDatabaseName()) - .setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())) - .setColumns(schemaFieldValues)); + return schemaFieldValues; } /** @@ -132,7 +145,6 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ deviceDataRedisDAO.set(deviceData); } - // TODO @haohao:实现没问题哈。这个方法的空行有点多,逻辑分块上没这么明显。看看能不能改下。 /** * 创建设备数据表 * @@ -142,36 +154,37 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ * @param deviceKey 设备 Key */ private void createDeviceTable(Integer deviceType, String productKey, String deviceName, String deviceKey) { + // 1. 获取超级表名和数据库名 String superTableName = getProductPropertySTableName(deviceType, productKey); String dataBaseName = getDatabaseName(); - List> maps = tdEngineSuperTableService.describeSuperTable(new TdTableDO(dataBaseName, superTableName)); + // 2. 获取超级表的结构信息 + List> maps = tdEngineDDLMapper.describeSuperTable(new TdTableDO(dataBaseName, superTableName)); List tagsFieldValues = new ArrayList<>(); - if (maps != null) { - // TODO @haohao:一些字符串,是不是可以枚举起来哈。 - // TODO @haohao:这种过滤的,常用的,可以考虑用 CollectionUtils.filterList。一些常用的 stream 操作,适合封装哈 - List> taggedNotesList = maps.stream() - .filter(map -> "TAG".equals(map.get("note"))) - .toList(); + // 2.1 过滤出 TAG 类型的字段 + List> taggedNotesList = CollectionUtils.filterList(maps, map -> TAG_NOTE.equals(map.get(NOTE))); + + // 2.2 解析字段信息 tagsFieldValues = FieldParser.parse(taggedNotesList.stream() .map(map -> List.of(map.get("field"), map.get("type"), map.get("length"))) .collect(Collectors.toList())); + // 2.3 设置 TAG 字段的值 for (TdFieldDO tagsFieldValue : tagsFieldValues) { switch (tagsFieldValue.getFieldName()) { - case "product_key" -> tagsFieldValue.setFieldValue(productKey); - case "device_key" -> tagsFieldValue.setFieldValue(deviceKey); - case "device_name" -> tagsFieldValue.setFieldValue(deviceName); - case "device_type" -> tagsFieldValue.setFieldValue(deviceType); + case PRODUCT_KEY -> tagsFieldValue.setFieldValue(productKey); + case DEVICE_KEY -> tagsFieldValue.setFieldValue(deviceKey); + case DEVICE_NAME -> tagsFieldValue.setFieldValue(deviceName); + case DEVICE_TYPE -> tagsFieldValue.setFieldValue(deviceType); } } } - // 创建设备数据表 + // 3. 创建设备数据表 String tableName = getDeviceTableName(productKey, deviceName); - tdEngineTableService.createTable(TdTableDO.builder().build() + tdEngineDDLMapper.createTable(TdTableDO.builder().build() .setDataBaseName(dataBaseName) .setSuperTableName(superTableName) .setTableName(tableName) @@ -184,8 +197,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ * @return 数据库名称 */ private String getDatabaseName() { - // TODO @haohao:可以使用 StrUtil.subAftetLast 这种方法 - return url.substring(url.lastIndexOf("/") + 1); + return StrUtil.subAfter(url, "/", true); } /** @@ -198,9 +210,9 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ private static String getProductPropertySTableName(Integer deviceType, String productKey) { // TODO @haohao:枚举下,会好点哈。 return switch (deviceType) { - case 1 -> String.format("gateway_sub_%s", productKey).toLowerCase(); - case 2 -> String.format("gateway_%s", productKey).toLowerCase(); - default -> String.format("device_%s", productKey).toLowerCase(); + case 1 -> String.format(IotConstants.GATEWAY_SUB_STABLE_NAME_FORMAT, productKey).toLowerCase(); + case 2 -> String.format(IotConstants.GATEWAY_STABLE_NAME_FORMAT, productKey).toLowerCase(); + default -> String.format(IotConstants.DEVICE_STABLE_NAME_FORMAT, productKey).toLowerCase(); }; } @@ -212,7 +224,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ * @return 设备表名 */ private static String getDeviceTableName(String productKey, String deviceName) { - return String.format("device_%s_%s", productKey.toLowerCase(), deviceName.toLowerCase()); + return String.format(IotConstants.DEVICE_TABLE_NAME_FORMAT, productKey.toLowerCase(), deviceName.toLowerCase()); } } \ 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/tdengine/TdEngineDataWriterService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterService.java deleted file mode 100644 index 0995b0797..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterService.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; - -/** - * TD 引擎的数据写入 Service 接口 - */ -public interface TdEngineDataWriterService { - - /** - * 插入数据 - 指定列插入数据 - * - * @param table 数据 - * dataBaseName 数据库名 - * tableName 表名 - * columns 列 - */ - void insertData(TdTableDO table); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java deleted file mode 100644 index f4dd2c8fd..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDataWriterMapper; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Service; - -/** - * TD 引擎的数据写入 Service 实现类 - */ -@Service -public class TdEngineDataWriterServiceImpl implements TdEngineDataWriterService { - - @Resource - private TdEngineDataWriterMapper tdEngineDataWriterMapper; - - @Override - public void insertData(TdTableDO table) { - tdEngineDataWriterMapper.insertData(table); - } -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java deleted file mode 100644 index d895262cc..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -/** - * TD 引擎的数据库 Service 接口 - */ -public interface TdEngineDatabaseService { - - /** - * 创建数据库 - * - * @param dataBaseName 数据库名称 - */ - void createDatabase(String dataBaseName); -} \ 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/tdengine/TdEngineDatabaseServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseServiceImpl.java deleted file mode 100644 index c880db8a9..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseServiceImpl.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDatabaseMapper; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * TD 引擎的数据库 Service 实现类 - */ -@Service -@Slf4j -public class TdEngineDatabaseServiceImpl implements TdEngineDatabaseService { - - @Resource - private TdEngineDatabaseMapper tdEngineDatabaseMapper; - - @Override - public void createDatabase(String dataBaseName) { - tdEngineDatabaseMapper.createDatabase(dataBaseName); - } -} \ 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/tdengine/TdEngineQueryService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryService.java deleted file mode 100644 index 8d07b4334..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryService.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; - -import java.util.List; -import java.util.Map; - -/** - * TD 引擎的查询 Service 接口 - */ -public interface TdEngineQueryService { - - /** - * 获取历史数据 - * - * @param selectVisualDO 查询条件 - * @return 历史数据列表 - */ - List> getHistoryData(SelectVisualDO selectVisualDO); - - /** - * 获取历史数据条数 - * - * @param selectVisualDO 查询条件 - * @return 数据条数 - */ - Long getHistoryCount(SelectVisualDO selectVisualDO); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java deleted file mode 100644 index 672a58640..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineQueryMapper; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Map; - -@Service -public class TdEngineQueryServiceImpl implements TdEngineQueryService { - - @Resource - private TdEngineQueryMapper tdEngineQueryMapper; - - @Override - public List> getHistoryData(SelectVisualDO selectVisualDO) { - return tdEngineQueryMapper.getHistoryData(selectVisualDO); - } - - @Override - public Long getHistoryCount(SelectVisualDO selectVisualDO) { - return tdEngineQueryMapper.getHistoryCount(selectVisualDO); - } -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java deleted file mode 100644 index df6290a98..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java +++ /dev/null @@ -1,123 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; - -import java.util.List; -import java.util.Map; - -/** - * TD 引擎的超级表 Service 接口 - */ -public interface TdEngineSuperTableService { - - /** - * 创建超级表 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * columns 列信息 - * tags 标签信息 - */ - void createSuperTable(TdTableDO superTable); - - /** - * 查看超级表 - 显示当前数据库下的所有超级表信息 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - */ - - List> showSuperTables(TdTableDO superTable); - - /** - * 查看超级表 - 获取超级表的结构信息 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - */ - List> describeSuperTable(TdTableDO superTable); - - /** - * 修改超级表 - 增加列 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * column 列信息 - */ - void addColumnForSuperTable(TdTableDO superTable); - - /** - * 修改超级表 - 删除列 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * column 列信息 - */ - void dropColumnForSuperTable(TdTableDO superTable); - - /** - * 修改超级表 - 修改列宽 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * column 列信息 - */ - void modifyColumnWidthForSuperTable(TdTableDO superTable); - - - /** - * 修改超级表 - 为超级表添加标签 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * tag 标签信息 - */ - void addTagForSuperTable(TdTableDO superTable); - - /** - * 修改超级表 - 为超级表删除标签 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * tag 标签信息 - */ - void dropTagForSuperTable(TdTableDO superTable); - - /** - * 检查超级表是否存在 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * @return 超级表数量 - */ - Integer checkSuperTableExists(TdTableDO superTable); - - /** - * 为超级表添加列 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * columns 列信息 - */ - void addColumnsForSuperTable(TdTableDO superTable); - - /** - * 为超级表删除列 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * columns 列信息 - */ - void dropColumnsForSuperTable(TdTableDO superTable); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java deleted file mode 100644 index 60436e7bd..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java +++ /dev/null @@ -1,90 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineSuperTableMapper; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Map; - -/** - * TD 引擎的超级表 Service 实现类 - */ -@Slf4j -@Service -public class TdEngineSuperTableServiceImpl implements TdEngineSuperTableService { - - @Resource - private TdEngineSuperTableMapper tdEngineSuperTableMapper; - - @Override - public void createSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.createSuperTable(superTable); - } - - @Override - public List> showSuperTables(TdTableDO superTable) { - return tdEngineSuperTableMapper.showSuperTables(superTable); - } - - @Override - public List> describeSuperTable(TdTableDO superTable) { - return tdEngineSuperTableMapper.describeSuperTable(superTable); - } - - @Override - public void addColumnForSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.addColumnForSuperTable(superTable); - } - - @Override - public void dropColumnForSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.dropColumnForSuperTable(superTable); - } - - @Override - public void modifyColumnWidthForSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.modifyColumnWidthForSuperTable(superTable); - } - - @Override - public void addTagForSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.addTagForSuperTable(superTable); - } - - @Override - public void dropTagForSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.dropTagForSuperTable(superTable); - } - - @Override - public Integer checkSuperTableExists(TdTableDO superTable) { - List> results = tdEngineSuperTableMapper.showSuperTables(superTable); - return results == null || results.isEmpty() ? 0 : results.size(); - } - - @Override - public void addColumnsForSuperTable(TdTableDO superTable) { - for (TdFieldDO column : superTable.getColumns()) { - tdEngineSuperTableMapper.addColumnForSuperTable(TdTableDO.builder() - .dataBaseName(superTable.getDataBaseName()) - .superTableName(superTable.getSuperTableName()) - .column(column) - .build()); - } - } - - @Override - public void dropColumnsForSuperTable(TdTableDO superTable) { - for (TdFieldDO column : superTable.getColumns()) { - tdEngineSuperTableMapper.dropColumnForSuperTable(TdTableDO.builder() - .dataBaseName(superTable.getDataBaseName()) - .superTableName(superTable.getSuperTableName()) - .column(column) - .build()); - } - } -} \ 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/tdengine/TdEngineTableService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableService.java deleted file mode 100644 index 078159784..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableService.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; - -/** - * TD 引擎的表 Service 接口 - */ -public interface TdEngineTableService { - - /** - * 创建表 - 创建超级表的子表 - * - * @param table 表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * tableName 子表名称 - * tags TAG 字段 - */ - void createTable(TdTableDO table); - -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java deleted file mode 100644 index cdca47888..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineTableMapper; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * TD 引擎的表 Service 实现类 - */ -@Slf4j -@Service -public class TdEngineTableServiceImpl implements TdEngineTableService { - - @Resource - private TdEngineTableMapper tdEngineTableMapper; - - @Override - public void createTable(TdTableDO table) { - tdEngineTableMapper.createTable(table); - } -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDDLMapper.xml similarity index 70% rename from yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml rename to yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDDLMapper.xml index 37cf71910..091b77f64 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDDLMapper.xml @@ -2,7 +2,12 @@ - + + + + + CREATE DATABASE IF NOT EXISTS ${dataBaseName} + @@ -68,4 +73,29 @@ ALTER STABLE ${dataBaseName}.${superTableName} DROP TAG ${tag.fieldName} - + + + CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} + USING ${dataBaseName}.${superTableName} + TAGS + + #{item.fieldValue} + + + + + + CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} + USING ${dataBaseName}.${superTableName} + + #{item.fieldName} + + TAGS + + #{item.fieldValue} + + + + \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDMLMapper.xml similarity index 68% rename from yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml rename to yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDMLMapper.xml index f4361bc67..0443a826b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDMLMapper.xml @@ -2,7 +2,21 @@ - + + + + + INSERT INTO ${dataBaseName}.${tableName} + + ${item.fieldName} + + VALUES + + #{item.fieldValue} + + - SELECT COUNT(0) AS count FROM ${dataBaseName}.${tableName} @@ -20,14 +34,14 @@ - + SELECT LAST(time), * FROM ${tableName} WHERE device_id = #{deviceId} - SELECT LAST(*) FROM ${dataBaseName}.${stableName} @@ -35,7 +49,7 @@ - SELECT ${fieldName} AS data, time FROM ${dataBaseName}.${tableName} @@ -46,14 +60,14 @@ - SELECT ${fieldName}, time FROM ${dataBaseName}.${tableName} - SELECT ${aggregate}(${fieldName}) FROM ${dataBaseName}.${tableName} @@ -62,11 +76,11 @@ - + SELECT COUNT(time) FROM ${dataBaseName}.${tableName} WHERE time BETWEEN #{startTime} AND #{endTime} AND ${fieldName} IS NOT NULL - + \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml deleted file mode 100644 index dd38cd08e..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - INSERT INTO ${dataBaseName}.${tableName} - - ${item.fieldName} - - VALUES - - #{item.fieldValue} - - - - \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml deleted file mode 100644 index 919c301f7..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - CREATE DATABASE IF NOT EXISTS ${dataBaseName} - - - \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml deleted file mode 100644 index 867ef8f43..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} - USING ${dataBaseName}.${superTableName} - TAGS - - #{item.fieldValue} - - - - - - CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} - USING ${dataBaseName}.${superTableName} - - #{item.fieldName} - - TAGS - - #{item.fieldValue} - - - - \ No newline at end of file From ce919d12d1b079ace85c70004bd6553053b76667 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 5 Dec 2024 21:45:48 +0800 Subject: [PATCH 013/228] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91IoT=EF=BC=9Atdengine=20=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/controller/admin/device/IotDeviceDataController.java | 2 ++ .../yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java | 1 - .../module/iot/service/device/IotDeviceDataServiceImpl.java | 2 +- .../module/iot/service/device/IotDeviceServiceImpl.java | 2 +- .../service/tdengine/IotThingModelMessageServiceImpl.java | 5 +---- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java index 72fdda8c8..77bc78c66 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java @@ -31,6 +31,7 @@ public class IotDeviceDataController { @Resource private IotDeviceDataService deviceDataService; + // TODO @浩浩:这里的 /latest-list,包括方法名。 @GetMapping("/latest") @Operation(summary = "获取设备属性最新数据") public CommonResult> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { @@ -38,6 +39,7 @@ public class IotDeviceDataController { return success(BeanUtils.toBean(list, IotDeviceDataRespVO.class)); } + // TODO @浩浩:这里的 /history-page 包括方法名。 @GetMapping("/history") @Operation(summary = "获取设备属性历史数据") public CommonResult> getHistoryDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java index 640255940..3d7aa84dd 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.iot.dal.tdengine; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java index 7d10977f9..d68287cd4 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java @@ -133,7 +133,7 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { } private static String getDeviceTableName(String productKey, String deviceName) { - return String.format(IotConstants.DEVICE_TABLE_NAME_FORMAT, productKey, deviceName); + return String.format(IotConstants.DEVICE_TABLE_NAME_FORMAT, productKey, deviceName); } } \ 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/IotDeviceServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java index 58918c130..bb302a22f 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 @@ -139,13 +139,13 @@ public class IotDeviceServiceImpl implements IotDeviceService { * @return 生成的 MQTT Password */ private String generateMqttPassword() { + // TODO @浩浩:这里的 StrUtil 随机字符串? SecureRandom secureRandom = new SecureRandom(); byte[] passwordBytes = new byte[32]; // 256 位的随机数 secureRandom.nextBytes(passwordBytes); return Base64.getUrlEncoder().withoutPadding().encodeToString(passwordBytes); } - /** * 生成唯一的 DeviceName * diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java index 92a30ebb0..9ffb47715 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java @@ -66,8 +66,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ if (IotDeviceStatusEnum.INACTIVE.getStatus().equals(device.getStatus())) { createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO() - .setId(device.getId()) - .setStatus(IotDeviceStatusEnum.ONLINE.getStatus())); + .setId(device.getId()).setStatus(IotDeviceStatusEnum.ONLINE.getStatus())); } // 2. 获取设备属性并进行物模型校验,过滤非物模型属性 @@ -77,7 +76,6 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ return; } - // 3. 过滤并收集有效的属性字段,缓存设备属性 List schemaFieldValues = filterAndCollectValidFields(params, functionList, device, thingModelMessage.getTime()); if (schemaFieldValues.size() == 1) { // 仅有时间字段,无需保存 @@ -165,7 +163,6 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ // 2.1 过滤出 TAG 类型的字段 List> taggedNotesList = CollectionUtils.filterList(maps, map -> TAG_NOTE.equals(map.get(NOTE))); - // 2.2 解析字段信息 tagsFieldValues = FieldParser.parse(taggedNotesList.stream() .map(map -> List.of(map.get("field"), map.get("type"), map.get("length"))) From 3a2c691af085c4e649373961e827627b8fcfaf9a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 7 Dec 2024 16:42:56 +0800 Subject: [PATCH 014/228] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E3=80=91IoT=EF=BC=9A=E4=BA=A7=E5=93=81=E5=88=86?= =?UTF-8?q?=E7=B1=BB=E7=9A=84=E7=BB=B4=E6=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/iot/enums/ErrorCodeConstants.java | 9 ++- .../product/IotProductCategoryController.java | 72 +++++++++++++++++++ .../admin/product/vo/IotProductSaveReqVO.java | 6 +- .../category/IotProductCategoryPageReqVO.java | 27 +++++++ .../vo/category/IotProductCategoryRespVO.java | 33 +++++++++ .../category/IotProductCategorySaveReqVO.java | 29 ++++++++ .../product/IotProductCategoryDO.java | 48 +++++++++++++ .../product/IotProductCategoryMapper.java | 25 +++++++ .../product/IotProductCategoryService.java | 54 ++++++++++++++ .../IotProductCategoryServiceImpl.java | 70 ++++++++++++++++++ 10 files changed, 369 insertions(+), 4 deletions(-) create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryPageReqVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryRespVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategorySaveReqVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductCategoryDO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductCategoryMapper.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryService.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryServiceImpl.java 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 be9d28ecb..1e947e633 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 @@ -9,20 +9,20 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; */ public interface ErrorCodeConstants { - // ========== IoT 产品相关 1-050-001-000 ============ + // ========== 产品相关 1-050-001-000 ============ ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_050_001_000, "产品不存在"); ErrorCode PRODUCT_IDENTIFICATION_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在"); ErrorCode PRODUCT_STATUS_NOT_DELETE = new ErrorCode(1_050_001_002, "产品状是发布状态,不允许删除"); ErrorCode PRODUCT_STATUS_NOT_ALLOW_FUNCTION = new ErrorCode(1_050_001_003, "产品状是发布状态,不允许操作物模型"); - // ========== IoT 产品物模型 1-050-002-000 ============ + // ========== 产品物模型 1-050-002-000 ============ ErrorCode THINK_MODEL_FUNCTION_NOT_EXISTS = new ErrorCode(1_050_002_000, "产品物模型不存在"); ErrorCode THINK_MODEL_FUNCTION_EXISTS_BY_PRODUCT_KEY = new ErrorCode(1_050_002_001, "ProductKey 对应的产品物模型已存在"); ErrorCode THINK_MODEL_FUNCTION_IDENTIFIER_EXISTS = new ErrorCode(1_050_002_002, "存在重复的功能标识符。"); ErrorCode THINK_MODEL_FUNCTION_NAME_EXISTS = new ErrorCode(1_050_002_003, "存在重复的功能名称。"); ErrorCode THINK_MODEL_FUNCTION_IDENTIFIER_INVALID = new ErrorCode(1_050_002_003, "产品物模型标识无效"); - // ========== IoT 设备 1-050-003-000 ============ + // ========== 设备 1-050-003-000 ============ ErrorCode DEVICE_NOT_EXISTS = new ErrorCode(1_050_003_000, "设备不存在"); ErrorCode DEVICE_NAME_EXISTS = new ErrorCode(1_050_003_001, "设备名称在同一产品下必须唯一"); ErrorCode DEVICE_HAS_CHILDREN = new ErrorCode(1_050_003_002, "有子设备,不允许删除"); @@ -30,4 +30,7 @@ public interface ErrorCodeConstants { ErrorCode DEVICE_PRODUCT_CANNOT_BE_MODIFIED = new ErrorCode(1_050_003_004, "产品不能修改"); ErrorCode DEVICE_INVALID_DEVICE_STATUS = new ErrorCode(1_050_003_005, "无效的设备状态"); + // ========== 产品分类 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/controller/admin/product/IotProductCategoryController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java new file mode 100644 index 000000000..b365ddea1 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.iot.controller.admin.product; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +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.product.vo.category.IotProductCategoryPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategoryRespVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategorySaveReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO; +import cn.iocoder.yudao.module.iot.service.product.IotProductCategoryService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - IoT 产品分类") +@RestController +@RequestMapping("/iot/product-category") +@Validated +public class IotProductCategoryController { + + @Resource + private IotProductCategoryService productCategoryService; + + @PostMapping("/create") + @Operation(summary = "创建IoT 产品分类") + @PreAuthorize("@ss.hasPermission('iot:product-category:create')") + public CommonResult createProductCategory(@Valid @RequestBody IotProductCategorySaveReqVO createReqVO) { + return success(productCategoryService.createProductCategory(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新IoT 产品分类") + @PreAuthorize("@ss.hasPermission('iot:product-category:update')") + public CommonResult updateProductCategory(@Valid @RequestBody IotProductCategorySaveReqVO updateReqVO) { + productCategoryService.updateProductCategory(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除IoT 产品分类") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('iot:product-category:delete')") + public CommonResult deleteProductCategory(@RequestParam("id") Long id) { + productCategoryService.deleteProductCategory(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得IoT 产品分类") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('iot:product-category:query')") + public CommonResult getProductCategory(@RequestParam("id") Long id) { + IotProductCategoryDO productCategory = productCategoryService.getProductCategory(id); + return success(BeanUtils.toBean(productCategory, IotProductCategoryRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得IoT 产品分类分页") + @PreAuthorize("@ss.hasPermission('iot:product-category:query')") + public CommonResult> getProductCategoryPage(@Valid IotProductCategoryPageReqVO pageReqVO) { + PageResult pageResult = productCategoryService.getProductCategoryPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, IotProductCategoryRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java index 254b6b9da..757750544 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java @@ -14,9 +14,13 @@ public class IotProductSaveReqVO { @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.AUTO, example = "1") private Long id; - @Schema(description = "产品Key", requiredMode = Schema.RequiredMode.AUTO, example = "12345abc") + @Schema(description = "产品 Key", requiredMode = Schema.RequiredMode.AUTO, example = "12345abc") private String productKey; + // TODO 芋艿:品类 + + // TODO 芋艿:【待确定】保活时长、产品图标、产品图片 + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "温湿度") @NotEmpty(message = "产品名称不能为空") private String name; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryPageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryPageReqVO.java new file mode 100644 index 000000000..90d338a89 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryPageReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.category; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - IoT 产品分类分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class IotProductCategoryPageReqVO extends PageParam { + + @Schema(description = "分类名字", example = "王五") + private String name; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryRespVO.java new file mode 100644 index 000000000..d684b0215 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryRespVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.category; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - IoT 产品分类 Response VO") +@Data +public class IotProductCategoryRespVO { + + @Schema(description = "分类 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "25284") + private Long id; + + @Schema(description = "分类名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") + private String name; + + @Schema(description = "分类排序") + private Integer sort; + + @Schema(description = "分类状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "分类描述", example = "随便") + private String description; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategorySaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategorySaveReqVO.java new file mode 100644 index 000000000..a7b2fe427 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategorySaveReqVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.category; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - IoT 产品分类新增/修改 Request VO") +@Data +public class IotProductCategorySaveReqVO { + + @Schema(description = "分类 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "25284") + private Long id; + + @Schema(description = "分类名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") + @NotEmpty(message = "分类名字不能为空") + private String name; + + @Schema(description = "分类排序") + private Integer sort; + + @Schema(description = "分类状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "分类状态不能为空") + private Integer status; + + @Schema(description = "分类描述", example = "随便") + private String description; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductCategoryDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductCategoryDO.java new file mode 100644 index 000000000..a6510488c --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductCategoryDO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.product; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * IoT 产品分类 DO + * + * @author 芋道源码 + */ +@TableName("iot_product_category") +@KeySequence("iot_product_category_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class IotProductCategoryDO extends BaseDO { + + /** + * 分类 ID + */ + @TableId + private Long id; + /** + * 分类名字 + */ + private String name; + /** + * 分类排序 + */ + private Integer sort; + /** + * 分类状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 分类描述 + */ + private String description; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductCategoryMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductCategoryMapper.java new file mode 100644 index 000000000..845eded14 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductCategoryMapper.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.iot.dal.mysql.product; + +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.module.iot.controller.admin.product.vo.category.IotProductCategoryPageReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * IoT 产品分类 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface IotProductCategoryMapper extends BaseMapperX { + + default PageResult selectPage(IotProductCategoryPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(IotProductCategoryDO::getName, reqVO.getName()) + .betweenIfPresent(IotProductCategoryDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(IotProductCategoryDO::getId)); + } + +} \ 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/IotProductCategoryService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryService.java new file mode 100644 index 000000000..9830ec8b9 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryService.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.iot.service.product; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategoryPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategorySaveReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO; +import jakarta.validation.Valid; + +/** + * IoT 产品分类 Service 接口 + * + * @author 芋道源码 + */ +public interface IotProductCategoryService { + + /** + * 创建IoT 产品分类 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProductCategory(@Valid IotProductCategorySaveReqVO createReqVO); + + /** + * 更新IoT 产品分类 + * + * @param updateReqVO 更新信息 + */ + void updateProductCategory(@Valid IotProductCategorySaveReqVO updateReqVO); + + /** + * 删除IoT 产品分类 + * + * @param id 编号 + */ + void deleteProductCategory(Long id); + + /** + * 获得IoT 产品分类 + * + * @param id 编号 + * @return IoT 产品分类 + */ + IotProductCategoryDO getProductCategory(Long id); + + /** + * 获得IoT 产品分类分页 + * + * @param pageReqVO 分页查询 + * @return IoT 产品分类分页 + */ + PageResult getProductCategoryPage(IotProductCategoryPageReqVO pageReqVO); + +} \ 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/IotProductCategoryServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryServiceImpl.java new file mode 100644 index 000000000..579d27cfb --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryServiceImpl.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.iot.service.product; + +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.product.vo.category.IotProductCategoryPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategorySaveReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO; +import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductCategoryMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PRODUCT_CATEGORY_NOT_EXISTS; + +/** + * IoT 产品分类 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class IotProductCategoryServiceImpl implements IotProductCategoryService { + + @Resource + private IotProductCategoryMapper productCategoryMapper; + + @Override + public Long createProductCategory(IotProductCategorySaveReqVO createReqVO) { + // 插入 + IotProductCategoryDO productCategory = BeanUtils.toBean(createReqVO, IotProductCategoryDO.class); + productCategoryMapper.insert(productCategory); + // 返回 + return productCategory.getId(); + } + + @Override + public void updateProductCategory(IotProductCategorySaveReqVO updateReqVO) { + // 校验存在 + validateProductCategoryExists(updateReqVO.getId()); + // 更新 + IotProductCategoryDO updateObj = BeanUtils.toBean(updateReqVO, IotProductCategoryDO.class); + productCategoryMapper.updateById(updateObj); + } + + @Override + public void deleteProductCategory(Long id) { + // 校验存在 + validateProductCategoryExists(id); + // 删除 + productCategoryMapper.deleteById(id); + } + + private void validateProductCategoryExists(Long id) { + if (productCategoryMapper.selectById(id) == null) { + throw exception(PRODUCT_CATEGORY_NOT_EXISTS); + } + } + + @Override + public IotProductCategoryDO getProductCategory(Long id) { + return productCategoryMapper.selectById(id); + } + + @Override + public PageResult getProductCategoryPage(IotProductCategoryPageReqVO pageReqVO) { + return productCategoryMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file From 9b9fd30c90bfb88d1ad61ef314ffab73e18264ea Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 7 Dec 2024 18:50:31 +0800 Subject: [PATCH 015/228] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E3=80=91IoT=EF=BC=9A=E4=BA=A7=E5=93=81=E6=94=BE?= =?UTF-8?q?=E5=88=B0=20product=20=E5=AD=90=E7=9B=AE=E5=BD=95=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/product/IotProductController.java | 13 +++--- .../product/vo/IotProductSimpleRespVO.java | 16 ------- .../vo/{ => product}/IotProductPageReqVO.java | 2 +- .../vo/{ => product}/IotProductRespVO.java | 43 +++++++++++-------- .../vo/{ => product}/IotProductSaveReqVO.java | 28 +++++++----- .../dal/dataobject/product/IotProductDO.java | 15 +++++-- .../dal/mysql/product/IotProductMapper.java | 2 +- .../service/product/IotProductService.java | 4 +- .../product/IotProductServiceImpl.java | 5 +-- .../dal/dataobject/notify/PayNotifyLogDO.java | 2 +- .../dataobject/notify/PayNotifyTaskDO.java | 4 +- 11 files changed, 68 insertions(+), 66 deletions(-) delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSimpleRespVO.java rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/{ => product}/IotProductPageReqVO.java (88%) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/{ => product}/IotProductRespVO.java (85%) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/{ => product}/IotProductSaveReqVO.java (82%) 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 e7f41d91d..a4d111a99 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 @@ -3,10 +3,9 @@ package cn.iocoder.yudao.module.iot.controller.admin.product; import cn.iocoder.yudao.framework.common.pojo.CommonResult; 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.product.vo.IotProductPageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductRespVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSimpleRespVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductRespVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductSaveReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.service.product.IotProductService; import io.swagger.v3.oas.annotations.Operation; @@ -21,6 +20,7 @@ import org.springframework.web.bind.annotation.*; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @Tag(name = "管理后台 - IoT 产品") @RestController @@ -86,9 +86,10 @@ public class IotProductController { @GetMapping("/simple-list") @Operation(summary = "获得所有产品列表") @PreAuthorize("@ss.hasPermission('iot:product:query')") - public CommonResult> getSimpleProductList() { + public CommonResult> getSimpleProductList() { List list = productService.getProductList(); - return success(BeanUtils.toBean(list, IotProductSimpleRespVO.class)); + return success(convertList(list, product -> // 只返回 id、name 字段 + new IotProductRespVO().setId(product.getId()).setName(product.getName()))); } } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSimpleRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSimpleRespVO.java deleted file mode 100644 index 83855eaaf..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSimpleRespVO.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.iot.controller.admin.product.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - IoT 产品 Response VO") -@Data -public class IotProductSimpleRespVO { - - @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "26087") - private Long id; - - @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") - private String name; - -} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductPageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductPageReqVO.java similarity index 88% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductPageReqVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductPageReqVO.java index 3437f563f..d54adec48 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductPageReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.iot.controller.admin.product.vo; +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.product; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java similarity index 85% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductRespVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java index 0958b3e84..65d26ff5b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductRespVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.iot.controller.admin.product.vo; +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.product; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; @@ -20,34 +20,23 @@ public class IotProductRespVO { @ExcelProperty("产品名称") private String name; - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("创建时间") - private LocalDateTime createTime; - @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("产品标识") private String productKey; - @Schema(description = "接入网关协议", example = "2") - @ExcelProperty("接入网关协议") - private Integer protocolType; - - @Schema(description = "协议编号(脚本解析 id)", requiredMode = Schema.RequiredMode.REQUIRED, example = "13177") - @ExcelProperty("协议编号(脚本解析 id)") - private Long protocolId; - - @Schema(description = "产品所属品类标识符", example = "14237") - @ExcelProperty("产品所属品类标识符") + @Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long categoryId; + @Schema(description = "产品图标", example = "https://iocoder.cn/1.svg") + private String icon; + + @Schema(description = "产品图标", example = "https://iocoder.cn/1.png") + private String picUrl; + @Schema(description = "产品描述", example = "你猜") @ExcelProperty("产品描述") private String description; - @Schema(description = "数据校验级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @ExcelProperty("数据校验级别") - private Integer validateType; - @Schema(description = "产品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @ExcelProperty("产品状态") private Integer status; @@ -60,8 +49,24 @@ public class IotProductRespVO { @ExcelProperty("联网方式") private Integer netType; + @Schema(description = "接入网关协议", example = "2") + @ExcelProperty("接入网关协议") + private Integer protocolType; + + @Schema(description = "协议编号(脚本解析 id)", requiredMode = Schema.RequiredMode.REQUIRED, example = "13177") + @ExcelProperty("协议编号(脚本解析 id)") + private Long protocolId; + @Schema(description = "数据格式") @ExcelProperty("数据格式") private Integer dataFormat; + @Schema(description = "数据校验级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("数据校验级别") + private Integer validateType; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductSaveReqVO.java similarity index 82% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductSaveReqVO.java index 757750544..31890beb7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductSaveReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.iot.controller.admin.product.vo; +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.product; import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.module.iot.enums.product.*; @@ -14,17 +14,26 @@ public class IotProductSaveReqVO { @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.AUTO, example = "1") private Long id; - @Schema(description = "产品 Key", requiredMode = Schema.RequiredMode.AUTO, example = "12345abc") - private String productKey; - - // TODO 芋艿:品类 - - // TODO 芋艿:【待确定】保活时长、产品图标、产品图片 - @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "温湿度") @NotEmpty(message = "产品名称不能为空") private String name; + @Schema(description = "产品 Key", requiredMode = Schema.RequiredMode.AUTO, example = "12345abc") + private String productKey; + + @Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "产品分类编号不能为空") + private Long categoryId; + + @Schema(description = "产品图标", example = "https://iocoder.cn/1.svg") + private String icon; + + @Schema(description = "产品图标", example = "https://iocoder.cn/1.png") + private String picUrl; + + @Schema(description = "产品描述", example = "描述") + private String description; + @Schema(description = "设备类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") @InEnum(value = IotProductDeviceTypeEnum.class, message = "设备类型必须是 {value}") @NotNull(message = "设备类型不能为空") @@ -48,7 +57,4 @@ public class IotProductSaveReqVO { @NotNull(message = "数据校验级别不能为空") private Integer validateType; - @Schema(description = "产品描述", example = "描述") - private String description; - } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java index eef466eda..34fd35706 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java @@ -22,7 +22,7 @@ import lombok.*; public class IotProductDO extends BaseDO { /** - * 产品ID + * 产品 ID */ @TableId private Long id; @@ -30,17 +30,24 @@ public class IotProductDO extends BaseDO { * 产品名称 */ private String name; - // TODO @haohao:这个字段,要不改成 identifier,和阿里云更统一些 /** * 产品标识 */ private String productKey; /** - * 产品所属品类编号 + * 产品分类编号 * - * TODO 外键:后续加 + * 关联 {@link IotProductCategoryDO#getId()} */ private Long categoryId; + /** + * 产品图标 + */ + private String icon; + /** + * 产品图片 + */ + private String picUrl; /** * 产品描述 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java index 0341e2492..eac1d29e8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.dal.mysql.product; 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.module.iot.controller.admin.product.vo.IotProductPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import org.apache.ibatis.annotations.Mapper; 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 3fff94fd9..bcbf13ef4 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 @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.iot.service.product; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductPageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductSaveReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import jakarta.validation.Valid; 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 d0ca09288..259bcaa1f 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 @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.iot.service.product; 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.product.vo.IotProductPageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductSaveReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductMapper; import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum; @@ -14,7 +14,6 @@ import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.util.List; diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java index a482605d5..384628370 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java @@ -44,7 +44,7 @@ public class PayNotifyLogDO extends BaseDO { /** * 支付通知状态 * - * 外键 {@link PayNotifyStatusEnum} + * 枚举 {@link PayNotifyStatusEnum} */ private Integer status; diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java index 7bfabad3f..9f9ee7fef 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java @@ -52,7 +52,7 @@ public class PayNotifyTaskDO extends TenantBaseDO { /** * 通知类型 * - * 外键 {@link PayNotifyTypeEnum} + * 枚举 {@link PayNotifyTypeEnum} */ private Integer type; /** @@ -73,7 +73,7 @@ public class PayNotifyTaskDO extends TenantBaseDO { /** * 通知状态 * - * 外键 {@link PayNotifyStatusEnum} + * 枚举 {@link PayNotifyStatusEnum} */ private Integer status; /** From a8c87d168accd14f5b266be9815046b1b45ff9db Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 7 Dec 2024 19:50:07 +0800 Subject: [PATCH 016/228] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E3=80=91IoT=EF=BC=9A=E4=BA=A7=E5=93=81=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=97=B6=EF=BC=8CproductKey=20=E7=94=B1=E5=89=8D?= =?UTF-8?q?=E7=AB=AF=E7=94=9F=E6=88=90=EF=BC=9B=E5=90=8C=E6=97=B6=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20icon=E3=80=81picUrl=20=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/iot/enums/ErrorCodeConstants.java | 2 +- .../enums/product/IotProductStatusEnum.java | 4 +-- .../product/IotProductCategoryController.java | 24 +++++++++++--- .../product/IotProductCategoryMapper.java | 6 ++++ .../product/IotProductCategoryService.java | 24 ++++++++++---- .../IotProductCategoryServiceImpl.java | 7 ++++ .../product/IotProductServiceImpl.java | 32 ++++--------------- .../IotThinkModelFunctionServiceImpl.java | 2 +- 8 files changed, 60 insertions(+), 41 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 1e947e633..d1d350d5e 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 @@ -11,7 +11,7 @@ public interface ErrorCodeConstants { // ========== 产品相关 1-050-001-000 ============ ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_050_001_000, "产品不存在"); - ErrorCode PRODUCT_IDENTIFICATION_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在"); + ErrorCode PRODUCT_KEY_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在"); ErrorCode PRODUCT_STATUS_NOT_DELETE = new ErrorCode(1_050_001_002, "产品状是发布状态,不允许删除"); ErrorCode PRODUCT_STATUS_NOT_ALLOW_FUNCTION = new ErrorCode(1_050_001_003, "产品状是发布状态,不允许操作物模型"); diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java index e64a3d678..7b4d90a5a 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java @@ -18,12 +18,12 @@ public enum IotProductStatusEnum implements IntArrayValuable { UNPUBLISHED(0, "开发中"), PUBLISHED(1, "已发布"); - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(IotProductStatusEnum::getType).toArray(); + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(IotProductStatusEnum::getStatus).toArray(); /** * 类型 */ - private final Integer type; + private final Integer status; /** * 描述 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java index b365ddea1..bc1c1fbf2 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.iot.controller.admin.product; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -17,7 +18,10 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.List; + import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @Tag(name = "管理后台 - IoT 产品分类") @RestController @@ -29,14 +33,14 @@ public class IotProductCategoryController { private IotProductCategoryService productCategoryService; @PostMapping("/create") - @Operation(summary = "创建IoT 产品分类") + @Operation(summary = "创建产品分类") @PreAuthorize("@ss.hasPermission('iot:product-category:create')") public CommonResult
+ * * @param dataBaseName 数据库名称 + * * @param superTableName 超级表名称 + */ + @InterceptorIgnore(tenantLine = "true") + List> describeSuperTable(@Param("dataBaseName") String dataBaseName, + @Param("superTableName") String superTableName); + + /** + * 为超级表添加列 + * + * @param dataBaseName 数据库名称 + * @param superTableName 超级表名称 + * @param field 字段信息 + */ + @InterceptorIgnore(tenantLine = "true") + void addColumnForSuperTable(@Param("dataBaseName") String dataBaseName, + @Param("superTableName") String superTableName, + @Param("field") TdFieldDO field); + + /** + * 为超级表删除列 + * + * @param dataBaseName 数据库名称 + * @param superTableName 超级表名称 + * @param field 字段信息 + */ + @InterceptorIgnore(tenantLine = "true") + void dropColumnForSuperTable(@Param("dataBaseName") String dataBaseName, + @Param("superTableName") String superTableName, + @Param("field") TdFieldDO field); + void createTable(TableDto tableDto); void insertData(TableDto tableDto); List> selectByTimestamp(SelectDto selectDto); - void addColumnForSuperTable(@Param("superTableName") String superTableName, - @Param("fieldsVo") FieldsVo fieldsVo); - - void dropColumnForSuperTable(@Param("superTableName") String superTableName, - @Param("fieldsVo") FieldsVo fieldsVo); void addTagForSuperTable(@Param("superTableName") String superTableName, @Param("fieldsVo") FieldsVo fieldsVo); @@ -44,14 +101,6 @@ public interface TdEngineMapper { Map getCountByTimestamp(SelectDto selectDto); - /** - * 检查表是否存在 - * - * @param dataBaseName 数据库名称 - * @param tableName 表名称 - */ - Integer checkTableExists(@Param("dataBaseName") String dataBaseName, @Param("tableName") String tableName); - Map getLastData(SelectDto selectDto); List> getHistoryData(SelectVisualDto selectVisualDto); @@ -62,13 +111,5 @@ public interface TdEngineMapper { List> getLastDataByTags(TagsSelectDao tagsSelectDao); - /** - * 创建超级表 - * - * @param sql sql - * @return 返回值 - */ - @InterceptorIgnore(tenantLine = "true") - Integer createSuperTableDevice(String sql); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java index f8dd6feb5..d42fd72fc 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java @@ -1,19 +1,22 @@ package cn.iocoder.yudao.module.iot.service.tdengine; -import cn.hutool.json.JSONUtil; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty; import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelRespVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.*; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdRestApi; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineMapper; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; @@ -22,147 +25,206 @@ import java.util.stream.Collectors; public class IotDbStructureDataServiceImpl implements IotDbStructureDataService { @Resource - private TdEngineMapper tdEngineMapper; + private TdEngineService tdEngineService; @Resource private TdRestApi tdRestApi; + @Value("${spring.datasource.dynamic.datasource.tdengine.url}") + private String url; + @Override public void createSuperTable(ThingModelRespVO thingModel, Integer deviceType) { - // 获取物模型中的属性定义 - List fields = FieldParser.parse(thingModel); - String tbName = getProductPropertySTableName(deviceType, thingModel.getProductKey()); + // 1. 解析物模型,获得字段列表 + List schemaFields = new ArrayList<>(); + schemaFields.add(TdFieldDO.builder(). + fieldName("time"). + dataType("TIMESTAMP"). + build()); + schemaFields.addAll(FieldParser.parse(thingModel)); - // 生成创建超级表的 SQL - String sql = TableManager.getCreateSTableSql(tbName, fields, new TdField("device_id", "NCHAR", 64)); - if (sql == null) { - log.warn("生成的 SQL 为空,无法创建超级表"); - return; - } - log.info("执行 SQL: {}", sql); + // 3. 设置超级表的标签 + List tagsFields = new ArrayList<>(); + tagsFields.add(TdFieldDO.builder(). + fieldName("product_key"). + dataType("NCHAR"). + dataLength(64). + build()); + tagsFields.add(TdFieldDO.builder(). + fieldName("device_key"). + dataType("NCHAR"). + dataLength(64). + build()); + tagsFields.add(TdFieldDO.builder(). + fieldName("device_name"). + dataType("NCHAR"). + dataLength(64). + build()); + // 年 + tagsFields.add(TdFieldDO.builder(). + fieldName("year"). + dataType("INT"). + build()); + // 月 + tagsFields.add(TdFieldDO.builder(). + fieldName("month"). + dataType("INT"). + build()); + // 日 + tagsFields.add(TdFieldDO.builder(). + fieldName("day"). + dataType("INT"). + build()); + // 时 + tagsFields.add(TdFieldDO.builder(). + fieldName("hour"). + dataType("INT"). + build()); - // 执行 SQL 创建超级表 - tdEngineMapper.createSuperTableDevice(sql); + + // 4. 获取超级表的名称 + String superTableName = getProductPropertySTableName(deviceType, thingModel.getProductKey()); + + // 5. 创建超级表 + String dataBaseName = url.substring(url.lastIndexOf("/") + 1); + tdEngineService.createSuperTable(schemaFields, tagsFields, dataBaseName, superTableName); } @Override public void updateSuperTable(ThingModelRespVO thingModel, Integer deviceType) { try { - // 获取旧字段信息 String tbName = getProductPropertySTableName(deviceType, thingModel.getProductKey()); - String sql = TableManager.getDescTableSql(tbName); - TdResponse response = tdRestApi.execSql(sql); - if (response.getCode() != TdResponse.CODE_SUCCESS) { - throw new RuntimeException("获取表描述错误: " + JSONUtil.toJsonStr(response)); - } + List oldFields = getTableFields(tbName); + List newFields = FieldParser.parse(thingModel); - List oldFields = FieldParser.parse(response.getData()); - List newFields = FieldParser.parse(thingModel); - - // 找出新增的字段 - List addFields = newFields.stream() - .filter(f -> oldFields.stream().noneMatch(old -> old.getName().equals(f.getName()))) - .collect(Collectors.toList()); - if (!addFields.isEmpty()) { - sql = TableManager.getAddSTableColumnSql(tbName, addFields); - response = tdRestApi.execSql(sql); - if (response.getCode() != TdResponse.CODE_SUCCESS) { - throw new RuntimeException("添加表字段错误: " + JSONUtil.toJsonStr(response)); - } - } - - // 找出修改的字段 - List modifyFields = newFields.stream() - .filter(f -> oldFields.stream().anyMatch(old -> - old.getName().equals(f.getName()) && - (!old.getType().equals(f.getType()) || old.getLength() != f.getLength()))) - .collect(Collectors.toList()); - if (!modifyFields.isEmpty()) { - sql = TableManager.getModifySTableColumnSql(tbName, modifyFields); - response = tdRestApi.execSql(sql); - if (response.getCode() != TdResponse.CODE_SUCCESS) { - throw new RuntimeException("修改表字段错误: " + JSONUtil.toJsonStr(response)); - } - } - - // 找出删除的字段 - List dropFields = oldFields.stream() - .filter(f -> !"time".equals(f.getName()) && !"device_id".equals(f.getName()) && - newFields.stream().noneMatch(n -> n.getName().equals(f.getName()))) - .collect(Collectors.toList()); - if (!dropFields.isEmpty()) { - sql = TableManager.getDropSTableColumnSql(tbName, dropFields); - response = tdRestApi.execSql(sql); - if (response.getCode() != TdResponse.CODE_SUCCESS) { - throw new RuntimeException("删除表字段错误: " + JSONUtil.toJsonStr(response)); - } - } + updateTableFields(tbName, oldFields, newFields); } catch (Throwable e) { log.error("更新物模型超级表失败", e); } } + // 获取表字段 + private List getTableFields(String tableName) { + List fields = new ArrayList<>(); + // 获取超级表的描述信息 + List> maps = tdEngineService.describeSuperTable(url.substring(url.lastIndexOf("/") + 1), tableName); + if (maps != null) { + // 过滤掉 note 字段为 TAG 的记录 + maps = maps.stream().filter(map -> !"TAG".equals(map.get("note"))).toList(); + // 过滤掉 time 字段 + maps = maps.stream().filter(map -> !"time".equals(map.get("field"))).toList(); + // 解析字段信息 + fields = FieldParser.parse(maps.stream() + .map(map -> List.of(map.get("field"), map.get("type"), map.get("length"))) + .collect(Collectors.toList())); + } + return fields; + } + + // 更新表字段 + private void updateTableFields(String tableName, List oldFields, List newFields) { + // 获取新增字段 + List addFields = getAddFields(oldFields, newFields); + // 获取修改字段 + List modifyFields = getModifyFields(oldFields, newFields); + // 获取删除字段 + List dropFields = getDropFields(oldFields, newFields); + + String dataBaseName = url.substring(url.lastIndexOf("/") + 1); + // 添加新增字段 + if (CollUtil.isNotEmpty(addFields)) { + tdEngineService.addColumnForSuperTable(dataBaseName,tableName, addFields); + } + // 删除旧字段 + if (CollUtil.isNotEmpty(dropFields)) { + tdEngineService.dropColumnForSuperTable(dataBaseName,tableName, dropFields); + } + // 修改字段(先删除再添加) + if (CollUtil.isNotEmpty(modifyFields)) { + tdEngineService.dropColumnForSuperTable(dataBaseName,tableName, modifyFields); + tdEngineService.addColumnForSuperTable(dataBaseName,tableName, modifyFields); + } + } + + // 获取新增字段 + private List getAddFields(List oldFields, List newFields) { + return newFields.stream() + .filter(f -> oldFields.stream().noneMatch(old -> old.getFieldName().equals(f.getFieldName()))) + .collect(Collectors.toList()); + } + + // 获取修改字段 + private List getModifyFields(List oldFields, List newFields) { + return newFields.stream() + .filter(f -> oldFields.stream().anyMatch(old -> + old.getFieldName().equals(f.getFieldName()) && + (!old.getDataType().equals(f.getDataType()) || !Objects.equals(old.getDataLength(), f.getDataLength())))) + .collect(Collectors.toList()); + } + + // 获取删除字段 + private List getDropFields(List oldFields, List newFields) { + return oldFields.stream() + .filter(f -> !"time".equals(f.getFieldName()) && !"device_id".equals(f.getFieldName()) && + newFields.stream().noneMatch(n -> n.getFieldName().equals(f.getFieldName()))) + .collect(Collectors.toList()); + } + @Override public void createSuperTableDataModel(IotProductDO product, List functionList) { - // 1. 生成 ThingModelRespVO - ThingModelRespVO thingModel = new ThingModelRespVO(); - thingModel.setId(product.getId()); - thingModel.setProductKey(product.getProductKey()); + ThingModelRespVO thingModel = buildThingModel(product, functionList); - // 1.1 设置属性、服务和事件 - ThingModelRespVO.Model model = new ThingModelRespVO.Model(); - List properties = new ArrayList<>(); - - // 1.2 遍历功能列表并分类 - for (IotThinkModelFunctionDO function : functionList) { - if (Objects.requireNonNull(IotProductFunctionTypeEnum.valueOf(function.getType())) == IotProductFunctionTypeEnum.PROPERTY) { - ThingModelProperty property = new ThingModelProperty(); - property.setIdentifier(function.getIdentifier()); - property.setName(function.getName()); - property.setDescription(function.getDescription()); - property.setDataType(function.getProperty().getDataType()); - properties.add(property); - } - } - - // 1.3 判断属性列表是否为空 - if (properties.isEmpty()) { + if (thingModel.getModel().getProperties().isEmpty()) { log.warn("物模型属性列表为空,不创建超级表"); return; } - model.setProperties(properties); - thingModel.setModel(model); + String superTableName = getProductPropertySTableName(product.getDeviceType(), product.getProductKey()); + String dataBaseName = url.substring(url.lastIndexOf("/") + 1); + Integer tableExists = tdEngineService.checkSuperTableExists(dataBaseName, superTableName); - // 2. 判断是否已经创建,如果已经创建则进行更新 - String tbName = getProductPropertySTableName(product.getDeviceType(), product.getProductKey()); - Integer iot = tdEngineMapper.checkTableExists("ruoyi_vue_pro", tbName); - if (iot != null && iot > 0) { - // 3. 更新 + if (tableExists != null && tableExists > 0) { updateSuperTable(thingModel, product.getDeviceType()); } else { - // 4. 创建 createSuperTable(thingModel, product.getDeviceType()); } } - /** - * 根据产品key获取产品属性超级表名 - */ - static String getProductPropertySTableName(Integer deviceType, String productKey) { - if (deviceType == 1) { - return String.format("gateway_sub_" + productKey).toLowerCase(); - } else if (deviceType == 2) { - return String.format("gateway_" + productKey).toLowerCase(); - } else { - return String.format("device_" + productKey).toLowerCase(); - } + private ThingModelRespVO buildThingModel(IotProductDO product, List functionList) { + ThingModelRespVO thingModel = new ThingModelRespVO(); + thingModel.setId(product.getId()); + thingModel.setProductKey(product.getProductKey()); + + ThingModelRespVO.Model model = new ThingModelRespVO.Model(); + List properties = functionList.stream() + .filter(function -> IotProductFunctionTypeEnum.PROPERTY.equals(IotProductFunctionTypeEnum.valueOf(function.getType()))) + .map(this::buildThingModelProperty) + .collect(Collectors.toList()); + + model.setProperties(properties); + thingModel.setModel(model); + + return thingModel; } - /** - * 根据deviceId获取设备属性表名 - */ - static String getDevicePropertyTableName(String deviceType, String productKey, String deviceKey) { - return String.format(deviceType + "_" + productKey + "_" + deviceKey).toLowerCase(); + private ThingModelProperty buildThingModelProperty(IotThinkModelFunctionDO function) { + ThingModelProperty property = new ThingModelProperty(); + property.setIdentifier(function.getIdentifier()); + property.setName(function.getName()); + property.setDescription(function.getDescription()); + property.setDataType(function.getProperty().getDataType()); + return property; } -} + + static String getProductPropertySTableName(Integer deviceType, String productKey) { + return switch (deviceType) { + case 1 -> String.format("gateway_sub_%s", productKey).toLowerCase(); + case 2 -> String.format("gateway_%s", productKey).toLowerCase(); + default -> String.format("device_%s", productKey).toLowerCase(); + }; + } + + static String getDevicePropertyTableName(String deviceType, String productKey, String deviceKey) { + return String.format("%s_%s_%s", deviceType, productKey, deviceKey).toLowerCase(); + } +} \ 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/tdengine/TdEngineService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineService.java index b3ae6f818..9319adbd7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineService.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.iot.service.tdengine; -import cn.iocoder.yudao.module.iot.domain.FieldsVo; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; import cn.iocoder.yudao.module.iot.domain.SelectDto; import cn.iocoder.yudao.module.iot.domain.TableDto; import cn.iocoder.yudao.module.iot.domain.TagsSelectDao; @@ -27,12 +27,44 @@ public interface TdEngineService { * * @param schemaFields schema字段 * @param tagsFields tags字段 - * @param dataBaseName 数据库名称 * @param superTableName 超级表名称 - * @throws Exception 异常 */ - void createSuperTable(List schemaFields, List tagsFields, String dataBaseName, - String superTableName) throws Exception; + void createSuperTable(List schemaFields, List tagsFields, String dataBaseName, String superTableName); + + /** + * 检查超级表是否存在 + */ + Integer checkSuperTableExists(String dataBaseName, String superTableName); + + + /** + * 获取超级表的结构信息 + */ + List> describeSuperTable(String dataBaseName, String superTableName); + + /** + * 为超级表添加列 + * + * @param dataBaseName 数据库名称 + * @param superTableName 超级表名称 + * @param fieldsVo 字段信息 + */ + void addColumnForSuperTable(String dataBaseName,String superTableName, List fieldsVo); + + /** + * 为超级表删除列 + * + * @param dataBaseName 数据库名称 + * @param superTableName 超级表名称 + * @param fieldsVo 字段信息 + */ + void dropColumnForSuperTable(String dataBaseName,String superTableName, List fieldsVo); + + /** + * 为超级表添加tag + */ + Long getCountByTimesTamp(SelectDto selectDto) throws Exception; + /** * 创建表 @@ -59,37 +91,6 @@ public interface TdEngineService { */ List> selectByTimesTamp(SelectDto selectDto) throws Exception; - /** - * 为超级表添加列 - * - * @param superTableName 超级表名称 - * @param fieldsVo 字段信息 - * @throws Exception 异常 - */ - void addColumnForSuperTable(String superTableName, FieldsVo fieldsVo) throws Exception; - - /** - * 为超级表删除列 - * - * @param superTableName 超级表名称 - * @param fieldsVo 字段信息 - * @throws Exception 异常 - */ - void dropColumnForSuperTable(String superTableName, FieldsVo fieldsVo) throws Exception; - - /** - * 为超级表添加tag - */ - Long getCountByTimesTamp(SelectDto selectDto) throws Exception; - - /** - * 检查表是否存在 - * - * @return 1存在 0不存在 - * @throws Exception 异常 - */ - Integer checkTableExists(SelectDto selectDto) throws Exception; - /** * 初始化超级表 * @@ -138,4 +139,6 @@ public interface TdEngineService { * @return 数据 */ List> getAggregateData(SelectVisualDto selectVisualDto); + + } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineServiceImpl.java index 70933617f..d61b78922 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineServiceImpl.java @@ -1,10 +1,12 @@ package cn.iocoder.yudao.module.iot.service.tdengine; -import cn.iocoder.yudao.module.iot.domain.FieldsVo; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineMapper; import cn.iocoder.yudao.module.iot.domain.SelectDto; import cn.iocoder.yudao.module.iot.domain.TableDto; import cn.iocoder.yudao.module.iot.domain.TagsSelectDao; import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; +import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -15,25 +17,27 @@ import java.util.Map; @Slf4j public class TdEngineServiceImpl implements TdEngineService { + @Resource + private TdEngineMapper tdEngineMapper; @Override public void createDateBase(String dataBaseName) { - + tdEngineMapper.createDatabase(dataBaseName); } @Override - public void createSuperTable(List schemaFields, List tagsFields, String dataBaseName, String superTableName) { - + public void createSuperTable(List schemaFields, List tagsFields, String dataBaseName, String superTableName) { + tdEngineMapper.createSuperTable(schemaFields, tagsFields, dataBaseName, superTableName); } @Override public void createTable(TableDto tableDto) { - + tdEngineMapper.createTable(tableDto); } @Override public void insertData(TableDto tableDto) { - + tdEngineMapper.insertData(tableDto); } @Override @@ -42,13 +46,17 @@ public class TdEngineServiceImpl implements TdEngineService { } @Override - public void addColumnForSuperTable(String superTableName, FieldsVo fieldsVo) { - + public void addColumnForSuperTable(String dataBaseName,String superTableName, List fields) { + for (TdFieldDO field : fields) { + tdEngineMapper.addColumnForSuperTable(dataBaseName,superTableName, field); + } } @Override - public void dropColumnForSuperTable(String superTableName, FieldsVo fieldsVo) { - + public void dropColumnForSuperTable(String dataBaseName,String superTableName, List fields) { + for (TdFieldDO field : fields) { + tdEngineMapper.dropColumnForSuperTable(dataBaseName,superTableName, field); + } } @Override @@ -56,11 +64,6 @@ public class TdEngineServiceImpl implements TdEngineService { return 0L; } - @Override - public Integer checkTableExists(SelectDto selectDto) { - return 0; - } - @Override public void initSTableFrame(String msg) { @@ -90,4 +93,15 @@ public class TdEngineServiceImpl implements TdEngineService { public List> getAggregateData(SelectVisualDto selectVisualDto) { return List.of(); } + + @Override + public Integer checkSuperTableExists(String dataBaseName, String superTableName) { + List> results = tdEngineMapper.showSuperTables(dataBaseName, superTableName); + return results == null || results.isEmpty() ? 0 : results.size(); + } + + @Override + public List> describeSuperTable(String dataBaseName, String superTableName) { + return tdEngineMapper.describeSuperTable(dataBaseName, superTableName); + } } \ 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/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java index 1e356c6b7..3f698999c 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java @@ -174,8 +174,10 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe public void createSuperTableDataModel(Long productId) { // 1. 查询产品 IotProductDO product = productService.getProduct(productId); + // 2. 查询产品的物模型功能列表 List functionList = thinkModelFunctionMapper.selectListByProductId(productId); + // 3. 生成 TDengine 的数据模型 dbStructureDataService.createSuperTableDataModel(product, functionList); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml index f722e0130..f1d748198 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml @@ -8,7 +8,7 @@ - create table if not exists #{dataBaseName}.#{superTableName} + CREATE STABLE IF NOT EXISTS ${dataBaseName}.${superTableName} @@ -16,46 +16,48 @@ - - timestamp + + TIMESTAMP - - tinyint + + TINYINT - - smallint + + SMALLINT - - int + + INT - - bigint + + BIGINT - - float + + FLOAT - - double + + DOUBLE - - binary + + BINARY - - nchar + + NCHAR - - bool + + BOOL - - json + + JSON - - (#{item.size}) + + ( + ${item.dataLength} + ) - tags + TAGS @@ -64,43 +66,45 @@ - - timestamp + + TIMESTAMP - - tinyint + + TINYINT - - smallint + + SMALLINT - - int + + INT - - bigint + + BIGINT - - float + + FLOAT - - double + + DOUBLE - - binary + + BINARY - - nchar + + NCHAR - - bool + + BOOL - - json + + JSON - - (#{item.size}) + + ( + ${item.dataLength} + ) @@ -135,7 +139,6 @@ - select * from #{dataBaseName}.#{tableName} @@ -146,66 +149,58 @@ - ALTER - STABLE - #{superTableName} - ADD - COLUMN - - #{fieldsVo.fieldName} + ALTER STABLE ${dataBaseName}.${superTableName} ADD COLUMN + + #{field.fieldName} - + - - timestamp + + TIMESTAMP - - tinyint + + TINYINT - - smallint + + SMALLINT - - int + + INT - - bigint + + BIGINT - - float + + FLOAT - - double + + DOUBLE - - binary + + BINARY - - nchar + + NCHAR - - bool + + BOOL - - json + + JSON - + ( - #{fieldsVo.size} + #{field.dataLength} ) - ALTER - STABLE - #{superTableName} - DROP - COLUMN - - #{fieldsVo.fieldName} + ALTER STABLE ${dataBaseName}.${superTableName} DROP COLUMN + + #{field.fieldName} @@ -215,49 +210,49 @@ #{superTableName} ADD TAG - - #{fieldsVo.fieldName} + + #{fieldDO.fieldName} - + - + timestamp - + tinyint - + smallint - + int - + bigint - + float - + double - + binary - + nchar - + bool - + json - + ( - #{fieldsVo.size} + #{fieldDO.dataLength} ) @@ -279,11 +274,8 @@ FROM #{dataBaseName}.#{tableName} WHERE ${fieldName} BETWEEN #{startTime} AND #{endTime} - - SELECT COUNT(0) - FROM information_schema.ins_tables - WHERE db_name = #{dataBaseName} - AND table_name = #{tableName} + + SHOW ${dataBaseName}.STABLES LIKE '${superTableName}' @@ -304,11 +296,13 @@ FROM #{dataBaseName}.#{tableName} WHERE ts BETWEEN #{startTime} AND #{endTime} LIMIT #{num} + SELECT #{fieldName}, ts FROM #{dataBaseName}.#{tableName} LIMIT #{num} + SELECT #{aggregate}(${fieldName}) @@ -316,9 +310,8 @@ LIMIT #{num} - - - ${sql} - + + DESCRIBE ${dataBaseName}.${superTableName} + From 88088c798799bfebd00439199914f2fb08a7a8a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Sat, 26 Oct 2024 23:26:26 +0800 Subject: [PATCH 005/228] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91=20=E4=BA=A7=E5=93=81=E5=8F=91=E5=B8=83?= =?UTF-8?q?=E5=90=8E=E7=89=A9=E6=A8=A1=E5=9E=8B=E4=B8=8D=E5=8F=AF=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/iot/enums/ErrorCodeConstants.java | 1 + .../IotThinkModelFunctionServiceImpl.java | 25 ++++++++++++++++--- 2 files changed, 22 insertions(+), 4 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 31702e1e6..be9d28ecb 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 @@ -13,6 +13,7 @@ public interface ErrorCodeConstants { ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_050_001_000, "产品不存在"); ErrorCode PRODUCT_IDENTIFICATION_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在"); ErrorCode PRODUCT_STATUS_NOT_DELETE = new ErrorCode(1_050_001_002, "产品状是发布状态,不允许删除"); + ErrorCode PRODUCT_STATUS_NOT_ALLOW_FUNCTION = new ErrorCode(1_050_001_003, "产品状是发布状态,不允许操作物模型"); // ========== IoT 产品物模型 1-050-002-000 ============ ErrorCode THINK_MODEL_FUNCTION_NOT_EXISTS = new ErrorCode(1_050_002_000, "产品物模型不存在"); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java index 3f698999c..dd7a51786 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java @@ -20,6 +20,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkMod import cn.iocoder.yudao.module.iot.dal.mysql.thinkmodelfunction.IotThinkModelFunctionMapper; import cn.iocoder.yudao.module.iot.enums.product.IotAccessModeEnum; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; +import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum; import cn.iocoder.yudao.module.iot.service.product.IotProductService; import cn.iocoder.yudao.module.iot.service.tdengine.IotDbStructureDataService; import jakarta.annotation.Resource; @@ -65,17 +66,27 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe // 3. 系统保留字段,不能用于标识符定义 validateNotDefaultEventAndService(createReqVO.getIdentifier()); - // 3. 插入数据库 + // 4. 校验产品状态,发布状态下,不允许新增功能 + validateProductStatus(createReqVO.getProductId()); + + // 5. 插入数据库 IotThinkModelFunctionDO function = IotThinkModelFunctionConvert.INSTANCE.convert(createReqVO); thinkModelFunctionMapper.insert(function); - // 4. 如果创建的是属性,需要更新默认的事件和服务 + // 6. 如果创建的是属性,需要更新默认的事件和服务 if (Objects.equals(createReqVO.getType(), IotProductFunctionTypeEnum.PROPERTY.getType())) { createDefaultEventsAndServices(createReqVO.getProductId(), createReqVO.getProductKey()); } return function.getId(); } + private void validateProductStatus(Long createReqVO) { + IotProductDO product = productService.getProduct(createReqVO); + if (Objects.equals(product.getStatus(), IotProductStatusEnum.PUBLISHED.getType())) { + throw exception(PRODUCT_STATUS_NOT_ALLOW_FUNCTION); + } + } + private void validateNotDefaultEventAndService(String identifier) { // set, get, post, property, event, time, value 是系统保留字段,不能用于标识符定义 if (CollUtil.containsAny(Arrays.asList("set", "get", "post", "property", "event", "time", "value"), Collections.singletonList(identifier))) { @@ -109,11 +120,14 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe // 2. 校验功能标识符是否唯一 validateIdentifierUniqueForUpdate(updateReqVO.getId(), updateReqVO.getProductId(), updateReqVO.getIdentifier()); - // 3. 更新数据库 + // 3. 校验产品状态,发布状态下,不允许操作功能 + validateProductStatus(updateReqVO.getProductId()); + + // 4. 更新数据库 IotThinkModelFunctionDO thinkModelFunction = IotThinkModelFunctionConvert.INSTANCE.convert(updateReqVO); thinkModelFunctionMapper.updateById(thinkModelFunction); - // 4. 如果更新的是属性,需要更新默认的事件和服务 + // 5. 如果更新的是属性,需要更新默认的事件和服务 if (Objects.equals(updateReqVO.getType(), IotProductFunctionTypeEnum.PROPERTY.getType())) { createDefaultEventsAndServices(updateReqVO.getProductId(), updateReqVO.getProductKey()); } @@ -135,6 +149,9 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe throw exception(THINK_MODEL_FUNCTION_NOT_EXISTS); } + // 3. 校验产品状态,发布状态下,不允许操作功能 + validateProductStatus(functionDO.getProductId()); + // 2. 删除功能 thinkModelFunctionMapper.deleteById(id); From 8c84ac9d8a88dd73d03746274f4f6e2de7004668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Sun, 27 Oct 2024 21:26:35 +0800 Subject: [PATCH 006/228] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E3=80=91=20mqtt=20=E6=95=B0=E6=8D=AE=E6=8E=A5?= =?UTF-8?q?=E6=94=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-iot/yudao-module-iot-biz/pom.xml | 5 ++ .../tdengine/ThingModelMessage.java | 70 +++++++++++++++++++ .../iot/emq/service/EmqxServiceImpl.java | 14 +++- .../service/device/IotDeviceDataService.java | 26 +++++++ .../device/IotDeviceDataServiceImpl.java | 39 +++++++++++ .../iot/service/device/IotDeviceService.java | 9 +++ ...iceImpl.java => IotDeviceServiceImpl.java} | 9 ++- .../IotDbStructureDataServiceImpl.java | 16 ++--- ...neService.java => IotTdEngineService.java} | 10 +-- ...eImpl.java => IotTdEngineServiceImpl.java} | 2 +- .../tdengine/IotThingModelMessageService.java | 16 +++++ .../IotThingModelMessageServiceImpl.java | 13 ++++ .../mapper/tdengine/TdEngineMapper.xml | 18 +++-- 13 files changed, 224 insertions(+), 23 deletions(-) create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/ThingModelMessage.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/{DeviceServiceImpl.java => IotDeviceServiceImpl.java} (95%) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/{TdEngineService.java => IotTdEngineService.java} (91%) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/{TdEngineServiceImpl.java => IotTdEngineServiceImpl.java} (97%) create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java diff --git a/yudao-module-iot/yudao-module-iot-biz/pom.xml b/yudao-module-iot/yudao-module-iot-biz/pom.xml index cb2fd818f..013287d2b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/pom.xml +++ b/yudao-module-iot/yudao-module-iot-biz/pom.xml @@ -25,6 +25,11 @@ ${revision}
+ * KEY 格式:device_property_data:{deviceId} + * VALUE 数据类型:String 设备属性数据 + */ + String DEVICE_PROPERTY_DATA = "device_property_data:%s_%s_%s"; + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/deviceData/DeviceDataRedisDAO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/deviceData/DeviceDataRedisDAO.java new file mode 100644 index 000000000..b1b69f8dc --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/redis/deviceData/DeviceDataRedisDAO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.iot.dal.redis.deviceData; + +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; +import jakarta.annotation.Resource; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Repository; + +import java.util.Collection; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import static cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants.DEVICE_PROPERTY_DATA; + +/** + * {@link IotDeviceDataDO} 的 Redis DAO + */ +@Repository +public class DeviceDataRedisDAO { + + @Resource + private StringRedisTemplate stringRedisTemplate; + + public IotDeviceDataDO get(String productKey, String deviceName, String identifier) { + String redisKey = formatKey(productKey, deviceName, identifier); + return JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(redisKey), IotDeviceDataDO.class); + } + + public void set(IotDeviceDataDO deviceData) { + String redisKey = formatKey(deviceData.getProductKey(), deviceData.getDeviceName(), deviceData.getIdentifier()); + stringRedisTemplate.opsForValue().set(redisKey, JsonUtils.toJsonString(deviceData)); + } + + public void delete(String productKey, String deviceName, String identifier) { + String redisKey = formatKey(productKey, deviceName, identifier); + stringRedisTemplate.delete(redisKey); + } + + private static String formatKey(String productKey, String deviceName, String identifier) { + return String.format(DEVICE_PROPERTY_DATA, productKey, deviceName, identifier); + } +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java index 4f3ef37d6..f67f42685 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java @@ -1,12 +1,11 @@ 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.IotDevicePageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceSaveReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceStatusUpdateReqVO; -import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import jakarta.validation.Valid; +import java.util.List; + /** * IoT 设备数据 Service 接口 * @@ -23,4 +22,12 @@ public interface IotDeviceDataService { * @param message 消息 */ void saveDeviceData(String productKey, String deviceName, String message); + + /** + * 获得设备属性最新数据 + * + * @param deviceId 设备编号 + * @return 设备属性最新数据 + */ + List getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceId); } \ 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/IotDeviceDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java index 6b7aac21f..86ac630c6 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java @@ -1,13 +1,23 @@ package cn.iocoder.yudao.module.iot.service.device; import cn.hutool.json.JSONObject; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; +import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; +import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; +import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import cn.iocoder.yudao.module.iot.service.tdengine.IotThingModelMessageService; +import cn.iocoder.yudao.module.iot.service.thinkmodelfunction.IotThinkModelFunctionService; import jakarta.annotation.Resource; +import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.util.ArrayList; +import java.util.List; + @Slf4j @Service public class IotDeviceDataServiceImpl implements IotDeviceDataService { @@ -16,6 +26,11 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { private IotDeviceService deviceService; @Resource private IotThingModelMessageService thingModelMessageService; + @Resource + private IotThinkModelFunctionService thinkModelFunctionService; + + @Resource + private DeviceDataRedisDAO deviceDataRedisDAO; @Override public void saveDeviceData(String productKey, String deviceName, String message) { @@ -34,6 +49,46 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { .deviceName(deviceName) .deviceKey(device.getDeviceKey()) .build(); - thingModelMessageService.saveThingModelMessage(device,thingModelMessage); + thingModelMessageService.saveThingModelMessage(device, thingModelMessage); + } + + @Override + public List getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceDataReqVO) { + List list = new ArrayList<>(); + // 1. 获取设备信息 + IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId()); + // 2. 获取设备属性最新数据 + List thinkModelFunctionList = thinkModelFunctionService.getThinkModelFunctionListByProductKey(device.getProductKey()); + thinkModelFunctionList = thinkModelFunctionList.stream() + .filter(function -> IotProductFunctionTypeEnum.PROPERTY.getType() + .equals(function.getType())).toList(); + + // 3. 过滤标识符和属性名称 + if (deviceDataReqVO.getIdentifier() != null) { + thinkModelFunctionList = thinkModelFunctionList.stream() + .filter(function -> function.getIdentifier().toLowerCase().contains(deviceDataReqVO.getIdentifier().toLowerCase())) + .toList(); + } + if (deviceDataReqVO.getName() != null) { + thinkModelFunctionList = thinkModelFunctionList.stream() + .filter(function -> function.getName().toLowerCase().contains(deviceDataReqVO.getName().toLowerCase())) + .toList(); + } + // 4. 获取设备属性最新数据 + thinkModelFunctionList.forEach(function -> { + IotDeviceDataDO deviceData = deviceDataRedisDAO.get(device.getProductKey(), device.getDeviceName(), function.getIdentifier()); + if (deviceData == null) { + deviceData = new IotDeviceDataDO(); + deviceData.setProductKey(device.getProductKey()); + deviceData.setDeviceName(device.getDeviceName()); + deviceData.setIdentifier(function.getIdentifier()); + deviceData.setDeviceId(deviceDataReqVO.getDeviceId()); + deviceData.setThinkModelFunctionId(function.getId()); + deviceData.setName(function.getName()); + deviceData.setDataType(function.getProperty().getDataType().getType()); + } + list.add(deviceData); + }); + return list; } } 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 c967a957e..ed4c6a60c 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 @@ -1,7 +1,9 @@ package cn.iocoder.yudao.module.iot.service.device; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDevicePageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceSaveReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceStatusUpdateReqVO; import jakarta.validation.*; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.*; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; 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 f3243900e..60743f671 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 @@ -5,9 +5,9 @@ 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.framework.tenant.core.aop.TenantIgnore; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDevicePageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceSaveReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceStatusUpdateReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDevicePageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceSaveReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceStatusUpdateReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.mysql.device.IotDeviceMapper; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java index b7de8882a..947178102 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java @@ -1,12 +1,12 @@ package cn.iocoder.yudao.module.iot.service.tdengine; +import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty; import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelRespVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdRestApi; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import jakarta.annotation.Resource; @@ -14,10 +14,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.stream.Collectors; @Service @@ -27,9 +24,6 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService @Resource private IotTdEngineService iotTdEngineService; - @Resource - private TdRestApi tdRestApi; - @Value("${spring.datasource.dynamic.datasource.tdengine.url}") private String url; @@ -37,39 +31,25 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService public void createSuperTable(ThingModelRespVO thingModel, Integer deviceType) { // 1. 解析物模型,获得字段列表 List schemaFields = new ArrayList<>(); - schemaFields.add(TdFieldDO.builder(). - fieldName("time"). - dataType("TIMESTAMP"). - build()); + schemaFields.add(TdFieldDO.builder() + .fieldName("time") + .dataType("TIMESTAMP") + .build()); schemaFields.addAll(FieldParser.parse(thingModel)); // 3. 设置超级表的标签 - List tagsFields = new ArrayList<>(); - tagsFields.add(TdFieldDO.builder(). - fieldName("product_key"). - dataType("NCHAR"). - dataLength(64). - build()); - tagsFields.add(TdFieldDO.builder(). - fieldName("device_key"). - dataType("NCHAR"). - dataLength(64). - build()); - tagsFields.add(TdFieldDO.builder(). - fieldName("device_name"). - dataType("NCHAR"). - dataLength(64). - build()); - tagsFields.add(TdFieldDO.builder(). - fieldName("device_type"). - dataType("INT"). - build()); + List tagsFields = Arrays.asList( + TdFieldDO.builder().fieldName("product_key").dataType("NCHAR").dataLength(64).build(), + TdFieldDO.builder().fieldName("device_key").dataType("NCHAR").dataLength(64).build(), + TdFieldDO.builder().fieldName("device_name").dataType("NCHAR").dataLength(64).build(), + TdFieldDO.builder().fieldName("device_type").dataType("INT").build() + ); // 4. 获取超级表的名称 String superTableName = getProductPropertySTableName(deviceType, thingModel.getProductKey()); // 5. 创建超级表 - String dataBaseName = url.substring(url.lastIndexOf("/") + 1); + String dataBaseName = getDatabaseName(); iotTdEngineService.createSuperTable(schemaFields, tagsFields, dataBaseName, superTableName); } @@ -81,7 +61,7 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService List newFields = FieldParser.parse(thingModel); updateTableFields(tbName, oldFields, newFields); - } catch (Throwable e) { + } catch (Exception e) { log.error("更新物模型超级表失败", e); } } @@ -90,14 +70,15 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService private List getTableFields(String tableName) { List fields = new ArrayList<>(); // 获取超级表的描述信息 - List> maps = iotTdEngineService.describeSuperTable(url.substring(url.lastIndexOf("/") + 1), tableName); + List> maps = iotTdEngineService.describeSuperTable(getDatabaseName(), tableName); if (maps != null) { - // 过滤掉 note 字段为 TAG 的记录 - maps = maps.stream().filter(map -> !"TAG".equals(map.get("note"))).toList(); - // 过滤掉 time 字段 - maps = maps.stream().filter(map -> !"time".equals(map.get("field"))).toList(); + // 过滤掉 note 字段为 TAG 的记录和 time 字段 + List> filteredMaps = maps.stream() + .filter(map -> !"TAG".equals(map.get("note"))) + .filter(map -> !"time".equals(map.get("field"))) + .toList(); // 解析字段信息 - fields = FieldParser.parse(maps.stream() + fields = FieldParser.parse(filteredMaps.stream() .map(map -> List.of(map.get("field"), map.get("type"), map.get("length"))) .collect(Collectors.toList())); } @@ -113,7 +94,7 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService // 获取删除字段 List dropFields = getDropFields(oldFields, newFields); - String dataBaseName = url.substring(url.lastIndexOf("/") + 1); + String dataBaseName = getDatabaseName(); // 添加新增字段 if (CollUtil.isNotEmpty(addFields)) { iotTdEngineService.addColumnForSuperTable(dataBaseName, tableName, addFields); @@ -131,25 +112,37 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService // 获取新增字段 private List getAddFields(List oldFields, List newFields) { + Set oldFieldNames = oldFields.stream() + .map(TdFieldDO::getFieldName) + .collect(Collectors.toSet()); return newFields.stream() - .filter(f -> oldFields.stream().noneMatch(old -> old.getFieldName().equals(f.getFieldName()))) + .filter(f -> !oldFieldNames.contains(f.getFieldName())) .collect(Collectors.toList()); } // 获取修改字段 private List getModifyFields(List oldFields, List newFields) { + Map oldFieldMap = oldFields.stream() + .collect(Collectors.toMap(TdFieldDO::getFieldName, f -> f)); + return newFields.stream() - .filter(f -> oldFields.stream().anyMatch(old -> - old.getFieldName().equals(f.getFieldName()) && - (!old.getDataType().equals(f.getDataType()) || !Objects.equals(old.getDataLength(), f.getDataLength())))) + .filter(f -> { + TdFieldDO oldField = oldFieldMap.get(f.getFieldName()); + return oldField != null && + (!oldField.getDataType().equals(f.getDataType()) || + !Objects.equals(oldField.getDataLength(), f.getDataLength())); + }) .collect(Collectors.toList()); } // 获取删除字段 private List getDropFields(List oldFields, List newFields) { + Set newFieldNames = newFields.stream() + .map(TdFieldDO::getFieldName) + .collect(Collectors.toSet()); return oldFields.stream() - .filter(f -> !"time".equals(f.getFieldName()) && !"device_id".equals(f.getFieldName()) && - newFields.stream().noneMatch(n -> n.getFieldName().equals(f.getFieldName()))) + .filter(f -> !"time".equals(f.getFieldName()) && !"device_id".equals(f.getFieldName())) + .filter(f -> !newFieldNames.contains(f.getFieldName())) .collect(Collectors.toList()); } @@ -157,13 +150,13 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService public void createSuperTableDataModel(IotProductDO product, List functionList) { ThingModelRespVO thingModel = buildThingModel(product, functionList); - if (thingModel.getModel().getProperties().isEmpty()) { + if (thingModel.getModel() == null || CollUtil.isEmpty(thingModel.getModel().getProperties())) { log.warn("物模型属性列表为空,不创建超级表"); return; } String superTableName = getProductPropertySTableName(product.getDeviceType(), product.getProductKey()); - String dataBaseName = url.substring(url.lastIndexOf("/") + 1); + String dataBaseName = getDatabaseName(); Integer tableExists = iotTdEngineService.checkSuperTableExists(dataBaseName, superTableName); if (tableExists != null && tableExists > 0) { @@ -180,7 +173,8 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService ThingModelRespVO.Model model = new ThingModelRespVO.Model(); List properties = functionList.stream() - .filter(function -> IotProductFunctionTypeEnum.PROPERTY.equals(IotProductFunctionTypeEnum.valueOf(function.getType()))) + .filter(function -> IotProductFunctionTypeEnum.PROPERTY.equals( + IotProductFunctionTypeEnum.valueOfType(function.getType()))) .map(this::buildThingModelProperty) .collect(Collectors.toList()); @@ -191,14 +185,15 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService } private ThingModelProperty buildThingModelProperty(IotThinkModelFunctionDO function) { - ThingModelProperty property = new ThingModelProperty(); - property.setIdentifier(function.getIdentifier()); - property.setName(function.getName()); - property.setDescription(function.getDescription()); + ThingModelProperty property = BeanUtil.copyProperties(function, ThingModelProperty.class); property.setDataType(function.getProperty().getDataType()); return property; } + private String getDatabaseName() { + return url.substring(url.lastIndexOf("/") + 1); + } + static String getProductPropertySTableName(Integer deviceType, String productKey) { return switch (deviceType) { case 1 -> String.format("gateway_sub_%s", productKey).toLowerCase(); @@ -207,7 +202,4 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService }; } - static String getDevicePropertyTableName(String deviceType, String productKey, String deviceKey) { - return String.format("%s_%s_%s", deviceType, productKey, deviceKey).toLowerCase(); - } } \ 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/tdengine/IotThingModelMessageServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java index ae7fa51ee..9bad7613e 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java @@ -1,13 +1,16 @@ package cn.iocoder.yudao.module.iot.service.tdengine; +import cn.hutool.core.date.DateUtil; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.IotDeviceStatusUpdateReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceStatusUpdateReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; +import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; @@ -17,9 +20,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; @Slf4j @@ -36,11 +37,14 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @Resource private IotTdEngineService iotTdEngineService; + @Resource + private DeviceDataRedisDAO deviceDataRedisDAO; + @Override @TenantIgnore public void saveThingModelMessage(IotDeviceDO device, ThingModelMessage thingModelMessage) { // 判断设备状态,如果为未激活状态,创建数据表 - if (device.getStatus().equals(0)) { + if (IotDeviceStatusEnum.INACTIVE.getStatus().equals(device.getStatus())) { // 创建设备数据表 createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); // 更新设备状态 @@ -50,53 +54,99 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ iotDeviceService.updateDeviceStatus(updateReqVO); } - // 1. 获取设备属性 + // 获取设备属性 Map params = thingModelMessage.dataToMap(); - // 2. 物模型校验,过滤非物模型属性 - List thinkModelFunctionListByProductKey = iotThinkModelFunctionService.getThinkModelFunctionListByProductKey(thingModelMessage.getProductKey()); + // 物模型校验,过滤非物模型属性 + List functionList = iotThinkModelFunctionService + .getThinkModelFunctionListByProductKey(thingModelMessage.getProductKey()) + .stream() + .filter(function -> IotProductFunctionTypeEnum.PROPERTY.getType().equals(function.getType())) + .toList(); - // 2.1 筛选是属性 IotProductFunctionTypeEnum - thinkModelFunctionListByProductKey.removeIf(iotThinkModelFunctionDO -> !iotThinkModelFunctionDO.getType().equals(IotProductFunctionTypeEnum.PROPERTY.getType())); - if (thinkModelFunctionListByProductKey.isEmpty()) { + if (functionList.isEmpty()) { return; } - // 2.2 获取属性名称 - Map thingModelProperties = thinkModelFunctionListByProductKey.stream().collect(Collectors.toMap(IotThinkModelFunctionDO::getIdentifier, IotThinkModelFunctionDO::getName)); - // 4. 保存属性记录 + // 获取属性标识符集合 + Set propertyIdentifiers = functionList.stream() + .map(IotThinkModelFunctionDO::getIdentifier) + .collect(Collectors.toSet()); + + Map functionMap = functionList.stream() + .collect(Collectors.toMap(IotThinkModelFunctionDO::getIdentifier, function -> function)); + + // 过滤并收集有效的属性字段 List schemaFieldValues = new ArrayList<>(); - - // 1. 设置字段名 schemaFieldValues.add(new TdFieldDO("time", thingModelMessage.getTime())); - - // 2. 遍历新属性 params.forEach((key, val) -> { - if (thingModelProperties.containsKey(key)) { + if (propertyIdentifiers.contains(key)) { schemaFieldValues.add(new TdFieldDO(key.toLowerCase(), val)); + // 缓存设备属性 + setDeviceDataCache(device, functionMap.get(key), val, thingModelMessage.getTime()); } }); + if (schemaFieldValues.size() == 1) { + return; + } - // 3. 保存设备属性 + // 构建并保存设备属性 TableDO tableData = new TableDO(); - tableData.setDataBaseName(url.substring(url.lastIndexOf("/") + 1)); + tableData.setDataBaseName(getDatabaseName()); tableData.setSuperTableName(getProductPropertySTableName(device.getDeviceType(), device.getProductKey())); - tableData.setTableName("device_" + device.getProductKey().toLowerCase() + "_" + device.getDeviceName().toLowerCase()); + tableData.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())); tableData.setSchemaFieldValues(schemaFieldValues); - // 4. 保存数据 iotTdEngineService.insertData(tableData); } + /** + * 缓存设备属性 + * + * @param device 设备信息 + * @param iotThinkModelFunctionDO 物模型属性 + * @param val 属性值 + * @param time 时间 + */ + private void setDeviceDataCache(IotDeviceDO device, IotThinkModelFunctionDO iotThinkModelFunctionDO, Object val, Long time) { + IotDeviceDataDO deviceData = IotDeviceDataDO.builder() + .productKey(device.getProductKey()) + .deviceName(device.getDeviceName()) + .identifier(iotThinkModelFunctionDO.getIdentifier()) + .value(val != null ? val.toString() : null) + .updateTime(DateUtil.toLocalDateTime(new Date(time))) + .deviceId(device.getId()) + .thinkModelFunctionId(iotThinkModelFunctionDO.getId()) + .name(iotThinkModelFunctionDO.getName()) + .dataType(iotThinkModelFunctionDO.getProperty().getDataType().getType()) + .build(); + deviceDataRedisDAO.set(deviceData); + } + + /** + * 创建设备数据表 + * + * @param deviceType 设备类型 + * @param productKey 产品 Key + * @param deviceName 设备名称 + * @param deviceKey 设备 Key + */ private void createDeviceTable(Integer deviceType, String productKey, String deviceName, String deviceKey) { + String superTableName = getProductPropertySTableName(deviceType, productKey); + String dataBaseName = getDatabaseName(); + + List> maps = iotTdEngineService.describeSuperTable(dataBaseName, superTableName); List tagsFieldValues = new ArrayList<>(); - String SuperTableName = getProductPropertySTableName(deviceType, productKey); - List> maps = iotTdEngineService.describeSuperTable(url.substring(url.lastIndexOf("/") + 1), SuperTableName); + if (maps != null) { - List> taggedNotesList = maps.stream().filter(map -> "TAG".equals(map.get("note"))).toList(); + List> taggedNotesList = maps.stream() + .filter(map -> "TAG".equals(map.get("note"))) + .toList(); + tagsFieldValues = FieldParser.parse(taggedNotesList.stream() .map(map -> List.of(map.get("field"), map.get("type"), map.get("length"))) .collect(Collectors.toList())); + for (TdFieldDO tagsFieldValue : tagsFieldValues) { switch (tagsFieldValue.getFieldName()) { case "product_key" -> tagsFieldValue.setFieldValue(productKey); @@ -107,21 +157,49 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ } } - // 1. 创建设备数据表 - String tableName = "device_" + productKey.toLowerCase() + "_" + deviceName.toLowerCase(); + // 创建设备数据表 + String tableName = getDeviceTableName(productKey, deviceName); TableDO tableDto = new TableDO(); - tableDto.setDataBaseName(url.substring(url.lastIndexOf("/") + 1)); - tableDto.setSuperTableName(SuperTableName); + tableDto.setDataBaseName(dataBaseName); + tableDto.setSuperTableName(superTableName); tableDto.setTableName(tableName); tableDto.setTagsFieldValues(tagsFieldValues); + iotTdEngineService.createTable(tableDto); } - static String getProductPropertySTableName(Integer deviceType, String productKey) { + /** + * 获取数据库名称 + * + * @return 数据库名称 + */ + private String getDatabaseName() { + return url.substring(url.lastIndexOf("/") + 1); + } + + /** + * 获取产品属性表名 + * + * @param deviceType 设备类型 + * @param productKey 产品 Key + * @return 产品属性表名 + */ + private static String getProductPropertySTableName(Integer deviceType, String productKey) { return switch (deviceType) { case 1 -> String.format("gateway_sub_%s", productKey).toLowerCase(); case 2 -> String.format("gateway_%s", productKey).toLowerCase(); default -> String.format("device_%s", productKey).toLowerCase(); }; } + + /** + * 获取设备表名 + * + * @param productKey 产品 Key + * @param deviceName 设备名称 + * @return 设备表名 + */ + private static String getDeviceTableName(String productKey, String deviceName) { + return String.format("device_%s_%s", productKey.toLowerCase(), deviceName.toLowerCase()); + } } \ No newline at end of file From d7b8cf547f4d96b49c3371fbbf4535a1c4dfab3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Tue, 5 Nov 2024 23:26:34 +0800 Subject: [PATCH 009/228] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E3=80=91=20=E8=AE=BE=E5=A4=87=E5=8E=86=E5=8F=B2?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=B1=95=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/domain/visual/SelectVisualDto.java | 29 +++++++------ .../admin/device/IotDeviceDataController.java | 10 +++++ .../vo/deviceData/IotDeviceDataReqVO.java | 12 +++++- .../vo/deviceData/IotTimeDataRespVO.java} | 8 ++-- .../iot/dal/tdengine/TdEngineMapper.java | 7 ++- .../service/device/IotDeviceDataService.java | 10 +++++ .../device/IotDeviceDataServiceImpl.java | 43 +++++++++++++++++++ .../mapper/tdengine/TdEngineMapper.xml | 19 +++++--- 8 files changed, 112 insertions(+), 26 deletions(-) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/{dal/dataobject/tdengine/TimeData.java => controller/admin/device/vo/deviceData/IotTimeDataRespVO.java} (67%) diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/visual/SelectVisualDto.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/visual/SelectVisualDto.java index 1444da972..071c76303 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/visual/SelectVisualDto.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/domain/visual/SelectVisualDto.java @@ -4,24 +4,24 @@ import lombok.Data; import java.util.Map; -/** - * @ClassDescription: 查询可视化所需入参对象 - * @ClassName: SelectDto - * @Author: andyz - * @Date: 2022-07-29 14:12:26 - * @Version 1.0 - */ @Data public class SelectVisualDto { -// @NotBlank(message = "invalid operation: tableName can not be empty") + /** + * 数据库名称 + */ private String dataBaseName; -// @NotBlank(message = "invalid operation: tableName can not be empty") + /** + * 表名 + */ private String tableName; -// @NotBlank(message = "invalid operation: fieldName can not be empty") //属性 + /** + * 属性 + */ private String fieldName; + /** * 查询类型,0历史数据,1实时数据,2聚合数据 */ @@ -39,10 +39,15 @@ public class SelectVisualDto { * 比如1s,1m,1h,1d代表1秒,1分钟,1小时,1天 */ private String interval; - // @NotNull(message = "invalid operation: startTime can not be null") + + /** + * 开始时间 + */ private Long startTime; - // @NotNull(message = "invalid operation: endTime can not be null") + /** + * 结束时间 + */ private Long endTime; /** diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java index 93b368bd8..e710d0ea8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java @@ -1,10 +1,12 @@ package cn.iocoder.yudao.module.iot.controller.admin.device; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +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.device.vo.deviceData.IotDeviceDataReqVO; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataRespVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotTimeDataRespVO; import cn.iocoder.yudao.module.iot.service.device.IotDeviceDataService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -16,6 +18,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; +import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -35,4 +38,11 @@ public class IotDeviceDataController { return success(BeanUtils.toBean(list, IotDeviceDataRespVO.class)); } + @GetMapping("/history-data") + @Operation(summary = "获取设备属性历史数据") + public CommonResult> getDevicePropertiesHistoryData(@Valid IotDeviceDataReqVO deviceDataReqVO) { + PageResult> list = deviceDataService.getDevicePropertiesHistoryData(deviceDataReqVO); + return success(BeanUtils.toBean(list, IotTimeDataRespVO.class)); + } + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java index b8a95f607..5f87a1cb8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java @@ -1,13 +1,18 @@ package cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData; +import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Size; import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + @Schema(description = "管理后台 - IoT 设备数据 Request VO") @Data -public class IotDeviceDataReqVO { +public class IotDeviceDataReqVO extends PageParam { @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "177") private Long deviceId; @@ -18,4 +23,9 @@ public class IotDeviceDataReqVO { @Schema(description = "属性名称", requiredMode = Schema.RequiredMode.REQUIRED) private String name; + @Schema(description = "时间范围", requiredMode = Schema.RequiredMode.NOT_REQUIRED) + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @Size(min = 2, max = 2, message = "请选择时间范围") + private LocalDateTime[] times; + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TimeData.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotTimeDataRespVO.java similarity index 67% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TimeData.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotTimeDataRespVO.java index f7e251ea8..1bf085c54 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TimeData.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotTimeDataRespVO.java @@ -1,16 +1,14 @@ -package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; +package cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -/** - * 统计的时间数据 - */ + @Data @NoArgsConstructor @AllArgsConstructor -public class TimeData { +public class IotTimeDataRespVO { /** * 时间 diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java index 94db527c2..c126946f1 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineMapper.java @@ -88,6 +88,7 @@ public interface TdEngineMapper { /** * 创建表 - 创建超级表的子表 + * * @param tableDO 表信息 */ @InterceptorIgnore(tenantLine = "true") @@ -114,6 +115,7 @@ public interface TdEngineMapper { Map getLastData(SelectDto selectDto); + @InterceptorIgnore(tenantLine = "true") List> getHistoryData(SelectVisualDto selectVisualDto); List> getRealtimeData(SelectVisualDto selectVisualDto); @@ -122,5 +124,6 @@ public interface TdEngineMapper { List> getLastDataByTags(TagsSelectDao tagsSelectDao); - -} + @InterceptorIgnore(tenantLine = "true") + Long getHistoryCount(SelectVisualDto selectVisualDto); +} \ 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/IotDeviceDataService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java index f67f42685..96181fd26 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java @@ -1,10 +1,12 @@ 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.deviceData.IotDeviceDataReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import jakarta.validation.Valid; import java.util.List; +import java.util.Map; /** * IoT 设备数据 Service 接口 @@ -30,4 +32,12 @@ public interface IotDeviceDataService { * @return 设备属性最新数据 */ List getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceId); + + /** + * 获得设备属性历史数据 + * + * @param deviceDataReqVO 设备属性历史数据 Request VO + * @return 设备属性历史数据 + */ + PageResult> getDevicePropertiesHistoryData(@Valid IotDeviceDataReqVO deviceDataReqVO); } \ 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/IotDeviceDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java index 86ac630c6..1b44bd5d0 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java @@ -1,27 +1,38 @@ package cn.iocoder.yudao.module.iot.service.device; +import cn.hutool.core.date.DateUtil; import cn.hutool.json.JSONObject; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineMapper; +import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import cn.iocoder.yudao.module.iot.service.tdengine.IotThingModelMessageService; import cn.iocoder.yudao.module.iot.service.thinkmodelfunction.IotThinkModelFunctionService; import jakarta.annotation.Resource; import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import java.time.ZoneId; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; @Slf4j @Service public class IotDeviceDataServiceImpl implements IotDeviceDataService { + @Value("${spring.datasource.dynamic.datasource.tdengine.url}") + private String url; + @Resource private IotDeviceService deviceService; @Resource @@ -32,6 +43,9 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { @Resource private DeviceDataRedisDAO deviceDataRedisDAO; + @Resource + private TdEngineMapper tdEngineMapper; + @Override public void saveDeviceData(String productKey, String deviceName, String message) { // 1. 根据产品 key 和设备名称,获得设备信息 @@ -91,4 +105,33 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { }); return list; } + + @Override + public PageResult> getDevicePropertiesHistoryData(IotDeviceDataReqVO deviceDataReqVO) { + PageResult> pageResult = new PageResult<>(); + // 1. 获取设备信息 + IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId()); + // 2. 获取设备属性历史数据 + SelectVisualDto selectVisualDto = new SelectVisualDto(); + selectVisualDto.setDataBaseName(getDatabaseName()); + selectVisualDto.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())); + selectVisualDto.setFieldName(deviceDataReqVO.getIdentifier()); + selectVisualDto.setStartTime(DateUtil.date(deviceDataReqVO.getTimes()[0].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime()); + selectVisualDto.setEndTime(DateUtil.date(deviceDataReqVO.getTimes()[1].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime()); + Map params = new HashMap<>(); + params.put("rows", deviceDataReqVO.getPageSize()); + params.put("page", (deviceDataReqVO.getPageNo() - 1) * deviceDataReqVO.getPageSize()); + selectVisualDto.setParams(params); + pageResult.setList(tdEngineMapper.getHistoryData(selectVisualDto)); + pageResult.setTotal(tdEngineMapper.getHistoryCount(selectVisualDto)); + return pageResult; + } + + private String getDatabaseName() { + return url.substring(url.lastIndexOf("/") + 1); + } + + private static String getDeviceTableName(String productKey, String deviceName) { + return String.format("device_%s_%s", productKey.toLowerCase(), deviceName.toLowerCase()); + } } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml index 9d5cf2a43..4e127e44b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml @@ -292,17 +292,18 @@ - SELECT #{fieldName}, ts - FROM #{dataBaseName}.#{tableName} - WHERE ts BETWEEN #{startTime} AND #{endTime} - LIMIT #{num} + SELECT ${fieldName} as data, time + FROM ${dataBaseName}.${tableName} + WHERE time BETWEEN #{startTime} AND #{endTime} + AND ${fieldName} IS NOT NULL + ORDER BY time DESC + LIMIT #{params.rows} offset #{params.page} - SELECT #{fieldName}, ts + SELECT #{fieldName}, time FROM #{dataBaseName}.#{tableName} - LIMIT #{num} DESCRIBE ${dataBaseName}.${superTableName} + + SELECT count(time) + FROM ${dataBaseName}.${tableName} + WHERE time BETWEEN #{startTime} AND #{endTime} + AND ${fieldName} IS NOT NULL +
- * * @param dataBaseName 数据库名称 - * * @param superTableName 超级表名称 - */ - @InterceptorIgnore(tenantLine = "true") - List> describeSuperTable(@Param("dataBaseName") String dataBaseName, - @Param("superTableName") String superTableName); - - /** - * 为超级表添加列 - * - * @param dataBaseName 数据库名称 - * @param superTableName 超级表名称 - * @param field 字段信息 - */ - @InterceptorIgnore(tenantLine = "true") - void addColumnForSuperTable(@Param("dataBaseName") String dataBaseName, - @Param("superTableName") String superTableName, - @Param("field") TdFieldDO field); - - /** - * 为超级表删除列 - * - * @param dataBaseName 数据库名称 - * @param superTableName 超级表名称 - * @param field 字段信息 - */ - @InterceptorIgnore(tenantLine = "true") - void dropColumnForSuperTable(@Param("dataBaseName") String dataBaseName, - @Param("superTableName") String superTableName, - @Param("field") TdFieldDO field); - - /** - * 创建表 - 创建超级表的子表 - * - * @param tableDO 表信息 - */ - @InterceptorIgnore(tenantLine = "true") - void createTable(TableDO tableDO); - - /** - * 插入数据 - 指定列插入数据 - * - * @param tableDto 数据 - */ - @InterceptorIgnore(tenantLine = "true") - void insertData(TableDO tableDto); - - List> selectByTimestamp(SelectDto selectDto); - - - void addTagForSuperTable(@Param("superTableName") String superTableName, - @Param("fieldsVo") FieldsVo fieldsVo); - - void dropTagForSuperTable(@Param("superTableName") String superTableName, - @Param("fieldsVo") FieldsVo fieldsVo); - - Map getCountByTimestamp(SelectDto selectDto); - - Map getLastData(SelectDto selectDto); - - @InterceptorIgnore(tenantLine = "true") - List> getHistoryData(SelectVisualDto selectVisualDto); - - List> getRealtimeData(SelectVisualDto selectVisualDto); - - List> getAggregateData(SelectVisualDto selectVisualDto); - - List> getLastDataByTags(TagsSelectDao tagsSelectDao); - - @InterceptorIgnore(tenantLine = "true") - Long getHistoryCount(SelectVisualDto selectVisualDto); -} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java new file mode 100644 index 000000000..e5353f7ee --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.iot.dal.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TagsSelectDO; +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; +import java.util.Map; + +/** + * TD 引擎的查询 Mapper + */ +@Mapper +@DS("tdengine") +public interface TdEngineQueryMapper { + + /** + * 根据时间戳查询数据 + * + * @param selectDO 查询条件 + * @return 查询结果 + */ + List> selectByTimestamp(SelectDO selectDO); + + /** + * 根据时间戳获取数据条数 + * + * @param selectDO 查询条件 + * @return 数据条数 + */ + Map getCountByTimestamp(SelectDO selectDO); + + /** + * 获取最新数据 + * + * @param selectDO 查询条件 + * @return 最新数据 + */ + Map getLastData(SelectDO selectDO); + + /** + * 获取历史数据 + * + * @param selectVisualDO 查询条件 + * @return 历史数据列表 + */ + @InterceptorIgnore(tenantLine = "true") + List> getHistoryData(SelectVisualDO selectVisualDO); + + /** + * 获取实时数据 + * + * @param selectVisualDO 查询条件 + * @return 实时数据列表 + */ + List> getRealtimeData(SelectVisualDO selectVisualDO); + + /** + * 获取聚合数据 + * + * @param selectVisualDO 查询条件 + * @return 聚合数据列表 + */ + List> getAggregateData(SelectVisualDO selectVisualDO); + + /** + * 根据标签获取最新数据 + * + * @param tagsSelectDO 查询条件 + * @return 最新数据列表 + */ + List> getLastDataByTags(TagsSelectDO tagsSelectDO); + + /** + * 获取历史数据条数 + * + * @param selectVisualDO 查询条件 + * @return 数据条数 + */ + @InterceptorIgnore(tenantLine = "true") + Long getHistoryCount(SelectVisualDO selectVisualDO); +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineSuperTableMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineSuperTableMapper.java new file mode 100644 index 000000000..e688563d5 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineSuperTableMapper.java @@ -0,0 +1,111 @@ +package cn.iocoder.yudao.module.iot.dal.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; +import java.util.Map; + +/** + * TD 引擎的超级表 Mapper + */ +@Mapper +@DS("tdengine") +public interface TdEngineSuperTableMapper { + + /** + * 创建超级表 + * SQL:CREATE STABLE [IF NOT EXISTS] stb_name (create_definition [, create_definition] ...) TAGS (create_definition [, create_definition] ...) [table_options]; + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * columns 列信息 + * tags 标签信息 + */ + @InterceptorIgnore(tenantLine = "true") + void createSuperTable(TdTableDO superTable); + + /** + * 查看超级表 - 显示当前数据库下的所有超级表信息 + * SQL:SHOW STABLES [LIKE tb_name_wildcard]; + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + */ + @InterceptorIgnore(tenantLine = "true") + List> showSuperTables(TdTableDO superTable); + + /** + * 查看超级表 - 获取超级表的结构信息 + * SQL:DESCRIBE [db_name.]stb_name; + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + */ + @InterceptorIgnore(tenantLine = "true") + List> describeSuperTable(TdTableDO superTable); + + /** + * 修改超级表 - 增加列 + * SQL:ALTER STABLE stb_name ADD COLUMN col_name column_type; + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * column 列信息 + */ + @InterceptorIgnore(tenantLine = "true") + void addColumnForSuperTable(TdTableDO superTable); + + /** + * 修改超级表 - 删除列 + * SQL:ALTER STABLE stb_name DROP COLUMN col_name; + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * column 列信息 + */ + @InterceptorIgnore(tenantLine = "true") + void dropColumnForSuperTable(TdTableDO superTable); + + /** + * 修改超级表 - 修改列宽 + * SQL:ALTER STABLE stb_name MODIFY COLUMN col_name data_type(length); + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * column 列信息 + */ + @InterceptorIgnore(tenantLine = "true") + void modifyColumnWidthForSuperTable(TdTableDO superTable); + + + /** + * 修改超级表 - 为超级表添加标签 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tag 标签信息 + */ + @InterceptorIgnore(tenantLine = "true") + void addTagForSuperTable(TdTableDO superTable); + + /** + * 修改超级表 - 为超级表删除标签 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tag 标签信息 + */ + @InterceptorIgnore(tenantLine = "true") + void dropTagForSuperTable(TdTableDO superTable); +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java new file mode 100644 index 000000000..72517bcab --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.iot.dal.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import org.apache.ibatis.annotations.Mapper; + +/** + * TD 引擎的表 Mapper + */ +@Mapper +@DS("tdengine") +public interface TdEngineTableMapper { + + /** + * 创建子表 - 创建子表 + * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name TAGS (tag_value1, ...); + * + * @param table 表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tableName 子表名称 + * tags TAG 字段 + */ + @InterceptorIgnore(tenantLine = "true") + void createTable(TdTableDO table); + + /** + * 创建子表 - 创建子表并指定标签的值 + * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name (tag_name1, ...) TAGS (tag_value1, ...); + * + * @param table 表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tableName 子表名称 + * tags TAG 字段 + */ + @InterceptorIgnore(tenantLine = "true") + void createTableWithTags(TdTableDO table); + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java index 1b44bd5d0..4179075df 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java @@ -6,13 +6,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineMapper; -import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import cn.iocoder.yudao.module.iot.service.tdengine.IotThingModelMessageService; +import cn.iocoder.yudao.module.iot.service.tdengine.TdEngineQueryService; import cn.iocoder.yudao.module.iot.service.thinkmodelfunction.IotThinkModelFunctionService; import jakarta.annotation.Resource; import jakarta.validation.Valid; @@ -39,13 +39,12 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { private IotThingModelMessageService thingModelMessageService; @Resource private IotThinkModelFunctionService thinkModelFunctionService; + @Resource + private TdEngineQueryService tdEngineQueryService; @Resource private DeviceDataRedisDAO deviceDataRedisDAO; - @Resource - private TdEngineMapper tdEngineMapper; - @Override public void saveDeviceData(String productKey, String deviceName, String message) { // 1. 根据产品 key 和设备名称,获得设备信息 @@ -112,18 +111,18 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { // 1. 获取设备信息 IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId()); // 2. 获取设备属性历史数据 - SelectVisualDto selectVisualDto = new SelectVisualDto(); - selectVisualDto.setDataBaseName(getDatabaseName()); - selectVisualDto.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())); - selectVisualDto.setFieldName(deviceDataReqVO.getIdentifier()); - selectVisualDto.setStartTime(DateUtil.date(deviceDataReqVO.getTimes()[0].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime()); - selectVisualDto.setEndTime(DateUtil.date(deviceDataReqVO.getTimes()[1].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime()); + SelectVisualDO selectVisualDO = new SelectVisualDO(); + selectVisualDO.setDataBaseName(getDatabaseName()); + selectVisualDO.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())); + selectVisualDO.setFieldName(deviceDataReqVO.getIdentifier()); + selectVisualDO.setStartTime(DateUtil.date(deviceDataReqVO.getTimes()[0].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime()); + selectVisualDO.setEndTime(DateUtil.date(deviceDataReqVO.getTimes()[1].atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()).getTime()); Map params = new HashMap<>(); params.put("rows", deviceDataReqVO.getPageSize()); params.put("page", (deviceDataReqVO.getPageNo() - 1) * deviceDataReqVO.getPageSize()); - selectVisualDto.setParams(params); - pageResult.setList(tdEngineMapper.getHistoryData(selectVisualDto)); - pageResult.setTotal(tdEngineMapper.getHistoryCount(selectVisualDto)); + selectVisualDO.setParams(params); + pageResult.setList(tdEngineQueryService.getHistoryData(selectVisualDO)); + pageResult.setTotal(tdEngineQueryService.getHistoryCount(selectVisualDO)); return pageResult; } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java similarity index 50% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataService.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java index 42439e25a..7c88b83aa 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java @@ -1,26 +1,15 @@ package cn.iocoder.yudao.module.iot.service.tdengine; -import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelRespVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import java.util.List; /** - * 数据结构接口 + * IoT 超级表服务,负责根据物模型创建和更新超级表,以及创建超级表的子表等操作。 */ -public interface IotDbStructureDataService { - - /** - * 创建物模型定义 - */ - void createSuperTable(ThingModelRespVO thingModel, Integer deviceType); - - /** - * 更新物模型定义 - */ - void updateSuperTable(ThingModelRespVO thingModel, Integer deviceType); +public interface IotSuperTableService { /** * 创建超级表数据模型 diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableServiceImpl.java similarity index 55% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableServiceImpl.java index 947178102..3be324c4e 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotDbStructureDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableServiceImpl.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingMode import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import jakarta.annotation.Resource; @@ -17,135 +18,19 @@ import org.springframework.stereotype.Service; import java.util.*; import java.util.stream.Collectors; +/** + * IoT 超级表服务实现类,负责根据物模型创建和更新超级表,以及创建超级表的子表等操作。 + */ @Service @Slf4j -public class IotDbStructureDataServiceImpl implements IotDbStructureDataService { +public class IotSuperTableServiceImpl implements IotSuperTableService { @Resource - private IotTdEngineService iotTdEngineService; + private TdEngineSuperTableService tdEngineSuperTableService; @Value("${spring.datasource.dynamic.datasource.tdengine.url}") private String url; - @Override - public void createSuperTable(ThingModelRespVO thingModel, Integer deviceType) { - // 1. 解析物模型,获得字段列表 - List schemaFields = new ArrayList<>(); - schemaFields.add(TdFieldDO.builder() - .fieldName("time") - .dataType("TIMESTAMP") - .build()); - schemaFields.addAll(FieldParser.parse(thingModel)); - - // 3. 设置超级表的标签 - List tagsFields = Arrays.asList( - TdFieldDO.builder().fieldName("product_key").dataType("NCHAR").dataLength(64).build(), - TdFieldDO.builder().fieldName("device_key").dataType("NCHAR").dataLength(64).build(), - TdFieldDO.builder().fieldName("device_name").dataType("NCHAR").dataLength(64).build(), - TdFieldDO.builder().fieldName("device_type").dataType("INT").build() - ); - - // 4. 获取超级表的名称 - String superTableName = getProductPropertySTableName(deviceType, thingModel.getProductKey()); - - // 5. 创建超级表 - String dataBaseName = getDatabaseName(); - iotTdEngineService.createSuperTable(schemaFields, tagsFields, dataBaseName, superTableName); - } - - @Override - public void updateSuperTable(ThingModelRespVO thingModel, Integer deviceType) { - try { - String tbName = getProductPropertySTableName(deviceType, thingModel.getProductKey()); - List oldFields = getTableFields(tbName); - List newFields = FieldParser.parse(thingModel); - - updateTableFields(tbName, oldFields, newFields); - } catch (Exception e) { - log.error("更新物模型超级表失败", e); - } - } - - // 获取表字段 - private List getTableFields(String tableName) { - List fields = new ArrayList<>(); - // 获取超级表的描述信息 - List> maps = iotTdEngineService.describeSuperTable(getDatabaseName(), tableName); - if (maps != null) { - // 过滤掉 note 字段为 TAG 的记录和 time 字段 - List> filteredMaps = maps.stream() - .filter(map -> !"TAG".equals(map.get("note"))) - .filter(map -> !"time".equals(map.get("field"))) - .toList(); - // 解析字段信息 - fields = FieldParser.parse(filteredMaps.stream() - .map(map -> List.of(map.get("field"), map.get("type"), map.get("length"))) - .collect(Collectors.toList())); - } - return fields; - } - - // 更新表字段 - private void updateTableFields(String tableName, List oldFields, List newFields) { - // 获取新增字段 - List addFields = getAddFields(oldFields, newFields); - // 获取修改字段 - List modifyFields = getModifyFields(oldFields, newFields); - // 获取删除字段 - List dropFields = getDropFields(oldFields, newFields); - - String dataBaseName = getDatabaseName(); - // 添加新增字段 - if (CollUtil.isNotEmpty(addFields)) { - iotTdEngineService.addColumnForSuperTable(dataBaseName, tableName, addFields); - } - // 删除旧字段 - if (CollUtil.isNotEmpty(dropFields)) { - iotTdEngineService.dropColumnForSuperTable(dataBaseName, tableName, dropFields); - } - // 修改字段(先删除再添加) - if (CollUtil.isNotEmpty(modifyFields)) { - iotTdEngineService.dropColumnForSuperTable(dataBaseName, tableName, modifyFields); - iotTdEngineService.addColumnForSuperTable(dataBaseName, tableName, modifyFields); - } - } - - // 获取新增字段 - private List getAddFields(List oldFields, List newFields) { - Set oldFieldNames = oldFields.stream() - .map(TdFieldDO::getFieldName) - .collect(Collectors.toSet()); - return newFields.stream() - .filter(f -> !oldFieldNames.contains(f.getFieldName())) - .collect(Collectors.toList()); - } - - // 获取修改字段 - private List getModifyFields(List oldFields, List newFields) { - Map oldFieldMap = oldFields.stream() - .collect(Collectors.toMap(TdFieldDO::getFieldName, f -> f)); - - return newFields.stream() - .filter(f -> { - TdFieldDO oldField = oldFieldMap.get(f.getFieldName()); - return oldField != null && - (!oldField.getDataType().equals(f.getDataType()) || - !Objects.equals(oldField.getDataLength(), f.getDataLength())); - }) - .collect(Collectors.toList()); - } - - // 获取删除字段 - private List getDropFields(List oldFields, List newFields) { - Set newFieldNames = newFields.stream() - .map(TdFieldDO::getFieldName) - .collect(Collectors.toSet()); - return oldFields.stream() - .filter(f -> !"time".equals(f.getFieldName()) && !"device_id".equals(f.getFieldName())) - .filter(f -> !newFieldNames.contains(f.getFieldName())) - .collect(Collectors.toList()); - } - @Override public void createSuperTableDataModel(IotProductDO product, List functionList) { ThingModelRespVO thingModel = buildThingModel(product, functionList); @@ -155,9 +40,9 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService return; } - String superTableName = getProductPropertySTableName(product.getDeviceType(), product.getProductKey()); - String dataBaseName = getDatabaseName(); - Integer tableExists = iotTdEngineService.checkSuperTableExists(dataBaseName, superTableName); + String superTableName = getSuperTableName(product.getDeviceType(), product.getProductKey()); + String databaseName = getDatabaseName(); + Integer tableExists = tdEngineSuperTableService.checkSuperTableExists(new TdTableDO(databaseName, superTableName)); if (tableExists != null && tableExists > 0) { updateSuperTable(thingModel, product.getDeviceType()); @@ -166,40 +51,202 @@ public class IotDbStructureDataServiceImpl implements IotDbStructureDataService } } + /** + * 创建超级表 + */ + private void createSuperTable(ThingModelRespVO thingModel, Integer deviceType) { + // 解析物模型,获取字段列表 + List schemaFields = new ArrayList<>(); + schemaFields.add(TdFieldDO.builder() + .fieldName("time") + .dataType("TIMESTAMP") + .build()); + schemaFields.addAll(FieldParser.parse(thingModel)); + + // 设置超级表的标签 + List tagsFields = List.of( + TdFieldDO.builder().fieldName("product_key").dataType("NCHAR").dataLength(64).build(), + TdFieldDO.builder().fieldName("device_key").dataType("NCHAR").dataLength(64).build(), + TdFieldDO.builder().fieldName("device_name").dataType("NCHAR").dataLength(64).build(), + TdFieldDO.builder().fieldName("device_type").dataType("INT").build() + ); + + // 获取超级表的名称和数据库名称 + String superTableName = getSuperTableName(deviceType, thingModel.getProductKey()); + String databaseName = getDatabaseName(); + + // 创建超级表 + tdEngineSuperTableService.createSuperTable(new TdTableDO(databaseName, superTableName, schemaFields, tagsFields)); + } + + /** + * 更新超级表 + */ + private void updateSuperTable(ThingModelRespVO thingModel, Integer deviceType) { + String superTableName = getSuperTableName(deviceType, thingModel.getProductKey()); + try { + List oldFields = getTableFields(superTableName); + List newFields = FieldParser.parse(thingModel); + + updateTableFields(superTableName, oldFields, newFields); + } catch (Exception e) { + log.error("更新物模型超级表失败: {}", e.getMessage(), e); + } + } + + /** + * 获取表的字段信息 + */ + private List getTableFields(String tableName) { + List> tableDescription = tdEngineSuperTableService.describeSuperTable(new TdTableDO(getDatabaseName(), tableName)); + if (CollUtil.isEmpty(tableDescription)) { + return Collections.emptyList(); + } + + return tableDescription.stream() + .filter(map -> !"TAG".equals(map.get("note"))) + .filter(map -> !"time".equals(map.get("field"))) + .map(map -> TdFieldDO.builder() + .fieldName((String) map.get("field")) + .dataType((String) map.get("type")) + .dataLength((Integer) map.get("length")) + .build()) + .collect(Collectors.toList()); + } + + /** + * 更新表的字段,包括新增、修改和删除字段 + */ + private void updateTableFields(String tableName, List oldFields, List newFields) { + String databaseName = getDatabaseName(); + + // 获取新增、修改、删除的字段 + List addFields = getAddFields(oldFields, newFields); + List modifyFields = getModifyFields(oldFields, newFields); + List dropFields = getDropFields(oldFields, newFields); + + // 添加新增字段 + if (CollUtil.isNotEmpty(addFields)) { + tdEngineSuperTableService.addColumnsForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .columns(addFields) + .build()); + } + // 删除旧字段 + if (CollUtil.isNotEmpty(dropFields)) { + tdEngineSuperTableService.dropColumnsForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .columns(dropFields) + .build()); + } + // 修改字段(先删除再添加) + if (CollUtil.isNotEmpty(modifyFields)) { + tdEngineSuperTableService.dropColumnsForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .columns(modifyFields) + .build()); + tdEngineSuperTableService.addColumnsForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .columns(addFields) + .build()); + } + } + + /** + * 获取需要新增的字段 + */ + private List getAddFields(List oldFields, List newFields) { + Set oldFieldNames = oldFields.stream() + .map(TdFieldDO::getFieldName) + .collect(Collectors.toSet()); + return newFields.stream() + .filter(f -> !oldFieldNames.contains(f.getFieldName())) + .collect(Collectors.toList()); + } + + /** + * 获取需要修改的字段 + */ + private List getModifyFields(List oldFields, List newFields) { + Map oldFieldMap = oldFields.stream() + .collect(Collectors.toMap(TdFieldDO::getFieldName, f -> f)); + + return newFields.stream() + .filter(f -> { + TdFieldDO oldField = oldFieldMap.get(f.getFieldName()); + return oldField != null && ( + !oldField.getDataType().equals(f.getDataType()) || + !Objects.equals(oldField.getDataLength(), f.getDataLength()) + ); + }) + .collect(Collectors.toList()); + } + + /** + * 获取需要删除的字段 + */ + private List getDropFields(List oldFields, List newFields) { + Set newFieldNames = newFields.stream() + .map(TdFieldDO::getFieldName) + .collect(Collectors.toSet()); + return oldFields.stream() + .filter(f -> !"time".equals(f.getFieldName())) + .filter(f -> !newFieldNames.contains(f.getFieldName())) + .collect(Collectors.toList()); + } + + /** + * 构建物模型 + */ private ThingModelRespVO buildThingModel(IotProductDO product, List functionList) { ThingModelRespVO thingModel = new ThingModelRespVO(); thingModel.setId(product.getId()); thingModel.setProductKey(product.getProductKey()); - ThingModelRespVO.Model model = new ThingModelRespVO.Model(); List properties = functionList.stream() .filter(function -> IotProductFunctionTypeEnum.PROPERTY.equals( IotProductFunctionTypeEnum.valueOfType(function.getType()))) .map(this::buildThingModelProperty) .collect(Collectors.toList()); + ThingModelRespVO.Model model = new ThingModelRespVO.Model(); model.setProperties(properties); thingModel.setModel(model); return thingModel; } + /** + * 构建物模型属性 + */ private ThingModelProperty buildThingModelProperty(IotThinkModelFunctionDO function) { ThingModelProperty property = BeanUtil.copyProperties(function, ThingModelProperty.class); property.setDataType(function.getProperty().getDataType()); return property; } + /** + * 获取数据库名称 + */ private String getDatabaseName() { - return url.substring(url.lastIndexOf("/") + 1); + int index = url.lastIndexOf("/"); + return index != -1 ? url.substring(index + 1) : url; } - static String getProductPropertySTableName(Integer deviceType, String productKey) { - return switch (deviceType) { - case 1 -> String.format("gateway_sub_%s", productKey).toLowerCase(); - case 2 -> String.format("gateway_%s", productKey).toLowerCase(); - default -> String.format("device_%s", productKey).toLowerCase(); + /** + * 获取超级表名称 + */ + private String getSuperTableName(Integer deviceType, String productKey) { + String prefix = switch (deviceType) { + case 1 -> "gateway_sub_"; + case 2 -> "gateway_"; + default -> "device_"; }; + return (prefix + productKey).toLowerCase(); } } \ 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/tdengine/IotTdEngineService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineService.java deleted file mode 100644 index 753284aca..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineService.java +++ /dev/null @@ -1,142 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; -import cn.iocoder.yudao.module.iot.domain.SelectDto; -import cn.iocoder.yudao.module.iot.domain.TagsSelectDao; -import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; - -import java.util.List; -import java.util.Map; - -/** - * TdEngineService - */ -public interface IotTdEngineService { - - /** - * 创建数据库 - * - * @param dataBaseName 数据库名称 - * @throws Exception 异常 - */ - void createDateBase(String dataBaseName) throws Exception; - - /** - * 创建超级表 - * - * @param schemaFields schema字段 - * @param tagsFields tags字段 - * @param superTableName 超级表名称 - */ - void createSuperTable(List schemaFields, List tagsFields, String dataBaseName, String superTableName); - - /** - * 检查超级表是否存在 - */ - Integer checkSuperTableExists(String dataBaseName, String superTableName); - - - /** - * 获取超级表的结构信息 - */ - List> describeSuperTable(String dataBaseName, String superTableName); - - /** - * 为超级表添加列 - * - * @param dataBaseName 数据库名称 - * @param superTableName 超级表名称 - * @param fieldsVo 字段信息 - */ - void addColumnForSuperTable(String dataBaseName, String superTableName, List fieldsVo); - - /** - * 为超级表删除列 - * - * @param dataBaseName 数据库名称 - * @param superTableName 超级表名称 - * @param fieldsVo 字段信息 - */ - void dropColumnForSuperTable(String dataBaseName, String superTableName, List fieldsVo); - - /** - * 为超级表添加tag - */ - Long getCountByTimesTamp(SelectDto selectDto) throws Exception; - - - /** - * 创建表 - * - * @param tableDto 表信息 - */ - void createTable(TableDO tableDto); - - /** - * 插入数据 - * - * @param tableDto 表信息 - */ - void insertData(TableDO tableDto); - - /** - * 根据时间戳查询数据 - * - * @param selectDto 查询条件 - * @return 数据 - * @throws Exception 异常 - */ - List> selectByTimesTamp(SelectDto selectDto) throws Exception; - - /** - * 初始化超级表 - * - * @param msg 消息 - * @throws Exception 异常 - */ - void initSTableFrame(String msg) throws Exception; - - /** - * 获取最新数据 - * - * @param selectDto 查询条件 - * @return 数据 - * @throws Exception 异常 - */ - Map getLastData(SelectDto selectDto) throws Exception; - - /** - * 根据tag查询最新数据 - * - * @param tagsSelectDao 查询条件 - * @return 数据 - */ - Map> getLastDataByTags(TagsSelectDao tagsSelectDao); - - /** - * 获取历史数据 - * - * @param selectVisualDto 查询条件 - * @return 数据 - */ - List> getHistoryData(SelectVisualDto selectVisualDto); - - /** - * 获取实时数据 - * - * @param selectVisualDto 查询条件 - * @return 数据 - */ - List> getRealtimeData(SelectVisualDto selectVisualDto); - - /** - * 获取聚合数据 - * - * @param selectVisualDto 查询条件 - * @return 数据 - */ - List> getAggregateData(SelectVisualDto selectVisualDto); - - -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineServiceImpl.java deleted file mode 100644 index c7f7e7309..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotTdEngineServiceImpl.java +++ /dev/null @@ -1,107 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineMapper; -import cn.iocoder.yudao.module.iot.domain.SelectDto; -import cn.iocoder.yudao.module.iot.domain.TagsSelectDao; -import cn.iocoder.yudao.module.iot.domain.visual.SelectVisualDto; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Map; - -@Service -@Slf4j -public class IotTdEngineServiceImpl implements IotTdEngineService { - - @Resource - private TdEngineMapper tdEngineMapper; - - @Override - public void createDateBase(String dataBaseName) { - tdEngineMapper.createDatabase(dataBaseName); - } - - @Override - public void createSuperTable(List schemaFields, List tagsFields, String dataBaseName, String superTableName) { - tdEngineMapper.createSuperTable(schemaFields, tagsFields, dataBaseName, superTableName); - } - - @Override - public void createTable(TableDO tableDto) { - tdEngineMapper.createTable(tableDto); - } - - @Override - public void insertData(TableDO tableDto) { - tdEngineMapper.insertData(tableDto); - } - - @Override - public List> selectByTimesTamp(SelectDto selectDto) { - return List.of(); - } - - @Override - public void addColumnForSuperTable(String dataBaseName,String superTableName, List fields) { - for (TdFieldDO field : fields) { - tdEngineMapper.addColumnForSuperTable(dataBaseName,superTableName, field); - } - } - - @Override - public void dropColumnForSuperTable(String dataBaseName,String superTableName, List fields) { - for (TdFieldDO field : fields) { - tdEngineMapper.dropColumnForSuperTable(dataBaseName,superTableName, field); - } - } - - @Override - public Long getCountByTimesTamp(SelectDto selectDto) { - return 0L; - } - - @Override - public void initSTableFrame(String msg) { - - } - - @Override - public Map getLastData(SelectDto selectDto) { - return Map.of(); - } - - @Override - public Map> getLastDataByTags(TagsSelectDao tagsSelectDao) { - return Map.of(); - } - - @Override - public List> getHistoryData(SelectVisualDto selectVisualDto) { - return List.of(); - } - - @Override - public List> getRealtimeData(SelectVisualDto selectVisualDto) { - return List.of(); - } - - @Override - public List> getAggregateData(SelectVisualDto selectVisualDto) { - return List.of(); - } - - @Override - public Integer checkSuperTableExists(String dataBaseName, String superTableName) { - List> results = tdEngineMapper.showSuperTables(dataBaseName, superTableName); - return results == null || results.isEmpty() ? 0 : results.size(); - } - - @Override - public List> describeSuperTable(String dataBaseName, String superTableName) { - return tdEngineMapper.describeSuperTable(dataBaseName, superTableName); - } -} \ 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/tdengine/IotThingModelMessageService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java index b2f51a7f8..ffcb3063c 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageService.java @@ -11,8 +11,8 @@ public interface IotThingModelMessageService { /** * 保存物模型消息 * - * @param device 设备 + * @param device 设备 * @param thingModelMessage 物模型消息 */ - void saveThingModelMessage(IotDeviceDO device,ThingModelMessage thingModelMessage); + void saveThingModelMessage(IotDeviceDO device, ThingModelMessage thingModelMessage); } \ 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/tdengine/IotThingModelMessageServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java index 9bad7613e..69c417839 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java @@ -6,8 +6,8 @@ import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceSt import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TableDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; @@ -23,6 +23,9 @@ import org.springframework.stereotype.Service; import java.util.*; import java.util.stream.Collectors; +/** + * 物模型消息 Service 实现类 + */ @Slf4j @Service public class IotThingModelMessageServiceImpl implements IotThingModelMessageService { @@ -35,7 +38,11 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @Resource private IotDeviceService iotDeviceService; @Resource - private IotTdEngineService iotTdEngineService; + private TdEngineTableService tdEngineTableService; + @Resource + private TdEngineSuperTableService tdEngineSuperTableService; + @Resource + private TdEngineDataWriterService tdEngineDataWriterService; @Resource private DeviceDataRedisDAO deviceDataRedisDAO; @@ -90,14 +97,11 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ return; } - // 构建并保存设备属性 - TableDO tableData = new TableDO(); - tableData.setDataBaseName(getDatabaseName()); - tableData.setSuperTableName(getProductPropertySTableName(device.getDeviceType(), device.getProductKey())); - tableData.setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())); - tableData.setSchemaFieldValues(schemaFieldValues); - - iotTdEngineService.insertData(tableData); + // 构建并保存设备属性数据 + tdEngineDataWriterService.insertData(TdTableDO.builder().build() + .setDataBaseName(getDatabaseName()) + .setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())) + .setColumns(schemaFieldValues)); } /** @@ -135,7 +139,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ String superTableName = getProductPropertySTableName(deviceType, productKey); String dataBaseName = getDatabaseName(); - List> maps = iotTdEngineService.describeSuperTable(dataBaseName, superTableName); + List> maps = tdEngineSuperTableService.describeSuperTable(new TdTableDO(dataBaseName, superTableName)); List tagsFieldValues = new ArrayList<>(); if (maps != null) { @@ -159,13 +163,11 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ // 创建设备数据表 String tableName = getDeviceTableName(productKey, deviceName); - TableDO tableDto = new TableDO(); - tableDto.setDataBaseName(dataBaseName); - tableDto.setSuperTableName(superTableName); - tableDto.setTableName(tableName); - tableDto.setTagsFieldValues(tagsFieldValues); - - iotTdEngineService.createTable(tableDto); + tdEngineTableService.createTable(TdTableDO.builder().build() + .setDataBaseName(dataBaseName) + .setSuperTableName(superTableName) + .setTableName(tableName) + .setTags(tagsFieldValues)); } /** diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterService.java new file mode 100644 index 000000000..0995b0797 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterService.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; + +/** + * TD 引擎的数据写入 Service 接口 + */ +public interface TdEngineDataWriterService { + + /** + * 插入数据 - 指定列插入数据 + * + * @param table 数据 + * dataBaseName 数据库名 + * tableName 表名 + * columns 列 + */ + void insertData(TdTableDO table); +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java new file mode 100644 index 000000000..f4dd2c8fd --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDataWriterMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +/** + * TD 引擎的数据写入 Service 实现类 + */ +@Service +public class TdEngineDataWriterServiceImpl implements TdEngineDataWriterService { + + @Resource + private TdEngineDataWriterMapper tdEngineDataWriterMapper; + + @Override + public void insertData(TdTableDO table) { + tdEngineDataWriterMapper.insertData(table); + } +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java new file mode 100644 index 000000000..d895262cc --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java @@ -0,0 +1,14 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +/** + * TD 引擎的数据库 Service 接口 + */ +public interface TdEngineDatabaseService { + + /** + * 创建数据库 + * + * @param dataBaseName 数据库名称 + */ + void createDatabase(String dataBaseName); +} \ 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/tdengine/TdEngineDatabaseServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseServiceImpl.java new file mode 100644 index 000000000..c880db8a9 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseServiceImpl.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDatabaseMapper; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * TD 引擎的数据库 Service 实现类 + */ +@Service +@Slf4j +public class TdEngineDatabaseServiceImpl implements TdEngineDatabaseService { + + @Resource + private TdEngineDatabaseMapper tdEngineDatabaseMapper; + + @Override + public void createDatabase(String dataBaseName) { + tdEngineDatabaseMapper.createDatabase(dataBaseName); + } +} \ 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/tdengine/TdEngineQueryService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryService.java new file mode 100644 index 000000000..8d07b4334 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryService.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; + +import java.util.List; +import java.util.Map; + +/** + * TD 引擎的查询 Service 接口 + */ +public interface TdEngineQueryService { + + /** + * 获取历史数据 + * + * @param selectVisualDO 查询条件 + * @return 历史数据列表 + */ + List> getHistoryData(SelectVisualDO selectVisualDO); + + /** + * 获取历史数据条数 + * + * @param selectVisualDO 查询条件 + * @return 数据条数 + */ + Long getHistoryCount(SelectVisualDO selectVisualDO); +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java new file mode 100644 index 000000000..672a58640 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineQueryMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +@Service +public class TdEngineQueryServiceImpl implements TdEngineQueryService { + + @Resource + private TdEngineQueryMapper tdEngineQueryMapper; + + @Override + public List> getHistoryData(SelectVisualDO selectVisualDO) { + return tdEngineQueryMapper.getHistoryData(selectVisualDO); + } + + @Override + public Long getHistoryCount(SelectVisualDO selectVisualDO) { + return tdEngineQueryMapper.getHistoryCount(selectVisualDO); + } +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java new file mode 100644 index 000000000..df6290a98 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java @@ -0,0 +1,123 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; + +import java.util.List; +import java.util.Map; + +/** + * TD 引擎的超级表 Service 接口 + */ +public interface TdEngineSuperTableService { + + /** + * 创建超级表 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * columns 列信息 + * tags 标签信息 + */ + void createSuperTable(TdTableDO superTable); + + /** + * 查看超级表 - 显示当前数据库下的所有超级表信息 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + */ + + List> showSuperTables(TdTableDO superTable); + + /** + * 查看超级表 - 获取超级表的结构信息 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + */ + List> describeSuperTable(TdTableDO superTable); + + /** + * 修改超级表 - 增加列 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * column 列信息 + */ + void addColumnForSuperTable(TdTableDO superTable); + + /** + * 修改超级表 - 删除列 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * column 列信息 + */ + void dropColumnForSuperTable(TdTableDO superTable); + + /** + * 修改超级表 - 修改列宽 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * column 列信息 + */ + void modifyColumnWidthForSuperTable(TdTableDO superTable); + + + /** + * 修改超级表 - 为超级表添加标签 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tag 标签信息 + */ + void addTagForSuperTable(TdTableDO superTable); + + /** + * 修改超级表 - 为超级表删除标签 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tag 标签信息 + */ + void dropTagForSuperTable(TdTableDO superTable); + + /** + * 检查超级表是否存在 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * @return 超级表数量 + */ + Integer checkSuperTableExists(TdTableDO superTable); + + /** + * 为超级表添加列 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * columns 列信息 + */ + void addColumnsForSuperTable(TdTableDO superTable); + + /** + * 为超级表删除列 + * + * @param superTable 超级表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * columns 列信息 + */ + void dropColumnsForSuperTable(TdTableDO superTable); +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java new file mode 100644 index 000000000..60436e7bd --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineSuperTableMapper; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; + +/** + * TD 引擎的超级表 Service 实现类 + */ +@Slf4j +@Service +public class TdEngineSuperTableServiceImpl implements TdEngineSuperTableService { + + @Resource + private TdEngineSuperTableMapper tdEngineSuperTableMapper; + + @Override + public void createSuperTable(TdTableDO superTable) { + tdEngineSuperTableMapper.createSuperTable(superTable); + } + + @Override + public List> showSuperTables(TdTableDO superTable) { + return tdEngineSuperTableMapper.showSuperTables(superTable); + } + + @Override + public List> describeSuperTable(TdTableDO superTable) { + return tdEngineSuperTableMapper.describeSuperTable(superTable); + } + + @Override + public void addColumnForSuperTable(TdTableDO superTable) { + tdEngineSuperTableMapper.addColumnForSuperTable(superTable); + } + + @Override + public void dropColumnForSuperTable(TdTableDO superTable) { + tdEngineSuperTableMapper.dropColumnForSuperTable(superTable); + } + + @Override + public void modifyColumnWidthForSuperTable(TdTableDO superTable) { + tdEngineSuperTableMapper.modifyColumnWidthForSuperTable(superTable); + } + + @Override + public void addTagForSuperTable(TdTableDO superTable) { + tdEngineSuperTableMapper.addTagForSuperTable(superTable); + } + + @Override + public void dropTagForSuperTable(TdTableDO superTable) { + tdEngineSuperTableMapper.dropTagForSuperTable(superTable); + } + + @Override + public Integer checkSuperTableExists(TdTableDO superTable) { + List> results = tdEngineSuperTableMapper.showSuperTables(superTable); + return results == null || results.isEmpty() ? 0 : results.size(); + } + + @Override + public void addColumnsForSuperTable(TdTableDO superTable) { + for (TdFieldDO column : superTable.getColumns()) { + tdEngineSuperTableMapper.addColumnForSuperTable(TdTableDO.builder() + .dataBaseName(superTable.getDataBaseName()) + .superTableName(superTable.getSuperTableName()) + .column(column) + .build()); + } + } + + @Override + public void dropColumnsForSuperTable(TdTableDO superTable) { + for (TdFieldDO column : superTable.getColumns()) { + tdEngineSuperTableMapper.dropColumnForSuperTable(TdTableDO.builder() + .dataBaseName(superTable.getDataBaseName()) + .superTableName(superTable.getSuperTableName()) + .column(column) + .build()); + } + } +} \ 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/tdengine/TdEngineTableService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableService.java new file mode 100644 index 000000000..078159784 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableService.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; + +/** + * TD 引擎的表 Service 接口 + */ +public interface TdEngineTableService { + + /** + * 创建表 - 创建超级表的子表 + * + * @param table 表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tableName 子表名称 + * tags TAG 字段 + */ + void createTable(TdTableDO table); + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java new file mode 100644 index 000000000..cdca47888 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.iot.service.tdengine; + +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineTableMapper; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * TD 引擎的表 Service 实现类 + */ +@Slf4j +@Service +public class TdEngineTableServiceImpl implements TdEngineTableService { + + @Resource + private TdEngineTableMapper tdEngineTableMapper; + + @Override + public void createTable(TdTableDO table) { + tdEngineTableMapper.createTable(table); + } +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java index a6bf7b458..f60610faf 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java @@ -75,5 +75,5 @@ public interface IotThinkModelFunctionService { * @param productKey 产品 Key * @return 产品物模型列表 */ - List getThinkModelFunctionListByProductKey(String productKey); + List getThinkModelFunctionListByProductKey(String productKey); } \ 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/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java index 25cfe7b46..404a2aaa0 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java @@ -22,7 +22,7 @@ import cn.iocoder.yudao.module.iot.enums.product.IotAccessModeEnum; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum; import cn.iocoder.yudao.module.iot.service.product.IotProductService; -import cn.iocoder.yudao.module.iot.service.tdengine.IotDbStructureDataService; +import cn.iocoder.yudao.module.iot.service.tdengine.IotSuperTableService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -52,7 +52,7 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe @Resource private IotProductService productService; @Resource - private IotDbStructureDataService dbStructureDataService; + private IotSuperTableService dbStructureDataService; @Override @Transactional(rollbackFor = Exception.class) diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml new file mode 100644 index 000000000..b5f044614 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml @@ -0,0 +1,22 @@ + + + + + + + + INSERT INTO ${dataBaseName}.${tableName} + + ${item.fieldName} + + VALUES + + #{item.fieldValue} + + + + \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml new file mode 100644 index 000000000..4d9a125db --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml @@ -0,0 +1,13 @@ + + + + + + + + CREATE DATABASE IF NOT EXISTS ${dataBaseName} + + + \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml deleted file mode 100644 index 4e127e44b..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineMapper.xml +++ /dev/null @@ -1,327 +0,0 @@ - - - - - - - - CREATE DATABASE IF NOT EXISTS ${dataBaseName} - - - - CREATE STABLE IF NOT EXISTS ${dataBaseName}.${superTableName} - - - ${item.fieldName} - - - - - TIMESTAMP - - - TINYINT - - - SMALLINT - - - INT - - - BIGINT - - - FLOAT - - - DOUBLE - - - BINARY - - - NCHAR - - - BOOL - - - JSON - - - - - ( - ${item.dataLength} - ) - - - TAGS - - - - ${item.fieldName} - - - - - TIMESTAMP - - - TINYINT - - - SMALLINT - - - INT - - - BIGINT - - - FLOAT - - - DOUBLE - - - BINARY - - - NCHAR - - - BOOL - - - JSON - - - - - ( - ${item.dataLength} - ) - - - - - - - CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} - USING ${dataBaseName}.${superTableName} - - ${item.fieldName} - - TAGS - - #{item.fieldValue} - - - - - - INSERT INTO ${dataBaseName}.${tableName} - - ${item.fieldName} - - VALUES - - #{item.fieldValue} - - - - - select * from #{dataBaseName}.#{tableName} - - - where ${fieldName} - between #{startTime} and #{endTime} - - - - ALTER STABLE ${dataBaseName}.${superTableName} ADD COLUMN - - #{field.fieldName} - - - - - TIMESTAMP - - - TINYINT - - - SMALLINT - - - INT - - - BIGINT - - - FLOAT - - - DOUBLE - - - BINARY - - - NCHAR - - - BOOL - - - JSON - - - - - ( - #{field.dataLength} - ) - - - - - ALTER STABLE ${dataBaseName}.${superTableName} DROP COLUMN - - #{field.fieldName} - - - - - ALTER - STABLE - #{superTableName} - ADD - TAG - - #{fieldDO.fieldName} - - - - - timestamp - - - tinyint - - - smallint - - - int - - - bigint - - - float - - - double - - - binary - - - nchar - - - bool - - - json - - - - - ( - #{fieldDO.dataLength} - ) - - - - - ALTER - STABLE - #{superTableName} - DROP - TAG - - #{fieldsVo.fieldName} - - - - - SELECT count(0) AS count - FROM #{dataBaseName}.#{tableName} - WHERE ${fieldName} BETWEEN #{startTime} AND #{endTime} - - - - SHOW ${dataBaseName}.STABLES LIKE '${superTableName}' - - - - select last(time), * - from #{tableName} - where device_id = #{deviceId} - - - - select last(*) - from #{dataBaseName}.#{stableName} - group by ${tagsName} - - - - SELECT ${fieldName} as data, time - FROM ${dataBaseName}.${tableName} - WHERE time BETWEEN #{startTime} AND #{endTime} - AND ${fieldName} IS NOT NULL - ORDER BY time DESC - LIMIT #{params.rows} offset #{params.page} - - - - SELECT #{fieldName}, time - FROM #{dataBaseName}.#{tableName} - - - - SELECT #{aggregate}(${fieldName}) - FROM #{dataBaseName}.#{tableName} - WHERE ts BETWEEN #{startTime} AND #{endTime} interval (${interval}) - LIMIT #{num} - - - - DESCRIBE ${dataBaseName}.${superTableName} - - - SELECT count(time) - FROM ${dataBaseName}.${tableName} - WHERE time BETWEEN #{startTime} AND #{endTime} - AND ${fieldName} IS NOT NULL - - - diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml new file mode 100644 index 000000000..9407b371d --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml @@ -0,0 +1,73 @@ + + + + + + + + SELECT * FROM ${dataBaseName}.${tableName} + WHERE ${fieldName} BETWEEN #{startTime} AND #{endTime} + + + + + SELECT COUNT(0) AS count + FROM ${dataBaseName}.${tableName} + WHERE ${fieldName} BETWEEN #{startTime} AND #{endTime} + + + + + SELECT LAST(time), * + FROM ${tableName} + WHERE device_id = #{deviceId} + + + + + SELECT LAST(*) + FROM ${dataBaseName}.${stableName} + GROUP BY ${tagsName} + + + + + SELECT ${fieldName} AS data, time + FROM ${dataBaseName}.${tableName} + WHERE time BETWEEN #{startTime} AND #{endTime} + AND ${fieldName} IS NOT NULL + ORDER BY time DESC + LIMIT #{params.rows} OFFSET #{params.page} + + + + + SELECT ${fieldName}, time + FROM ${dataBaseName}.${tableName} + + + + + SELECT ${aggregate}(${fieldName}) + FROM ${dataBaseName}.${tableName} + WHERE ts BETWEEN #{startTime} AND #{endTime} INTERVAL (${interval}) + LIMIT #{num} + + + + + SELECT COUNT(time) + FROM ${dataBaseName}.${tableName} + WHERE time BETWEEN #{startTime} AND #{endTime} + AND ${fieldName} IS NOT NULL + + + diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml new file mode 100644 index 000000000..1ddbe3b97 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + CREATE STABLE IF NOT EXISTS ${dataBaseName}.${superTableName} + + ${item.fieldName} ${item.dataType} + + (${item.dataLength}) + + + TAGS + + ${item.fieldName} ${item.dataType} + + (${item.dataLength}) + + + + + + + SHOW ${dataBaseName}.STABLES LIKE '${superTableName}' + + + + + DESCRIBE ${dataBaseName}.${superTableName} + + + + + ALTER STABLE ${dataBaseName}.${superTableName} ADD COLUMN ${column.fieldName} ${column.dataType} + + (${column.dataLength}) + + + + + + ALTER STABLE ${dataBaseName}.${superTableName} DROP COLUMN ${column.fieldName} + + + + + ALTER STABLE ${dataBaseName}.${superTableName} MODIFY COLUMN ${column.fieldName} ${column.dataType} + + (${column.dataLength}) + + + + + + ALTER STABLE ${dataBaseName}.${superTableName} ADD TAG ${tag.fieldName} ${tag.dataType} + + (${tag.dataLength}) + + + + + + ALTER STABLE ${dataBaseName}.${superTableName} DROP TAG ${tag.fieldName} + + + diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml new file mode 100644 index 000000000..2d469a390 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml @@ -0,0 +1,33 @@ + + + + + + + + CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} + USING ${dataBaseName}.${superTableName} + TAGS + + #{item.fieldValue} + + + + + + CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} + USING ${dataBaseName}.${superTableName} + + #{item.fieldName} + + TAGS + + #{item.fieldValue} + + + + \ No newline at end of file From 9b30d5d35572dc54646b2c3f3ad2fe04368fcd5d Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 9 Nov 2024 13:39:51 +0800 Subject: [PATCH 011/228] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91IoT=EF=BC=9Atdengine=20=E5=B0=81=E8=A3=85?= =?UTF-8?q?=E7=9A=84=20review?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/device/IotDeviceDataController.java | 2 ++ .../vo/deviceData/IotDeviceDataReqVO.java | 1 + .../dataobject/device/IotDeviceDataDO.java | 1 + .../iot/dal/dataobject/tdengine/SelectDO.java | 4 ++++ .../dataobject/tdengine/SelectVisualDO.java | 1 + .../dal/dataobject/tdengine/TableManager.java | 1 + .../dal/dataobject/tdengine/TdRestApi.java | 1 + .../dal/dataobject/tdengine/TdTableDO.java | 1 + .../iot/dal/mysql/device/IotDeviceMapper.java | 1 + .../IotThinkModelFunctionMapper.java | 5 +++-- .../dal/tdengine/TdEngineDatabaseMapper.java | 1 + .../iot/dal/tdengine/TdEngineQueryMapper.java | 1 + .../iot/emq/service/EmqxServiceImpl.java | 2 ++ .../device/IotDeviceDataServiceImpl.java | 1 + .../service/device/IotDeviceServiceImpl.java | 21 +++++++++---------- .../IotThingModelMessageServiceImpl.java | 13 +++++++++++- .../tdengine/TdEngineDataWriterMapper.xml | 1 - .../tdengine/TdEngineDatabaseMapper.xml | 1 - .../mapper/tdengine/TdEngineQueryMapper.xml | 1 - .../tdengine/TdEngineSuperTableMapper.xml | 1 - .../mapper/tdengine/TdEngineTableMapper.xml | 1 - 21 files changed, 43 insertions(+), 19 deletions(-) diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java index e710d0ea8..ac2ec5cf7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java @@ -31,6 +31,7 @@ public class IotDeviceDataController { @Resource private IotDeviceDataService deviceDataService; + // TODO @haohao:是不是叫 get-latest 就好了。因为 data 已经在 url 里了哈 @GetMapping("/latest-data") @Operation(summary = "获取设备属性最新数据") public CommonResult> getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceDataReqVO) { @@ -38,6 +39,7 @@ public class IotDeviceDataController { return success(BeanUtils.toBean(list, IotDeviceDataRespVO.class)); } + // TODO @haohao:是不是叫 /history-data => page @GetMapping("/history-data") @Operation(summary = "获取设备属性历史数据") public CommonResult> getDevicePropertiesHistoryData(@Valid IotDeviceDataReqVO deviceDataReqVO) { diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java index 5f87a1cb8..21e53aff8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java @@ -10,6 +10,7 @@ import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +// TODO @haohao:IotDeviceDataPageReqVO @Schema(description = "管理后台 - IoT 设备数据 Request VO") @Data public class IotDeviceDataReqVO extends PageParam { diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java index 5d8051172..68370d731 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java @@ -23,6 +23,7 @@ import java.time.LocalDateTime; @AllArgsConstructor public class IotDeviceDataDO { + // TODO @haohao:每个字段的关联关系,可以 @ 下哈。 /** * 设备编号 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java index 503b26310..652c3aee6 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java @@ -3,12 +3,15 @@ package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; import lombok.Data; import java.util.Set; + +// TODO @haohao:类似这个,其实可以参考 mybatis plus,querywrapper,搞个 TdEngineQueryWrapper。这样看起来会更好懂。 /** * 查询DO */ @Data public class SelectDO { + // TODO @haoha:database 是个单词 /** * 数据库名称 */ @@ -39,6 +42,7 @@ public class SelectDO { */ private String type; + // TODO @haohao:这个字段,是啥哈? /** * 查询条件 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java index d5faf45a9..d4c35d66d 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java @@ -4,6 +4,7 @@ import lombok.Data; import java.util.Map; +// TODO @haohao:类似 SelectDO 的想法,只是它是返回。ps:貌似可以在 tdengine 里面,创建一个 query 包,放这种比较特殊的查询和结果对象。dataobject 更多还是实际存储的结构化的 do @Data public class SelectVisualDO { diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java index 65663d805..e11db58e7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; import java.util.List; +// TODO @haohao:这个还有用哇? /** * TableManager 类用于管理 TDengine 表的创建、删除和结构信息获取 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java index 6653ece40..b2d1ac029 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdRestApi.java @@ -7,6 +7,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +// TODO @haohao:有部分非实体的部分,是不是可以搞到 iot 的 framework 包下,搞个 tdengine 包,作为框架级的封装,放在 dataobject,感觉不是很合理哈。【可以微信讨论下】 /** * TdRestApi 类用于处理 TDengine 的 REST API 请求 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdTableDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdTableDO.java index 314c51de3..3b30352e4 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdTableDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TdTableDO.java @@ -21,6 +21,7 @@ public class TdTableDO { */ private String dataBaseName; + // TODO @haohao:superTableName 和 tableName 是不是合并。因为每个 mapper 操作的时候,有且只会使用到其中一个。 /** * 超级表名称 */ 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 3129f400c..4d8315eb3 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 @@ -15,6 +15,7 @@ import org.apache.ibatis.annotations.Mapper; @Mapper public interface IotDeviceMapper extends BaseMapperX { + // TODO @haohao:可能多余的查询条件,要去掉哈 default PageResult selectPage(IotDevicePageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() .eqIfPresent(IotDeviceDO::getDeviceKey, reqVO.getDeviceKey()) diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java index 2883abe4e..c8745aab6 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java @@ -43,7 +43,7 @@ public interface IotThinkModelFunctionMapper extends BaseMapperX selectListByProductIdAndIdentifiersAndTypes(Long productId, List identifiers, - List types){ + List types) { return selectList(new LambdaQueryWrapperX() .eq(IotThinkModelFunctionDO::getProductId, productId) .in(IotThinkModelFunctionDO::getIdentifier, identifiers) @@ -55,7 +55,8 @@ public interface IotThinkModelFunctionMapper extends BaseMapperX selectListByProductKey(String productKey){ + default List selectListByProductKey(String productKey) { return selectList(IotThinkModelFunctionDO::getProductKey, productKey); } + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java index bc562ccca..cd3eaa8b9 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.InterceptorIgnore; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; +// TODO @haohao:InterceptorIgnore 忽略租户,可以在每个方法上,添加 @TenantIgnore 哈。 /** * TD 引擎的数据库 Mapper */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java index e5353f7ee..a2408e335 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java @@ -25,6 +25,7 @@ public interface TdEngineQueryMapper { */ List> selectByTimestamp(SelectDO selectDO); + // TODO @haohao:最好方法的命名,和数据库操作的保持一直。get => select。然后 selectList or selectOne /** * 根据时间戳获取数据条数 * diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java index f338d6249..343f9ba21 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/emq/service/EmqxServiceImpl.java @@ -31,6 +31,7 @@ public class EmqxServiceImpl implements EmqxService { // 根据不同的主题,处理不同的业务逻辑 if (topic.contains("/property/post")) { // 设备上报数据 topic /sys/f13f57c63e9/dianbiao1/thing/event/property/post + // TODO @hao:这块未来可能,搞个 IotTopicUrls 之类?把拼接和解析的逻辑,收敛 String productKey = topic.split("/")[2]; String deviceName = topic.split("/")[3]; String message = new String(mqttMessage.getPayload()); @@ -48,4 +49,5 @@ public class EmqxServiceImpl implements EmqxService { log.error("订阅默认主题失败", e); } } + } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java index 4179075df..8f68989c9 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java @@ -133,4 +133,5 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { private static String getDeviceTableName(String productKey, String deviceName) { return String.format("device_%s_%s", productKey.toLowerCase(), deviceName.toLowerCase()); } + } 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 60743f671..0ec737a30 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 @@ -213,31 +213,30 @@ public class IotDeviceServiceImpl implements IotDeviceService { @Override public void updateDeviceStatus(IotDeviceStatusUpdateReqVO updateReqVO) { - // 校验存在 + // 1. 校验存在 + // TODO @haohao:这里的 iotDeviceDO => device。一个是去掉 iot,一个是去掉 DO 后缀。这样,简洁一点。 IotDeviceDO iotDeviceDO = validateDeviceExists(updateReqVO.getId()); - // 更新状态和更新时间 + // 2.1 更新状态和更新时间 IotDeviceDO updateObj = BeanUtils.toBean(updateReqVO, IotDeviceDO.class); - - // 以前是未激活,现在是上线,设置设备激活时间 + // TODO @haohao:下面几个状态的处理,可以考虑 if else if。这样,看起来会有层次感哈 + // 2.2.1 以前是未激活,现在是上线,设置设备激活时间 + // TODO @haohao:这里可以使用 ObjectUtils.equalsAny 类似这种哈。 if (Objects.equals(iotDeviceDO.getStatus(), IotDeviceStatusEnum.INACTIVE.getStatus()) && Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { updateObj.setActiveTime(LocalDateTime.now()); } - - // 如果是上线,设置上线时间 + // 2.2.2 如果是上线,设置上线时间 if (Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { updateObj.setLastOnlineTime(LocalDateTime.now()); } - - // 如果是离线,设置离线时间 + // 2.2.3 如果是离线,设置离线时间 if (Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.OFFLINE.getStatus())) { updateObj.setLastOfflineTime(LocalDateTime.now()); } - - // 设置状态更新时间 + // 2.3 设置状态更新时间 updateObj.setStatusLastUpdateTime(LocalDateTime.now()); - + // 2.4 更新到数据库 deviceMapper.updateById(updateObj); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java index 69c417839..280b32d9a 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java @@ -47,6 +47,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @Resource private DeviceDataRedisDAO deviceDataRedisDAO; + // TODO @haohao:这个方法,可以考虑加下 1. 2. 3. 更有层次感 @Override @TenantIgnore public void saveThingModelMessage(IotDeviceDO device, ThingModelMessage thingModelMessage) { @@ -55,12 +56,14 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ // 创建设备数据表 createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); // 更新设备状态 + // TODO @haohao:下面可以考虑,链式调用。iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO().setid().setstatus()) IotDeviceStatusUpdateReqVO updateReqVO = new IotDeviceStatusUpdateReqVO(); updateReqVO.setId(device.getId()); updateReqVO.setStatus(IotDeviceStatusEnum.ONLINE.getStatus()); iotDeviceService.updateDeviceStatus(updateReqVO); } + // TODO @haohao:这个变量,可以和 “过滤并收集有效的属性字段” 那块,因为关联度高一点。 // 获取设备属性 Map params = thingModelMessage.dataToMap(); @@ -70,12 +73,12 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ .stream() .filter(function -> IotProductFunctionTypeEnum.PROPERTY.getType().equals(function.getType())) .toList(); - if (functionList.isEmpty()) { return; } // 获取属性标识符集合 + // TODO @haohao:这个变量,可以和 “过滤并收集有效的属性字段” 那块,因为关联度高一点。另外,可以使用 CollectionUtils。convertSet Set propertyIdentifiers = functionList.stream() .map(IotThinkModelFunctionDO::getIdentifier) .collect(Collectors.toSet()); @@ -90,9 +93,11 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ if (propertyIdentifiers.contains(key)) { schemaFieldValues.add(new TdFieldDO(key.toLowerCase(), val)); // 缓存设备属性 + // TODO @haohao:这个缓存的写入,可以使用的时候 cache 么?被动读 setDeviceDataCache(device, functionMap.get(key), val, thingModelMessage.getTime()); } }); + // TODO @haohao:疑问,为什么 1 不继续哈? if (schemaFieldValues.size() == 1) { return; } @@ -127,6 +132,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ deviceDataRedisDAO.set(deviceData); } + // TODO @haohao:实现没问题哈。这个方法的空行有点多,逻辑分块上没这么明显。看看能不能改下。 /** * 创建设备数据表 * @@ -143,6 +149,8 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ List tagsFieldValues = new ArrayList<>(); if (maps != null) { + // TODO @haohao:一些字符串,是不是可以枚举起来哈。 + // TODO @haohao:这种过滤的,常用的,可以考虑用 CollectionUtils.filterList。一些常用的 stream 操作,适合封装哈 List> taggedNotesList = maps.stream() .filter(map -> "TAG".equals(map.get("note"))) .toList(); @@ -176,6 +184,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ * @return 数据库名称 */ private String getDatabaseName() { + // TODO @haohao:可以使用 StrUtil.subAftetLast 这种方法 return url.substring(url.lastIndexOf("/") + 1); } @@ -187,6 +196,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ * @return 产品属性表名 */ private static String getProductPropertySTableName(Integer deviceType, String productKey) { + // TODO @haohao:枚举下,会好点哈。 return switch (deviceType) { case 1 -> String.format("gateway_sub_%s", productKey).toLowerCase(); case 2 -> String.format("gateway_%s", productKey).toLowerCase(); @@ -204,4 +214,5 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ private static String getDeviceTableName(String productKey, String deviceName) { return String.format("device_%s_%s", productKey.toLowerCase(), deviceName.toLowerCase()); } + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml index b5f044614..dd38cd08e 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml @@ -2,7 +2,6 @@ - diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml index 4d9a125db..919c301f7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml @@ -2,7 +2,6 @@ - diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml index 9407b371d..f4361bc67 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml @@ -2,7 +2,6 @@ - diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml index 1ddbe3b97..37cf71910 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml @@ -2,7 +2,6 @@ - diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml index 2d469a390..867ef8f43 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml @@ -2,7 +2,6 @@ - From 89fb71e8573d1f6552d70a699e3a8b1ec8612f02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Sat, 9 Nov 2024 23:44:05 +0800 Subject: [PATCH 012/228] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E3=80=91=20=E4=BC=98=E5=8C=96=20tdengine=20=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E6=95=B0=E6=8D=AE=E5=BA=93=E7=9B=B8=E5=85=B3=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/iot/enums/IotConstants.java | 38 +++++ .../admin/device/IotDeviceDataController.java | 16 +- ...ReqVO.java => IotDeviceDataPageReqVO.java} | 3 +- .../vo/deviceData/IotDeviceDataRespVO.java | 3 - .../dataobject/device/IotDeviceDataDO.java | 20 ++- .../iot/dal/dataobject/tdengine/SelectDO.java | 6 - .../dataobject/tdengine/SelectVisualDO.java | 3 + .../dal/dataobject/tdengine/TableManager.java | 159 ------------------ ...ableMapper.java => TdEngineDDLMapper.java} | 60 +++++-- .../iot/dal/tdengine/TdEngineDMLMapper.java | 103 ++++++++++++ .../tdengine/TdEngineDataWriterMapper.java | 25 --- .../dal/tdengine/TdEngineDatabaseMapper.java | 24 --- .../iot/dal/tdengine/TdEngineQueryMapper.java | 86 ---------- .../iot/dal/tdengine/TdEngineTableMapper.java | 41 ----- .../service/device/IotDeviceDataService.java | 6 +- .../device/IotDeviceDataServiceImpl.java | 22 +-- .../service/device/IotDeviceServiceImpl.java | 45 ++--- .../tdengine/IotSuperTableService.java | 2 +- .../tdengine/IotSuperTableServiceImpl.java | 59 ++++--- .../IotThingModelMessageServiceImpl.java | 130 +++++++------- .../tdengine/TdEngineDataWriterService.java | 19 --- .../TdEngineDataWriterServiceImpl.java | 21 --- .../tdengine/TdEngineDatabaseService.java | 14 -- .../tdengine/TdEngineDatabaseServiceImpl.java | 22 --- .../tdengine/TdEngineQueryService.java | 28 --- .../tdengine/TdEngineQueryServiceImpl.java | 26 --- .../tdengine/TdEngineSuperTableService.java | 123 -------------- .../TdEngineSuperTableServiceImpl.java | 90 ---------- .../tdengine/TdEngineTableService.java | 21 --- .../tdengine/TdEngineTableServiceImpl.java | 23 --- ...rTableMapper.xml => TdEngineDDLMapper.xml} | 34 +++- ...eQueryMapper.xml => TdEngineDMLMapper.xml} | 32 +++- .../tdengine/TdEngineDataWriterMapper.xml | 21 --- .../tdengine/TdEngineDatabaseMapper.xml | 12 -- .../mapper/tdengine/TdEngineTableMapper.xml | 32 ---- 35 files changed, 416 insertions(+), 953 deletions(-) create mode 100644 yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/IotConstants.java rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/{IotDeviceDataReqVO.java => IotDeviceDataPageReqVO.java} (92%) delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/{TdEngineSuperTableMapper.java => TdEngineDDLMapper.java} (68%) create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDMLMapper.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDataWriterMapper.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterService.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseServiceImpl.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryService.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableService.java delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java rename yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/{TdEngineSuperTableMapper.xml => TdEngineDDLMapper.xml} (70%) rename yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/{TdEngineQueryMapper.xml => TdEngineDMLMapper.xml} (68%) delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/IotConstants.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/IotConstants.java new file mode 100644 index 000000000..5927f44b9 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/IotConstants.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.module.iot.enums; + +/** + * Iot 常量 + * + * @author 芋道源码 + */ +public interface IotConstants { + + /** + * 获取设备表名 + * + * 格式为 device_{productKey}_{deviceName} + */ + String DEVICE_TABLE_NAME_FORMAT = "device_%s_%s"; + + /** + * 获取产品属性超级表名 - 网关子设备 + * + * 格式为 gateway_sub_{productKey} + */ + String GATEWAY_SUB_STABLE_NAME_FORMAT = "gateway_sub_%s"; + + /** + * 获取产品属性超级表名 - 网关 + * + * 格式为 gateway_{productKey} + */ + String GATEWAY_STABLE_NAME_FORMAT = "gateway_%s"; + + /** + * 获取产品属性超级表名 - 设备 + * + * 格式为 device_{productKey} + */ + String DEVICE_STABLE_NAME_FORMAT = "device_%s"; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java index ac2ec5cf7..72fdda8c8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.controller.admin.device; import cn.iocoder.yudao.framework.common.pojo.CommonResult; 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.device.vo.deviceData.IotDeviceDataReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataRespVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotTimeDataRespVO; @@ -31,19 +31,17 @@ public class IotDeviceDataController { @Resource private IotDeviceDataService deviceDataService; - // TODO @haohao:是不是叫 get-latest 就好了。因为 data 已经在 url 里了哈 - @GetMapping("/latest-data") + @GetMapping("/latest") @Operation(summary = "获取设备属性最新数据") - public CommonResult> getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceDataReqVO) { - List list = deviceDataService.getDevicePropertiesLatestData(deviceDataReqVO); + public CommonResult> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { + List list = deviceDataService.getLatestDeviceProperties(deviceDataReqVO); return success(BeanUtils.toBean(list, IotDeviceDataRespVO.class)); } - // TODO @haohao:是不是叫 /history-data => page - @GetMapping("/history-data") + @GetMapping("/history") @Operation(summary = "获取设备属性历史数据") - public CommonResult> getDevicePropertiesHistoryData(@Valid IotDeviceDataReqVO deviceDataReqVO) { - PageResult> list = deviceDataService.getDevicePropertiesHistoryData(deviceDataReqVO); + public CommonResult> getHistoryDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { + PageResult> list = deviceDataService.getHistoryDeviceProperties(deviceDataReqVO); return success(BeanUtils.toBean(list, IotTimeDataRespVO.class)); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataPageReqVO.java similarity index 92% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataPageReqVO.java index 21e53aff8..da41299d8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataPageReqVO.java @@ -10,10 +10,9 @@ import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -// TODO @haohao:IotDeviceDataPageReqVO @Schema(description = "管理后台 - IoT 设备数据 Request VO") @Data -public class IotDeviceDataReqVO extends PageParam { +public class IotDeviceDataPageReqVO extends PageParam { @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "177") private Long deviceId; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataRespVO.java index 256bf84fa..ad32fb5f9 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataRespVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataRespVO.java @@ -1,9 +1,6 @@ package cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Builder; import lombok.Data; import java.time.LocalDateTime; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java index 68370d731..892a6b8b7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java @@ -1,15 +1,12 @@ package cn.iocoder.yudao.module.iot.dal.dataobject.device; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; -import com.baomidou.mybatisplus.annotation.TableId; -import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import java.math.BigDecimal; import java.time.LocalDateTime; /** @@ -23,39 +20,52 @@ import java.time.LocalDateTime; @AllArgsConstructor public class IotDeviceDataDO { - // TODO @haohao:每个字段的关联关系,可以 @ 下哈。 /** * 设备编号 + * + * 关联 {@link IotDeviceDO#getId()} */ private Long deviceId; /** * 物模型编号 + * + * 关联 {@link IotThinkModelFunctionDO#getId()} */ private Long thinkModelFunctionId; /** * 产品标识 + * + * 关联 {@link IotProductDO#getProductKey()} */ private String productKey; /** * 设备名称 + * + * 冗余 {@link IotDeviceDO#getDeviceName()} */ private String deviceName; /** * 属性标识符 + * + * 关联 {@link IotThinkModelFunctionDO#getIdentifier()} */ private String identifier; /** * 属性名称 + * + * 关联 {@link IotThinkModelFunctionDO#getName()} */ private String name; /** * 数据类型 + * + * 关联 {@link IotThinkModelFunctionDO#getProperty()#getDataType()} */ private String dataType; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java index 652c3aee6..542dd1e7b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java @@ -42,12 +42,6 @@ public class SelectDO { */ private String type; - // TODO @haohao:这个字段,是啥哈? - /** - * 查询条件 - */ - private Set orgIds; - /** * 设备ID */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java index d4c35d66d..44acc3ac5 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java @@ -27,14 +27,17 @@ public class SelectVisualDO { * 查询类型,0历史数据,1实时数据,2聚合数据 */ private int type; + /** * 查询的数据量 */ private int num; + /** * 聚合函数 */ private String aggregate; + /** * 统计间隔数字+s/m/h/d * 比如1s,1m,1h,1d代表1秒,1分钟,1小时,1天 diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java deleted file mode 100644 index e11db58e7..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java +++ /dev/null @@ -1,159 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; - -import java.util.List; - -// TODO @haohao:这个还有用哇? -/** - * TableManager 类用于管理 TDengine 表的创建、删除和结构信息获取 - */ -public class TableManager { - - /** - * 创建超级表模板(含存在判断) - */ - private static final String CREATE_STABLE_INE_TPL = "CREATE STABLE IF NOT EXISTS %s (%s) TAGS (%s);"; - - /** - * 删除超级表 - */ - private static final String DROP_STABLE_TPL = "DROP STABLE IF EXISTS %s;"; - - /** - * 获取表的结构信息 - */ - private static final String DESC_TB_TPL = "DESCRIBE %s;"; - - /** - * 超级表增加列 - */ - private static final String ALTER_STABLE_ADD_COL_TPL = "ALTER STABLE %s ADD COLUMN %s;"; - - /** - * 超级表修改列 - */ - private static final String ALTER_STABLE_MODIFY_COL_TPL = "ALTER STABLE %s MODIFY COLUMN %s;"; - - /** - * 超级表删除列 - */ - private static final String ALTER_STABLE_DROP_COL_TPL = "ALTER STABLE %s DROP COLUMN %s;"; - - /** - * 创建普通表模板(含存在判断) - */ - private static final String CREATE_CTABLE_INE_TPL = "CREATE TABLE IF NOT EXISTS %s (%s)"; - - /** - * 获取创建表sql - */ - public static String getCreateSTableSql(String tbName, List fields, TdFieldDO... tags) { - if (fields.isEmpty()) { - return null; - } - - // 生成字段片段 - StringBuilder sbField = new StringBuilder("time TIMESTAMP,"); - - for (TdFieldDO field : fields) { - sbField.append(FieldParser.getFieldDefine(field)); - sbField.append(","); - } - sbField.deleteCharAt(sbField.length() - 1); - - String fieldFrag = sbField.toString(); - - // 生成tag - StringBuilder sbTag = new StringBuilder(); - for (TdFieldDO tag : tags) { - sbTag.append(FieldParser.getFieldDefine(tag)) - .append(","); - } - sbTag.deleteCharAt(sbTag.length() - 1); - - return String.format(CREATE_STABLE_INE_TPL, tbName, fieldFrag, sbTag); - - } - - /** - * 获取创建普通表sql - */ - public static String getCreateCTableSql(String tbName, List fields) { - if (fields.size() == 0) { - return null; - } - - //生成字段片段 - StringBuilder sbField = new StringBuilder("time timestamp,"); - - for (TdFieldDO field : fields) { - sbField.append(FieldParser.getFieldDefine(field)); - sbField.append(","); - } - sbField.deleteCharAt(sbField.length() - 1); - - String fieldFrag = sbField.toString(); - - return String.format(CREATE_CTABLE_INE_TPL, tbName, fieldFrag); - - } - - - /** - * 取正确的表名 - * - * @param name 表象 - */ - public static String rightTbName(String name) { - return name.toLowerCase().replace("-" , "_"); - } - - /** - * 获取表详情的sql - */ - public static String getDescTableSql(String tbName) { - return String.format(DESC_TB_TPL, tbName); - } - - /** - * 获取添加字段sql - */ - public static String getAddSTableColumnSql(String tbName, List fields) { - StringBuilder sbAdd = new StringBuilder(); - for (TdFieldDO field : fields) { - sbAdd.append(String.format(ALTER_STABLE_ADD_COL_TPL, - tbName, - FieldParser.getFieldDefine(field) - )); - } - return sbAdd.toString(); - } - - /** - * 获取修改字段sql - */ - public static String getModifySTableColumnSql(String tbName, List fields) { - StringBuilder sbModify = new StringBuilder(); - for (TdFieldDO field : fields) { - sbModify.append(String.format(ALTER_STABLE_MODIFY_COL_TPL, - tbName, - FieldParser.getFieldDefine(field) - )); - } - return sbModify.toString(); - } - - /** - * 获取删除字段sql - */ - public static String getDropSTableColumnSql(String tbName, List fields) { - StringBuilder sbDrop = new StringBuilder(); - for (TdFieldDO field : fields) { - sbDrop.append(String.format(ALTER_STABLE_DROP_COL_TPL, - tbName, - field.getFieldName() - )); - } - return sbDrop.toString(); - } - -} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineSuperTableMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java similarity index 68% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineSuperTableMapper.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java index e688563d5..640255940 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineSuperTableMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java @@ -1,19 +1,30 @@ package cn.iocoder.yudao.module.iot.dal.tdengine; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.mybatisplus.annotation.InterceptorIgnore; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; import java.util.List; import java.util.Map; /** - * TD 引擎的超级表 Mapper + * 专门处理 DDL(数据定义语言)操作,包含所有的数据库和表的定义操作,例如创建数据库、创建超级表、创建子表等 */ @Mapper @DS("tdengine") -public interface TdEngineSuperTableMapper { +public interface TdEngineDDLMapper { + + /** + * 创建数据库 + * SQL:CREATE DATABASE [IF NOT EXISTS] db_name [database_options]; + * + * @param dataBaseName 数据库名称 + */ + @TenantIgnore + void createDatabase(@Param("dataBaseName") String dataBaseName); /** * 创建超级表 @@ -25,7 +36,7 @@ public interface TdEngineSuperTableMapper { * columns 列信息 * tags 标签信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void createSuperTable(TdTableDO superTable); /** @@ -36,7 +47,7 @@ public interface TdEngineSuperTableMapper { * dataBaseName 数据库名称 * superTableName 超级表名称 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore List> showSuperTables(TdTableDO superTable); /** @@ -47,7 +58,7 @@ public interface TdEngineSuperTableMapper { * dataBaseName 数据库名称 * superTableName 超级表名称 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore List> describeSuperTable(TdTableDO superTable); /** @@ -59,7 +70,7 @@ public interface TdEngineSuperTableMapper { * superTableName 超级表名称 * column 列信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void addColumnForSuperTable(TdTableDO superTable); /** @@ -71,7 +82,7 @@ public interface TdEngineSuperTableMapper { * superTableName 超级表名称 * column 列信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void dropColumnForSuperTable(TdTableDO superTable); /** @@ -83,7 +94,7 @@ public interface TdEngineSuperTableMapper { * superTableName 超级表名称 * column 列信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void modifyColumnWidthForSuperTable(TdTableDO superTable); @@ -95,7 +106,7 @@ public interface TdEngineSuperTableMapper { * superTableName 超级表名称 * tag 标签信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void addTagForSuperTable(TdTableDO superTable); /** @@ -106,6 +117,33 @@ public interface TdEngineSuperTableMapper { * superTableName 超级表名称 * tag 标签信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void dropTagForSuperTable(TdTableDO superTable); -} \ No newline at end of file + + /** + * 创建子表 - 创建子表 + * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name TAGS (tag_value1, ...); + * + * @param table 表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tableName 子表名称 + * tags TAG 字段 + */ + @TenantIgnore + void createTable(TdTableDO table); + + /** + * 创建子表 - 创建子表并指定标签的值 + * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name (tag_name1, ...) TAGS (tag_value1, ...); + * + * @param table 表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tableName 子表名称 + * tags TAG 字段 + */ + @TenantIgnore + void createTableWithTags(TdTableDO table); + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDMLMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDMLMapper.java new file mode 100644 index 000000000..12b2c232c --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDMLMapper.java @@ -0,0 +1,103 @@ +package cn.iocoder.yudao.module.iot.dal.tdengine; + +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TagsSelectDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; +import com.baomidou.dynamic.datasource.annotation.DS; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; +import java.util.Map; + +/** + * 专门处理 TD Engine 的 DML(数据操作语言)操作,处理所有的数据查询和写入操作,如插入数据、查询数据等 + */ +@Mapper +@DS("tdengine") +public interface TdEngineDMLMapper { + + /** + * 插入数据 - 指定列插入数据 + * + * @param table 数据 + * dataBaseName 数据库名 + * tableName 表名 + * columns 列 + */ + @TenantIgnore + void insertData(TdTableDO table); + + /** + * 根据时间戳查询数据 + * + * @param selectDO 查询条件 + * @return 查询结果列表 + */ + @TenantIgnore + List> selectByTimestamp(SelectDO selectDO); + + /** + * 根据时间戳获取数据条数 + * + * @param selectDO 查询条件 + * @return 数据条数 + */ + @TenantIgnore + Map selectCountByTimestamp(SelectDO selectDO); + + /** + * 获取最新数据 + * + * @param selectDO 查询条件 + * @return 最新数据 + */ + @TenantIgnore + Map selectOneLastData(SelectDO selectDO); + + /** + * 获取历史数据列表 + * + * @param selectVisualDO 查询条件 + * @return 历史数据列表 + */ + @TenantIgnore + List> selectHistoryDataList(SelectVisualDO selectVisualDO); + + /** + * 获取实时数据列表 + * + * @param selectVisualDO 查询条件 + * @return 实时数据列表 + */ + @TenantIgnore + List> selectRealtimeDataList(SelectVisualDO selectVisualDO); + + /** + * 获取聚合数据列表 + * + * @param selectVisualDO 查询条件 + * @return 聚合数据列表 + */ + @TenantIgnore + List> selectAggregateDataList(SelectVisualDO selectVisualDO); + + /** + * 根据标签获取最新数据列表 + * + * @param tagsSelectDO 查询条件 + * @return 最新数据列表 + */ + @TenantIgnore + List> selectLastDataListByTags(TagsSelectDO tagsSelectDO); + + /** + * 获取历史数据条数 + * + * @param selectVisualDO 查询条件 + * @return 数据条数 + */ + @TenantIgnore + Long selectHistoryCount(SelectVisualDO selectVisualDO); +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDataWriterMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDataWriterMapper.java deleted file mode 100644 index 51f4229a0..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDataWriterMapper.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.apache.ibatis.annotations.Mapper; - -/** - * TD 引擎的数据写入 Mapper - */ -@Mapper -@DS("tdengine") -public interface TdEngineDataWriterMapper { - - /** - * 插入数据 - 指定列插入数据 - * - * @param table 数据 - * dataBaseName 数据库名 - * tableName 表名 - * columns 列 - */ - @InterceptorIgnore(tenantLine = "true") - void insertData(TdTableDO table); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java deleted file mode 100644 index cd3eaa8b9..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.tdengine; - -import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -// TODO @haohao:InterceptorIgnore 忽略租户,可以在每个方法上,添加 @TenantIgnore 哈。 -/** - * TD 引擎的数据库 Mapper - */ -@Mapper -@DS("tdengine") -public interface TdEngineDatabaseMapper { - - /** - * 创建数据库 - * SQL:CREATE DATABASE [IF NOT EXISTS] db_name [database_options]; - * - * @param dataBaseName 数据库名称 - */ - @InterceptorIgnore(tenantLine = "true") - void createDatabase(@Param("dataBaseName") String dataBaseName); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java deleted file mode 100644 index a2408e335..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java +++ /dev/null @@ -1,86 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TagsSelectDO; -import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; -import java.util.Map; - -/** - * TD 引擎的查询 Mapper - */ -@Mapper -@DS("tdengine") -public interface TdEngineQueryMapper { - - /** - * 根据时间戳查询数据 - * - * @param selectDO 查询条件 - * @return 查询结果 - */ - List> selectByTimestamp(SelectDO selectDO); - - // TODO @haohao:最好方法的命名,和数据库操作的保持一直。get => select。然后 selectList or selectOne - /** - * 根据时间戳获取数据条数 - * - * @param selectDO 查询条件 - * @return 数据条数 - */ - Map getCountByTimestamp(SelectDO selectDO); - - /** - * 获取最新数据 - * - * @param selectDO 查询条件 - * @return 最新数据 - */ - Map getLastData(SelectDO selectDO); - - /** - * 获取历史数据 - * - * @param selectVisualDO 查询条件 - * @return 历史数据列表 - */ - @InterceptorIgnore(tenantLine = "true") - List> getHistoryData(SelectVisualDO selectVisualDO); - - /** - * 获取实时数据 - * - * @param selectVisualDO 查询条件 - * @return 实时数据列表 - */ - List> getRealtimeData(SelectVisualDO selectVisualDO); - - /** - * 获取聚合数据 - * - * @param selectVisualDO 查询条件 - * @return 聚合数据列表 - */ - List> getAggregateData(SelectVisualDO selectVisualDO); - - /** - * 根据标签获取最新数据 - * - * @param tagsSelectDO 查询条件 - * @return 最新数据列表 - */ - List> getLastDataByTags(TagsSelectDO tagsSelectDO); - - /** - * 获取历史数据条数 - * - * @param selectVisualDO 查询条件 - * @return 数据条数 - */ - @InterceptorIgnore(tenantLine = "true") - Long getHistoryCount(SelectVisualDO selectVisualDO); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java deleted file mode 100644 index 72517bcab..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.apache.ibatis.annotations.Mapper; - -/** - * TD 引擎的表 Mapper - */ -@Mapper -@DS("tdengine") -public interface TdEngineTableMapper { - - /** - * 创建子表 - 创建子表 - * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name TAGS (tag_value1, ...); - * - * @param table 表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * tableName 子表名称 - * tags TAG 字段 - */ - @InterceptorIgnore(tenantLine = "true") - void createTable(TdTableDO table); - - /** - * 创建子表 - 创建子表并指定标签的值 - * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name (tag_name1, ...) TAGS (tag_value1, ...); - * - * @param table 表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * tableName 子表名称 - * tags TAG 字段 - */ - @InterceptorIgnore(tenantLine = "true") - void createTableWithTags(TdTableDO table); - -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java index 96181fd26..4f390ca3b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java @@ -1,7 +1,7 @@ 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.deviceData.IotDeviceDataReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import jakarta.validation.Valid; @@ -31,7 +31,7 @@ public interface IotDeviceDataService { * @param deviceId 设备编号 * @return 设备属性最新数据 */ - List getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceId); + List getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceId); /** * 获得设备属性历史数据 @@ -39,5 +39,5 @@ public interface IotDeviceDataService { * @param deviceDataReqVO 设备属性历史数据 Request VO * @return 设备属性历史数据 */ - PageResult> getDevicePropertiesHistoryData(@Valid IotDeviceDataReqVO deviceDataReqVO); + PageResult> getHistoryDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO); } \ 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/IotDeviceDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java index 8f68989c9..7d10977f9 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java @@ -1,18 +1,20 @@ package cn.iocoder.yudao.module.iot.service.device; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONObject; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper; +import cn.iocoder.yudao.module.iot.enums.IotConstants; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import cn.iocoder.yudao.module.iot.service.tdengine.IotThingModelMessageService; -import cn.iocoder.yudao.module.iot.service.tdengine.TdEngineQueryService; import cn.iocoder.yudao.module.iot.service.thinkmodelfunction.IotThinkModelFunctionService; import jakarta.annotation.Resource; import jakarta.validation.Valid; @@ -40,7 +42,7 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { @Resource private IotThinkModelFunctionService thinkModelFunctionService; @Resource - private TdEngineQueryService tdEngineQueryService; + private TdEngineDMLMapper tdEngineDMLMapper; @Resource private DeviceDataRedisDAO deviceDataRedisDAO; @@ -66,7 +68,7 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { } @Override - public List getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceDataReqVO) { + public List getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { List list = new ArrayList<>(); // 1. 获取设备信息 IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId()); @@ -106,7 +108,7 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { } @Override - public PageResult> getDevicePropertiesHistoryData(IotDeviceDataReqVO deviceDataReqVO) { + public PageResult> getHistoryDeviceProperties(IotDeviceDataPageReqVO deviceDataReqVO) { PageResult> pageResult = new PageResult<>(); // 1. 获取设备信息 IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId()); @@ -121,17 +123,17 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { params.put("rows", deviceDataReqVO.getPageSize()); params.put("page", (deviceDataReqVO.getPageNo() - 1) * deviceDataReqVO.getPageSize()); selectVisualDO.setParams(params); - pageResult.setList(tdEngineQueryService.getHistoryData(selectVisualDO)); - pageResult.setTotal(tdEngineQueryService.getHistoryCount(selectVisualDO)); + pageResult.setList(tdEngineDMLMapper.selectHistoryDataList(selectVisualDO)); + pageResult.setTotal(tdEngineDMLMapper.selectHistoryCount(selectVisualDO)); return pageResult; } private String getDatabaseName() { - return url.substring(url.lastIndexOf("/") + 1); + return StrUtil.subAfter(url, "/", true); } private static String getDeviceTableName(String productKey, String deviceName) { - return String.format("device_%s_%s", productKey.toLowerCase(), deviceName.toLowerCase()); + return String.format(IotConstants.DEVICE_TABLE_NAME_FORMAT, productKey, deviceName); } -} +} \ 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/IotDeviceServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java index 0ec737a30..58918c130 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 @@ -19,7 +19,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import java.security.SecureRandom; import java.time.LocalDateTime; +import java.util.Base64; import java.util.Objects; import java.util.UUID; @@ -137,10 +139,13 @@ public class IotDeviceServiceImpl implements IotDeviceService { * @return 生成的 MQTT Password */ private String generateMqttPassword() { - // TODO @haohao:【后续优化】在实际应用中,建议使用更安全的方法生成 MQTT Password,如加密或哈希 - return UUID.randomUUID().toString(); + SecureRandom secureRandom = new SecureRandom(); + byte[] passwordBytes = new byte[32]; // 256 位的随机数 + secureRandom.nextBytes(passwordBytes); + return Base64.getUrlEncoder().withoutPadding().encodeToString(passwordBytes); } + /** * 生成唯一的 DeviceName * @@ -214,30 +219,28 @@ public class IotDeviceServiceImpl implements IotDeviceService { @Override public void updateDeviceStatus(IotDeviceStatusUpdateReqVO updateReqVO) { // 1. 校验存在 - // TODO @haohao:这里的 iotDeviceDO => device。一个是去掉 iot,一个是去掉 DO 后缀。这样,简洁一点。 - IotDeviceDO iotDeviceDO = validateDeviceExists(updateReqVO.getId()); + IotDeviceDO device = validateDeviceExists(updateReqVO.getId()); // 2.1 更新状态和更新时间 - IotDeviceDO updateObj = BeanUtils.toBean(updateReqVO, IotDeviceDO.class); - // TODO @haohao:下面几个状态的处理,可以考虑 if else if。这样,看起来会有层次感哈 - // 2.2.1 以前是未激活,现在是上线,设置设备激活时间 - // TODO @haohao:这里可以使用 ObjectUtils.equalsAny 类似这种哈。 - if (Objects.equals(iotDeviceDO.getStatus(), IotDeviceStatusEnum.INACTIVE.getStatus()) - && Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { - updateObj.setActiveTime(LocalDateTime.now()); - } - // 2.2.2 如果是上线,设置上线时间 - if (Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { - updateObj.setLastOnlineTime(LocalDateTime.now()); - } - // 2.2.3 如果是离线,设置离线时间 - if (Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.OFFLINE.getStatus())) { - updateObj.setLastOfflineTime(LocalDateTime.now()); + IotDeviceDO updateDevice = BeanUtils.toBean(updateReqVO, IotDeviceDO.class); + // 2.2 更新状态相关时间 + if (Objects.equals(device.getStatus(), IotDeviceStatusEnum.INACTIVE.getStatus()) + && Objects.equals(updateDevice.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { + // 从未激活到在线,设置激活时间和最后上线时间 + updateDevice.setActiveTime(LocalDateTime.now()); + updateDevice.setLastOnlineTime(LocalDateTime.now()); + } else if (Objects.equals(updateDevice.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { + // 如果是上线,设置最后上线时间 + updateDevice.setLastOnlineTime(LocalDateTime.now()); + } else if (Objects.equals(updateDevice.getStatus(), IotDeviceStatusEnum.OFFLINE.getStatus())) { + // 如果是离线,设置最后离线时间 + updateDevice.setLastOfflineTime(LocalDateTime.now()); } + // 2.3 设置状态更新时间 - updateObj.setStatusLastUpdateTime(LocalDateTime.now()); + updateDevice.setStatusLastUpdateTime(LocalDateTime.now()); // 2.4 更新到数据库 - deviceMapper.updateById(updateObj); + deviceMapper.updateById(updateDevice); } @Override diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java index 7c88b83aa..8aec32f32 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java @@ -15,4 +15,4 @@ public interface IotSuperTableService { * 创建超级表数据模型 */ void createSuperTableDataModel(IotProductDO product, List functionList); -} +} \ 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/tdengine/IotSuperTableServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableServiceImpl.java index 3be324c4e..20989181e 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableServiceImpl.java @@ -9,6 +9,8 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -26,7 +28,7 @@ import java.util.stream.Collectors; public class IotSuperTableServiceImpl implements IotSuperTableService { @Resource - private TdEngineSuperTableService tdEngineSuperTableService; + private TdEngineDDLMapper tdEngineDDLMapper; @Value("${spring.datasource.dynamic.datasource.tdengine.url}") private String url; @@ -42,9 +44,10 @@ public class IotSuperTableServiceImpl implements IotSuperTableService { String superTableName = getSuperTableName(product.getDeviceType(), product.getProductKey()); String databaseName = getDatabaseName(); - Integer tableExists = tdEngineSuperTableService.checkSuperTableExists(new TdTableDO(databaseName, superTableName)); - if (tableExists != null && tableExists > 0) { + List> results = tdEngineDDLMapper.showSuperTables(new TdTableDO(databaseName, superTableName)); + int tableExists = results == null || results.isEmpty() ? 0 : results.size(); + if (tableExists > 0) { updateSuperTable(thingModel, product.getDeviceType()); } else { createSuperTable(thingModel, product.getDeviceType()); @@ -76,7 +79,7 @@ public class IotSuperTableServiceImpl implements IotSuperTableService { String databaseName = getDatabaseName(); // 创建超级表 - tdEngineSuperTableService.createSuperTable(new TdTableDO(databaseName, superTableName, schemaFields, tagsFields)); + tdEngineDDLMapper.createSuperTable(new TdTableDO(databaseName, superTableName, schemaFields, tagsFields)); } /** @@ -98,7 +101,7 @@ public class IotSuperTableServiceImpl implements IotSuperTableService { * 获取表的字段信息 */ private List getTableFields(String tableName) { - List> tableDescription = tdEngineSuperTableService.describeSuperTable(new TdTableDO(getDatabaseName(), tableName)); + List> tableDescription = tdEngineDDLMapper.describeSuperTable(new TdTableDO(getDatabaseName(), tableName)); if (CollUtil.isEmpty(tableDescription)) { return Collections.emptyList(); } @@ -127,32 +130,38 @@ public class IotSuperTableServiceImpl implements IotSuperTableService { // 添加新增字段 if (CollUtil.isNotEmpty(addFields)) { - tdEngineSuperTableService.addColumnsForSuperTable(TdTableDO.builder() - .dataBaseName(databaseName) - .superTableName(tableName) - .columns(addFields) - .build()); + for (TdFieldDO addField : addFields) { + tdEngineDDLMapper.addColumnForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .column(addField) + .build()); + } } // 删除旧字段 if (CollUtil.isNotEmpty(dropFields)) { - tdEngineSuperTableService.dropColumnsForSuperTable(TdTableDO.builder() - .dataBaseName(databaseName) - .superTableName(tableName) - .columns(dropFields) - .build()); + for (TdFieldDO dropField : dropFields) { + tdEngineDDLMapper.dropColumnForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .column(dropField) + .build()); + } } // 修改字段(先删除再添加) if (CollUtil.isNotEmpty(modifyFields)) { - tdEngineSuperTableService.dropColumnsForSuperTable(TdTableDO.builder() - .dataBaseName(databaseName) - .superTableName(tableName) - .columns(modifyFields) - .build()); - tdEngineSuperTableService.addColumnsForSuperTable(TdTableDO.builder() - .dataBaseName(databaseName) - .superTableName(tableName) - .columns(addFields) - .build()); + for (TdFieldDO modifyField : modifyFields) { + tdEngineDDLMapper.dropColumnForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .column(modifyField) + .build()); + tdEngineDDLMapper.addColumnForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .column(modifyField) + .build()); + } } } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java index 280b32d9a..92a30ebb0 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.iot.service.tdengine; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceStatusUpdateReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; @@ -11,6 +13,9 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper; +import cn.iocoder.yudao.module.iot.enums.IotConstants; import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; @@ -30,6 +35,14 @@ import java.util.stream.Collectors; @Service public class IotThingModelMessageServiceImpl implements IotThingModelMessageService { + private static final String TAG_NOTE = "TAG"; + private static final String NOTE = "note"; + private static final String TIME = "time"; + private static final String DEVICE_KEY = "device_key"; + private static final String DEVICE_NAME = "device_name"; + private static final String PRODUCT_KEY = "product_key"; + private static final String DEVICE_TYPE = "device_type"; + @Value("${spring.datasource.dynamic.datasource.tdengine.url}") private String url; @@ -38,11 +51,9 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @Resource private IotDeviceService iotDeviceService; @Resource - private TdEngineTableService tdEngineTableService; + private TdEngineDDLMapper tdEngineDDLMapper; @Resource - private TdEngineSuperTableService tdEngineSuperTableService; - @Resource - private TdEngineDataWriterService tdEngineDataWriterService; + private TdEngineDMLMapper tdEngineDMLMapper; @Resource private DeviceDataRedisDAO deviceDataRedisDAO; @@ -51,62 +62,64 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @Override @TenantIgnore public void saveThingModelMessage(IotDeviceDO device, ThingModelMessage thingModelMessage) { - // 判断设备状态,如果为未激活状态,创建数据表 + // 1. 判断设备状态,如果为未激活状态,创建数据表并更新设备状态 if (IotDeviceStatusEnum.INACTIVE.getStatus().equals(device.getStatus())) { - // 创建设备数据表 createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); - // 更新设备状态 - // TODO @haohao:下面可以考虑,链式调用。iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO().setid().setstatus()) - IotDeviceStatusUpdateReqVO updateReqVO = new IotDeviceStatusUpdateReqVO(); - updateReqVO.setId(device.getId()); - updateReqVO.setStatus(IotDeviceStatusEnum.ONLINE.getStatus()); - iotDeviceService.updateDeviceStatus(updateReqVO); + iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO() + .setId(device.getId()) + .setStatus(IotDeviceStatusEnum.ONLINE.getStatus())); } - // TODO @haohao:这个变量,可以和 “过滤并收集有效的属性字段” 那块,因为关联度高一点。 - // 获取设备属性 + // 2. 获取设备属性并进行物模型校验,过滤非物模型属性 Map params = thingModelMessage.dataToMap(); - - // 物模型校验,过滤非物模型属性 - List functionList = iotThinkModelFunctionService - .getThinkModelFunctionListByProductKey(thingModelMessage.getProductKey()) - .stream() - .filter(function -> IotProductFunctionTypeEnum.PROPERTY.getType().equals(function.getType())) - .toList(); + List functionList = getValidFunctionList(thingModelMessage.getProductKey()); if (functionList.isEmpty()) { return; } - // 获取属性标识符集合 - // TODO @haohao:这个变量,可以和 “过滤并收集有效的属性字段” 那块,因为关联度高一点。另外,可以使用 CollectionUtils。convertSet - Set propertyIdentifiers = functionList.stream() - .map(IotThinkModelFunctionDO::getIdentifier) - .collect(Collectors.toSet()); + // 3. 过滤并收集有效的属性字段,缓存设备属性 + List schemaFieldValues = filterAndCollectValidFields(params, functionList, device, thingModelMessage.getTime()); + if (schemaFieldValues.size() == 1) { // 仅有时间字段,无需保存 + return; + } + + // 4. 构建并保存设备属性数据 + tdEngineDMLMapper.insertData(TdTableDO.builder() + .dataBaseName(getDatabaseName()) + .tableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())) + .columns(schemaFieldValues) + .build()); + } + + private List getValidFunctionList(String productKey) { + return iotThinkModelFunctionService + .getThinkModelFunctionListByProductKey(productKey) + .stream() + .filter(function -> IotProductFunctionTypeEnum.PROPERTY.getType().equals(function.getType())) + .toList(); + } + + private List filterAndCollectValidFields(Map params, List functionList, IotDeviceDO device, Long time) { + // 1. 获取属性标识符集合 + Set propertyIdentifiers = CollectionUtils.convertSet(functionList, IotThinkModelFunctionDO::getIdentifier); + + // 2. 构建属性标识符和属性的映射 Map functionMap = functionList.stream() .collect(Collectors.toMap(IotThinkModelFunctionDO::getIdentifier, function -> function)); - // 过滤并收集有效的属性字段 + // 3. 过滤并收集有效的属性字段 List schemaFieldValues = new ArrayList<>(); - schemaFieldValues.add(new TdFieldDO("time", thingModelMessage.getTime())); + schemaFieldValues.add(new TdFieldDO(TIME, time)); params.forEach((key, val) -> { if (propertyIdentifiers.contains(key)) { schemaFieldValues.add(new TdFieldDO(key.toLowerCase(), val)); // 缓存设备属性 // TODO @haohao:这个缓存的写入,可以使用的时候 cache 么?被动读 - setDeviceDataCache(device, functionMap.get(key), val, thingModelMessage.getTime()); + setDeviceDataCache(device, functionMap.get(key), val, time); } }); - // TODO @haohao:疑问,为什么 1 不继续哈? - if (schemaFieldValues.size() == 1) { - return; - } - - // 构建并保存设备属性数据 - tdEngineDataWriterService.insertData(TdTableDO.builder().build() - .setDataBaseName(getDatabaseName()) - .setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())) - .setColumns(schemaFieldValues)); + return schemaFieldValues; } /** @@ -132,7 +145,6 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ deviceDataRedisDAO.set(deviceData); } - // TODO @haohao:实现没问题哈。这个方法的空行有点多,逻辑分块上没这么明显。看看能不能改下。 /** * 创建设备数据表 * @@ -142,36 +154,37 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ * @param deviceKey 设备 Key */ private void createDeviceTable(Integer deviceType, String productKey, String deviceName, String deviceKey) { + // 1. 获取超级表名和数据库名 String superTableName = getProductPropertySTableName(deviceType, productKey); String dataBaseName = getDatabaseName(); - List> maps = tdEngineSuperTableService.describeSuperTable(new TdTableDO(dataBaseName, superTableName)); + // 2. 获取超级表的结构信息 + List> maps = tdEngineDDLMapper.describeSuperTable(new TdTableDO(dataBaseName, superTableName)); List tagsFieldValues = new ArrayList<>(); - if (maps != null) { - // TODO @haohao:一些字符串,是不是可以枚举起来哈。 - // TODO @haohao:这种过滤的,常用的,可以考虑用 CollectionUtils.filterList。一些常用的 stream 操作,适合封装哈 - List> taggedNotesList = maps.stream() - .filter(map -> "TAG".equals(map.get("note"))) - .toList(); + // 2.1 过滤出 TAG 类型的字段 + List> taggedNotesList = CollectionUtils.filterList(maps, map -> TAG_NOTE.equals(map.get(NOTE))); + + // 2.2 解析字段信息 tagsFieldValues = FieldParser.parse(taggedNotesList.stream() .map(map -> List.of(map.get("field"), map.get("type"), map.get("length"))) .collect(Collectors.toList())); + // 2.3 设置 TAG 字段的值 for (TdFieldDO tagsFieldValue : tagsFieldValues) { switch (tagsFieldValue.getFieldName()) { - case "product_key" -> tagsFieldValue.setFieldValue(productKey); - case "device_key" -> tagsFieldValue.setFieldValue(deviceKey); - case "device_name" -> tagsFieldValue.setFieldValue(deviceName); - case "device_type" -> tagsFieldValue.setFieldValue(deviceType); + case PRODUCT_KEY -> tagsFieldValue.setFieldValue(productKey); + case DEVICE_KEY -> tagsFieldValue.setFieldValue(deviceKey); + case DEVICE_NAME -> tagsFieldValue.setFieldValue(deviceName); + case DEVICE_TYPE -> tagsFieldValue.setFieldValue(deviceType); } } } - // 创建设备数据表 + // 3. 创建设备数据表 String tableName = getDeviceTableName(productKey, deviceName); - tdEngineTableService.createTable(TdTableDO.builder().build() + tdEngineDDLMapper.createTable(TdTableDO.builder().build() .setDataBaseName(dataBaseName) .setSuperTableName(superTableName) .setTableName(tableName) @@ -184,8 +197,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ * @return 数据库名称 */ private String getDatabaseName() { - // TODO @haohao:可以使用 StrUtil.subAftetLast 这种方法 - return url.substring(url.lastIndexOf("/") + 1); + return StrUtil.subAfter(url, "/", true); } /** @@ -198,9 +210,9 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ private static String getProductPropertySTableName(Integer deviceType, String productKey) { // TODO @haohao:枚举下,会好点哈。 return switch (deviceType) { - case 1 -> String.format("gateway_sub_%s", productKey).toLowerCase(); - case 2 -> String.format("gateway_%s", productKey).toLowerCase(); - default -> String.format("device_%s", productKey).toLowerCase(); + case 1 -> String.format(IotConstants.GATEWAY_SUB_STABLE_NAME_FORMAT, productKey).toLowerCase(); + case 2 -> String.format(IotConstants.GATEWAY_STABLE_NAME_FORMAT, productKey).toLowerCase(); + default -> String.format(IotConstants.DEVICE_STABLE_NAME_FORMAT, productKey).toLowerCase(); }; } @@ -212,7 +224,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ * @return 设备表名 */ private static String getDeviceTableName(String productKey, String deviceName) { - return String.format("device_%s_%s", productKey.toLowerCase(), deviceName.toLowerCase()); + return String.format(IotConstants.DEVICE_TABLE_NAME_FORMAT, productKey.toLowerCase(), deviceName.toLowerCase()); } } \ 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/tdengine/TdEngineDataWriterService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterService.java deleted file mode 100644 index 0995b0797..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterService.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; - -/** - * TD 引擎的数据写入 Service 接口 - */ -public interface TdEngineDataWriterService { - - /** - * 插入数据 - 指定列插入数据 - * - * @param table 数据 - * dataBaseName 数据库名 - * tableName 表名 - * columns 列 - */ - void insertData(TdTableDO table); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java deleted file mode 100644 index f4dd2c8fd..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDataWriterMapper; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Service; - -/** - * TD 引擎的数据写入 Service 实现类 - */ -@Service -public class TdEngineDataWriterServiceImpl implements TdEngineDataWriterService { - - @Resource - private TdEngineDataWriterMapper tdEngineDataWriterMapper; - - @Override - public void insertData(TdTableDO table) { - tdEngineDataWriterMapper.insertData(table); - } -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java deleted file mode 100644 index d895262cc..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -/** - * TD 引擎的数据库 Service 接口 - */ -public interface TdEngineDatabaseService { - - /** - * 创建数据库 - * - * @param dataBaseName 数据库名称 - */ - void createDatabase(String dataBaseName); -} \ 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/tdengine/TdEngineDatabaseServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseServiceImpl.java deleted file mode 100644 index c880db8a9..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseServiceImpl.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDatabaseMapper; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * TD 引擎的数据库 Service 实现类 - */ -@Service -@Slf4j -public class TdEngineDatabaseServiceImpl implements TdEngineDatabaseService { - - @Resource - private TdEngineDatabaseMapper tdEngineDatabaseMapper; - - @Override - public void createDatabase(String dataBaseName) { - tdEngineDatabaseMapper.createDatabase(dataBaseName); - } -} \ 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/tdengine/TdEngineQueryService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryService.java deleted file mode 100644 index 8d07b4334..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryService.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; - -import java.util.List; -import java.util.Map; - -/** - * TD 引擎的查询 Service 接口 - */ -public interface TdEngineQueryService { - - /** - * 获取历史数据 - * - * @param selectVisualDO 查询条件 - * @return 历史数据列表 - */ - List> getHistoryData(SelectVisualDO selectVisualDO); - - /** - * 获取历史数据条数 - * - * @param selectVisualDO 查询条件 - * @return 数据条数 - */ - Long getHistoryCount(SelectVisualDO selectVisualDO); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java deleted file mode 100644 index 672a58640..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineQueryMapper; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Map; - -@Service -public class TdEngineQueryServiceImpl implements TdEngineQueryService { - - @Resource - private TdEngineQueryMapper tdEngineQueryMapper; - - @Override - public List> getHistoryData(SelectVisualDO selectVisualDO) { - return tdEngineQueryMapper.getHistoryData(selectVisualDO); - } - - @Override - public Long getHistoryCount(SelectVisualDO selectVisualDO) { - return tdEngineQueryMapper.getHistoryCount(selectVisualDO); - } -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java deleted file mode 100644 index df6290a98..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java +++ /dev/null @@ -1,123 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; - -import java.util.List; -import java.util.Map; - -/** - * TD 引擎的超级表 Service 接口 - */ -public interface TdEngineSuperTableService { - - /** - * 创建超级表 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * columns 列信息 - * tags 标签信息 - */ - void createSuperTable(TdTableDO superTable); - - /** - * 查看超级表 - 显示当前数据库下的所有超级表信息 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - */ - - List> showSuperTables(TdTableDO superTable); - - /** - * 查看超级表 - 获取超级表的结构信息 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - */ - List> describeSuperTable(TdTableDO superTable); - - /** - * 修改超级表 - 增加列 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * column 列信息 - */ - void addColumnForSuperTable(TdTableDO superTable); - - /** - * 修改超级表 - 删除列 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * column 列信息 - */ - void dropColumnForSuperTable(TdTableDO superTable); - - /** - * 修改超级表 - 修改列宽 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * column 列信息 - */ - void modifyColumnWidthForSuperTable(TdTableDO superTable); - - - /** - * 修改超级表 - 为超级表添加标签 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * tag 标签信息 - */ - void addTagForSuperTable(TdTableDO superTable); - - /** - * 修改超级表 - 为超级表删除标签 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * tag 标签信息 - */ - void dropTagForSuperTable(TdTableDO superTable); - - /** - * 检查超级表是否存在 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * @return 超级表数量 - */ - Integer checkSuperTableExists(TdTableDO superTable); - - /** - * 为超级表添加列 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * columns 列信息 - */ - void addColumnsForSuperTable(TdTableDO superTable); - - /** - * 为超级表删除列 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * columns 列信息 - */ - void dropColumnsForSuperTable(TdTableDO superTable); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java deleted file mode 100644 index 60436e7bd..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java +++ /dev/null @@ -1,90 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineSuperTableMapper; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Map; - -/** - * TD 引擎的超级表 Service 实现类 - */ -@Slf4j -@Service -public class TdEngineSuperTableServiceImpl implements TdEngineSuperTableService { - - @Resource - private TdEngineSuperTableMapper tdEngineSuperTableMapper; - - @Override - public void createSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.createSuperTable(superTable); - } - - @Override - public List> showSuperTables(TdTableDO superTable) { - return tdEngineSuperTableMapper.showSuperTables(superTable); - } - - @Override - public List> describeSuperTable(TdTableDO superTable) { - return tdEngineSuperTableMapper.describeSuperTable(superTable); - } - - @Override - public void addColumnForSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.addColumnForSuperTable(superTable); - } - - @Override - public void dropColumnForSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.dropColumnForSuperTable(superTable); - } - - @Override - public void modifyColumnWidthForSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.modifyColumnWidthForSuperTable(superTable); - } - - @Override - public void addTagForSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.addTagForSuperTable(superTable); - } - - @Override - public void dropTagForSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.dropTagForSuperTable(superTable); - } - - @Override - public Integer checkSuperTableExists(TdTableDO superTable) { - List> results = tdEngineSuperTableMapper.showSuperTables(superTable); - return results == null || results.isEmpty() ? 0 : results.size(); - } - - @Override - public void addColumnsForSuperTable(TdTableDO superTable) { - for (TdFieldDO column : superTable.getColumns()) { - tdEngineSuperTableMapper.addColumnForSuperTable(TdTableDO.builder() - .dataBaseName(superTable.getDataBaseName()) - .superTableName(superTable.getSuperTableName()) - .column(column) - .build()); - } - } - - @Override - public void dropColumnsForSuperTable(TdTableDO superTable) { - for (TdFieldDO column : superTable.getColumns()) { - tdEngineSuperTableMapper.dropColumnForSuperTable(TdTableDO.builder() - .dataBaseName(superTable.getDataBaseName()) - .superTableName(superTable.getSuperTableName()) - .column(column) - .build()); - } - } -} \ 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/tdengine/TdEngineTableService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableService.java deleted file mode 100644 index 078159784..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableService.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; - -/** - * TD 引擎的表 Service 接口 - */ -public interface TdEngineTableService { - - /** - * 创建表 - 创建超级表的子表 - * - * @param table 表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * tableName 子表名称 - * tags TAG 字段 - */ - void createTable(TdTableDO table); - -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java deleted file mode 100644 index cdca47888..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineTableMapper; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * TD 引擎的表 Service 实现类 - */ -@Slf4j -@Service -public class TdEngineTableServiceImpl implements TdEngineTableService { - - @Resource - private TdEngineTableMapper tdEngineTableMapper; - - @Override - public void createTable(TdTableDO table) { - tdEngineTableMapper.createTable(table); - } -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDDLMapper.xml similarity index 70% rename from yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml rename to yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDDLMapper.xml index 37cf71910..091b77f64 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDDLMapper.xml @@ -2,7 +2,12 @@ - + + + + + CREATE DATABASE IF NOT EXISTS ${dataBaseName} + @@ -68,4 +73,29 @@ ALTER STABLE ${dataBaseName}.${superTableName} DROP TAG ${tag.fieldName} - + + + CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} + USING ${dataBaseName}.${superTableName} + TAGS + + #{item.fieldValue} + + + + + + CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} + USING ${dataBaseName}.${superTableName} + + #{item.fieldName} + + TAGS + + #{item.fieldValue} + + + + \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDMLMapper.xml similarity index 68% rename from yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml rename to yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDMLMapper.xml index f4361bc67..0443a826b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDMLMapper.xml @@ -2,7 +2,21 @@ - + + + + + INSERT INTO ${dataBaseName}.${tableName} + + ${item.fieldName} + + VALUES + + #{item.fieldValue} + + - SELECT COUNT(0) AS count FROM ${dataBaseName}.${tableName} @@ -20,14 +34,14 @@ - + SELECT LAST(time), * FROM ${tableName} WHERE device_id = #{deviceId} - SELECT LAST(*) FROM ${dataBaseName}.${stableName} @@ -35,7 +49,7 @@ - SELECT ${fieldName} AS data, time FROM ${dataBaseName}.${tableName} @@ -46,14 +60,14 @@ - SELECT ${fieldName}, time FROM ${dataBaseName}.${tableName} - SELECT ${aggregate}(${fieldName}) FROM ${dataBaseName}.${tableName} @@ -62,11 +76,11 @@ - + SELECT COUNT(time) FROM ${dataBaseName}.${tableName} WHERE time BETWEEN #{startTime} AND #{endTime} AND ${fieldName} IS NOT NULL - + \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml deleted file mode 100644 index dd38cd08e..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - INSERT INTO ${dataBaseName}.${tableName} - - ${item.fieldName} - - VALUES - - #{item.fieldValue} - - - - \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml deleted file mode 100644 index 919c301f7..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - CREATE DATABASE IF NOT EXISTS ${dataBaseName} - - - \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml deleted file mode 100644 index 867ef8f43..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} - USING ${dataBaseName}.${superTableName} - TAGS - - #{item.fieldValue} - - - - - - CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} - USING ${dataBaseName}.${superTableName} - - #{item.fieldName} - - TAGS - - #{item.fieldValue} - - - - \ No newline at end of file From ce919d12d1b079ace85c70004bd6553053b76667 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 5 Dec 2024 21:45:48 +0800 Subject: [PATCH 013/228] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91IoT=EF=BC=9Atdengine=20=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/controller/admin/device/IotDeviceDataController.java | 2 ++ .../yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java | 1 - .../module/iot/service/device/IotDeviceDataServiceImpl.java | 2 +- .../module/iot/service/device/IotDeviceServiceImpl.java | 2 +- .../service/tdengine/IotThingModelMessageServiceImpl.java | 5 +---- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java index 72fdda8c8..77bc78c66 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java @@ -31,6 +31,7 @@ public class IotDeviceDataController { @Resource private IotDeviceDataService deviceDataService; + // TODO @浩浩:这里的 /latest-list,包括方法名。 @GetMapping("/latest") @Operation(summary = "获取设备属性最新数据") public CommonResult> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { @@ -38,6 +39,7 @@ public class IotDeviceDataController { return success(BeanUtils.toBean(list, IotDeviceDataRespVO.class)); } + // TODO @浩浩:这里的 /history-page 包括方法名。 @GetMapping("/history") @Operation(summary = "获取设备属性历史数据") public CommonResult> getHistoryDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java index 640255940..3d7aa84dd 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.iot.dal.tdengine; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java index 7d10977f9..d68287cd4 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java @@ -133,7 +133,7 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { } private static String getDeviceTableName(String productKey, String deviceName) { - return String.format(IotConstants.DEVICE_TABLE_NAME_FORMAT, productKey, deviceName); + return String.format(IotConstants.DEVICE_TABLE_NAME_FORMAT, productKey, deviceName); } } \ 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/IotDeviceServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java index 58918c130..bb302a22f 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 @@ -139,13 +139,13 @@ public class IotDeviceServiceImpl implements IotDeviceService { * @return 生成的 MQTT Password */ private String generateMqttPassword() { + // TODO @浩浩:这里的 StrUtil 随机字符串? SecureRandom secureRandom = new SecureRandom(); byte[] passwordBytes = new byte[32]; // 256 位的随机数 secureRandom.nextBytes(passwordBytes); return Base64.getUrlEncoder().withoutPadding().encodeToString(passwordBytes); } - /** * 生成唯一的 DeviceName * diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java index 92a30ebb0..9ffb47715 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java @@ -66,8 +66,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ if (IotDeviceStatusEnum.INACTIVE.getStatus().equals(device.getStatus())) { createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO() - .setId(device.getId()) - .setStatus(IotDeviceStatusEnum.ONLINE.getStatus())); + .setId(device.getId()).setStatus(IotDeviceStatusEnum.ONLINE.getStatus())); } // 2. 获取设备属性并进行物模型校验,过滤非物模型属性 @@ -77,7 +76,6 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ return; } - // 3. 过滤并收集有效的属性字段,缓存设备属性 List schemaFieldValues = filterAndCollectValidFields(params, functionList, device, thingModelMessage.getTime()); if (schemaFieldValues.size() == 1) { // 仅有时间字段,无需保存 @@ -165,7 +163,6 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ // 2.1 过滤出 TAG 类型的字段 List> taggedNotesList = CollectionUtils.filterList(maps, map -> TAG_NOTE.equals(map.get(NOTE))); - // 2.2 解析字段信息 tagsFieldValues = FieldParser.parse(taggedNotesList.stream() .map(map -> List.of(map.get("field"), map.get("type"), map.get("length"))) From 3a2c691af085c4e649373961e827627b8fcfaf9a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 7 Dec 2024 16:42:56 +0800 Subject: [PATCH 014/228] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E3=80=91IoT=EF=BC=9A=E4=BA=A7=E5=93=81=E5=88=86?= =?UTF-8?q?=E7=B1=BB=E7=9A=84=E7=BB=B4=E6=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/iot/enums/ErrorCodeConstants.java | 9 ++- .../product/IotProductCategoryController.java | 72 +++++++++++++++++++ .../admin/product/vo/IotProductSaveReqVO.java | 6 +- .../category/IotProductCategoryPageReqVO.java | 27 +++++++ .../vo/category/IotProductCategoryRespVO.java | 33 +++++++++ .../category/IotProductCategorySaveReqVO.java | 29 ++++++++ .../product/IotProductCategoryDO.java | 48 +++++++++++++ .../product/IotProductCategoryMapper.java | 25 +++++++ .../product/IotProductCategoryService.java | 54 ++++++++++++++ .../IotProductCategoryServiceImpl.java | 70 ++++++++++++++++++ 10 files changed, 369 insertions(+), 4 deletions(-) create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryPageReqVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryRespVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategorySaveReqVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductCategoryDO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductCategoryMapper.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryService.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryServiceImpl.java 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 be9d28ecb..1e947e633 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 @@ -9,20 +9,20 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; */ public interface ErrorCodeConstants { - // ========== IoT 产品相关 1-050-001-000 ============ + // ========== 产品相关 1-050-001-000 ============ ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_050_001_000, "产品不存在"); ErrorCode PRODUCT_IDENTIFICATION_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在"); ErrorCode PRODUCT_STATUS_NOT_DELETE = new ErrorCode(1_050_001_002, "产品状是发布状态,不允许删除"); ErrorCode PRODUCT_STATUS_NOT_ALLOW_FUNCTION = new ErrorCode(1_050_001_003, "产品状是发布状态,不允许操作物模型"); - // ========== IoT 产品物模型 1-050-002-000 ============ + // ========== 产品物模型 1-050-002-000 ============ ErrorCode THINK_MODEL_FUNCTION_NOT_EXISTS = new ErrorCode(1_050_002_000, "产品物模型不存在"); ErrorCode THINK_MODEL_FUNCTION_EXISTS_BY_PRODUCT_KEY = new ErrorCode(1_050_002_001, "ProductKey 对应的产品物模型已存在"); ErrorCode THINK_MODEL_FUNCTION_IDENTIFIER_EXISTS = new ErrorCode(1_050_002_002, "存在重复的功能标识符。"); ErrorCode THINK_MODEL_FUNCTION_NAME_EXISTS = new ErrorCode(1_050_002_003, "存在重复的功能名称。"); ErrorCode THINK_MODEL_FUNCTION_IDENTIFIER_INVALID = new ErrorCode(1_050_002_003, "产品物模型标识无效"); - // ========== IoT 设备 1-050-003-000 ============ + // ========== 设备 1-050-003-000 ============ ErrorCode DEVICE_NOT_EXISTS = new ErrorCode(1_050_003_000, "设备不存在"); ErrorCode DEVICE_NAME_EXISTS = new ErrorCode(1_050_003_001, "设备名称在同一产品下必须唯一"); ErrorCode DEVICE_HAS_CHILDREN = new ErrorCode(1_050_003_002, "有子设备,不允许删除"); @@ -30,4 +30,7 @@ public interface ErrorCodeConstants { ErrorCode DEVICE_PRODUCT_CANNOT_BE_MODIFIED = new ErrorCode(1_050_003_004, "产品不能修改"); ErrorCode DEVICE_INVALID_DEVICE_STATUS = new ErrorCode(1_050_003_005, "无效的设备状态"); + // ========== 产品分类 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/controller/admin/product/IotProductCategoryController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java new file mode 100644 index 000000000..b365ddea1 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.iot.controller.admin.product; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +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.product.vo.category.IotProductCategoryPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategoryRespVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategorySaveReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO; +import cn.iocoder.yudao.module.iot.service.product.IotProductCategoryService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - IoT 产品分类") +@RestController +@RequestMapping("/iot/product-category") +@Validated +public class IotProductCategoryController { + + @Resource + private IotProductCategoryService productCategoryService; + + @PostMapping("/create") + @Operation(summary = "创建IoT 产品分类") + @PreAuthorize("@ss.hasPermission('iot:product-category:create')") + public CommonResult createProductCategory(@Valid @RequestBody IotProductCategorySaveReqVO createReqVO) { + return success(productCategoryService.createProductCategory(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新IoT 产品分类") + @PreAuthorize("@ss.hasPermission('iot:product-category:update')") + public CommonResult updateProductCategory(@Valid @RequestBody IotProductCategorySaveReqVO updateReqVO) { + productCategoryService.updateProductCategory(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除IoT 产品分类") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('iot:product-category:delete')") + public CommonResult deleteProductCategory(@RequestParam("id") Long id) { + productCategoryService.deleteProductCategory(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得IoT 产品分类") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('iot:product-category:query')") + public CommonResult getProductCategory(@RequestParam("id") Long id) { + IotProductCategoryDO productCategory = productCategoryService.getProductCategory(id); + return success(BeanUtils.toBean(productCategory, IotProductCategoryRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得IoT 产品分类分页") + @PreAuthorize("@ss.hasPermission('iot:product-category:query')") + public CommonResult> getProductCategoryPage(@Valid IotProductCategoryPageReqVO pageReqVO) { + PageResult pageResult = productCategoryService.getProductCategoryPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, IotProductCategoryRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java index 254b6b9da..757750544 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java @@ -14,9 +14,13 @@ public class IotProductSaveReqVO { @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.AUTO, example = "1") private Long id; - @Schema(description = "产品Key", requiredMode = Schema.RequiredMode.AUTO, example = "12345abc") + @Schema(description = "产品 Key", requiredMode = Schema.RequiredMode.AUTO, example = "12345abc") private String productKey; + // TODO 芋艿:品类 + + // TODO 芋艿:【待确定】保活时长、产品图标、产品图片 + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "温湿度") @NotEmpty(message = "产品名称不能为空") private String name; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryPageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryPageReqVO.java new file mode 100644 index 000000000..90d338a89 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryPageReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.category; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - IoT 产品分类分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class IotProductCategoryPageReqVO extends PageParam { + + @Schema(description = "分类名字", example = "王五") + private String name; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryRespVO.java new file mode 100644 index 000000000..d684b0215 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryRespVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.category; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - IoT 产品分类 Response VO") +@Data +public class IotProductCategoryRespVO { + + @Schema(description = "分类 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "25284") + private Long id; + + @Schema(description = "分类名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") + private String name; + + @Schema(description = "分类排序") + private Integer sort; + + @Schema(description = "分类状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "分类描述", example = "随便") + private String description; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategorySaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategorySaveReqVO.java new file mode 100644 index 000000000..a7b2fe427 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategorySaveReqVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.category; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - IoT 产品分类新增/修改 Request VO") +@Data +public class IotProductCategorySaveReqVO { + + @Schema(description = "分类 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "25284") + private Long id; + + @Schema(description = "分类名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") + @NotEmpty(message = "分类名字不能为空") + private String name; + + @Schema(description = "分类排序") + private Integer sort; + + @Schema(description = "分类状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "分类状态不能为空") + private Integer status; + + @Schema(description = "分类描述", example = "随便") + private String description; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductCategoryDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductCategoryDO.java new file mode 100644 index 000000000..a6510488c --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductCategoryDO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.product; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * IoT 产品分类 DO + * + * @author 芋道源码 + */ +@TableName("iot_product_category") +@KeySequence("iot_product_category_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class IotProductCategoryDO extends BaseDO { + + /** + * 分类 ID + */ + @TableId + private Long id; + /** + * 分类名字 + */ + private String name; + /** + * 分类排序 + */ + private Integer sort; + /** + * 分类状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 分类描述 + */ + private String description; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductCategoryMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductCategoryMapper.java new file mode 100644 index 000000000..845eded14 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductCategoryMapper.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.iot.dal.mysql.product; + +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.module.iot.controller.admin.product.vo.category.IotProductCategoryPageReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * IoT 产品分类 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface IotProductCategoryMapper extends BaseMapperX { + + default PageResult selectPage(IotProductCategoryPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(IotProductCategoryDO::getName, reqVO.getName()) + .betweenIfPresent(IotProductCategoryDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(IotProductCategoryDO::getId)); + } + +} \ 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/IotProductCategoryService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryService.java new file mode 100644 index 000000000..9830ec8b9 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryService.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.iot.service.product; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategoryPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategorySaveReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO; +import jakarta.validation.Valid; + +/** + * IoT 产品分类 Service 接口 + * + * @author 芋道源码 + */ +public interface IotProductCategoryService { + + /** + * 创建IoT 产品分类 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProductCategory(@Valid IotProductCategorySaveReqVO createReqVO); + + /** + * 更新IoT 产品分类 + * + * @param updateReqVO 更新信息 + */ + void updateProductCategory(@Valid IotProductCategorySaveReqVO updateReqVO); + + /** + * 删除IoT 产品分类 + * + * @param id 编号 + */ + void deleteProductCategory(Long id); + + /** + * 获得IoT 产品分类 + * + * @param id 编号 + * @return IoT 产品分类 + */ + IotProductCategoryDO getProductCategory(Long id); + + /** + * 获得IoT 产品分类分页 + * + * @param pageReqVO 分页查询 + * @return IoT 产品分类分页 + */ + PageResult getProductCategoryPage(IotProductCategoryPageReqVO pageReqVO); + +} \ 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/IotProductCategoryServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryServiceImpl.java new file mode 100644 index 000000000..579d27cfb --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryServiceImpl.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.iot.service.product; + +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.product.vo.category.IotProductCategoryPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategorySaveReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO; +import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductCategoryMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PRODUCT_CATEGORY_NOT_EXISTS; + +/** + * IoT 产品分类 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class IotProductCategoryServiceImpl implements IotProductCategoryService { + + @Resource + private IotProductCategoryMapper productCategoryMapper; + + @Override + public Long createProductCategory(IotProductCategorySaveReqVO createReqVO) { + // 插入 + IotProductCategoryDO productCategory = BeanUtils.toBean(createReqVO, IotProductCategoryDO.class); + productCategoryMapper.insert(productCategory); + // 返回 + return productCategory.getId(); + } + + @Override + public void updateProductCategory(IotProductCategorySaveReqVO updateReqVO) { + // 校验存在 + validateProductCategoryExists(updateReqVO.getId()); + // 更新 + IotProductCategoryDO updateObj = BeanUtils.toBean(updateReqVO, IotProductCategoryDO.class); + productCategoryMapper.updateById(updateObj); + } + + @Override + public void deleteProductCategory(Long id) { + // 校验存在 + validateProductCategoryExists(id); + // 删除 + productCategoryMapper.deleteById(id); + } + + private void validateProductCategoryExists(Long id) { + if (productCategoryMapper.selectById(id) == null) { + throw exception(PRODUCT_CATEGORY_NOT_EXISTS); + } + } + + @Override + public IotProductCategoryDO getProductCategory(Long id) { + return productCategoryMapper.selectById(id); + } + + @Override + public PageResult getProductCategoryPage(IotProductCategoryPageReqVO pageReqVO) { + return productCategoryMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file From 9b9fd30c90bfb88d1ad61ef314ffab73e18264ea Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 7 Dec 2024 18:50:31 +0800 Subject: [PATCH 015/228] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E3=80=91IoT=EF=BC=9A=E4=BA=A7=E5=93=81=E6=94=BE?= =?UTF-8?q?=E5=88=B0=20product=20=E5=AD=90=E7=9B=AE=E5=BD=95=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/product/IotProductController.java | 13 +++--- .../product/vo/IotProductSimpleRespVO.java | 16 ------- .../vo/{ => product}/IotProductPageReqVO.java | 2 +- .../vo/{ => product}/IotProductRespVO.java | 43 +++++++++++-------- .../vo/{ => product}/IotProductSaveReqVO.java | 28 +++++++----- .../dal/dataobject/product/IotProductDO.java | 15 +++++-- .../dal/mysql/product/IotProductMapper.java | 2 +- .../service/product/IotProductService.java | 4 +- .../product/IotProductServiceImpl.java | 5 +-- .../dal/dataobject/notify/PayNotifyLogDO.java | 2 +- .../dataobject/notify/PayNotifyTaskDO.java | 4 +- 11 files changed, 68 insertions(+), 66 deletions(-) delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSimpleRespVO.java rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/{ => product}/IotProductPageReqVO.java (88%) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/{ => product}/IotProductRespVO.java (85%) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/{ => product}/IotProductSaveReqVO.java (82%) 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 e7f41d91d..a4d111a99 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 @@ -3,10 +3,9 @@ package cn.iocoder.yudao.module.iot.controller.admin.product; import cn.iocoder.yudao.framework.common.pojo.CommonResult; 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.product.vo.IotProductPageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductRespVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSimpleRespVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductRespVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductSaveReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.service.product.IotProductService; import io.swagger.v3.oas.annotations.Operation; @@ -21,6 +20,7 @@ import org.springframework.web.bind.annotation.*; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @Tag(name = "管理后台 - IoT 产品") @RestController @@ -86,9 +86,10 @@ public class IotProductController { @GetMapping("/simple-list") @Operation(summary = "获得所有产品列表") @PreAuthorize("@ss.hasPermission('iot:product:query')") - public CommonResult> getSimpleProductList() { + public CommonResult> getSimpleProductList() { List list = productService.getProductList(); - return success(BeanUtils.toBean(list, IotProductSimpleRespVO.class)); + return success(convertList(list, product -> // 只返回 id、name 字段 + new IotProductRespVO().setId(product.getId()).setName(product.getName()))); } } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSimpleRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSimpleRespVO.java deleted file mode 100644 index 83855eaaf..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSimpleRespVO.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.iot.controller.admin.product.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - IoT 产品 Response VO") -@Data -public class IotProductSimpleRespVO { - - @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "26087") - private Long id; - - @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") - private String name; - -} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductPageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductPageReqVO.java similarity index 88% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductPageReqVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductPageReqVO.java index 3437f563f..d54adec48 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductPageReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.iot.controller.admin.product.vo; +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.product; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java similarity index 85% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductRespVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java index 0958b3e84..65d26ff5b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductRespVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.iot.controller.admin.product.vo; +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.product; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; @@ -20,34 +20,23 @@ public class IotProductRespVO { @ExcelProperty("产品名称") private String name; - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("创建时间") - private LocalDateTime createTime; - @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("产品标识") private String productKey; - @Schema(description = "接入网关协议", example = "2") - @ExcelProperty("接入网关协议") - private Integer protocolType; - - @Schema(description = "协议编号(脚本解析 id)", requiredMode = Schema.RequiredMode.REQUIRED, example = "13177") - @ExcelProperty("协议编号(脚本解析 id)") - private Long protocolId; - - @Schema(description = "产品所属品类标识符", example = "14237") - @ExcelProperty("产品所属品类标识符") + @Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long categoryId; + @Schema(description = "产品图标", example = "https://iocoder.cn/1.svg") + private String icon; + + @Schema(description = "产品图标", example = "https://iocoder.cn/1.png") + private String picUrl; + @Schema(description = "产品描述", example = "你猜") @ExcelProperty("产品描述") private String description; - @Schema(description = "数据校验级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @ExcelProperty("数据校验级别") - private Integer validateType; - @Schema(description = "产品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @ExcelProperty("产品状态") private Integer status; @@ -60,8 +49,24 @@ public class IotProductRespVO { @ExcelProperty("联网方式") private Integer netType; + @Schema(description = "接入网关协议", example = "2") + @ExcelProperty("接入网关协议") + private Integer protocolType; + + @Schema(description = "协议编号(脚本解析 id)", requiredMode = Schema.RequiredMode.REQUIRED, example = "13177") + @ExcelProperty("协议编号(脚本解析 id)") + private Long protocolId; + @Schema(description = "数据格式") @ExcelProperty("数据格式") private Integer dataFormat; + @Schema(description = "数据校验级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("数据校验级别") + private Integer validateType; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductSaveReqVO.java similarity index 82% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductSaveReqVO.java index 757750544..31890beb7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductSaveReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.iot.controller.admin.product.vo; +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.product; import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.module.iot.enums.product.*; @@ -14,17 +14,26 @@ public class IotProductSaveReqVO { @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.AUTO, example = "1") private Long id; - @Schema(description = "产品 Key", requiredMode = Schema.RequiredMode.AUTO, example = "12345abc") - private String productKey; - - // TODO 芋艿:品类 - - // TODO 芋艿:【待确定】保活时长、产品图标、产品图片 - @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "温湿度") @NotEmpty(message = "产品名称不能为空") private String name; + @Schema(description = "产品 Key", requiredMode = Schema.RequiredMode.AUTO, example = "12345abc") + private String productKey; + + @Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "产品分类编号不能为空") + private Long categoryId; + + @Schema(description = "产品图标", example = "https://iocoder.cn/1.svg") + private String icon; + + @Schema(description = "产品图标", example = "https://iocoder.cn/1.png") + private String picUrl; + + @Schema(description = "产品描述", example = "描述") + private String description; + @Schema(description = "设备类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") @InEnum(value = IotProductDeviceTypeEnum.class, message = "设备类型必须是 {value}") @NotNull(message = "设备类型不能为空") @@ -48,7 +57,4 @@ public class IotProductSaveReqVO { @NotNull(message = "数据校验级别不能为空") private Integer validateType; - @Schema(description = "产品描述", example = "描述") - private String description; - } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java index eef466eda..34fd35706 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java @@ -22,7 +22,7 @@ import lombok.*; public class IotProductDO extends BaseDO { /** - * 产品ID + * 产品 ID */ @TableId private Long id; @@ -30,17 +30,24 @@ public class IotProductDO extends BaseDO { * 产品名称 */ private String name; - // TODO @haohao:这个字段,要不改成 identifier,和阿里云更统一些 /** * 产品标识 */ private String productKey; /** - * 产品所属品类编号 + * 产品分类编号 * - * TODO 外键:后续加 + * 关联 {@link IotProductCategoryDO#getId()} */ private Long categoryId; + /** + * 产品图标 + */ + private String icon; + /** + * 产品图片 + */ + private String picUrl; /** * 产品描述 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java index 0341e2492..eac1d29e8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.dal.mysql.product; 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.module.iot.controller.admin.product.vo.IotProductPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import org.apache.ibatis.annotations.Mapper; 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 3fff94fd9..bcbf13ef4 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 @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.iot.service.product; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductPageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductSaveReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import jakarta.validation.Valid; 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 d0ca09288..259bcaa1f 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 @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.iot.service.product; 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.product.vo.IotProductPageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductSaveReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductMapper; import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum; @@ -14,7 +14,6 @@ import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.util.List; diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java index a482605d5..384628370 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java @@ -44,7 +44,7 @@ public class PayNotifyLogDO extends BaseDO { /** * 支付通知状态 * - * 外键 {@link PayNotifyStatusEnum} + * 枚举 {@link PayNotifyStatusEnum} */ private Integer status; diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java index 7bfabad3f..9f9ee7fef 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java @@ -52,7 +52,7 @@ public class PayNotifyTaskDO extends TenantBaseDO { /** * 通知类型 * - * 外键 {@link PayNotifyTypeEnum} + * 枚举 {@link PayNotifyTypeEnum} */ private Integer type; /** @@ -73,7 +73,7 @@ public class PayNotifyTaskDO extends TenantBaseDO { /** * 通知状态 * - * 外键 {@link PayNotifyStatusEnum} + * 枚举 {@link PayNotifyStatusEnum} */ private Integer status; /** From a8c87d168accd14f5b266be9815046b1b45ff9db Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 7 Dec 2024 19:50:07 +0800 Subject: [PATCH 016/228] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E3=80=91IoT=EF=BC=9A=E4=BA=A7=E5=93=81=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=97=B6=EF=BC=8CproductKey=20=E7=94=B1=E5=89=8D?= =?UTF-8?q?=E7=AB=AF=E7=94=9F=E6=88=90=EF=BC=9B=E5=90=8C=E6=97=B6=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20icon=E3=80=81picUrl=20=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/iot/enums/ErrorCodeConstants.java | 2 +- .../enums/product/IotProductStatusEnum.java | 4 +-- .../product/IotProductCategoryController.java | 24 +++++++++++--- .../product/IotProductCategoryMapper.java | 6 ++++ .../product/IotProductCategoryService.java | 24 ++++++++++---- .../IotProductCategoryServiceImpl.java | 7 ++++ .../product/IotProductServiceImpl.java | 32 ++++--------------- .../IotThinkModelFunctionServiceImpl.java | 2 +- 8 files changed, 60 insertions(+), 41 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 1e947e633..d1d350d5e 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 @@ -11,7 +11,7 @@ public interface ErrorCodeConstants { // ========== 产品相关 1-050-001-000 ============ ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_050_001_000, "产品不存在"); - ErrorCode PRODUCT_IDENTIFICATION_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在"); + ErrorCode PRODUCT_KEY_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在"); ErrorCode PRODUCT_STATUS_NOT_DELETE = new ErrorCode(1_050_001_002, "产品状是发布状态,不允许删除"); ErrorCode PRODUCT_STATUS_NOT_ALLOW_FUNCTION = new ErrorCode(1_050_001_003, "产品状是发布状态,不允许操作物模型"); diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java index e64a3d678..7b4d90a5a 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java @@ -18,12 +18,12 @@ public enum IotProductStatusEnum implements IntArrayValuable { UNPUBLISHED(0, "开发中"), PUBLISHED(1, "已发布"); - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(IotProductStatusEnum::getType).toArray(); + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(IotProductStatusEnum::getStatus).toArray(); /** * 类型 */ - private final Integer type; + private final Integer status; /** * 描述 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java index b365ddea1..bc1c1fbf2 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.iot.controller.admin.product; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -17,7 +18,10 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.List; + import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @Tag(name = "管理后台 - IoT 产品分类") @RestController @@ -29,14 +33,14 @@ public class IotProductCategoryController { private IotProductCategoryService productCategoryService; @PostMapping("/create") - @Operation(summary = "创建IoT 产品分类") + @Operation(summary = "创建产品分类") @PreAuthorize("@ss.hasPermission('iot:product-category:create')") public CommonResult
+ * 格式为 device_{productKey}_{deviceName} + */ + String DEVICE_TABLE_NAME_FORMAT = "device_%s_%s"; + + /** + * 获取产品属性超级表名 - 网关子设备 + *
+ * 格式为 gateway_sub_{productKey} + */ + String GATEWAY_SUB_STABLE_NAME_FORMAT = "gateway_sub_%s"; + + /** + * 获取产品属性超级表名 - 网关 + *
+ * 格式为 gateway_{productKey} + */ + String GATEWAY_STABLE_NAME_FORMAT = "gateway_%s"; + + /** + * 获取产品属性超级表名 - 设备 + *
+ * 格式为 device_{productKey} + */ + String DEVICE_STABLE_NAME_FORMAT = "device_%s"; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java index ac2ec5cf7..72fdda8c8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.controller.admin.device; import cn.iocoder.yudao.framework.common.pojo.CommonResult; 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.device.vo.deviceData.IotDeviceDataReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataRespVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotTimeDataRespVO; @@ -31,19 +31,17 @@ public class IotDeviceDataController { @Resource private IotDeviceDataService deviceDataService; - // TODO @haohao:是不是叫 get-latest 就好了。因为 data 已经在 url 里了哈 - @GetMapping("/latest-data") + @GetMapping("/latest") @Operation(summary = "获取设备属性最新数据") - public CommonResult> getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceDataReqVO) { - List list = deviceDataService.getDevicePropertiesLatestData(deviceDataReqVO); + public CommonResult> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { + List list = deviceDataService.getLatestDeviceProperties(deviceDataReqVO); return success(BeanUtils.toBean(list, IotDeviceDataRespVO.class)); } - // TODO @haohao:是不是叫 /history-data => page - @GetMapping("/history-data") + @GetMapping("/history") @Operation(summary = "获取设备属性历史数据") - public CommonResult> getDevicePropertiesHistoryData(@Valid IotDeviceDataReqVO deviceDataReqVO) { - PageResult> list = deviceDataService.getDevicePropertiesHistoryData(deviceDataReqVO); + public CommonResult> getHistoryDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { + PageResult> list = deviceDataService.getHistoryDeviceProperties(deviceDataReqVO); return success(BeanUtils.toBean(list, IotTimeDataRespVO.class)); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataPageReqVO.java similarity index 92% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataPageReqVO.java index 21e53aff8..da41299d8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataPageReqVO.java @@ -10,10 +10,9 @@ import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -// TODO @haohao:IotDeviceDataPageReqVO @Schema(description = "管理后台 - IoT 设备数据 Request VO") @Data -public class IotDeviceDataReqVO extends PageParam { +public class IotDeviceDataPageReqVO extends PageParam { @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "177") private Long deviceId; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataRespVO.java index 256bf84fa..ad32fb5f9 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataRespVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataRespVO.java @@ -1,9 +1,6 @@ package cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Builder; import lombok.Data; import java.time.LocalDateTime; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java index 68370d731..892a6b8b7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java @@ -1,15 +1,12 @@ package cn.iocoder.yudao.module.iot.dal.dataobject.device; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; -import com.baomidou.mybatisplus.annotation.TableId; -import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; -import java.math.BigDecimal; import java.time.LocalDateTime; /** @@ -23,39 +20,52 @@ import java.time.LocalDateTime; @AllArgsConstructor public class IotDeviceDataDO { - // TODO @haohao:每个字段的关联关系,可以 @ 下哈。 /** * 设备编号 + * + * 关联 {@link IotDeviceDO#getId()} */ private Long deviceId; /** * 物模型编号 + * + * 关联 {@link IotThinkModelFunctionDO#getId()} */ private Long thinkModelFunctionId; /** * 产品标识 + * + * 关联 {@link IotProductDO#getProductKey()} */ private String productKey; /** * 设备名称 + * + * 冗余 {@link IotDeviceDO#getDeviceName()} */ private String deviceName; /** * 属性标识符 + * + * 关联 {@link IotThinkModelFunctionDO#getIdentifier()} */ private String identifier; /** * 属性名称 + * + * 关联 {@link IotThinkModelFunctionDO#getName()} */ private String name; /** * 数据类型 + * + * 关联 {@link IotThinkModelFunctionDO#getProperty()#getDataType()} */ private String dataType; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java index 652c3aee6..542dd1e7b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java @@ -42,12 +42,6 @@ public class SelectDO { */ private String type; - // TODO @haohao:这个字段,是啥哈? - /** - * 查询条件 - */ - private Set orgIds; - /** * 设备ID */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java index d4c35d66d..44acc3ac5 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java @@ -27,14 +27,17 @@ public class SelectVisualDO { * 查询类型,0历史数据,1实时数据,2聚合数据 */ private int type; + /** * 查询的数据量 */ private int num; + /** * 聚合函数 */ private String aggregate; + /** * 统计间隔数字+s/m/h/d * 比如1s,1m,1h,1d代表1秒,1分钟,1小时,1天 diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java deleted file mode 100644 index e11db58e7..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java +++ /dev/null @@ -1,159 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; - -import java.util.List; - -// TODO @haohao:这个还有用哇? -/** - * TableManager 类用于管理 TDengine 表的创建、删除和结构信息获取 - */ -public class TableManager { - - /** - * 创建超级表模板(含存在判断) - */ - private static final String CREATE_STABLE_INE_TPL = "CREATE STABLE IF NOT EXISTS %s (%s) TAGS (%s);"; - - /** - * 删除超级表 - */ - private static final String DROP_STABLE_TPL = "DROP STABLE IF EXISTS %s;"; - - /** - * 获取表的结构信息 - */ - private static final String DESC_TB_TPL = "DESCRIBE %s;"; - - /** - * 超级表增加列 - */ - private static final String ALTER_STABLE_ADD_COL_TPL = "ALTER STABLE %s ADD COLUMN %s;"; - - /** - * 超级表修改列 - */ - private static final String ALTER_STABLE_MODIFY_COL_TPL = "ALTER STABLE %s MODIFY COLUMN %s;"; - - /** - * 超级表删除列 - */ - private static final String ALTER_STABLE_DROP_COL_TPL = "ALTER STABLE %s DROP COLUMN %s;"; - - /** - * 创建普通表模板(含存在判断) - */ - private static final String CREATE_CTABLE_INE_TPL = "CREATE TABLE IF NOT EXISTS %s (%s)"; - - /** - * 获取创建表sql - */ - public static String getCreateSTableSql(String tbName, List fields, TdFieldDO... tags) { - if (fields.isEmpty()) { - return null; - } - - // 生成字段片段 - StringBuilder sbField = new StringBuilder("time TIMESTAMP,"); - - for (TdFieldDO field : fields) { - sbField.append(FieldParser.getFieldDefine(field)); - sbField.append(","); - } - sbField.deleteCharAt(sbField.length() - 1); - - String fieldFrag = sbField.toString(); - - // 生成tag - StringBuilder sbTag = new StringBuilder(); - for (TdFieldDO tag : tags) { - sbTag.append(FieldParser.getFieldDefine(tag)) - .append(","); - } - sbTag.deleteCharAt(sbTag.length() - 1); - - return String.format(CREATE_STABLE_INE_TPL, tbName, fieldFrag, sbTag); - - } - - /** - * 获取创建普通表sql - */ - public static String getCreateCTableSql(String tbName, List fields) { - if (fields.size() == 0) { - return null; - } - - //生成字段片段 - StringBuilder sbField = new StringBuilder("time timestamp,"); - - for (TdFieldDO field : fields) { - sbField.append(FieldParser.getFieldDefine(field)); - sbField.append(","); - } - sbField.deleteCharAt(sbField.length() - 1); - - String fieldFrag = sbField.toString(); - - return String.format(CREATE_CTABLE_INE_TPL, tbName, fieldFrag); - - } - - - /** - * 取正确的表名 - * - * @param name 表象 - */ - public static String rightTbName(String name) { - return name.toLowerCase().replace("-" , "_"); - } - - /** - * 获取表详情的sql - */ - public static String getDescTableSql(String tbName) { - return String.format(DESC_TB_TPL, tbName); - } - - /** - * 获取添加字段sql - */ - public static String getAddSTableColumnSql(String tbName, List fields) { - StringBuilder sbAdd = new StringBuilder(); - for (TdFieldDO field : fields) { - sbAdd.append(String.format(ALTER_STABLE_ADD_COL_TPL, - tbName, - FieldParser.getFieldDefine(field) - )); - } - return sbAdd.toString(); - } - - /** - * 获取修改字段sql - */ - public static String getModifySTableColumnSql(String tbName, List fields) { - StringBuilder sbModify = new StringBuilder(); - for (TdFieldDO field : fields) { - sbModify.append(String.format(ALTER_STABLE_MODIFY_COL_TPL, - tbName, - FieldParser.getFieldDefine(field) - )); - } - return sbModify.toString(); - } - - /** - * 获取删除字段sql - */ - public static String getDropSTableColumnSql(String tbName, List fields) { - StringBuilder sbDrop = new StringBuilder(); - for (TdFieldDO field : fields) { - sbDrop.append(String.format(ALTER_STABLE_DROP_COL_TPL, - tbName, - field.getFieldName() - )); - } - return sbDrop.toString(); - } - -} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineSuperTableMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java similarity index 68% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineSuperTableMapper.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java index e688563d5..640255940 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineSuperTableMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java @@ -1,19 +1,30 @@ package cn.iocoder.yudao.module.iot.dal.tdengine; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.mybatisplus.annotation.InterceptorIgnore; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; import java.util.List; import java.util.Map; /** - * TD 引擎的超级表 Mapper + * 专门处理 DDL(数据定义语言)操作,包含所有的数据库和表的定义操作,例如创建数据库、创建超级表、创建子表等 */ @Mapper @DS("tdengine") -public interface TdEngineSuperTableMapper { +public interface TdEngineDDLMapper { + + /** + * 创建数据库 + * SQL:CREATE DATABASE [IF NOT EXISTS] db_name [database_options]; + * + * @param dataBaseName 数据库名称 + */ + @TenantIgnore + void createDatabase(@Param("dataBaseName") String dataBaseName); /** * 创建超级表 @@ -25,7 +36,7 @@ public interface TdEngineSuperTableMapper { * columns 列信息 * tags 标签信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void createSuperTable(TdTableDO superTable); /** @@ -36,7 +47,7 @@ public interface TdEngineSuperTableMapper { * dataBaseName 数据库名称 * superTableName 超级表名称 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore List> showSuperTables(TdTableDO superTable); /** @@ -47,7 +58,7 @@ public interface TdEngineSuperTableMapper { * dataBaseName 数据库名称 * superTableName 超级表名称 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore List> describeSuperTable(TdTableDO superTable); /** @@ -59,7 +70,7 @@ public interface TdEngineSuperTableMapper { * superTableName 超级表名称 * column 列信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void addColumnForSuperTable(TdTableDO superTable); /** @@ -71,7 +82,7 @@ public interface TdEngineSuperTableMapper { * superTableName 超级表名称 * column 列信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void dropColumnForSuperTable(TdTableDO superTable); /** @@ -83,7 +94,7 @@ public interface TdEngineSuperTableMapper { * superTableName 超级表名称 * column 列信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void modifyColumnWidthForSuperTable(TdTableDO superTable); @@ -95,7 +106,7 @@ public interface TdEngineSuperTableMapper { * superTableName 超级表名称 * tag 标签信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void addTagForSuperTable(TdTableDO superTable); /** @@ -106,6 +117,33 @@ public interface TdEngineSuperTableMapper { * superTableName 超级表名称 * tag 标签信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void dropTagForSuperTable(TdTableDO superTable); -} \ No newline at end of file + + /** + * 创建子表 - 创建子表 + * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name TAGS (tag_value1, ...); + * + * @param table 表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tableName 子表名称 + * tags TAG 字段 + */ + @TenantIgnore + void createTable(TdTableDO table); + + /** + * 创建子表 - 创建子表并指定标签的值 + * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name (tag_name1, ...) TAGS (tag_value1, ...); + * + * @param table 表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tableName 子表名称 + * tags TAG 字段 + */ + @TenantIgnore + void createTableWithTags(TdTableDO table); + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDMLMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDMLMapper.java new file mode 100644 index 000000000..12b2c232c --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDMLMapper.java @@ -0,0 +1,103 @@ +package cn.iocoder.yudao.module.iot.dal.tdengine; + +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TagsSelectDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; +import com.baomidou.dynamic.datasource.annotation.DS; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; +import java.util.Map; + +/** + * 专门处理 TD Engine 的 DML(数据操作语言)操作,处理所有的数据查询和写入操作,如插入数据、查询数据等 + */ +@Mapper +@DS("tdengine") +public interface TdEngineDMLMapper { + + /** + * 插入数据 - 指定列插入数据 + * + * @param table 数据 + * dataBaseName 数据库名 + * tableName 表名 + * columns 列 + */ + @TenantIgnore + void insertData(TdTableDO table); + + /** + * 根据时间戳查询数据 + * + * @param selectDO 查询条件 + * @return 查询结果列表 + */ + @TenantIgnore + List> selectByTimestamp(SelectDO selectDO); + + /** + * 根据时间戳获取数据条数 + * + * @param selectDO 查询条件 + * @return 数据条数 + */ + @TenantIgnore + Map selectCountByTimestamp(SelectDO selectDO); + + /** + * 获取最新数据 + * + * @param selectDO 查询条件 + * @return 最新数据 + */ + @TenantIgnore + Map selectOneLastData(SelectDO selectDO); + + /** + * 获取历史数据列表 + * + * @param selectVisualDO 查询条件 + * @return 历史数据列表 + */ + @TenantIgnore + List> selectHistoryDataList(SelectVisualDO selectVisualDO); + + /** + * 获取实时数据列表 + * + * @param selectVisualDO 查询条件 + * @return 实时数据列表 + */ + @TenantIgnore + List> selectRealtimeDataList(SelectVisualDO selectVisualDO); + + /** + * 获取聚合数据列表 + * + * @param selectVisualDO 查询条件 + * @return 聚合数据列表 + */ + @TenantIgnore + List> selectAggregateDataList(SelectVisualDO selectVisualDO); + + /** + * 根据标签获取最新数据列表 + * + * @param tagsSelectDO 查询条件 + * @return 最新数据列表 + */ + @TenantIgnore + List> selectLastDataListByTags(TagsSelectDO tagsSelectDO); + + /** + * 获取历史数据条数 + * + * @param selectVisualDO 查询条件 + * @return 数据条数 + */ + @TenantIgnore + Long selectHistoryCount(SelectVisualDO selectVisualDO); +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDataWriterMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDataWriterMapper.java deleted file mode 100644 index 51f4229a0..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDataWriterMapper.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.apache.ibatis.annotations.Mapper; - -/** - * TD 引擎的数据写入 Mapper - */ -@Mapper -@DS("tdengine") -public interface TdEngineDataWriterMapper { - - /** - * 插入数据 - 指定列插入数据 - * - * @param table 数据 - * dataBaseName 数据库名 - * tableName 表名 - * columns 列 - */ - @InterceptorIgnore(tenantLine = "true") - void insertData(TdTableDO table); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java deleted file mode 100644 index cd3eaa8b9..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.tdengine; - -import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -// TODO @haohao:InterceptorIgnore 忽略租户,可以在每个方法上,添加 @TenantIgnore 哈。 -/** - * TD 引擎的数据库 Mapper - */ -@Mapper -@DS("tdengine") -public interface TdEngineDatabaseMapper { - - /** - * 创建数据库 - * SQL:CREATE DATABASE [IF NOT EXISTS] db_name [database_options]; - * - * @param dataBaseName 数据库名称 - */ - @InterceptorIgnore(tenantLine = "true") - void createDatabase(@Param("dataBaseName") String dataBaseName); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java deleted file mode 100644 index a2408e335..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java +++ /dev/null @@ -1,86 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TagsSelectDO; -import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; -import java.util.Map; - -/** - * TD 引擎的查询 Mapper - */ -@Mapper -@DS("tdengine") -public interface TdEngineQueryMapper { - - /** - * 根据时间戳查询数据 - * - * @param selectDO 查询条件 - * @return 查询结果 - */ - List> selectByTimestamp(SelectDO selectDO); - - // TODO @haohao:最好方法的命名,和数据库操作的保持一直。get => select。然后 selectList or selectOne - /** - * 根据时间戳获取数据条数 - * - * @param selectDO 查询条件 - * @return 数据条数 - */ - Map getCountByTimestamp(SelectDO selectDO); - - /** - * 获取最新数据 - * - * @param selectDO 查询条件 - * @return 最新数据 - */ - Map getLastData(SelectDO selectDO); - - /** - * 获取历史数据 - * - * @param selectVisualDO 查询条件 - * @return 历史数据列表 - */ - @InterceptorIgnore(tenantLine = "true") - List> getHistoryData(SelectVisualDO selectVisualDO); - - /** - * 获取实时数据 - * - * @param selectVisualDO 查询条件 - * @return 实时数据列表 - */ - List> getRealtimeData(SelectVisualDO selectVisualDO); - - /** - * 获取聚合数据 - * - * @param selectVisualDO 查询条件 - * @return 聚合数据列表 - */ - List> getAggregateData(SelectVisualDO selectVisualDO); - - /** - * 根据标签获取最新数据 - * - * @param tagsSelectDO 查询条件 - * @return 最新数据列表 - */ - List> getLastDataByTags(TagsSelectDO tagsSelectDO); - - /** - * 获取历史数据条数 - * - * @param selectVisualDO 查询条件 - * @return 数据条数 - */ - @InterceptorIgnore(tenantLine = "true") - Long getHistoryCount(SelectVisualDO selectVisualDO); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java deleted file mode 100644 index 72517bcab..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.apache.ibatis.annotations.Mapper; - -/** - * TD 引擎的表 Mapper - */ -@Mapper -@DS("tdengine") -public interface TdEngineTableMapper { - - /** - * 创建子表 - 创建子表 - * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name TAGS (tag_value1, ...); - * - * @param table 表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * tableName 子表名称 - * tags TAG 字段 - */ - @InterceptorIgnore(tenantLine = "true") - void createTable(TdTableDO table); - - /** - * 创建子表 - 创建子表并指定标签的值 - * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name (tag_name1, ...) TAGS (tag_value1, ...); - * - * @param table 表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * tableName 子表名称 - * tags TAG 字段 - */ - @InterceptorIgnore(tenantLine = "true") - void createTableWithTags(TdTableDO table); - -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java index 96181fd26..4f390ca3b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java @@ -1,7 +1,7 @@ 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.deviceData.IotDeviceDataReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import jakarta.validation.Valid; @@ -31,7 +31,7 @@ public interface IotDeviceDataService { * @param deviceId 设备编号 * @return 设备属性最新数据 */ - List getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceId); + List getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceId); /** * 获得设备属性历史数据 @@ -39,5 +39,5 @@ public interface IotDeviceDataService { * @param deviceDataReqVO 设备属性历史数据 Request VO * @return 设备属性历史数据 */ - PageResult> getDevicePropertiesHistoryData(@Valid IotDeviceDataReqVO deviceDataReqVO); + PageResult> getHistoryDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO); } \ 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/IotDeviceDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java index 8f68989c9..7d10977f9 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java @@ -1,18 +1,20 @@ package cn.iocoder.yudao.module.iot.service.device; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONObject; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper; +import cn.iocoder.yudao.module.iot.enums.IotConstants; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import cn.iocoder.yudao.module.iot.service.tdengine.IotThingModelMessageService; -import cn.iocoder.yudao.module.iot.service.tdengine.TdEngineQueryService; import cn.iocoder.yudao.module.iot.service.thinkmodelfunction.IotThinkModelFunctionService; import jakarta.annotation.Resource; import jakarta.validation.Valid; @@ -40,7 +42,7 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { @Resource private IotThinkModelFunctionService thinkModelFunctionService; @Resource - private TdEngineQueryService tdEngineQueryService; + private TdEngineDMLMapper tdEngineDMLMapper; @Resource private DeviceDataRedisDAO deviceDataRedisDAO; @@ -66,7 +68,7 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { } @Override - public List getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceDataReqVO) { + public List getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { List list = new ArrayList<>(); // 1. 获取设备信息 IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId()); @@ -106,7 +108,7 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { } @Override - public PageResult> getDevicePropertiesHistoryData(IotDeviceDataReqVO deviceDataReqVO) { + public PageResult> getHistoryDeviceProperties(IotDeviceDataPageReqVO deviceDataReqVO) { PageResult> pageResult = new PageResult<>(); // 1. 获取设备信息 IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId()); @@ -121,17 +123,17 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { params.put("rows", deviceDataReqVO.getPageSize()); params.put("page", (deviceDataReqVO.getPageNo() - 1) * deviceDataReqVO.getPageSize()); selectVisualDO.setParams(params); - pageResult.setList(tdEngineQueryService.getHistoryData(selectVisualDO)); - pageResult.setTotal(tdEngineQueryService.getHistoryCount(selectVisualDO)); + pageResult.setList(tdEngineDMLMapper.selectHistoryDataList(selectVisualDO)); + pageResult.setTotal(tdEngineDMLMapper.selectHistoryCount(selectVisualDO)); return pageResult; } private String getDatabaseName() { - return url.substring(url.lastIndexOf("/") + 1); + return StrUtil.subAfter(url, "/", true); } private static String getDeviceTableName(String productKey, String deviceName) { - return String.format("device_%s_%s", productKey.toLowerCase(), deviceName.toLowerCase()); + return String.format(IotConstants.DEVICE_TABLE_NAME_FORMAT, productKey, deviceName); } -} +} \ 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/IotDeviceServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java index 0ec737a30..58918c130 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 @@ -19,7 +19,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import java.security.SecureRandom; import java.time.LocalDateTime; +import java.util.Base64; import java.util.Objects; import java.util.UUID; @@ -137,10 +139,13 @@ public class IotDeviceServiceImpl implements IotDeviceService { * @return 生成的 MQTT Password */ private String generateMqttPassword() { - // TODO @haohao:【后续优化】在实际应用中,建议使用更安全的方法生成 MQTT Password,如加密或哈希 - return UUID.randomUUID().toString(); + SecureRandom secureRandom = new SecureRandom(); + byte[] passwordBytes = new byte[32]; // 256 位的随机数 + secureRandom.nextBytes(passwordBytes); + return Base64.getUrlEncoder().withoutPadding().encodeToString(passwordBytes); } + /** * 生成唯一的 DeviceName * @@ -214,30 +219,28 @@ public class IotDeviceServiceImpl implements IotDeviceService { @Override public void updateDeviceStatus(IotDeviceStatusUpdateReqVO updateReqVO) { // 1. 校验存在 - // TODO @haohao:这里的 iotDeviceDO => device。一个是去掉 iot,一个是去掉 DO 后缀。这样,简洁一点。 - IotDeviceDO iotDeviceDO = validateDeviceExists(updateReqVO.getId()); + IotDeviceDO device = validateDeviceExists(updateReqVO.getId()); // 2.1 更新状态和更新时间 - IotDeviceDO updateObj = BeanUtils.toBean(updateReqVO, IotDeviceDO.class); - // TODO @haohao:下面几个状态的处理,可以考虑 if else if。这样,看起来会有层次感哈 - // 2.2.1 以前是未激活,现在是上线,设置设备激活时间 - // TODO @haohao:这里可以使用 ObjectUtils.equalsAny 类似这种哈。 - if (Objects.equals(iotDeviceDO.getStatus(), IotDeviceStatusEnum.INACTIVE.getStatus()) - && Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { - updateObj.setActiveTime(LocalDateTime.now()); - } - // 2.2.2 如果是上线,设置上线时间 - if (Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { - updateObj.setLastOnlineTime(LocalDateTime.now()); - } - // 2.2.3 如果是离线,设置离线时间 - if (Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.OFFLINE.getStatus())) { - updateObj.setLastOfflineTime(LocalDateTime.now()); + IotDeviceDO updateDevice = BeanUtils.toBean(updateReqVO, IotDeviceDO.class); + // 2.2 更新状态相关时间 + if (Objects.equals(device.getStatus(), IotDeviceStatusEnum.INACTIVE.getStatus()) + && Objects.equals(updateDevice.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { + // 从未激活到在线,设置激活时间和最后上线时间 + updateDevice.setActiveTime(LocalDateTime.now()); + updateDevice.setLastOnlineTime(LocalDateTime.now()); + } else if (Objects.equals(updateDevice.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { + // 如果是上线,设置最后上线时间 + updateDevice.setLastOnlineTime(LocalDateTime.now()); + } else if (Objects.equals(updateDevice.getStatus(), IotDeviceStatusEnum.OFFLINE.getStatus())) { + // 如果是离线,设置最后离线时间 + updateDevice.setLastOfflineTime(LocalDateTime.now()); } + // 2.3 设置状态更新时间 - updateObj.setStatusLastUpdateTime(LocalDateTime.now()); + updateDevice.setStatusLastUpdateTime(LocalDateTime.now()); // 2.4 更新到数据库 - deviceMapper.updateById(updateObj); + deviceMapper.updateById(updateDevice); } @Override diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java index 7c88b83aa..8aec32f32 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java @@ -15,4 +15,4 @@ public interface IotSuperTableService { * 创建超级表数据模型 */ void createSuperTableDataModel(IotProductDO product, List functionList); -} +} \ 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/tdengine/IotSuperTableServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableServiceImpl.java index 3be324c4e..20989181e 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableServiceImpl.java @@ -9,6 +9,8 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -26,7 +28,7 @@ import java.util.stream.Collectors; public class IotSuperTableServiceImpl implements IotSuperTableService { @Resource - private TdEngineSuperTableService tdEngineSuperTableService; + private TdEngineDDLMapper tdEngineDDLMapper; @Value("${spring.datasource.dynamic.datasource.tdengine.url}") private String url; @@ -42,9 +44,10 @@ public class IotSuperTableServiceImpl implements IotSuperTableService { String superTableName = getSuperTableName(product.getDeviceType(), product.getProductKey()); String databaseName = getDatabaseName(); - Integer tableExists = tdEngineSuperTableService.checkSuperTableExists(new TdTableDO(databaseName, superTableName)); - if (tableExists != null && tableExists > 0) { + List> results = tdEngineDDLMapper.showSuperTables(new TdTableDO(databaseName, superTableName)); + int tableExists = results == null || results.isEmpty() ? 0 : results.size(); + if (tableExists > 0) { updateSuperTable(thingModel, product.getDeviceType()); } else { createSuperTable(thingModel, product.getDeviceType()); @@ -76,7 +79,7 @@ public class IotSuperTableServiceImpl implements IotSuperTableService { String databaseName = getDatabaseName(); // 创建超级表 - tdEngineSuperTableService.createSuperTable(new TdTableDO(databaseName, superTableName, schemaFields, tagsFields)); + tdEngineDDLMapper.createSuperTable(new TdTableDO(databaseName, superTableName, schemaFields, tagsFields)); } /** @@ -98,7 +101,7 @@ public class IotSuperTableServiceImpl implements IotSuperTableService { * 获取表的字段信息 */ private List getTableFields(String tableName) { - List> tableDescription = tdEngineSuperTableService.describeSuperTable(new TdTableDO(getDatabaseName(), tableName)); + List> tableDescription = tdEngineDDLMapper.describeSuperTable(new TdTableDO(getDatabaseName(), tableName)); if (CollUtil.isEmpty(tableDescription)) { return Collections.emptyList(); } @@ -127,32 +130,38 @@ public class IotSuperTableServiceImpl implements IotSuperTableService { // 添加新增字段 if (CollUtil.isNotEmpty(addFields)) { - tdEngineSuperTableService.addColumnsForSuperTable(TdTableDO.builder() - .dataBaseName(databaseName) - .superTableName(tableName) - .columns(addFields) - .build()); + for (TdFieldDO addField : addFields) { + tdEngineDDLMapper.addColumnForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .column(addField) + .build()); + } } // 删除旧字段 if (CollUtil.isNotEmpty(dropFields)) { - tdEngineSuperTableService.dropColumnsForSuperTable(TdTableDO.builder() - .dataBaseName(databaseName) - .superTableName(tableName) - .columns(dropFields) - .build()); + for (TdFieldDO dropField : dropFields) { + tdEngineDDLMapper.dropColumnForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .column(dropField) + .build()); + } } // 修改字段(先删除再添加) if (CollUtil.isNotEmpty(modifyFields)) { - tdEngineSuperTableService.dropColumnsForSuperTable(TdTableDO.builder() - .dataBaseName(databaseName) - .superTableName(tableName) - .columns(modifyFields) - .build()); - tdEngineSuperTableService.addColumnsForSuperTable(TdTableDO.builder() - .dataBaseName(databaseName) - .superTableName(tableName) - .columns(addFields) - .build()); + for (TdFieldDO modifyField : modifyFields) { + tdEngineDDLMapper.dropColumnForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .column(modifyField) + .build()); + tdEngineDDLMapper.addColumnForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .column(modifyField) + .build()); + } } } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java index 280b32d9a..92a30ebb0 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.iot.service.tdengine; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceStatusUpdateReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; @@ -11,6 +13,9 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper; +import cn.iocoder.yudao.module.iot.enums.IotConstants; import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; @@ -30,6 +35,14 @@ import java.util.stream.Collectors; @Service public class IotThingModelMessageServiceImpl implements IotThingModelMessageService { + private static final String TAG_NOTE = "TAG"; + private static final String NOTE = "note"; + private static final String TIME = "time"; + private static final String DEVICE_KEY = "device_key"; + private static final String DEVICE_NAME = "device_name"; + private static final String PRODUCT_KEY = "product_key"; + private static final String DEVICE_TYPE = "device_type"; + @Value("${spring.datasource.dynamic.datasource.tdengine.url}") private String url; @@ -38,11 +51,9 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @Resource private IotDeviceService iotDeviceService; @Resource - private TdEngineTableService tdEngineTableService; + private TdEngineDDLMapper tdEngineDDLMapper; @Resource - private TdEngineSuperTableService tdEngineSuperTableService; - @Resource - private TdEngineDataWriterService tdEngineDataWriterService; + private TdEngineDMLMapper tdEngineDMLMapper; @Resource private DeviceDataRedisDAO deviceDataRedisDAO; @@ -51,62 +62,64 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @Override @TenantIgnore public void saveThingModelMessage(IotDeviceDO device, ThingModelMessage thingModelMessage) { - // 判断设备状态,如果为未激活状态,创建数据表 + // 1. 判断设备状态,如果为未激活状态,创建数据表并更新设备状态 if (IotDeviceStatusEnum.INACTIVE.getStatus().equals(device.getStatus())) { - // 创建设备数据表 createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); - // 更新设备状态 - // TODO @haohao:下面可以考虑,链式调用。iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO().setid().setstatus()) - IotDeviceStatusUpdateReqVO updateReqVO = new IotDeviceStatusUpdateReqVO(); - updateReqVO.setId(device.getId()); - updateReqVO.setStatus(IotDeviceStatusEnum.ONLINE.getStatus()); - iotDeviceService.updateDeviceStatus(updateReqVO); + iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO() + .setId(device.getId()) + .setStatus(IotDeviceStatusEnum.ONLINE.getStatus())); } - // TODO @haohao:这个变量,可以和 “过滤并收集有效的属性字段” 那块,因为关联度高一点。 - // 获取设备属性 + // 2. 获取设备属性并进行物模型校验,过滤非物模型属性 Map params = thingModelMessage.dataToMap(); - - // 物模型校验,过滤非物模型属性 - List functionList = iotThinkModelFunctionService - .getThinkModelFunctionListByProductKey(thingModelMessage.getProductKey()) - .stream() - .filter(function -> IotProductFunctionTypeEnum.PROPERTY.getType().equals(function.getType())) - .toList(); + List functionList = getValidFunctionList(thingModelMessage.getProductKey()); if (functionList.isEmpty()) { return; } - // 获取属性标识符集合 - // TODO @haohao:这个变量,可以和 “过滤并收集有效的属性字段” 那块,因为关联度高一点。另外,可以使用 CollectionUtils。convertSet - Set propertyIdentifiers = functionList.stream() - .map(IotThinkModelFunctionDO::getIdentifier) - .collect(Collectors.toSet()); + // 3. 过滤并收集有效的属性字段,缓存设备属性 + List schemaFieldValues = filterAndCollectValidFields(params, functionList, device, thingModelMessage.getTime()); + if (schemaFieldValues.size() == 1) { // 仅有时间字段,无需保存 + return; + } + + // 4. 构建并保存设备属性数据 + tdEngineDMLMapper.insertData(TdTableDO.builder() + .dataBaseName(getDatabaseName()) + .tableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())) + .columns(schemaFieldValues) + .build()); + } + + private List getValidFunctionList(String productKey) { + return iotThinkModelFunctionService + .getThinkModelFunctionListByProductKey(productKey) + .stream() + .filter(function -> IotProductFunctionTypeEnum.PROPERTY.getType().equals(function.getType())) + .toList(); + } + + private List filterAndCollectValidFields(Map params, List functionList, IotDeviceDO device, Long time) { + // 1. 获取属性标识符集合 + Set propertyIdentifiers = CollectionUtils.convertSet(functionList, IotThinkModelFunctionDO::getIdentifier); + + // 2. 构建属性标识符和属性的映射 Map functionMap = functionList.stream() .collect(Collectors.toMap(IotThinkModelFunctionDO::getIdentifier, function -> function)); - // 过滤并收集有效的属性字段 + // 3. 过滤并收集有效的属性字段 List schemaFieldValues = new ArrayList<>(); - schemaFieldValues.add(new TdFieldDO("time", thingModelMessage.getTime())); + schemaFieldValues.add(new TdFieldDO(TIME, time)); params.forEach((key, val) -> { if (propertyIdentifiers.contains(key)) { schemaFieldValues.add(new TdFieldDO(key.toLowerCase(), val)); // 缓存设备属性 // TODO @haohao:这个缓存的写入,可以使用的时候 cache 么?被动读 - setDeviceDataCache(device, functionMap.get(key), val, thingModelMessage.getTime()); + setDeviceDataCache(device, functionMap.get(key), val, time); } }); - // TODO @haohao:疑问,为什么 1 不继续哈? - if (schemaFieldValues.size() == 1) { - return; - } - - // 构建并保存设备属性数据 - tdEngineDataWriterService.insertData(TdTableDO.builder().build() - .setDataBaseName(getDatabaseName()) - .setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())) - .setColumns(schemaFieldValues)); + return schemaFieldValues; } /** @@ -132,7 +145,6 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ deviceDataRedisDAO.set(deviceData); } - // TODO @haohao:实现没问题哈。这个方法的空行有点多,逻辑分块上没这么明显。看看能不能改下。 /** * 创建设备数据表 * @@ -142,36 +154,37 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ * @param deviceKey 设备 Key */ private void createDeviceTable(Integer deviceType, String productKey, String deviceName, String deviceKey) { + // 1. 获取超级表名和数据库名 String superTableName = getProductPropertySTableName(deviceType, productKey); String dataBaseName = getDatabaseName(); - List> maps = tdEngineSuperTableService.describeSuperTable(new TdTableDO(dataBaseName, superTableName)); + // 2. 获取超级表的结构信息 + List> maps = tdEngineDDLMapper.describeSuperTable(new TdTableDO(dataBaseName, superTableName)); List tagsFieldValues = new ArrayList<>(); - if (maps != null) { - // TODO @haohao:一些字符串,是不是可以枚举起来哈。 - // TODO @haohao:这种过滤的,常用的,可以考虑用 CollectionUtils.filterList。一些常用的 stream 操作,适合封装哈 - List> taggedNotesList = maps.stream() - .filter(map -> "TAG".equals(map.get("note"))) - .toList(); + // 2.1 过滤出 TAG 类型的字段 + List> taggedNotesList = CollectionUtils.filterList(maps, map -> TAG_NOTE.equals(map.get(NOTE))); + + // 2.2 解析字段信息 tagsFieldValues = FieldParser.parse(taggedNotesList.stream() .map(map -> List.of(map.get("field"), map.get("type"), map.get("length"))) .collect(Collectors.toList())); + // 2.3 设置 TAG 字段的值 for (TdFieldDO tagsFieldValue : tagsFieldValues) { switch (tagsFieldValue.getFieldName()) { - case "product_key" -> tagsFieldValue.setFieldValue(productKey); - case "device_key" -> tagsFieldValue.setFieldValue(deviceKey); - case "device_name" -> tagsFieldValue.setFieldValue(deviceName); - case "device_type" -> tagsFieldValue.setFieldValue(deviceType); + case PRODUCT_KEY -> tagsFieldValue.setFieldValue(productKey); + case DEVICE_KEY -> tagsFieldValue.setFieldValue(deviceKey); + case DEVICE_NAME -> tagsFieldValue.setFieldValue(deviceName); + case DEVICE_TYPE -> tagsFieldValue.setFieldValue(deviceType); } } } - // 创建设备数据表 + // 3. 创建设备数据表 String tableName = getDeviceTableName(productKey, deviceName); - tdEngineTableService.createTable(TdTableDO.builder().build() + tdEngineDDLMapper.createTable(TdTableDO.builder().build() .setDataBaseName(dataBaseName) .setSuperTableName(superTableName) .setTableName(tableName) @@ -184,8 +197,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ * @return 数据库名称 */ private String getDatabaseName() { - // TODO @haohao:可以使用 StrUtil.subAftetLast 这种方法 - return url.substring(url.lastIndexOf("/") + 1); + return StrUtil.subAfter(url, "/", true); } /** @@ -198,9 +210,9 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ private static String getProductPropertySTableName(Integer deviceType, String productKey) { // TODO @haohao:枚举下,会好点哈。 return switch (deviceType) { - case 1 -> String.format("gateway_sub_%s", productKey).toLowerCase(); - case 2 -> String.format("gateway_%s", productKey).toLowerCase(); - default -> String.format("device_%s", productKey).toLowerCase(); + case 1 -> String.format(IotConstants.GATEWAY_SUB_STABLE_NAME_FORMAT, productKey).toLowerCase(); + case 2 -> String.format(IotConstants.GATEWAY_STABLE_NAME_FORMAT, productKey).toLowerCase(); + default -> String.format(IotConstants.DEVICE_STABLE_NAME_FORMAT, productKey).toLowerCase(); }; } @@ -212,7 +224,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ * @return 设备表名 */ private static String getDeviceTableName(String productKey, String deviceName) { - return String.format("device_%s_%s", productKey.toLowerCase(), deviceName.toLowerCase()); + return String.format(IotConstants.DEVICE_TABLE_NAME_FORMAT, productKey.toLowerCase(), deviceName.toLowerCase()); } } \ 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/tdengine/TdEngineDataWriterService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterService.java deleted file mode 100644 index 0995b0797..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterService.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; - -/** - * TD 引擎的数据写入 Service 接口 - */ -public interface TdEngineDataWriterService { - - /** - * 插入数据 - 指定列插入数据 - * - * @param table 数据 - * dataBaseName 数据库名 - * tableName 表名 - * columns 列 - */ - void insertData(TdTableDO table); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java deleted file mode 100644 index f4dd2c8fd..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDataWriterMapper; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Service; - -/** - * TD 引擎的数据写入 Service 实现类 - */ -@Service -public class TdEngineDataWriterServiceImpl implements TdEngineDataWriterService { - - @Resource - private TdEngineDataWriterMapper tdEngineDataWriterMapper; - - @Override - public void insertData(TdTableDO table) { - tdEngineDataWriterMapper.insertData(table); - } -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java deleted file mode 100644 index d895262cc..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -/** - * TD 引擎的数据库 Service 接口 - */ -public interface TdEngineDatabaseService { - - /** - * 创建数据库 - * - * @param dataBaseName 数据库名称 - */ - void createDatabase(String dataBaseName); -} \ 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/tdengine/TdEngineDatabaseServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseServiceImpl.java deleted file mode 100644 index c880db8a9..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseServiceImpl.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDatabaseMapper; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * TD 引擎的数据库 Service 实现类 - */ -@Service -@Slf4j -public class TdEngineDatabaseServiceImpl implements TdEngineDatabaseService { - - @Resource - private TdEngineDatabaseMapper tdEngineDatabaseMapper; - - @Override - public void createDatabase(String dataBaseName) { - tdEngineDatabaseMapper.createDatabase(dataBaseName); - } -} \ 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/tdengine/TdEngineQueryService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryService.java deleted file mode 100644 index 8d07b4334..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryService.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; - -import java.util.List; -import java.util.Map; - -/** - * TD 引擎的查询 Service 接口 - */ -public interface TdEngineQueryService { - - /** - * 获取历史数据 - * - * @param selectVisualDO 查询条件 - * @return 历史数据列表 - */ - List> getHistoryData(SelectVisualDO selectVisualDO); - - /** - * 获取历史数据条数 - * - * @param selectVisualDO 查询条件 - * @return 数据条数 - */ - Long getHistoryCount(SelectVisualDO selectVisualDO); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java deleted file mode 100644 index 672a58640..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineQueryMapper; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Map; - -@Service -public class TdEngineQueryServiceImpl implements TdEngineQueryService { - - @Resource - private TdEngineQueryMapper tdEngineQueryMapper; - - @Override - public List> getHistoryData(SelectVisualDO selectVisualDO) { - return tdEngineQueryMapper.getHistoryData(selectVisualDO); - } - - @Override - public Long getHistoryCount(SelectVisualDO selectVisualDO) { - return tdEngineQueryMapper.getHistoryCount(selectVisualDO); - } -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java deleted file mode 100644 index df6290a98..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java +++ /dev/null @@ -1,123 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; - -import java.util.List; -import java.util.Map; - -/** - * TD 引擎的超级表 Service 接口 - */ -public interface TdEngineSuperTableService { - - /** - * 创建超级表 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * columns 列信息 - * tags 标签信息 - */ - void createSuperTable(TdTableDO superTable); - - /** - * 查看超级表 - 显示当前数据库下的所有超级表信息 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - */ - - List> showSuperTables(TdTableDO superTable); - - /** - * 查看超级表 - 获取超级表的结构信息 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - */ - List> describeSuperTable(TdTableDO superTable); - - /** - * 修改超级表 - 增加列 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * column 列信息 - */ - void addColumnForSuperTable(TdTableDO superTable); - - /** - * 修改超级表 - 删除列 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * column 列信息 - */ - void dropColumnForSuperTable(TdTableDO superTable); - - /** - * 修改超级表 - 修改列宽 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * column 列信息 - */ - void modifyColumnWidthForSuperTable(TdTableDO superTable); - - - /** - * 修改超级表 - 为超级表添加标签 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * tag 标签信息 - */ - void addTagForSuperTable(TdTableDO superTable); - - /** - * 修改超级表 - 为超级表删除标签 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * tag 标签信息 - */ - void dropTagForSuperTable(TdTableDO superTable); - - /** - * 检查超级表是否存在 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * @return 超级表数量 - */ - Integer checkSuperTableExists(TdTableDO superTable); - - /** - * 为超级表添加列 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * columns 列信息 - */ - void addColumnsForSuperTable(TdTableDO superTable); - - /** - * 为超级表删除列 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * columns 列信息 - */ - void dropColumnsForSuperTable(TdTableDO superTable); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java deleted file mode 100644 index 60436e7bd..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java +++ /dev/null @@ -1,90 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineSuperTableMapper; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Map; - -/** - * TD 引擎的超级表 Service 实现类 - */ -@Slf4j -@Service -public class TdEngineSuperTableServiceImpl implements TdEngineSuperTableService { - - @Resource - private TdEngineSuperTableMapper tdEngineSuperTableMapper; - - @Override - public void createSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.createSuperTable(superTable); - } - - @Override - public List> showSuperTables(TdTableDO superTable) { - return tdEngineSuperTableMapper.showSuperTables(superTable); - } - - @Override - public List> describeSuperTable(TdTableDO superTable) { - return tdEngineSuperTableMapper.describeSuperTable(superTable); - } - - @Override - public void addColumnForSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.addColumnForSuperTable(superTable); - } - - @Override - public void dropColumnForSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.dropColumnForSuperTable(superTable); - } - - @Override - public void modifyColumnWidthForSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.modifyColumnWidthForSuperTable(superTable); - } - - @Override - public void addTagForSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.addTagForSuperTable(superTable); - } - - @Override - public void dropTagForSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.dropTagForSuperTable(superTable); - } - - @Override - public Integer checkSuperTableExists(TdTableDO superTable) { - List> results = tdEngineSuperTableMapper.showSuperTables(superTable); - return results == null || results.isEmpty() ? 0 : results.size(); - } - - @Override - public void addColumnsForSuperTable(TdTableDO superTable) { - for (TdFieldDO column : superTable.getColumns()) { - tdEngineSuperTableMapper.addColumnForSuperTable(TdTableDO.builder() - .dataBaseName(superTable.getDataBaseName()) - .superTableName(superTable.getSuperTableName()) - .column(column) - .build()); - } - } - - @Override - public void dropColumnsForSuperTable(TdTableDO superTable) { - for (TdFieldDO column : superTable.getColumns()) { - tdEngineSuperTableMapper.dropColumnForSuperTable(TdTableDO.builder() - .dataBaseName(superTable.getDataBaseName()) - .superTableName(superTable.getSuperTableName()) - .column(column) - .build()); - } - } -} \ 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/tdengine/TdEngineTableService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableService.java deleted file mode 100644 index 078159784..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableService.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; - -/** - * TD 引擎的表 Service 接口 - */ -public interface TdEngineTableService { - - /** - * 创建表 - 创建超级表的子表 - * - * @param table 表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * tableName 子表名称 - * tags TAG 字段 - */ - void createTable(TdTableDO table); - -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java deleted file mode 100644 index cdca47888..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineTableMapper; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * TD 引擎的表 Service 实现类 - */ -@Slf4j -@Service -public class TdEngineTableServiceImpl implements TdEngineTableService { - - @Resource - private TdEngineTableMapper tdEngineTableMapper; - - @Override - public void createTable(TdTableDO table) { - tdEngineTableMapper.createTable(table); - } -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDDLMapper.xml similarity index 70% rename from yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml rename to yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDDLMapper.xml index 37cf71910..091b77f64 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDDLMapper.xml @@ -2,7 +2,12 @@ - + + + + + CREATE DATABASE IF NOT EXISTS ${dataBaseName} + @@ -68,4 +73,29 @@ ALTER STABLE ${dataBaseName}.${superTableName} DROP TAG ${tag.fieldName} - + + + CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} + USING ${dataBaseName}.${superTableName} + TAGS + + #{item.fieldValue} + + + + + + CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} + USING ${dataBaseName}.${superTableName} + + #{item.fieldName} + + TAGS + + #{item.fieldValue} + + + + \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDMLMapper.xml similarity index 68% rename from yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml rename to yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDMLMapper.xml index f4361bc67..0443a826b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDMLMapper.xml @@ -2,7 +2,21 @@ - + + + + + INSERT INTO ${dataBaseName}.${tableName} + + ${item.fieldName} + + VALUES + + #{item.fieldValue} + + - SELECT COUNT(0) AS count FROM ${dataBaseName}.${tableName} @@ -20,14 +34,14 @@ - + SELECT LAST(time), * FROM ${tableName} WHERE device_id = #{deviceId} - SELECT LAST(*) FROM ${dataBaseName}.${stableName} @@ -35,7 +49,7 @@ - SELECT ${fieldName} AS data, time FROM ${dataBaseName}.${tableName} @@ -46,14 +60,14 @@ - SELECT ${fieldName}, time FROM ${dataBaseName}.${tableName} - SELECT ${aggregate}(${fieldName}) FROM ${dataBaseName}.${tableName} @@ -62,11 +76,11 @@ - + SELECT COUNT(time) FROM ${dataBaseName}.${tableName} WHERE time BETWEEN #{startTime} AND #{endTime} AND ${fieldName} IS NOT NULL - + \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml deleted file mode 100644 index dd38cd08e..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - INSERT INTO ${dataBaseName}.${tableName} - - ${item.fieldName} - - VALUES - - #{item.fieldValue} - - - - \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml deleted file mode 100644 index 919c301f7..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - CREATE DATABASE IF NOT EXISTS ${dataBaseName} - - - \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml deleted file mode 100644 index 867ef8f43..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} - USING ${dataBaseName}.${superTableName} - TAGS - - #{item.fieldValue} - - - - - - CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} - USING ${dataBaseName}.${superTableName} - - #{item.fieldName} - - TAGS - - #{item.fieldValue} - - - - \ No newline at end of file From ce919d12d1b079ace85c70004bd6553053b76667 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 5 Dec 2024 21:45:48 +0800 Subject: [PATCH 013/228] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91IoT=EF=BC=9Atdengine=20=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/controller/admin/device/IotDeviceDataController.java | 2 ++ .../yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java | 1 - .../module/iot/service/device/IotDeviceDataServiceImpl.java | 2 +- .../module/iot/service/device/IotDeviceServiceImpl.java | 2 +- .../service/tdengine/IotThingModelMessageServiceImpl.java | 5 +---- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java index 72fdda8c8..77bc78c66 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java @@ -31,6 +31,7 @@ public class IotDeviceDataController { @Resource private IotDeviceDataService deviceDataService; + // TODO @浩浩:这里的 /latest-list,包括方法名。 @GetMapping("/latest") @Operation(summary = "获取设备属性最新数据") public CommonResult> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { @@ -38,6 +39,7 @@ public class IotDeviceDataController { return success(BeanUtils.toBean(list, IotDeviceDataRespVO.class)); } + // TODO @浩浩:这里的 /history-page 包括方法名。 @GetMapping("/history") @Operation(summary = "获取设备属性历史数据") public CommonResult> getHistoryDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java index 640255940..3d7aa84dd 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.iot.dal.tdengine; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java index 7d10977f9..d68287cd4 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java @@ -133,7 +133,7 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { } private static String getDeviceTableName(String productKey, String deviceName) { - return String.format(IotConstants.DEVICE_TABLE_NAME_FORMAT, productKey, deviceName); + return String.format(IotConstants.DEVICE_TABLE_NAME_FORMAT, productKey, deviceName); } } \ 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/IotDeviceServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java index 58918c130..bb302a22f 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 @@ -139,13 +139,13 @@ public class IotDeviceServiceImpl implements IotDeviceService { * @return 生成的 MQTT Password */ private String generateMqttPassword() { + // TODO @浩浩:这里的 StrUtil 随机字符串? SecureRandom secureRandom = new SecureRandom(); byte[] passwordBytes = new byte[32]; // 256 位的随机数 secureRandom.nextBytes(passwordBytes); return Base64.getUrlEncoder().withoutPadding().encodeToString(passwordBytes); } - /** * 生成唯一的 DeviceName * diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java index 92a30ebb0..9ffb47715 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java @@ -66,8 +66,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ if (IotDeviceStatusEnum.INACTIVE.getStatus().equals(device.getStatus())) { createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO() - .setId(device.getId()) - .setStatus(IotDeviceStatusEnum.ONLINE.getStatus())); + .setId(device.getId()).setStatus(IotDeviceStatusEnum.ONLINE.getStatus())); } // 2. 获取设备属性并进行物模型校验,过滤非物模型属性 @@ -77,7 +76,6 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ return; } - // 3. 过滤并收集有效的属性字段,缓存设备属性 List schemaFieldValues = filterAndCollectValidFields(params, functionList, device, thingModelMessage.getTime()); if (schemaFieldValues.size() == 1) { // 仅有时间字段,无需保存 @@ -165,7 +163,6 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ // 2.1 过滤出 TAG 类型的字段 List> taggedNotesList = CollectionUtils.filterList(maps, map -> TAG_NOTE.equals(map.get(NOTE))); - // 2.2 解析字段信息 tagsFieldValues = FieldParser.parse(taggedNotesList.stream() .map(map -> List.of(map.get("field"), map.get("type"), map.get("length"))) From 3a2c691af085c4e649373961e827627b8fcfaf9a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 7 Dec 2024 16:42:56 +0800 Subject: [PATCH 014/228] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E3=80=91IoT=EF=BC=9A=E4=BA=A7=E5=93=81=E5=88=86?= =?UTF-8?q?=E7=B1=BB=E7=9A=84=E7=BB=B4=E6=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/iot/enums/ErrorCodeConstants.java | 9 ++- .../product/IotProductCategoryController.java | 72 +++++++++++++++++++ .../admin/product/vo/IotProductSaveReqVO.java | 6 +- .../category/IotProductCategoryPageReqVO.java | 27 +++++++ .../vo/category/IotProductCategoryRespVO.java | 33 +++++++++ .../category/IotProductCategorySaveReqVO.java | 29 ++++++++ .../product/IotProductCategoryDO.java | 48 +++++++++++++ .../product/IotProductCategoryMapper.java | 25 +++++++ .../product/IotProductCategoryService.java | 54 ++++++++++++++ .../IotProductCategoryServiceImpl.java | 70 ++++++++++++++++++ 10 files changed, 369 insertions(+), 4 deletions(-) create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryPageReqVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryRespVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategorySaveReqVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductCategoryDO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductCategoryMapper.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryService.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryServiceImpl.java 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 be9d28ecb..1e947e633 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 @@ -9,20 +9,20 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; */ public interface ErrorCodeConstants { - // ========== IoT 产品相关 1-050-001-000 ============ + // ========== 产品相关 1-050-001-000 ============ ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_050_001_000, "产品不存在"); ErrorCode PRODUCT_IDENTIFICATION_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在"); ErrorCode PRODUCT_STATUS_NOT_DELETE = new ErrorCode(1_050_001_002, "产品状是发布状态,不允许删除"); ErrorCode PRODUCT_STATUS_NOT_ALLOW_FUNCTION = new ErrorCode(1_050_001_003, "产品状是发布状态,不允许操作物模型"); - // ========== IoT 产品物模型 1-050-002-000 ============ + // ========== 产品物模型 1-050-002-000 ============ ErrorCode THINK_MODEL_FUNCTION_NOT_EXISTS = new ErrorCode(1_050_002_000, "产品物模型不存在"); ErrorCode THINK_MODEL_FUNCTION_EXISTS_BY_PRODUCT_KEY = new ErrorCode(1_050_002_001, "ProductKey 对应的产品物模型已存在"); ErrorCode THINK_MODEL_FUNCTION_IDENTIFIER_EXISTS = new ErrorCode(1_050_002_002, "存在重复的功能标识符。"); ErrorCode THINK_MODEL_FUNCTION_NAME_EXISTS = new ErrorCode(1_050_002_003, "存在重复的功能名称。"); ErrorCode THINK_MODEL_FUNCTION_IDENTIFIER_INVALID = new ErrorCode(1_050_002_003, "产品物模型标识无效"); - // ========== IoT 设备 1-050-003-000 ============ + // ========== 设备 1-050-003-000 ============ ErrorCode DEVICE_NOT_EXISTS = new ErrorCode(1_050_003_000, "设备不存在"); ErrorCode DEVICE_NAME_EXISTS = new ErrorCode(1_050_003_001, "设备名称在同一产品下必须唯一"); ErrorCode DEVICE_HAS_CHILDREN = new ErrorCode(1_050_003_002, "有子设备,不允许删除"); @@ -30,4 +30,7 @@ public interface ErrorCodeConstants { ErrorCode DEVICE_PRODUCT_CANNOT_BE_MODIFIED = new ErrorCode(1_050_003_004, "产品不能修改"); ErrorCode DEVICE_INVALID_DEVICE_STATUS = new ErrorCode(1_050_003_005, "无效的设备状态"); + // ========== 产品分类 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/controller/admin/product/IotProductCategoryController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java new file mode 100644 index 000000000..b365ddea1 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.iot.controller.admin.product; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +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.product.vo.category.IotProductCategoryPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategoryRespVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategorySaveReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO; +import cn.iocoder.yudao.module.iot.service.product.IotProductCategoryService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - IoT 产品分类") +@RestController +@RequestMapping("/iot/product-category") +@Validated +public class IotProductCategoryController { + + @Resource + private IotProductCategoryService productCategoryService; + + @PostMapping("/create") + @Operation(summary = "创建IoT 产品分类") + @PreAuthorize("@ss.hasPermission('iot:product-category:create')") + public CommonResult createProductCategory(@Valid @RequestBody IotProductCategorySaveReqVO createReqVO) { + return success(productCategoryService.createProductCategory(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新IoT 产品分类") + @PreAuthorize("@ss.hasPermission('iot:product-category:update')") + public CommonResult updateProductCategory(@Valid @RequestBody IotProductCategorySaveReqVO updateReqVO) { + productCategoryService.updateProductCategory(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除IoT 产品分类") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('iot:product-category:delete')") + public CommonResult deleteProductCategory(@RequestParam("id") Long id) { + productCategoryService.deleteProductCategory(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得IoT 产品分类") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('iot:product-category:query')") + public CommonResult getProductCategory(@RequestParam("id") Long id) { + IotProductCategoryDO productCategory = productCategoryService.getProductCategory(id); + return success(BeanUtils.toBean(productCategory, IotProductCategoryRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得IoT 产品分类分页") + @PreAuthorize("@ss.hasPermission('iot:product-category:query')") + public CommonResult> getProductCategoryPage(@Valid IotProductCategoryPageReqVO pageReqVO) { + PageResult pageResult = productCategoryService.getProductCategoryPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, IotProductCategoryRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java index 254b6b9da..757750544 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java @@ -14,9 +14,13 @@ public class IotProductSaveReqVO { @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.AUTO, example = "1") private Long id; - @Schema(description = "产品Key", requiredMode = Schema.RequiredMode.AUTO, example = "12345abc") + @Schema(description = "产品 Key", requiredMode = Schema.RequiredMode.AUTO, example = "12345abc") private String productKey; + // TODO 芋艿:品类 + + // TODO 芋艿:【待确定】保活时长、产品图标、产品图片 + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "温湿度") @NotEmpty(message = "产品名称不能为空") private String name; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryPageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryPageReqVO.java new file mode 100644 index 000000000..90d338a89 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryPageReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.category; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - IoT 产品分类分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class IotProductCategoryPageReqVO extends PageParam { + + @Schema(description = "分类名字", example = "王五") + private String name; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryRespVO.java new file mode 100644 index 000000000..d684b0215 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryRespVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.category; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - IoT 产品分类 Response VO") +@Data +public class IotProductCategoryRespVO { + + @Schema(description = "分类 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "25284") + private Long id; + + @Schema(description = "分类名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") + private String name; + + @Schema(description = "分类排序") + private Integer sort; + + @Schema(description = "分类状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "分类描述", example = "随便") + private String description; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategorySaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategorySaveReqVO.java new file mode 100644 index 000000000..a7b2fe427 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategorySaveReqVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.category; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - IoT 产品分类新增/修改 Request VO") +@Data +public class IotProductCategorySaveReqVO { + + @Schema(description = "分类 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "25284") + private Long id; + + @Schema(description = "分类名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") + @NotEmpty(message = "分类名字不能为空") + private String name; + + @Schema(description = "分类排序") + private Integer sort; + + @Schema(description = "分类状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "分类状态不能为空") + private Integer status; + + @Schema(description = "分类描述", example = "随便") + private String description; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductCategoryDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductCategoryDO.java new file mode 100644 index 000000000..a6510488c --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductCategoryDO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.product; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * IoT 产品分类 DO + * + * @author 芋道源码 + */ +@TableName("iot_product_category") +@KeySequence("iot_product_category_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class IotProductCategoryDO extends BaseDO { + + /** + * 分类 ID + */ + @TableId + private Long id; + /** + * 分类名字 + */ + private String name; + /** + * 分类排序 + */ + private Integer sort; + /** + * 分类状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 分类描述 + */ + private String description; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductCategoryMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductCategoryMapper.java new file mode 100644 index 000000000..845eded14 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductCategoryMapper.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.iot.dal.mysql.product; + +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.module.iot.controller.admin.product.vo.category.IotProductCategoryPageReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * IoT 产品分类 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface IotProductCategoryMapper extends BaseMapperX { + + default PageResult selectPage(IotProductCategoryPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(IotProductCategoryDO::getName, reqVO.getName()) + .betweenIfPresent(IotProductCategoryDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(IotProductCategoryDO::getId)); + } + +} \ 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/IotProductCategoryService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryService.java new file mode 100644 index 000000000..9830ec8b9 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryService.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.iot.service.product; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategoryPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategorySaveReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO; +import jakarta.validation.Valid; + +/** + * IoT 产品分类 Service 接口 + * + * @author 芋道源码 + */ +public interface IotProductCategoryService { + + /** + * 创建IoT 产品分类 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProductCategory(@Valid IotProductCategorySaveReqVO createReqVO); + + /** + * 更新IoT 产品分类 + * + * @param updateReqVO 更新信息 + */ + void updateProductCategory(@Valid IotProductCategorySaveReqVO updateReqVO); + + /** + * 删除IoT 产品分类 + * + * @param id 编号 + */ + void deleteProductCategory(Long id); + + /** + * 获得IoT 产品分类 + * + * @param id 编号 + * @return IoT 产品分类 + */ + IotProductCategoryDO getProductCategory(Long id); + + /** + * 获得IoT 产品分类分页 + * + * @param pageReqVO 分页查询 + * @return IoT 产品分类分页 + */ + PageResult getProductCategoryPage(IotProductCategoryPageReqVO pageReqVO); + +} \ 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/IotProductCategoryServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryServiceImpl.java new file mode 100644 index 000000000..579d27cfb --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryServiceImpl.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.iot.service.product; + +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.product.vo.category.IotProductCategoryPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategorySaveReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO; +import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductCategoryMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PRODUCT_CATEGORY_NOT_EXISTS; + +/** + * IoT 产品分类 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class IotProductCategoryServiceImpl implements IotProductCategoryService { + + @Resource + private IotProductCategoryMapper productCategoryMapper; + + @Override + public Long createProductCategory(IotProductCategorySaveReqVO createReqVO) { + // 插入 + IotProductCategoryDO productCategory = BeanUtils.toBean(createReqVO, IotProductCategoryDO.class); + productCategoryMapper.insert(productCategory); + // 返回 + return productCategory.getId(); + } + + @Override + public void updateProductCategory(IotProductCategorySaveReqVO updateReqVO) { + // 校验存在 + validateProductCategoryExists(updateReqVO.getId()); + // 更新 + IotProductCategoryDO updateObj = BeanUtils.toBean(updateReqVO, IotProductCategoryDO.class); + productCategoryMapper.updateById(updateObj); + } + + @Override + public void deleteProductCategory(Long id) { + // 校验存在 + validateProductCategoryExists(id); + // 删除 + productCategoryMapper.deleteById(id); + } + + private void validateProductCategoryExists(Long id) { + if (productCategoryMapper.selectById(id) == null) { + throw exception(PRODUCT_CATEGORY_NOT_EXISTS); + } + } + + @Override + public IotProductCategoryDO getProductCategory(Long id) { + return productCategoryMapper.selectById(id); + } + + @Override + public PageResult getProductCategoryPage(IotProductCategoryPageReqVO pageReqVO) { + return productCategoryMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file From 9b9fd30c90bfb88d1ad61ef314ffab73e18264ea Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 7 Dec 2024 18:50:31 +0800 Subject: [PATCH 015/228] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E3=80=91IoT=EF=BC=9A=E4=BA=A7=E5=93=81=E6=94=BE?= =?UTF-8?q?=E5=88=B0=20product=20=E5=AD=90=E7=9B=AE=E5=BD=95=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/product/IotProductController.java | 13 +++--- .../product/vo/IotProductSimpleRespVO.java | 16 ------- .../vo/{ => product}/IotProductPageReqVO.java | 2 +- .../vo/{ => product}/IotProductRespVO.java | 43 +++++++++++-------- .../vo/{ => product}/IotProductSaveReqVO.java | 28 +++++++----- .../dal/dataobject/product/IotProductDO.java | 15 +++++-- .../dal/mysql/product/IotProductMapper.java | 2 +- .../service/product/IotProductService.java | 4 +- .../product/IotProductServiceImpl.java | 5 +-- .../dal/dataobject/notify/PayNotifyLogDO.java | 2 +- .../dataobject/notify/PayNotifyTaskDO.java | 4 +- 11 files changed, 68 insertions(+), 66 deletions(-) delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSimpleRespVO.java rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/{ => product}/IotProductPageReqVO.java (88%) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/{ => product}/IotProductRespVO.java (85%) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/{ => product}/IotProductSaveReqVO.java (82%) 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 e7f41d91d..a4d111a99 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 @@ -3,10 +3,9 @@ package cn.iocoder.yudao.module.iot.controller.admin.product; import cn.iocoder.yudao.framework.common.pojo.CommonResult; 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.product.vo.IotProductPageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductRespVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSimpleRespVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductRespVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductSaveReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.service.product.IotProductService; import io.swagger.v3.oas.annotations.Operation; @@ -21,6 +20,7 @@ import org.springframework.web.bind.annotation.*; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @Tag(name = "管理后台 - IoT 产品") @RestController @@ -86,9 +86,10 @@ public class IotProductController { @GetMapping("/simple-list") @Operation(summary = "获得所有产品列表") @PreAuthorize("@ss.hasPermission('iot:product:query')") - public CommonResult> getSimpleProductList() { + public CommonResult> getSimpleProductList() { List list = productService.getProductList(); - return success(BeanUtils.toBean(list, IotProductSimpleRespVO.class)); + return success(convertList(list, product -> // 只返回 id、name 字段 + new IotProductRespVO().setId(product.getId()).setName(product.getName()))); } } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSimpleRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSimpleRespVO.java deleted file mode 100644 index 83855eaaf..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSimpleRespVO.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.iot.controller.admin.product.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - IoT 产品 Response VO") -@Data -public class IotProductSimpleRespVO { - - @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "26087") - private Long id; - - @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") - private String name; - -} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductPageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductPageReqVO.java similarity index 88% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductPageReqVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductPageReqVO.java index 3437f563f..d54adec48 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductPageReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.iot.controller.admin.product.vo; +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.product; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java similarity index 85% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductRespVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java index 0958b3e84..65d26ff5b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductRespVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.iot.controller.admin.product.vo; +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.product; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; @@ -20,34 +20,23 @@ public class IotProductRespVO { @ExcelProperty("产品名称") private String name; - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("创建时间") - private LocalDateTime createTime; - @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("产品标识") private String productKey; - @Schema(description = "接入网关协议", example = "2") - @ExcelProperty("接入网关协议") - private Integer protocolType; - - @Schema(description = "协议编号(脚本解析 id)", requiredMode = Schema.RequiredMode.REQUIRED, example = "13177") - @ExcelProperty("协议编号(脚本解析 id)") - private Long protocolId; - - @Schema(description = "产品所属品类标识符", example = "14237") - @ExcelProperty("产品所属品类标识符") + @Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long categoryId; + @Schema(description = "产品图标", example = "https://iocoder.cn/1.svg") + private String icon; + + @Schema(description = "产品图标", example = "https://iocoder.cn/1.png") + private String picUrl; + @Schema(description = "产品描述", example = "你猜") @ExcelProperty("产品描述") private String description; - @Schema(description = "数据校验级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @ExcelProperty("数据校验级别") - private Integer validateType; - @Schema(description = "产品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @ExcelProperty("产品状态") private Integer status; @@ -60,8 +49,24 @@ public class IotProductRespVO { @ExcelProperty("联网方式") private Integer netType; + @Schema(description = "接入网关协议", example = "2") + @ExcelProperty("接入网关协议") + private Integer protocolType; + + @Schema(description = "协议编号(脚本解析 id)", requiredMode = Schema.RequiredMode.REQUIRED, example = "13177") + @ExcelProperty("协议编号(脚本解析 id)") + private Long protocolId; + @Schema(description = "数据格式") @ExcelProperty("数据格式") private Integer dataFormat; + @Schema(description = "数据校验级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("数据校验级别") + private Integer validateType; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductSaveReqVO.java similarity index 82% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductSaveReqVO.java index 757750544..31890beb7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductSaveReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.iot.controller.admin.product.vo; +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.product; import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.module.iot.enums.product.*; @@ -14,17 +14,26 @@ public class IotProductSaveReqVO { @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.AUTO, example = "1") private Long id; - @Schema(description = "产品 Key", requiredMode = Schema.RequiredMode.AUTO, example = "12345abc") - private String productKey; - - // TODO 芋艿:品类 - - // TODO 芋艿:【待确定】保活时长、产品图标、产品图片 - @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "温湿度") @NotEmpty(message = "产品名称不能为空") private String name; + @Schema(description = "产品 Key", requiredMode = Schema.RequiredMode.AUTO, example = "12345abc") + private String productKey; + + @Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "产品分类编号不能为空") + private Long categoryId; + + @Schema(description = "产品图标", example = "https://iocoder.cn/1.svg") + private String icon; + + @Schema(description = "产品图标", example = "https://iocoder.cn/1.png") + private String picUrl; + + @Schema(description = "产品描述", example = "描述") + private String description; + @Schema(description = "设备类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") @InEnum(value = IotProductDeviceTypeEnum.class, message = "设备类型必须是 {value}") @NotNull(message = "设备类型不能为空") @@ -48,7 +57,4 @@ public class IotProductSaveReqVO { @NotNull(message = "数据校验级别不能为空") private Integer validateType; - @Schema(description = "产品描述", example = "描述") - private String description; - } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java index eef466eda..34fd35706 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java @@ -22,7 +22,7 @@ import lombok.*; public class IotProductDO extends BaseDO { /** - * 产品ID + * 产品 ID */ @TableId private Long id; @@ -30,17 +30,24 @@ public class IotProductDO extends BaseDO { * 产品名称 */ private String name; - // TODO @haohao:这个字段,要不改成 identifier,和阿里云更统一些 /** * 产品标识 */ private String productKey; /** - * 产品所属品类编号 + * 产品分类编号 * - * TODO 外键:后续加 + * 关联 {@link IotProductCategoryDO#getId()} */ private Long categoryId; + /** + * 产品图标 + */ + private String icon; + /** + * 产品图片 + */ + private String picUrl; /** * 产品描述 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java index 0341e2492..eac1d29e8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.dal.mysql.product; 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.module.iot.controller.admin.product.vo.IotProductPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import org.apache.ibatis.annotations.Mapper; 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 3fff94fd9..bcbf13ef4 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 @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.iot.service.product; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductPageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductSaveReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import jakarta.validation.Valid; 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 d0ca09288..259bcaa1f 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 @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.iot.service.product; 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.product.vo.IotProductPageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductSaveReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductMapper; import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum; @@ -14,7 +14,6 @@ import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.util.List; diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java index a482605d5..384628370 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java @@ -44,7 +44,7 @@ public class PayNotifyLogDO extends BaseDO { /** * 支付通知状态 * - * 外键 {@link PayNotifyStatusEnum} + * 枚举 {@link PayNotifyStatusEnum} */ private Integer status; diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java index 7bfabad3f..9f9ee7fef 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java @@ -52,7 +52,7 @@ public class PayNotifyTaskDO extends TenantBaseDO { /** * 通知类型 * - * 外键 {@link PayNotifyTypeEnum} + * 枚举 {@link PayNotifyTypeEnum} */ private Integer type; /** @@ -73,7 +73,7 @@ public class PayNotifyTaskDO extends TenantBaseDO { /** * 通知状态 * - * 外键 {@link PayNotifyStatusEnum} + * 枚举 {@link PayNotifyStatusEnum} */ private Integer status; /** From a8c87d168accd14f5b266be9815046b1b45ff9db Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 7 Dec 2024 19:50:07 +0800 Subject: [PATCH 016/228] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E3=80=91IoT=EF=BC=9A=E4=BA=A7=E5=93=81=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=97=B6=EF=BC=8CproductKey=20=E7=94=B1=E5=89=8D?= =?UTF-8?q?=E7=AB=AF=E7=94=9F=E6=88=90=EF=BC=9B=E5=90=8C=E6=97=B6=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20icon=E3=80=81picUrl=20=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/iot/enums/ErrorCodeConstants.java | 2 +- .../enums/product/IotProductStatusEnum.java | 4 +-- .../product/IotProductCategoryController.java | 24 +++++++++++--- .../product/IotProductCategoryMapper.java | 6 ++++ .../product/IotProductCategoryService.java | 24 ++++++++++---- .../IotProductCategoryServiceImpl.java | 7 ++++ .../product/IotProductServiceImpl.java | 32 ++++--------------- .../IotThinkModelFunctionServiceImpl.java | 2 +- 8 files changed, 60 insertions(+), 41 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 1e947e633..d1d350d5e 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 @@ -11,7 +11,7 @@ public interface ErrorCodeConstants { // ========== 产品相关 1-050-001-000 ============ ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_050_001_000, "产品不存在"); - ErrorCode PRODUCT_IDENTIFICATION_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在"); + ErrorCode PRODUCT_KEY_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在"); ErrorCode PRODUCT_STATUS_NOT_DELETE = new ErrorCode(1_050_001_002, "产品状是发布状态,不允许删除"); ErrorCode PRODUCT_STATUS_NOT_ALLOW_FUNCTION = new ErrorCode(1_050_001_003, "产品状是发布状态,不允许操作物模型"); diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java index e64a3d678..7b4d90a5a 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java @@ -18,12 +18,12 @@ public enum IotProductStatusEnum implements IntArrayValuable { UNPUBLISHED(0, "开发中"), PUBLISHED(1, "已发布"); - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(IotProductStatusEnum::getType).toArray(); + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(IotProductStatusEnum::getStatus).toArray(); /** * 类型 */ - private final Integer type; + private final Integer status; /** * 描述 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java index b365ddea1..bc1c1fbf2 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.iot.controller.admin.product; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -17,7 +18,10 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.List; + import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @Tag(name = "管理后台 - IoT 产品分类") @RestController @@ -29,14 +33,14 @@ public class IotProductCategoryController { private IotProductCategoryService productCategoryService; @PostMapping("/create") - @Operation(summary = "创建IoT 产品分类") + @Operation(summary = "创建产品分类") @PreAuthorize("@ss.hasPermission('iot:product-category:create')") public CommonResult
+ * 关联 {@link IotDeviceDO#getId()} */ private Long deviceId; /** * 物模型编号 + *
+ * 关联 {@link IotThinkModelFunctionDO#getId()} */ private Long thinkModelFunctionId; /** * 产品标识 + *
+ * 关联 {@link IotProductDO#getProductKey()} */ private String productKey; /** * 设备名称 + *
+ * 冗余 {@link IotDeviceDO#getDeviceName()} */ private String deviceName; /** * 属性标识符 + *
+ * 关联 {@link IotThinkModelFunctionDO#getIdentifier()} */ private String identifier; /** * 属性名称 + *
+ * 关联 {@link IotThinkModelFunctionDO#getName()} */ private String name; /** * 数据类型 + *
+ * 关联 {@link IotThinkModelFunctionDO#getProperty()#getDataType()} */ private String dataType; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java index 652c3aee6..542dd1e7b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectDO.java @@ -42,12 +42,6 @@ public class SelectDO { */ private String type; - // TODO @haohao:这个字段,是啥哈? - /** - * 查询条件 - */ - private Set orgIds; - /** * 设备ID */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java index d4c35d66d..44acc3ac5 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/SelectVisualDO.java @@ -27,14 +27,17 @@ public class SelectVisualDO { * 查询类型,0历史数据,1实时数据,2聚合数据 */ private int type; + /** * 查询的数据量 */ private int num; + /** * 聚合函数 */ private String aggregate; + /** * 统计间隔数字+s/m/h/d * 比如1s,1m,1h,1d代表1秒,1分钟,1小时,1天 diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java deleted file mode 100644 index e11db58e7..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java +++ /dev/null @@ -1,159 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine; - -import java.util.List; - -// TODO @haohao:这个还有用哇? -/** - * TableManager 类用于管理 TDengine 表的创建、删除和结构信息获取 - */ -public class TableManager { - - /** - * 创建超级表模板(含存在判断) - */ - private static final String CREATE_STABLE_INE_TPL = "CREATE STABLE IF NOT EXISTS %s (%s) TAGS (%s);"; - - /** - * 删除超级表 - */ - private static final String DROP_STABLE_TPL = "DROP STABLE IF EXISTS %s;"; - - /** - * 获取表的结构信息 - */ - private static final String DESC_TB_TPL = "DESCRIBE %s;"; - - /** - * 超级表增加列 - */ - private static final String ALTER_STABLE_ADD_COL_TPL = "ALTER STABLE %s ADD COLUMN %s;"; - - /** - * 超级表修改列 - */ - private static final String ALTER_STABLE_MODIFY_COL_TPL = "ALTER STABLE %s MODIFY COLUMN %s;"; - - /** - * 超级表删除列 - */ - private static final String ALTER_STABLE_DROP_COL_TPL = "ALTER STABLE %s DROP COLUMN %s;"; - - /** - * 创建普通表模板(含存在判断) - */ - private static final String CREATE_CTABLE_INE_TPL = "CREATE TABLE IF NOT EXISTS %s (%s)"; - - /** - * 获取创建表sql - */ - public static String getCreateSTableSql(String tbName, List fields, TdFieldDO... tags) { - if (fields.isEmpty()) { - return null; - } - - // 生成字段片段 - StringBuilder sbField = new StringBuilder("time TIMESTAMP,"); - - for (TdFieldDO field : fields) { - sbField.append(FieldParser.getFieldDefine(field)); - sbField.append(","); - } - sbField.deleteCharAt(sbField.length() - 1); - - String fieldFrag = sbField.toString(); - - // 生成tag - StringBuilder sbTag = new StringBuilder(); - for (TdFieldDO tag : tags) { - sbTag.append(FieldParser.getFieldDefine(tag)) - .append(","); - } - sbTag.deleteCharAt(sbTag.length() - 1); - - return String.format(CREATE_STABLE_INE_TPL, tbName, fieldFrag, sbTag); - - } - - /** - * 获取创建普通表sql - */ - public static String getCreateCTableSql(String tbName, List fields) { - if (fields.size() == 0) { - return null; - } - - //生成字段片段 - StringBuilder sbField = new StringBuilder("time timestamp,"); - - for (TdFieldDO field : fields) { - sbField.append(FieldParser.getFieldDefine(field)); - sbField.append(","); - } - sbField.deleteCharAt(sbField.length() - 1); - - String fieldFrag = sbField.toString(); - - return String.format(CREATE_CTABLE_INE_TPL, tbName, fieldFrag); - - } - - - /** - * 取正确的表名 - * - * @param name 表象 - */ - public static String rightTbName(String name) { - return name.toLowerCase().replace("-" , "_"); - } - - /** - * 获取表详情的sql - */ - public static String getDescTableSql(String tbName) { - return String.format(DESC_TB_TPL, tbName); - } - - /** - * 获取添加字段sql - */ - public static String getAddSTableColumnSql(String tbName, List fields) { - StringBuilder sbAdd = new StringBuilder(); - for (TdFieldDO field : fields) { - sbAdd.append(String.format(ALTER_STABLE_ADD_COL_TPL, - tbName, - FieldParser.getFieldDefine(field) - )); - } - return sbAdd.toString(); - } - - /** - * 获取修改字段sql - */ - public static String getModifySTableColumnSql(String tbName, List fields) { - StringBuilder sbModify = new StringBuilder(); - for (TdFieldDO field : fields) { - sbModify.append(String.format(ALTER_STABLE_MODIFY_COL_TPL, - tbName, - FieldParser.getFieldDefine(field) - )); - } - return sbModify.toString(); - } - - /** - * 获取删除字段sql - */ - public static String getDropSTableColumnSql(String tbName, List fields) { - StringBuilder sbDrop = new StringBuilder(); - for (TdFieldDO field : fields) { - sbDrop.append(String.format(ALTER_STABLE_DROP_COL_TPL, - tbName, - field.getFieldName() - )); - } - return sbDrop.toString(); - } - -} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineSuperTableMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java similarity index 68% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineSuperTableMapper.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java index e688563d5..640255940 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineSuperTableMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java @@ -1,19 +1,30 @@ package cn.iocoder.yudao.module.iot.dal.tdengine; +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.mybatisplus.annotation.InterceptorIgnore; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; import java.util.List; import java.util.Map; /** - * TD 引擎的超级表 Mapper + * 专门处理 DDL(数据定义语言)操作,包含所有的数据库和表的定义操作,例如创建数据库、创建超级表、创建子表等 */ @Mapper @DS("tdengine") -public interface TdEngineSuperTableMapper { +public interface TdEngineDDLMapper { + + /** + * 创建数据库 + * SQL:CREATE DATABASE [IF NOT EXISTS] db_name [database_options]; + * + * @param dataBaseName 数据库名称 + */ + @TenantIgnore + void createDatabase(@Param("dataBaseName") String dataBaseName); /** * 创建超级表 @@ -25,7 +36,7 @@ public interface TdEngineSuperTableMapper { * columns 列信息 * tags 标签信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void createSuperTable(TdTableDO superTable); /** @@ -36,7 +47,7 @@ public interface TdEngineSuperTableMapper { * dataBaseName 数据库名称 * superTableName 超级表名称 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore List> showSuperTables(TdTableDO superTable); /** @@ -47,7 +58,7 @@ public interface TdEngineSuperTableMapper { * dataBaseName 数据库名称 * superTableName 超级表名称 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore List> describeSuperTable(TdTableDO superTable); /** @@ -59,7 +70,7 @@ public interface TdEngineSuperTableMapper { * superTableName 超级表名称 * column 列信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void addColumnForSuperTable(TdTableDO superTable); /** @@ -71,7 +82,7 @@ public interface TdEngineSuperTableMapper { * superTableName 超级表名称 * column 列信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void dropColumnForSuperTable(TdTableDO superTable); /** @@ -83,7 +94,7 @@ public interface TdEngineSuperTableMapper { * superTableName 超级表名称 * column 列信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void modifyColumnWidthForSuperTable(TdTableDO superTable); @@ -95,7 +106,7 @@ public interface TdEngineSuperTableMapper { * superTableName 超级表名称 * tag 标签信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void addTagForSuperTable(TdTableDO superTable); /** @@ -106,6 +117,33 @@ public interface TdEngineSuperTableMapper { * superTableName 超级表名称 * tag 标签信息 */ - @InterceptorIgnore(tenantLine = "true") + @TenantIgnore void dropTagForSuperTable(TdTableDO superTable); -} \ No newline at end of file + + /** + * 创建子表 - 创建子表 + * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name TAGS (tag_value1, ...); + * + * @param table 表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tableName 子表名称 + * tags TAG 字段 + */ + @TenantIgnore + void createTable(TdTableDO table); + + /** + * 创建子表 - 创建子表并指定标签的值 + * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name (tag_name1, ...) TAGS (tag_value1, ...); + * + * @param table 表信息 + * dataBaseName 数据库名称 + * superTableName 超级表名称 + * tableName 子表名称 + * tags TAG 字段 + */ + @TenantIgnore + void createTableWithTags(TdTableDO table); + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDMLMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDMLMapper.java new file mode 100644 index 000000000..12b2c232c --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDMLMapper.java @@ -0,0 +1,103 @@ +package cn.iocoder.yudao.module.iot.dal.tdengine; + +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TagsSelectDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; +import com.baomidou.dynamic.datasource.annotation.DS; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; +import java.util.Map; + +/** + * 专门处理 TD Engine 的 DML(数据操作语言)操作,处理所有的数据查询和写入操作,如插入数据、查询数据等 + */ +@Mapper +@DS("tdengine") +public interface TdEngineDMLMapper { + + /** + * 插入数据 - 指定列插入数据 + * + * @param table 数据 + * dataBaseName 数据库名 + * tableName 表名 + * columns 列 + */ + @TenantIgnore + void insertData(TdTableDO table); + + /** + * 根据时间戳查询数据 + * + * @param selectDO 查询条件 + * @return 查询结果列表 + */ + @TenantIgnore + List> selectByTimestamp(SelectDO selectDO); + + /** + * 根据时间戳获取数据条数 + * + * @param selectDO 查询条件 + * @return 数据条数 + */ + @TenantIgnore + Map selectCountByTimestamp(SelectDO selectDO); + + /** + * 获取最新数据 + * + * @param selectDO 查询条件 + * @return 最新数据 + */ + @TenantIgnore + Map selectOneLastData(SelectDO selectDO); + + /** + * 获取历史数据列表 + * + * @param selectVisualDO 查询条件 + * @return 历史数据列表 + */ + @TenantIgnore + List> selectHistoryDataList(SelectVisualDO selectVisualDO); + + /** + * 获取实时数据列表 + * + * @param selectVisualDO 查询条件 + * @return 实时数据列表 + */ + @TenantIgnore + List> selectRealtimeDataList(SelectVisualDO selectVisualDO); + + /** + * 获取聚合数据列表 + * + * @param selectVisualDO 查询条件 + * @return 聚合数据列表 + */ + @TenantIgnore + List> selectAggregateDataList(SelectVisualDO selectVisualDO); + + /** + * 根据标签获取最新数据列表 + * + * @param tagsSelectDO 查询条件 + * @return 最新数据列表 + */ + @TenantIgnore + List> selectLastDataListByTags(TagsSelectDO tagsSelectDO); + + /** + * 获取历史数据条数 + * + * @param selectVisualDO 查询条件 + * @return 数据条数 + */ + @TenantIgnore + Long selectHistoryCount(SelectVisualDO selectVisualDO); +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDataWriterMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDataWriterMapper.java deleted file mode 100644 index 51f4229a0..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDataWriterMapper.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.apache.ibatis.annotations.Mapper; - -/** - * TD 引擎的数据写入 Mapper - */ -@Mapper -@DS("tdengine") -public interface TdEngineDataWriterMapper { - - /** - * 插入数据 - 指定列插入数据 - * - * @param table 数据 - * dataBaseName 数据库名 - * tableName 表名 - * columns 列 - */ - @InterceptorIgnore(tenantLine = "true") - void insertData(TdTableDO table); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java deleted file mode 100644 index cd3eaa8b9..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java +++ /dev/null @@ -1,24 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.tdengine; - -import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; - -// TODO @haohao:InterceptorIgnore 忽略租户,可以在每个方法上,添加 @TenantIgnore 哈。 -/** - * TD 引擎的数据库 Mapper - */ -@Mapper -@DS("tdengine") -public interface TdEngineDatabaseMapper { - - /** - * 创建数据库 - * SQL:CREATE DATABASE [IF NOT EXISTS] db_name [database_options]; - * - * @param dataBaseName 数据库名称 - */ - @InterceptorIgnore(tenantLine = "true") - void createDatabase(@Param("dataBaseName") String dataBaseName); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java deleted file mode 100644 index a2408e335..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java +++ /dev/null @@ -1,86 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TagsSelectDO; -import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; -import java.util.Map; - -/** - * TD 引擎的查询 Mapper - */ -@Mapper -@DS("tdengine") -public interface TdEngineQueryMapper { - - /** - * 根据时间戳查询数据 - * - * @param selectDO 查询条件 - * @return 查询结果 - */ - List> selectByTimestamp(SelectDO selectDO); - - // TODO @haohao:最好方法的命名,和数据库操作的保持一直。get => select。然后 selectList or selectOne - /** - * 根据时间戳获取数据条数 - * - * @param selectDO 查询条件 - * @return 数据条数 - */ - Map getCountByTimestamp(SelectDO selectDO); - - /** - * 获取最新数据 - * - * @param selectDO 查询条件 - * @return 最新数据 - */ - Map getLastData(SelectDO selectDO); - - /** - * 获取历史数据 - * - * @param selectVisualDO 查询条件 - * @return 历史数据列表 - */ - @InterceptorIgnore(tenantLine = "true") - List> getHistoryData(SelectVisualDO selectVisualDO); - - /** - * 获取实时数据 - * - * @param selectVisualDO 查询条件 - * @return 实时数据列表 - */ - List> getRealtimeData(SelectVisualDO selectVisualDO); - - /** - * 获取聚合数据 - * - * @param selectVisualDO 查询条件 - * @return 聚合数据列表 - */ - List> getAggregateData(SelectVisualDO selectVisualDO); - - /** - * 根据标签获取最新数据 - * - * @param tagsSelectDO 查询条件 - * @return 最新数据列表 - */ - List> getLastDataByTags(TagsSelectDO tagsSelectDO); - - /** - * 获取历史数据条数 - * - * @param selectVisualDO 查询条件 - * @return 数据条数 - */ - @InterceptorIgnore(tenantLine = "true") - Long getHistoryCount(SelectVisualDO selectVisualDO); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java deleted file mode 100644 index 72517bcab..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.module.iot.dal.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; -import org.apache.ibatis.annotations.Mapper; - -/** - * TD 引擎的表 Mapper - */ -@Mapper -@DS("tdengine") -public interface TdEngineTableMapper { - - /** - * 创建子表 - 创建子表 - * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name TAGS (tag_value1, ...); - * - * @param table 表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * tableName 子表名称 - * tags TAG 字段 - */ - @InterceptorIgnore(tenantLine = "true") - void createTable(TdTableDO table); - - /** - * 创建子表 - 创建子表并指定标签的值 - * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name (tag_name1, ...) TAGS (tag_value1, ...); - * - * @param table 表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * tableName 子表名称 - * tags TAG 字段 - */ - @InterceptorIgnore(tenantLine = "true") - void createTableWithTags(TdTableDO table); - -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java index 96181fd26..4f390ca3b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java @@ -1,7 +1,7 @@ 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.deviceData.IotDeviceDataReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import jakarta.validation.Valid; @@ -31,7 +31,7 @@ public interface IotDeviceDataService { * @param deviceId 设备编号 * @return 设备属性最新数据 */ - List getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceId); + List getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceId); /** * 获得设备属性历史数据 @@ -39,5 +39,5 @@ public interface IotDeviceDataService { * @param deviceDataReqVO 设备属性历史数据 Request VO * @return 设备属性历史数据 */ - PageResult> getDevicePropertiesHistoryData(@Valid IotDeviceDataReqVO deviceDataReqVO); + PageResult> getHistoryDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO); } \ 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/IotDeviceDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java index 8f68989c9..7d10977f9 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java @@ -1,18 +1,20 @@ package cn.iocoder.yudao.module.iot.service.device; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONObject; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper; +import cn.iocoder.yudao.module.iot.enums.IotConstants; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import cn.iocoder.yudao.module.iot.service.tdengine.IotThingModelMessageService; -import cn.iocoder.yudao.module.iot.service.tdengine.TdEngineQueryService; import cn.iocoder.yudao.module.iot.service.thinkmodelfunction.IotThinkModelFunctionService; import jakarta.annotation.Resource; import jakarta.validation.Valid; @@ -40,7 +42,7 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { @Resource private IotThinkModelFunctionService thinkModelFunctionService; @Resource - private TdEngineQueryService tdEngineQueryService; + private TdEngineDMLMapper tdEngineDMLMapper; @Resource private DeviceDataRedisDAO deviceDataRedisDAO; @@ -66,7 +68,7 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { } @Override - public List getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceDataReqVO) { + public List getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { List list = new ArrayList<>(); // 1. 获取设备信息 IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId()); @@ -106,7 +108,7 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { } @Override - public PageResult> getDevicePropertiesHistoryData(IotDeviceDataReqVO deviceDataReqVO) { + public PageResult> getHistoryDeviceProperties(IotDeviceDataPageReqVO deviceDataReqVO) { PageResult> pageResult = new PageResult<>(); // 1. 获取设备信息 IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId()); @@ -121,17 +123,17 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { params.put("rows", deviceDataReqVO.getPageSize()); params.put("page", (deviceDataReqVO.getPageNo() - 1) * deviceDataReqVO.getPageSize()); selectVisualDO.setParams(params); - pageResult.setList(tdEngineQueryService.getHistoryData(selectVisualDO)); - pageResult.setTotal(tdEngineQueryService.getHistoryCount(selectVisualDO)); + pageResult.setList(tdEngineDMLMapper.selectHistoryDataList(selectVisualDO)); + pageResult.setTotal(tdEngineDMLMapper.selectHistoryCount(selectVisualDO)); return pageResult; } private String getDatabaseName() { - return url.substring(url.lastIndexOf("/") + 1); + return StrUtil.subAfter(url, "/", true); } private static String getDeviceTableName(String productKey, String deviceName) { - return String.format("device_%s_%s", productKey.toLowerCase(), deviceName.toLowerCase()); + return String.format(IotConstants.DEVICE_TABLE_NAME_FORMAT, productKey, deviceName); } -} +} \ 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/IotDeviceServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java index 0ec737a30..58918c130 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 @@ -19,7 +19,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import java.security.SecureRandom; import java.time.LocalDateTime; +import java.util.Base64; import java.util.Objects; import java.util.UUID; @@ -137,10 +139,13 @@ public class IotDeviceServiceImpl implements IotDeviceService { * @return 生成的 MQTT Password */ private String generateMqttPassword() { - // TODO @haohao:【后续优化】在实际应用中,建议使用更安全的方法生成 MQTT Password,如加密或哈希 - return UUID.randomUUID().toString(); + SecureRandom secureRandom = new SecureRandom(); + byte[] passwordBytes = new byte[32]; // 256 位的随机数 + secureRandom.nextBytes(passwordBytes); + return Base64.getUrlEncoder().withoutPadding().encodeToString(passwordBytes); } + /** * 生成唯一的 DeviceName * @@ -214,30 +219,28 @@ public class IotDeviceServiceImpl implements IotDeviceService { @Override public void updateDeviceStatus(IotDeviceStatusUpdateReqVO updateReqVO) { // 1. 校验存在 - // TODO @haohao:这里的 iotDeviceDO => device。一个是去掉 iot,一个是去掉 DO 后缀。这样,简洁一点。 - IotDeviceDO iotDeviceDO = validateDeviceExists(updateReqVO.getId()); + IotDeviceDO device = validateDeviceExists(updateReqVO.getId()); // 2.1 更新状态和更新时间 - IotDeviceDO updateObj = BeanUtils.toBean(updateReqVO, IotDeviceDO.class); - // TODO @haohao:下面几个状态的处理,可以考虑 if else if。这样,看起来会有层次感哈 - // 2.2.1 以前是未激活,现在是上线,设置设备激活时间 - // TODO @haohao:这里可以使用 ObjectUtils.equalsAny 类似这种哈。 - if (Objects.equals(iotDeviceDO.getStatus(), IotDeviceStatusEnum.INACTIVE.getStatus()) - && Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { - updateObj.setActiveTime(LocalDateTime.now()); - } - // 2.2.2 如果是上线,设置上线时间 - if (Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { - updateObj.setLastOnlineTime(LocalDateTime.now()); - } - // 2.2.3 如果是离线,设置离线时间 - if (Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.OFFLINE.getStatus())) { - updateObj.setLastOfflineTime(LocalDateTime.now()); + IotDeviceDO updateDevice = BeanUtils.toBean(updateReqVO, IotDeviceDO.class); + // 2.2 更新状态相关时间 + if (Objects.equals(device.getStatus(), IotDeviceStatusEnum.INACTIVE.getStatus()) + && Objects.equals(updateDevice.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { + // 从未激活到在线,设置激活时间和最后上线时间 + updateDevice.setActiveTime(LocalDateTime.now()); + updateDevice.setLastOnlineTime(LocalDateTime.now()); + } else if (Objects.equals(updateDevice.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) { + // 如果是上线,设置最后上线时间 + updateDevice.setLastOnlineTime(LocalDateTime.now()); + } else if (Objects.equals(updateDevice.getStatus(), IotDeviceStatusEnum.OFFLINE.getStatus())) { + // 如果是离线,设置最后离线时间 + updateDevice.setLastOfflineTime(LocalDateTime.now()); } + // 2.3 设置状态更新时间 - updateObj.setStatusLastUpdateTime(LocalDateTime.now()); + updateDevice.setStatusLastUpdateTime(LocalDateTime.now()); // 2.4 更新到数据库 - deviceMapper.updateById(updateObj); + deviceMapper.updateById(updateDevice); } @Override diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java index 7c88b83aa..8aec32f32 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableService.java @@ -15,4 +15,4 @@ public interface IotSuperTableService { * 创建超级表数据模型 */ void createSuperTableDataModel(IotProductDO product, List functionList); -} +} \ 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/tdengine/IotSuperTableServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableServiceImpl.java index 3be324c4e..20989181e 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotSuperTableServiceImpl.java @@ -9,6 +9,8 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.FieldParser; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -26,7 +28,7 @@ import java.util.stream.Collectors; public class IotSuperTableServiceImpl implements IotSuperTableService { @Resource - private TdEngineSuperTableService tdEngineSuperTableService; + private TdEngineDDLMapper tdEngineDDLMapper; @Value("${spring.datasource.dynamic.datasource.tdengine.url}") private String url; @@ -42,9 +44,10 @@ public class IotSuperTableServiceImpl implements IotSuperTableService { String superTableName = getSuperTableName(product.getDeviceType(), product.getProductKey()); String databaseName = getDatabaseName(); - Integer tableExists = tdEngineSuperTableService.checkSuperTableExists(new TdTableDO(databaseName, superTableName)); - if (tableExists != null && tableExists > 0) { + List> results = tdEngineDDLMapper.showSuperTables(new TdTableDO(databaseName, superTableName)); + int tableExists = results == null || results.isEmpty() ? 0 : results.size(); + if (tableExists > 0) { updateSuperTable(thingModel, product.getDeviceType()); } else { createSuperTable(thingModel, product.getDeviceType()); @@ -76,7 +79,7 @@ public class IotSuperTableServiceImpl implements IotSuperTableService { String databaseName = getDatabaseName(); // 创建超级表 - tdEngineSuperTableService.createSuperTable(new TdTableDO(databaseName, superTableName, schemaFields, tagsFields)); + tdEngineDDLMapper.createSuperTable(new TdTableDO(databaseName, superTableName, schemaFields, tagsFields)); } /** @@ -98,7 +101,7 @@ public class IotSuperTableServiceImpl implements IotSuperTableService { * 获取表的字段信息 */ private List getTableFields(String tableName) { - List> tableDescription = tdEngineSuperTableService.describeSuperTable(new TdTableDO(getDatabaseName(), tableName)); + List> tableDescription = tdEngineDDLMapper.describeSuperTable(new TdTableDO(getDatabaseName(), tableName)); if (CollUtil.isEmpty(tableDescription)) { return Collections.emptyList(); } @@ -127,32 +130,38 @@ public class IotSuperTableServiceImpl implements IotSuperTableService { // 添加新增字段 if (CollUtil.isNotEmpty(addFields)) { - tdEngineSuperTableService.addColumnsForSuperTable(TdTableDO.builder() - .dataBaseName(databaseName) - .superTableName(tableName) - .columns(addFields) - .build()); + for (TdFieldDO addField : addFields) { + tdEngineDDLMapper.addColumnForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .column(addField) + .build()); + } } // 删除旧字段 if (CollUtil.isNotEmpty(dropFields)) { - tdEngineSuperTableService.dropColumnsForSuperTable(TdTableDO.builder() - .dataBaseName(databaseName) - .superTableName(tableName) - .columns(dropFields) - .build()); + for (TdFieldDO dropField : dropFields) { + tdEngineDDLMapper.dropColumnForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .column(dropField) + .build()); + } } // 修改字段(先删除再添加) if (CollUtil.isNotEmpty(modifyFields)) { - tdEngineSuperTableService.dropColumnsForSuperTable(TdTableDO.builder() - .dataBaseName(databaseName) - .superTableName(tableName) - .columns(modifyFields) - .build()); - tdEngineSuperTableService.addColumnsForSuperTable(TdTableDO.builder() - .dataBaseName(databaseName) - .superTableName(tableName) - .columns(addFields) - .build()); + for (TdFieldDO modifyField : modifyFields) { + tdEngineDDLMapper.dropColumnForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .column(modifyField) + .build()); + tdEngineDDLMapper.addColumnForSuperTable(TdTableDO.builder() + .dataBaseName(databaseName) + .superTableName(tableName) + .column(modifyField) + .build()); + } } } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java index 280b32d9a..92a30ebb0 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java @@ -1,6 +1,8 @@ package cn.iocoder.yudao.module.iot.service.tdengine; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceStatusUpdateReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; @@ -11,6 +13,9 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage; import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO; import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper; +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper; +import cn.iocoder.yudao.module.iot.enums.IotConstants; import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum; import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum; import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; @@ -30,6 +35,14 @@ import java.util.stream.Collectors; @Service public class IotThingModelMessageServiceImpl implements IotThingModelMessageService { + private static final String TAG_NOTE = "TAG"; + private static final String NOTE = "note"; + private static final String TIME = "time"; + private static final String DEVICE_KEY = "device_key"; + private static final String DEVICE_NAME = "device_name"; + private static final String PRODUCT_KEY = "product_key"; + private static final String DEVICE_TYPE = "device_type"; + @Value("${spring.datasource.dynamic.datasource.tdengine.url}") private String url; @@ -38,11 +51,9 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @Resource private IotDeviceService iotDeviceService; @Resource - private TdEngineTableService tdEngineTableService; + private TdEngineDDLMapper tdEngineDDLMapper; @Resource - private TdEngineSuperTableService tdEngineSuperTableService; - @Resource - private TdEngineDataWriterService tdEngineDataWriterService; + private TdEngineDMLMapper tdEngineDMLMapper; @Resource private DeviceDataRedisDAO deviceDataRedisDAO; @@ -51,62 +62,64 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ @Override @TenantIgnore public void saveThingModelMessage(IotDeviceDO device, ThingModelMessage thingModelMessage) { - // 判断设备状态,如果为未激活状态,创建数据表 + // 1. 判断设备状态,如果为未激活状态,创建数据表并更新设备状态 if (IotDeviceStatusEnum.INACTIVE.getStatus().equals(device.getStatus())) { - // 创建设备数据表 createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); - // 更新设备状态 - // TODO @haohao:下面可以考虑,链式调用。iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO().setid().setstatus()) - IotDeviceStatusUpdateReqVO updateReqVO = new IotDeviceStatusUpdateReqVO(); - updateReqVO.setId(device.getId()); - updateReqVO.setStatus(IotDeviceStatusEnum.ONLINE.getStatus()); - iotDeviceService.updateDeviceStatus(updateReqVO); + iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO() + .setId(device.getId()) + .setStatus(IotDeviceStatusEnum.ONLINE.getStatus())); } - // TODO @haohao:这个变量,可以和 “过滤并收集有效的属性字段” 那块,因为关联度高一点。 - // 获取设备属性 + // 2. 获取设备属性并进行物模型校验,过滤非物模型属性 Map params = thingModelMessage.dataToMap(); - - // 物模型校验,过滤非物模型属性 - List functionList = iotThinkModelFunctionService - .getThinkModelFunctionListByProductKey(thingModelMessage.getProductKey()) - .stream() - .filter(function -> IotProductFunctionTypeEnum.PROPERTY.getType().equals(function.getType())) - .toList(); + List functionList = getValidFunctionList(thingModelMessage.getProductKey()); if (functionList.isEmpty()) { return; } - // 获取属性标识符集合 - // TODO @haohao:这个变量,可以和 “过滤并收集有效的属性字段” 那块,因为关联度高一点。另外,可以使用 CollectionUtils。convertSet - Set propertyIdentifiers = functionList.stream() - .map(IotThinkModelFunctionDO::getIdentifier) - .collect(Collectors.toSet()); + // 3. 过滤并收集有效的属性字段,缓存设备属性 + List schemaFieldValues = filterAndCollectValidFields(params, functionList, device, thingModelMessage.getTime()); + if (schemaFieldValues.size() == 1) { // 仅有时间字段,无需保存 + return; + } + + // 4. 构建并保存设备属性数据 + tdEngineDMLMapper.insertData(TdTableDO.builder() + .dataBaseName(getDatabaseName()) + .tableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())) + .columns(schemaFieldValues) + .build()); + } + + private List getValidFunctionList(String productKey) { + return iotThinkModelFunctionService + .getThinkModelFunctionListByProductKey(productKey) + .stream() + .filter(function -> IotProductFunctionTypeEnum.PROPERTY.getType().equals(function.getType())) + .toList(); + } + + private List filterAndCollectValidFields(Map params, List functionList, IotDeviceDO device, Long time) { + // 1. 获取属性标识符集合 + Set propertyIdentifiers = CollectionUtils.convertSet(functionList, IotThinkModelFunctionDO::getIdentifier); + + // 2. 构建属性标识符和属性的映射 Map functionMap = functionList.stream() .collect(Collectors.toMap(IotThinkModelFunctionDO::getIdentifier, function -> function)); - // 过滤并收集有效的属性字段 + // 3. 过滤并收集有效的属性字段 List schemaFieldValues = new ArrayList<>(); - schemaFieldValues.add(new TdFieldDO("time", thingModelMessage.getTime())); + schemaFieldValues.add(new TdFieldDO(TIME, time)); params.forEach((key, val) -> { if (propertyIdentifiers.contains(key)) { schemaFieldValues.add(new TdFieldDO(key.toLowerCase(), val)); // 缓存设备属性 // TODO @haohao:这个缓存的写入,可以使用的时候 cache 么?被动读 - setDeviceDataCache(device, functionMap.get(key), val, thingModelMessage.getTime()); + setDeviceDataCache(device, functionMap.get(key), val, time); } }); - // TODO @haohao:疑问,为什么 1 不继续哈? - if (schemaFieldValues.size() == 1) { - return; - } - - // 构建并保存设备属性数据 - tdEngineDataWriterService.insertData(TdTableDO.builder().build() - .setDataBaseName(getDatabaseName()) - .setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName())) - .setColumns(schemaFieldValues)); + return schemaFieldValues; } /** @@ -132,7 +145,6 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ deviceDataRedisDAO.set(deviceData); } - // TODO @haohao:实现没问题哈。这个方法的空行有点多,逻辑分块上没这么明显。看看能不能改下。 /** * 创建设备数据表 * @@ -142,36 +154,37 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ * @param deviceKey 设备 Key */ private void createDeviceTable(Integer deviceType, String productKey, String deviceName, String deviceKey) { + // 1. 获取超级表名和数据库名 String superTableName = getProductPropertySTableName(deviceType, productKey); String dataBaseName = getDatabaseName(); - List> maps = tdEngineSuperTableService.describeSuperTable(new TdTableDO(dataBaseName, superTableName)); + // 2. 获取超级表的结构信息 + List> maps = tdEngineDDLMapper.describeSuperTable(new TdTableDO(dataBaseName, superTableName)); List tagsFieldValues = new ArrayList<>(); - if (maps != null) { - // TODO @haohao:一些字符串,是不是可以枚举起来哈。 - // TODO @haohao:这种过滤的,常用的,可以考虑用 CollectionUtils.filterList。一些常用的 stream 操作,适合封装哈 - List> taggedNotesList = maps.stream() - .filter(map -> "TAG".equals(map.get("note"))) - .toList(); + // 2.1 过滤出 TAG 类型的字段 + List> taggedNotesList = CollectionUtils.filterList(maps, map -> TAG_NOTE.equals(map.get(NOTE))); + + // 2.2 解析字段信息 tagsFieldValues = FieldParser.parse(taggedNotesList.stream() .map(map -> List.of(map.get("field"), map.get("type"), map.get("length"))) .collect(Collectors.toList())); + // 2.3 设置 TAG 字段的值 for (TdFieldDO tagsFieldValue : tagsFieldValues) { switch (tagsFieldValue.getFieldName()) { - case "product_key" -> tagsFieldValue.setFieldValue(productKey); - case "device_key" -> tagsFieldValue.setFieldValue(deviceKey); - case "device_name" -> tagsFieldValue.setFieldValue(deviceName); - case "device_type" -> tagsFieldValue.setFieldValue(deviceType); + case PRODUCT_KEY -> tagsFieldValue.setFieldValue(productKey); + case DEVICE_KEY -> tagsFieldValue.setFieldValue(deviceKey); + case DEVICE_NAME -> tagsFieldValue.setFieldValue(deviceName); + case DEVICE_TYPE -> tagsFieldValue.setFieldValue(deviceType); } } } - // 创建设备数据表 + // 3. 创建设备数据表 String tableName = getDeviceTableName(productKey, deviceName); - tdEngineTableService.createTable(TdTableDO.builder().build() + tdEngineDDLMapper.createTable(TdTableDO.builder().build() .setDataBaseName(dataBaseName) .setSuperTableName(superTableName) .setTableName(tableName) @@ -184,8 +197,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ * @return 数据库名称 */ private String getDatabaseName() { - // TODO @haohao:可以使用 StrUtil.subAftetLast 这种方法 - return url.substring(url.lastIndexOf("/") + 1); + return StrUtil.subAfter(url, "/", true); } /** @@ -198,9 +210,9 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ private static String getProductPropertySTableName(Integer deviceType, String productKey) { // TODO @haohao:枚举下,会好点哈。 return switch (deviceType) { - case 1 -> String.format("gateway_sub_%s", productKey).toLowerCase(); - case 2 -> String.format("gateway_%s", productKey).toLowerCase(); - default -> String.format("device_%s", productKey).toLowerCase(); + case 1 -> String.format(IotConstants.GATEWAY_SUB_STABLE_NAME_FORMAT, productKey).toLowerCase(); + case 2 -> String.format(IotConstants.GATEWAY_STABLE_NAME_FORMAT, productKey).toLowerCase(); + default -> String.format(IotConstants.DEVICE_STABLE_NAME_FORMAT, productKey).toLowerCase(); }; } @@ -212,7 +224,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ * @return 设备表名 */ private static String getDeviceTableName(String productKey, String deviceName) { - return String.format("device_%s_%s", productKey.toLowerCase(), deviceName.toLowerCase()); + return String.format(IotConstants.DEVICE_TABLE_NAME_FORMAT, productKey.toLowerCase(), deviceName.toLowerCase()); } } \ 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/tdengine/TdEngineDataWriterService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterService.java deleted file mode 100644 index 0995b0797..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterService.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; - -/** - * TD 引擎的数据写入 Service 接口 - */ -public interface TdEngineDataWriterService { - - /** - * 插入数据 - 指定列插入数据 - * - * @param table 数据 - * dataBaseName 数据库名 - * tableName 表名 - * columns 列 - */ - void insertData(TdTableDO table); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java deleted file mode 100644 index f4dd2c8fd..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDataWriterMapper; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Service; - -/** - * TD 引擎的数据写入 Service 实现类 - */ -@Service -public class TdEngineDataWriterServiceImpl implements TdEngineDataWriterService { - - @Resource - private TdEngineDataWriterMapper tdEngineDataWriterMapper; - - @Override - public void insertData(TdTableDO table) { - tdEngineDataWriterMapper.insertData(table); - } -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java deleted file mode 100644 index d895262cc..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java +++ /dev/null @@ -1,14 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -/** - * TD 引擎的数据库 Service 接口 - */ -public interface TdEngineDatabaseService { - - /** - * 创建数据库 - * - * @param dataBaseName 数据库名称 - */ - void createDatabase(String dataBaseName); -} \ 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/tdengine/TdEngineDatabaseServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseServiceImpl.java deleted file mode 100644 index c880db8a9..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseServiceImpl.java +++ /dev/null @@ -1,22 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDatabaseMapper; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * TD 引擎的数据库 Service 实现类 - */ -@Service -@Slf4j -public class TdEngineDatabaseServiceImpl implements TdEngineDatabaseService { - - @Resource - private TdEngineDatabaseMapper tdEngineDatabaseMapper; - - @Override - public void createDatabase(String dataBaseName) { - tdEngineDatabaseMapper.createDatabase(dataBaseName); - } -} \ 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/tdengine/TdEngineQueryService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryService.java deleted file mode 100644 index 8d07b4334..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryService.java +++ /dev/null @@ -1,28 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; - -import java.util.List; -import java.util.Map; - -/** - * TD 引擎的查询 Service 接口 - */ -public interface TdEngineQueryService { - - /** - * 获取历史数据 - * - * @param selectVisualDO 查询条件 - * @return 历史数据列表 - */ - List> getHistoryData(SelectVisualDO selectVisualDO); - - /** - * 获取历史数据条数 - * - * @param selectVisualDO 查询条件 - * @return 数据条数 - */ - Long getHistoryCount(SelectVisualDO selectVisualDO); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java deleted file mode 100644 index 672a58640..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineQueryMapper; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Map; - -@Service -public class TdEngineQueryServiceImpl implements TdEngineQueryService { - - @Resource - private TdEngineQueryMapper tdEngineQueryMapper; - - @Override - public List> getHistoryData(SelectVisualDO selectVisualDO) { - return tdEngineQueryMapper.getHistoryData(selectVisualDO); - } - - @Override - public Long getHistoryCount(SelectVisualDO selectVisualDO) { - return tdEngineQueryMapper.getHistoryCount(selectVisualDO); - } -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java deleted file mode 100644 index df6290a98..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java +++ /dev/null @@ -1,123 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; - -import java.util.List; -import java.util.Map; - -/** - * TD 引擎的超级表 Service 接口 - */ -public interface TdEngineSuperTableService { - - /** - * 创建超级表 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * columns 列信息 - * tags 标签信息 - */ - void createSuperTable(TdTableDO superTable); - - /** - * 查看超级表 - 显示当前数据库下的所有超级表信息 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - */ - - List> showSuperTables(TdTableDO superTable); - - /** - * 查看超级表 - 获取超级表的结构信息 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - */ - List> describeSuperTable(TdTableDO superTable); - - /** - * 修改超级表 - 增加列 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * column 列信息 - */ - void addColumnForSuperTable(TdTableDO superTable); - - /** - * 修改超级表 - 删除列 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * column 列信息 - */ - void dropColumnForSuperTable(TdTableDO superTable); - - /** - * 修改超级表 - 修改列宽 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * column 列信息 - */ - void modifyColumnWidthForSuperTable(TdTableDO superTable); - - - /** - * 修改超级表 - 为超级表添加标签 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * tag 标签信息 - */ - void addTagForSuperTable(TdTableDO superTable); - - /** - * 修改超级表 - 为超级表删除标签 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * tag 标签信息 - */ - void dropTagForSuperTable(TdTableDO superTable); - - /** - * 检查超级表是否存在 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * @return 超级表数量 - */ - Integer checkSuperTableExists(TdTableDO superTable); - - /** - * 为超级表添加列 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * columns 列信息 - */ - void addColumnsForSuperTable(TdTableDO superTable); - - /** - * 为超级表删除列 - * - * @param superTable 超级表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * columns 列信息 - */ - void dropColumnsForSuperTable(TdTableDO superTable); -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java deleted file mode 100644 index 60436e7bd..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java +++ /dev/null @@ -1,90 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineSuperTableMapper; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.Map; - -/** - * TD 引擎的超级表 Service 实现类 - */ -@Slf4j -@Service -public class TdEngineSuperTableServiceImpl implements TdEngineSuperTableService { - - @Resource - private TdEngineSuperTableMapper tdEngineSuperTableMapper; - - @Override - public void createSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.createSuperTable(superTable); - } - - @Override - public List> showSuperTables(TdTableDO superTable) { - return tdEngineSuperTableMapper.showSuperTables(superTable); - } - - @Override - public List> describeSuperTable(TdTableDO superTable) { - return tdEngineSuperTableMapper.describeSuperTable(superTable); - } - - @Override - public void addColumnForSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.addColumnForSuperTable(superTable); - } - - @Override - public void dropColumnForSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.dropColumnForSuperTable(superTable); - } - - @Override - public void modifyColumnWidthForSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.modifyColumnWidthForSuperTable(superTable); - } - - @Override - public void addTagForSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.addTagForSuperTable(superTable); - } - - @Override - public void dropTagForSuperTable(TdTableDO superTable) { - tdEngineSuperTableMapper.dropTagForSuperTable(superTable); - } - - @Override - public Integer checkSuperTableExists(TdTableDO superTable) { - List> results = tdEngineSuperTableMapper.showSuperTables(superTable); - return results == null || results.isEmpty() ? 0 : results.size(); - } - - @Override - public void addColumnsForSuperTable(TdTableDO superTable) { - for (TdFieldDO column : superTable.getColumns()) { - tdEngineSuperTableMapper.addColumnForSuperTable(TdTableDO.builder() - .dataBaseName(superTable.getDataBaseName()) - .superTableName(superTable.getSuperTableName()) - .column(column) - .build()); - } - } - - @Override - public void dropColumnsForSuperTable(TdTableDO superTable) { - for (TdFieldDO column : superTable.getColumns()) { - tdEngineSuperTableMapper.dropColumnForSuperTable(TdTableDO.builder() - .dataBaseName(superTable.getDataBaseName()) - .superTableName(superTable.getSuperTableName()) - .column(column) - .build()); - } - } -} \ 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/tdengine/TdEngineTableService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableService.java deleted file mode 100644 index 078159784..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableService.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; - -/** - * TD 引擎的表 Service 接口 - */ -public interface TdEngineTableService { - - /** - * 创建表 - 创建超级表的子表 - * - * @param table 表信息 - * dataBaseName 数据库名称 - * superTableName 超级表名称 - * tableName 子表名称 - * tags TAG 字段 - */ - void createTable(TdTableDO table); - -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java deleted file mode 100644 index cdca47888..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.module.iot.service.tdengine; - -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineTableMapper; -import jakarta.annotation.Resource; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -/** - * TD 引擎的表 Service 实现类 - */ -@Slf4j -@Service -public class TdEngineTableServiceImpl implements TdEngineTableService { - - @Resource - private TdEngineTableMapper tdEngineTableMapper; - - @Override - public void createTable(TdTableDO table) { - tdEngineTableMapper.createTable(table); - } -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDDLMapper.xml similarity index 70% rename from yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml rename to yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDDLMapper.xml index 37cf71910..091b77f64 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDDLMapper.xml @@ -2,7 +2,12 @@ - + + + + + CREATE DATABASE IF NOT EXISTS ${dataBaseName} + @@ -68,4 +73,29 @@ ALTER STABLE ${dataBaseName}.${superTableName} DROP TAG ${tag.fieldName} - + + + CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} + USING ${dataBaseName}.${superTableName} + TAGS + + #{item.fieldValue} + + + + + + CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} + USING ${dataBaseName}.${superTableName} + + #{item.fieldName} + + TAGS + + #{item.fieldValue} + + + + \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDMLMapper.xml similarity index 68% rename from yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml rename to yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDMLMapper.xml index f4361bc67..0443a826b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDMLMapper.xml @@ -2,7 +2,21 @@ - + + + + + INSERT INTO ${dataBaseName}.${tableName} + + ${item.fieldName} + + VALUES + + #{item.fieldValue} + + - SELECT COUNT(0) AS count FROM ${dataBaseName}.${tableName} @@ -20,14 +34,14 @@ - + SELECT LAST(time), * FROM ${tableName} WHERE device_id = #{deviceId} - SELECT LAST(*) FROM ${dataBaseName}.${stableName} @@ -35,7 +49,7 @@ - SELECT ${fieldName} AS data, time FROM ${dataBaseName}.${tableName} @@ -46,14 +60,14 @@ - SELECT ${fieldName}, time FROM ${dataBaseName}.${tableName} - SELECT ${aggregate}(${fieldName}) FROM ${dataBaseName}.${tableName} @@ -62,11 +76,11 @@ - + SELECT COUNT(time) FROM ${dataBaseName}.${tableName} WHERE time BETWEEN #{startTime} AND #{endTime} AND ${fieldName} IS NOT NULL - + \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml deleted file mode 100644 index dd38cd08e..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - INSERT INTO ${dataBaseName}.${tableName} - - ${item.fieldName} - - VALUES - - #{item.fieldValue} - - - - \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml deleted file mode 100644 index 919c301f7..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - CREATE DATABASE IF NOT EXISTS ${dataBaseName} - - - \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml deleted file mode 100644 index 867ef8f43..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} - USING ${dataBaseName}.${superTableName} - TAGS - - #{item.fieldValue} - - - - - - CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName} - USING ${dataBaseName}.${superTableName} - - #{item.fieldName} - - TAGS - - #{item.fieldValue} - - - - \ No newline at end of file From ce919d12d1b079ace85c70004bd6553053b76667 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 5 Dec 2024 21:45:48 +0800 Subject: [PATCH 013/228] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91IoT=EF=BC=9Atdengine=20=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/controller/admin/device/IotDeviceDataController.java | 2 ++ .../yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java | 1 - .../module/iot/service/device/IotDeviceDataServiceImpl.java | 2 +- .../module/iot/service/device/IotDeviceServiceImpl.java | 2 +- .../service/tdengine/IotThingModelMessageServiceImpl.java | 5 +---- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java index 72fdda8c8..77bc78c66 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceDataController.java @@ -31,6 +31,7 @@ public class IotDeviceDataController { @Resource private IotDeviceDataService deviceDataService; + // TODO @浩浩:这里的 /latest-list,包括方法名。 @GetMapping("/latest") @Operation(summary = "获取设备属性最新数据") public CommonResult> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { @@ -38,6 +39,7 @@ public class IotDeviceDataController { return success(BeanUtils.toBean(list, IotDeviceDataRespVO.class)); } + // TODO @浩浩:这里的 /history-page 包括方法名。 @GetMapping("/history") @Operation(summary = "获取设备属性历史数据") public CommonResult> getHistoryDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) { diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java index 640255940..3d7aa84dd 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.iot.dal.tdengine; import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore; import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO; import com.baomidou.dynamic.datasource.annotation.DS; -import com.baomidou.mybatisplus.annotation.InterceptorIgnore; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java index 7d10977f9..d68287cd4 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java @@ -133,7 +133,7 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService { } private static String getDeviceTableName(String productKey, String deviceName) { - return String.format(IotConstants.DEVICE_TABLE_NAME_FORMAT, productKey, deviceName); + return String.format(IotConstants.DEVICE_TABLE_NAME_FORMAT, productKey, deviceName); } } \ 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/IotDeviceServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java index 58918c130..bb302a22f 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 @@ -139,13 +139,13 @@ public class IotDeviceServiceImpl implements IotDeviceService { * @return 生成的 MQTT Password */ private String generateMqttPassword() { + // TODO @浩浩:这里的 StrUtil 随机字符串? SecureRandom secureRandom = new SecureRandom(); byte[] passwordBytes = new byte[32]; // 256 位的随机数 secureRandom.nextBytes(passwordBytes); return Base64.getUrlEncoder().withoutPadding().encodeToString(passwordBytes); } - /** * 生成唯一的 DeviceName * diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java index 92a30ebb0..9ffb47715 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java @@ -66,8 +66,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ if (IotDeviceStatusEnum.INACTIVE.getStatus().equals(device.getStatus())) { createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey()); iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO() - .setId(device.getId()) - .setStatus(IotDeviceStatusEnum.ONLINE.getStatus())); + .setId(device.getId()).setStatus(IotDeviceStatusEnum.ONLINE.getStatus())); } // 2. 获取设备属性并进行物模型校验,过滤非物模型属性 @@ -77,7 +76,6 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ return; } - // 3. 过滤并收集有效的属性字段,缓存设备属性 List schemaFieldValues = filterAndCollectValidFields(params, functionList, device, thingModelMessage.getTime()); if (schemaFieldValues.size() == 1) { // 仅有时间字段,无需保存 @@ -165,7 +163,6 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ // 2.1 过滤出 TAG 类型的字段 List> taggedNotesList = CollectionUtils.filterList(maps, map -> TAG_NOTE.equals(map.get(NOTE))); - // 2.2 解析字段信息 tagsFieldValues = FieldParser.parse(taggedNotesList.stream() .map(map -> List.of(map.get("field"), map.get("type"), map.get("length"))) From 3a2c691af085c4e649373961e827627b8fcfaf9a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 7 Dec 2024 16:42:56 +0800 Subject: [PATCH 014/228] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E3=80=91IoT=EF=BC=9A=E4=BA=A7=E5=93=81=E5=88=86?= =?UTF-8?q?=E7=B1=BB=E7=9A=84=E7=BB=B4=E6=8A=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/iot/enums/ErrorCodeConstants.java | 9 ++- .../product/IotProductCategoryController.java | 72 +++++++++++++++++++ .../admin/product/vo/IotProductSaveReqVO.java | 6 +- .../category/IotProductCategoryPageReqVO.java | 27 +++++++ .../vo/category/IotProductCategoryRespVO.java | 33 +++++++++ .../category/IotProductCategorySaveReqVO.java | 29 ++++++++ .../product/IotProductCategoryDO.java | 48 +++++++++++++ .../product/IotProductCategoryMapper.java | 25 +++++++ .../product/IotProductCategoryService.java | 54 ++++++++++++++ .../IotProductCategoryServiceImpl.java | 70 ++++++++++++++++++ 10 files changed, 369 insertions(+), 4 deletions(-) create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryPageReqVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryRespVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategorySaveReqVO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductCategoryDO.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductCategoryMapper.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryService.java create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryServiceImpl.java 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 be9d28ecb..1e947e633 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 @@ -9,20 +9,20 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; */ public interface ErrorCodeConstants { - // ========== IoT 产品相关 1-050-001-000 ============ + // ========== 产品相关 1-050-001-000 ============ ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_050_001_000, "产品不存在"); ErrorCode PRODUCT_IDENTIFICATION_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在"); ErrorCode PRODUCT_STATUS_NOT_DELETE = new ErrorCode(1_050_001_002, "产品状是发布状态,不允许删除"); ErrorCode PRODUCT_STATUS_NOT_ALLOW_FUNCTION = new ErrorCode(1_050_001_003, "产品状是发布状态,不允许操作物模型"); - // ========== IoT 产品物模型 1-050-002-000 ============ + // ========== 产品物模型 1-050-002-000 ============ ErrorCode THINK_MODEL_FUNCTION_NOT_EXISTS = new ErrorCode(1_050_002_000, "产品物模型不存在"); ErrorCode THINK_MODEL_FUNCTION_EXISTS_BY_PRODUCT_KEY = new ErrorCode(1_050_002_001, "ProductKey 对应的产品物模型已存在"); ErrorCode THINK_MODEL_FUNCTION_IDENTIFIER_EXISTS = new ErrorCode(1_050_002_002, "存在重复的功能标识符。"); ErrorCode THINK_MODEL_FUNCTION_NAME_EXISTS = new ErrorCode(1_050_002_003, "存在重复的功能名称。"); ErrorCode THINK_MODEL_FUNCTION_IDENTIFIER_INVALID = new ErrorCode(1_050_002_003, "产品物模型标识无效"); - // ========== IoT 设备 1-050-003-000 ============ + // ========== 设备 1-050-003-000 ============ ErrorCode DEVICE_NOT_EXISTS = new ErrorCode(1_050_003_000, "设备不存在"); ErrorCode DEVICE_NAME_EXISTS = new ErrorCode(1_050_003_001, "设备名称在同一产品下必须唯一"); ErrorCode DEVICE_HAS_CHILDREN = new ErrorCode(1_050_003_002, "有子设备,不允许删除"); @@ -30,4 +30,7 @@ public interface ErrorCodeConstants { ErrorCode DEVICE_PRODUCT_CANNOT_BE_MODIFIED = new ErrorCode(1_050_003_004, "产品不能修改"); ErrorCode DEVICE_INVALID_DEVICE_STATUS = new ErrorCode(1_050_003_005, "无效的设备状态"); + // ========== 产品分类 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/controller/admin/product/IotProductCategoryController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java new file mode 100644 index 000000000..b365ddea1 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.iot.controller.admin.product; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +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.product.vo.category.IotProductCategoryPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategoryRespVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategorySaveReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO; +import cn.iocoder.yudao.module.iot.service.product.IotProductCategoryService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - IoT 产品分类") +@RestController +@RequestMapping("/iot/product-category") +@Validated +public class IotProductCategoryController { + + @Resource + private IotProductCategoryService productCategoryService; + + @PostMapping("/create") + @Operation(summary = "创建IoT 产品分类") + @PreAuthorize("@ss.hasPermission('iot:product-category:create')") + public CommonResult createProductCategory(@Valid @RequestBody IotProductCategorySaveReqVO createReqVO) { + return success(productCategoryService.createProductCategory(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新IoT 产品分类") + @PreAuthorize("@ss.hasPermission('iot:product-category:update')") + public CommonResult updateProductCategory(@Valid @RequestBody IotProductCategorySaveReqVO updateReqVO) { + productCategoryService.updateProductCategory(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除IoT 产品分类") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('iot:product-category:delete')") + public CommonResult deleteProductCategory(@RequestParam("id") Long id) { + productCategoryService.deleteProductCategory(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得IoT 产品分类") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('iot:product-category:query')") + public CommonResult getProductCategory(@RequestParam("id") Long id) { + IotProductCategoryDO productCategory = productCategoryService.getProductCategory(id); + return success(BeanUtils.toBean(productCategory, IotProductCategoryRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得IoT 产品分类分页") + @PreAuthorize("@ss.hasPermission('iot:product-category:query')") + public CommonResult> getProductCategoryPage(@Valid IotProductCategoryPageReqVO pageReqVO) { + PageResult pageResult = productCategoryService.getProductCategoryPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, IotProductCategoryRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java index 254b6b9da..757750544 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java @@ -14,9 +14,13 @@ public class IotProductSaveReqVO { @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.AUTO, example = "1") private Long id; - @Schema(description = "产品Key", requiredMode = Schema.RequiredMode.AUTO, example = "12345abc") + @Schema(description = "产品 Key", requiredMode = Schema.RequiredMode.AUTO, example = "12345abc") private String productKey; + // TODO 芋艿:品类 + + // TODO 芋艿:【待确定】保活时长、产品图标、产品图片 + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "温湿度") @NotEmpty(message = "产品名称不能为空") private String name; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryPageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryPageReqVO.java new file mode 100644 index 000000000..90d338a89 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryPageReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.category; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - IoT 产品分类分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class IotProductCategoryPageReqVO extends PageParam { + + @Schema(description = "分类名字", example = "王五") + private String name; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryRespVO.java new file mode 100644 index 000000000..d684b0215 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategoryRespVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.category; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - IoT 产品分类 Response VO") +@Data +public class IotProductCategoryRespVO { + + @Schema(description = "分类 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "25284") + private Long id; + + @Schema(description = "分类名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") + private String name; + + @Schema(description = "分类排序") + private Integer sort; + + @Schema(description = "分类状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "分类描述", example = "随便") + private String description; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategorySaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategorySaveReqVO.java new file mode 100644 index 000000000..a7b2fe427 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/category/IotProductCategorySaveReqVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.category; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - IoT 产品分类新增/修改 Request VO") +@Data +public class IotProductCategorySaveReqVO { + + @Schema(description = "分类 ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "25284") + private Long id; + + @Schema(description = "分类名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "王五") + @NotEmpty(message = "分类名字不能为空") + private String name; + + @Schema(description = "分类排序") + private Integer sort; + + @Schema(description = "分类状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "分类状态不能为空") + private Integer status; + + @Schema(description = "分类描述", example = "随便") + private String description; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductCategoryDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductCategoryDO.java new file mode 100644 index 000000000..a6510488c --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductCategoryDO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.iot.dal.dataobject.product; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * IoT 产品分类 DO + * + * @author 芋道源码 + */ +@TableName("iot_product_category") +@KeySequence("iot_product_category_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class IotProductCategoryDO extends BaseDO { + + /** + * 分类 ID + */ + @TableId + private Long id; + /** + * 分类名字 + */ + private String name; + /** + * 分类排序 + */ + private Integer sort; + /** + * 分类状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 分类描述 + */ + private String description; + +} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductCategoryMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductCategoryMapper.java new file mode 100644 index 000000000..845eded14 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductCategoryMapper.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.iot.dal.mysql.product; + +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.module.iot.controller.admin.product.vo.category.IotProductCategoryPageReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * IoT 产品分类 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface IotProductCategoryMapper extends BaseMapperX { + + default PageResult selectPage(IotProductCategoryPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(IotProductCategoryDO::getName, reqVO.getName()) + .betweenIfPresent(IotProductCategoryDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(IotProductCategoryDO::getId)); + } + +} \ 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/IotProductCategoryService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryService.java new file mode 100644 index 000000000..9830ec8b9 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryService.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.iot.service.product; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategoryPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategorySaveReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO; +import jakarta.validation.Valid; + +/** + * IoT 产品分类 Service 接口 + * + * @author 芋道源码 + */ +public interface IotProductCategoryService { + + /** + * 创建IoT 产品分类 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProductCategory(@Valid IotProductCategorySaveReqVO createReqVO); + + /** + * 更新IoT 产品分类 + * + * @param updateReqVO 更新信息 + */ + void updateProductCategory(@Valid IotProductCategorySaveReqVO updateReqVO); + + /** + * 删除IoT 产品分类 + * + * @param id 编号 + */ + void deleteProductCategory(Long id); + + /** + * 获得IoT 产品分类 + * + * @param id 编号 + * @return IoT 产品分类 + */ + IotProductCategoryDO getProductCategory(Long id); + + /** + * 获得IoT 产品分类分页 + * + * @param pageReqVO 分页查询 + * @return IoT 产品分类分页 + */ + PageResult getProductCategoryPage(IotProductCategoryPageReqVO pageReqVO); + +} \ 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/IotProductCategoryServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryServiceImpl.java new file mode 100644 index 000000000..579d27cfb --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryServiceImpl.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.iot.service.product; + +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.product.vo.category.IotProductCategoryPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategorySaveReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO; +import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductCategoryMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PRODUCT_CATEGORY_NOT_EXISTS; + +/** + * IoT 产品分类 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class IotProductCategoryServiceImpl implements IotProductCategoryService { + + @Resource + private IotProductCategoryMapper productCategoryMapper; + + @Override + public Long createProductCategory(IotProductCategorySaveReqVO createReqVO) { + // 插入 + IotProductCategoryDO productCategory = BeanUtils.toBean(createReqVO, IotProductCategoryDO.class); + productCategoryMapper.insert(productCategory); + // 返回 + return productCategory.getId(); + } + + @Override + public void updateProductCategory(IotProductCategorySaveReqVO updateReqVO) { + // 校验存在 + validateProductCategoryExists(updateReqVO.getId()); + // 更新 + IotProductCategoryDO updateObj = BeanUtils.toBean(updateReqVO, IotProductCategoryDO.class); + productCategoryMapper.updateById(updateObj); + } + + @Override + public void deleteProductCategory(Long id) { + // 校验存在 + validateProductCategoryExists(id); + // 删除 + productCategoryMapper.deleteById(id); + } + + private void validateProductCategoryExists(Long id) { + if (productCategoryMapper.selectById(id) == null) { + throw exception(PRODUCT_CATEGORY_NOT_EXISTS); + } + } + + @Override + public IotProductCategoryDO getProductCategory(Long id) { + return productCategoryMapper.selectById(id); + } + + @Override + public PageResult getProductCategoryPage(IotProductCategoryPageReqVO pageReqVO) { + return productCategoryMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file From 9b9fd30c90bfb88d1ad61ef314ffab73e18264ea Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 7 Dec 2024 18:50:31 +0800 Subject: [PATCH 015/228] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E3=80=91IoT=EF=BC=9A=E4=BA=A7=E5=93=81=E6=94=BE?= =?UTF-8?q?=E5=88=B0=20product=20=E5=AD=90=E7=9B=AE=E5=BD=95=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/product/IotProductController.java | 13 +++--- .../product/vo/IotProductSimpleRespVO.java | 16 ------- .../vo/{ => product}/IotProductPageReqVO.java | 2 +- .../vo/{ => product}/IotProductRespVO.java | 43 +++++++++++-------- .../vo/{ => product}/IotProductSaveReqVO.java | 28 +++++++----- .../dal/dataobject/product/IotProductDO.java | 15 +++++-- .../dal/mysql/product/IotProductMapper.java | 2 +- .../service/product/IotProductService.java | 4 +- .../product/IotProductServiceImpl.java | 5 +-- .../dal/dataobject/notify/PayNotifyLogDO.java | 2 +- .../dataobject/notify/PayNotifyTaskDO.java | 4 +- 11 files changed, 68 insertions(+), 66 deletions(-) delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSimpleRespVO.java rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/{ => product}/IotProductPageReqVO.java (88%) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/{ => product}/IotProductRespVO.java (85%) rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/{ => product}/IotProductSaveReqVO.java (82%) 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 e7f41d91d..a4d111a99 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 @@ -3,10 +3,9 @@ package cn.iocoder.yudao.module.iot.controller.admin.product; import cn.iocoder.yudao.framework.common.pojo.CommonResult; 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.product.vo.IotProductPageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductRespVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSimpleRespVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductRespVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductSaveReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.service.product.IotProductService; import io.swagger.v3.oas.annotations.Operation; @@ -21,6 +20,7 @@ import org.springframework.web.bind.annotation.*; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @Tag(name = "管理后台 - IoT 产品") @RestController @@ -86,9 +86,10 @@ public class IotProductController { @GetMapping("/simple-list") @Operation(summary = "获得所有产品列表") @PreAuthorize("@ss.hasPermission('iot:product:query')") - public CommonResult> getSimpleProductList() { + public CommonResult> getSimpleProductList() { List list = productService.getProductList(); - return success(BeanUtils.toBean(list, IotProductSimpleRespVO.class)); + return success(convertList(list, product -> // 只返回 id、name 字段 + new IotProductRespVO().setId(product.getId()).setName(product.getName()))); } } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSimpleRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSimpleRespVO.java deleted file mode 100644 index 83855eaaf..000000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSimpleRespVO.java +++ /dev/null @@ -1,16 +0,0 @@ -package cn.iocoder.yudao.module.iot.controller.admin.product.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - IoT 产品 Response VO") -@Data -public class IotProductSimpleRespVO { - - @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "26087") - private Long id; - - @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") - private String name; - -} \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductPageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductPageReqVO.java similarity index 88% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductPageReqVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductPageReqVO.java index 3437f563f..d54adec48 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductPageReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.iot.controller.admin.product.vo; +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.product; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java similarity index 85% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductRespVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java index 0958b3e84..65d26ff5b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductRespVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.iot.controller.admin.product.vo; +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.product; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; @@ -20,34 +20,23 @@ public class IotProductRespVO { @ExcelProperty("产品名称") private String name; - @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("创建时间") - private LocalDateTime createTime; - @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("产品标识") private String productKey; - @Schema(description = "接入网关协议", example = "2") - @ExcelProperty("接入网关协议") - private Integer protocolType; - - @Schema(description = "协议编号(脚本解析 id)", requiredMode = Schema.RequiredMode.REQUIRED, example = "13177") - @ExcelProperty("协议编号(脚本解析 id)") - private Long protocolId; - - @Schema(description = "产品所属品类标识符", example = "14237") - @ExcelProperty("产品所属品类标识符") + @Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long categoryId; + @Schema(description = "产品图标", example = "https://iocoder.cn/1.svg") + private String icon; + + @Schema(description = "产品图标", example = "https://iocoder.cn/1.png") + private String picUrl; + @Schema(description = "产品描述", example = "你猜") @ExcelProperty("产品描述") private String description; - @Schema(description = "数据校验级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - @ExcelProperty("数据校验级别") - private Integer validateType; - @Schema(description = "产品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @ExcelProperty("产品状态") private Integer status; @@ -60,8 +49,24 @@ public class IotProductRespVO { @ExcelProperty("联网方式") private Integer netType; + @Schema(description = "接入网关协议", example = "2") + @ExcelProperty("接入网关协议") + private Integer protocolType; + + @Schema(description = "协议编号(脚本解析 id)", requiredMode = Schema.RequiredMode.REQUIRED, example = "13177") + @ExcelProperty("协议编号(脚本解析 id)") + private Long protocolId; + @Schema(description = "数据格式") @ExcelProperty("数据格式") private Integer dataFormat; + @Schema(description = "数据校验级别", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("数据校验级别") + private Integer validateType; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductSaveReqVO.java similarity index 82% rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductSaveReqVO.java index 757750544..31890beb7 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductSaveReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.iot.controller.admin.product.vo; +package cn.iocoder.yudao.module.iot.controller.admin.product.vo.product; import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.module.iot.enums.product.*; @@ -14,17 +14,26 @@ public class IotProductSaveReqVO { @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.AUTO, example = "1") private Long id; - @Schema(description = "产品 Key", requiredMode = Schema.RequiredMode.AUTO, example = "12345abc") - private String productKey; - - // TODO 芋艿:品类 - - // TODO 芋艿:【待确定】保活时长、产品图标、产品图片 - @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "温湿度") @NotEmpty(message = "产品名称不能为空") private String name; + @Schema(description = "产品 Key", requiredMode = Schema.RequiredMode.AUTO, example = "12345abc") + private String productKey; + + @Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "产品分类编号不能为空") + private Long categoryId; + + @Schema(description = "产品图标", example = "https://iocoder.cn/1.svg") + private String icon; + + @Schema(description = "产品图标", example = "https://iocoder.cn/1.png") + private String picUrl; + + @Schema(description = "产品描述", example = "描述") + private String description; + @Schema(description = "设备类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") @InEnum(value = IotProductDeviceTypeEnum.class, message = "设备类型必须是 {value}") @NotNull(message = "设备类型不能为空") @@ -48,7 +57,4 @@ public class IotProductSaveReqVO { @NotNull(message = "数据校验级别不能为空") private Integer validateType; - @Schema(description = "产品描述", example = "描述") - private String description; - } \ No newline at end of file diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java index eef466eda..34fd35706 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java @@ -22,7 +22,7 @@ import lombok.*; public class IotProductDO extends BaseDO { /** - * 产品ID + * 产品 ID */ @TableId private Long id; @@ -30,17 +30,24 @@ public class IotProductDO extends BaseDO { * 产品名称 */ private String name; - // TODO @haohao:这个字段,要不改成 identifier,和阿里云更统一些 /** * 产品标识 */ private String productKey; /** - * 产品所属品类编号 + * 产品分类编号 * - * TODO 外键:后续加 + * 关联 {@link IotProductCategoryDO#getId()} */ private Long categoryId; + /** + * 产品图标 + */ + private String icon; + /** + * 产品图片 + */ + private String picUrl; /** * 产品描述 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java index 0341e2492..eac1d29e8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.dal.mysql.product; 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.module.iot.controller.admin.product.vo.IotProductPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import org.apache.ibatis.annotations.Mapper; 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 3fff94fd9..bcbf13ef4 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 @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.iot.service.product; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductPageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductSaveReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import jakarta.validation.Valid; 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 d0ca09288..259bcaa1f 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 @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.iot.service.product; 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.product.vo.IotProductPageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductSaveReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductMapper; import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum; @@ -14,7 +14,6 @@ import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.util.List; diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java index a482605d5..384628370 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java @@ -44,7 +44,7 @@ public class PayNotifyLogDO extends BaseDO { /** * 支付通知状态 * - * 外键 {@link PayNotifyStatusEnum} + * 枚举 {@link PayNotifyStatusEnum} */ private Integer status; diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java index 7bfabad3f..9f9ee7fef 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java @@ -52,7 +52,7 @@ public class PayNotifyTaskDO extends TenantBaseDO { /** * 通知类型 * - * 外键 {@link PayNotifyTypeEnum} + * 枚举 {@link PayNotifyTypeEnum} */ private Integer type; /** @@ -73,7 +73,7 @@ public class PayNotifyTaskDO extends TenantBaseDO { /** * 通知状态 * - * 外键 {@link PayNotifyStatusEnum} + * 枚举 {@link PayNotifyStatusEnum} */ private Integer status; /** From a8c87d168accd14f5b266be9815046b1b45ff9db Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 7 Dec 2024 19:50:07 +0800 Subject: [PATCH 016/228] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E3=80=91IoT=EF=BC=9A=E4=BA=A7=E5=93=81=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=97=B6=EF=BC=8CproductKey=20=E7=94=B1=E5=89=8D?= =?UTF-8?q?=E7=AB=AF=E7=94=9F=E6=88=90=EF=BC=9B=E5=90=8C=E6=97=B6=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20icon=E3=80=81picUrl=20=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/iot/enums/ErrorCodeConstants.java | 2 +- .../enums/product/IotProductStatusEnum.java | 4 +-- .../product/IotProductCategoryController.java | 24 +++++++++++--- .../product/IotProductCategoryMapper.java | 6 ++++ .../product/IotProductCategoryService.java | 24 ++++++++++---- .../IotProductCategoryServiceImpl.java | 7 ++++ .../product/IotProductServiceImpl.java | 32 ++++--------------- .../IotThinkModelFunctionServiceImpl.java | 2 +- 8 files changed, 60 insertions(+), 41 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 1e947e633..d1d350d5e 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 @@ -11,7 +11,7 @@ public interface ErrorCodeConstants { // ========== 产品相关 1-050-001-000 ============ ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_050_001_000, "产品不存在"); - ErrorCode PRODUCT_IDENTIFICATION_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在"); + ErrorCode PRODUCT_KEY_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在"); ErrorCode PRODUCT_STATUS_NOT_DELETE = new ErrorCode(1_050_001_002, "产品状是发布状态,不允许删除"); ErrorCode PRODUCT_STATUS_NOT_ALLOW_FUNCTION = new ErrorCode(1_050_001_003, "产品状是发布状态,不允许操作物模型"); diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java index e64a3d678..7b4d90a5a 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java @@ -18,12 +18,12 @@ public enum IotProductStatusEnum implements IntArrayValuable { UNPUBLISHED(0, "开发中"), PUBLISHED(1, "已发布"); - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(IotProductStatusEnum::getType).toArray(); + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(IotProductStatusEnum::getStatus).toArray(); /** * 类型 */ - private final Integer type; + private final Integer status; /** * 描述 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java index b365ddea1..bc1c1fbf2 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.iot.controller.admin.product; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -17,7 +18,10 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.List; + import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @Tag(name = "管理后台 - IoT 产品分类") @RestController @@ -29,14 +33,14 @@ public class IotProductCategoryController { private IotProductCategoryService productCategoryService; @PostMapping("/create") - @Operation(summary = "创建IoT 产品分类") + @Operation(summary = "创建产品分类") @PreAuthorize("@ss.hasPermission('iot:product-category:create')") public CommonResult
- * TODO 外键:后续加 + * 关联 {@link IotProductCategoryDO#getId()} */ private Long categoryId; + /** + * 产品图标 + */ + private String icon; + /** + * 产品图片 + */ + private String picUrl; /** * 产品描述 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java index 0341e2492..eac1d29e8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.dal.mysql.product; 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.module.iot.controller.admin.product.vo.IotProductPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import org.apache.ibatis.annotations.Mapper; 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 3fff94fd9..bcbf13ef4 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 @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.iot.service.product; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductPageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductSaveReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import jakarta.validation.Valid; 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 d0ca09288..259bcaa1f 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 @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.iot.service.product; 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.product.vo.IotProductPageReqVO; -import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductPageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductSaveReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductMapper; import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum; @@ -14,7 +14,6 @@ import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.util.List; diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java index a482605d5..384628370 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyLogDO.java @@ -44,7 +44,7 @@ public class PayNotifyLogDO extends BaseDO { /** * 支付通知状态 * - * 外键 {@link PayNotifyStatusEnum} + * 枚举 {@link PayNotifyStatusEnum} */ private Integer status; diff --git a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java index 7bfabad3f..9f9ee7fef 100644 --- a/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java +++ b/yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java @@ -52,7 +52,7 @@ public class PayNotifyTaskDO extends TenantBaseDO { /** * 通知类型 * - * 外键 {@link PayNotifyTypeEnum} + * 枚举 {@link PayNotifyTypeEnum} */ private Integer type; /** @@ -73,7 +73,7 @@ public class PayNotifyTaskDO extends TenantBaseDO { /** * 通知状态 * - * 外键 {@link PayNotifyStatusEnum} + * 枚举 {@link PayNotifyStatusEnum} */ private Integer status; /** From a8c87d168accd14f5b266be9815046b1b45ff9db Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 7 Dec 2024 19:50:07 +0800 Subject: [PATCH 016/228] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E3=80=91IoT=EF=BC=9A=E4=BA=A7=E5=93=81=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=97=B6=EF=BC=8CproductKey=20=E7=94=B1=E5=89=8D?= =?UTF-8?q?=E7=AB=AF=E7=94=9F=E6=88=90=EF=BC=9B=E5=90=8C=E6=97=B6=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20icon=E3=80=81picUrl=20=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/iot/enums/ErrorCodeConstants.java | 2 +- .../enums/product/IotProductStatusEnum.java | 4 +-- .../product/IotProductCategoryController.java | 24 +++++++++++--- .../product/IotProductCategoryMapper.java | 6 ++++ .../product/IotProductCategoryService.java | 24 ++++++++++---- .../IotProductCategoryServiceImpl.java | 7 ++++ .../product/IotProductServiceImpl.java | 32 ++++--------------- .../IotThinkModelFunctionServiceImpl.java | 2 +- 8 files changed, 60 insertions(+), 41 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 1e947e633..d1d350d5e 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 @@ -11,7 +11,7 @@ public interface ErrorCodeConstants { // ========== 产品相关 1-050-001-000 ============ ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_050_001_000, "产品不存在"); - ErrorCode PRODUCT_IDENTIFICATION_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在"); + ErrorCode PRODUCT_KEY_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在"); ErrorCode PRODUCT_STATUS_NOT_DELETE = new ErrorCode(1_050_001_002, "产品状是发布状态,不允许删除"); ErrorCode PRODUCT_STATUS_NOT_ALLOW_FUNCTION = new ErrorCode(1_050_001_003, "产品状是发布状态,不允许操作物模型"); diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java index e64a3d678..7b4d90a5a 100644 --- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java +++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/product/IotProductStatusEnum.java @@ -18,12 +18,12 @@ public enum IotProductStatusEnum implements IntArrayValuable { UNPUBLISHED(0, "开发中"), PUBLISHED(1, "已发布"); - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(IotProductStatusEnum::getType).toArray(); + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(IotProductStatusEnum::getStatus).toArray(); /** * 类型 */ - private final Integer type; + private final Integer status; /** * 描述 */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java index b365ddea1..bc1c1fbf2 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductCategoryController.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.iot.controller.admin.product; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -17,7 +18,10 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.List; + import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; @Tag(name = "管理后台 - IoT 产品分类") @RestController @@ -29,14 +33,14 @@ public class IotProductCategoryController { private IotProductCategoryService productCategoryService; @PostMapping("/create") - @Operation(summary = "创建IoT 产品分类") + @Operation(summary = "创建产品分类") @PreAuthorize("@ss.hasPermission('iot:product-category:create')") public CommonResult