若依微服务1.04版本,主要支持tdengine服务

1、创建数据库
2、创建超级表
3、创建子表
4、添加超级表column
5、删除超级表column
6、插入数据
7、获取子表最新数据
8、根据tags获取超级表最新数据
9、获取历史数据
10、获取历史数据数量
master
xins 2 years ago
parent 854309654d
commit 08c2a39100

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-api</artifactId>
<version>3.6.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>hw-api-tdengine</artifactId>
<description>
hw-api-tdengine时序数据库接口模块
</description>
<dependencies>
<!-- RuoYi Common Core-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-core</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,55 @@
package com.ruoyi.tdengine.api;
import com.ruoyi.common.core.constant.ServiceNameConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.hw.validated.tdengine.AddTdSTableColumn;
import com.ruoyi.common.core.hw.validated.tdengine.InsertTdTable;
import com.ruoyi.tdengine.api.domain.TdHistorySelectDto;
import com.ruoyi.tdengine.api.domain.TdSelectDto;
import com.ruoyi.tdengine.api.domain.TdSuperTableVo;
import com.ruoyi.tdengine.api.domain.TdTableVo;
import com.ruoyi.tdengine.api.factory.RemoteTdEngineFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Map;
@FeignClient(contextId = "remoteTdEngineService", value = ServiceNameConstants.TDENGINE_SERVICE, fallbackFactory = RemoteTdEngineFallbackFactory.class)
public interface RemoteTdEngineService {
@PostMapping("/tdengine/createDatabase")
R<?> createDataBase(@RequestParam("databaseName") String databaseName);
@PostMapping("/tdengine/createSuperTable")
R<?> createSuperTable(@Validated @RequestBody TdSuperTableVo tdSuperTableVo);
@PostMapping("/tdengine/createTable")
R<?> createTable(@Validated @RequestBody TdTableVo tdTableVo);
@PostMapping("/tdengine/addSuperTableColumn")
R<?> addSuperTableColumn(@Validated(AddTdSTableColumn.class) @RequestBody TdSuperTableVo tdSuperTableVo);
@PostMapping("/tdengine/dropSuperTableColumn")
R<?> dropColumnForSuperTable(@Validated(AddTdSTableColumn.class) @RequestBody TdSuperTableVo tdSuperTableVo);
@PostMapping("/tdengine/insertTable")
R<?> insertTable(@Validated(InsertTdTable.class) @RequestBody TdTableVo tdTableVo);
@PostMapping("/tdengine/getLatestData")
R<?> getLatestData(@Validated @RequestBody TdSelectDto tdSelectDto);
@PostMapping("/tdengine/getLatestDataByTags")
R<Map<String, Map<String, Object>>> getLatestDataByTags(@RequestBody TdSelectDto tdSelectDto);
@PostMapping("/tdengine/getHistoryData")
R<?> getHistoryData(@Validated @RequestBody TdHistorySelectDto tdHistorySelectDto);
@PostMapping("/tdengine/getCountOfHistoryData")
R<?> getCountOfHistoryData(@Validated @RequestBody TdHistorySelectDto tdHistorySelectDto);
}

@ -0,0 +1,40 @@
package com.ruoyi.tdengine.api.domain;
import com.ruoyi.common.core.enums.DataTypeEnums;
import lombok.Data;
/**
* @ClassName: TdField
* @Author : xins
* @Date :2023-08-28 9:47
* @Description: TDengine filed
* @Version :1.0
*/
@Data
public class TdField {
//字段名称
private String fieldName;
//字段值
private Object fieldValue;
//字段数据类型code
private Integer dataTypeCode;
//字段数据类型
private String dataType;
//字段字节大小
private Integer size;
public TdField() {
}
public TdField(String fieldName, Integer dataTypeCode, Integer size) {
this.fieldName = fieldName;
this.dataTypeCode = dataTypeCode;
this.dataType = DataTypeEnums.dataCodeTypeMap.get(dataTypeCode);
this.size = size;
}
}

@ -0,0 +1,68 @@
package com.ruoyi.tdengine.api.domain;
import com.ruoyi.common.core.enums.DataTypeEnums;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.annotation.Validated;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* @Description: Tdengine
* @ClassName: TdFieldsVo
* @Author : xins
* @Date :2023-08-28 14:34
* @Version :1.0
*/
public class TdFieldVo {
private static final long serialVersionUID = 1L;
private String fieldName;
private String dataType;
private Integer size;
public TdFieldVo(String fieldName, Integer dataTypeCode, Integer size) {
this.fieldName = fieldName;
this.dataType = DataTypeEnums.dataCodeTypeMap.get(dataTypeCode);
this.size = size;
}
/**
* @description TdFieldsTdFieldsVodatatype
* @author xins
* @date 2023-08-28 14:40
* @param field
* @return TdFieldsVo
*/
public static TdFieldVo convertField(@Validated TdField field) throws SQLException {
String fieldName = field.getFieldName();
Integer datatypeCode = field.getDataTypeCode();
Integer size = field.getSize();
if(StringUtils.isBlank(fieldName) || datatypeCode == null){
throw new SQLException("fieldname and datatype cannot be null");
}
TdFieldVo tdFieldsVo = new TdFieldVo(fieldName, datatypeCode, size);
return tdFieldsVo;
}
/**
* @description
* @author xins
* @date 2023-08-28 14:58
* @param fieldList
* @return List<TdFieldsVo>
*/
public static List<TdFieldVo> batchConvertFields(List<TdField> fieldList) throws SQLException{
List<TdFieldVo> tdFieldsVoList = new ArrayList<>();
for(TdField tdField:fieldList){
tdFieldsVoList.add(convertField(tdField));
}
return tdFieldsVoList;
}
}

@ -0,0 +1,40 @@
package com.ruoyi.tdengine.api.domain;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class TdHistorySelectDto {
//数据库名称
@NotBlank(message="databaseName cannot be empty")
private String databaseName;
//子表名称
@NotBlank(message="tableName cannot be empty")
private String tableName;
//控制输出条数
private int limit;
//指定从第几条之后输出例如limit 2,5输出第3行到第7行的数据
private int offset;
/**
* timestamp
*/
private String firstFieldName;
//过滤条件:开始时间
private long startTime;
//过滤条件:结束时间
private long endTime;
//排序字段
private String orderByFieldName;
//排序方式
private String orderByMode;
}

@ -0,0 +1,33 @@
package com.ruoyi.tdengine.api.domain;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
/**
* @Description: TDengine
* @ClassName: TdSelectDto
* @Author : xins
* @Date :2023-08-29 10:39
* @Version :1.0
*/
@Data
public class TdSelectDto {
//数据库名称
@NotBlank(message="databaseName cannot be empty")
private String databaseName;
//子表名称
@NotBlank(message="tableName cannot be empty")
private String tableName;
//超级表名称
private String superTableName;
//tags名称
private String tagsName;
}

