Commit 89fb71e8573d1f6552d70a699e3a8b1ec8612f02

Authored by 安浩浩
1 parent 9b30d5d3

【优化功能】 优化 tdengine 操作数据库相关代码

Showing 34 changed files with 348 additions and 885 deletions
yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/IotConstants.java 0 → 100644
  1 +package cn.iocoder.yudao.module.iot.enums;
  2 +
  3 +/**
  4 + * Iot 常量
  5 + *
  6 + * @author 芋道源码
  7 + */
  8 +public interface IotConstants {
  9 +
  10 + /**
  11 + * 获取设备表名
  12 + * <p>
  13 + * 格式为 device_{productKey}_{deviceName}
  14 + */
  15 + String DEVICE_TABLE_NAME_FORMAT = "device_%s_%s";
  16 +
  17 + /**
  18 + * 获取产品属性超级表名 - 网关子设备
  19 + * <p>
  20 + * 格式为 gateway_sub_{productKey}
  21 + */
  22 + String GATEWAY_SUB_STABLE_NAME_FORMAT = "gateway_sub_%s";
  23 +
  24 + /**
  25 + * 获取产品属性超级表名 - 网关
  26 + * <p>
  27 + * 格式为 gateway_{productKey}
  28 + */
  29 + String GATEWAY_STABLE_NAME_FORMAT = "gateway_%s";
  30 +
  31 + /**
  32 + * 获取产品属性超级表名 - 设备
  33 + * <p>
  34 + * 格式为 device_{productKey}
  35 + */
  36 + String DEVICE_STABLE_NAME_FORMAT = "device_%s";
  37 +
  38 +}
0 39 \ No newline at end of file
... ...
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;
3 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 5 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
6   -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataReqVO;
  6 +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO;
7 7 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataRespVO;
8 8 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO;
9 9 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotTimeDataRespVO;
... ... @@ -31,19 +31,17 @@ public class IotDeviceDataController {
31 31 @Resource
32 32 private IotDeviceDataService deviceDataService;
33 33  
34   - // TODO @haohao:是不是叫 get-latest 就好了。因为 data 已经在 url 里了哈
35   - @GetMapping("/latest-data")
  34 + @GetMapping("/latest")
36 35 @Operation(summary = "获取设备属性最新数据")
37   - public CommonResult<List<IotDeviceDataRespVO>> getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceDataReqVO) {
38   - List<IotDeviceDataDO> list = deviceDataService.getDevicePropertiesLatestData(deviceDataReqVO);
  36 + public CommonResult<List<IotDeviceDataRespVO>> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) {
  37 + List<IotDeviceDataDO> list = deviceDataService.getLatestDeviceProperties(deviceDataReqVO);
39 38 return success(BeanUtils.toBean(list, IotDeviceDataRespVO.class));
40 39 }
41 40  
42   - // TODO @haohao:是不是叫 /history-data => page
43   - @GetMapping("/history-data")
  41 + @GetMapping("/history")
