Browse Source

首次提交

xushili 2 years ago
commit
fa5de2cd21
47 changed files with 1957 additions and 0 deletions
  1. 37 0
      .gitignore
  2. 46 0
      build.gradle
  3. BIN
      gradle/wrapper/gradle-wrapper.jar
  4. 5 0
      gradle/wrapper/gradle-wrapper.properties
  5. 240 0
      gradlew
  6. 91 0
      gradlew.bat
  7. 1 0
      settings.gradle
  8. 13 0
      src/main/java/com/gyee/redis2taos/Redis2taosApp.java
  9. 30 0
      src/main/java/com/gyee/redis2taos/config/FilePathConfig.java
  10. 33 0
      src/main/java/com/gyee/redis2taos/config/RedisConfig.java
  11. 103 0
      src/main/java/com/gyee/redis2taos/config/TaosConfig.java
  12. 70 0
      src/main/java/com/gyee/redis2taos/config/ThreadPoolTaskConfig.java
  13. 70 0
      src/main/java/com/gyee/redis2taos/controller/TaosController.java
  14. 76 0
      src/main/java/com/gyee/redis2taos/service/FileService.java
  15. 72 0
      src/main/java/com/gyee/redis2taos/service/ReadAndWriteService.java
  16. 48 0
      src/main/java/com/gyee/redis2taos/service/RedisService.java
  17. 116 0
      src/main/java/com/gyee/redis2taos/service/TaosService.java
  18. 50 0
      src/main/java/com/gyee/redis2taos/service/TaskInsert2Taos.java
  19. 126 0
      src/main/java/com/gyee/redis2taos/service/TaskRedis2Taos.java
  20. 47 0
      src/main/java/com/gyee/redis2taos/timeseries/BaseTsQuery.java
  21. 40 0
      src/main/java/com/gyee/redis2taos/timeseries/BasicTsData.java
  22. 68 0
      src/main/java/com/gyee/redis2taos/timeseries/BasicTsPoint.java
  23. 24 0
      src/main/java/com/gyee/redis2taos/timeseries/BlobTsData.java
  24. 22 0
      src/main/java/com/gyee/redis2taos/timeseries/BlobWriteTsData.java
  25. 20 0
      src/main/java/com/gyee/redis2taos/timeseries/BooleanTsData.java
  26. 19 0
      src/main/java/com/gyee/redis2taos/timeseries/BooleanWriteTsData.java
  27. 18 0
      src/main/java/com/gyee/redis2taos/timeseries/Coordinate.java
  28. 26 0
      src/main/java/com/gyee/redis2taos/timeseries/CoordinateTsData.java
  29. 26 0
      src/main/java/com/gyee/redis2taos/timeseries/CoordinateWriteTsData.java
  30. 30 0
      src/main/java/com/gyee/redis2taos/timeseries/DoubleStatData.java
  31. 33 0
      src/main/java/com/gyee/redis2taos/timeseries/DoubleTsData.java
  32. 19 0
      src/main/java/com/gyee/redis2taos/timeseries/DoubleWriteTsData.java
  33. 28 0
      src/main/java/com/gyee/redis2taos/timeseries/GeneralTsData.java
  34. 20 0
      src/main/java/com/gyee/redis2taos/timeseries/IntegerTsData.java
  35. 8 0
      src/main/java/com/gyee/redis2taos/timeseries/Interpolation.java
  36. 24 0
      src/main/java/com/gyee/redis2taos/timeseries/LongTsData.java
  37. 20 0
      src/main/java/com/gyee/redis2taos/timeseries/LongWriteTsData.java
  38. 24 0
      src/main/java/com/gyee/redis2taos/timeseries/StringTsData.java
  39. 20 0
      src/main/java/com/gyee/redis2taos/timeseries/StringWriteTsData.java
  40. 15 0
      src/main/java/com/gyee/redis2taos/timeseries/TsData.java
  41. 15 0
      src/main/java/com/gyee/redis2taos/timeseries/TsDataType.java
  42. 21 0
      src/main/java/com/gyee/redis2taos/timeseries/TsPoint.java
  43. 54 0
      src/main/java/com/gyee/redis2taos/timeseries/TsPointData.java
  44. 23 0
      src/main/java/com/gyee/redis2taos/timeseries/TsPointDataList.java
  45. 21 0
      src/main/java/com/gyee/redis2taos/timeseries/TsQuery.java
  46. 32 0
      src/main/resources/application.yml
  47. 13 0
      src/test/java/com/gyee/redis2taos/Redis2taosApplicationTests.java

+ 37 - 0
.gitignore

@@ -0,0 +1,37 @@
+HELP.md
+.gradle
+build/
+!gradle/wrapper/gradle-wrapper.jar
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/

+ 46 - 0
build.gradle

@@ -0,0 +1,46 @@
+plugins {
+    id 'java'
+    id 'org.springframework.boot' version '2.7.9'
+    id 'io.spring.dependency-management' version '1.0.15.RELEASE'
+}
+
+group = 'com.gyee'
+version = '0.0.1-SNAPSHOT'
+sourceCompatibility = '1.8'
+
+configurations {
+    compileOnly {
+        extendsFrom annotationProcessor
+    }
+}
+
+repositories {
+    mavenLocal()
+    maven {
+        url 'https://maven.aliyun.com/repository/public/'
+    }
+    maven {
+        url 'https://maven.aliyun.com/repository/gradle-plugin/'
+    }
+    mavenCentral()
+}
+
+dependencies {
+    implementation 'org.springframework.boot:spring-boot-starter-web'
+    compileOnly 'org.projectlombok:lombok'
+    runtimeOnly 'com.oracle.database.jdbc:ojdbc8'
+    runtimeOnly 'org.postgresql:postgresql'
+    annotationProcessor 'org.projectlombok:lombok'
+    testImplementation 'org.springframework.boot:spring-boot-starter-test'
+
+    implementation 'redis.clients:jedis:4.3.1'
+    implementation 'xerces:xercesImpl:2.12.2'
+    implementation('org.apache.poi:poi-ooxml:5.2.3')
+    implementation 'cn.hutool:hutool-poi:5.8.12'
+    implementation 'cn.hutool:hutool-core:5.8.13'
+    implementation("com.taosdata.jdbc:taos-jdbcdriver:3.0.3")
+}
+
+tasks.named('test') {
+    useJUnitPlatform()
+}

BIN
gradle/wrapper/gradle-wrapper.jar


+ 5 - 0
gradle/wrapper/gradle-wrapper.properties

@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists

+ 240 - 0
gradlew