@ -0,0 +1,57 @@
package com.ruoyi.tdengine.api.domain;
import com.ruoyi.common.core.hw.validated.tdengine.AddTdSTableColumn;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import java.util.List;
/**
* @ClassDescription:
* @ClassName: TdSuperTableVo
* @Author: xins
* @Date: 2023-08-28 09:30:45
* @Version 1.0
*/
@Data
public class TdSuperTableVo {
//数据库名称
@NotEmpty(message="databaseName cannot be empty",groups = AddTdSTableColumn.class)
private String databaseName;
//超级表名称
@NotEmpty(message="supertableName cannot be empty",groups = AddTdSTableColumn.class)
private String superTableName;
/**
* timestamp
*/
private String firstFieldName;
/**
* Schema
* timestamptimestamp
*
*
*/
@NotEmpty(message="schemeFields cannot be empty")
private List<TdField> schemaFields;
/**
* Schema
* TAGS
* TAGS
* TAGS 128 1 16 KB
*/
@NotEmpty(message="tagsFields cannot be empty")
private List<TdField> tagsFields;
/**
* 使
*/
private TdField field;
}

@ -0,0 +1,42 @@
package com.ruoyi.tdengine.api.domain;
import com.ruoyi.common.core.hw.validated.tdengine.InsertTdTable;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import java.util.List;
/**
* @Description:
* @ClassName: TdTableVo
* @Author : xins
* @Date :2023-08-28 15:45
* @Version :1.0
*/
@Data
public class TdTableVo {
//数据库名称
@NotEmpty(message="databaseName cannot be empty",groups = InsertTdTable.class)
private String databaseName;
//超级表名称
@NotEmpty(message="supertableName cannot be empty")
private String superTableName;
//子表名称
@NotEmpty(message="tableName cannot be empty",groups = InsertTdTable.class)
private String tableName;
/**
*
*/
private List<TdField> tagsFieldValues;
/**
* schemaschema
*/
@NotEmpty(message="schemaFields cannot be empty",groups = InsertTdTable.class)
private List<TdField> schemaFields;
}

@ -0,0 +1,76 @@
package com.ruoyi.tdengine.api.factory;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.tdengine.api.RemoteTdEngineService;
import com.ruoyi.tdengine.api.domain.TdHistorySelectDto;
import com.ruoyi.tdengine.api.domain.TdSelectDto;
import com.ruoyi.tdengine.api.domain.TdSuperTableVo;
import com.ruoyi.tdengine.api.domain.TdTableVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
public class RemoteTdEngineFallbackFactory implements FallbackFactory<RemoteTdEngineService> {
private static final Logger log = LoggerFactory.getLogger(RemoteTdEngineFallbackFactory.class);
@Override
public RemoteTdEngineService create(Throwable throwable) {
return new RemoteTdEngineService()
{
@Override
public R<?> createDataBase(String databaseName) {
return R.fail("创建数据库失败:" + throwable.getMessage());
}
@Override
public R<?> createSuperTable(TdSuperTableVo tdSuperTableVo) {
return R.fail("创建超级表失败:" + throwable.getMessage());
}
@Override
public R<?> createTable(TdTableVo tdTableVo) {
return R.fail("创建子表失败:" + throwable.getMessage());
}
@Override
public R<?> addSuperTableColumn(TdSuperTableVo tdSuperTableVo) {
return R.fail("添加超级表Column失败:" + throwable.getMessage());
}
@Override
public R<?> dropColumnForSuperTable(TdSuperTableVo tdSuperTableVo) {
return R.fail("删除超级表Column失败:" + throwable.getMessage());
}
@Override
public R<?> insertTable(TdTableVo tdTableVo) {
return R.fail("插入数据失败:" + throwable.getMessage());
}
@Override
public R<?> getLatestData(TdSelectDto tdSelectDto) {
return R.fail("获取子表最新数据失败:" + throwable.getMessage());
}
@Override
public R<Map<String, Map<String, Object>>> getLatestDataByTags(TdSelectDto tdSelectDto) {
return R.fail("根据tags获取超级表最新数据失败:" + throwable.getMessage());
}
@Override
public R<?> getHistoryData(TdHistorySelectDto tdHistorySelectDto) {
return R.fail("获取历史数据失败:" + throwable.getMessage());
}
@Override
public R<?> getCountOfHistoryData(TdHistorySelectDto tdHistorySelectDto) {
return R.fail("获取历史数据数量失败:" + throwable.getMessage());
}
};
}
}

@ -10,6 +10,7 @@
<modules>
<module>ruoyi-api-system</module>
<module>hw-api-tdengine</module>
</modules>
<artifactId>ruoyi-api</artifactId>

