Browse Source

风机报警和升压站报警功能修改优化

shilin 1 year ago
parent
commit
5f8dd489e7
55 changed files with 9947 additions and 0 deletions
  1. 83 0
      alarm-web/src/main/java/com/gyee/alarm/util/ClassUtil.java
  2. 614 0
      alarm-web/src/main/java/com/gyee/alarm/util/DateUtils.java
  3. 274 0
      alarm-web/src/main/java/com/gyee/alarm/util/ExcelExport.java
  4. 107 0
      alarm-web/src/main/java/com/gyee/alarm/util/FileUtils.java
  5. 20 0
      alarm-web/src/main/java/com/gyee/alarm/util/PointUtil.java
  6. 161 0
      alarm-web/src/main/java/com/gyee/alarm/util/SnowflakeGenerator.java
  7. 116 0
      alarm-web/src/main/java/com/gyee/alarm/util/SpringUtils.java
  8. 559 0
      alarm-web/src/main/java/com/gyee/alarm/util/StringUtils.java
  9. 219 0
      alarm-web/src/main/java/com/gyee/alarm/util/math/LineUtil.java
  10. 48 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/ApiGolden.java
  11. 1955 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/EdosUtil.java
  12. 27 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/GoldenConfig.java
  13. 278 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/IEdosUtil.java
  14. 34 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/StringUtil.java
  15. 228 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/math/LineUtil.java
  16. 28 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/BaseTsQuery.java
  17. 38 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/BasicTsData.java
  18. 29 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/BasicTsPoint.java
  19. 24 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/BlobTsData.java
  20. 22 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/BlobWriteTsData.java
  21. 24 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/BooleanTsData.java
  22. 19 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/BooleanWriteTsData.java
  23. 18 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/Coordinate.java
  24. 26 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/CoordinateTsData.java
  25. 21 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/CoordinateWriteTsData.java
  26. 30 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/DoubleStatData.java
  27. 25 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/DoubleTsData.java
  28. 19 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/DoubleWriteTsData.java
  29. 38 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/ErrorRequest.java
  30. 27 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/GeneralTsData.java
  31. 8 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/Interpolation.java
  32. 277 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/JsonObjectHelper.java
  33. 24 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/LongTsData.java
  34. 20 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/LongWriteTsData.java
  35. 24 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/StringTsData.java
  36. 34 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/StringUtil.java
  37. 20 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/StringWriteTsData.java
  38. 15 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/TsData.java
  39. 15 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/TsDataType.java
  40. 12 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/TsPoint.java
  41. 36 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/TsPointData.java
  42. 23 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/TsPointDataList.java
  43. 17 0
      alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/TsQuery.java
  44. 81 0
      alarm-web/src/main/java/com/gyee/alarm/util/statisticcs/ActivePowerStatistics.java
  45. 3316 0
      alarm-web/src/main/java/com/gyee/alarm/util/statisticcs/Initial.java
  46. 133 0
      alarm-web/src/main/java/com/gyee/alarm/util/statisticcs/StatusStatistics.java
  47. 170 0
      alarm-web/src/main/java/com/gyee/alarm/util/statisticcs/TheoryPowerStatistics.java
  48. 119 0
      alarm-web/src/main/java/com/gyee/alarm/util/statisticcs/WindSpeedStatistics.java
  49. 52 0
      alarm-web/src/main/java/com/gyee/alarm/util/taos/DataBaseMonitor.java
  50. 70 0
      alarm-web/src/main/java/com/gyee/alarm/util/taos/FastWriteExample.java
  51. 53 0
      alarm-web/src/main/java/com/gyee/alarm/util/taos/MockDataSource.java
  52. 58 0
      alarm-web/src/main/java/com/gyee/alarm/util/taos/ReadTask.java
  53. 197 0
      alarm-web/src/main/java/com/gyee/alarm/util/taos/SQLWriter.java
  54. 4 0
      alarm-web/src/main/java/com/gyee/alarm/util/taos/StmtWriter.java
  55. 58 0
      alarm-web/src/main/java/com/gyee/alarm/util/taos/WriteTask.java

+ 83 - 0
alarm-web/src/main/java/com/gyee/alarm/util/ClassUtil.java

@@ -0,0 +1,83 @@
+package com.gyee.alarm.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Author:
+ * @Date:
+ * @Description:关于类的操作的工具类
+ */
+public final class ClassUtil {
+
+    private ClassUtil() {
+        throw new Error("工具类不允许实例化!");
+    }
+
+    /**
+     * 获取类属性
+     * @param targetObj 要获取属性的类
+     * @return 含有类属性的集合
+     */
+    public static Field[] getClassAttribute(Object targetObj){
+
+        Class<?> objectClass = targetObj.getClass();
+        return objectClass.getDeclaredFields();
+
+    }
+
+    /**
+     * 获取对象的所有get或set方法
+     * @param targetObj 要获取属性的类
+     * @param methodKeyword get或者set关键字
+     * @return 含有类get或set方法的集合
+     */
+    public static List<Method> getMethod(Object targetObj,String methodKeyword){
+        List<Method> methodList = new ArrayList<>();
+
+        Class<?> objectClass = targetObj.getClass();
+
+        Field[] field = objectClass.getDeclaredFields();
+        for (int i = 0;i<field.length;i++){
+
+            if(!field[i].getName().equals("serialVersionUID"))
+            {
+
+                //获取属性名并组装方法名
+                String fieldName = field[i].getName();
+                String getMethodName = methodKeyword
+                        + fieldName.substring(0, 1).toUpperCase()
+                        + fieldName.substring(1);
+
+                try {
+                    Method method = objectClass.getMethod(getMethodName,new Class[]{});
+                    methodList.add(method);
+                } catch (NoSuchMethodException e) {
+                    e.printStackTrace();
+                }
+
+            }
+        }
+        return methodList;
+    }
+
+    /**
+     * 获取对象的所有get方法
+     * @param targetObj 要获取属性的类
+     * @return 含有类方法的集合
+     */
+    public static List<Method> getMethodGet(Object targetObj){
+        return getMethod(targetObj,"get");
+    }
+
+    /**
+     * 获取对象的所有set方法
+     * @param targetObj 要获取属性的类
+     * @return 含有类方法的集合
+     */
+    public static List<Method> getMethodSet(Object targetObj){
+        return getMethod(targetObj,"set");
+    }
+}

+ 614 - 0
alarm-web/src/main/java/com/gyee/alarm/util/DateUtils.java

