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 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