@@ -0,0 +1,240 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+#   Gradle start up script for POSIX generated by Gradle.
+#
+#   Important for running:
+#
+#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+#       noncompliant, but you have some other compliant shell such as ksh or
+#       bash, then to run this script, type that shell name before the whole
+#       command line, like:
+#
+#           ksh Gradle
+#
+#       Busybox and similar reduced shells will NOT work, because this script
+#       requires all of these POSIX shell features:
+#         * functions;
+#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+#         * compound commands having a testable exit status, especially «case»;
+#         * various built-in commands including «command», «set», and «ulimit».
+#
+#   Important for patching:
+#
+#   (2) This script targets any POSIX shell, so it avoids extensions provided
+#       by Bash, Ksh, etc; in particular arrays are avoided.
+#
+#       The "traditional" practice of packing multiple parameters into a
+#       space-separated string is a well documented source of bugs and security
+#       problems, so this is (mostly) avoided, by progressively accumulating
+#       options in "$@", and eventually passing that to Java.
+#
+#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+#       see the in-line comments for details.
+#
+#       There are tweaks for specific operating systems such as AIX, CygWin,
+#       Darwin, MinGW, and NonStop.
+#
+#   (3) This script is generated from the Groovy template
+#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+#       within the Gradle project.
+#
+#       You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+    APP_HOME=${app_path%"${app_path##*/}"}  # leaves a trailing /; empty if no leading path
+    [ -h "$app_path" ]
+do
+    ls=$( ls -ld "$app_path" )
+    link=${ls#*' -> '}
+    case $link in             #(
+      /*)   app_path=$link ;; #(
+      *)    app_path=$APP_HOME$link ;;
+    esac
+done
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+APP_NAME="Gradle"
+APP_BASE_NAME=${0##*/}
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+    echo "$*"
+} >&2
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in                #(
+  CYGWIN* )         cygwin=true  ;; #(
+  Darwin* )         darwin=true  ;; #(
+  MSYS* | MINGW* )  msys=true    ;; #(
+  NONSTOP* )        nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD=$JAVA_HOME/jre/sh/java
+    else
+        JAVACMD=$JAVA_HOME/bin/java
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD=java
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+    case $MAX_FD in #(
+      max*)
+        MAX_FD=$( ulimit -H -n ) ||
+            warn "Could not query maximum file descriptor limit"
+    esac
+    case $MAX_FD in  #(
+      '' | soft) :;; #(
+      *)
+        ulimit -n "$MAX_FD" ||
+            warn "Could not set maximum file descriptor limit to $MAX_FD"
+    esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+#   * args from the command line
+#   * the main class name
+#   * -classpath
+#   * -D...appname settings
+#   * --module-path (only if needed)
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+    APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+    CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+    JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    for arg do
+        if
+            case $arg in                                #(
+              -*)   false ;;                            # don't mess with options #(
+              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath
+                    [ -e "$t" ] ;;                      #(
+              *)    false ;;
+            esac
+        then
+            arg=$( cygpath --path --ignore --mixed "$arg" )
+        fi
+        # Roll the args list around exactly as many times as the number of
+        # args, so each arg winds up back in the position where it started, but
+        # possibly modified.
+        #
+        # NB: a `for` loop captures its iteration list before it begins, so
+        # changing the positional parameters here affects neither the number of
+        # iterations, nor the values presented in `arg`.
+        shift                   # remove old arg
+        set -- "$@" "$arg"      # push replacement arg
+    done
+fi
+
+# Collect all arguments for the java command;
+#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+#     shell script including quotes and variable substitutions, so put them in
+#     double quotes to make sure that they get re-expanded; and
+#   * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+        "-Dorg.gradle.appname=$APP_BASE_NAME" \
+        -classpath "$CLASSPATH" \
+        org.gradle.wrapper.GradleWrapperMain \
+        "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+    die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+#   readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+#   set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+        printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+        xargs -n1 |
+        sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+        tr '\n' ' '
+    )" '"$@"'
+
+exec "$JAVACMD" "$@"

+ 91 - 0
gradlew.bat

@@ -0,0 +1,91 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem      https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega

+ 1 - 0
settings.gradle

@@ -0,0 +1 @@
+rootProject.name = 'redis2taos'

+ 13 - 0
src/main/java/com/gyee/redis2taos/Redis2taosApp.java

@@ -0,0 +1,13 @@
+package com.gyee.redis2taos;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class Redis2taosApp {
+
+    public static void main(String[] args) {
+        SpringApplication.run(Redis2taosApp.class, args);
+    }
+
+}

+ 30 - 0
src/main/java/com/gyee/redis2taos/config/FilePathConfig.java

@@ -0,0 +1,30 @@
+package com.gyee.redis2taos.config;
+
+import org.springframework.boot.system.ApplicationHome;
+import org.springframework.stereotype.Component;
+
+import java.io.File;
+
+@Component
+public class FilePathConfig {
+    private static String filePath;
+    private static String excelPath;
+
+    public static String getFilePath() {
+        if (filePath == null) {
+            ApplicationHome home = new ApplicationHome(FilePathConfig.class);
+            filePath = home.getSource().getParentFile().getAbsolutePath();
+        }
+        return filePath;
+    }
+
+    public static String getExcelPath() {
+        if (excelPath == null) {
+            getFilePath();
+            excelPath = filePath + "\\excel\\";
+            File file = new File(excelPath);
+            if (!file.exists()) file.mkdirs();
+        }
+        return excelPath;
+    }
+}

+ 33 - 0
src/main/java/com/gyee/redis2taos/config/RedisConfig.java

@@ -0,0 +1,33 @@
+package com.gyee.redis2taos.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisPool;
+import redis.clients.jedis.JedisPoolConfig;
+
+@Component
+public class RedisConfig {
+    @Value("${redis.host:127.0.0.1}")
+    private String host;
+    @Value("${redis.port:6379}")
+    private Integer port;
+    @Value("${redis.password:}")
+    private String password;
+
+    private JedisPool jedisPool;
+
+    public Jedis getJedis() {
+        if (jedisPool == null) {
+            JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
+            // 最大连接
+            jedisPoolConfig.setMaxTotal(32);
+            // 最大空闲连接
+            jedisPoolConfig.setMaxIdle(64);
+            // 最小空闲连接
+            jedisPoolConfig.setMinIdle(0);
+            jedisPool = new JedisPool(jedisPoolConfig, host, port, 5000, password);
+        }
+        return jedisPool.getResource();
+    }
+}

+ 103 - 0
src/main/java/com/gyee/redis2taos/config/TaosConfig.java