@@ -0,0 +1,614 @@
+package com.gyee.alarm.util;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+ * 
+ * 
+ * 项目名称:nxfd 类名称:DateUtils 类描述: 创建人:石林 创建时间:2015-3-30 上午11:42:54 修改人:shilinno1
+ * 修改时间:2015-3-30 上午11:42:54 修改备注:
+ * 
+ * @version
+ * 
+ */
+public class DateUtils {
+
+    private static final String format = "yyyy-MM-dd";
+    private static final String format1 = "yyyy-MM-dd HH:mm:ss";
+    private static final String format2 = "MM/dd/yyyy HH:mm:ss";
+
+
+    private static final String formatnew = "yyyy-MM-dd HH:mm:ss.ms";
+    // 第一次调用get将返回null
+
+    private static ThreadLocal<SimpleDateFormat> threadLocal = new ThreadLocal<SimpleDateFormat>();
+
+    // 获取线程的变量副本,如果不覆盖initialValue,第一次get返回null,故需要初始化一个SimpleDateFormat,并set到threadLocal中
+
+    public static String getFormatNew(Date date) {
+
+        SimpleDateFormat df =new SimpleDateFormat(formatnew);
+
+        String datestr=df.format(date);
+
+        return datestr;
+
+    }
+
+
+    public static SimpleDateFormat getFormat() {
+
+        SimpleDateFormat df = (SimpleDateFormat) threadLocal.get();
+
+        if (df == null) {
+            df = new SimpleDateFormat(format);
+            threadLocal.set(df);
+        }
+
+        return df;
+
+    }
+
+    public static SimpleDateFormat getFormat1() {
+
+        SimpleDateFormat df1 = (SimpleDateFormat) threadLocal.get();
+
+        if (df1 == null) {
+            df1 = new SimpleDateFormat(format1);
+            threadLocal.set(df1);
+        }
+
+        return df1;
+
+    }
+
+    public static SimpleDateFormat getFormat2() {
+
+        SimpleDateFormat df2 = (SimpleDateFormat) threadLocal.get();
+
+        if (df2 == null) {
+            df2 = new SimpleDateFormat(format2);
+            threadLocal.set(df2);
+        }
+
+        return df2;
+
+    }
+
+    private DateUtils() {
+    }
+
+    /**
+     * 获取系统日期(无时分秒毫秒)
+     * 
+     * @return
+     */
+    public static Date today() {
+        return truncate(now());
+    }
+
+    /**
+     * 获取系统时间
+     * 
+     * @return
+     */
+    public static Date now() {
+        return new Date();
+    }
+
+    /**
+     * 根据年月日生成日期对象
+     * 
+     * @param y
+     * @param m
+     * @param d
+     * @return
+     */
+    public static Date cons(int y, int m, int d) {
+        Calendar cal = Calendar.getInstance();
+        cal.set(y, m, d, 0, 0, 0);
+        return cal.getTime();
+    }
+
+    public static String toDate(Date date) {
+        return getFormat1().format(date);
+    }
+
+    public static String toDate2(Date date) {
+        return getFormat2().format(date);
+    }
+
+    public static String toDate1(Date date) {
+        return getFormat().format(date);
+    }
+
+    /**
+     * 根据年月日时分秒生成日期对象
+     * 
+     * @param y
+     * @param m
+     * @param d
+     * @param h
+     * @param mi
+     * @param s
+     * @return
+     */
+    public static Date cons(int y, int m, int d, int h, int mi, int s) {
+        Calendar cal = Calendar.getInstance();
+        cal.set(y, m, d, h, mi, s);
+        return cal.getTime();
+    }
+
+    /**
+     * 将指定时间转化为 Calendar
+     * 
+     * @param date
+     * @return
+     */
+    public static Calendar getCal(Date date) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        return cal;
+    }
+
+    /**
+     * 将时间的时分秒毫秒字段去掉
+     * 
+     * @param date
+     * @return
+     */
+    public static Date truncate(Date date) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        return cal.getTime();
+    }
+
+    /**
+     * 去掉日期中日及下级字段
+     * 
+     * @param date
+     * @return
+     */
+    public static Date truncDay(Date date) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        cal.set(Calendar.DAY_OF_MONTH, 1);
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        return cal.getTime();
+    }
+
+    /**
+     * 去掉日期中的月及下级字段
+     * 
+     * @param date
+     * @return
+     */
+    public static Date truncMonth(Date date) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        cal.set(Calendar.MONTH, 0);
+        cal.set(Calendar.DAY_OF_MONTH, 1);
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        return cal.getTime();
+    }
+
+    /**
+     * 在指定时间上加指定的天数
+     * 
+     * @param date
+     * @param day
+     * @return
+     */
+    public static Date addDays(Date date, int day) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        cal.add(Calendar.DAY_OF_MONTH, day);
+        return cal.getTime();
+    }
+
+    /**
+     * 在指定的时间上加指定的月数
+     * 
+     * @param date
+     * @param month
+     * @return
+     */
+    public static Date addMonths(Date date, int month) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        cal.add(Calendar.MONTH, month);
+        return cal.getTime();
+    }
+
+    /**
+     * 在指定的时间上加指定的月数
+     * 
+     * @param date
+
+     * @return
+     */
+    public static Date addYears(Date date, int year) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        cal.add(Calendar.YEAR, year);
+        return cal.getTime();
+    }
+
+    /**
+     * 在指定时间上加指定的小时
+     * 
+     * @param date
+
+     * @return
+     */
+    public static Date addHours(Date date, int hour) {
+        return new Date(date.getTime() + hour * 3600 * 1000);
+    }
+
+    /**
+     * 在指定时间上加指定的分钟
+     * 
+     * @param date
+     * @return
+     */
+    public static Date addMinutes(Date date, int m) {
+        return new Date(date.getTime() + m * 60 * 1000);
+    }
+
+    /**
+     * 在指定时间上加指定的秒
+     * 
+     * @param date
+     * @return
+     */
+    public static Date addSeconds(Date date, int s) {
+        return new Date(date.getTime() + s * 1000);
+    }
+
+    /**
+     * 计算两个时间之间差的天数(取整后)
+     * 
+     * @param d1
+     * @param d2
+     * @return
+     */
+    public static int daysDiff(Date d1, Date d2) {
+        return (int) Math.floor(Math.abs((d1.getTime() - d2.getTime())) / (60 * 60 * 24 * 1000));
+    }
+    public static int daysDiff1(Date d1, Date d2) {
+        return (int) Math.ceil(Math.abs((d1.getTime() - d2.getTime())) / (60 * 60 * 24 * 1000));
+    }
+    /**
+     * 计算两个时间之间差的小时数(取整后)
+     * 
+     * @param d1
+     * @param d2
+     * @return
+     */
+    public static int hoursDiff(Date d1, Date d2) {
+        return (int) Math.floor(Math.abs((d1.getTime() - d2.getTime())) / (60 * 60 * 1000));
+    }
+
+    public static double hoursDiff1(Date d1, Date d2) {
+        return Math.floor(Math.abs((d1.getTime() - d2.getTime())) / (double) (60 * 60 * 1000));
+    }
+
+    public static double hoursDiff2(Date d1, Date d2) {
+        return Math.abs((d1.getTime() - d2.getTime())) / (double) (60 * 60 * 1000);
+    }
+
+    /**
+     * 计算两个时间之间差的分钟数(取整后)
+     * 
+     * @param d1
+     * @param d2
+     * @return
+     */
+    public static int minutesDiff(Date d1, Date d2) {
+        return (int) Math.floor(Math.abs((d1.getTime() - d2.getTime())) / (60 * 1000));
+    }
+
+    /**
+     * 计算两个时间之间差的分钟数(取整后)
+     * 
+     * @param d1
+     * @param d2
+     * @return
+     */
+    public static double minutesDiff2(Date d1, Date d2) {
+        return Math.floor(Math.abs((d1.getTime() - d2.getTime())) / (60 * 1000));
+    }
+
+    /**
+     * 计算两个时间之间差的毫秒数(取整后)
+     * 
+     * @param d1
+     * @param d2
+     * @return
+     */
+    public static long millisecondDiff(Date d1, Date d2) {
+        return Math.abs(d1.getTime() - d2.getTime());
+    }
+
+    /**
+     * 计算两个时间之间差的秒数(取整后)
+     * 
+     * @param d1
+     * @param d2
+     * @return
+     */
+    public static long secondsDiff(Date d1, Date d2) {
+        return (long) Math.floor(Math.abs((d1.getTime() - d2.getTime())) / (1000));
+    }
+
+    /**
+     * 计算两个时间之间的月差
+     * 
+     * @param d1
+     * @param d2
+     * @return
+     */
+    public static int monthsDiff(Date d1, Date d2) {
+        Calendar cal1 = Calendar.getInstance();
+        Calendar cal2 = Calendar.getInstance();
+        cal1.setTime(d1);
+        cal2.setTime(d2);
+
+        return (int) Math.abs((cal1.get(Calendar.YEAR) - cal2.get(Calendar.YEAR)) * 12 + cal1.get(Calendar.MONTH) - cal2.get(Calendar.MONTH));
+
+    }
+
+    /**
+     * 获得指定时间的月数
+     * 
+     * @param date
+     * @return
+     */
+    public static int getMonth(Date date) {
+        Calendar cd = Calendar.getInstance();
+        cd.setTime(date);
+        return cd.get(Calendar.MONTH);
+    }
+
+    /**
+     * 获得指定时间的年数
+     * 
+     * @param date
+     * @return
+     */
+    public static int getYear(Date date) {
+        Calendar cd = Calendar.getInstance();
+        cd.setTime(date);
+        return cd.get(Calendar.YEAR);
+    }
+
+    /**
+     * 获取指定时间的天数
+     * 
+     * @param date
+     * @return
+     */
+    public static int getDay(Date date) {
+        Calendar cd = Calendar.getInstance();
+        cd.setTime(date);
+        return cd.get(Calendar.DAY_OF_MONTH);
+    }
+
+    public static int getCurrentMonthLastDay() {
+        Calendar a = Calendar.getInstance();
+        a.set(Calendar.DATE, 1);
+        a.roll(Calendar.DATE, -1);
+        int maxDate = a.get(Calendar.DATE);
+        return maxDate;
+    }
+
+    public static int getMonthDays(Date date) {
+        Calendar cal = Calendar.getInstance();
+        cal.set(DateUtils.getYear(date), DateUtils.getMonth(date), DateUtils.getDay(date));
+        int dayst = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
+        return dayst;
+    }
+
+    /**
+     * 获取当前月的第一天
+     * 
+     * @return
+     */
+    public static String getCurrtenFirstDay() {
+
+        Calendar c = Calendar.getInstance();
+        // c.add(Calendar.MONTH, 0);
+        c.set(Calendar.DAY_OF_MONTH, 1);
+        return getFormat().format(c.getTime());
+    }
+
+    /**
+     * 获取当前月的最后一天
+     * 
+     * @return
+     */
+    public static String getCurrtenLastDay() {
+
+        Calendar ca = Calendar.getInstance();
+        ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
+        return getFormat().format(ca.getTime());
+    }
+
+    /**
+     * 获取当前月的第一天
+     * 
+     * @return
+     */
+    public static Date getCurrtenFirstDate() {
+
+        Calendar c = Calendar.getInstance();
+        c.set(Calendar.DAY_OF_MONTH, c.getActualMinimum(Calendar.DAY_OF_MONTH));
+        c.set(Calendar.HOUR_OF_DAY, 0);
+        c.set(Calendar.MINUTE, 0);
+        c.set(Calendar.SECOND, 1);
+        return c.getTime();
+    }
+
+    /**
+     * 获取当前月的最后一天
+     * 
+     * @return
+     */
+    public static Date getCurrtenLastDate() {
+
+        Calendar c = Calendar.getInstance();
+        c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
+        c.set(Calendar.HOUR_OF_DAY, 23);
+        c.set(Calendar.MINUTE, 59);
+        c.set(Calendar.SECOND, 59);
+        return c.getTime();
+    }
+
+    public static Date parseDate(String date) {
+        try {
+            return getFormat().parse(date);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public static Date parseDate1(String date) {
+        try {
+            return getFormat1().parse(date);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public static Date parseDate2(String date) {
+        try {
+            return getFormat2().parse(date);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public static Date parseLongToDate(long time) {
+        return new Date(time);
+    }
+
+    /**
+     * 转换Edna时间格式为标准格式
+     * 
+     * @param pointTime
+     * @return
+     */
+    public static String convertEdnaTime2(String pointTime, Boolean isNoSec) {
+        StringBuffer sb = new StringBuffer();
+        String[] dt = pointTime.split(" ");
+        String[] ymd = dt[0].split("-");
+        String[] hms = dt[1].split(":");
+        sb.append(ymd[0]).append("-");
+        if (ymd[1].length() == 1) {
+            sb.append("0").append(ymd[1]);
+        } else {
+            sb.append(ymd[1]);
+        }
+        if (ymd[2].length() == 1) {
+            sb.append("-").append("0").append(ymd[2]);
+        } else {
+            sb.append("-").append(ymd[2]);
+        }
+        if (hms[0].length() == 1) {
+            sb.append(" ").append("0").append(hms[0]);
+        } else {
+            sb.append(" ").append(hms[0]);
+        }
+        if (hms[1].length() == 1) {
+            sb.append(":").append("0").append(hms[1]);
+        } else {
+            sb.append(":").append(hms[1]);
+        }
+
+        if (isNoSec) {
+            sb.append(":").append("00");
+        } else {
+            if (hms[2].length() == 1) {
+                sb.append(":").append("0").append(hms[2]);
+            } else {
+                sb.append(":").append(hms[2]);
+            }
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * 转换Edna时间格式为标准格式
+     * 
+     * @param pointTime
+     * @return
+     */
+    public static String convertEdnaTime(String pointTime, Boolean isNoSec) {
+        String date = getFormat().format(new Date());
+        StringBuffer sb = new StringBuffer();
+        String[] dt = pointTime.split(" ");
+        String[] ymd = dt[0].split("/");
+        String[] hms = dt[1].split(":");
+        if (ymd[2].length() == 2) {
+            sb.append(date.substring(0, 2)).append(ymd[2]).append("-");
+        }
+        if (ymd[0].length() == 1) {
+            sb.append("0").append(ymd[0]);
+        } else {
+            sb.append(ymd[0]);
+        }
+        if (ymd[1].length() == 1) {
+            sb.append("-").append("0").append(ymd[1]);
+        } else {
+            sb.append("-").append(ymd[1]);
+        }
+        if (hms[0].length() == 1) {
+            sb.append(" ").append("0").append(hms[0]);
+        } else {
+            sb.append(" ").append(hms[0]);
+        }
+        if (hms[1].length() == 1) {
+            sb.append(":").append("0").append(hms[1]);
+        } else {
+            sb.append(":").append(hms[1]);
+        }
+
+        if (isNoSec) {
+            sb.append(":").append("00");
+        } else {
+            if (hms[2].length() == 1) {
+                sb.append(":").append("0").append(hms[2]);
+            } else {
+                sb.append(":").append(hms[2]);
+            }
+        }
+
+        return sb.toString();
+    }
+
+    public static String convertEdnaTime(String pointTime) {
+        return convertEdnaTime2(pointTime, false);
+    }
+
+    public static void main(String[] args) {
+        System.out.println(DateUtils.getMonthDays(DateUtils.today()));
+    }
+
+}

+ 274 - 0
alarm-web/src/main/java/com/gyee/alarm/util/ExcelExport.java

@@ -0,0 +1,274 @@
+package com.gyee.alarm.util;
+
+
+
+
+import org.apache.poi.hssf.usermodel.HSSFCellStyle;
+import org.apache.poi.hssf.usermodel.HSSFFont;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.util.CellRangeAddress;
+
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @Author:
+ * @Date:
+ * @Description:Excel导出工具类,依赖于ClassUtil工具类
+ */
+public final class ExcelExport {
+
+    /**
+     * 将传入的数据导出excel表并下载
+     * @param response 返回的HttpServletResponse
+     * @param importlist 要导出的对象的集合
+     * @param attributeNames 含有每个对象属性在excel表中对应的标题字符串的数组(请按对象中属性排序调整字符串在数组中的位置)
+     * @param heardName 导出文件 标题名称
+     * @param cnt 合并单元格数 (一般标题字符串的数组长度-1)
+     */
+    public static void export(HttpServletResponse response, List<?> importlist, String[] attributeNames,
+                              String heardName, int cnt ) {
+        //获取数据集
+        List<?> datalist = importlist;
+
+        //声明一个工作薄
+        HSSFWorkbook workbook = new HSSFWorkbook();
+        //生成一个表格
+        HSSFSheet sheet = workbook.createSheet();
+        //设置表格默认列宽度为15个字节
+        sheet.setDefaultColumnWidth((short) 18);
+        //用于设置表格字体
+        HSSFCellStyle style = workbook.createCellStyle();
+
+        //获取字段名数组
+        String[] tableAttributeName = attributeNames;
+        //获取对象属性
+        Field[] fields = ClassUtil.getClassAttribute(importlist.get(0));
+        //获取对象get方法
+        List<Method> methodList = ClassUtil.getMethodGet(importlist.get(0));
+
+        //设置标题样式
+        HSSFCellStyle headerStyle = workbook.createCellStyle();
+        HSSFFont headerFont = workbook.createFont();
+        headerFont.setFontHeightInPoints((short) 14);
+        headerFont.setBold(true);
+        headerStyle.setAlignment(HorizontalAlignment.CENTER);
+        headerStyle.setFont(headerFont);
+        CellRangeAddress cra0 = new CellRangeAddress(0, 1, 0, cnt);// 合并单元格
+        sheet.addMergedRegion(cra0);
+        //创建标标题题
+        Row row = sheet.createRow(0);
+        Cell cell1 = row.createCell(0);
+        cell1.setCellValue(heardName);
+        cell1.setCellStyle(headerStyle);
+
+        // 设置字体样式
+        HSSFFont titleFont = workbook.createFont();
+        titleFont.setBold(true);
+        titleFont.setFontHeightInPoints((short) 10);
+
+        style.setFont(titleFont);
+        style.setAlignment(HorizontalAlignment.CENTER);
+        //循环字段名数组,创建标题行
+        row = sheet.createRow(2);
+        for (int j = 0; j< tableAttributeName.length; j++){
+            //创建列
+            Cell cell = row.createCell(j);
+            cell.setCellStyle(style);
+            //设置单元类型为String
+            cell.setCellType(CellType.STRING);
+            cell.setCellValue(transCellType(tableAttributeName[j]));
+        }
+        //创建普通行
+        for (int i = 0;i<datalist.size();i++){
+            //因为第一行已经用于创建标题行,故从第二行开始创建
+            row = sheet.createRow(i+3);
+            //如果是第一行就让其为标题行
+            Object targetObj = datalist.get(i);
+            for (int j = 0;j<fields.length;j++){
+                //创建列
+                Cell cell = row.createCell(j);
+                cell.setCellType(CellType.STRING);
+                //
+                try {
+                    Object value = methodList.get(j).invoke(targetObj, new Object[]{});
+                    cell.setCellValue(transCellType(value));
+                } catch (IllegalAccessException e) {
+                    e.printStackTrace();
+                } catch (InvocationTargetException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        response.setContentType("application/octet-stream");
+        //默认Excel名称
+        response.setHeader("Content-Disposition", "attachment;fileName="+"test.xls");
+        try {
+            OutputStream outputStream = response.getOutputStream();
+            workbook.write(outputStream);
+            outputStream.flush();
+            outputStream.close();
+
+//            response.flushBuffer();
+//            workbook.write(response.getOutputStream());
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+    }
+
+
+
+    /**
+     * 将传入的数据导出excel表并下载
+     * @param importlist 要导出的对象的集合
+     * @param attributeNames 含有每个对象属性在excel表中对应的标题字符串的数组(请按对象中属性排序调整字符串在数组中的位置)
+     * @param heardName 导出文件 标题名称
+     * @param cnt 合并单元格数 (一般标题字符串的数组长度-1)
+     * @param filename 文件名称
+     */
+    public static void exportToPath( List<?> importlist, String[] attributeNames,
+                                     String heardName, int cnt,String filename ) throws IOException {
+        //获取数据集
+        List<?> datalist = importlist;
+
+        //声明一个工作薄
+        HSSFWorkbook workbook = new HSSFWorkbook();
+        //生成一个表格
+        HSSFSheet sheet = workbook.createSheet();
+        //设置表格默认列宽度为15个字节
+        sheet.setDefaultColumnWidth((short) 18*2);
+        //用于设置表格字体
+        HSSFCellStyle style = workbook.createCellStyle();
+
+        //获取字段名数组
+        String[] tableAttributeName = attributeNames;
+        //获取对象属性
+        Field[] fields = ClassUtil.getClassAttribute(importlist.get(0));
+        //获取对象get方法
+        List<Method> methodList = ClassUtil.getMethodGet(importlist.get(0));
+
+        //设置标题样式
+        HSSFCellStyle headerStyle = workbook.createCellStyle();
+        HSSFFont headerFont = workbook.createFont();
+        headerFont.setFontHeightInPoints((short) 14);
+        headerFont.setBold(true);
+        headerStyle.setAlignment(HorizontalAlignment.CENTER);
+        headerStyle.setFont(headerFont);
+//        CellRangeAddress cra0 = new CellRangeAddress(0, 1, 0, cnt);// 合并单元格
+//        sheet.addMergedRegion(cra0);
+//        //创建标标题题
+//        Row row = sheet.createRow(0);
+//        Cell cell1 = row.createCell(0);
+//        cell1.setCellValue(heardName);
+//        cell1.setCellStyle(headerStyle);
+
+        // 设置字体样式
+        HSSFFont titleFont = workbook.createFont();
+        titleFont.setBold(true);
+        titleFont.setFontHeightInPoints((short) 10);
+
+        style.setFont(titleFont);
+        style.setAlignment(HorizontalAlignment.CENTER);
+        //循环字段名数组,创建标题行
+        Row row = sheet.createRow(0);
+        for (int j = 0; j< tableAttributeName.length; j++){
+            //创建列
+            Cell cell = row.createCell(j);
+            cell.setCellStyle(style);
+            //设置单元类型为String
+            cell.setCellType(CellType.STRING);
+            cell.setCellValue(transCellType(tableAttributeName[j]));
+        }
+
+        int index = 0;
+        //创建普通行
+        for (int i = 0;i<datalist.size();i++){
+            //因为第一行已经用于创建标题行,故从第二行开始创建
+
+
+            if ((i + 1) % 65535 == 0) {
+                sheet = workbook.createSheet("sheet" + (index+1));
+                row = sheet.createRow(0);
+                for (int j = 0; j< tableAttributeName.length; j++){
+                    //创建列
+                    Cell cell = row.createCell(j);
+                    cell.setCellStyle(style);
+                    //设置单元类型为String
+                    cell.setCellType(CellType.STRING);
+                    cell.setCellValue(transCellType(tableAttributeName[j]));
+                }
+                index++;
+            }
+            row = sheet.createRow((i + 1) - (index * 65535));
+
+            //如果是第一行就让其为标题行
+            Object targetObj = datalist.get(i);
+            for (int j = 0;j<attributeNames.length;j++){
+
+                //创建列
+                Cell cell = row.createCell(j);
+                cell.setCellType(CellType.STRING);
+                //
+                try {
+                    Object value = methodList.get(j).invoke(targetObj, new Object[]{});
+                    cell.setCellValue(transCellType(value));
+                } catch (IllegalAccessException e) {
+                    e.printStackTrace();
+                } catch (InvocationTargetException e) {
+                    e.printStackTrace();
+                }
+
+            }
+        }
+
+        if(StringUtils.notEmp(filename))
+        {
+            //  StringBuilder sb=new StringBuilder("/usr/local/gyee/monitor/");
+            StringBuilder sb=new StringBuilder("d:\\");
+            sb.append(filename);
+            sb.append(".xls");
+
+            FileUtils.deleteFile(String.valueOf(sb));
+
+            FileOutputStream fileOutputStream = new FileOutputStream(String.valueOf(sb));
+
+            workbook.write(fileOutputStream);
+            fileOutputStream.close();
+
+        }
+
+    }
+    private static String transCellType(Object value){
+        String str = null;
+        if (value instanceof Date){
+            Date date = (Date) value;
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            str = sdf.format(date);
+        }else{
+            str = String.valueOf(value);
+            if (str == "null"){
+                str = "";
+            }
+        }
+
+        return str;
+    }
+
+
+}
+

+ 107 - 0
alarm-web/src/main/java/com/gyee/alarm/util/FileUtils.java

@@ -0,0 +1,107 @@
+package com.gyee.alarm.util;
+
+import org.springframework.beans.factory.annotation.Value;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+
+/**
+ * 文件处理工具类
+ *
+ * @author gyee
+ * @date: 2018年9月22日 下午10:33:31
+ */
+public class FileUtils {
+
+    // 设置目标文件的映射路径
+    @Value("classpath:static/syz")
+    private Resource syz;
+
+    private FileUtils() {
+    }
+
+    /**
+     * 输出指定文件的byte数组
+     *
+     * @return
+     */
+    public static void writeBytes(String filePath, OutputStream os) throws IOException {
+        FileInputStream fis = null;
+        try {
+            File file = new File(filePath);
+            if (!file.exists()) {
+                throw new FileNotFoundException(filePath);
+            }
+            fis = new FileInputStream(file);
+            byte[] b = new byte[1024];
+            int length;
+            while ((length = fis.read(b)) > 0) {
+                os.write(b, 0, length);
+            }
+        } catch (IOException e) {
+            throw e;
+        } finally {
+            if (os != null) {
+                try {
+                    os.close();
+                } catch (IOException e1) {
+                    e1.printStackTrace();
+                }
+            }
+            if (fis != null) {
+                try {
+                    fis.close();
+                } catch (IOException e1) {
+                    e1.printStackTrace();
+                }
+            }
+        }
+    }
+
+    /**
+     * 删除文件
+     *
+     * @param filePath 文件
+     * @return
+     */
+    public static boolean deleteFile(String filePath) {
+        boolean flag = false;
+        File file = new File(filePath);
+        // 路径为文件且不为空则进行删除
+        if (file.isFile() && file.exists()) {
+            file.delete();
+            flag = true;
+        }
+        return flag;
+    }
+
+    /**
+     * 读取图片地址 输出到页面
+     *
+     * @param request
+     * @param response
+     * @param fileurl
+     * @throws IOException
+     */
+    public static void readIMGTohtml(HttpServletRequest request, HttpServletResponse response, String fileurl) throws IOException {
+        //设置发送到客户端的响应内容类型
+        response.setContentType("image/*");
+        //读取本地图片输入流
+        try (FileInputStream inputStream = new FileInputStream(fileurl); OutputStream out = response.getOutputStream()) {
+            int i = inputStream.available();
+            //byte数组用于存放图片字节数据
+            byte[] buff = new byte[i];
+            inputStream.read(buff);
+            out.write(buff);
+        }
+    }
+
+
+
+
+
+
+
+}

+ 20 - 0
alarm-web/src/main/java/com/gyee/alarm/util/PointUtil.java

@@ -0,0 +1,20 @@
+package com.gyee.alarm.util;/*
+@author   谢生杰
+@date   2022/11/4-20:09
+*/
+
+import com.gyee.common.model.PointData;
+
+import java.util.Date;
+
+public class PointUtil {
+    public static PointData createPointData(Date date, double value, String code, String name) {
+        PointData y = new PointData();
+        y.setPointTime(date.getTime());
+        y.setPointValue(String.valueOf(value));
+        y.setPointValueInDouble(value);
+        y.setEdnaId(code);
+        y.setPointName(name);
+        return y;
+    }
+}

+ 161 - 0
alarm-web/src/main/java/com/gyee/alarm/util/SnowflakeGenerator.java

@@ -0,0 +1,161 @@
+package com.gyee.alarm.util;
+
+/**
+ * Twitter_Snowflake<br>
+ * SnowFlake的结构如下(每部分用-分开):<br>
+ * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 <br>
+ * 1位标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0<br>
+ * 41位时间截(毫秒级),注意,41位时间截不是存储当前时间的时间截,而是存储时间截的差值(当前时间截 - 开始时间截)
+ * 得到的值),这里的的开始时间截,一般是我们的id生成器开始使用的时间,由我们程序来指定的(如下下面程序IdWorker类的startTime属性)。41位的时间截,可以使用69年,年T = (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69<br>
+ * 10位的数据机器位,可以部署在1024个节点,包括5位datacenterId和5位workerId<br>
+ * 12位序列,毫秒内的计数,12位的计数顺序号支持每个节点每毫秒(同一机器,同一时间截)产生4096个ID序号<br>
+ * 加起来刚好64位,为一个Long型。<br>
+ * SnowFlake的优点是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由数据中心ID和机器ID作区分),并且效率较高,经测试,SnowFlake每秒能够产生26万ID左右。
+ */
+public class SnowflakeGenerator {
+
+    // ==============================Fields===========================================
+    /** 开始时间截 (2015-01-01) */
+    private final long twepoch = 1420041600000L;
+
+    /** 机器id所占的位数 */
+    private final long workerIdBits = 5L;
+
+    /** 数据标识id所占的位数 */
+    private final long datacenterIdBits = 5L;
+
+    /** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
+    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
+
+    /** 支持的最大数据标识id,结果是31 */
+    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
+
+    /** 序列在id中占的位数 */
+    private final long sequenceBits = 12L;
+
+    /** 机器ID向左移12位 */
+    private final long workerIdShift = sequenceBits;
+
+    /** 数据标识id向左移17位(12+5) */
+    private final long datacenterIdShift = sequenceBits + workerIdBits;
+
+    /** 时间截向左移22位(5+5+12) */
+    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
+
+    /** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */
+    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
+
+    /** 工作机器ID(0~31) */
+    private long workerId;
+
+    /** 数据中心ID(0~31) */
+    private long datacenterId;
+
+    /** 毫秒内序列(0~4095) */
+    private long sequence = 0L;
+
+    /** 上次生成ID的时间截 */
+    private long lastTimestamp = -1L;
+
+    //==============================Constructors=====================================
+    /**
+     * 构造函数
+     * @param workerId 工作ID (0~31)
+     * @param datacenterId 数据中心ID (0~31)
+     */
+    public SnowflakeGenerator(long workerId, long datacenterId) {
+        if (workerId > maxWorkerId || workerId < 0) {
+            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
+        }
+        if (datacenterId > maxDatacenterId || datacenterId < 0) {
+            throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
+        }
+        this.workerId = workerId;
+        this.datacenterId = datacenterId;
+    }
+
+    // ==============================Methods==========================================
+    /**
+     * 获得下一个ID (该方法是线程安全的)
+     * @return SnowflakeId
+     */
+    public synchronized long nextId() {
+        long timestamp = timeGen();
+
+        //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
+        if (timestamp < lastTimestamp) {
+            throw new RuntimeException(
+                    String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
+        }
+
+        //如果是同一时间生成的,则进行毫秒内序列
+        if (lastTimestamp == timestamp) {
+            sequence = (sequence + 1) & sequenceMask;
+            //毫秒内序列溢出
+            if (sequence == 0) {
+                //阻塞到下一个毫秒,获得新的时间戳
+                timestamp = tilNextMillis(lastTimestamp);
+            }
+        }
+        //时间戳改变,毫秒内序列重置
+        else {
+            sequence = 0L;
+        }
+
+        //上次生成ID的时间截
+        lastTimestamp = timestamp;
+
+        //移位并通过或运算拼到一起组成64位的ID
+        return ((timestamp - twepoch) << timestampLeftShift) //
+                | (datacenterId << datacenterIdShift) //
+                | (workerId << workerIdShift) //
+                | sequence;
+    }
+
+    /**
+     * 阻塞到下一个毫秒,直到获得新的时间戳
+     * @param lastTimestamp 上次生成ID的时间截
+     * @return 当前时间戳
+     */
+    protected long tilNextMillis(long lastTimestamp) {
+        long timestamp = timeGen();
+        while (timestamp <= lastTimestamp) {
+            timestamp = timeGen();
+        }
+        return timestamp;
+    }
+
+    /**
+     * 返回以毫秒为单位的当前时间
+     * @return 当前时间(毫秒)
+     */
+    protected long timeGen() {
+        return System.currentTimeMillis();
+    }
+
+
+    private static SnowflakeGenerator idWorker = null;
+
+    public synchronized static SnowflakeGenerator getIdWorker() {
+
+        if (idWorker == null)
+            idWorker = new SnowflakeGenerator(2, 3);
+
+        return idWorker;
+    }
+
+    public static long generateId() {
+        //if (idWorker == null)
+            //idWorker = new SnowflakeGenerator(0, 0);
+
+        //return idWorker.nextId();
+        SnowflakeGenerator snowflakeGenerator = getIdWorker();
+
+        return snowflakeGenerator.nextId();
+//        for (int i = 0; i < 1000; i++) {
+//            long id = idWorker.nextId();
+//            System.out.println(Long.toBinaryString(id));
+//            System.out.println(id);
+//        }
+    }
+}

+ 116 - 0
alarm-web/src/main/java/com/gyee/alarm/util/SpringUtils.java

@@ -0,0 +1,116 @@
+package com.gyee.alarm.util;
+
+import org.springframework.aop.framework.AopContext;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.stereotype.Component;
+
+/**
+* spring工具类 方便在非spring管理环境中获取bean
+* @ClassName: SpringUtils
+* @author gyee
+* @date 2019-09-11 11:28
+*
+ */
+@Component
+public final class SpringUtils implements BeanFactoryPostProcessor
+{
+    /** Spring应用上下文环境 */
+    private static ConfigurableListableBeanFactory beanFactory;
+
+    @Override
+    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
+    {
+        SpringUtils.beanFactory = beanFactory;
+    }
+
+    /**
+     * 获取对象
+     *
+     * @param name
+     * @return Object 一个以所给名字注册的bean的实例
+     * @throws BeansException
+     *
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getBean(String name) throws BeansException
+    {
+        return (T) beanFactory.getBean(name);
+    }
+
+    /**
+     * 获取类型为requiredType的对象
+     *
+     * @param clz
+     * @return
+     * @throws BeansException
+     *
+     */
+    public static <T> T getBean(Class<T> clz) throws BeansException
+    {
+        T result = (T) beanFactory.getBean(clz);
+        return result;
+    }
+
+    /**
+     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
+     *
+     * @param name
+     * @return boolean
+     */
+    public static boolean containsBean(String name)
+    {
+        return beanFactory.containsBean(name);
+    }
+
+    /**
+     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
+     *
+     * @param name
+     * @return boolean
+     * @throws NoSuchBeanDefinitionException
+     *
+     */
+    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.isSingleton(name);
+    }
+
+    /**
+     * @param name
+     * @return Class 注册对象的类型
+     * @throws NoSuchBeanDefinitionException
+     *
+     */
+    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.getType(name);
+    }
+
+    /**
+     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
+     *
+     * @param name
+     * @return
+     * @throws NoSuchBeanDefinitionException
+     *
+     */
+    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
+    {
+        return beanFactory.getAliases(name);
+    }
+
+    /**
+     * 获取aop代理对象
+     * 
+     * @param invoker
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> T getAopProxy(T invoker)
+    {
+        return (T) AopContext.currentProxy();
+    }
+}

+ 559 - 0
alarm-web/src/main/java/com/gyee/alarm/util/StringUtils.java

@@ -0,0 +1,559 @@
+package com.gyee.alarm.util;
+
+import org.apache.commons.lang.WordUtils;
+import org.apache.commons.lang.text.StrBuilder;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+/**
+ * 字符串工具类
+ * 
+ * @author fc
+ */
+public class StringUtils extends org.apache.commons.lang3.StringUtils
+{
+    /** 空字符串 */
+    private static final String NULLSTR = "";
+
+    /** 下划线 */
+    private static final char SEPARATOR = '_';
+
+    /**
+     * 获取参数不为空值
+     * 
+     * @param value defaultValue 要判断的value
+     * @return value 返回值
+     */
+    public static <T> T nvl(T value, T defaultValue)
+    {
+        return value != null ? value : defaultValue;
+    }
+
+    /**
+     * * 判断一个Collection是否为空, 包含List,Set,Queue
+     * 
+     * @param coll 要判断的Collection
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Collection<?> coll)
+    {
+        return isNull(coll) || coll.isEmpty();
+    }
+
+    /**
+     * * 判断一个Collection是否非空,包含List,Set,Queue
+     * 
+     * @param coll 要判断的Collection
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Collection<?> coll)
+    {
+        return !isEmpty(coll);
+    }
+    public static int roundToInt(double num) {
+
+        return new BigDecimal(num).setScale(0, RoundingMode.HALF_UP).intValue();
+    }
+    /**
+     * * 判断一个对象数组是否为空
+     * 
+     * @param objects 要判断的对象数组
+     ** @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Object[] objects)
+    {
+        return isNull(objects) || (objects.length == 0);
+    }
+
+    /**
+     * * 判断一个对象数组是否非空
+     * 
+     * @param objects 要判断的对象数组
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Object[] objects)
+    {
+        return !isEmpty(objects);
+    }
+
+    /**
+     * * 判断一个Map是否为空
+     * 
+     * @param map 要判断的Map
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(Map<?, ?> map)
+    {
+        return isNull(map) || map.isEmpty();
+    }
+
+    /**
+     * * 判断一个Map是否为空
+     * 
+     * @param map 要判断的Map
+     * @return true:非空 false:空
+     */
+    public static boolean isNotEmpty(Map<?, ?> map)
+    {
+        return !isEmpty(map);
+    }
+
+    /**
+     * * 判断一个字符串是否为空串
+     * 
+     * @param str String
+     * @return true:为空 false:非空
+     */
+    public static boolean isEmpty(String str)
+    {
+        return isNull(str) || NULLSTR.equals(str.trim());
+    }
+
+    /**
+     * * 判断一个字符串是否为非空串
+     * 
+     * @param str String
+     * @return true:非空串 false:空串
+     */
+    public static boolean isNotEmpty(String str)
+    {
+        return !isEmpty(str);
+    }
+
+    /**
+     * * 判断一个对象是否为空
+     * 
+     * @param object Object
+     * @return true:为空 false:非空
+     */
+    public static boolean isNull(Object object)
+    {
+        return object == null;
+    }
+
+    /**
+     * * 判断一个对象是否非空
+     * 
+     * @param object Object
+     * @return true:非空 false:空
+     */
+    public static boolean isNotNull(Object object)
+    {
+        return !isNull(object);
+    }
+
+    /**
+     * * 判断一个对象是否是数组类型(Java基本型别的数组)
+     * 
+     * @param object 对象
+     * @return true:是数组 false:不是数组
+     */
+    public static boolean isArray(Object object)
+    {
+        return isNotNull(object) && object.getClass().isArray();
+    }
+
+    /**
+     * 去空格
+     */
+    public static String trim(String str)
+    {
+        return (str == null ? "" : str.trim());
+    }
+
+    /**
+     * 截取字符串
+     * 
+     * @param str 字符串
+     * @param start 开始
+     * @return 结果
+     */
+    public static String substring(final String str, int start)
+    {
+        if (str == null)
+        {
+            return NULLSTR;
+        }
+
+        if (start < 0)
+        {
+            start = str.length() + start;
+        }
+
+        if (start < 0)
+        {
+            start = 0;
+        }
+        if (start > str.length())
+        {
+            return NULLSTR;
+        }
+
+        return str.substring(start);
+    }
+
+    /**
+     * 截取字符串
+     * 
+     * @param str 字符串
+     * @param start 开始
+     * @param end 结束
+     * @return 结果
+     */
+    public static String substring(final String str, int start, int end)
+    {
+        if (str == null)
+        {
+            return NULLSTR;
+        }
+
+        if (end < 0)
+        {
+            end = str.length() + end;
+        }
+        if (start < 0)
+        {
+            start = str.length() + start;
+        }
+
+        if (end > str.length())
+        {
+            end = str.length();
+        }
+
+        if (start > end)
+        {
+            return NULLSTR;
+        }
+
+        if (start < 0)
+        {
+            start = 0;
+        }
+        if (end < 0)
+        {
+            end = 0;
+        }
+
+        return str.substring(start, end);
+    }
+
+
+    /**
+     * 驼峰首字符小写 NameVc>>nameVc
+     */
+    public static String uncapitalize(String str)
+    {
+        int strLen;
+        if (str == null || (strLen = str.length()) == 0)
+        {
+            return str;
+        }
+        return new StrBuilder(strLen).append(Character.toLowerCase(str.charAt(0))).append(str.substring(1)).toString();
+    }
+
+    /**
+     * 驼峰命名转下划线 nameVc>>name_vc
+     */
+    public static String toUnderScoreCase(String s)
+    {
+        if (s == null)
+        {
+            return null;
+        }
+        StringBuilder sb = new StringBuilder();
+        boolean upperCase = false;
+        for (int i = 0; i < s.length(); i++)
+        {
+            char c = s.charAt(i);
+
+            boolean nextUpperCase = true;
+
+            if (i < (s.length() - 1))
+            {
+                nextUpperCase = Character.isUpperCase(s.charAt(i + 1));
+            }
+
+            if ((i > 0) && Character.isUpperCase(c))
+            {
+                if (!upperCase || !nextUpperCase)
+                {
+                    sb.append(SEPARATOR);
+                }
+                upperCase = true;
+            }
+            else
+            {
+                upperCase = false;
+            }
+
+            sb.append(Character.toLowerCase(c));
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * 是否包含字符串
+     * 
+     * @param str 验证字符串
+     * @param strs 字符串组
+     * @return 包含返回true
+     */
+    public static boolean inStringIgnoreCase(String str, String... strs)
+    {
+        if (str != null && strs != null)
+        {
+            for (String s : strs)
+            {
+                if (str.equalsIgnoreCase(trim(s)))
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+   
+    
+    /**
+     * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld
+     * 
+     * @param name 转换前的下划线大写方式命名的字符串
+     * @return 转换后的驼峰式命名的字符串
+     */
+    public static String convertToCamelCase(String name)
+    {
+        StringBuilder result = new StringBuilder();
+        // 快速检查
+        if (name == null || name.isEmpty())
+        {
+            // 没必要转换
+            return "";
+        }
+        else if (!name.contains("_"))
+        {
+            // 不含下划线,仅将首字母大写
+            return name.substring(0, 1).toUpperCase() + name.substring(1);
+        }
+        // 用下划线将原始字符串分割
+        String[] camels = name.split("_");
+        for (String camel : camels)
+        {
+            // 跳过原始字符串中开头、结尾的下换线或双重下划线
+            if (camel.isEmpty())
+            {
+                continue;
+            }
+            // 首字母大写
+            result.append(camel.substring(0, 1).toUpperCase());
+            result.append(camel.substring(1).toLowerCase());
+        }
+        return result.toString();
+    }
+    /**
+     * 首字母大写
+     *
+     * @param name
+     * @return
+     */
+    public static String firstUpperCase(String name) {
+        name = name.substring(0, 1).toUpperCase() + name.substring(1);
+        return name;
+    }
+    /**
+     * 首字母小写
+     *
+     * @param name
+     * @return
+     */
+    public static String firstLowerCase(String name) {
+        name = name.substring(0, 1).toLowerCase() + name.substring(1);
+        return name;
+
+    }
+    
+    /**
+     * 将下划线转化为大写
+     *
+     * @param name
+     * @param firstCase 首字母是否大写 true:大写 false;小写
+     * @return
+     */
+    public static String upperCase_(String name, boolean firstCase) {
+        if(isEmpty(name)){
+            return "";
+        }
+        String[] s = name.split("_");
+        StringBuffer stringBuffer = new StringBuffer();
+        for (String s1 : s) {
+            stringBuffer.append(s1.substring(0, 1).toUpperCase() + s1.substring(1));
+        }
+        if(!firstCase){
+            return firstLowerCase(stringBuffer.toString());
+        }
+        return stringBuffer.toString();
+    }
+    
+    /**
+     * get方法名字转成 t_b_abc>>tBAbc
+     * @param str
+     * @return
+     * @author gyee
+     * @Date 2020年1月30日 下午11:55:54
+     */
+    public static String toFUNName(String str) {
+    	StringBuffer buffer=new StringBuffer();
+    	String name=str;
+    	if(name.contains("_")) {
+    		// 用下划线将原始字符串分割
+            String[] camels = name.split("_");
+            boolean b=true;
+            
+            for (String str1 : camels) {
+            	if(str1.length()==1&&b) {
+            		b=false;
+            		buffer.append(str1);
+            	}else {
+            		buffer.append(StringUtils.firstUpperCase(str1));
+            	}
+				
+			}
+    	}else {
+    		buffer.append(StringUtils.firstUpperCase(name));
+    	}
+		return buffer.toString();
+    }
+
+    /**
+     * 列名转换成Java属性名
+     */
+    public static String columnToJava(String columnName) {
+        return WordUtils.capitalizeFully(columnName, new char[]{'_'}).replace("_", "" );
+    }
+    
+    
+    /**
+     * 表名转换成Java类名
+     */
+    public static String tableToJava(String tableName, String tablePrefix) {
+        if (StringUtils.isNotBlank(tablePrefix)) {
+            tableName = tableName.replaceFirst(tablePrefix, "" );
+        }
+        return columnToJava(tableName);
+    }
+
+    /**
+     * 是否不为空串
+     *
+     * @param obj
+     * @return
+     */
+    public static boolean notEmp(Object obj) {
+        return !empty(obj);
+    }
+
+    /**
+     * 是否为空串
+     *
+     * @param obj
+     * @return
+     */
+    public static boolean empty(Object obj) {
+        if (obj == null)
+            return true;
+        String str;
+        if (obj instanceof String) {
+            str = (String) obj;
+        } else {
+            str = obj.toString();
+        }
+        return str.length() == 0;
+    }
+
+    public static double round(double num, int digit) {
+
+        return new BigDecimal(num).setScale(digit, RoundingMode.HALF_UP).doubleValue();
+    }
+    /**
+     * 将字符串解析为Date类型
+     *
+     * @param date
+     * @param pattern
+     * @return
+     */
+    public static Date toDate(String date, String pattern) {
+        SimpleDateFormat format = new SimpleDateFormat(pattern);
+        try {
+            return format.parse(date);
+        } catch (ParseException e) {
+            throw new RuntimeException(String.format("Failed to parse the String [%s] to Date.", date), e);
+        }
+    }
+    /**
+     *
+     * @方法名称: getUUID
+     * @描述: 获得UUID
+     * @参数 @return
+     * @返回值 String
+     * @抛出异常
+     */
+    public static String getUUID() {
+        String s = UUID.randomUUID().toString();
+        // 去掉“-”符号
+        return s.substring(0, 8) + s.substring(9, 13) + s.substring(14, 18) + s.substring(19, 23) + s.substring(24);
+    }
+
+    /**
+     * 判断是否为数字字符串
+     * @param str
+     * @return
+     */
+    public static boolean isNumeric(String str){
+        Pattern pattern = Pattern.compile("^(-?\\d+)(\\.\\d+)?$");
+        if(notEmp(str))
+        {
+            Matcher isNum = pattern.matcher(str);
+            if( !isNum.matches() ){
+                return false;
+            }
+
+        }else
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+
+    /**
+     * 正则表达式
+     * @param input     需要匹配的字符串
+     * @param expression 正则表达公式
+     * @return
+     */
+    public static List<String> pattern(String input, String expression){
+        // 创建 Pattern 对象
+        Pattern p = Pattern.compile(expression);
+        Matcher m = p.matcher(input);
+
+        ArrayList list = new ArrayList();
+        while (m.find()) {
+            list.add(m.group(0));
+        }
+        //去除重复值
+        HashSet hs=new HashSet(list);
+        list.clear();
+        list.addAll(hs);
+
+        return list;
+    }
+}

+ 219 - 0
alarm-web/src/main/java/com/gyee/alarm/util/math/LineUtil.java

@@ -0,0 +1,219 @@
+package com.gyee.alarm.util.math;
+
+import com.gyee.alarm.model.vo.PointVo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class LineUtil {
+
+    public static List<PointVo> buildLine(double[] arrX, double[] arrY, int length, int dimension, double scale)
+    {
+
+        List<PointVo> points =new ArrayList<PointVo>();
+
+        if (arrX.length != arrY.length || arrX.length<3)
+        {
+            return points;
+        }
+
+        double minValue=arrY[0];
+        double maxValue=arrY[arrY.length-1];
+
+
+        double min = 0;
+        double max= 0;
+
+        double[] coefficient = MultiLine(arrX, arrY, length, dimension);
+
+        for (double i = arrX[0]; i <= arrX[arrX.length - 1]; i += scale)
+        {
+            PointVo point = new PointVo();
+            point.setX(i);
+
+
+            for (int j = 0; j < coefficient.length; j++)
+            {
+                if(j==0)
+                {
+                    point.setY(coefficient[j] * Math.pow(point.getX(), (double)j));
+                }else
+                {
+                    double temp=coefficient[j] * Math.pow(point.getX(), (double)j);
+                    point.setY(point.getY()+temp);
+                }
+
+            }
+            if (point.getY() < minValue)
+            {
+                point.setY(minValue);
+   
+            }
+            if (point.getY() > maxValue)
+            {
+                point.setY(maxValue);
+            }
+
+            if (point.getY() < min)
+            {
+                min = point.getY();
+            }
+            if (point.getY() > max)
+            {
+                max = point.getY();
+            }
+
+            points.add(point);
+        }
+        Builder(points, min, max);
+        return points;
+    }
+
+    private static void Builder(List<PointVo> points, double min, double max)
+    {
+        boolean b = false;
+        for (int i = 0; i < points.size(); i++)
+        {
+            if (b)
+            {
+                points.get(i).setY(max);
+            }
+            else
+            {
+                if (max == points.get(i).getY())
+                {
+                    b = true;
+                }
+            }
+
+        }
+
+        for (int i = points.size()-1; i > -1; i--)
+        {
+            if (!b)
+            {
+                points.get(i).setY(min);
+            }
+            else
+            {
+                if (min == points.get(i).getY())
+                {
+                    b = false;
+                }
+            }
+
+        }
+    }
+
+
+
+    ///<summary>
+    ///用最小二乘法拟合二元多次曲线
+    ///</summary>
+    ///<param name="arrX">已知点的x坐标集合</param>
+    ///<param name="arrY">已知点的y坐标集合</param>
+    ///<param name="length">已知点的个数</param>
+    ///<param name="dimension">方程的最高次数</param>
+    public static double[] MultiLine(double[] arrX, double[] arrY, int length, int dimension)//二元多次线性方程拟合曲线
+    {
+        int n = dimension + 1;                  //dimension次方程需要求 dimension+1个 系数
+        double[][] Guass = new double[n][n+1];      //高斯矩阵 例如:y=a0+a1*x+a2*x*x
+        for (int i = 0; i < n; i++)
+        {
+            int j;
+            for (j = 0; j < n; j++)
+            {
+                Guass[i][j] = SumArr(arrX, j + i, length);
+            }
+            Guass[i][j]= SumArr(arrX, i, arrY, 1, length);
+        }
+        return ComputGauss(Guass, n);
+    }
+    public static double SumArr(double[] arr, int n, int length) //求数组的元素的n次方的和
+    {
+        double s = 0;
+        for (int i = 0; i < length; i++)
+        {
+            if (arr[i] != 0 || n != 0)
+                s = s + Math.pow(arr[i], n);
+            else
+                s = s + 1;
+        }
+        return s;
+    }
+    public static double SumArr(double[] arr1, int n1, double[] arr2, int n2, int length)
+    {
+        double s = 0;
+        for (int i = 0; i < length; i++)
+        {
+            if ((arr1[i] != 0 || n1 != 0) && (arr2[i] != 0 || n2 != 0))
+                s = s + Math.pow(arr1[i], n1) * Math.pow(arr2[i], n2);
+            else
+                s = s + 1;
+        }
+        return s;
+
+    }
+    public static double[] ComputGauss(double[][] Guass, int n)
+    {
+        int i, j;
+        int k, m;
+        double temp;
+        double max;
+        double s;
+        double[] x = new double[n];
+        for (i = 0; i < n; i++) x[i] = 0.0;//初始化
+
+        for (j = 0; j < n; j++)
+        {
+            max = 0;
+            k = j;
+            for (i = j; i < n; i++)
+            {
+                if (Math.abs(Guass[i][j]) > max)
+                {
+                    max = Guass[i][j];
+                    k = i;
+                }
+            }
+
+
+            if (k != j)
+            {
+                for (m = j; m < n + 1; m++)
+                {
+                    temp = Guass[j][m];
+                    Guass[j][m]= Guass[k][m];
+                    Guass[k][m] = temp;
+                }
+            }
+            if (0 == max)
+            {
+                // "此线性方程为奇异线性方程" 
+                return x;
+            }
+
+            for (i = j + 1; i < n; i++)
+            {
+                s = Guass[i][j];
+                for (m = j; m < n + 1; m++)
+                {
+                    Guass[i][m] = Guass[i][m] - Guass[j][m] * s / (Guass[j][j]);
+                }
+            }
+
+        }//结束for (j=0;j<n;j++)
+
+        for (i = n - 1; i >= 0; i--)
+        {
+            s = 0;
+            for (j = i + 1; j < n; j++)
+            {
+                s = s + Guass[i][j] * x[j];
+            }
+            x[i] = (Guass[i][n]- s) / Guass[i][i];
+        }
+        return x;
+    }//返回值是函数的系数
+}
+

+ 48 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/ApiGolden.java

@@ -0,0 +1,48 @@
+/** 
+ * ProBasicProject Name:nxfd2 
+ * File Name:ApiEdos.java 
+ * Package Name:com.gyee.frame.util
+ * Date:2016-7-25下午12:26:14 
+ * Copyright (c) 2016, chenzhou1025@126.com All Rights Reserved. 
+ * 
+ */
+
+package com.gyee.alarm.util.realtimesource;
+
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * ClassName:ApiEdos <br/>
+ * Function: TODO ADD FUNCTION. <br/>
+ * Reason: TODO ADD REASON. <br/>
+ * Date: 2016-7-25 下午12:26:14 <br/>
+ * 
+ * @author 石林
+ * @version
+ * @since JDK 1.6
+ * @see
+ */
+public class ApiGolden {
+
+    private static RestTemplate restTemplate = null;
+
+  
+    private ApiGolden() {
+
+    }
+
+    public static RestTemplate getInstance() {
+    	
+    	
+
+        if (restTemplate == null) {
+        	
+        	restTemplate = new RestTemplate();
+
+        }
+
+        return restTemplate;
+
+    }
+
+}

File diff suppressed because it is too large
+ 1955 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/EdosUtil.java


+ 27 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/GoldenConfig.java

@@ -0,0 +1,27 @@
+package com.gyee.alarm.util.realtimesource;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 读取项目相关配置
+ * 
+ * @author gyee
+ */
+
+@Configuration
+@ConfigurationProperties(prefix = "golden")
+public class GoldenConfig
+{
+    private static String baseURL;
+
+    public static String getBaseurl() {
+        return baseURL;
+    }
+
+    public  void setBaseurl(String baseURL) {
+        GoldenConfig.baseURL = baseURL;
+    }
+}
+
+

+ 278 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/IEdosUtil.java

@@ -0,0 +1,278 @@
+package com.gyee.alarm.util.realtimesource;
+
+
+import com.gyee.common.model.DNAStatVal;
+import com.gyee.common.model.DNAVal;
+import com.gyee.common.model.PointData;
+import com.gyee.alarm.model.auto.ProBasicEquipmentPoint;
+import com.gyee.alarm.model.auto.ProBasicPowerstationPoint;
+import com.gyee.alarm.model.vo.RealTimeParameterVo;
+
+import java.util.List;
+import java.util.Map;
+
+
+public interface IEdosUtil {
+
+	/**
+	 * 通过风场测点获得测点实时数据
+	 * @param point 只是用了code字段,作为唯一标识
+	 * @return
+	 * @throws Exception
+	 */
+    public PointData getRealData(ProBasicPowerstationPoint point) throws Exception;
+
+
+    /**
+     * 通过风场测点获得测点切面数据
+     * @param point 只是用了code字段,作为唯一标识
+     * @param date 时间
+     * @return
+     * @throws Exception
+     */
+    public PointData getSectionData(String point,Long date) throws Exception;
+
+
+    /**
+     * 通过风场测点获得测点切面数据
+     * @param point 只是用了code字段,作为唯一标识
+     * @param date 时间
+     * @return
+     * @throws Exception
+     */
+    public PointData getSectionData(ProBasicPowerstationPoint point, Long date) throws Exception;
+
+    /**
+     * 通过风机测点获得测点切面数据
+     * @param point 只是用了code字段,作为唯一标识
+     * @param date 时间
+     * @return
+     * @throws Exception
+     */
+    public PointData getSectionData(ProBasicEquipmentPoint point, Long date) throws Exception;
+
+    /**
+     * 通过风场测点获得测点历史快照数据
+     * @param point 只是用了code字段,作为唯一标识
+     * @param beginDate 开始时间(秒级)
+     * @param endDate 结束时间(秒级)
+     * @param count  点数
+     * @param pried  时间间隔
+     * @return
+     * @throws Exception
+     */
+    public List<PointData> getHistoryDatasSnap(ProBasicPowerstationPoint point, Long beginDate, Long endDate, Long count, Long pried) throws Exception;
+
+    /**
+     * 通过风场测点获得测点历史存储数据,存多少取多少
+     * @param point 只是用了code字段,作为唯一标识
+     * @param beginDate 开始时间(秒级)
+     * @param endDate 结束时间(秒级)
+     * @return
+     * @throws Exception
+     */
+    public List<PointData> getHistoryDatasRaw(ProBasicPowerstationPoint point, Long beginDate, Long endDate) throws Exception;
+
+    /**
+     * 通过风机测点获得测点实时数据
+     * @param point 只是用了id字段,作为唯一标识
+     * @return
+     * @throws Exception
+     */
+    public PointData getRealData(ProBasicEquipmentPoint point) throws Exception;
+
+    /**
+     * 通过风机测点获得历史快照
+     * @param point  只是用了id字段,作为唯一标识
+     * @param  beginDate 开始时间(秒级)
+     * @param endDate 结束时间(秒级)
+     * @param count  点数
+     * @param pried  时间间隔
+     * @return
+     * @throws Exception
+     */
+    public List<PointData> getHistoryDatasSnap(ProBasicEquipmentPoint point, Long beginDate, Long endDate, Long count, Long pried) throws Exception;
+
+    /**
+     * 通过风机测点获得测点历史存储数据,存多少取多少
+     * @param point 只是用了id字段,作为唯一标识
+     * @param  beginDate 开始时间(秒级)
+     * @param endDate 结束时间(秒级)
+     * @return
+     * @throws Exception
+     */
+    public List<PointData> getHistoryDatasRaw(ProBasicEquipmentPoint point, Long beginDate, Long endDate) throws Exception;
+
+
+    /**
+     * 通过风机测点获得测点实时数据
+     * @param pointid 测点编号
+     * @return
+     * @throws Exception
+     */
+    public PointData getRealData(String pointid) throws Exception;
+
+    /**
+     * 通过全局点名获得测点实时数据 读取多个点
+     * @param pointids 测点的数组
+     * @return 列表集合
+     * @throws Exception
+     */
+    public List<PointData> getRealData(String... pointids) throws Exception;
+    /**
+     * 通过全局点名获得测点实时数据 读取多个点
+     * @param pointids 测点的列表
+     * @return 列表集合
+     * @throws Exception
+     */
+    public List<PointData> getRealData(List<String> pointids) throws Exception;
+    /**
+     * 通过全局点名获得测点实时数据 读取多个点
+     * @param pointids 测点的数组
+     * @return Map集合
+     * @throws Exception
+     */
+    public Map<String,Double> getRealDataMap(String... pointids) throws Exception;
+
+    /**
+     * 通过全局点名获得历史数据快照
+     * @param pointid  全局点名
+     * @param beginDate 开始时间(秒级)
+     * @param endDate 结束时间(秒级)
+     * @param count  点数
+     * @param pried  时间间隔
+     * @return
+     * @throws Exception
+     */
+    public List<PointData> getHistoryDatasSnap(String pointid, Long beginDate, Long endDate, Long count, Long pried) throws Exception;
+
+    /**
+     * 通过风机测点获得测点历史存储数据,存多少取多少
+     * @param pointid 全局点名
+     * @param  beginDate 开始时间(秒级)
+     * @param endDate 结束时间(秒级)
+     * @return
+     * @throws Exception
+     */
+    public List<PointData> getHistoryDatasRaw(String pointid, Long beginDate, Long endDate) throws Exception;
+
+
+    /**
+     * 通过风机测点获得测点指定时间周期的统计数据
+     * @param point 只是用了id字段,作为唯一标识
+     * @param  beginDate 开始时间(秒级)
+     * @param endDate 结束时间(秒级)
+     * @param count  点数
+     * @param pried  时间间隔
+     * @type 0、最大值。1、最小值。、平均值
+     * @return
+     * @throws Exception
+     */
+    public List<PointData> getHistStat(ProBasicEquipmentPoint point, Long beginDate, Long endDate, Long count, Long pried, int type) throws Exception;
+
+    /**
+     * 通过风场测点获得测点指定时间周期的统计数据
+     * @param point 只是用了code字段,作为唯一标识
+     * @param  beginDate 开始时间(秒级)
+     * @param endDate 结束时间(秒级)
+     * @param count  点数
+     * @param pried  时间间隔
+     * @type 0、最大值。1、最小值。、平均值
+     * @return
+     * @throws Exception
+     */
+    public List<PointData> getHistStat(ProBasicPowerstationPoint point, Long beginDate, Long endDate, Long count, Long pried, int type) throws Exception;
+
+    /**
+     * 通过全局点名获得测点指定时间周期的统计数据
+     * @param pointid 全局点名
+     * @param  beginDate 开始时间(秒级)
+     * @param endDate 结束时间(秒级)
+     * @param count  点数
+     * @param pried  时间间隔
+     * @type 0、最大值。1、最小值。、平均值
+     * @return
+     * @throws Exception
+     */
+    public List<PointData> getHistStat(String pointid, Long beginDate, Long endDate, Long count, Long pried, int type) throws Exception;
+
+    /**
+     * 通过全局点名获得测点指定时间周期的统计数据 同时返回max、min、avg数据
+     * @param point 全局点名
+     * @param  beginDate 开始时间(秒级)
+     * @param endDate 结束时间(秒级)
+     * @param pried  时间间隔
+     * @return
+     * @throws Exception
+     */
+    public DNAStatVal[] getHistStat(String point, Long beginDate, Long endDate, Integer pried) throws Exception;
+    /**
+     * 补录单点历史数据
+     * @param point 测点对象
+     * @return
+     * @throws Exception
+     */
+    public void updatePoint(PointData point) throws Exception;
+
+    /**
+     * 批量查询实时数据
+     * @param tagNames 测点字符串数组
+     * @return
+     * @throws Exception
+     */
+
+    public DNAVal[] getRealtimeTagValues(String... tagNames) throws Exception;
+
+    /**
+     * 批量插入历史数据
+     * @param pointls 测点对象集合
+     * @throws Exception
+     */
+    public void updatePoint(List<PointData> pointls) throws Exception;
+
+    /**
+     * 单点写入实时数据
+     * @param point 测点对象
+     * @throws Exception
+     */
+    public void sendSinglePoint(PointData point) throws Exception ;
+    /**
+     * 批量写入实时数据
+     * @param pointls 测点对象列表
+     * @throws Exception
+     */
+    public void sendMultiPoint(List<PointData> pointls) throws Exception ;
+
+    /**
+     * 通过两个字符串数组对象批量写入实时数据
+     * @param realvalue 插入值字符串数组
+     * @param pointls 存储对象数组对象
+     * @throws Exception
+     */
+
+    public void sendMultiPoint(String[] realvalue,DNAVal[] pointls) throws Exception;
+    /**
+     *
+     * @param nameList 测点名称列表集合
+     * @param tTime  时间点(秒级)
+     * @return
+     * @throws Exception
+     */
+    public DNAVal[] getHistMatrix(String[] nameList, int tTime) throws Exception;
+
+
+    public void sendMultiRealTimeParamete(List<RealTimeParameterVo> pointls) throws Exception;
+
+    public List<PointData> getHistoryDatasSnap(String pointid, Long beginDate, Long endDate) throws Exception;
+
+
+    /**
+     *
+     * @param nameList 测点名称列表集合
+     * @param tTime  时间点(秒级)
+     * @return
+     * @throws Exception
+     */
+    public List<PointData> getHistMatrix(List<String> nameList, long tTime) throws Exception;
+    public PointData getHistMatrix(String id, long tTime) throws Exception;
+}

+ 34 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/StringUtil.java

@@ -0,0 +1,34 @@
+package com.gyee.alarm.util.realtimesource;
+
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * String辅助类
+ * 
+ */
+public class StringUtil extends StringUtils {
+	
+	/**
+	 * 非空判断
+	 * 
+	 * @param obj
+	 * @return
+	 */
+	public static boolean isNotBlank(Object obj) {
+		return !isBlank(obj);
+	}
+
+	/**
+	 * 为空判断
+	 * 
+	 * @param obj
+	 * @return
+	 */
+	public static boolean isBlank(Object obj) {
+		if (obj == null || StringUtils.isBlank(obj.toString())) {
+			return true;
+		}
+		return false;
+	}
+
+}

+ 228 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/math/LineUtil.java

@@ -0,0 +1,228 @@
+package com.gyee.alarm.util.realtimesource.math;
+
+import com.gyee.alarm.model.vo.PointVo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class LineUtil {
+
+    /// <summary>
+    /// 用最小二乘法拟合二元多次曲线
+    /// </summary>
+    /// <param name="arrX">已知点的x坐标集合</param>
+    /// <param name="arrY">已知点的y坐标集合</param>
+    /// <param name="length">已知点的个数</param>
+    /// <param name="dimension">方程的最高次数</param>
+    /// <param name="scale">曲线的刻度</param>
+    /// <returns></returns>
+    public static List<PointVo> buildLine(double[] arrX, double[] arrY, int length, int dimension, double scale)
+    {
+
+        List<PointVo> points =new ArrayList<PointVo>();
+
+        if (arrX.length != arrY.length || arrX.length<3)
+        {
+            return points;
+        }
+
+        double minValue=arrY[0];
+        double maxValue=arrY[arrY.length-1];
+
+
+        double min = 0;
+        double max= 0;
+
+        double[] coefficient = multiLine(arrX, arrY, length, dimension);
+
+        for (double i = arrX[0]; i <= arrX[arrX.length - 1]; i += scale)
+        {
+            PointVo point = new PointVo();
+            point.setX(i);
+
+
+            for (int j = 0; j < coefficient.length; j++)
+            {
+                if(j==0)
+                {
+                    point.setY(coefficient[j] * Math.pow(point.getX(), (double)j));
+                }else
+                {
+                    double temp=coefficient[j] * Math.pow(point.getX(), (double)j);
+                    point.setY(point.getY()+temp);
+                }
+
+            }
+            if (point.getY() < minValue)
+            {
+                point.setY(minValue);
+   
+            }
+            if (point.getY() > maxValue)
+            {
+                point.setY(maxValue);
+            }
+
+            if (point.getY() < min)
+            {
+                min = point.getY();
+            }
+            if (point.getY() > max)
+            {
+                max = point.getY();
+            }
+
+            points.add(point);
+        }
+        builder(points, min, max);
+        return points;
+    }
+
+    private static void builder(List<PointVo> points, double min, double max)
+    {
+        boolean b = false;
+        for (int i = 0; i < points.size(); i++)
+        {
+            if (b)
+            {
+                points.get(i).setY(max);
+            }
+            else
+            {
+                if (max == points.get(i).getY())
+                {
+                    b = true;
+                }
+            }
+
+        }
+
+        for (int i = points.size()-1; i > -1; i--)
+        {
+            if (!b)
+            {
+                points.get(i).setY(min);
+            }
+            else
+            {
+                if (min == points.get(i).getY())
+                {
+                    b = false;
+                }
+            }
+
+        }
+    }
+
+
+
+    ///<summary>
+    ///用最小二乘法拟合二元多次曲线
+    ///</summary>
+    ///<param name="arrX">已知点的x坐标集合</param>
+    ///<param name="arrY">已知点的y坐标集合</param>
+    ///<param name="length">已知点的个数</param>
+    ///<param name="dimension">方程的最高次数</param>
+    public static double[] multiLine(double[] arrX, double[] arrY, int length, int dimension)//二元多次线性方程拟合曲线
+    {
+        int n = dimension + 1;                  //dimension次方程需要求 dimension+1个 系数
+        double[][] guass = new double[n][n+1];      //高斯矩阵 例如:y=a0+a1*x+a2*x*x
+        for (int i = 0; i < n; i++)
+        {
+            int j;
+            for (j = 0; j < n; j++)
+            {
+                guass[i][j] = sumArr(arrX, j + i, length);
+            }
+            guass[i][j]= sumArr(arrX, i, arrY, 1, length);
+        }
+        return computGauss(guass, n);
+    }
+    public static double sumArr(double[] arr, int n, int length) //求数组的元素的n次方的和
+    {
+        double s = 0;
+        for (int i = 0; i < length; i++)
+        {
+            if (arr[i] != 0 || n != 0)
+                s = s + Math.pow(arr[i], n);
+            else
+                s = s + 1;
+        }
+        return s;
+    }
+    public static double sumArr(double[] arr1, int n1, double[] arr2, int n2, int length)
+    {
+        double s = 0;
+        for (int i = 0; i < length; i++)
+        {
+            if ((arr1[i] != 0 || n1 != 0) && (arr2[i] != 0 || n2 != 0))
+                s = s + Math.pow(arr1[i], n1) * Math.pow(arr2[i], n2);
+            else
+                s = s + 1;
+        }
+        return s;
+
+    }
+    public static double[] computGauss(double[][] guass, int n)
+    {
+        int i, j;
+        int k, m;
+        double temp;
+        double max;
+        double s;
+        double[] x = new double[n];
+        for (i = 0; i < n; i++) x[i] = 0.0;//初始化
+
+        for (j = 0; j < n; j++)
+        {
+            max = 0;
+            k = j;
+            for (i = j; i < n; i++)
+            {
+                if (Math.abs(guass[i][j]) > max)
+                {
+                    max = guass[i][j];
+                    k = i;
+                }
+            }
+
+
+            if (k != j)
+            {
+                for (m = j; m < n + 1; m++)
+                {
+                    temp = guass[j][m];
+                    guass[j][m]= guass[k][m];
+                    guass[k][m] = temp;
+                }
+            }
+            if (0 == max)
+            {
+                // "此线性方程为奇异线性方程" 
+                return x;
+            }
+
+            for (i = j + 1; i < n; i++)
+            {
+                s = guass[i][j];
+                for (m = j; m < n + 1; m++)
+                {
+                    guass[i][m] = guass[i][m] - guass[j][m] * s / (guass[j][j]);
+                }
+            }
+
+        }//结束for (j=0;j<n;j++)
+
+        for (i = n - 1; i >= 0; i--)
+        {
+            s = 0;
+            for (j = i + 1; j < n; j++)
+            {
+                s = s + guass[i][j] * x[j];
+            }
+            x[i] = (guass[i][n]- s) / guass[i][i];
+        }
+        return x;
+    }//返回值是函数的系数
+}
+

+ 28 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/BaseTsQuery.java

@@ -0,0 +1,28 @@
+package com.gyee.alarm.util.realtimesource.timeseries;
+
+import lombok.Data;
+
+@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);
+    }
+
+}

+ 38 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/BasicTsData.java

@@ -0,0 +1,38 @@
+package com.gyee.alarm.util.realtimesource.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;
+    }
+
+    public long getTs() {
+        return ts;
+    }
+
+    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() +
+                "'}";
+    }
+
+}
+

+ 29 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/BasicTsPoint.java

@@ -0,0 +1,29 @@
+package com.gyee.alarm.util.realtimesource.timeseries;
+
+/**
+ * @author songwb<songwb@aliyun.com>
+ */
+public class BasicTsPoint implements TsPoint {
+
+    private final String id;
+
+    private final TsDataType tsDataType;
+
+    public BasicTsPoint(String id,  TsDataType tsDataType) {
+        this.id = id;
+        this.tsDataType = tsDataType;
+    }
+
+    public String getId() { return id; }
+
+    public TsDataType getTsDataType() {return tsDataType; }
+
+    @Override
+    public String toString() {
+        return "BasicTsPoint{id='" + id +
+                "', dataType='" + this.getTsDataType() +
+                "'}";
+    }
+
+}
+

+ 24 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/BlobTsData.java

@@ -0,0 +1,24 @@
+package com.gyee.alarm.util.realtimesource.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
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/BlobWriteTsData.java

@@ -0,0 +1,22 @@
+package com.gyee.alarm.util.realtimesource.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);
+    }
+
+}

+ 24 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/BooleanTsData.java

@@ -0,0 +1,24 @@
+package com.gyee.alarm.util.realtimesource.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 getActualValue() {
+//        return actualValue;
+//    }
+
+    public String getBooleanValue() {
+        return Boolean.toString(actualValue);
+    }
+
+}
+

+ 19 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/BooleanWriteTsData.java

@@ -0,0 +1,19 @@
+package com.gyee.alarm.util.realtimesource.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
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/Coordinate.java

@@ -0,0 +1,18 @@
+package com.gyee.alarm.util.realtimesource.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
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/CoordinateTsData.java

@@ -0,0 +1,26 @@
+package com.gyee.alarm.util.realtimesource.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);
+    }
+
+}
+

+ 21 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/CoordinateWriteTsData.java

@@ -0,0 +1,21 @@
+package com.gyee.alarm.util.realtimesource.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
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/DoubleStatData.java

@@ -0,0 +1,30 @@
+package com.gyee.alarm.util.realtimesource.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;
+    }
+}
+

+ 25 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/DoubleTsData.java

@@ -0,0 +1,25 @@
+package com.gyee.alarm.util.realtimesource.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);
+//    }
+
+}
+

+ 19 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/DoubleWriteTsData.java

@@ -0,0 +1,19 @@
+package com.gyee.alarm.util.realtimesource.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;
+    }
+}