@ -31,7 +31,7 @@ public class MyLocaleChangeInterceptor implements HandlerInterceptor {
// Proceed in cookie
cookieLocale=cookie.getValue();
}
if(cookieLocale!=null&& !cookieLocale.trim().equals("")){
if(cookieLocale!=null&& !"".equals(cookieLocale.trim())){
locale=cookieLocale;
}
@ -41,12 +41,12 @@ public class MyLocaleChangeInterceptor implements HandlerInterceptor {
// System.out.println((request.getHeader("accept-language")));
// System.out.println(request.getHeader("cookie"));
if(headerLocale!=null && !headerLocale.trim().equals("")){
if(headerLocale!=null && !"".equals(headerLocale.trim())){
locale=headerLocale;
}
// 3、从get 参数数据获取 language=zh_CN
String parameterLocale=request.getParameter(paramName);
if(parameterLocale!=null && !parameterLocale.trim().equals("")){
if(parameterLocale!=null && !"".equals(parameterLocale.trim())){
locale=parameterLocale;
}
//4 语言信息写入线程变量

@ -0,0 +1,11 @@
user.login.username=\u7528\u6237\u540D
user.login.password=\u5BC6\u7801
user.login.code=\u9A8C\u8BC1\u7801
user.login.remember=\u8BB0\u4F4F\u6211
user.login.submit=\u767B\u5F55
menu.system.management=\u7CFB\u7EDF\u7BA1\u7406
tdengine.supertable1.pressure=yali

@ -3,3 +3,5 @@ user.login.password=Password
user.login.code=Security code
user.login.remember=Remember me
user.login.submit=Sign In
menu.system.management=System Management

@ -4,3 +4,6 @@ user.login.code=\u9A8C\u8BC1\u7801
user.login.remember=\u8BB0\u4F4F\u6211
user.login.submit=\u767B\u5F55
menu.system.management=\u7CFB\u7EDF\u7BA1\u7406

@ -113,6 +113,11 @@
<artifactId>swagger-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>

@ -21,4 +21,9 @@ public class ServiceNameConstants
* serviceid
*/
public static final String FILE_SERVICE = "ruoyi-file";
/**
* Tdengineserviceid
*/
public static final String TDENGINE_SERVICE = "hw-tdengine";
}

@ -0,0 +1,8 @@
package com.ruoyi.common.core.constant;
public class TdEngineConstants {
public static final String DEFAULT_FIRST_FIELD_NAME = "ts";
public static final String DEFAULT_ORDER_BY_MODE = "desc";
}

@ -0,0 +1,115 @@
package com.ruoyi.common.core.enums;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public enum DataTypeEnums{
/**
*
*/
TIMESTAMP(1,"timestamp"),
/**
* [-2^31, 2^31-1]
*/
INT(2, "int"),
/**
* [-2^63, 2^63-1]
*/
BIGINT(3, "bigint"),
/**
* 6-7 [-3.4E38, 3.4E38]
*/
FLOAT(4, "float"),
/**
* 15-16 [-1.7E308, 1.7E308]
*/
DOUBLE(5, "double"),
/**
* ASCII ,16000使 NCHAR
*/
BINARY(6, "binary"),
/**
* [-32768, 32767]
*/
SMALLINT(7, "smallint"),
/**
* [-128, 127]
*/
TINYINT(8, "tinyint"),
/**
* {true, false}
*/
BOOL(9, "bool"),
/**
*
* NCHAR 4 使 \'
* NCHAR 使 NCHAR(10) 10 NCHAR
* 4093
*/
NCHAR(10, "nchar"),
/**
* json tagjson
*/
JSON(11, "json");
// 性别值数组
public static final List<Integer> genderValueList = Arrays.stream(values()).map(DataTypeEnums::getDataCode).collect(Collectors.toList());
// 性别名数组
public static final List<String> genderNameList = Arrays.stream(values()).map(DataTypeEnums::getDataType).collect(Collectors.toList());
// 属性值与属性名Map
public static final Map<Integer, String> dataCodeTypeMap = Arrays.stream(values()).collect(
Collectors.toMap(
DataTypeEnums::getDataCode,
DataTypeEnums::getDataType
)
);
// 属性名与属性值Map
public static final Map<String, Integer> dataTypeCodeMap = Arrays.stream(values()).collect(
Collectors.toMap(
DataTypeEnums::getDataType,
DataTypeEnums::getDataCode
)
);
// 性别值
private final Integer dataCode;
// 性别名
private final String dataType;
DataTypeEnums(Integer dataCode, String dataType) {
this.dataCode = dataCode;
this.dataType = dataType;
}
public Integer getDataCode() {
return dataCode;
}
public String getDataType() {
return dataType;
}
public static void main(String[] args) {
System.out.println(dataCodeTypeMap.get(1));
}
}

@ -0,0 +1,4 @@
package com.ruoyi.common.core.hw.validated.tdengine;
public interface AddTdSTableColumn {
}

@ -0,0 +1,4 @@
package com.ruoyi.common.core.hw.validated.tdengine;
public interface InsertTdTable {
}

@ -304,7 +304,7 @@ public class IpUtils
String[] s1 = ipWildCard.split("\\.");
String[] s2 = ip.split("\\.");
boolean isMatchedSeg = true;
for (int i = 0; i < s1.length && !s1[i].equals("*"); i++)
for (int i = 0; i < s1.length && !"*".equals(s1[i]); i++)
{
if (!s1[i].equals(s2[i]))
{

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-modules</artifactId>
<version>3.6.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-modules-tdengine</artifactId>
<description>
ruoyi-modules-tdengine 时序数据库处理模块
</description>
<dependencies>
<!-- SpringCloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- SpringCloud Alibaba Nacos Config -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- SpringCloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- SpringBoot Actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Swagger UI -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.fox.version}</version>
</dependency>
<!-- RuoYi Common DataSource -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-datasource</artifactId>
</dependency>
<!-- RuoYi Common DataScope -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-datascope</artifactId>
</dependency>
<!-- RuoYi Common Log -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-log</artifactId>
</dependency>
<!-- RuoYi Common Swagger -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-swagger</artifactId>
</dependency>
<!-- TDengine -->
<dependency>
<groupId>com.taosdata.jdbc</groupId>
<artifactId>taos-jdbcdriver</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>hw-api-tdengine</artifactId>
<version>3.6.3</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,34 @@
package com.ruoyi.tdengine;
import com.ruoyi.common.security.annotation.EnableCustomConfig;
import com.ruoyi.common.security.annotation.EnableRyFeignClients;
import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
*
*
* @author ruoyi
*/
@EnableCustomConfig
@EnableCustomSwagger2
@EnableRyFeignClients
@SpringBootApplication
public class HwTdengineApplication
{
public static void main(String[] args)
{
SpringApplication.run(HwTdengineApplication.class, args);
System.out.println("(♥◠‿◠)ノ゙ 时序数据库模块启动成功 ლ(´ڡ`ლ)゙ \n" +
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +
" |(_ o _) / _( )_ .' \n" +
" | (_,_).' __ ___(_ o _)' \n" +
" | |\\ \\ | || |(_,_)' \n" +
" | | \\ `' /| `-' / \n" +
" | | \\ / \\ / \n" +
" ''-' `'-' `-..-' ");
}
}

@ -0,0 +1,339 @@
package com.ruoyi.tdengine.controller;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.hw.validated.tdengine.AddTdSTableColumn;
import com.ruoyi.common.core.hw.validated.tdengine.InsertTdTable;
import com.ruoyi.tdengine.api.domain.*;
import com.ruoyi.tdengine.service.ITdEngineService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
/**
* @ClassDescription: TdEngine Controller
* @ClassName: TdEngineController
* @Author: xins
* @Date: 2023-08-25 16:38:44
* @Version 1.0
*/
@RestController
@RequestMapping("/tdengine")
public class TdEngineController {
@Autowired
private ITdEngineService tdEngineService;
private static final Logger log = LoggerFactory.getLogger(TdEngineController.class);
/* @description
* @author xins
* @date 2023-08-28 11:38
* @param databaseName
* @return R<?>
*/
@PostMapping("/createDatabase")
public R<?> createDataBase(@RequestBody() String databaseName) {
try {
//调用创建数据库方法
this.tdEngineService.createDatabase(databaseName);
log.info("success for create database " + databaseName);
return R.ok();
} catch (UncategorizedSQLException e) {
String message = e.getCause().getMessage();
try {
message = message.substring(message.lastIndexOf("invalid operation"));
} catch (Exception ex) {
}
log.error(message);
return R.fail(message);
} catch (Exception e) {
log.error(e.getMessage());
return R.fail(e.getMessage());
}
}
/* * @description
* @author xins
* @date 2023-08-28 11:41
* @param tdSuperTableVo
* @return R<?>
*/
@PostMapping("/createSuperTable")
public R<?> createSuperTable(@Validated @RequestBody TdSuperTableVo tdSuperTableVo) {
//数据库名称
String databaseName = tdSuperTableVo.getDatabaseName();
//超级表名称
String superTableName = tdSuperTableVo.getSuperTableName();
//第一个字段名称
String firstFieldName = tdSuperTableVo.getFirstFieldName();
//schema列字段超级表结构对象集合
List<TdField> schemaFields = tdSuperTableVo.getSchemaFields();
//标签字段对象集合
List<TdField> tagsFields = tdSuperTableVo.getTagsFields();
try {
//将Schema字段对象和标签字段对象转换为创建表的字段Vo类对象集合
List<TdFieldVo> schemaFieldsVos = TdFieldVo.batchConvertFields(schemaFields);
List<TdFieldVo> tagsFieldsVos = TdFieldVo.batchConvertFields(tagsFields);
this.tdEngineService.createSuperTable(databaseName, superTableName, firstFieldName, schemaFieldsVos, tagsFieldsVos);
log.info("success for create superTable " + superTableName);
return R.ok("created superTable '" + superTableName + "' success");
} catch (UncategorizedSQLException e) {
String message = e.getCause().getMessage();
try {
message = message.substring(message.lastIndexOf("invalid operation"));
} catch (Exception ex) {
}
log.error(message);
return R.fail(message);
} catch (Exception e) {
log.error(e.getMessage());
return R.fail(e.getMessage());
}
}
/**
* @return R<?>
* @param: tableDto
* @description
* @author xins
* @date 2023-08-28 16:17
*/
@PostMapping("/createTable")
public R<?> createTable(@Validated @RequestBody TdTableVo tdTableVo) {
try {
String databaseName = tdTableVo.getDatabaseName();
String superTableName = tdTableVo.getSuperTableName();
String tableName = tdTableVo.getTableName();
List<TdField> tagsFieldValues = tdTableVo.getTagsFieldValues();
this.tdEngineService.createTable(databaseName, superTableName, tableName, tagsFieldValues);
log.info("success for create table " + tableName);
return R.ok("created table '" + tableName + "' success");
} catch (Exception e) {
String message = e.getCause().getMessage();
try {
message = message.substring(message.lastIndexOf("invalid operation"));
} catch (Exception ex) {
log.error(ex.getMessage());
}
log.error(message);
return R.fail(message);
}
}
/**
* @return R<?>
* @param: tdSuperTableVo
* @description
* @author xins
* @date 2023-08-28 17:55
*/
@PostMapping("/addSuperTableColumn")
public R<?> addSuperTableColumn(@Validated(AddTdSTableColumn.class) @RequestBody TdSuperTableVo tdSuperTableVo) {
String databaseName = tdSuperTableVo.getDatabaseName();
String superTableName = tdSuperTableVo.getSuperTableName();
TdField addTdField = tdSuperTableVo.getField();
try {
TdFieldVo addFieldVo = TdFieldVo.convertField(addTdField);
this.tdEngineService.addSuperTableColumn(databaseName, superTableName, addFieldVo);
log.info("success for add column for superTable " + superTableName + "");
return R.ok();
} catch (UncategorizedSQLException e) {
String message = e.getCause().getMessage();
try {
message = message.substring(message.lastIndexOf("invalid operation"));
} catch (Exception ex) {
}
log.error(message);
return R.fail(message);
} catch (Exception e) {
log.error(e.getMessage());
return R.fail(e.getMessage());
}
}
/**
* @return R<?>
* @param: tdSuperTableVo
* @description
* @author xins
* @date 2023-08-28 17:56
*/
@PostMapping("/dropSuperTableColumn")
public R<?> dropColumnForSuperTable(@Validated(AddTdSTableColumn.class) @RequestBody TdSuperTableVo tdSuperTableVo) {
String databaseName = tdSuperTableVo.getDatabaseName();
String superTableName = tdSuperTableVo.getSuperTableName();
TdField dropField = tdSuperTableVo.getField();
try {
TdFieldVo dropFieldVo = TdFieldVo.convertField(dropField);
this.tdEngineService.dropSuperTableColumn(databaseName, superTableName, dropFieldVo);
log.info("successful operation: drop column for superTable '" + superTableName + "' success");
return R.ok();
} catch (UncategorizedSQLException e) {
String message = e.getCause().getMessage();
try {
message = message.substring(message.lastIndexOf("invalid operation"));
} catch (Exception ex) {
}
log.error(message);
return R.fail(message);
} catch (Exception e) {
log.error(e.getMessage());
return R.fail(e.getMessage());
}
}
/**
* @return R<?>
* @param: tdTableVo
* @description
* @author xins
* @date 2023-08-29 10:04
*/
@PostMapping("/insertTable")
public R<?> insertTable(@Validated(InsertTdTable.class) @RequestBody TdTableVo tdTableVo) {
try {
String databaseName = tdTableVo.getDatabaseName();
String tableName = tdTableVo.getTableName();
List<TdField> schemaFields = tdTableVo.getSchemaFields();
this.tdEngineService.insertTable(databaseName, tableName, schemaFields);
log.info("success for insert table " + databaseName + "." + tableName);
return R.ok();
} catch (UncategorizedSQLException e) {
String message = e.getCause().getMessage();
try {
message = message.substring(message.lastIndexOf("invalid operation"));
} catch (Exception ex) {
}
log.error(message);
return R.fail(message);
} catch (Exception e) {
log.error(e.getMessage());
return R.fail(e.getMessage());
}
}
/**
* @return R<?>
* @param: tdSelectDto
* @description
* @author xins
* @date 2023-08-29 11:26
*/
@PostMapping("/getLatestData")
public R<?> getLatestData(@Validated @RequestBody TdSelectDto tdSelectDto) {
try {
return R.ok(this.tdEngineService.getLatestData(tdSelectDto));
} catch (UncategorizedSQLException e) {
String message = e.getCause().getMessage();
try {
message = message.substring(message.lastIndexOf("invalid operation"));
} catch (Exception ex) {
}
log.error(message);
return R.fail(message);
} catch (Exception e) {
log.error(e.getMessage());
return R.fail(e.getMessage());
}
}
/**
* @return R<Map < String, Map < String, Object>>>
* @param: tdSelectDto
* @description tagsname
* @author xins
* @date 2023-08-29 14:51
*/
@PostMapping("/getLatestDataByTags")
public R<Map<String, Map<String, Object>>> getLatestDataByTags(@RequestBody TdSelectDto tdSelectDto) {
try {
return R.ok(this.tdEngineService.getLatestDataByTags(tdSelectDto));
} catch (UncategorizedSQLException e) {
String message = e.getCause().getMessage();
try {
message = message.substring(message.lastIndexOf("invalid operation"));
} catch (Exception ex) {
}
log.error(message);
return R.fail(message);
} catch (Exception e) {
log.error(e.getMessage());
return R.fail(e.getMessage());
}
}
/**
* @param tdHistorySelectDto
* @return R<?>
* @MethodDescription
* SELECT voltage ,ts FROM test.meters where ts between '2017-07-14 02:40:00.000' and '2017-07-14 02:40:00.001' LIMIT [topnums]
* ts > now - 24h;
* select col from table LIMIT [topnums]
* select [avg/max/sum/count..](col) from table where ts between '2017-07-14 02:40:00.000' and '2017-07-14 02:40:00.001' group by col LIMIT [topnums]
*/
@PostMapping("/getHistoryData")
public R<?> getHistoryData(@Validated @RequestBody TdHistorySelectDto tdHistorySelectDto) {
try {
// if (selectVisualDto.getType() == 0) {//查询历史
// return R.ok(this.tdEngineService.getHistoryData(selectVisualDto));
// }else if(selectVisualDto.getType() == 1) {//查询实时
// return R.ok(this.tdEngineService.getRealtimeData(selectVisualDto));
// }else {//查询聚合
// return R.ok(this.tdEngineService.getAggregateData(selectVisualDto));
// }
return R.ok(this.tdEngineService.getHistoryData(tdHistorySelectDto));
} catch (UncategorizedSQLException e) {
String message = e.getCause().getMessage();
try {
message = message.substring(message.lastIndexOf("invalid operation"));
} catch (Exception ex) {
}
log.error(message);
return R.fail(message);
} catch (Exception e) {
log.error(e.getMessage());
return R.fail(e.getMessage());
}
}
/**
* @param: tdHistorySelectDto
* @description
* @author xins
* @date 2023-08-29 17:29
* @return R<?>
*/
@PostMapping("/getCountOfHistoryData")
public R<?> getCountOfHistoryData(@Validated @RequestBody TdHistorySelectDto tdHistorySelectDto) {
try {
return R.ok(this.tdEngineService.getCountOfHistoryData(tdHistorySelectDto));
} catch (UncategorizedSQLException e) {
String message = e.getCause().getMessage();
try {
message = message.substring(message.lastIndexOf("invalid operation"));
} catch (Exception ex) {
}
log.error(message);
return R.fail(message);
} catch (Exception e) {
log.error(e.getMessage());
return R.fail(e.getMessage());
}
}
}

@ -0,0 +1,154 @@
package com.ruoyi.tdengine.mapper;
import com.ruoyi.tdengine.api.domain.TdField;
import com.ruoyi.tdengine.api.domain.TdFieldVo;
import com.ruoyi.tdengine.api.domain.TdHistorySelectDto;
import com.ruoyi.tdengine.api.domain.TdSelectDto;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* @ClassDescription:
* @ClassName: TdEngineMapper
* @Author: thinglinks
* @Date: 2021-12-27 14:52:34
* @Version 1.0
*/
public interface TdEngineMapper {
/**
* @param databaseName
* @description
* @author xins
* @date 2023-08-28 13:16
*/
void createDatabase(String databaseName);
/**
* @param databaseName
* @param superTableName
* @param firstFieldName
* @param schemaFields
* @param tagsFields
* @description
* @author xins
* @date 2023-08-28 11:09
*/
void createSuperTable(@Param("databaseName") String databaseName,
@Param("superTableName") String superTableName,
@Param("firstFieldName") String firstFieldName,
@Param("schemaFields") List<TdFieldVo> schemaFields,
@Param("tagsFields") List<TdFieldVo> tagsFields
);
/**
* @param: databaseName
* @param: superTableName
* @param: tableName
* @param: tagsFieldValues
* @description
* @author xins
* @date 2023-08-28 15:58
*/
void createTable(@Param("databaseName") String databaseName,
@Param("superTableName") String superTableName,
@Param("tableName") String tableName,
@Param("tagsFieldValues") List<TdField> tagsFieldValues);
/**
* @param: databaseName
* @param: superTableName
* @param: addFieldsVo
* @description
* @author xins
* @date 2023-08-28 17:11
*/
void addSuperTableColumn(@Param("databaseName") String databaseName,
@Param("superTableName") String superTableName,
@Param("addFieldsVo") TdFieldVo addFieldsVo);
/**
* @param: databaseName
* @param: superTableName
* @param: dropFieldsVo
* @description
* @author xins
* @date 2023-08-28 17:11
*/
void dropSuperTableColumn(@Param("databaseName") String databaseName,
@Param("superTableName") String superTableName,
@Param("dropFieldsVo") TdFieldVo dropFieldsVo);
/**
* @param: databaseName
* @param: tableName
* @param: schemaFields
* @description
* @author xins
* @date 2023-08-29 10:03
*/
void insertTable(@Param("databaseName") String databaseName,
@Param("tableName") String tableName,
@Param("schemaFields") List<TdField> schemaFields);
/**
* @return List<Map < Object>>
* @param: tdSelectDto
* @description
* @author xins
* @date 2023-08-29 10:43
*/
List<Map<String, Object>> getLatestData(TdSelectDto tdSelectDto);
/**
* @return List<Map < Object>>
* @param: tdSelectDto
* @description tagsname
* select last_row()
* @author xins
* @date 2023-08-29 14:42
*/
List<Map<String, Object>> getLatestDataByTags(TdSelectDto tdSelectDto);
/**
* @return List<Map < Object>>
* @param: tdSelectDto
* @description
* @author xins
* @date 2023-08-29 15:50
*/
List<Map<String, Object>> getHistoryData(TdHistorySelectDto tdHistorySelectDto);
Map<String, Long> getCountOfHistoryData(TdHistorySelectDto tdHistorySelectDto);
// /**
// * 检查表是否存在
// * @param dataBaseName
// * @param tableName 可以为超级表名或普通表名
// * @return
// */
// Integer checkTableExists(@Param("dataBaseName") String dataBaseName, @Param("tableName")String tableName);
//
// List<Map<String, Object>> getRealtimeData(SelectVisualDto selectVisualDto);
//
// List<Map<String, Object>> getAggregateData(SelectVisualDto selectVisualDto);
// void addTagForSuperTable(@Param("superTableName") String superTableName,
// @Param("fieldsVo") FieldsVo fieldsVo);
//
// void dropTagForSuperTable(@Param("superTableName") String superTableName,
// @Param("fieldsVo") FieldsVo fieldsVo);
}

@ -0,0 +1,125 @@
package com.ruoyi.tdengine.service;
import com.ruoyi.tdengine.api.domain.TdField;
import com.ruoyi.tdengine.api.domain.TdFieldVo;
import com.ruoyi.tdengine.api.domain.TdHistorySelectDto;
import com.ruoyi.tdengine.api.domain.TdSelectDto;
import java.util.List;
import java.util.Map;
/**
* @InterfaceName: ITdEngineService
* @Author : xins
* @Date :2023-08-28 13:14
* @Description: TdEngineService
* @Version :1.0
*/
public interface ITdEngineService {
/**
* @param databaseName
* @description:
* @author xins
* @date 2023-08-28 11:32
*/
public void createDatabase(String databaseName) throws Exception;
/**
* @param databaseName
* @param superTableName
* @param firstFieldName
* @param schemaFields
* @param tagsFields
* @description
* @author xins
* @date 2023-08-28 13:18
*/
public void createSuperTable(String databaseName, String superTableName, String firstFieldName, List<TdFieldVo> schemaFields, List<TdFieldVo> tagsFields) throws Exception;
/**
* @param: databaseName
* @param: superTableName
* @param: tableName
* @param: tagsFieldValues
* @description
* @author xins
* @date 2023-08-28 16:16
*/
public void createTable(String databaseName, String superTableName, String tableName, List<TdField> tagsFieldValues) throws Exception;
/**
* @param: databaseName
* @param: superTableName
* @param: addFieldsVo
* @description
* @author xins
* @date 2023-08-28 17:12
*/
public void addSuperTableColumn(String databaseName,String superTableName, TdFieldVo addFieldsVo) throws Exception;
/**
* @param: databaseName
* @param: superTableName
* @param: dropFieldsVo
* @description
* @author xins
* @date 2023-08-28 17:13
*/
public void dropSuperTableColumn(String databaseName,String superTableName, TdFieldVo dropFieldsVo) throws Exception;
/**
* @param: databaseName
* @param: tableName
* @param: schemaFields
* @description
* @author xins
* @date 2023-08-29 10:10
*/
public void insertTable(String databaseName,String tableName,List<TdField> schemaFields) throws Exception;
/**
* @param: tdSelectDto
* @description
* @author xins
* @date 2023-08-29 11:28
* @return List<Map<Object>>
*/
public List<Map<String, Object>> getLatestData(TdSelectDto tdSelectDto) throws Exception;
/**
* @return Map<Map < Object>>
* @param: tdSelectDto
* @description tagsname
* * select last_row()
* @author xins
* @date 2023-08-29 14:47
*/
public Map<String, Map<String, Object>> getLatestDataByTags(TdSelectDto tdSelectDto);
/**
* @param: tdHistorySelectDto
* @description
* @author xins
* @date 2023-08-29 15:52
* @return List<Map<Object>>
*/
public List<Map<String, Object>> getHistoryData(TdHistorySelectDto tdHistorySelectDto);
/**
* @param: tdHistorySelectDto
* @description
* @author xins
* @date 2023-08-29 16:54
* @return Long
*/
public Long getCountOfHistoryData(TdHistorySelectDto tdHistorySelectDto) throws Exception;
// void initSTableFrame(String msg) throws Exception;
// List<Map<String, Object>> getRealtimeData(SelectVisualDto selectVisualDto);
//
// List<Map<String, Object>> getAggregateData(SelectVisualDto selectVisualDto);
}

@ -0,0 +1,289 @@
package com.ruoyi.tdengine.service.impl;
import com.ruoyi.common.core.constant.TdEngineConstants;
import com.ruoyi.tdengine.api.domain.TdField;
import com.ruoyi.tdengine.api.domain.TdFieldVo;
import com.ruoyi.tdengine.api.domain.TdHistorySelectDto;
import com.ruoyi.tdengine.api.domain.TdSelectDto;
import com.ruoyi.tdengine.mapper.TdEngineMapper;
import com.ruoyi.tdengine.service.ITdEngineService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* @ClassDescription: TdEngine
* @ClassName: TdEngineServiceImpl
* @Author: xins
* @Date: 2023-08-25 15:55:50
* @Version 1.0
*/
@Service
//@Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public class TdEngineServiceImpl implements ITdEngineService {
private static final String DEFAULT_FIRST_FIELD_NAME = "ts";
@Autowired
private TdEngineMapper tdEngineMapper;
// @Autowired
// private RedisService redisService;
/**
* @param databaseName
* @description:
* @author xins
* @date 2023-08-28 11:32
*/
@Override
public void createDatabase(String databaseName) throws Exception {
this.tdEngineMapper.createDatabase(databaseName);
}
/**
* @param databaseName
* @param superTableName
* @param firstFieldName
* @param schemaFields
* @param tagsFields
* @description
* @author xins
* @date 2023-08-28 13:18
*/
@Override
public void createSuperTable(String databaseName, String superTableName, String firstFieldName, List<TdFieldVo> schemaFields, List<TdFieldVo> tagsFields) throws Exception {
if (StringUtils.isBlank(firstFieldName)) {
firstFieldName = DEFAULT_FIRST_FIELD_NAME;
}
this.tdEngineMapper.createSuperTable(databaseName, superTableName, firstFieldName, schemaFields, tagsFields);
}
/**
* @param: databaseName
* @param: superTableName
* @param: tableName
* @param: tagsFieldValues
* @description
* @author xins
* @date 2023-08-28 16:16
*/
@Override
public void createTable(String databaseName, String superTableName, String tableName, List<TdField> tagsFieldValues) throws Exception {
this.tdEngineMapper.createTable(databaseName, superTableName, tableName, tagsFieldValues);
}
/**
* @param: databaseName
* @param: superTableName
* @param: addFieldsVo
* @description
* @author xins
* @date 2023-08-28 17:12
*/
@Override
public void addSuperTableColumn(String databaseName, String superTableName, TdFieldVo addFieldsVo) throws Exception {
this.tdEngineMapper.addSuperTableColumn(databaseName, superTableName, addFieldsVo);
}
/**
* @param: databaseName
* @param: superTableName
* @param: dropFieldsVo
* @description
* @author xins
* @date 2023-08-28 17:13
*/
public void dropSuperTableColumn(String databaseName, String superTableName, TdFieldVo dropFieldsVo) throws Exception {
this.tdEngineMapper.dropSuperTableColumn(databaseName, superTableName, dropFieldsVo);
}
/**
* @param: databaseName
* @param: tableName
* @param: schemaFields
* @description
* @author xins
* @date 2023-08-29 10:10
*/
@Override
public void insertTable(String databaseName, String tableName, List<TdField> schemaFields) throws Exception {
this.tdEngineMapper.insertTable(databaseName, tableName, schemaFields);
}
/**
* @return List<Map < Object>>
* @param: tdSelectDto
* @description
* @author xins
* @date 2023-08-29 11:28
*/
@Override
public List<Map<String, Object>> getLatestData(TdSelectDto tdSelectDto) throws Exception {
List<Map<String, Object>> latestMaps = this.tdEngineMapper.getLatestData(tdSelectDto);
List<Map<String, Object>> filterMaps = new ArrayList<>();
// String i18nKey = "tdengine_supertable1_";
String i18nKey = "";//todo国际化看在哪处理
/**
* last(*)keylast(key),key
*/
for (Map<String, Object> latestMap : latestMaps) {
Map<String, Object> filterMap = latestMap.entrySet()
.stream()
.filter(entry -> entry.getValue() != null)
.collect(HashMap::new, (m, v) ->
m.put(i18nKey + v.getKey().substring(v.getKey().indexOf("(") + 1,
v.getKey().indexOf(")")), v.getValue()), HashMap::putAll);
filterMaps.add(filterMap);
}
return filterMaps;
}
/**
* @return Map<Map < Object>>
* @param: tdSelectDto
* @description tagsname
* * select last_row()
* @author xins
* @date 2023-08-29 14:47
*/
@Override
public Map<String, Map<String, Object>> getLatestDataByTags(TdSelectDto tdSelectDto) {
List<Map<String, Object>> latestMaps = this.tdEngineMapper.getLatestDataByTags(tdSelectDto);
Map<String, Map<String, Object>> tagsMap = new HashMap<>();
for (Map<String, Object> latestMap : latestMaps) {
Map<String, Object> filterMap = latestMap.entrySet()
.stream()
.filter(entry -> entry.getValue() != null)
.collect(HashMap::new, (m, v) ->
m.put(v.getKey().substring(v.getKey().indexOf("(") + 1,
v.getKey().indexOf(")")), v.getValue()), HashMap::putAll);
tagsMap.put(filterMap.get(tdSelectDto.getTagsName()).toString(), filterMap);
}
return tagsMap;
}
/**
* @return List<Map < Object>>
* @param: tdHistorySelectDto
* @description
* @author xins
* @date 2023-08-29 15:52
*/
@Override
public List<Map<String, Object>> getHistoryData(TdHistorySelectDto tdHistorySelectDto) {
if (StringUtils.isBlank(tdHistorySelectDto.getOrderByFieldName())) {
tdHistorySelectDto.setOrderByFieldName(TdEngineConstants.DEFAULT_FIRST_FIELD_NAME);
}
if (StringUtils.isBlank(tdHistorySelectDto.getOrderByMode())) {
tdHistorySelectDto.setOrderByMode(TdEngineConstants.DEFAULT_ORDER_BY_MODE);
}
List<Map<String, Object>> historyDataMaps = this.tdEngineMapper.getHistoryData(tdHistorySelectDto);
return historyDataMaps;
}
/**
* @param: tdHistorySelectDto
* @description
* @author xins
* @date 2023-08-29 16:54
* @return Long
*/
@Override
public Long getCountOfHistoryData(TdHistorySelectDto tdHistorySelectDto) throws Exception {
Map<String, Long> countMap = this.tdEngineMapper.getCountOfHistoryData(tdHistorySelectDto);
if (countMap == null) {
return 0L;
}
return countMap.get("dataCount");
}
//
// /**
// * 检查数据库表是否存在
// *
// * @param dataBaseName 数据库名
// * @param tableName tableName 可以为超级表名或普通表名
// * @return
// */
// public boolean checkTableExists(String dataBaseName, String tableName) throws Exception {
// try {
// Integer count = tdEngineMapper.checkTableExists(dataBaseName, tableName);
// return count == 1;
// } catch (Exception e) {
// log.warn("{},{} 数据库表不存在", dataBaseName, tableName);
// return false;
// }
// }
//
// @Override
// public void initSTableFrame(String msg) throws Exception {
// final SuperTableDto superTableDto = JSONObject.toJavaObject(JSONObject.parseObject(msg), SuperTableDto.class);
// //从入参对象获取列字段(超级表结构)对象集合
// List<Fields> schemaFields = superTableDto.getSchemaFields();
// //从入参对象获取标签字段对象集合
// List<Fields> tagsFields = superTableDto.getTagsFields();
// //从入参获取数据库名称
// String dataBaseName = superTableDto.getDataBaseName();
// //从入参获取超级表名称
// String superTableName = superTableDto.getSuperTableName();
// final boolean tableExists = this.checkTableExists(dataBaseName, superTableName);
// if (tableExists) {
// log.info("超级表{}已存在", superTableName);
// return;
// }
// //获取列字段对象集合的第一个对象的字段数据类型
// DataTypeEnum dataType = schemaFields.get(0).getDataType();
// //如果该数据类型不是时间戳,打印和返回报错信息
// if (dataType == null || !"timestamp".equals(dataType.getDataType())) {
// log.error("invalid operation: first column must be timestamp");
// return;
// }
// //将列字段对象集合和标签字段对象集合转码为字段Vo类对象集合
// List<FieldsVo> schemaFieldsVoList = FieldsVo.fieldsTranscoding(schemaFields);
// List<FieldsVo> tagsFieldsVoList = FieldsVo.fieldsTranscoding(tagsFields);
// //创建超级表
// this.createSuperTable(schemaFieldsVoList, tagsFieldsVoList, dataBaseName, superTableName);
// log.info("create {} super table success", superTableName);
// }
//
//
// /**
// * @param tagsSelectDao
// * @return
// */
// @Override
//
//
//
// @Override
// public List<Map<String, Object>> getRealtimeData(SelectVisualDto selectVisualDto) {
// List<Map<String, Object>> maps = this.tdEngineMapper.getRealtimeData(selectVisualDto);
// return maps;
// }
//
// @Override
// public List<Map<String, Object>> getAggregateData(SelectVisualDto selectVisualDto) {
// List<Map<String, Object>> maps = this.tdEngineMapper.getAggregateData(selectVisualDto);
// return maps;
// }
}

@ -0,0 +1,10 @@
Spring Boot Version: ${spring-boot.version}
Spring Application Name: ${spring.application.name}
_ _
(_) | |
_ __ _ _ ___ _ _ _ ______ ___ _ _ ___ | |_ ___ _ __ ___
| '__|| | | | / _ \ | | | || ||______|/ __|| | | |/ __|| __| / _ \| '_ ` _ \
| | | |_| || (_) || |_| || | \__ \| |_| |\__ \| |_ | __/| | | | | |
|_| \__,_| \___/ \__, ||_| |___/ \__, ||___/ \__| \___||_| |_| |_|
__/ | __/ |
|___/ |___/

@ -0,0 +1,25 @@
# Tomcat
server:
port: 9602
# Spring
spring:
application:
# 应用名称
name: hw-tdengine
profiles:
# 环境配置
active: dev
cloud:
nacos:
discovery:
# 服务注册地址
server-addr: 127.0.0.1:8848
config:
# 配置中心地址
server-addr: 127.0.0.1:8848
# 配置文件格式
file-extension: yml
# 共享配置
shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 -->
<property name="log.path" value="logs/hw-tdengine" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.ruoyi" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
</configuration>

@ -0,0 +1,251 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.tdengine.mapper.TdEngineMapper">
<update id="createDatabase" parameterType="String">
create database if not exists #{databaseName}
</update>
<update id="createSuperTable">
create table if not exists #{databaseName}.#{superTableName}
(${firstFieldName} timestamp,
<!--tdEngine不支持动态fields里的数据类型只能使用choose-->
<foreach item="item" collection="schemaFields" separator=","
index="">
<if test="item.fieldName != null and item.fieldName != ''">
${item.fieldName}
</if>
<if test="item.dataType != null and item.dataType != ''">
<choose>
<when test="item.dataType == 'timestamp'">
timestamp
</when>
<when test="item.dataType == 'tinyint'">
tinyint
</when>
<when test="item.dataType == 'smallint'">
smallint
</when>
<when test="item.dataType == 'int'">
int
</when>
<when test="item.dataType == 'bigint'">
bigint
</when>
<when test="item.dataType == 'float'">
float
</when>
<when test="item.dataType == 'double'">
double
</when>
<when test="item.dataType == 'binary'">
binary
</when>
<when test="item.dataType == 'nchar'">
nchar
</when>
<when test="item.dataType == 'bool'">
bool
</when>
<when test="item.dataType == 'json'">
json
</when>
</choose>
</if>
<if test="item.size != null">
(#{item.size})
</if>
</foreach>
) tags
<!--tdEngine不支持动态tags里的数据类型只能使用choose-->
<foreach item="item" collection="tagsFields" separator=","
open="(" close=")" index="">
<if test="item.fieldName != null and item.fieldName != ''">
${item.fieldName}
</if>
<if test="item.dataType != null and item.dataType != ''">
<choose>
<when test="item.dataType == 'timestamp'">
timestamp
</when>
<when test="item.dataType == 'int'">
int
</when>
<when test="item.dataType == 'bigint'">
bigint
</when>
<when test="item.dataType == 'float'">
float
</when>
<when test="item.dataType == 'double'">
double
</when>
<when test="item.dataType == 'binary'">
binary
</when>
<when test="item.dataType == 'smallint'">
smallint
</when>
<when test="item.dataType == 'tinyint'">
tinyint
</when>
<when test="item.dataType == 'bool'">
bool
</when>
<when test="item.dataType == 'nchar'">
nchar
</when>
<when test="item.dataType == 'json'">
json
</when>
</choose>
</if>
<if test="item.size != null">
(#{item.size})
</if>
</foreach>
</update>
<update id="createTable">
create table if not exists #{databaseName}.#{tableName}
using #{databaseName}.#{superTableName}
tags
<foreach item="item" collection="tagsFieldValues" separator=","
open="(" close=")" index="">
${item.fieldValue}
</foreach>
</update>
<update id="addSuperTableColumn">
ALTER STABLE #{databaseName}.#{superTableName} ADD COLUMN
<if test="addFieldsVo.fieldName != null and addFieldsVo.fieldName != ''">
${addFieldsVo.fieldName}
</if>
<if test="addFieldsVo.dataType != null and addFieldsVo.dataType != ''">
<choose>
<when test="addFieldsVo.dataType == 'timestamp'">
timestamp
</when>
<when test="addFieldsVo.dataType == 'int'">
int
</when>
<when test="addFieldsVo.dataType == 'bigint'">
bigint
</when>
<when test="addFieldsVo.dataType == 'float'">
float
</when>
<when test="addFieldsVo.dataType == 'double'">
double
</when>
<when test="addFieldsVo.dataType == 'binary'">
binary
</when>
<when test="addFieldsVo.dataType == 'smallint'">
smallint
</when>
<when test="addFieldsVo.dataType == 'tinyint'">
tinyint
</when>
<when test="addFieldsVo.dataType == 'bool'">
bool
</when>
<when test="addFieldsVo.dataType == 'nchar'">
nchar
</when>
<when test="addFieldsVo.dataType == 'json'">
json
</when>
</choose>
</if>
<if test="addFieldsVo.size != null">
(#{addFieldsVo.size})
</if>
</update>
<update id="dropSuperTableColumn">
ALTER STABLE #{databaseName}.#{superTableName} DROP COLUMN
<if test="dropFieldsVo.fieldName != null and dropFieldsVo.fieldName != ''">
${dropFieldsVo.fieldName}
</if>
</update>
<!-- 需要提前建表。如果用插入记录时自动建表则会有概率出现问题:设备上报的属性值跟定义的属性值不同的情况-->
<insert id="insertTable">
insert into #{databaseName}.#{tableName}
<foreach item="item" collection="schemaFields" separator=","
open="(" close=")" index="">
${item.fieldName}
</foreach>
values
<foreach item="item" collection="schemaFields" separator=","
open="(" close=")" index="">
#{item.fieldValue}
</foreach>
</insert>
<!--适用于设备监测页面,先根据监控单元获取设备信息,再根据设备来获取最新的数据-->
<select id="getLatestData" parameterType="com.ruoyi.tdengine.api.domain.TdSelectDto"
resultType="java.util.Map">
select last(*) from #{databaseName}.#{tableName}
</select>
<!--适用于设备汇总页面,先分页获取设备信息,再获取所有此物模型下的最新信息(冗余,但每页只获取一次,不需要每个设备都获取一次
如果需要根据时间周期获取最新的数据则需要用select last_row()-->
<select id="getLatestDataByTags" parameterType="com.ruoyi.tdengine.api.domain.TdSelectDto"
resultType="java.util.Map">
select last(*), last(${tagsName}) from #{databaseName}.#{superTableName} group by ${tagsName}
</select>
<select id="getHistoryData" parameterType="com.ruoyi.tdengine.api.domain.TdSelectDto" resultType="java.util.Map" >
SELECT * FROM #{databaseName}.#{tableName}
<where>
<if test="#{firstFieldName} != null and #{firstFieldName} != '' and
startTime!= 0 and endTime != 0">
${firstFieldName} BETWEEN #{startTime} AND #{endTime}
</if>
</where>
order by ${orderByFieldName}
<if test="#{orderByMode} != null and #{orderByMode} != ''">
${orderByMode}
</if>
<if test="offset != 0 and limit != 0 ">
LIMIT #{offset},#{limit}
</if>
</select>
<select id="getCountOfHistoryData" parameterType="com.ruoyi.tdengine.api.domain.TdSelectDto" resultType="java.util.Map" >
<!--as后不要用常用单词例如count会报错-->
SELECT count(0) as dataCount FROM #{databaseName}.#{tableName}
<where>
<if test="#{firstFieldName} != null and #{firstFieldName} != '' and
startTime!= 0 and endTime != 0">
${firstFieldName} BETWEEN #{startTime} AND #{endTime}
</if>
</where>
</select>
<!--
<select id="checkTableExists" resultType="java.lang.Integer">
SELECT COUNT(0) FROM #{dataBaseName}.#{tableName}
</select>
<select id="getRealtimeData" resultType="java.util.Map" parameterType="">
SELECT #{fieldName},ts
FROM #{dataBaseName}.#{tableName} LIMIT #{num}
</select>
<select id="getAggregateData" resultType="java.util.Map" parameterType="">
SELECT #{aggregate}(${fieldName})
FROM #{dataBaseName}.#{tableName} WHERE ts BETWEEN #{startTime} AND #{endTime} interval(${interval}) LIMIT #{num}
</select>-->
</mapper>

@ -26,6 +26,7 @@
<module>hw-mqtt-broker</module>
<module>hw-business</module>
<module>hw-basic</module>
<module>hw-tdengine</module>
</modules>
<artifactId>ruoyi-modules</artifactId>

Loading…
Cancel
Save