@@ -0,0 +1,103 @@
+package com.gyee.redis2taos.config;
+
+import com.taosdata.jdbc.TSDBDriver;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.util.Properties;
+
+@Slf4j
+@Configuration
+public class TaosConfig {
+
+    @Value("${taoscz.server_ip:192.168.1.60}")
+    private String serverIp;
+
+    @Value("${taoscz.server_port:6030}")
+    private int serverPort;
+
+    @Value("${taoscz.db_name:power_test}")
+    private String dbName;
+
+    @Value("${taoscz.user_name:root}")
+    private String userName;
+
+    @Value("${taoscz.password:taosdata}")
+    private String password;
+
+    @Value("${taoscz.pool_size:10}")
+    private int poolSize;
+
+    @Value("${taoscz.max_pool_size:100}")
+    private int maxPoolSize;
+
+    @Value("${taoscz.driver_type:com.taosdata.jdbc.rs.RestfulDriver}")
+    private String driverType;
+
+    @Value("${taoscz.ai_stable_name:windturbineai}")
+    private String aiStableName;
+
+    @Value("${taoscz.di_stable_name:windturbinedi}")
+    private String diStableName;
+
+    private Connection connection = null;
+    private Connection createCon = null;
+
+    public Connection getInstance() throws Exception {
+        if (null == connection || connection.isClosed())
+            connection = getConnection();
+
+        return connection;
+    }
+
+    public Connection getCreateCon() throws Exception {
+        if (null == createCon || createCon.isClosed()) {
+            Class.forName(driverType);
+            String jdbcUrl = "jdbc:TAOS-RS://" + serverIp + ":" + serverPort + "?user=" + userName + "&password=" + password;
+            if (driverType.equals("com.taosdata.jdbc.TSDBDriver"))
+                jdbcUrl = "jdbc:TAOS://" + serverIp + ":" + serverPort + "?user=" + userName + "&password=" + password;
+            Properties connProps = new Properties();
+            connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
+            connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
+            connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
+            createCon = DriverManager.getConnection(jdbcUrl, connProps);
+        }
+        return createCon;
+    }
+
+    private Connection getConnection() throws Exception {
+        Connection connection = null;
+
+        Class.forName(driverType);
+        String jdbcUrl = "jdbc:TAOS-RS://" + serverIp + ":" + serverPort + "/" + dbName + "?user=" + userName + "&password=" + password;
+        if (driverType.equals("com.taosdata.jdbc.TSDBDriver"))
+            jdbcUrl = "jdbc:TAOS://" + serverIp + ":" + serverPort + "/" + dbName + "?user=" + userName + "&password=" + password;
+        Properties connProps = new Properties();
+        connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
+        connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
+        connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
+        connection = DriverManager.getConnection(jdbcUrl, connProps);
+
+        return connection;
+    }
+
+    public String getTableName(String tagName) {
+        return dbName + "." + tagName;
+    }
+
+    public String getDbName() {
+        return dbName;
+    }
+
+
+    public String getAIStableName() {
+        return aiStableName;
+    }
+
+    public String getDIStableName() {
+        return diStableName;
+    }
+}

+ 70 - 0
src/main/java/com/gyee/redis2taos/config/ThreadPoolTaskConfig.java

@@ -0,0 +1,70 @@
+package com.gyee.redis2taos.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.ThreadPoolExecutor;
+
+@Configuration
+public class ThreadPoolTaskConfig {
+
+    /**
+     *   默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务,
+     *	当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中;
+     *  当队列满了,就继续创建线程,当线程数量大于等于maxPoolSize后,开始使用拒绝策略拒绝
+     */
+
+    /**
+     * 核心线程数(默认线程数)
+     */
+    private static final int corePoolSize = 64;
+    /**
+     * 最大线程数
+     */
+    private static final int maxPoolSize = 128;
+    /**
+     * 允许线程空闲时间(单位:默认为秒)
+     */
+    private static final int keepAliveTime = 60;
+    /**
+     * 缓冲队列大小
+     */
+    private static final int queueCapacity = 1000;
+    /**
+     * 允许等待最长时间
+     */
+    private static final int awaitTime = 60;
+    /**
+     * 线程池名前缀
+     */
+    private static final String threadNamePrefix = "GYEE-Thread-";
+
+    private ThreadPoolTaskExecutor executor;
+
+    public ThreadPoolTaskExecutor getInstance() {
+        if (executor == null)
+            executor = taskExecutor();
+
+        return executor;
+    }
+
+    @Bean
+    public ThreadPoolTaskExecutor taskExecutor() {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        executor.setCorePoolSize(corePoolSize);
+        executor.setMaxPoolSize(maxPoolSize);
+        executor.setQueueCapacity(queueCapacity);
+        executor.setKeepAliveSeconds(keepAliveTime);
+        executor.setThreadNamePrefix(threadNamePrefix);
+        executor.setAwaitTerminationSeconds(awaitTime);
+
+        // 线程池对拒绝任务的处理策略
+        // CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务
+        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+        // 初始化
+        executor.initialize();
+        return executor;
+    }
+
+}

+ 70 - 0
src/main/java/com/gyee/redis2taos/controller/TaosController.java