+ 38 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/ErrorRequest.java

@@ -0,0 +1,38 @@
+package com.gyee.alarm.util.realtimesource.timeseries;
+
+import com.gyee.common.model.PointData;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @descrition:接口请求失败返回操作类
+ * @author:Wanghs
+ * @date:2018-05-21
+ */
+public class ErrorRequest {
+
+    public static List<PointData> RequestListError(String pointId) {
+        List<PointData> dataList = new ArrayList<>();
+        return dataList;
+    }
+
+    public static List<PointData> RequestListError(String... pointId) {
+        List<PointData> dataList = new ArrayList<>();
+        return dataList;
+    }
+
+    public static PointData RequestError(String pointId) {
+        PointData data = new PointData();
+        data.setPointValueInDouble(0);
+        data.setPointName("0");
+        return data;
+    }
+
+    public static Map<String, Double> RequestMapError() {
+        Map<String, Double> resultMap = new HashMap();
+        return resultMap;
+    }
+}

+ 27 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/GeneralTsData.java

@@ -0,0 +1,27 @@
+package com.gyee.alarm.util.realtimesource.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;
+
+}
+

+ 8 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/Interpolation.java

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

+ 277 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/JsonObjectHelper.java

@@ -0,0 +1,277 @@
+package com.gyee.alarm.util.realtimesource.timeseries;
+
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.gyee.common.model.DNAStatVal;
+import com.gyee.common.model.DNAVal;
+import com.gyee.common.model.PointData;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+
+/**
+ * @descrition:JSONObject转实体辅助类
+ * @author:Wanghs
+ * @date:2018-05-10
+ */
+public class JsonObjectHelper {
+    public static List<PointData> phrasePointData(JSONArray jsonArray, String tagName) {
+        List<PointData> result = new ArrayList<>();
+
+        for (int i = 0; i < jsonArray.size(); i++) {
+            JSONObject tsData = jsonArray.getJSONObject(i);
+
+            Long ts = tsData.getLong("ts");
+            String pointValue = null;
+            if (tsData.containsKey("doubleValue")) {
+                pointValue = tsData.getString("doubleValue");
+            } else if (tsData.containsKey("booleanValue")) {
+                pointValue = tsData.getString("booleanValue");
+            } else if (tsData.containsKey("longValue")) {
+                pointValue = tsData.getString("longValue");
+            } else if (tsData.containsKey("stringValue")) {
+                pointValue = tsData.getString("stringValue");
+            }
+            PointData pointData = new PointData();
+            pointData.setEdnaId(tagName);
+            pointData.setPointName("1");
+            pointData.setPointTime(ts);
+            pointData.setPointValue(pointValue);
+            pointData.setPointValueInDouble(Double.parseDouble(pointValue));
+            //System.out.println("key= " + tagName + ", ts = " + ts + ", value = " + pointValue);
+            result.add(pointData);
+        }
+        return result;
+    }
+
+    public static List<PointData> phrasePointData(JSONObject jsonObject, List<String> tagName) {
+        List<PointData> result = new ArrayList<>();
+
+        if(tagName.size()==jsonObject.keySet().size())
+        {
+
+            for (int i = 0; i < tagName.size(); i++) {
+
+                // 获得key
+                String key = tagName.get(i);
+                JSONObject tsData = jsonObject.getJSONObject(key);
+                Long ts = tsData.getLong("ts");
+                String pointValue = null;
+                if (tsData.containsKey("doubleValue")) {
+                    pointValue = tsData.getString("doubleValue");
+                } else if (tsData.containsKey("booleanValue")) {
+                    pointValue = tsData.getString("booleanValue");
+                } else if (tsData.containsKey("longValue")) {
+                    pointValue = tsData.getString("longValue");
+                } else if (tsData.containsKey("stringValue")) {
+                    pointValue = tsData.getString("stringValue");
+                }
+                PointData pointData = new PointData();
+                pointData.setEdnaId(tagName.get(i));
+                pointData.setPointName("1");
+                pointData.setPointTime(ts);
+                pointData.setPointValue(pointValue);
+                pointData.setPointValueInDouble(Double.parseDouble(pointValue));
+                //System.out.println("key= " + tagName + ", ts = " + ts + ", value = " + pointValue);
+                result.add(pointData);
+            }
+
+        }
+
+        return result;
+    }
+
+
+    public static PointData phrasePointData(JSONObject jsonObject, String tagName) {
+        PointData pointData = new PointData();
+
+        if(jsonObject.keySet().size()>0)
+        {
+
+                // 获得key
+                String key = tagName;
+                JSONObject tsData = jsonObject.getJSONObject(key);
+                Long ts = tsData.getLong("ts");
+                String pointValue = null;
+                if (tsData.containsKey("doubleValue")) {
+                    pointValue = tsData.getString("doubleValue");
+                } else if (tsData.containsKey("booleanValue")) {
+                    pointValue = tsData.getString("booleanValue");
+                } else if (tsData.containsKey("longValue")) {
+                    pointValue = tsData.getString("longValue");
+                } else if (tsData.containsKey("stringValue")) {
+                    pointValue = tsData.getString("stringValue");
+                }
+
+                pointData.setEdnaId(tagName);
+                pointData.setPointName("1");
+                pointData.setPointTime(ts);
+                pointData.setPointValue(pointValue);
+                pointData.setPointValueInDouble(Double.parseDouble(pointValue));
+                //System.out.println("key= " + tagName + ", ts = " + ts + ", value = " + pointValue);
+
+            }
+
+
+
+        return pointData;
+    }
+    public static List<PointData> phrasePointData(JSONObject jsonObject) {
+        List<PointData> result = new ArrayList<>();
+        Iterator<String> sIterator = jsonObject.keySet().iterator();
+        while (sIterator.hasNext()) {
+            // 获得key
+            String key = sIterator.next();
+            // 根据key获得value, value也可以是JSONObject,JSONArray,使用对应的参数接收即可
+            JSONObject jsonData = jsonObject.getJSONObject(key);
+            Long ts = 0l;
+
+            if (jsonData!=null){
+                ts  = jsonData.getLong("ts");
+                String pointValue = null;
+                if (jsonData.containsKey("doubleValue")) {
+                    pointValue = jsonData.getString("doubleValue");
+                } else if (jsonData.containsKey("booleanValue")) {
+                    pointValue = jsonData.getString("booleanValue");
+                } else if (jsonData.containsKey("longValue")) {
+                    pointValue = jsonData.getString("longValue");
+                } else if (jsonData.containsKey("stringValue")) {
+                    pointValue = jsonData.getString("stringValue");
+                }
+                PointData pointData = new PointData();
+                pointData.setEdnaId(key);
+                pointData.setPointName(key);
+                pointData.setPointValue(pointValue);
+                pointData.setPointTime(ts);
+                if(pointValue.equals("false")  )
+                {
+                    pointData.setPointValueInDouble(0.0);
+                }else  if(pointValue.equals("true") )
+                {
+                    pointData.setPointValueInDouble(1.0);
+                }else
+                {
+                    pointData.setPointValueInDouble(Double.parseDouble(pointValue));
+                }
+
+                //  System.out.println("key= " + key + ", ts = " + ts + ", value = " + pointValue);
+                result.add(pointData);
+            }
+        }
+        return result;
+    }
+    /**
+     * @param arry    DoubleStatData集合
+     * @param tagName 标签点名
+     * @param type    0、最大值。1、最小值。2、平均值
+     */
+    public static List<PointData> GeneralTsDataToPointDataByStat(JSONArray arry, String tagName, int type) {
+        List<PointData> result = new ArrayList<>();
+        for (int i = 0; i < arry.size(); i++) {
+            JSONObject jsonData = arry.getJSONObject(i);
+            PointData data = new PointData();
+            data.setEdnaId(tagName);
+            data.setPointName("1");
+            JSONObject avgData = null;
+            JSONObject maxData = null;
+            JSONObject minData = null;
+            if (jsonData.containsKey("avg")) {
+                avgData = jsonData.getJSONObject("avg");
+            }
+            if (jsonData.containsKey("max")) {
+                maxData = jsonData.getJSONObject("max");
+            }
+            if (jsonData.containsKey("min")) {
+                minData = jsonData.getJSONObject("min");
+            }
+            switch (type) {
+                case 0:
+                    data.setPointValue(String.valueOf(maxData.getString("doubleValue")));
+                    data.setPointValueInDouble(Double.valueOf(maxData.getString("doubleValue")));
+                    data.setPointTime(Long.valueOf(maxData.getString("ts")) );
+                    break;
+                case 1:
+                    data.setPointValue(String.valueOf(minData.getString("doubleValue")));
+                    data.setPointValueInDouble(Double.valueOf(minData.getString("doubleValue")));
+                    data.setPointTime(Long.valueOf(minData.getString("ts")) );
+                    break;
+                case 2:
+                    data.setPointValue(String.valueOf(avgData.getString("doubleValue")));
+                    data.setPointValueInDouble(Double.valueOf(avgData.getString("doubleValue")));
+                    data.setPointTime(Long.valueOf(avgData.getString("ts")) );
+                    break;
+                default:
+                    break;
+            }
+            result.add(data);
+        }
+        return result;
+    }
+
+    public static DNAVal[] phraseDNAVal(JSONObject jsonObject, String[] tagName) {
+        DNAVal[] arr = new DNAVal[jsonObject.size()];
+        List<DNAVal> list = new ArrayList<>();
+        Iterator<String> sIterator = jsonObject.keySet().iterator();
+
+        for (int i = 0; i < tagName.length; i++) {
+            // 获得key
+            String key = tagName[i];
+            // 根据key获得value, value也可以是JSONObject,JSONArray,使用对应的参数接收即可
+            JSONObject jsonData = jsonObject.getJSONObject(key);
+            DNAVal data = new DNAVal();
+            data.Time = Integer.parseInt(String.valueOf(Long.valueOf(jsonData.getString("ts")) ));
+            data.Status = (short) jsonData.getShortValue("status");
+            data.DValue = (Double.valueOf(jsonData.getDoubleValue("doubleValue")));
+            list.add(data);
+        }
+
+        return list.toArray(arr);
+    }
+
+    public static DNAStatVal[] phraseDNAVal(JSONArray jsonArray) {
+
+        DNAStatVal[] arr = new DNAStatVal[jsonArray.size()];
+        List<DNAStatVal> list = new ArrayList<>();
+        for (int i = 0; i < jsonArray.size(); i++) {
+            JSONObject jsonData = jsonArray.getJSONObject(i);
+            JSONObject avgData = null;
+            JSONObject maxData = null;
+            JSONObject minData = null;
+            if (jsonData.containsKey("avg")) {
+                avgData = jsonData.getJSONObject("avg");
+            }
+            if (jsonData.containsKey("max")) {
+                maxData = jsonData.getJSONObject("max");
+            }
+            if (jsonData.containsKey("min")) {
+                minData = jsonData.getJSONObject("min");
+            }
+            DNAStatVal statVal = new DNAStatVal();
+
+            DNAVal avgVal = new DNAVal();
+            DNAVal maxVal = new DNAVal();
+            DNAVal minVal = new DNAVal();
+
+            avgVal.Time = Integer.valueOf(String.valueOf(Long.valueOf(avgData.getString("ts")) ));
+            avgVal.DValue = Double.valueOf(avgData.getString("doubleValue"));
+
+            maxVal.Time =  Integer.valueOf(String.valueOf(Long.valueOf(maxData.getString("ts")) ));
+            maxVal.DValue = Double.valueOf(maxData.getString("doubleValue"));
+
+            minVal.Time =  Integer.valueOf(String.valueOf(Long.valueOf(minData.getString("ts")) ));
+            minVal.DValue = Double.valueOf(minData.getString("doubleValue"));
+
+            statVal.max = maxVal;
+            statVal.min = minVal;
+            statVal.avg = avgVal;
+
+            list.add(statVal);
+        }
+
+        return list.toArray(arr);
+    }
+
+}