44 42 @Operation(summary = "获取设备属性历史数据")
45   - public CommonResult<PageResult<IotTimeDataRespVO>> getDevicePropertiesHistoryData(@Valid IotDeviceDataReqVO deviceDataReqVO) {
46   - PageResult<Map<String, Object>> list = deviceDataService.getDevicePropertiesHistoryData(deviceDataReqVO);
  43 + public CommonResult<PageResult<IotTimeDataRespVO>> getHistoryDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) {
  44 + PageResult<Map<String, Object>> list = deviceDataService.getHistoryDeviceProperties(deviceDataReqVO);
47 45 return success(BeanUtils.toBean(list, IotTimeDataRespVO.class));
48 46 }
49 47  
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataReqVO.java renamed to 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;
10 10  
11 11 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
12 12  
13   -// TODO @haohao:IotDeviceDataPageReqVO
14 13 @Schema(description = "管理后台 - IoT 设备数据 Request VO")
15 14 @Data
16   -public class IotDeviceDataReqVO extends PageParam {
  15 +public class IotDeviceDataPageReqVO extends PageParam {
17 16  
18 17 @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "177")
19 18 private Long deviceId;
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/deviceData/IotDeviceDataRespVO.java
1 1 package cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData;
2 2  
3   -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
4   -import com.alibaba.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6   -import lombok.Builder;
7 4 import lombok.Data;
8 5  
9 6 import java.time.LocalDateTime;
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDataDO.java
1 1 package cn.iocoder.yudao.module.iot.dal.dataobject.device;
2 2  
3 3 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
4   -import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum;
5   -import com.baomidou.mybatisplus.annotation.TableId;
6   -import io.swagger.v3.oas.annotations.media.Schema;
  4 +import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
7 5 import lombok.AllArgsConstructor;
8 6 import lombok.Builder;
9 7 import lombok.Data;
10 8 import lombok.NoArgsConstructor;
11 9  
12   -import java.math.BigDecimal;
13 10 import java.time.LocalDateTime;
14 11  
15 12 /**
... ... @@ -23,39 +20,52 @@ import java.time.LocalDateTime;
23 20 @AllArgsConstructor
24 21 public class IotDeviceDataDO {
25 22  
26   - // TODO @haohao:每个字段的关联关系,可以 @ 下哈。
27 23 /**
28 24 * 设备编号
  25 + * <p>
  26 + * 关联 {@link IotDeviceDO#getId()}
29 27 */
30 28 private Long deviceId;
31 29  
32 30 /**
33 31 * 物模型编号
  32 + * <p>
  33 + * 关联 {@link IotThinkModelFunctionDO#getId()}
34 34 */
35 35 private Long thinkModelFunctionId;
36 36  
37 37 /**
38 38 * 产品标识
  39 + * <p>
  40 + * 关联 {@link IotProductDO#getProductKey()}
39 41 */
40 42 private String productKey;
41 43  
42 44 /**
43 45 * 设备名称
  46 + * <p>
  47 + * 冗余 {@link IotDeviceDO#getDeviceName()}
44 48 */
45 49 private String deviceName;
46 50  
47 51 /**
48 52 * 属性标识符
  53 + * <p>
  54 + * 关联 {@link IotThinkModelFunctionDO#getIdentifier()}
49 55 */
50 56 private String identifier;
51 57  
52 58 /**
53 59 * 属性名称
  60 + * <p>
  61 + * 关联 {@link IotThinkModelFunctionDO#getName()}
54 62 */
55 63 private String name;
56 64  
57 65 /**
58 66 * 数据类型
  67 + * <p>
  68 + * 关联 {@link IotThinkModelFunctionDO#getProperty()#getDataType()}
59 69 */
60 70 private String dataType;
61 71  
... ...
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 {
42 42 */
43 43 private String type;
44 44  
45   - // TODO @haohao:这个字段,是啥哈?
46   - /**
47   - * 查询条件
48   - */
49   - private Set<Integer> orgIds;
50   -
51 45 /**
52 46 * 设备ID
53 47 */
... ...
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 {
27 27 * 查询类型,0历史数据,1实时数据,2聚合数据
28 28 */
29 29 private int type;
  30 +
30 31 /**
31 32 * 查询的数据量
32 33 */
33 34 private int num;
  35 +
34 36 /**
35 37 * 聚合函数
36 38 */
37 39 private String aggregate;
  40 +
38 41 /**
39 42 * 统计间隔数字+s/m/h/d
40 43 * 比如1s,1m,1h,1d代表1秒,1分钟,1小时,1天
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/tdengine/TableManager.java deleted
1   -package cn.iocoder.yudao.module.iot.dal.dataobject.tdengine;
2   -
3   -import java.util.List;
4   -
5   -// TODO @haohao:这个还有用哇?
6   -/**
7   - * TableManager 类用于管理 TDengine 表的创建、删除和结构信息获取
8   - */
9   -public class TableManager {
10   -
11   - /**
12   - * 创建超级表模板(含存在判断)
13   - */
14   - private static final String CREATE_STABLE_INE_TPL = "CREATE STABLE IF NOT EXISTS %s (%s) TAGS (%s);";
15   -
16   - /**
17   - * 删除超级表
18   - */
19   - private static final String DROP_STABLE_TPL = "DROP STABLE IF EXISTS %s;";
20   -
21   - /**
22   - * 获取表的结构信息
23   - */
24   - private static final String DESC_TB_TPL = "DESCRIBE %s;";
25   -
26   - /**
27   - * 超级表增加列
28   - */
29   - private static final String ALTER_STABLE_ADD_COL_TPL = "ALTER STABLE %s ADD COLUMN %s;";
30   -
31   - /**
32   - * 超级表修改列
33   - */
34   - private static final String ALTER_STABLE_MODIFY_COL_TPL = "ALTER STABLE %s MODIFY COLUMN %s;";
35   -
36   - /**
37   - * 超级表删除列
38   - */
39   - private static final String ALTER_STABLE_DROP_COL_TPL = "ALTER STABLE %s DROP COLUMN %s;";
40   -
41   - /**
42   - * 创建普通表模板(含存在判断)
43   - */
44   - private static final String CREATE_CTABLE_INE_TPL = "CREATE TABLE IF NOT EXISTS %s (%s)";
45   -
46   - /**
47   - * 获取创建表sql
48   - */
49   - public static String getCreateSTableSql(String tbName, List<TdFieldDO> fields, TdFieldDO... tags) {
50   - if (fields.isEmpty()) {
51   - return null;
52   - }
53   -
54   - // 生成字段片段
55   - StringBuilder sbField = new StringBuilder("time TIMESTAMP,");
56   -
57   - for (TdFieldDO field : fields) {
58   - sbField.append(FieldParser.getFieldDefine(field));
59   - sbField.append(",");
60   - }
61   - sbField.deleteCharAt(sbField.length() - 1);
62   -
63   - String fieldFrag = sbField.toString();
64   -
65   - // 生成tag
66   - StringBuilder sbTag = new StringBuilder();
67   - for (TdFieldDO tag : tags) {
68   - sbTag.append(FieldParser.getFieldDefine(tag))
69   - .append(",");
70   - }
71   - sbTag.deleteCharAt(sbTag.length() - 1);
72   -
73   - return String.format(CREATE_STABLE_INE_TPL, tbName, fieldFrag, sbTag);
74   -
75   - }
76   -
77   - /**
78   - * 获取创建普通表sql
79   - */
80   - public static String getCreateCTableSql(String tbName, List<TdFieldDO> fields) {
81   - if (fields.size() == 0) {
82   - return null;
83   - }
84   -
85   - //生成字段片段
86   - StringBuilder sbField = new StringBuilder("time timestamp,");
87   -
88   - for (TdFieldDO field : fields) {
89   - sbField.append(FieldParser.getFieldDefine(field));
90   - sbField.append(",");
91   - }
92   - sbField.deleteCharAt(sbField.length() - 1);
93   -
94   - String fieldFrag = sbField.toString();
95   -
96   - return String.format(CREATE_CTABLE_INE_TPL, tbName, fieldFrag);
97   -
98   - }
99   -
100   -
101   - /**
102   - * 取正确的表名
103   - *
104   - * @param name 表象
105   - */
106   - public static String rightTbName(String name) {
107   - return name.toLowerCase().replace("-" , "_");
108   - }
109   -
110   - /**
111   - * 获取表详情的sql
112   - */
113   - public static String getDescTableSql(String tbName) {
114   - return String.format(DESC_TB_TPL, tbName);
115   - }
116   -
117   - /**
118   - * 获取添加字段sql
119   - */
120   - public static String getAddSTableColumnSql(String tbName, List<TdFieldDO> fields) {
121   - StringBuilder sbAdd = new StringBuilder();
122   - for (TdFieldDO field : fields) {
123   - sbAdd.append(String.format(ALTER_STABLE_ADD_COL_TPL,
124   - tbName,
125   - FieldParser.getFieldDefine(field)
126   - ));
127   - }
128   - return sbAdd.toString();
129   - }
130   -
131   - /**
132   - * 获取修改字段sql
133   - */
134   - public static String getModifySTableColumnSql(String tbName, List<TdFieldDO> fields) {
135   - StringBuilder sbModify = new StringBuilder();
136   - for (TdFieldDO field : fields) {
137   - sbModify.append(String.format(ALTER_STABLE_MODIFY_COL_TPL,
138   - tbName,
139   - FieldParser.getFieldDefine(field)
140   - ));
141   - }
142   - return sbModify.toString();
143   - }
144   -
145   - /**
146   - * 获取删除字段sql
147   - */
148   - public static String getDropSTableColumnSql(String tbName, List<TdFieldDO> fields) {
149   - StringBuilder sbDrop = new StringBuilder();
150   - for (TdFieldDO field : fields) {
151   - sbDrop.append(String.format(ALTER_STABLE_DROP_COL_TPL,
152   - tbName,
153   - field.getFieldName()
154   - ));
155   - }
156   - return sbDrop.toString();
157   - }
158   -
159   -}
160 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineSuperTableMapper.java renamed to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDDLMapper.java
1 1 package cn.iocoder.yudao.module.iot.dal.tdengine;
2 2  
  3 +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
3 4 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
4 5 import com.baomidou.dynamic.datasource.annotation.DS;
5 6 import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
6 7 import org.apache.ibatis.annotations.Mapper;
  8 +import org.apache.ibatis.annotations.Param;
7 9  
8 10 import java.util.List;
9 11 import java.util.Map;
10 12  
11 13 /**
12   - * TD 引擎的超级表 Mapper
  14 + * 专门处理 DDL(数据定义语言)操作,包含所有的数据库和表的定义操作,例如创建数据库、创建超级表、创建子表等
13 15 */
14 16 @Mapper
15 17 @DS("tdengine")
16   -public interface TdEngineSuperTableMapper {
  18 +public interface TdEngineDDLMapper {
  19 +
  20 + /**
  21 + * 创建数据库
  22 + * SQL:CREATE DATABASE [IF NOT EXISTS] db_name [database_options];
  23 + *
  24 + * @param dataBaseName 数据库名称
  25 + */
  26 + @TenantIgnore
  27 + void createDatabase(@Param("dataBaseName") String dataBaseName);
17 28  
18 29 /**
19 30 * 创建超级表
... ... @@ -25,7 +36,7 @@ public interface TdEngineSuperTableMapper {
25 36 * columns 列信息
26 37 * tags 标签信息
27 38 */
28   - @InterceptorIgnore(tenantLine = "true")
  39 + @TenantIgnore
29 40 void createSuperTable(TdTableDO superTable);
30 41  
31 42 /**
... ... @@ -36,7 +47,7 @@ public interface TdEngineSuperTableMapper {
36 47 * dataBaseName 数据库名称
37 48 * superTableName 超级表名称
38 49 */
39   - @InterceptorIgnore(tenantLine = "true")
  50 + @TenantIgnore
40 51 List<Map<String, Object>> showSuperTables(TdTableDO superTable);
41 52  
42 53 /**
... ... @@ -47,7 +58,7 @@ public interface TdEngineSuperTableMapper {
47 58 * dataBaseName 数据库名称
48 59 * superTableName 超级表名称
49 60 */
50   - @InterceptorIgnore(tenantLine = "true")
  61 + @TenantIgnore
51 62 List<Map<String, Object>> describeSuperTable(TdTableDO superTable);
52 63  
53 64 /**
... ... @@ -59,7 +70,7 @@ public interface TdEngineSuperTableMapper {
59 70 * superTableName 超级表名称
60 71 * column 列信息
61 72 */
62   - @InterceptorIgnore(tenantLine = "true")
  73 + @TenantIgnore
63 74 void addColumnForSuperTable(TdTableDO superTable);
64 75  
65 76 /**
... ... @@ -71,7 +82,7 @@ public interface TdEngineSuperTableMapper {
71 82 * superTableName 超级表名称
72 83 * column 列信息
73 84 */
74   - @InterceptorIgnore(tenantLine = "true")
  85 + @TenantIgnore
75 86 void dropColumnForSuperTable(TdTableDO superTable);
76 87  
77 88 /**
... ... @@ -83,7 +94,7 @@ public interface TdEngineSuperTableMapper {
83 94 * superTableName 超级表名称
84 95 * column 列信息
85 96 */
86   - @InterceptorIgnore(tenantLine = "true")
  97 + @TenantIgnore
87 98 void modifyColumnWidthForSuperTable(TdTableDO superTable);
88 99  
89 100  
... ... @@ -95,7 +106,7 @@ public interface TdEngineSuperTableMapper {
95 106 * superTableName 超级表名称
96 107 * tag 标签信息
97 108 */
98   - @InterceptorIgnore(tenantLine = "true")
  109 + @TenantIgnore
99 110 void addTagForSuperTable(TdTableDO superTable);
100 111  
101 112 /**
... ... @@ -106,6 +117,33 @@ public interface TdEngineSuperTableMapper {
106 117 * superTableName 超级表名称
107 118 * tag 标签信息
108 119 */
109   - @InterceptorIgnore(tenantLine = "true")
  120 + @TenantIgnore
110 121 void dropTagForSuperTable(TdTableDO superTable);
111   -}
112 122 \ No newline at end of file
  123 +
  124 + /**
  125 + * 创建子表 - 创建子表
  126 + * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name TAGS (tag_value1, ...);
  127 + *
  128 + * @param table 表信息
  129 + * dataBaseName 数据库名称
  130 + * superTableName 超级表名称
  131 + * tableName 子表名称
  132 + * tags TAG 字段
  133 + */
  134 + @TenantIgnore
  135 + void createTable(TdTableDO table);
  136 +
  137 + /**
  138 + * 创建子表 - 创建子表并指定标签的值
  139 + * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name (tag_name1, ...) TAGS (tag_value1, ...);
  140 + *
  141 + * @param table 表信息
  142 + * dataBaseName 数据库名称
  143 + * superTableName 超级表名称
  144 + * tableName 子表名称
  145 + * tags TAG 字段
  146 + */
  147 + @TenantIgnore
  148 + void createTableWithTags(TdTableDO table);
  149 +
  150 +}
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineQueryMapper.java renamed to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDMLMapper.java
1 1 package cn.iocoder.yudao.module.iot.dal.tdengine;
2 2  
  3 +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
3 4 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectDO;
4 5 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO;
5 6 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TagsSelectDO;
  7 +import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
6 8 import com.baomidou.dynamic.datasource.annotation.DS;
7   -import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
8 9 import org.apache.ibatis.annotations.Mapper;
9 10  
10 11 import java.util.List;
11 12 import java.util.Map;
12 13  
13 14 /**
14   - * TD 引擎的查询 Mapper
  15 + * 专门处理 TD Engine 的 DML(数据操作语言)操作,处理所有的数据查询和写入操作,如插入数据、查询数据等
15 16 */
16 17 @Mapper
17 18 @DS("tdengine")
18   -public interface TdEngineQueryMapper {
  19 +public interface TdEngineDMLMapper {
  20 +
  21 + /**
  22 + * 插入数据 - 指定列插入数据
  23 + *
  24 + * @param table 数据
  25 + * dataBaseName 数据库名
  26 + * tableName 表名
  27 + * columns 列
  28 + */
  29 + @TenantIgnore
  30 + void insertData(TdTableDO table);
19 31  
20 32 /**
21 33 * 根据时间戳查询数据
22 34 *
23 35 * @param selectDO 查询条件
24   - * @return 查询结果
  36 + * @return 查询结果列表
25 37 */
  38 + @TenantIgnore
26 39 List<Map<String, Object>> selectByTimestamp(SelectDO selectDO);
27 40  
28   - // TODO @haohao:最好方法的命名,和数据库操作的保持一直。get => select。然后 selectList or selectOne
29 41 /**
30 42 * 根据时间戳获取数据条数
31 43 *
32 44 * @param selectDO 查询条件
33 45 * @return 数据条数
34 46 */
35   - Map<String, Long> getCountByTimestamp(SelectDO selectDO);
  47 + @TenantIgnore
  48 + Map<String, Long> selectCountByTimestamp(SelectDO selectDO);
36 49  
37 50 /**
38 51 * 获取最新数据
... ... @@ -40,40 +53,44 @@ public interface TdEngineQueryMapper {
40 53 * @param selectDO 查询条件
41 54 * @return 最新数据
42 55 */
43   - Map<String, Object> getLastData(SelectDO selectDO);
  56 + @TenantIgnore
  57 + Map<String, Object> selectOneLastData(SelectDO selectDO);
44 58  
45 59 /**
46   - * 获取历史数据
  60 + * 获取历史数据列表
47 61 *
48 62 * @param selectVisualDO 查询条件
49 63 * @return 历史数据列表
50 64 */
51   - @InterceptorIgnore(tenantLine = "true")
52   - List<Map<String, Object>> getHistoryData(SelectVisualDO selectVisualDO);
  65 + @TenantIgnore
  66 + List<Map<String, Object>> selectHistoryDataList(SelectVisualDO selectVisualDO);
53 67  
54 68 /**
55   - * 获取实时数据
  69 + * 获取实时数据列表
56 70 *
57 71 * @param selectVisualDO 查询条件
58 72 * @return 实时数据列表
59 73 */
60   - List<Map<String, Object>> getRealtimeData(SelectVisualDO selectVisualDO);
  74 + @TenantIgnore
  75 + List<Map<String, Object>> selectRealtimeDataList(SelectVisualDO selectVisualDO);
61 76  
62 77 /**
63   - * 获取聚合数据
  78 + * 获取聚合数据列表
64 79 *
65 80 * @param selectVisualDO 查询条件
66 81 * @return 聚合数据列表
67 82 */
68   - List<Map<String, Object>> getAggregateData(SelectVisualDO selectVisualDO);
  83 + @TenantIgnore
  84 + List<Map<String, Object>> selectAggregateDataList(SelectVisualDO selectVisualDO);
69 85  
70 86 /**
71   - * 根据标签获取最新数据
  87 + * 根据标签获取最新数据列表
72 88 *
73 89 * @param tagsSelectDO 查询条件
74 90 * @return 最新数据列表
75 91 */
76   - List<Map<String, Object>> getLastDataByTags(TagsSelectDO tagsSelectDO);
  92 + @TenantIgnore
  93 + List<Map<String, Object>> selectLastDataListByTags(TagsSelectDO tagsSelectDO);
77 94  
78 95 /**
79 96 * 获取历史数据条数
... ... @@ -81,6 +98,6 @@ public interface TdEngineQueryMapper {
81 98 * @param selectVisualDO 查询条件
82 99 * @return 数据条数
83 100 */
84   - @InterceptorIgnore(tenantLine = "true")
85   - Long getHistoryCount(SelectVisualDO selectVisualDO);
86   -}
  101 + @TenantIgnore
  102 + Long selectHistoryCount(SelectVisualDO selectVisualDO);
  103 +}
87 104 \ No newline at end of file
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDataWriterMapper.java deleted
1   -package cn.iocoder.yudao.module.iot.dal.tdengine;
2   -
3   -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
4   -import com.baomidou.dynamic.datasource.annotation.DS;
5   -import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
6   -import org.apache.ibatis.annotations.Mapper;
7   -
8   -/**
9   - * TD 引擎的数据写入 Mapper
10   - */
11   -@Mapper
12   -@DS("tdengine")
13   -public interface TdEngineDataWriterMapper {
14   -
15   - /**
16   - * 插入数据 - 指定列插入数据
17   - *
18   - * @param table 数据
19   - * dataBaseName 数据库名
20   - * tableName 表名
21   - * columns 列
22   - */
23   - @InterceptorIgnore(tenantLine = "true")
24   - void insertData(TdTableDO table);
25   -}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineDatabaseMapper.java deleted
1   -package cn.iocoder.yudao.module.iot.dal.tdengine;
2   -
3   -import com.baomidou.dynamic.datasource.annotation.DS;
4   -import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
5   -import org.apache.ibatis.annotations.Mapper;
6   -import org.apache.ibatis.annotations.Param;
7   -
8   -// TODO @haohao:InterceptorIgnore 忽略租户,可以在每个方法上,添加 @TenantIgnore 哈。
9   -/**
10   - * TD 引擎的数据库 Mapper
11   - */
12   -@Mapper
13   -@DS("tdengine")
14   -public interface TdEngineDatabaseMapper {
15   -
16   - /**
17   - * 创建数据库
18   - * SQL:CREATE DATABASE [IF NOT EXISTS] db_name [database_options];
19   - *
20   - * @param dataBaseName 数据库名称
21   - */
22   - @InterceptorIgnore(tenantLine = "true")
23   - void createDatabase(@Param("dataBaseName") String dataBaseName);
24   -}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/TdEngineTableMapper.java deleted
1   -package cn.iocoder.yudao.module.iot.dal.tdengine;
2   -
3   -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
4   -import com.baomidou.dynamic.datasource.annotation.DS;
5   -import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
6   -import org.apache.ibatis.annotations.Mapper;
7   -
8   -/**
9   - * TD 引擎的表 Mapper
10   - */
11   -@Mapper
12   -@DS("tdengine")
13   -public interface TdEngineTableMapper {
14   -
15   - /**
16   - * 创建子表 - 创建子表
17   - * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name TAGS (tag_value1, ...);
18   - *
19   - * @param table 表信息
20   - * dataBaseName 数据库名称
21   - * superTableName 超级表名称
22   - * tableName 子表名称
23   - * tags TAG 字段
24   - */
25   - @InterceptorIgnore(tenantLine = "true")
26   - void createTable(TdTableDO table);
27   -
28   - /**
29   - * 创建子表 - 创建子表并指定标签的值
30   - * SQL:CREATE TABLE [IF NOT EXISTS] tb_name USING stb_name (tag_name1, ...) TAGS (tag_value1, ...);
31   - *
32   - * @param table 表信息
33   - * dataBaseName 数据库名称
34   - * superTableName 超级表名称
35   - * tableName 子表名称
36   - * tags TAG 字段
37   - */
38   - @InterceptorIgnore(tenantLine = "true")
39   - void createTableWithTags(TdTableDO table);
40   -
41   -}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataService.java
1 1 package cn.iocoder.yudao.module.iot.service.device;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4   -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataReqVO;
  4 +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO;
5 5 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO;
6 6 import jakarta.validation.Valid;
7 7  
... ... @@ -31,7 +31,7 @@ public interface IotDeviceDataService {
31 31 * @param deviceId 设备编号
32 32 * @return 设备属性最新数据
33 33 */
34   - List<IotDeviceDataDO> getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceId);
  34 + List<IotDeviceDataDO> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceId);
35 35  
36 36 /**
37 37 * 获得设备属性历史数据
... ... @@ -39,5 +39,5 @@ public interface IotDeviceDataService {
39 39 * @param deviceDataReqVO 设备属性历史数据 Request VO
40 40 * @return 设备属性历史数据
41 41 */
42   - PageResult<Map<String, Object>> getDevicePropertiesHistoryData(@Valid IotDeviceDataReqVO deviceDataReqVO);
  42 + PageResult<Map<String, Object>> getHistoryDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO);
43 43 }
44 44 \ No newline at end of file
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceDataServiceImpl.java
1 1 package cn.iocoder.yudao.module.iot.service.device;
2 2  
3 3 import cn.hutool.core.date.DateUtil;
  4 +import cn.hutool.core.util.StrUtil;
4 5 import cn.hutool.json.JSONObject;
5 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6   -import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataReqVO;
  7 +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.deviceData.IotDeviceDataPageReqVO;
7 8 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
8 9 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDataDO;
9 10 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO;
10 11 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage;
11 12 import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
12 13 import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO;
  14 +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper;
  15 +import cn.iocoder.yudao.module.iot.enums.IotConstants;
13 16 import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum;
14 17 import cn.iocoder.yudao.module.iot.service.tdengine.IotThingModelMessageService;
15   -import cn.iocoder.yudao.module.iot.service.tdengine.TdEngineQueryService;
16 18 import cn.iocoder.yudao.module.iot.service.thinkmodelfunction.IotThinkModelFunctionService;
17 19 import jakarta.annotation.Resource;
18 20 import jakarta.validation.Valid;
... ... @@ -40,7 +42,7 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService {
40 42 @Resource
41 43 private IotThinkModelFunctionService thinkModelFunctionService;
42 44 @Resource
43   - private TdEngineQueryService tdEngineQueryService;
  45 + private TdEngineDMLMapper tdEngineDMLMapper;
44 46  
45 47 @Resource
46 48 private DeviceDataRedisDAO deviceDataRedisDAO;
... ... @@ -66,7 +68,7 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService {
66 68 }
67 69  
68 70 @Override
69   - public List<IotDeviceDataDO> getDevicePropertiesLatestData(@Valid IotDeviceDataReqVO deviceDataReqVO) {
  71 + public List<IotDeviceDataDO> getLatestDeviceProperties(@Valid IotDeviceDataPageReqVO deviceDataReqVO) {
70 72 List<IotDeviceDataDO> list = new ArrayList<>();
71 73 // 1. 获取设备信息
72 74 IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId());
... ... @@ -106,7 +108,7 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService {
106 108 }
107 109  
108 110 @Override
109   - public PageResult<Map<String, Object>> getDevicePropertiesHistoryData(IotDeviceDataReqVO deviceDataReqVO) {
  111 + public PageResult<Map<String, Object>> getHistoryDeviceProperties(IotDeviceDataPageReqVO deviceDataReqVO) {
110 112 PageResult<Map<String, Object>> pageResult = new PageResult<>();
111 113 // 1. 获取设备信息
112 114 IotDeviceDO device = deviceService.getDevice(deviceDataReqVO.getDeviceId());
... ... @@ -121,17 +123,17 @@ public class IotDeviceDataServiceImpl implements IotDeviceDataService {
121 123 params.put("rows", deviceDataReqVO.getPageSize());
122 124 params.put("page", (deviceDataReqVO.getPageNo() - 1) * deviceDataReqVO.getPageSize());
123 125 selectVisualDO.setParams(params);
124   - pageResult.setList(tdEngineQueryService.getHistoryData(selectVisualDO));
125   - pageResult.setTotal(tdEngineQueryService.getHistoryCount(selectVisualDO));
  126 + pageResult.setList(tdEngineDMLMapper.selectHistoryDataList(selectVisualDO));
  127 + pageResult.setTotal(tdEngineDMLMapper.selectHistoryCount(selectVisualDO));
126 128 return pageResult;
127 129 }
128 130  
129 131 private String getDatabaseName() {
130   - return url.substring(url.lastIndexOf("/") + 1);
  132 + return StrUtil.subAfter(url, "/", true);
131 133 }
132 134  
133 135 private static String getDeviceTableName(String productKey, String deviceName) {
134   - return String.format("device_%s_%s", productKey.toLowerCase(), deviceName.toLowerCase());
  136 + return String.format(IotConstants.DEVICE_TABLE_NAME_FORMAT, productKey, deviceName);
135 137 }
136 138  
137 139 -}
  140 +}
138 141 \ No newline at end of file
... ...
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;
19 19 import org.springframework.transaction.annotation.Transactional;
20 20 import org.springframework.validation.annotation.Validated;
21 21  
  22 +import java.security.SecureRandom;
22 23 import java.time.LocalDateTime;
  24 +import java.util.Base64;
23 25 import java.util.Objects;
24 26 import java.util.UUID;
25 27  
... ... @@ -137,10 +139,13 @@ public class IotDeviceServiceImpl implements IotDeviceService {
137 139 * @return 生成的 MQTT Password
138 140 */
139 141 private String generateMqttPassword() {
140   - // TODO @haohao:【后续优化】在实际应用中,建议使用更安全的方法生成 MQTT Password,如加密或哈希
141   - return UUID.randomUUID().toString();
  142 + SecureRandom secureRandom = new SecureRandom();
  143 + byte[] passwordBytes = new byte[32]; // 256 位的随机数
  144 + secureRandom.nextBytes(passwordBytes);
  145 + return Base64.getUrlEncoder().withoutPadding().encodeToString(passwordBytes);
142 146 }
143 147  
  148 +
144 149 /**
145 150 * 生成唯一的 DeviceName
146 151 *
... ... @@ -214,30 +219,28 @@ public class IotDeviceServiceImpl implements IotDeviceService {
214 219 @Override
215 220 public void updateDeviceStatus(IotDeviceStatusUpdateReqVO updateReqVO) {
216 221 // 1. 校验存在
217   - // TODO @haohao:这里的 iotDeviceDO => device。一个是去掉 iot,一个是去掉 DO 后缀。这样,简洁一点。
218   - IotDeviceDO iotDeviceDO = validateDeviceExists(updateReqVO.getId());
  222 + IotDeviceDO device = validateDeviceExists(updateReqVO.getId());
219 223  
220 224 // 2.1 更新状态和更新时间
221   - IotDeviceDO updateObj = BeanUtils.toBean(updateReqVO, IotDeviceDO.class);
222   - // TODO @haohao:下面几个状态的处理,可以考虑 if else if。这样,看起来会有层次感哈
223   - // 2.2.1 以前是未激活,现在是上线,设置设备激活时间
224   - // TODO @haohao:这里可以使用 ObjectUtils.equalsAny 类似这种哈。
225   - if (Objects.equals(iotDeviceDO.getStatus(), IotDeviceStatusEnum.INACTIVE.getStatus())
226   - && Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) {
227   - updateObj.setActiveTime(LocalDateTime.now());
228   - }
229   - // 2.2.2 如果是上线,设置上线时间
230   - if (Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) {
231   - updateObj.setLastOnlineTime(LocalDateTime.now());
232   - }
233   - // 2.2.3 如果是离线,设置离线时间
234   - if (Objects.equals(updateObj.getStatus(), IotDeviceStatusEnum.OFFLINE.getStatus())) {
235   - updateObj.setLastOfflineTime(LocalDateTime.now());
  225 + IotDeviceDO updateDevice = BeanUtils.toBean(updateReqVO, IotDeviceDO.class);
  226 + // 2.2 更新状态相关时间
  227 + if (Objects.equals(device.getStatus(), IotDeviceStatusEnum.INACTIVE.getStatus())
  228 + && Objects.equals(updateDevice.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) {
  229 + // 从未激活到在线,设置激活时间和最后上线时间
  230 + updateDevice.setActiveTime(LocalDateTime.now());
  231 + updateDevice.setLastOnlineTime(LocalDateTime.now());
  232 + } else if (Objects.equals(updateDevice.getStatus(), IotDeviceStatusEnum.ONLINE.getStatus())) {
  233 + // 如果是上线,设置最后上线时间
  234 + updateDevice.setLastOnlineTime(LocalDateTime.now());
  235 + } else if (Objects.equals(updateDevice.getStatus(), IotDeviceStatusEnum.OFFLINE.getStatus())) {
  236 + // 如果是离线,设置最后离线时间
  237 + updateDevice.setLastOfflineTime(LocalDateTime.now());
236 238 }
  239 +
237 240 // 2.3 设置状态更新时间
238   - updateObj.setStatusLastUpdateTime(LocalDateTime.now());
  241 + updateDevice.setStatusLastUpdateTime(LocalDateTime.now());
239 242 // 2.4 更新到数据库
240   - deviceMapper.updateById(updateObj);
  243 + deviceMapper.updateById(updateDevice);
241 244 }
242 245  
243 246 @Override
... ...
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 {
15 15 * 创建超级表数据模型
16 16 */
17 17 void createSuperTableDataModel(IotProductDO product, List<IotThinkModelFunctionDO> functionList);
18 18 -}
  19 +}
19 20 \ No newline at end of file
... ...
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;
9 9 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO;
10 10 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
11 11 import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
  12 +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper;
  13 +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper;
12 14 import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum;
13 15 import jakarta.annotation.Resource;
14 16 import lombok.extern.slf4j.Slf4j;
... ... @@ -26,7 +28,7 @@ import java.util.stream.Collectors;
26 28 public class IotSuperTableServiceImpl implements IotSuperTableService {
27 29  
28 30 @Resource
29   - private TdEngineSuperTableService tdEngineSuperTableService;
  31 + private TdEngineDDLMapper tdEngineDDLMapper;
30 32  
31 33 @Value("${spring.datasource.dynamic.datasource.tdengine.url}")
32 34 private String url;
... ... @@ -42,9 +44,10 @@ public class IotSuperTableServiceImpl implements IotSuperTableService {
42 44  
43 45 String superTableName = getSuperTableName(product.getDeviceType(), product.getProductKey());
44 46 String databaseName = getDatabaseName();
45   - Integer tableExists = tdEngineSuperTableService.checkSuperTableExists(new TdTableDO(databaseName, superTableName));
46 47  
47   - if (tableExists != null && tableExists > 0) {
  48 + List<Map<String, Object>> results = tdEngineDDLMapper.showSuperTables(new TdTableDO(databaseName, superTableName));
  49 + int tableExists = results == null || results.isEmpty() ? 0 : results.size();
  50 + if (tableExists > 0) {
48 51 updateSuperTable(thingModel, product.getDeviceType());
49 52 } else {
50 53 createSuperTable(thingModel, product.getDeviceType());
... ... @@ -76,7 +79,7 @@ public class IotSuperTableServiceImpl implements IotSuperTableService {
76 79 String databaseName = getDatabaseName();
77 80  
78 81 // 创建超级表
79   - tdEngineSuperTableService.createSuperTable(new TdTableDO(databaseName, superTableName, schemaFields, tagsFields));
  82 + tdEngineDDLMapper.createSuperTable(new TdTableDO(databaseName, superTableName, schemaFields, tagsFields));
80 83 }
81 84  
82 85 /**
... ... @@ -98,7 +101,7 @@ public class IotSuperTableServiceImpl implements IotSuperTableService {
98 101 * 获取表的字段信息
99 102 */
100 103 private List<TdFieldDO> getTableFields(String tableName) {
101   - List<Map<String, Object>> tableDescription = tdEngineSuperTableService.describeSuperTable(new TdTableDO(getDatabaseName(), tableName));
  104 + List<Map<String, Object>> tableDescription = tdEngineDDLMapper.describeSuperTable(new TdTableDO(getDatabaseName(), tableName));
102 105 if (CollUtil.isEmpty(tableDescription)) {
103 106 return Collections.emptyList();
104 107 }
... ... @@ -127,32 +130,38 @@ public class IotSuperTableServiceImpl implements IotSuperTableService {
127 130  
128 131 // 添加新增字段
129 132 if (CollUtil.isNotEmpty(addFields)) {
130   - tdEngineSuperTableService.addColumnsForSuperTable(TdTableDO.builder()
131   - .dataBaseName(databaseName)
132   - .superTableName(tableName)
133   - .columns(addFields)
134   - .build());
  133 + for (TdFieldDO addField : addFields) {
  134 + tdEngineDDLMapper.addColumnForSuperTable(TdTableDO.builder()
  135 + .dataBaseName(databaseName)
  136 + .superTableName(tableName)
  137 + .column(addField)
  138 + .build());
  139 + }
135 140 }
136 141 // 删除旧字段
137 142 if (CollUtil.isNotEmpty(dropFields)) {
138   - tdEngineSuperTableService.dropColumnsForSuperTable(TdTableDO.builder()
139   - .dataBaseName(databaseName)
140   - .superTableName(tableName)
141   - .columns(dropFields)
142   - .build());
  143 + for (TdFieldDO dropField : dropFields) {
  144 + tdEngineDDLMapper.dropColumnForSuperTable(TdTableDO.builder()
  145 + .dataBaseName(databaseName)
  146 + .superTableName(tableName)
  147 + .column(dropField)
  148 + .build());
  149 + }
143 150 }
144 151 // 修改字段(先删除再添加)
145 152 if (CollUtil.isNotEmpty(modifyFields)) {
146   - tdEngineSuperTableService.dropColumnsForSuperTable(TdTableDO.builder()
147   - .dataBaseName(databaseName)
148   - .superTableName(tableName)
149   - .columns(modifyFields)
150   - .build());
151   - tdEngineSuperTableService.addColumnsForSuperTable(TdTableDO.builder()
152   - .dataBaseName(databaseName)
153   - .superTableName(tableName)
154   - .columns(addFields)
155   - .build());
  153 + for (TdFieldDO modifyField : modifyFields) {
  154 + tdEngineDDLMapper.dropColumnForSuperTable(TdTableDO.builder()
  155 + .dataBaseName(databaseName)
  156 + .superTableName(tableName)
  157 + .column(modifyField)
  158 + .build());
  159 + tdEngineDDLMapper.addColumnForSuperTable(TdTableDO.builder()
  160 + .dataBaseName(databaseName)
  161 + .superTableName(tableName)
  162 + .column(modifyField)
  163 + .build());
  164 + }
156 165 }
157 166 }
158 167  
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/IotThingModelMessageServiceImpl.java
1 1 package cn.iocoder.yudao.module.iot.service.tdengine;
2 2  
3 3 import cn.hutool.core.date.DateUtil;
  4 +import cn.hutool.core.util.StrUtil;
  5 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
4 6 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
5 7 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDeviceStatusUpdateReqVO;
6 8 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
... ... @@ -11,6 +13,9 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
11 13 import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.ThingModelMessage;
12 14 import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
13 15 import cn.iocoder.yudao.module.iot.dal.redis.deviceData.DeviceDataRedisDAO;
  16 +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper;
  17 +import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper;
  18 +import cn.iocoder.yudao.module.iot.enums.IotConstants;
14 19 import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStatusEnum;
15 20 import cn.iocoder.yudao.module.iot.enums.product.IotProductFunctionTypeEnum;
16 21 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
... ... @@ -30,6 +35,14 @@ import java.util.stream.Collectors;
30 35 @Service
31 36 public class IotThingModelMessageServiceImpl implements IotThingModelMessageService {
32 37  
  38 + private static final String TAG_NOTE = "TAG";
  39 + private static final String NOTE = "note";
  40 + private static final String TIME = "time";
  41 + private static final String DEVICE_KEY = "device_key";
  42 + private static final String DEVICE_NAME = "device_name";
  43 + private static final String PRODUCT_KEY = "product_key";
  44 + private static final String DEVICE_TYPE = "device_type";
  45 +
33 46 @Value("${spring.datasource.dynamic.datasource.tdengine.url}")
34 47 private String url;
35 48  
... ... @@ -38,11 +51,9 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
38 51 @Resource
39 52 private IotDeviceService iotDeviceService;
40 53 @Resource
41   - private TdEngineTableService tdEngineTableService;
42   - @Resource
43   - private TdEngineSuperTableService tdEngineSuperTableService;
  54 + private TdEngineDDLMapper tdEngineDDLMapper;
44 55 @Resource
45   - private TdEngineDataWriterService tdEngineDataWriterService;
  56 + private TdEngineDMLMapper tdEngineDMLMapper;
46 57  
47 58 @Resource
48 59 private DeviceDataRedisDAO deviceDataRedisDAO;
... ... @@ -51,62 +62,64 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
51 62 @Override
52 63 @TenantIgnore
53 64 public void saveThingModelMessage(IotDeviceDO device, ThingModelMessage thingModelMessage) {
54   - // 判断设备状态,如果为未激活状态,创建数据表
  65 + // 1. 判断设备状态,如果为未激活状态,创建数据表并更新设备状态
55 66 if (IotDeviceStatusEnum.INACTIVE.getStatus().equals(device.getStatus())) {
56   - // 创建设备数据表
57 67 createDeviceTable(device.getDeviceType(), device.getProductKey(), device.getDeviceName(), device.getDeviceKey());
58   - // 更新设备状态
59   - // TODO @haohao:下面可以考虑,链式调用。iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO().setid().setstatus())
60   - IotDeviceStatusUpdateReqVO updateReqVO = new IotDeviceStatusUpdateReqVO();
61   - updateReqVO.setId(device.getId());
62   - updateReqVO.setStatus(IotDeviceStatusEnum.ONLINE.getStatus());
63   - iotDeviceService.updateDeviceStatus(updateReqVO);
  68 + iotDeviceService.updateDeviceStatus(new IotDeviceStatusUpdateReqVO()
  69 + .setId(device.getId())
  70 + .setStatus(IotDeviceStatusEnum.ONLINE.getStatus()));
64 71 }
65 72  
66   - // TODO @haohao:这个变量,可以和 “过滤并收集有效的属性字段” 那块,因为关联度高一点。
67   - // 获取设备属性
  73 + // 2. 获取设备属性并进行物模型校验,过滤非物模型属性
68 74 Map<String, Object> params = thingModelMessage.dataToMap();
  75 + List<IotThinkModelFunctionDO> functionList = getValidFunctionList(thingModelMessage.getProductKey());
  76 + if (functionList.isEmpty()) {
  77 + return;
  78 + }
  79 +
  80 +
  81 + // 3. 过滤并收集有效的属性字段,缓存设备属性
  82 + List<TdFieldDO> schemaFieldValues = filterAndCollectValidFields(params, functionList, device, thingModelMessage.getTime());
  83 + if (schemaFieldValues.size() == 1) { // 仅有时间字段,无需保存
  84 + return;
  85 + }
  86 +
  87 + // 4. 构建并保存设备属性数据
  88 + tdEngineDMLMapper.insertData(TdTableDO.builder()
  89 + .dataBaseName(getDatabaseName())
  90 + .tableName(getDeviceTableName(device.getProductKey(), device.getDeviceName()))
  91 + .columns(schemaFieldValues)
  92 + .build());
  93 + }
69 94  
70   - // 物模型校验,过滤非物模型属性
71   - List<IotThinkModelFunctionDO> functionList = iotThinkModelFunctionService
72   - .getThinkModelFunctionListByProductKey(thingModelMessage.getProductKey())
  95 + private List<IotThinkModelFunctionDO> getValidFunctionList(String productKey) {
  96 + return iotThinkModelFunctionService
  97 + .getThinkModelFunctionListByProductKey(productKey)
73 98 .stream()
74 99 .filter(function -> IotProductFunctionTypeEnum.PROPERTY.getType().equals(function.getType()))
75 100 .toList();
76   - if (functionList.isEmpty()) {
77   - return;
78   - }
  101 + }
79 102  
80   - // 获取属性标识符集合
81   - // TODO @haohao:这个变量,可以和 “过滤并收集有效的属性字段” 那块,因为关联度高一点。另外,可以使用 CollectionUtils。convertSet
82   - Set<String> propertyIdentifiers = functionList.stream()
83   - .map(IotThinkModelFunctionDO::getIdentifier)
84   - .collect(Collectors.toSet());
  103 + private List<TdFieldDO> filterAndCollectValidFields(Map<String, Object> params, List<IotThinkModelFunctionDO> functionList, IotDeviceDO device, Long time) {
  104 + // 1. 获取属性标识符集合
  105 + Set<String> propertyIdentifiers = CollectionUtils.convertSet(functionList, IotThinkModelFunctionDO::getIdentifier);
85 106  
  107 + // 2. 构建属性标识符和属性的映射
86 108 Map<String, IotThinkModelFunctionDO> functionMap = functionList.stream()
87 109 .collect(Collectors.toMap(IotThinkModelFunctionDO::getIdentifier, function -> function));
88 110  
89   - // 过滤并收集有效的属性字段
  111 + // 3. 过滤并收集有效的属性字段
90 112 List<TdFieldDO> schemaFieldValues = new ArrayList<>();
91   - schemaFieldValues.add(new TdFieldDO("time", thingModelMessage.getTime()));
  113 + schemaFieldValues.add(new TdFieldDO(TIME, time));
92 114 params.forEach((key, val) -> {
93 115 if (propertyIdentifiers.contains(key)) {
94 116 schemaFieldValues.add(new TdFieldDO(key.toLowerCase(), val));
95 117 // 缓存设备属性
96 118 // TODO @haohao:这个缓存的写入,可以使用的时候 cache 么?被动读
97   - setDeviceDataCache(device, functionMap.get(key), val, thingModelMessage.getTime());
  119 + setDeviceDataCache(device, functionMap.get(key), val, time);
98 120 }
99 121 });
100   - // TODO @haohao:疑问,为什么 1 不继续哈?
101   - if (schemaFieldValues.size() == 1) {
102   - return;
103   - }
104   -
105   - // 构建并保存设备属性数据
106   - tdEngineDataWriterService.insertData(TdTableDO.builder().build()
107   - .setDataBaseName(getDatabaseName())
108   - .setTableName(getDeviceTableName(device.getProductKey(), device.getDeviceName()))
109   - .setColumns(schemaFieldValues));
  122 + return schemaFieldValues;
110 123 }
111 124  
112 125 /**
... ... @@ -132,7 +145,6 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
132 145 deviceDataRedisDAO.set(deviceData);
133 146 }
134 147  
135   - // TODO @haohao:实现没问题哈。这个方法的空行有点多,逻辑分块上没这么明显。看看能不能改下。
136 148 /**
137 149 * 创建设备数据表
138 150 *
... ... @@ -142,36 +154,37 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
142 154 * @param deviceKey 设备 Key
143 155 */
144 156 private void createDeviceTable(Integer deviceType, String productKey, String deviceName, String deviceKey) {
  157 + // 1. 获取超级表名和数据库名
145 158 String superTableName = getProductPropertySTableName(deviceType, productKey);
146 159 String dataBaseName = getDatabaseName();
147 160  
148   - List<Map<String, Object>> maps = tdEngineSuperTableService.describeSuperTable(new TdTableDO(dataBaseName, superTableName));
  161 + // 2. 获取超级表的结构信息
  162 + List<Map<String, Object>> maps = tdEngineDDLMapper.describeSuperTable(new TdTableDO(dataBaseName, superTableName));
149 163 List<TdFieldDO> tagsFieldValues = new ArrayList<>();
150   -
151 164 if (maps != null) {
152   - // TODO @haohao:一些字符串,是不是可以枚举起来哈。
153   - // TODO @haohao:这种过滤的,常用的,可以考虑用 CollectionUtils.filterList。一些常用的 stream 操作,适合封装哈
154   - List<Map<String, Object>> taggedNotesList = maps.stream()
155   - .filter(map -> "TAG".equals(map.get("note")))
156   - .toList();
  165 + // 2.1 过滤出 TAG 类型的字段
  166 + List<Map<String, Object>> taggedNotesList = CollectionUtils.filterList(maps, map -> TAG_NOTE.equals(map.get(NOTE)));
  167 +
157 168  
  169 + // 2.2 解析字段信息
158 170 tagsFieldValues = FieldParser.parse(taggedNotesList.stream()
159 171 .map(map -> List.of(map.get("field"), map.get("type"), map.get("length")))
160 172 .collect(Collectors.toList()));
161 173  
  174 + // 2.3 设置 TAG 字段的值
162 175 for (TdFieldDO tagsFieldValue : tagsFieldValues) {
163 176 switch (tagsFieldValue.getFieldName()) {
164   - case "product_key" -> tagsFieldValue.setFieldValue(productKey);
165   - case "device_key" -> tagsFieldValue.setFieldValue(deviceKey);
166   - case "device_name" -> tagsFieldValue.setFieldValue(deviceName);
167   - case "device_type" -> tagsFieldValue.setFieldValue(deviceType);
  177 + case PRODUCT_KEY -> tagsFieldValue.setFieldValue(productKey);
  178 + case DEVICE_KEY -> tagsFieldValue.setFieldValue(deviceKey);
  179 + case DEVICE_NAME -> tagsFieldValue.setFieldValue(deviceName);
  180 + case DEVICE_TYPE -> tagsFieldValue.setFieldValue(deviceType);
168 181 }
169 182 }
170 183 }
171 184  
172   - // 创建设备数据表
  185 + // 3. 创建设备数据表
173 186 String tableName = getDeviceTableName(productKey, deviceName);
174   - tdEngineTableService.createTable(TdTableDO.builder().build()
  187 + tdEngineDDLMapper.createTable(TdTableDO.builder().build()
175 188 .setDataBaseName(dataBaseName)
176 189 .setSuperTableName(superTableName)
177 190 .setTableName(tableName)
... ... @@ -184,8 +197,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
184 197 * @return 数据库名称
185 198 */
186 199 private String getDatabaseName() {
187   - // TODO @haohao:可以使用 StrUtil.subAftetLast 这种方法
188   - return url.substring(url.lastIndexOf("/") + 1);
  200 + return StrUtil.subAfter(url, "/", true);
189 201 }
190 202  
191 203 /**
... ... @@ -198,9 +210,9 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
198 210 private static String getProductPropertySTableName(Integer deviceType, String productKey) {
199 211 // TODO @haohao:枚举下,会好点哈。
200 212 return switch (deviceType) {
201   - case 1 -> String.format("gateway_sub_%s", productKey).toLowerCase();
202   - case 2 -> String.format("gateway_%s", productKey).toLowerCase();
203   - default -> String.format("device_%s", productKey).toLowerCase();
  213 + case 1 -> String.format(IotConstants.GATEWAY_SUB_STABLE_NAME_FORMAT, productKey).toLowerCase();
  214 + case 2 -> String.format(IotConstants.GATEWAY_STABLE_NAME_FORMAT, productKey).toLowerCase();
  215 + default -> String.format(IotConstants.DEVICE_STABLE_NAME_FORMAT, productKey).toLowerCase();
204 216 };
205 217 }
206 218  
... ... @@ -212,7 +224,7 @@ public class IotThingModelMessageServiceImpl implements IotThingModelMessageServ
212 224 * @return 设备表名
213 225 */
214 226 private static String getDeviceTableName(String productKey, String deviceName) {
215   - return String.format("device_%s_%s", productKey.toLowerCase(), deviceName.toLowerCase());
  227 + return String.format(IotConstants.DEVICE_TABLE_NAME_FORMAT, productKey.toLowerCase(), deviceName.toLowerCase());
216 228 }
217 229  
218 230 }
219 231 \ No newline at end of file
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterService.java deleted
1   -package cn.iocoder.yudao.module.iot.service.tdengine;
2   -
3   -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
4   -
5   -/**
6   - * TD 引擎的数据写入 Service 接口
7   - */
8   -public interface TdEngineDataWriterService {
9   -
10   - /**
11   - * 插入数据 - 指定列插入数据
12   - *
13   - * @param table 数据
14   - * dataBaseName 数据库名
15   - * tableName 表名
16   - * columns 列
17   - */
18   - void insertData(TdTableDO table);
19   -}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDataWriterServiceImpl.java deleted
1   -package cn.iocoder.yudao.module.iot.service.tdengine;
2   -
3   -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
4   -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDataWriterMapper;
5   -import jakarta.annotation.Resource;
6   -import org.springframework.stereotype.Service;
7   -
8   -/**
9   - * TD 引擎的数据写入 Service 实现类
10   - */
11   -@Service
12   -public class TdEngineDataWriterServiceImpl implements TdEngineDataWriterService {
13   -
14   - @Resource
15   - private TdEngineDataWriterMapper tdEngineDataWriterMapper;
16   -
17   - @Override
18   - public void insertData(TdTableDO table) {
19   - tdEngineDataWriterMapper.insertData(table);
20   - }
21   -}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseService.java deleted
1   -package cn.iocoder.yudao.module.iot.service.tdengine;
2   -
3   -/**
4   - * TD 引擎的数据库 Service 接口
5   - */
6   -public interface TdEngineDatabaseService {
7   -
8   - /**
9   - * 创建数据库
10   - *
11   - * @param dataBaseName 数据库名称
12   - */
13   - void createDatabase(String dataBaseName);
14   -}
15 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineDatabaseServiceImpl.java deleted
1   -package cn.iocoder.yudao.module.iot.service.tdengine;
2   -
3   -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDatabaseMapper;
4   -import jakarta.annotation.Resource;
5   -import lombok.extern.slf4j.Slf4j;
6   -import org.springframework.stereotype.Service;
7   -
8   -/**
9   - * TD 引擎的数据库 Service 实现类
10   - */
11   -@Service
12   -@Slf4j
13   -public class TdEngineDatabaseServiceImpl implements TdEngineDatabaseService {
14   -
15   - @Resource
16   - private TdEngineDatabaseMapper tdEngineDatabaseMapper;
17   -
18   - @Override
19   - public void createDatabase(String dataBaseName) {
20   - tdEngineDatabaseMapper.createDatabase(dataBaseName);
21   - }
22   -}
23 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryService.java deleted
1   -package cn.iocoder.yudao.module.iot.service.tdengine;
2   -
3   -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO;
4   -
5   -import java.util.List;
6   -import java.util.Map;
7   -
8   -/**
9   - * TD 引擎的查询 Service 接口
10   - */
11   -public interface TdEngineQueryService {
12   -
13   - /**
14   - * 获取历史数据
15   - *
16   - * @param selectVisualDO 查询条件
17   - * @return 历史数据列表
18   - */
19   - List<Map<String, Object>> getHistoryData(SelectVisualDO selectVisualDO);
20   -
21   - /**
22   - * 获取历史数据条数
23   - *
24   - * @param selectVisualDO 查询条件
25   - * @return 数据条数
26   - */
27   - Long getHistoryCount(SelectVisualDO selectVisualDO);
28   -}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineQueryServiceImpl.java deleted
1   -package cn.iocoder.yudao.module.iot.service.tdengine;
2   -
3   -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO;
4   -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineQueryMapper;
5   -import jakarta.annotation.Resource;
6   -import org.springframework.stereotype.Service;
7   -
8   -import java.util.List;
9   -import java.util.Map;
10   -
11   -@Service
12   -public class TdEngineQueryServiceImpl implements TdEngineQueryService {
13   -
14   - @Resource
15   - private TdEngineQueryMapper tdEngineQueryMapper;
16   -
17   - @Override
18   - public List<Map<String, Object>> getHistoryData(SelectVisualDO selectVisualDO) {
19   - return tdEngineQueryMapper.getHistoryData(selectVisualDO);
20   - }
21   -
22   - @Override
23   - public Long getHistoryCount(SelectVisualDO selectVisualDO) {
24   - return tdEngineQueryMapper.getHistoryCount(selectVisualDO);
25   - }
26   -}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableService.java deleted
1   -package cn.iocoder.yudao.module.iot.service.tdengine;
2   -
3   -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
4   -
5   -import java.util.List;
6   -import java.util.Map;
7   -
8   -/**
9   - * TD 引擎的超级表 Service 接口
10   - */
11   -public interface TdEngineSuperTableService {
12   -
13   - /**
14   - * 创建超级表
15   - *
16   - * @param superTable 超级表信息
17   - * dataBaseName 数据库名称
18   - * superTableName 超级表名称
19   - * columns 列信息
20   - * tags 标签信息
21   - */
22   - void createSuperTable(TdTableDO superTable);
23   -
24   - /**
25   - * 查看超级表 - 显示当前数据库下的所有超级表信息
26   - *
27   - * @param superTable 超级表信息
28   - * dataBaseName 数据库名称
29   - * superTableName 超级表名称
30   - */
31   -
32   - List<Map<String, Object>> showSuperTables(TdTableDO superTable);
33   -
34   - /**
35   - * 查看超级表 - 获取超级表的结构信息
36   - *
37   - * @param superTable 超级表信息
38   - * dataBaseName 数据库名称
39   - * superTableName 超级表名称
40   - */
41   - List<Map<String, Object>> describeSuperTable(TdTableDO superTable);
42   -
43   - /**
44   - * 修改超级表 - 增加列
45   - *
46   - * @param superTable 超级表信息
47   - * dataBaseName 数据库名称
48   - * superTableName 超级表名称
49   - * column 列信息
50   - */
51   - void addColumnForSuperTable(TdTableDO superTable);
52   -
53   - /**
54   - * 修改超级表 - 删除列
55   - *
56   - * @param superTable 超级表信息
57   - * dataBaseName 数据库名称
58   - * superTableName 超级表名称
59   - * column 列信息
60   - */
61   - void dropColumnForSuperTable(TdTableDO superTable);
62   -
63   - /**
64   - * 修改超级表 - 修改列宽
65   - *
66   - * @param superTable 超级表信息
67   - * dataBaseName 数据库名称
68   - * superTableName 超级表名称
69   - * column 列信息
70   - */
71   - void modifyColumnWidthForSuperTable(TdTableDO superTable);
72   -
73   -
74   - /**
75   - * 修改超级表 - 为超级表添加标签
76   - *
77   - * @param superTable 超级表信息
78   - * dataBaseName 数据库名称
79   - * superTableName 超级表名称
80   - * tag 标签信息
81   - */
82   - void addTagForSuperTable(TdTableDO superTable);
83   -
84   - /**
85   - * 修改超级表 - 为超级表删除标签
86   - *
87   - * @param superTable 超级表信息
88   - * dataBaseName 数据库名称
89   - * superTableName 超级表名称
90   - * tag 标签信息
91   - */
92   - void dropTagForSuperTable(TdTableDO superTable);
93   -
94   - /**
95   - * 检查超级表是否存在
96   - *
97   - * @param superTable 超级表信息
98   - * dataBaseName 数据库名称
99   - * superTableName 超级表名称
100   - * @return 超级表数量
101   - */
102   - Integer checkSuperTableExists(TdTableDO superTable);
103   -
104   - /**
105   - * 为超级表添加列
106   - *
107   - * @param superTable 超级表信息
108   - * dataBaseName 数据库名称
109   - * superTableName 超级表名称
110   - * columns 列信息
111   - */
112   - void addColumnsForSuperTable(TdTableDO superTable);
113   -
114   - /**
115   - * 为超级表删除列
116   - *
117   - * @param superTable 超级表信息
118   - * dataBaseName 数据库名称
119   - * superTableName 超级表名称
120   - * columns 列信息
121   - */
122   - void dropColumnsForSuperTable(TdTableDO superTable);
123   -}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineSuperTableServiceImpl.java deleted
1   -package cn.iocoder.yudao.module.iot.service.tdengine;
2   -
3   -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdFieldDO;
4   -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
5   -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineSuperTableMapper;
6   -import jakarta.annotation.Resource;
7   -import lombok.extern.slf4j.Slf4j;
8   -import org.springframework.stereotype.Service;
9   -
10   -import java.util.List;
11   -import java.util.Map;
12   -
13   -/**
14   - * TD 引擎的超级表 Service 实现类
15   - */
16   -@Slf4j
17   -@Service
18   -public class TdEngineSuperTableServiceImpl implements TdEngineSuperTableService {
19   -
20   - @Resource
21   - private TdEngineSuperTableMapper tdEngineSuperTableMapper;
22   -
23   - @Override
24   - public void createSuperTable(TdTableDO superTable) {
25   - tdEngineSuperTableMapper.createSuperTable(superTable);
26   - }
27   -
28   - @Override
29   - public List<Map<String, Object>> showSuperTables(TdTableDO superTable) {
30   - return tdEngineSuperTableMapper.showSuperTables(superTable);
31   - }
32   -
33   - @Override
34   - public List<Map<String, Object>> describeSuperTable(TdTableDO superTable) {
35   - return tdEngineSuperTableMapper.describeSuperTable(superTable);
36   - }
37   -
38   - @Override
39   - public void addColumnForSuperTable(TdTableDO superTable) {
40   - tdEngineSuperTableMapper.addColumnForSuperTable(superTable);
41   - }
42   -
43   - @Override
44   - public void dropColumnForSuperTable(TdTableDO superTable) {
45   - tdEngineSuperTableMapper.dropColumnForSuperTable(superTable);
46   - }
47   -
48   - @Override
49   - public void modifyColumnWidthForSuperTable(TdTableDO superTable) {
50   - tdEngineSuperTableMapper.modifyColumnWidthForSuperTable(superTable);
51   - }
52   -
53   - @Override
54   - public void addTagForSuperTable(TdTableDO superTable) {
55   - tdEngineSuperTableMapper.addTagForSuperTable(superTable);
56   - }
57   -
58   - @Override
59   - public void dropTagForSuperTable(TdTableDO superTable) {
60   - tdEngineSuperTableMapper.dropTagForSuperTable(superTable);
61   - }
62   -
63   - @Override
64   - public Integer checkSuperTableExists(TdTableDO superTable) {
65   - List<Map<String, Object>> results = tdEngineSuperTableMapper.showSuperTables(superTable);
66   - return results == null || results.isEmpty() ? 0 : results.size();
67   - }
68   -
69   - @Override
70   - public void addColumnsForSuperTable(TdTableDO superTable) {
71   - for (TdFieldDO column : superTable.getColumns()) {
72   - tdEngineSuperTableMapper.addColumnForSuperTable(TdTableDO.builder()
73   - .dataBaseName(superTable.getDataBaseName())
74   - .superTableName(superTable.getSuperTableName())
75   - .column(column)
76   - .build());
77   - }
78   - }
79   -
80   - @Override
81   - public void dropColumnsForSuperTable(TdTableDO superTable) {
82   - for (TdFieldDO column : superTable.getColumns()) {
83   - tdEngineSuperTableMapper.dropColumnForSuperTable(TdTableDO.builder()
84   - .dataBaseName(superTable.getDataBaseName())
85   - .superTableName(superTable.getSuperTableName())
86   - .column(column)
87   - .build());
88   - }
89   - }
90   -}
91 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableService.java deleted
1   -package cn.iocoder.yudao.module.iot.service.tdengine;
2   -
3   -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
4   -
5   -/**
6   - * TD 引擎的表 Service 接口
7   - */
8   -public interface TdEngineTableService {
9   -
10   - /**
11   - * 创建表 - 创建超级表的子表
12   - *
13   - * @param table 表信息
14   - * dataBaseName 数据库名称
15   - * superTableName 超级表名称
16   - * tableName 子表名称
17   - * tags TAG 字段
18   - */
19   - void createTable(TdTableDO table);
20   -
21   -}
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/tdengine/TdEngineTableServiceImpl.java deleted
1   -package cn.iocoder.yudao.module.iot.service.tdengine;
2   -
3   -import cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TdTableDO;
4   -import cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineTableMapper;
5   -import jakarta.annotation.Resource;
6   -import lombok.extern.slf4j.Slf4j;
7   -import org.springframework.stereotype.Service;
8   -
9   -/**
10   - * TD 引擎的表 Service 实现类
11   - */
12   -@Slf4j
13   -@Service
14   -public class TdEngineTableServiceImpl implements TdEngineTableService {
15   -
16   - @Resource
17   - private TdEngineTableMapper tdEngineTableMapper;
18   -
19   - @Override
20   - public void createTable(TdTableDO table) {
21   - tdEngineTableMapper.createTable(table);
22   - }
23   -}
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineSuperTableMapper.xml renamed to yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDDLMapper.xml
... ... @@ -2,7 +2,12 @@
2 2 <!DOCTYPE mapper
3 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
4 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5   -<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineSuperTableMapper">
  5 +<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDDLMapper">
  6 +
  7 + <!-- 创建数据库 -->
  8 + <update id="createDatabase" parameterType="String">
  9 + CREATE DATABASE IF NOT EXISTS ${dataBaseName}
  10 + </update>
6 11  
7 12 <!-- 创建超级表 -->
8 13 <update id="createSuperTable">
... ... @@ -68,4 +73,29 @@
68 73 ALTER STABLE ${dataBaseName}.${superTableName} DROP TAG ${tag.fieldName}
69 74 </update>
70 75  
71   -</mapper>
  76 + <!-- 创建子表 -->
  77 + <update id="createTable">
  78 + CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName}
  79 + USING ${dataBaseName}.${superTableName}
  80 + TAGS
  81 + <foreach item="item" collection="tags" separator=","
  82 + open="(" close=")">
  83 + #{item.fieldValue}
  84 + </foreach>
  85 + </update>
  86 +
  87 + <!-- 创建子表,带有 TAGS -->
  88 + <update id="createTableWithTags">
  89 + CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName}
  90 + USING ${dataBaseName}.${superTableName}
  91 + <foreach item="item" collection="tags" separator="," open="(" close=")">
  92 + #{item.fieldName}
  93 + </foreach>
  94 + TAGS
  95 + <foreach item="item" collection="tags" separator=","
  96 + open="(" close=")">
  97 + #{item.fieldValue}
  98 + </foreach>
  99 + </update>
  100 +
  101 +</mapper>
72 102 \ No newline at end of file
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineQueryMapper.xml renamed to yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDMLMapper.xml
... ... @@ -2,7 +2,21 @@
2 2 <!DOCTYPE mapper
3 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
4 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5   -<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineQueryMapper">
  5 +<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDMLMapper">
  6 +
  7 + <!-- 插入数据 -->
  8 + <insert id="insertData">
  9 + INSERT INTO ${dataBaseName}.${tableName}
  10 + <foreach item="item" collection="columns" separator=","
  11 + open="(" close=")">
  12 + ${item.fieldName}
  13 + </foreach>
  14 + VALUES
  15 + <foreach item="item" collection="columns" separator=","
  16 + open="(" close=")">
  17 + #{item.fieldValue}
  18 + </foreach>
  19 + </insert>
6 20  
7 21 <!-- 根据时间戳查询数据 -->
8 22 <select id="selectByTimestamp" parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectDO"
... ... @@ -12,7 +26,7 @@
12 26 </select>
13 27  
14 28 <!-- 获取时间范围内的数据条数 -->
15   - <select id="getCountByTimestamp" parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectDO"
  29 + <select id="selectCountByTimestamp" parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectDO"
16 30 resultType="java.util.Map">
17 31 SELECT COUNT(0) AS count
18 32 FROM ${dataBaseName}.${tableName}
... ... @@ -20,14 +34,14 @@
20 34 </select>
21 35  
22 36 <!-- 获取最新数据 -->
23   - <select id="getLastData" resultType="java.util.Map">
  37 + <select id="selectOneLastData" resultType="java.util.Map">
24 38 SELECT LAST(time), *
25 39 FROM ${tableName}
26 40 WHERE device_id = #{deviceId}
27 41 </select>
28 42  
29 43 <!-- 根据标签获取最新数据 -->
30   - <select id="getLastDataByTags" parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TagsSelectDO"
  44 + <select id="selectLastDataListByTags" parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.TagsSelectDO"
31 45 resultType="Map">
32 46 SELECT LAST(*)
33 47 FROM ${dataBaseName}.${stableName}
... ... @@ -35,7 +49,7 @@
35 49 </select>
36 50  
37 51 <!-- 获取历史数据 -->
38   - <select id="getHistoryData" resultType="java.util.Map"
  52 + <select id="selectHistoryDataList" resultType="java.util.Map"
39 53 parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO">
40 54 SELECT ${fieldName} AS data, time
41 55 FROM ${dataBaseName}.${tableName}
... ... @@ -46,14 +60,14 @@
46 60 </select>
47 61  
48 62 <!-- 获取实时数据 -->
49   - <select id="getRealtimeData" resultType="java.util.Map"
  63 + <select id="selectRealtimeDataList" resultType="java.util.Map"
50 64 parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO">
51 65 SELECT ${fieldName}, time
52 66 FROM ${dataBaseName}.${tableName}
53 67 </select>
54 68  
55 69 <!-- 获取聚合数据 -->
56   - <select id="getAggregateData" resultType="java.util.Map"
  70 + <select id="selectAggregateDataList" resultType="java.util.Map"
57 71 parameterType="cn.iocoder.yudao.module.iot.dal.dataobject.tdengine.SelectVisualDO">
58 72 SELECT ${aggregate}(${fieldName})
59 73 FROM ${dataBaseName}.${tableName}
... ... @@ -62,11 +76,11 @@
62 76 </select>
63 77  
64 78 <!-- 获取历史数据条数 -->
65   - <select id="getHistoryCount" resultType="java.lang.Long">
  79 + <select id="selectHistoryCount" resultType="java.lang.Long">
66 80 SELECT COUNT(time)
67 81 FROM ${dataBaseName}.${tableName}
68 82 WHERE time BETWEEN #{startTime} AND #{endTime}
69 83 AND ${fieldName} IS NOT NULL
70 84 </select>
71 85  
72 86 -</mapper>
  87 +</mapper>
73 88 \ No newline at end of file
... ...
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDataWriterMapper.xml deleted
1   -<?xml version="1.0" encoding="UTF-8"?>
2   -<!DOCTYPE mapper
3   - PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
4   - "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5   -<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDataWriterMapper">
6   -
7   - <!-- 插入数据 -->
8   - <insert id="insertData">
9   - INSERT INTO ${dataBaseName}.${tableName}
10   - <foreach item="item" collection="columns" separator=","
11   - open="(" close=")">
12   - ${item.fieldName}
13   - </foreach>
14   - VALUES
15   - <foreach item="item" collection="columns" separator=","
16   - open="(" close=")">
17   - #{item.fieldValue}
18   - </foreach>
19   - </insert>
20   -
21   -</mapper>
22 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineDatabaseMapper.xml deleted
1   -<?xml version="1.0" encoding="UTF-8"?>
2   -<!DOCTYPE mapper
3   - PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
4   - "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5   -<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineDatabaseMapper">
6   -
7   - <!-- 创建数据库 -->
8   - <update id="createDatabase" parameterType="String">
9   - CREATE DATABASE IF NOT EXISTS ${dataBaseName}
10   - </update>
11   -
12   -</mapper>
13 0 \ No newline at end of file
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/tdengine/TdEngineTableMapper.xml deleted
1   -<?xml version="1.0" encoding="UTF-8"?>
2   -<!DOCTYPE mapper
3   - PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
4   - "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5   -<mapper namespace="cn.iocoder.yudao.module.iot.dal.tdengine.TdEngineTableMapper">
6   -
7   - <!-- 创建子表 -->
8   - <update id="createTable">
9   - CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName}
10   - USING ${dataBaseName}.${superTableName}
11   - TAGS
12   - <foreach item="item" collection="tags" separator=","
13   - open="(" close=")">
14   - #{item.fieldValue}
15   - </foreach>
16   - </update>
17   -
18   - <!-- 创建子表,带有 TAGS -->
19   - <update id="createTableWithTags">
20   - CREATE TABLE IF NOT EXISTS ${dataBaseName}.${tableName}
21   - USING ${dataBaseName}.${superTableName}
22   - <foreach item="item" collection="tags" separator="," open="(" close=")">
23   - #{item.fieldName}
24   - </foreach>
25   - TAGS
26   - <foreach item="item" collection="tags" separator=","
27   - open="(" close=")">
28   - #{item.fieldValue}
29   - </foreach>
30   - </update>
31   -
32   -</mapper>
33 0 \ No newline at end of file