@@ -0,0 +1,70 @@
+package com.gyee.redis2taos.controller;
+
+import com.gyee.redis2taos.service.RedisService;
+import com.gyee.redis2taos.service.TaosService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController("/taos")
+public class TaosController {
+
+    @Autowired
+    private RedisService redisService;
+    @Autowired
+    private TaosService taosService;
+
+    //TODO 升级用mybatis-plus
+
+    @GetMapping("/database/create")
+    private boolean stableCreat(int keepday) {
+        try {
+            return taosService.createDataBase(keepday);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return false;
+    }
+
+    @GetMapping("/stable/create")
+    private void stableCreat() {
+        try {
+            taosService.createStables();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @GetMapping("/table/create")
+    private void tableCreat() {
+        try {
+            taosService.createTables();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @GetMapping("/table/create2")
+    private void tableCreat2() {
+        try {
+            redisService.creatTables();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @GetMapping("/table/delete")
+    private void tableDelete() {
+
+    }
+
+    @GetMapping("/table/update")
+    private void tableUpdate() {
+
+    }
+
+    @GetMapping("/table/select")
+    private void tableSelect() {
+
+    }
+}

+ 76 - 0
src/main/java/com/gyee/redis2taos/service/FileService.java

@@ -0,0 +1,76 @@
+package com.gyee.redis2taos.service;
+
+import cn.hutool.poi.excel.ExcelUtil;
+import cn.hutool.poi.excel.sax.handler.RowHandler;
+import com.gyee.redis2taos.config.FilePathConfig;
+import com.gyee.redis2taos.config.TaosConfig;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Slf4j
+@Service
+public class FileService {
+
+    @Autowired
+    private TaosConfig taosConfig;
+
+    private List<StringBuilder> sbList = new ArrayList<>();
+    private StringBuilder sb = new StringBuilder();
+    private String type = null;
+    private List<String> point = new ArrayList<>();
+
+    private String s0 = null;
+    private int i = 0;
+    private String substring = null;
+
+    public List<StringBuilder> getExcelTaos() {
+        if (sbList.size() == 0)
+            ExcelUtil.readBySax(FilePathConfig.getExcelPath() + "Taos及Redis更新表.xlsx", 0, createRowHandler());
+        log.info("Excel数据转换完毕!");
+        return sbList;
+    }
+
+    public List<String> getExcelRedis() {
+        if (point.size() == 0) getExcelTaos();
+        return point;
+    }
+
+    private RowHandler createRowHandler() {
+        return new RowHandler() {
+            @Override
+            public void handle(int sheetIndex, long rowIndex, List<Object> rowlist) {
+                //entity = new TaosEntity();
+                if (rowIndex == 0) {
+                    log.info("Excel读取完毕!");
+                    sbList.add(sb);
+                    sb.append("create table");
+                    return;
+                }
+                if (rowIndex % 2999 == 0) {
+                    sb = new StringBuilder();
+                    sbList.add(sb);
+                    sb.append("create table");
+                }
+                if ("double".equals(rowlist.get(7))) {
+                    type = taosConfig.getAIStableName();
+                } else {
+                    type = taosConfig.getDIStableName();
+                }
+                s0 = rowlist.get(0).toString();
+                i = s0.indexOf(".");
+                substring = s0.substring(i + 1);
+                sb.append(" if not exists ").append(taosConfig.getDbName()).append(".").append(substring).append(" using ")
+                        .append(taosConfig.getDbName()).append(".").append(type).append(" tags('").append(rowlist.get(1)).append("','")
+                        .append(rowlist.get(2)).append("','").append(rowlist.get(3)).append("','").append(rowlist.get(4)).append("','")
+                        .append(rowlist.get(5)).append("','").append(rowlist.get(6)).append("','").append(s0.substring(0, i < 0 ? 0 : i))
+                        .append("')");
+                point.add(substring);
+                //entities.add(entity);
+            }
+        };
+    }
+}

+ 72 - 0
src/main/java/com/gyee/redis2taos/service/ReadAndWriteService.java

@@ -0,0 +1,72 @@
+package com.gyee.redis2taos.service;
+
+import cn.hutool.core.collection.ListUtil;
+import com.gyee.redis2taos.config.RedisConfig;
+import com.gyee.redis2taos.config.TaosConfig;
+import com.gyee.redis2taos.timeseries.BasicTsPoint;
+import com.gyee.redis2taos.timeseries.TsDataType;
+import com.gyee.redis2taos.timeseries.TsPoint;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.core.annotation.Order;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+@Slf4j
+@Order(1)
+@Service
+public class ReadAndWriteService implements ApplicationRunner {
+
+    @Resource
+    private RedisService redisService;
+    @Resource
+    private ThreadPoolTaskExecutor taskExecutor;
+    @Resource
+    private RedisConfig redisConfig;
+    @Resource
+    private TaosConfig taosConfig;
+
+    @Override
+    public void run(ApplicationArguments args) throws Exception {
+
+        //long l1 = System.currentTimeMillis();
+        Set<String> keys = redisService.getKeys();
+        //long l2 = System.currentTimeMillis();
+        log.info("读取rediskeys成功!!!," + keys.size() + "个点。");
+        //按类型分点
+        Map<TsDataType, List<BasicTsPoint>> di = keys.stream().map(ss -> {
+            if (ss.contains("DI")) {
+                return new BasicTsPoint(ss, TsDataType.BOOLEAN);
+            } else {
+                return new BasicTsPoint(ss, TsDataType.DOUBLE);
+            }
+        }).collect(Collectors.groupingBy(TsPoint::getTsDataType));
+        //di点
+        List<String> boolCollect = di.get(TsDataType.BOOLEAN).stream().map(k1 -> k1.getId()).collect(Collectors.toList());
+        //ai点
+        List<String> douCollect = di.get(TsDataType.DOUBLE).stream().map(k1 -> k1.getId()).collect(Collectors.toList());
+
+        //按数量分组,di点,分为9216个1组,redis单机可以控制在1s内
+        List<List<String>> boolStrll = ListUtil.split(boolCollect, 9216);
+        //按数量分组,ai点
+        List<List<String>> douStrll = ListUtil.split(douCollect, 9216);
+
+        while (true) {
+            for (List<String> strings : boolStrll) {
+                taskExecutor.execute(new TaskRedis2Taos(strings, redisConfig, taosConfig, TsDataType.BOOLEAN, taskExecutor));
+            }
+            for (List<String> strings : douStrll) {
+                taskExecutor.execute(new TaskRedis2Taos(strings, redisConfig, taosConfig, TsDataType.DOUBLE, taskExecutor));
+            }
+            Thread.sleep(1000);
+            log.info("\n#");
+        }
+    }
+}

+ 48 - 0
src/main/java/com/gyee/redis2taos/service/RedisService.java

@@ -0,0 +1,48 @@
+package com.gyee.redis2taos.service;
+
+import com.gyee.redis2taos.config.RedisConfig;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import redis.clients.jedis.Jedis;
+
+import javax.annotation.Resource;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+@Slf4j
+@Service
+public class RedisService {
+
+    @Resource
+    private FileService fileService;
+    @Resource
+    private RedisConfig redisConfig;
+
+    private static final ThreadLocal<SimpleDateFormat> sdf = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
+
+    public void creatTables() {
+        List<String> excelRedis = fileService.getExcelRedis();
+        Map<String, String> map = null;
+        Date date = new Date();
+        try (Jedis jedis = redisConfig.getJedis();) {
+            for (String excelRedi : excelRedis) {
+                if (!jedis.exists(excelRedi)) {
+                    map = new LinkedHashMap<>();
+                    map.put("pointid", excelRedi);
+                    map.put("value", "0");
+                    map.put("timestamp", String.valueOf(date.getTime()));
+                    map.put("datetime", sdf.get().format(date));
+                    map.put("status", "0");
+                    jedis.hmset(excelRedi, map);
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        System.out.println("redis建表完成!");
+    }
+
+    public Set<String> getKeys() {
+        return redisConfig.getJedis().keys("*");
+    }
+}

+ 116 - 0
src/main/java/com/gyee/redis2taos/service/TaosService.java

@@ -0,0 +1,116 @@
+package com.gyee.redis2taos.service;
+
+import com.gyee.redis2taos.config.TaosConfig;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+
+@Slf4j
+@Service
+public class TaosService {
+
+    @Resource
+    private TaosConfig taosConfig;
+    @Resource
+    private FileService fileService;
+
+    public boolean createDataBase(int keepday) throws Exception {
+        log.info("创建taos库!");
+        Statement st = taosConfig.getCreateCon().createStatement();
+        String createSTableSql = "create database if not exists " + taosConfig.getDbName() + " cachemodel 'last_row' wal_retention_period 1800 keep " + keepday;
+        int i = st.executeUpdate(createSTableSql);
+        //taosConfig.closeCon();
+        if (i > 0) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+
+    public boolean createStables() throws Exception {
+        log.info("创建taos超级表!");
+        Statement st = taosConfig.getInstance().createStatement();
+        String sqlai = "create stable if not exists " + taosConfig.getDbName() + "." + taosConfig.getAIStableName() + " (ts timestamp,val double) " +
+                "tags (description nchar(100),station binary(20),category binary(20),facility binary(20),uniformcode binary(20),rate float,remark binary(30));";
+        int a = st.executeUpdate(sqlai);
+        String sqladi = "create stable if not exists " + taosConfig.getDbName() + "." + taosConfig.getDIStableName() + " (ts timestamp,val bool) " +
+                "tags (description nchar(100),station binary(20),category binary(20),facility binary(20),uniformcode binary(20),rate float,remark binary(30));";
+        int d = st.executeUpdate(sqladi);
+        if ((a + d) > 0) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public List<String> showDataBase() throws Exception {
+        Statement st = taosConfig.getInstance().createStatement();
+        String showSTableSql = "SHOW DATABASES;";
+        ResultSet resultSet = st.executeQuery(showSTableSql);
+        List<String> ss = new ArrayList<>();
+        int i = 0;
+        while (resultSet.next()) {
+            ss.add(resultSet.getString(i));
+            i++;
+        }
+        return ss;
+    }
+
+    public int createTables() throws Exception {
+        log.info("创建taos表!");
+        Statement st = taosConfig.getInstance().createStatement();
+        List<StringBuilder> excelTaos = fileService.getExcelTaos();
+        int i = 0;
+        for (StringBuilder excelTao : excelTaos) {
+            int i1 = st.executeUpdate(excelTao.toString() + ";");
+            i += i1;
+        }
+        log.info("taos表创建完成!");
+        return i;
+    }
+
+    public List<String> deleteTables() throws Exception {
+        Statement st = taosConfig.getInstance().createStatement();
+        String showSTableSql = "SHOW DATABASES;";
+        ResultSet resultSet = st.executeQuery(showSTableSql);
+        List<String> ss = new ArrayList<>();
+        int i = 0;
+        while (resultSet.next()) {
+            ss.add(resultSet.getString(i));
+            i++;
+        }
+        return ss;
+    }
+
+    public boolean updateTables(int keepday) throws Exception {
+        log.info("创建taos库!");
+        Statement st = taosConfig.getInstance().createStatement();
+        String createSTableSql = "create database if not exists " + taosConfig.getDbName() + " replica 1 quorum 1 days 1 keep " + keepday + " cache 16 blocks 6" +
+                " minrows 100 maxrows 4096 wal 1 fsync 3000 comp 2 cachelast 0 precision 'ms' update 1";
+        int i = st.executeUpdate(createSTableSql);
+        if (i > 0) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public List<String> selectTables() throws Exception {
+        Statement st = taosConfig.getInstance().createStatement();
+        String showSTableSql = "SHOW DATABASES;";
+        ResultSet resultSet = st.executeQuery(showSTableSql);
+        List<String> ss = new ArrayList<>();
+        int i = 0;
+        while (resultSet.next()) {
+            ss.add(resultSet.getString(i));
+            i++;
+        }
+        return ss;
+    }
+}

+ 50 - 0
src/main/java/com/gyee/redis2taos/service/TaskInsert2Taos.java

@@ -0,0 +1,50 @@
+package com.gyee.redis2taos.service;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+public class TaskInsert2Taos implements Runnable {
+
+    private Connection conn;
+    private String sql;
+    private String replace;
+    public static final Logger log = LoggerFactory.getLogger(TaskInsert2Taos.class);
+
+    public TaskInsert2Taos(Connection conn, String sql, String replace) {
+        this.conn = conn;
+        this.sql = sql;
+        this.replace = replace;
+    }
+
+    @Override
+    public void run() {
+        try {
+            conn.createStatement().executeUpdate(sql);
+        } catch (SQLException e) {
+            e.printStackTrace();
+            /*replace = " TAGS('','','','','',1,'');~CREATE TABLE IF NOT EXISTS ";
+            sql = sql.replaceFirst("INSERT INTO ", "CREATE TABLE IF NOT EXISTS ");
+            sql = sql.replaceAll("VALUES.+?\\) ", replace);
+            sql = sql.replace(",CREATE TABLE IF NOT EXISTS ;", "");*/
+            sql = sql.replaceAll("\\) ", ");~INSERT INTO ");
+            sql = sql.replaceAll("VALUES", replace);
+            sql = sql.replaceAll("~INSERT INTO ;", "");
+            String ss = null;
+            try {
+                Statement st = conn.createStatement();
+                String[] split = sql.split("~");
+                for (String s : split) {
+                    ss = s;
+                    st.executeUpdate(s);
+                }
+            } catch (Exception ex) {
+                ex.printStackTrace();
+                log.error(ss);
+            }
+        }
+    }
+}

+ 126 - 0
src/main/java/com/gyee/redis2taos/service/TaskRedis2Taos.java

@@ -0,0 +1,126 @@
+package com.gyee.redis2taos.service;
+
+import com.gyee.redis2taos.config.RedisConfig;
+import com.gyee.redis2taos.config.TaosConfig;
+import com.gyee.redis2taos.timeseries.TsDataType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.util.StringUtils;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.Pipeline;
+
+import java.sql.Connection;
+import java.util.List;
+
+public class TaskRedis2Taos implements Runnable {
+    private final List<String> keys;
+    private RedisConfig redisConfig;
+    private TaosConfig taosConfig;
+    private TsDataType dataType;
+    private ThreadPoolTaskExecutor taskExecutor;
+
+    public static final Logger log = LoggerFactory.getLogger(TaskRedis2Taos.class);
+
+    TaskRedis2Taos(List<String> keys, RedisConfig redisConfig, TaosConfig taosConfig, TsDataType dataType, ThreadPoolTaskExecutor taskExecutor) {
+        this.keys = keys;
+        this.redisConfig = redisConfig;
+        this.taosConfig = taosConfig;
+        this.dataType = dataType;
+        this.taskExecutor = taskExecutor;
+    }
+
+    @Override
+    public void run() {
+
+        List<Object> objects;
+
+        String pointid = null;
+
+        try (Jedis jedis = redisConfig.getJedis(); Pipeline pipelined = jedis.pipelined();) {
+            //TSDBPreparedStatement pstmt = conn.prepareStatement(sql).unwrap(TSDBPreparedStatement.class);
+
+            Connection conn = taosConfig.getInstance();
+
+            for (String key : keys) {
+                //pipelined.hscan(key, "0");
+                pipelined.hmget(key, "pointid", "value", "timestamp");
+            }
+            //redis批量获取接收为Object
+            objects = pipelined.syncAndReturnAll();
+
+            conn.createStatement().executeUpdate("use " + taosConfig.getDbName() + ";");
+
+            StringBuilder sb = new StringBuilder();
+            sb.append("INSERT INTO ");
+
+            String value;
+            String datetime;
+            double val;
+            long ts;
+            boolean bl;
+            List<String> response;
+
+            if (dataType == TsDataType.BOOLEAN) {
+                for (int i = 0; i < objects.size(); ) {
+                    response = (List<String>) objects.get(i);
+
+                    value = response.get(1);
+                    if (value == null || "".equals(value) || "-nan".equals(value)) continue;
+                    datetime = response.get(2);
+                    if (StringUtils.isEmpty(datetime)) continue;
+                    pointid = response.get(0);
+                    if (StringUtils.isEmpty(pointid)) continue;
+
+                    ts = Long.valueOf(datetime) * 1000;
+                    bl = "0".equals(value) ? false : true;
+
+                    sb.append(pointid).append(" VALUES (").append(ts).append(",").append(bl).append(") ");
+
+                    i++;
+                    //分为1000个1组,taos单机可以控制在1s内
+                    if (i % 1000 == 0 || i == objects.size()) {
+                        sb.append(";");
+
+                        taskExecutor.execute(new TaskInsert2Taos(conn, sb.toString(), "USING " +
+                                taosConfig.getDIStableName() + " TAGS('','','','','',1,'') VALUES"));
+
+                        sb = new StringBuilder();
+                        sb.append("INSERT INTO ");
+                    }
+                }
+            } else {
+                for (int i = 0; i < objects.size(); ) {
+                    response = (List<String>) objects.get(i);
+
+                    value = response.get(1);
+                    if (value == null || "".equals(value) || "-nan".equals(value)) continue;
+                    datetime = response.get(2);
+                    if (StringUtils.isEmpty(datetime)) continue;
+                    pointid = response.get(0);
+                    if (StringUtils.isEmpty(pointid)) continue;
+
+                    ts = Long.valueOf(datetime) * 1000;
+                    val = Double.valueOf(value);
+
+                    sb.append(pointid).append(" VALUES (").append(ts).append(",").append(val).append(") ");
+
+                    i++;
+                    if (i % 1000 == 0 || i == objects.size()) {
+                        sb.append(";");
+
+                        taskExecutor.execute(new TaskInsert2Taos(conn, sb.toString(), "USING " +
+                                taosConfig.getAIStableName() + " TAGS('','','','','',1,'') VALUES"));
+
+                        sb = new StringBuilder();
+                        sb.append("INSERT INTO ");
+                    }
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            log.error(pointid + "------读取redis出错!");
+        }
+        System.out.print("*");
+    }
+}

+ 47 - 0
src/main/java/com/gyee/redis2taos/timeseries/BaseTsQuery.java

@@ -0,0 +1,47 @@
+package com.gyee.redis2taos.timeseries;
+
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class BaseTsQuery implements TsQuery {
+
+    private final TsPoint tsPoint;
+    private final long startTs;
+    private final long endTs;
+    private final int interval;
+    private final int limit;
+    private final Interpolation interpolation;
+
+
+    public BaseTsQuery(TsPoint tsPoint, long startTs, long endTs, int interval, int limit, Interpolation interpolation) {
+        this.tsPoint = tsPoint;
+        this.startTs = startTs;
+        this.endTs = endTs;
+        this.interval = interval;
+        this.limit = limit;
+        this.interpolation = interpolation;
+    }
+
+    public BaseTsQuery(TsPoint tsPoint, long startTs, long endTs) {
+        this(tsPoint, startTs, endTs, 1, 1, Interpolation.RAW);
+    }
+
+    @Override
+    public Date[] getDateArray() {
+        if (interpolation == Interpolation.SNAP && startTs > 0 && endTs > 0 && interval > 0 && endTs > startTs) {
+            int count = Math.round((endTs - startTs) / interval / 1000);
+            int length = count;// <= limit ? count : limit;
+            Date[] result = new Date[length];
+            for (int i = 0; i < length; i++) {
+                long ts = startTs + (long) i * interval * 1000;
+                result[i] = new Date(ts);
+            }
+
+            return result;
+        }
+        return null;
+    }
+
+}

+ 40 - 0
src/main/java/com/gyee/redis2taos/timeseries/BasicTsData.java

@@ -0,0 +1,40 @@
+package com.gyee.redis2taos.timeseries;
+
+/**
+ * @author songwb<songwb @ aliyun.com>
+ */
+public abstract class BasicTsData implements TsData, Comparable<BasicTsData> {
+
+    private final long ts;
+
+    private final short status;
+
+    public BasicTsData(long ts, short status) {
+        this.ts = ts;
+        this.status = status;
+    }
+
+    @Override
+    public long getTs() {
+        return ts;
+    }
+
+    @Override
+    public short getStatus() {
+        return status;
+    }
+
+    @Override
+    public int compareTo(BasicTsData o) {
+        return Long.compare(ts, o.ts);
+    }
+
+    @Override
+    public String toString() {
+        return "BasicTsData{ts='" + ts +
+                "', status='" + this.getStatus() +
+                "'}";
+    }
+
+}
+

+ 68 - 0
src/main/java/com/gyee/redis2taos/timeseries/BasicTsPoint.java

@@ -0,0 +1,68 @@
+package com.gyee.redis2taos.timeseries;
+
+import lombok.Data;
+
+/**
+ * @author songwb<songwb @ aliyun.com>
+ */
+@Data
+public class BasicTsPoint implements TsPoint {
+
+    private final String id;
+
+    private TsDataType tsDataType;
+
+    private String thingId;
+
+    private String thingType;
+
+    private String uniformCode;
+
+    private String tag;
+
+    public BasicTsPoint(String id, TsDataType tsDataType) {
+        this.id = id;
+        this.tsDataType = tsDataType;
+    }
+
+    @Override
+    public String getId() {
+        return id;
+    }
+
+    @Override
+    public TsDataType getTsDataType() {
+        return tsDataType;
+    }
+
+    @Override
+    public String getUniformCode() {
+        return uniformCode;
+    }
+
+
+    @Override
+    public String getThingId() {
+        return thingId;
+    }
+
+    @Override
+    public String getThingType() {
+        return thingType;
+    }
+
+    @Override
+    public String toString() {
+        return "BasicTsPoint{id='" + id +
+                "', dataType='" + this.getTsDataType() +
+                "'}";
+    }
+
+
+    @Override
+    public String getTag() {
+        return tag;
+    }
+
+}
+

+ 24 - 0
src/main/java/com/gyee/redis2taos/timeseries/BlobTsData.java

@@ -0,0 +1,24 @@
+package com.gyee.redis2taos.timeseries;
+
+import java.util.Base64;
+
+/**
+ * @author songwb<songwb @ aliyun.com>
+ */
+public class BlobTsData extends BasicTsData {
+
+    private final byte[] blob;
+
+    public BlobTsData(long ts, short status, byte[] blob) {
+        super(ts, status);
+        this.blob = blob;
+    }
+
+    //public byte[] getBlob() { return  blob ;}
+
+    public String getBlobValue() {
+        return Base64.getEncoder().encodeToString(blob);
+    }
+
+}
+

+ 22 - 0
src/main/java/com/gyee/redis2taos/timeseries/BlobWriteTsData.java

@@ -0,0 +1,22 @@
+package com.gyee.redis2taos.timeseries;
+
+import lombok.Data;
+
+import java.util.Base64;
+
+/**
+ * @descrition:
+ * @author:Wanghs
+ * @date:2018-05-04
+ */
+@Data
+public class BlobWriteTsData {
+    private String tagName;
+    private long ts;
+    private byte[] blob;
+
+    public String getValue() {
+        return Base64.getEncoder().encodeToString(blob);
+    }
+
+}

+ 20 - 0
src/main/java/com/gyee/redis2taos/timeseries/BooleanTsData.java

@@ -0,0 +1,20 @@
+package com.gyee.redis2taos.timeseries;
+
+/**
+ * @author songwb<songwb @ aliyun.com>
+ */
+public class BooleanTsData extends BasicTsData {
+
+    private final boolean actualValue;
+
+    public BooleanTsData(long ts, short status, boolean actualValue) {
+        super(ts, status);
+        this.actualValue = actualValue;
+    }
+
+    public boolean getBooleanValue() {
+        return actualValue;
+    }
+
+}
+

+ 19 - 0
src/main/java/com/gyee/redis2taos/timeseries/BooleanWriteTsData.java

@@ -0,0 +1,19 @@
+package com.gyee.redis2taos.timeseries;
+
+import lombok.Data;
+
+/**
+ * @descrition:
+ * @author:Wanghs
+ * @date:2018-05-04
+ */
+@Data
+public class BooleanWriteTsData {
+    private String tagName;
+    private long ts;
+    private boolean actualValue;
+
+    public boolean getValue() {
+        return this.actualValue;
+    }
+}

+ 18 - 0
src/main/java/com/gyee/redis2taos/timeseries/Coordinate.java

@@ -0,0 +1,18 @@
+package com.gyee.redis2taos.timeseries;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+/**
+ * @author songwb<songwb @ aliyun.com>
+ */
+@Data
+@AllArgsConstructor
+public class Coordinate {
+
+    private double latitude;
+
+    private double longitude;
+
+}
+

+ 26 - 0
src/main/java/com/gyee/redis2taos/timeseries/CoordinateTsData.java

@@ -0,0 +1,26 @@
+package com.gyee.redis2taos.timeseries;
+
+/**
+ * @author songwb<songwb @ aliyun.com>
+ */
+public class CoordinateTsData extends BasicTsData {
+
+    private final Coordinate coordinate;
+
+    public CoordinateTsData(long ts, short status, double latitude, double longitude) {
+        super(ts, status);
+        this.coordinate = new Coordinate(latitude, longitude);
+    }
+
+    public CoordinateTsData(long ts, short status, Coordinate coordinate) {
+        super(ts, status);
+        this.coordinate = coordinate;
+    }
+
+    public Coordinate getCoordinateValue() {
+        return coordinate;
+        //return String.format("{\"longitude\":%f,\"latitude\":\"%f\"}", longitude, latitude);
+    }
+
+}
+

+ 26 - 0
src/main/java/com/gyee/redis2taos/timeseries/CoordinateWriteTsData.java

@@ -0,0 +1,26 @@
+package com.gyee.redis2taos.timeseries;
+
+import lombok.Data;
+
+/**
+ * @descrition:
+ * @author:Wanghs
+ * @date:2018-05-04
+ */
+@Data
+public class CoordinateWriteTsData {
+
+    private String tagName;
+    private long ts;
+    private double latitude;
+    private double longitude;
+
+    public double getLatitude() {
+        return latitude;
+    }
+
+    public double getLongitude() {
+        return longitude;
+    }
+
+}

+ 30 - 0
src/main/java/com/gyee/redis2taos/timeseries/DoubleStatData.java

@@ -0,0 +1,30 @@
+package com.gyee.redis2taos.timeseries;
+
+/**
+ * @author songwb<songwb @ aliyun.com>
+ */
+public class DoubleStatData {
+
+    private DoubleTsData avg;
+    private DoubleTsData max;
+    private DoubleTsData min;
+
+    public DoubleStatData(DoubleTsData avg, DoubleTsData max, DoubleTsData min) {
+        this.avg = avg;
+        this.max = max;
+        this.min = min;
+    }
+
+    public DoubleTsData getAvg() {
+        return avg;
+    }
+
+    public DoubleTsData getMax() {
+        return max;
+    }
+
+    public DoubleTsData getMin() {
+        return min;
+    }
+}
+

+ 33 - 0
src/main/java/com/gyee/redis2taos/timeseries/DoubleTsData.java

@@ -0,0 +1,33 @@
+package com.gyee.redis2taos.timeseries;
+
+/**
+ * @author songwb<songwb @ aliyun.com>
+ */
+public class DoubleTsData extends BasicTsData {
+
+    private final double actualValue;
+
+    public DoubleTsData(long ts, short status, double actualValue) {
+        super(ts, status);
+        this.actualValue = actualValue;
+    }
+
+
+    public double getDoubleValue() {
+        return actualValue;
+    }
+
+    //    public String getValue() {
+    //        return Double.toString(actualValue);
+    //    }
+
+    @Override
+    public String toString() {
+        return "DoubleTsData{ts='" + this.getTs() +
+                "', status='" + this.getStatus() +
+                "', value='" + this.getDoubleValue() +
+                "'}";
+    }
+
+}
+

+ 19 - 0
src/main/java/com/gyee/redis2taos/timeseries/DoubleWriteTsData.java

@@ -0,0 +1,19 @@
+package com.gyee.redis2taos.timeseries;
+
+import lombok.Data;
+
+/**
+ * @descrition:
+ * @author:Wanghs
+ * @date:2018-05-04
+ */
+@Data
+public class DoubleWriteTsData {
+    private String tagName;
+    private long ts;
+    private double actualValue;
+
+    public double getValue() {
+        return this.actualValue;
+    }
+}

+ 28 - 0
src/main/java/com/gyee/redis2taos/timeseries/GeneralTsData.java

@@ -0,0 +1,28 @@
+package com.gyee.redis2taos.timeseries;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Optional;
+
+/**
+ * @author songwb<songwb @ aliyun.com>
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class GeneralTsData implements TsData {
+
+    private long ts;
+    private short status;
+    private Optional<Double> doubleValue;
+    private Optional<Long> longValue;
+    private Optional<Boolean> booleanValue;
+    private Optional<String> stringValue;
+    private Optional<String> blobValue;
+    private Optional<Coordinate> coordinateValue;
+
+
+}
+

+ 20 - 0
src/main/java/com/gyee/redis2taos/timeseries/IntegerTsData.java

@@ -0,0 +1,20 @@
+package com.gyee.redis2taos.timeseries;
+
+/**
+ * @Auther: ruyuan
+ * @Date: 2019-05-04 17:26
+ * @Description:
+ */
+public class IntegerTsData extends BasicTsData {
+
+    private final Integer actualValue;
+
+    public IntegerTsData(long ts, short status, Integer actualValue) {
+        super(ts, status);
+        this.actualValue = actualValue;
+    }
+
+    public Integer getIntegerValue() {
+        return actualValue;
+    }
+}

+ 8 - 0
src/main/java/com/gyee/redis2taos/timeseries/Interpolation.java

@@ -0,0 +1,8 @@
+
+package com.gyee.redis2taos.timeseries;
+
+public enum Interpolation {
+    SNAP,   // 历史快照数据
+    INTERPOLATION, //插值
+    RAW    //原始数据
+}

+ 24 - 0
src/main/java/com/gyee/redis2taos/timeseries/LongTsData.java

@@ -0,0 +1,24 @@
+package com.gyee.redis2taos.timeseries;
+
+/**
+ * @author songwb<songwb @ aliyun.com>
+ */
+public class LongTsData extends BasicTsData {
+
+    private final long actualValue;
+
+    public LongTsData(long ts, short status, long actualValue) {
+        super(ts, status);
+        this.actualValue = actualValue;
+    }
+
+    public long getLongValue() {
+        return actualValue;
+    }
+
+    //    public String getValue() {
+    //        return Long.toString(actualValue);
+    //    }
+
+}
+

+ 20 - 0
src/main/java/com/gyee/redis2taos/timeseries/LongWriteTsData.java

@@ -0,0 +1,20 @@
+package com.gyee.redis2taos.timeseries;
+
+import lombok.Data;
+
+/**
+ * @descrition:
+ * @author:Wanghs
+ * @date:2018-05-04
+ */
+@Data
+public class LongWriteTsData {
+
+    private String tagName;
+    private long ts;
+    private long actualValue;
+
+    public long getValue() {
+        return this.actualValue;
+    }
+}

+ 24 - 0
src/main/java/com/gyee/redis2taos/timeseries/StringTsData.java

@@ -0,0 +1,24 @@
+package com.gyee.redis2taos.timeseries;
+
+/**
+ * @author songwb<songwb @ aliyun.com>
+ */
+public class StringTsData extends BasicTsData {
+
+    private final String actualValue;
+
+    public StringTsData(long ts, short status, String actualValue) {
+        super(ts, status);
+        this.actualValue = actualValue;
+    }
+
+    //    public String getActualValue() {
+    //        return actualValue;
+    //    }
+
+    public String getStringValue() {
+        return actualValue;
+    }
+
+}
+

+ 20 - 0
src/main/java/com/gyee/redis2taos/timeseries/StringWriteTsData.java

@@ -0,0 +1,20 @@
+package com.gyee.redis2taos.timeseries;
+
+import lombok.Data;
+
+/**
+ * @descrition:String类型写入实体类
+ * @author:Wanghs
+ * @date:2018-05-04
+ */
+@Data
+public class StringWriteTsData {
+    private String tagName;
+    private long ts;
+    private String actualValue;
+
+    public String getValue() {
+        return this.actualValue;
+    }
+
+}

+ 15 - 0
src/main/java/com/gyee/redis2taos/timeseries/TsData.java

@@ -0,0 +1,15 @@
+package com.gyee.redis2taos.timeseries;
+
+/**
+ * @author songwb<songwb @ aliyun.com>
+ */
+public interface TsData {
+
+    long getTs();
+
+    short getStatus();
+
+    //double getValue();
+
+}
+

+ 15 - 0
src/main/java/com/gyee/redis2taos/timeseries/TsDataType.java

@@ -0,0 +1,15 @@
+package com.gyee.redis2taos.timeseries;
+
+/**
+ * @author songwb<songwb @ aliyun.com>
+ */
+public enum TsDataType {
+    LONG,
+    DOUBLE,
+    BOOLEAN,
+    STRING,
+    BLOB,
+    COORDINATE
+
+}
+

+ 21 - 0
src/main/java/com/gyee/redis2taos/timeseries/TsPoint.java

@@ -0,0 +1,21 @@
+package com.gyee.redis2taos.timeseries;
+
+/**
+ * @author songwb<songwb @ aliyun.com>
+ */
+public interface TsPoint {
+
+    String getId();
+
+    String getThingId();
+
+    String getThingType();
+
+    String getUniformCode();
+
+    TsDataType getTsDataType();
+
+    //reids库
+    String getTag();
+}
+

+ 54 - 0
src/main/java/com/gyee/redis2taos/timeseries/TsPointData.java

@@ -0,0 +1,54 @@
+package com.gyee.redis2taos.timeseries;
+
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author songwb<songwb @ aliyun.com>
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class TsPointData {
+
+    private String tagName;
+    private GeneralTsData tsData;
+
+    public TsDataType findDataType() {
+        if (tsData.getDoubleValue().isPresent()) {
+            return TsDataType.DOUBLE;
+        } else if (tsData.getBooleanValue().isPresent()) {
+            return TsDataType.BOOLEAN;
+        } else if (tsData.getLongValue().isPresent()) {
+            return TsDataType.LONG;
+        } else if (tsData.getStringValue().isPresent()) {
+            return TsDataType.STRING;
+        } else if (tsData.getBlobValue().isPresent()) {
+            return TsDataType.BLOB;
+        } else if (tsData.getCoordinateValue().isPresent()) {
+            return TsDataType.COORDINATE;
+        }
+
+
+        return TsDataType.DOUBLE;
+    }
+
+    /**
+     * 获取 double 类型值
+     *
+     * @return
+     */
+    public double getValue() {
+        if (tsData.getDoubleValue().isPresent()) {
+            return tsData.getDoubleValue().get();
+        } else if (tsData.getBooleanValue().isPresent()) {
+            return tsData.getBooleanValue().get() ? 1.0 : 0.0;
+        } else if (tsData.getLongValue().isPresent()) {
+            return tsData.getLongValue().get();
+        }
+        return 0.0;
+    }
+}
+

+ 23 - 0
src/main/java/com/gyee/redis2taos/timeseries/TsPointDataList.java

@@ -0,0 +1,23 @@
+package com.gyee.redis2taos.timeseries;
+
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+/**
+ * @author songwb<songwb @ aliyun.com>
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class TsPointDataList {
+
+    private String tagName;
+
+    private List<GeneralTsData> tsDataList;
+
+}
+

+ 21 - 0
src/main/java/com/gyee/redis2taos/timeseries/TsQuery.java

@@ -0,0 +1,21 @@
+package com.gyee.redis2taos.timeseries;
+
+import java.util.Date;
+
+public interface TsQuery {
+
+    TsPoint getTsPoint();
+
+    long getStartTs();
+
+    long getEndTs();
+
+    // 单位秒
+    int getInterval();
+
+    int getLimit();
+
+    Interpolation getInterpolation();
+
+    Date[] getDateArray();
+}

+ 32 - 0
src/main/resources/application.yml

@@ -0,0 +1,32 @@
+server:
+  port: 8085
+
+spring:
+  application:
+    name: redis2taos
+
+#redis:
+#  host: 192.168.126.128
+#  port: 6379
+#  password: zghww693
+
+redis:
+  host: 18.6.30.75
+  port: 6379
+  password: 123456
+
+#适配器链接taos数据库配置信息
+taoscz:
+  server_ip: 192.168.126.128
+  server_port: 6030
+  db_name: nxxny
+  user_name: root
+  password: taosdata
+  pool_size: 10
+  max_pool_size: 100
+  #driver_type: com.taosdata.jdbc.rs.RestfulDriver
+  driver_type: com.taosdata.jdbc.TSDBDriver
+  #taos中ai测点的超级表名
+  ai_stable_name: pointai
+  #taos中di测点的超级表名
+  di_stable_name: pointdi

+ 13 - 0
src/test/java/com/gyee/redis2taos/Redis2taosApplicationTests.java

@@ -0,0 +1,13 @@
+package com.gyee.redis2taos;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class Redis2taosApplicationTests {
+
+    @Test
+    void contextLoads() {
+    }
+
+}