+ 24 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/LongTsData.java

@@ -0,0 +1,24 @@
+package com.gyee.alarm.util.realtimesource.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
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/LongWriteTsData.java

@@ -0,0 +1,20 @@
+package com.gyee.alarm.util.realtimesource.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
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/StringTsData.java

@@ -0,0 +1,24 @@
+package com.gyee.alarm.util.realtimesource.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;
+    }
+
+}
+

+ 34 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/StringUtil.java

@@ -0,0 +1,34 @@
+package com.gyee.alarm.util.realtimesource.timeseries;
+
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * String辅助类
+ * 
+ */
+public class StringUtil extends StringUtils {
+	
+	/**
+	 * 非空判断
+	 * 
+	 * @param obj
+	 * @return
+	 */
+	public static boolean isNotBlank(Object obj) {
+		return !isBlank(obj);
+	}
+
+	/**
+	 * 为空判断
+	 * 
+	 * @param obj
+	 * @return
+	 */
+	public static boolean isBlank(Object obj) {
+		if (obj == null || StringUtils.isBlank(obj.toString())) {
+			return true;
+		}
+		return false;
+	}
+
+}

+ 20 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/StringWriteTsData.java

@@ -0,0 +1,20 @@
+package com.gyee.alarm.util.realtimesource.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
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/TsData.java

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

+ 15 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/TsDataType.java

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

+ 12 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/TsPoint.java

@@ -0,0 +1,12 @@
+package com.gyee.alarm.util.realtimesource.timeseries;
+
+/**
+ * @author songwb<songwb@aliyun.com>
+ */
+public interface TsPoint {
+
+    String getId();
+
+    TsDataType getTsDataType();
+}
+

+ 36 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/TsPointData.java

@@ -0,0 +1,36 @@
+package com.gyee.alarm.util.realtimesource.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;
+    }
+}
+

+ 23 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/TsPointDataList.java

@@ -0,0 +1,23 @@
+package com.gyee.alarm.util.realtimesource.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;
+
+}
+

+ 17 - 0
alarm-web/src/main/java/com/gyee/alarm/util/realtimesource/timeseries/TsQuery.java

@@ -0,0 +1,17 @@
+package com.gyee.alarm.util.realtimesource.timeseries;
+
+public interface TsQuery {
+
+    TsPoint getTsPoint();
+
+    long getStartTs();
+
+    long getEndTs();
+
+    int getInterval();
+
+    int getLimit();
+
+    Interpolation getInterpolation();
+
+}

+ 81 - 0
alarm-web/src/main/java/com/gyee/alarm/util/statisticcs/ActivePowerStatistics.java

@@ -0,0 +1,81 @@
+package com.gyee.alarm.util.statisticcs;
+
+import com.gyee.common.contant.Contant;
+import com.gyee.alarm.model.auto.ProBasicEquipment;
+import com.gyee.alarm.model.vo.StatusItemVo;
+
+import java.util.Date;
+import java.util.Map;
+
+public class ActivePowerStatistics extends  StatusStatistics{
+
+    public ActivePowerStatistics(Map<String, ProBasicEquipment> windTurbines, Date date)
+    {
+            super(windTurbines, date);
+    }
+    
+    @Override
+    public  void addPointValue(String windTurbineId, double value)
+    {
+        ProBasicEquipment wt = windTurbines.get(windTurbineId);
+        
+
+        if (dic.containsKey(wt.getWindpowerstationId()) && dic.get(wt.getWindpowerstationId()).containsKey(Contant.SSZGL)) {
+
+            Map<String, StatusItemVo> tempmap=dic.get(wt.getWindpowerstationId());
+            Double tempvalue= tempmap.get(Contant.SSZGL).getEdnaValue();
+            tempvalue++;
+            tempmap.get(Contant.SSZGL).setEdnaValue(tempvalue);
+
+
+        }
+        if (dic.containsKey(wt.getLineId()) && dic.get(wt.getLineId()).containsKey(Contant.SSZGL)) {
+
+            Map<String, StatusItemVo> tempmap=dic.get(wt.getLineId());
+            Double tempvalue= tempmap.get(Contant.SSZGL).getEdnaValue();
+            tempvalue++;
+            tempmap.get(Contant.SSZGL).setEdnaValue(tempvalue);
+
+
+        }
+        if (dic.containsKey(wt.getProjectId()) && dic.get(wt.getProjectId()).containsKey(Contant.SSZGL)) {
+
+            Map<String, StatusItemVo> tempmap=dic.get(wt.getProjectId());
+            Double tempvalue= tempmap.get(Contant.SSZGL).getEdnaValue();
+            tempvalue++;
+            tempmap.get(Contant.SSZGL).setEdnaValue(tempvalue);
+
+
+        }
+        if (dic.containsKey("0") && dic.get("0").containsKey(Contant.SSZGL)) {
+
+            Map<String, StatusItemVo> tempmap=dic.get("0");
+            Double tempvalue= tempmap.get(Contant.SSZGL).getEdnaValue();
+            tempvalue++;
+            tempmap.get(Contant.SSZGL).setEdnaValue(tempvalue);
+
+
+        }
+        if (wt.getWindpowerstationId().indexOf("FDC")>=0) {
+            if (dic.containsKey("-1") && dic.get("-1").containsKey(Contant.SSZGL)) {
+
+                Map<String, StatusItemVo> tempmap=dic.get("-1");
+                Double tempvalue= tempmap.get(Contant.SSZGL).getEdnaValue();
+                tempvalue++;
+                tempmap.get(Contant.SSZGL).setEdnaValue(tempvalue);
+
+            }
+        } else {
+            if (dic.containsKey("-2") && dic.get("-2").containsKey(Contant.SSZGL)) {
+
+                Map<String, StatusItemVo> tempmap=dic.get("-2");
+                Double tempvalue= tempmap.get(Contant.SSZGL).getEdnaValue();
+                tempvalue++;
+                tempmap.get(Contant.SSZGL).setEdnaValue(tempvalue);
+
+            }
+        }
+
+    }
+
+}

File diff suppressed because it is too large
+ 3316 - 0
alarm-web/src/main/java/com/gyee/alarm/util/statisticcs/Initial.java


+ 133 - 0
alarm-web/src/main/java/com/gyee/alarm/util/statisticcs/StatusStatistics.java

@@ -0,0 +1,133 @@
+package com.gyee.alarm.util.statisticcs;
+
+import com.gyee.common.contant.Contant;
+import com.gyee.common.model.PointData;
+import com.gyee.alarm.model.auto.ProBasicEquipment;
+import com.gyee.alarm.model.auto.ProBasicPowerstationPoint;
+import com.gyee.alarm.model.vo.StatusItemVo;
+
+import java.util.*;
+
+public abstract class StatusStatistics {
+    private static Map<Integer, String> statusToUniformCode = new HashMap<Integer, String>();
+
+    static  {
+        statusToUniformCode.put(0, Contant.DJTS);
+        statusToUniformCode.put(1, Contant.YXTS);
+        statusToUniformCode.put(2, Contant.GZTJ);
+        statusToUniformCode.put(3, Contant.TXZD);
+        statusToUniformCode.put(4, Contant.WHTJ);
+
+         //   #region 新增限电台数
+        statusToUniformCode.put(5, Contant.XDTS);
+        statusToUniformCode.put(6, Contant.XDTS);
+
+    }
+
+    protected Map<String, Map<String, StatusItemVo>> dic = new HashMap<String, Map<String, StatusItemVo>>();
+    protected Map<String, ProBasicEquipment> windTurbines;
+    protected Date date;
+
+    public StatusStatistics(Map<String, ProBasicEquipment> windTurbines, Date date) {
+        this.windTurbines = windTurbines;
+        this.date = date;
+    }
+
+    public void addInitData(ProBasicPowerstationPoint wpstp) {
+        Map<String, StatusItemVo> items = null;
+        if (dic.containsKey(wpstp.getWindpowerstationId())) {
+            items = dic.get(wpstp.getWindpowerstationId());
+        } else {
+            items = new HashMap<String, StatusItemVo>();
+            dic.put(wpstp.getWindpowerstationId(), items);
+        }
+            //#region EDNA转EDOS
+        //StatusItemVo item = new StatusItemVo { UniformCode = wpstp.UNIFORMCODE, EdnaPoint = wpstp.SHORTID, EdnaValue = 0, size = 0 };
+        StatusItemVo item = new StatusItemVo();
+        item.setUniformCode(wpstp.getUniformCode());
+        item.setEdnaValue(0.0);
+        item.setEdnaPoint(wpstp.getNemCode());
+        item.setCount(0.0);
+
+
+        items.put(item.getUniformCode(), item);
+    }
+
+    public   void addPointValue(String windTurbineId, Double value) {
+        ProBasicEquipment wt = windTurbines.get(windTurbineId);
+
+        if (!statusToUniformCode.containsKey(value.intValue())){
+            return;
+        }
+
+
+        if (dic.containsKey(wt.getWindpowerstationId()) && dic.get(wt.getWindpowerstationId()).containsKey(statusToUniformCode.get(value.intValue()))) {
+
+            Map<String, StatusItemVo> tempmap=dic.get(wt.getWindpowerstationId());
+            Double tempvalue= tempmap.get(statusToUniformCode.get(value.intValue())).getEdnaValue();
+            tempvalue++;
+            tempmap.get(statusToUniformCode.get(value.intValue())).setEdnaValue(tempvalue);
+
+        }
+        if (dic.containsKey(wt.getLineId()) && dic.get(wt.getLineId()).containsKey(statusToUniformCode.get(value.intValue()))) {
+
+            Map<String, StatusItemVo> tempmap=dic.get(wt.getLineId());
+            Double tempvalue= tempmap.get(statusToUniformCode.get(value.intValue())).getEdnaValue();
+            tempvalue++;
+            tempmap.get(statusToUniformCode.get(value.intValue())).setEdnaValue(tempvalue);
+
+        }
+        if (dic.containsKey(wt.getProjectId()) && dic.get(wt.getProjectId()).containsKey(statusToUniformCode.get(value.intValue()))) {
+
+            Map<String, StatusItemVo> tempmap=dic.get(wt.getProjectId());
+            Double tempvalue= tempmap.get(statusToUniformCode.get(value.intValue())).getEdnaValue();
+            tempvalue++;
+            tempmap.get(statusToUniformCode.get(value.intValue())).setEdnaValue(tempvalue);
+
+        }
+        if (dic.containsKey("0") && dic.get("0").containsKey(statusToUniformCode.get(value.intValue()))) {
+
+            Map<String, StatusItemVo> tempmap=dic.get("0");
+            Double tempvalue= tempmap.get(statusToUniformCode.get(value.intValue())).getEdnaValue();
+            tempvalue++;
+            tempmap.get(statusToUniformCode.get(value.intValue())).setEdnaValue(tempvalue);
+
+        }
+        if (wt.getWindpowerstationId().indexOf("FDC")>=0) {
+            if (dic.containsKey("-1") && dic.get("-1").containsKey(statusToUniformCode.get(value.intValue()))) {
+
+                Map<String, StatusItemVo> tempmap=dic.get("-1");
+                Double tempvalue= tempmap.get(statusToUniformCode.get(value.intValue())).getEdnaValue();
+                tempvalue++;
+                tempmap.get(statusToUniformCode.get(value.intValue())).setEdnaValue(tempvalue);
+            }
+        } else {
+            if (dic.containsKey("-2") && dic.get("-2").containsKey(statusToUniformCode.get(value.intValue()))) {
+
+                Map<String, StatusItemVo> tempmap=dic.get("-2");
+                Double tempvalue= tempmap.get(statusToUniformCode.get(value.intValue())).getEdnaValue();
+                tempvalue++;
+                tempmap.get(statusToUniformCode.get(value.intValue())).setEdnaValue(tempvalue);
+            }
+        }
+
+
+    }
+
+    public  List<PointData> getRealParameter() {
+        java.util.List<PointData> retValue = new ArrayList<PointData>();
+        for (String mkey : dic.keySet()) {
+            for (String skey : dic.get(mkey).keySet()) {
+                StatusItemVo item =dic.get(mkey).get(skey);
+                PointData p = new PointData();
+                p.setPointValueInDouble(item.getEdnaValue());
+                p.setEdnaId(item.getEdnaPoint());
+                p.setPointTime(date.getTime()/1000);
+                retValue.add(p);
+            }
+        }
+        return retValue;
+    }
+
+    public abstract void addPointValue(String windTurbineId, double value);
+}

+ 170 - 0
alarm-web/src/main/java/com/gyee/alarm/util/statisticcs/TheoryPowerStatistics.java

@@ -0,0 +1,170 @@
+package com.gyee.alarm.util.statisticcs;
+
+import com.gyee.common.contant.Contant;
+import com.gyee.common.model.PointData;
+import com.gyee.alarm.model.auto.ProBasicEquipmentPoint;
+import com.gyee.alarm.model.auto.ProBasicEquipment;
+import com.gyee.alarm.model.vo.StatusItemVo;
+
+import java.util.*;
+
+public class TheoryPowerStatistics extends  StatusStatistics{
+
+    public TheoryPowerStatistics(Map<String, ProBasicEquipment> windTurbines, Date date)
+    {
+            super(windTurbines, date);
+    }
+
+    protected Map<String, Map<String, StatusItemVo>> dicWindturbine = new HashMap<String, Map<String, StatusItemVo>>();
+    public  void addPointValue(String windTurbineId, double value, String powerKey)
+    {
+        ProBasicEquipment wt = windTurbines.get(windTurbineId);
+        
+
+        if (dic.containsKey(wt.getWindpowerstationId()) && dic.get(wt.getWindpowerstationId()).containsKey(Contant.SSZGL)) {
+
+            Map<String, StatusItemVo> tempmap=dic.get(wt.getWindpowerstationId());
+            Double tempvalue= tempmap.get(Contant.SSZGL).getEdnaValue();
+            tempvalue++;
+            tempmap.get(Contant.SSZGL).setEdnaValue(tempvalue);
+
+
+        }
+        if (dic.containsKey(wt.getLineId()) && dic.get(wt.getLineId()).containsKey(Contant.SSZGL)) {
+
+            Map<String, StatusItemVo> tempmap=dic.get(wt.getLineId());
+            Double tempvalue= tempmap.get(Contant.SSZGL).getEdnaValue();
+            tempvalue++;
+            tempmap.get(Contant.SSZGL).setEdnaValue(tempvalue);
+
+
+        }
+        if (dic.containsKey(wt.getProjectId()) && dic.get(wt.getProjectId()).containsKey(Contant.SSZGL)) {
+
+            Map<String, StatusItemVo> tempmap=dic.get(wt.getProjectId());
+            Double tempvalue= tempmap.get(Contant.SSZGL).getEdnaValue();
+            tempvalue++;
+            tempmap.get(Contant.SSZGL).setEdnaValue(tempvalue);
+
+
+        }
+        if (dic.containsKey("0") && dic.get("0").containsKey(Contant.SSZGL)) {
+
+            Map<String, StatusItemVo> tempmap=dic.get("0");
+            Double tempvalue= tempmap.get(Contant.SSZGL).getEdnaValue();
+            tempvalue++;
+            tempmap.get(Contant.SSZGL).setEdnaValue(tempvalue);
+
+
+        }
+        if (wt.getWindpowerstationId().indexOf("FDC")>=0) {
+            if (dic.containsKey("-1") && dic.get("-1").containsKey(Contant.SSZGL)) {
+
+                Map<String, StatusItemVo> tempmap=dic.get("-1");
+                Double tempvalue= tempmap.get(Contant.SSZGL).getEdnaValue();
+                tempvalue++;
+                tempmap.get(Contant.SSZGL).setEdnaValue(tempvalue);
+
+            }
+        } else {
+            if (dic.containsKey("-2") && dic.get("-2").containsKey(Contant.SSZGL)) {
+
+                Map<String, StatusItemVo> tempmap=dic.get("-2");
+                Double tempvalue= tempmap.get(Contant.SSZGL).getEdnaValue();
+                tempvalue++;
+                tempmap.get(Contant.SSZGL).setEdnaValue(tempvalue);
+
+            }
+        }
+
+    }
+
+
+    public  void addInitWindTrubineData(ProBasicEquipmentPoint ais)
+    {
+        Map<String, StatusItemVo> items = null;
+        if (dicWindturbine.containsKey(ais.getWindturbineId()))
+        {
+            items = dicWindturbine.get(ais.getWindturbineId());
+        }
+        else
+        {
+            items = new HashMap<String, StatusItemVo>();
+            dicWindturbine.put(ais.getWindturbineId(), items);
+        }
+        
+        StatusItemVo item = new StatusItemVo();
+        item.setUniformCode(ais.getUniformCode());
+        item.setEdnaValue(0.0);
+        item.setEdnaPoint(ais.getNemCode());
+        item.setCount(0.0);
+
+
+        items.put(item.getUniformCode(), item);
+    }
+    public void addWindturbinePointValue(String windTurbineId, double value, String powerKey)
+    {
+        if (dicWindturbine.containsKey(windTurbineId))
+        {
+            dicWindturbine.get(windTurbineId).get(powerKey).setEdnaValue(value);
+        }
+    }
+    @Override
+    public List<PointData> getRealParameter()
+    {
+        java.util.List<PointData> retValue = new ArrayList<PointData>();
+        for (String mkey : dic.keySet())
+        {
+            for (String skey : dic.get(mkey).keySet())
+            {
+                StatusItemVo item = dic.get(mkey).get(skey);
+
+                if (item.getCount() != 0)
+                {
+                    PointData p = new PointData();
+
+                    p.setPointValueInDouble(item.getEdnaValue());
+                    p.setEdnaId(item.getEdnaPoint());
+                    p.setPointTime(date.getTime()/1000);
+                    retValue.add(p);
+                }
+            }
+        }
+
+
+        for (String mkey : dic.keySet())
+
+        {
+            for (String skey : dic.get(mkey).keySet())
+            {
+                StatusItemVo item = dic.get(mkey).get(skey);
+                PointData p = new PointData();
+
+                p.setPointValueInDouble(item.getEdnaValue());
+                p.setEdnaId(item.getEdnaPoint());
+                p.setPointTime(date.getTime()/1000);
+                retValue.add(p);
+            }
+        }
+        for (String mkey : dicWindturbine.keySet())
+        {
+            for (String skey : dicWindturbine.get(mkey).keySet())
+            {
+                StatusItemVo item = dicWindturbine.get(mkey).get(skey);
+                PointData p = new PointData();
+
+                p.setPointValueInDouble(item.getEdnaValue());
+                p.setEdnaId(item.getEdnaPoint());
+                p.setPointTime(date.getTime()/1000);
+                retValue.add(p);
+            }
+        }
+        return retValue;
+    }
+
+    @Override
+    public void addPointValue(String windTurbineId, double value) {
+
+    }
+
+}

+ 119 - 0
alarm-web/src/main/java/com/gyee/alarm/util/statisticcs/WindSpeedStatistics.java

@@ -0,0 +1,119 @@
+package com.gyee.alarm.util.statisticcs;
+
+import com.gyee.common.contant.Contant;
+import com.gyee.common.model.PointData;
+import com.gyee.common.model.StringUtils;
+import com.gyee.alarm.model.auto.ProBasicEquipment;
+import com.gyee.alarm.model.vo.StatusItemVo;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Map;
+import java.util.List;
+
+public class WindSpeedStatistics extends  StatusStatistics{
+
+    public WindSpeedStatistics(Map<String, ProBasicEquipment> windTurbines, Date date)
+    {
+            super(windTurbines, date);
+    }
+    
+    @Override
+    public  void addPointValue(String windTurbineId, double value)
+    {
+        ProBasicEquipment wt = windTurbines.get(windTurbineId);
+
+
+        if (dic.containsKey(wt.getWindpowerstationId()) && dic.get(wt.getWindpowerstationId()).containsKey(Contant.SSFS)) {
+
+            Map<String, StatusItemVo> tempmap=dic.get(wt.getWindpowerstationId());
+            Double tempvalue= tempmap.get(Contant.SSFS).getEdnaValue();
+            tempvalue++;
+            tempmap.get(Contant.SSFS).setEdnaValue(tempvalue);
+            Double tempcount= tempmap.get(Contant.SSFS).getCount();
+            tempcount++;
+            tempmap.get(Contant.SSFS).setCount(tempcount);
+
+        }
+        if (dic.containsKey(wt.getLineId()) && dic.get(wt.getLineId()).containsKey(Contant.SSFS)) {
+
+            Map<String, StatusItemVo> tempmap=dic.get(wt.getLineId());
+            Double tempvalue= tempmap.get(Contant.SSFS).getEdnaValue();
+            tempvalue++;
+            tempmap.get(Contant.SSFS).setEdnaValue(tempvalue);
+            Double tempcount= tempmap.get(Contant.SSFS).getCount();
+            tempcount++;
+            tempmap.get(Contant.SSFS).setCount(tempcount);
+
+        }
+        if (dic.containsKey(wt.getProjectId()) && dic.get(wt.getProjectId()).containsKey(Contant.SSFS)) {
+
+            Map<String, StatusItemVo> tempmap=dic.get(wt.getProjectId());
+            Double tempvalue= tempmap.get(Contant.SSFS).getEdnaValue();
+            tempvalue++;
+            tempmap.get(Contant.SSFS).setEdnaValue(tempvalue);
+            Double tempcount= tempmap.get(Contant.SSFS).getCount();
+            tempcount++;
+            tempmap.get(Contant.SSFS).setCount(tempcount);
+
+        }
+        if (dic.containsKey("0") && dic.get("0").containsKey(Contant.SSFS)) {
+
+            Map<String, StatusItemVo> tempmap=dic.get("0");
+            Double tempvalue= tempmap.get(Contant.SSFS).getEdnaValue();
+            tempvalue++;
+            tempmap.get(Contant.SSFS).setEdnaValue(tempvalue);
+            Double tempcount= tempmap.get(Contant.SSFS).getCount();
+            tempcount++;
+            tempmap.get(Contant.SSFS).setCount(tempcount);
+
+        }
+        if (wt.getWindpowerstationId().indexOf("FDC")>=0) {
+            if (dic.containsKey("-1") && dic.get("-1").containsKey(Contant.SSFS)) {
+
+                Map<String, StatusItemVo> tempmap=dic.get("-1");
+                Double tempvalue= tempmap.get(Contant.SSFS).getEdnaValue();
+                tempvalue++;
+                tempmap.get(Contant.SSFS).setEdnaValue(tempvalue);
+                Double tempcount= tempmap.get(Contant.SSFS).getCount();
+                tempcount++;
+                tempmap.get(Contant.SSFS).setCount(tempcount);
+            }
+        } else {
+            if (dic.containsKey("-2") && dic.get("-2").containsKey(Contant.SSFS)) {
+
+                Map<String, StatusItemVo> tempmap=dic.get("-2");
+                Double tempvalue= tempmap.get(Contant.SSFS).getEdnaValue();
+                tempvalue++;
+                tempmap.get(Contant.SSFS).setEdnaValue(tempvalue);
+                Double tempcount= tempmap.get(Contant.SSFS).getCount();
+                tempcount++;
+                tempmap.get(Contant.SSFS).setCount(tempcount);
+            }
+        }
+
+    }
+    @Override
+    public  List<PointData> getRealParameter()
+    {
+        java.util.List<PointData> retValue = new ArrayList<PointData>();
+        for (String mkey : dic.keySet())
+        {
+            for (String skey : dic.get(mkey).keySet())
+            {
+                StatusItemVo item = dic.get(mkey).get(skey);
+
+                if (item.getCount() != 0)
+                {
+                    PointData p = new PointData();
+
+                    p.setPointValueInDouble(StringUtils.round(item.getEdnaValue() / item.getCount(),2));
+                    p.setEdnaId(item.getEdnaPoint());
+                    p.setPointTime(date.getTime()/1000);
+                    retValue.add(p);
+                }
+            }
+        }
+        return retValue;
+    }
+}

+ 52 - 0
alarm-web/src/main/java/com/gyee/alarm/util/taos/DataBaseMonitor.java

@@ -0,0 +1,52 @@
+package com.gyee.alarm.util.taos;
+
+import java.sql.*;
+
+/**
+ * Prepare target database.
+ * Count total records in database periodically so that we can estimate the writing speed.
+ */
+public class DataBaseMonitor {
+    private Connection conn;
+    private Statement stmt;
+
+    public DataBaseMonitor init() throws SQLException {
+        if (conn == null) {
+            String jdbcURL = "jdbc:TAOS://192.168.1.109:6030?user=root&password=taosdata";
+            conn = DriverManager.getConnection(jdbcURL);
+            stmt = conn.createStatement();
+        }
+        return this;
+    }
+
+    public void close() {
+        try {
+            stmt.close();
+        } catch (SQLException e) {
+        }
+        try {
+            conn.close();
+        } catch (SQLException e) {
+        }
+    }
+
+    public void prepareDatabase() throws SQLException {
+        stmt.execute("DROP DATABASE IF EXISTS test");
+        stmt.execute("CREATE DATABASE test");
+        stmt.execute("CREATE STABLE test.meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS (location BINARY(64), groupId INT)");
+    }
+
+    public long count() throws SQLException {
+        try (ResultSet result = stmt.executeQuery("SELECT count(*) from test.meters")) {
+            result.next();
+            return result.getLong(1);
+        }
+    }
+
+    public long getTableCount() throws SQLException {
+        try (ResultSet result = stmt.executeQuery("select count(*) from information_schema.ins_tables where db_name = 'test';")) {
+            result.next();
+            return result.getLong(1);
+        }
+    }
+}

+ 70 - 0
alarm-web/src/main/java/com/gyee/alarm/util/taos/FastWriteExample.java

@@ -0,0 +1,70 @@
+package com.gyee.alarm.util.taos;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+
+
+public class FastWriteExample {
+    final static Logger logger = LoggerFactory.getLogger(FastWriteExample.class);
+
+    final static int taskQueueCapacity = 1000000;
+    final static List<BlockingQueue<String>> taskQueues = new ArrayList<>();
+    final static List<ReadTask> readTasks = new ArrayList<>();
+    final static List<WriteTask> writeTasks = new ArrayList<>();
+    final static DataBaseMonitor databaseMonitor = new DataBaseMonitor();
+
+    public static void stopAll() {
+        logger.info("shutting down");
+        readTasks.forEach(task -> task.stop());
+        writeTasks.forEach(task -> task.stop());
+        databaseMonitor.close();
+    }
+
+    public static void main(String[] args) throws InterruptedException, SQLException {
+        int readTaskCount = args.length > 0 ? Integer.parseInt(args[0]) : 1;
+        int writeTaskCount = args.length > 1 ? Integer.parseInt(args[1]) : 3;
+        int tableCount = args.length > 2 ? Integer.parseInt(args[2]) : 1000;
+        int maxBatchSize = args.length > 3 ? Integer.parseInt(args[3]) : 3000;
+
+        logger.info("readTaskCount={}, writeTaskCount={} tableCount={} maxBatchSize={}",
+                readTaskCount, writeTaskCount, tableCount, maxBatchSize);
+
+        databaseMonitor.init().prepareDatabase();
+
+        // Create task queues, whiting tasks and start writing threads.
+        for (int i = 0; i < writeTaskCount; ++i) {
+            BlockingQueue<String> queue = new ArrayBlockingQueue<>(taskQueueCapacity);
+            taskQueues.add(queue);
+            WriteTask task = new WriteTask(queue, maxBatchSize);
+            Thread t = new Thread(task);
+            t.setName("WriteThread-" + i);
+            t.start();
+        }
+
+        // create reading tasks and start reading threads
+        int tableCountPerTask = tableCount / readTaskCount;
+        for (int i = 0; i < readTaskCount; ++i) {
+            ReadTask task = new ReadTask(i, taskQueues, tableCountPerTask);
+            Thread t = new Thread(task);
+            t.setName("ReadThread-" + i);
+            t.start();
+        }
+
+        Runtime.getRuntime().addShutdownHook(new Thread(FastWriteExample::stopAll));
+
+        long lastCount = 0;
+        while (true) {
+            Thread.sleep(10000);
+            long numberOfTable = databaseMonitor.getTableCount();
+            long count = databaseMonitor.count();
+            logger.info("numberOfTable={} count={} speed={}", numberOfTable, count, (count - lastCount) / 10);
+            lastCount = count;
+        }
+    }
+}

+ 53 - 0
alarm-web/src/main/java/com/gyee/alarm/util/taos/MockDataSource.java

@@ -0,0 +1,53 @@
+package com.gyee.alarm.util.taos;
+
+import java.util.Iterator;
+
+/**
+ * Generate test data
+ */
+class MockDataSource implements Iterator {
+    private String tbNamePrefix;
+    private int tableCount;
+    private long maxRowsPerTable = 1000000000L;
+
+    // 100 milliseconds between two neighbouring rows.
+    long startMs = System.currentTimeMillis() - maxRowsPerTable * 100;
+    private int currentRow = 0;
+    private int currentTbId = -1;
+
+    // mock values
+    String[] location = {"California.LosAngeles", "California.SanDiego", "California.SanJose", "California.Campbell", "California.SanFrancisco"};
+    float[] current = {8.8f, 10.7f, 9.9f, 8.9f, 9.4f};
+    int[] voltage = {119, 116, 111, 113, 118};
+    float[] phase = {0.32f, 0.34f, 0.33f, 0.329f, 0.141f};
+
+    public MockDataSource(String tbNamePrefix, int tableCount) {
+        this.tbNamePrefix = tbNamePrefix;
+        this.tableCount = tableCount;
+    }
+
+    @Override
+    public boolean hasNext() {
+        currentTbId += 1;
+        if (currentTbId == tableCount) {
+            currentTbId = 0;
+            currentRow += 1;
+        }
+        return currentRow < maxRowsPerTable;
+    }
+
+    @Override
+    public String next() {
+        long ts = startMs + 100 * currentRow;
+        int groupId = currentTbId % 5 == 0 ? currentTbId / 5 : currentTbId / 5 + 1;
+        StringBuilder sb = new StringBuilder(tbNamePrefix + "_" + currentTbId + ","); // tbName
+        sb.append(ts).append(','); // ts
+        sb.append(current[currentRow % 5]).append(','); // current
+        sb.append(voltage[currentRow % 5]).append(','); // voltage
+        sb.append(phase[currentRow % 5]).append(','); // phase
+        sb.append(location[currentRow % 5]).append(','); // location
+        sb.append(groupId); // groupID
+
+        return sb.toString();
+    }
+}

+ 58 - 0
alarm-web/src/main/java/com/gyee/alarm/util/taos/ReadTask.java

@@ -0,0 +1,58 @@
+package com.gyee.alarm.util.taos;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+
+class ReadTask implements Runnable {
+    private final static Logger logger = LoggerFactory.getLogger(ReadTask.class);
+    private final int taskId;
+    private final List<BlockingQueue<String>> taskQueues;
+    private final int queueCount;
+    private final int tableCount;
+    private boolean active = true;
+
+    public ReadTask(int readTaskId, List<BlockingQueue<String>> queues, int tableCount) {
+        this.taskId = readTaskId;
+        this.taskQueues = queues;
+        this.queueCount = queues.size();
+        this.tableCount = tableCount;
+    }
+
+    /**
+     * Assign data received to different queues.
+     * Here we use the suffix number in table name.
+     * You are expected to define your own rule in practice.
+     *
+     * @param line record received
+     * @return which queue to use
+     */
+    public int getQueueId(String line) {
+        String tbName = line.substring(0, line.indexOf(',')); // For example: tb1_101
+        String suffixNumber = tbName.split("_")[1];
+        return Integer.parseInt(suffixNumber) % this.queueCount;
+    }
+
+    @Override
+    public void run() {
+        logger.info("started");
+        Iterator<String> it = new MockDataSource("tb" + this.taskId, tableCount);
+        try {
+            while (it.hasNext() && active) {
+                String line = it.next();
+                int queueId = getQueueId(line);
+                taskQueues.get(queueId).put(line);
+            }
+        } catch (Exception e) {
+            logger.error("Read Task Error", e);
+        }
+    }
+
+    public void stop() {
+        logger.info("stop");
+        this.active = false;
+    }
+}

+ 197 - 0
alarm-web/src/main/java/com/gyee/alarm/util/taos/SQLWriter.java

@@ -0,0 +1,197 @@
+package com.gyee.alarm.util.taos;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.sql.*;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A helper class encapsulate the logic of writing using SQL.
+ * <p>
+ * The main interfaces are two methods:
+ * <ol>
+ *     <li>{@link SQLWriter#processLine}, which receive raw lines from WriteTask and group them by table names.</li>
+ *     <li>{@link  SQLWriter#flush}, which assemble INSERT statement and execute it.</li>
+ * </ol>
+ * <p>
+ * There is a technical skill worth mentioning: we create table as needed when "table does not exist" error occur instead of creating table automatically using syntax "INSET INTO tb USING stb".
+ * This ensure that checking table existence is a one-time-only operation.
+ * </p>
+ *
+ * </p>
+ */
+public class SQLWriter {
+    final static Logger logger = LoggerFactory.getLogger(SQLWriter.class);
+
+    private Connection conn;
+    private Statement stmt;
+
+    /**
+     * current number of buffered records
+     */
+    private int bufferedCount = 0;
+    /**
+     * Maximum number of buffered records.
+     * Flush action will be triggered if bufferedCount reached this value,
+     */
+    private int maxBatchSize;
+
+
+    /**
+     * Maximum SQL length.
+     */
+    private int maxSQLLength = 800_000;
+
+    /**
+     * Map from table name to column values. For example:
+     * "tb001" -> "(1648432611249,2.1,114,0.09) (1648432611250,2.2,135,0.2)"
+     */
+    private Map<String, String> tbValues = new HashMap<>();
+
+    /**
+     * Map from table name to tag values in the same order as creating stable.
+     * Used for creating table.
+     */
+    private Map<String, String> tbTags = new HashMap<>();
+
+    public SQLWriter(int maxBatchSize) {
+        this.maxBatchSize = maxBatchSize;
+    }
+
+
+    /**
+     * Get Database Connection
+     *
+     * @return Connection
+     * @throws SQLException
+     */
+    private static Connection getConnection() throws SQLException {
+        String jdbcURL = "jdbc:TAOS://192.168.1.109:6030?user=root&password=taosdata";
+        return DriverManager.getConnection(jdbcURL);
+    }
+
+    /**
+     * Create Connection and Statement
+     *
+     * @throws SQLException
+     */
+    public void init() throws SQLException {
+        conn = getConnection();
+        stmt = conn.createStatement();
+        stmt.execute("use test");
+    }
+
+    /**
+     * Convert raw data to SQL fragments, group them by table name and cache them in a HashMap.
+     * Trigger writing when number of buffered records reached maxBachSize.
+     *
+     * @param line raw data get from task queue in format: tbName,ts,current,voltage,phase,location,groupId
+     */
+    public void processLine(String line) throws SQLException {
+        bufferedCount += 1;
+        int firstComma = line.indexOf(',');
+        String tbName = line.substring(0, firstComma);
+        int lastComma = line.lastIndexOf(',');
+        int secondLastComma = line.lastIndexOf(',', lastComma - 1);
+        String value = "(" + line.substring(firstComma + 1, secondLastComma) + ") ";
+        if (tbValues.containsKey(tbName)) {
+            tbValues.put(tbName, tbValues.get(tbName) + value);
+        } else {
+            tbValues.put(tbName, value);
+        }
+        if (!tbTags.containsKey(tbName)) {
+            String location = line.substring(secondLastComma + 1, lastComma);
+            String groupId = line.substring(lastComma + 1);
+            String tagValues = "('" + location + "'," + groupId + ')';
+            tbTags.put(tbName, tagValues);
+        }
+        if (bufferedCount == maxBatchSize) {
+            flush();
+        }
+    }
+
+
+    /**
+     * Assemble INSERT statement using buffered SQL fragments in Map {@link SQLWriter#tbValues} and execute it.
+     * In case of "Table does not exit" exception, create all tables in the sql and retry the sql.
+     */
+    public void flush() throws SQLException {
+        StringBuilder sb = new StringBuilder("INSERT INTO ");
+        for (Map.Entry<String, String> entry : tbValues.entrySet()) {
+            String tableName = entry.getKey();
+            String values = entry.getValue();
+            String q = tableName + " values " + values + " ";
+            if (sb.length() + q.length() > maxSQLLength) {
+                executeSQL(sb.toString());
+                logger.warn("increase maxSQLLength or decrease maxBatchSize to gain better performance");
+                sb = new StringBuilder("INSERT INTO ");
+            }
+            sb.append(q);
+        }
+        executeSQL(sb.toString());
+        tbValues.clear();
+        bufferedCount = 0;
+    }
+
+    private void executeSQL(String sql) throws SQLException {
+        try {
+            stmt.executeUpdate(sql);
+        } catch (SQLException e) {
+            // convert to error code defined in taoserror.h
+            int errorCode = e.getErrorCode() & 0xffff;
+            if (errorCode == 0x2603) {
+                // Table does not exist
+                createTables();
+                executeSQL(sql);
+            } else {
+                logger.error("Execute SQL: {}", sql);
+                throw e;
+            }
+        } catch (Throwable throwable) {
+            logger.error("Execute SQL: {}", sql);
+            throw throwable;
+        }
+    }
+
+    /**
+     * Create tables in batch using syntax:
+     * <p>
+     * CREATE TABLE [IF NOT EXISTS] tb_name1 USING stb_name TAGS (tag_value1, ...) [IF NOT EXISTS] tb_name2 USING stb_name TAGS (tag_value2, ...) ...;
+     * </p>
+     */
+    private void createTables() throws SQLException {
+        StringBuilder sb = new StringBuilder("CREATE TABLE ");
+        for (String tbName : tbValues.keySet()) {
+            String tagValues = tbTags.get(tbName);
+            sb.append("IF NOT EXISTS ").append(tbName).append(" USING meters TAGS ").append(tagValues).append(" ");
+        }
+        String sql = sb.toString();
+        try {
+            stmt.executeUpdate(sql);
+        } catch (Throwable throwable) {
+            logger.error("Execute SQL: {}", sql);
+            throw throwable;
+        }
+    }
+
+    public boolean hasBufferedValues() {
+        return bufferedCount > 0;
+    }
+
+    public int getBufferedCount() {
+        return bufferedCount;
+    }
+
+    public void close() {
+        try {
+            stmt.close();
+        } catch (SQLException e) {
+        }
+        try {
+            conn.close();
+        } catch (SQLException e) {
+        }
+    }
+}

+ 4 - 0
alarm-web/src/main/java/com/gyee/alarm/util/taos/StmtWriter.java

@@ -0,0 +1,4 @@
+package com.gyee.alarm.util.taos;
+
+public class StmtWriter {
+}

+ 58 - 0
alarm-web/src/main/java/com/gyee/alarm/util/taos/WriteTask.java

@@ -0,0 +1,58 @@
+package com.gyee.alarm.util.taos;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.BlockingQueue;
+
+class WriteTask implements Runnable {
+    private final static Logger logger = LoggerFactory.getLogger(WriteTask.class);
+    private final int maxBatchSize;
+
+    // the queue from which this writing task get raw data.
+    private final BlockingQueue<String> queue;
+
+    // A flag indicate whether to continue.
+    private boolean active = true;
+
+    public WriteTask(BlockingQueue<String> taskQueue, int maxBatchSize) {
+        this.queue = taskQueue;
+        this.maxBatchSize = maxBatchSize;
+    }
+
+    @Override
+    public void run() {
+        logger.info("started");
+        String line = null; // data getting from the queue just now.
+        SQLWriter writer = new SQLWriter(maxBatchSize);
+        try {
+            writer.init();
+            while (active) {
+                line = queue.poll();
+                if (line != null) {
+                    // parse raw data and buffer the data.
+                    writer.processLine(line);
+                } else if (writer.hasBufferedValues()) {
+                    // write data immediately if no more data in the queue
+                    writer.flush();
+                } else {
+                    // sleep a while to avoid high CPU usage if no more data in the queue and no buffered records, .
+                    Thread.sleep(100);
+                }
+            }
+            if (writer.hasBufferedValues()) {
+                writer.flush();
+            }
+        } catch (Exception e) {
+            String msg = String.format("line=%s, bufferedCount=%s", line, writer.getBufferedCount());
+            logger.error(msg, e);
+        } finally {
+            writer.close();
+        }
+    }
+
+    public void stop() {
+        logger.info("stop");
+        this.active = false;
+    }
+}