Browse Source

更新最新镜像配置, 更新当阳数据采集至influxdb实时数据机制

1037015548@qq.com 9 months ago
parent
commit
e46053caa0
24 changed files with 1895 additions and 21 deletions
  1. 4 2
      dc3-center/dc3-center-auth/src/main/resources/application-dev.yml
  2. 1 1
      dc3-center/dc3-center-data/src/main/resources/application-dev.yml
  3. 1 1
      dc3-center/dc3-center-manager/src/main/resources/application-dev.yml
  4. 12 0
      dc3-gateway/pom.xml
  5. 293 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/bizmgr/KprDangyangWaterBizFun.java
  6. 90 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/bizmgr/baseInit/KprBaseInitFun.java
  7. 137 13
      dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/ScheduleTaskMgr.java
  8. 42 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/ThreadPoolTaskTool.java
  9. 231 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/ThreadTask.java
  10. 10 3
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/DBMgrProxy.java
  11. 87 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/mapper/DeviceKindMapper.java
  12. 87 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/mapper/TypeDefineMapper.java
  13. 60 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/providers/DeviceKindProvider.java
  14. 60 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/providers/TypeDefineProvider.java
  15. 196 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/DeviceKindServiceImpl.java
  16. 196 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/TypeDefineServiceImpl.java
  17. 27 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/intef/DeviceKindService.java
  18. 27 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/intef/TypeDefineService.java
  19. 20 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/tables/DeviceKindTable.java
  20. 20 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/tables/TypeDefineTable.java
  21. 102 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/utils/HttpUtil.java
  22. 62 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/utils/InfulxDbUtil.java
  23. 70 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/utils/TestUtil.java
  24. 60 1
      dc3-gateway/src/main/resources/application.yml

+ 4 - 2
dc3-center/dc3-center-auth/src/main/resources/application-dev.yml

@@ -22,7 +22,7 @@ spring:
     dynamic:
       datasource:
         master:
-          url: jdbc:mysql://${DB_HOST:dc3-mysql}:${MYSQL_PORT:33306}/${DB_NAME:dc3}?allowPublicKeyRetrieval=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
+          url: jdbc:mysql://${DB_HOST:dc3-mysql}:${MYSQL_PORT:33306}/${DB_NAME:dc3_auth}?allowPublicKeyRetrieval=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
           username: ${DB_USERNAME:root}
           password: ${DB_PASSWORD:dc3}
   redis:
@@ -38,4 +38,6 @@ spring:
         group: ${spring.group}
         watch-delay: 5000
         username: dc3
-        password: dc3
+        password: dc3
+        #服务器配置
+        server-addr: 127.0.0.1:8849

+ 1 - 1
dc3-center/dc3-center-data/src/main/resources/application-dev.yml

@@ -22,7 +22,7 @@ spring:
     dynamic:
       datasource:
         master:
-          url: jdbc:mysql://${DB_HOST:dc3-mysql}:${MYSQL_PORT:33306}/${DB_NAME:dc3}?allowPublicKeyRetrieval=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
+          url: jdbc:mysql://${DB_HOST:dc3-mysql}:${MYSQL_PORT:33306}/${DB_NAME:dc3_data}?allowPublicKeyRetrieval=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
           username: ${DB_USERNAME:root}
           password: ${DB_PASSWORD:dc3}
   rabbitmq:

+ 1 - 1
dc3-center/dc3-center-manager/src/main/resources/application-dev.yml

@@ -22,7 +22,7 @@ spring:
     dynamic:
       datasource:
         master:
-          url: jdbc:mysql://${DB_HOST:dc3-mysql}:${MYSQL_PORT:33306}/${DB_NAME:dc3}?allowPublicKeyRetrieval=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
+          url: jdbc:mysql://${DB_HOST:dc3-mysql}:${MYSQL_PORT:33306}/${DB_NAME:dc3_manager}?allowPublicKeyRetrieval=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
           username: ${DB_USERNAME:root}
           password: ${DB_PASSWORD:dc3}
   rabbitmq:

+ 12 - 0
dc3-gateway/pom.xml

@@ -164,6 +164,18 @@
             <version>2.5.0</version>
         </dependency>
 
+        <dependency>
+            <groupId>org.influxdb</groupId>
+            <artifactId>influxdb-java</artifactId>
+            <version>2.21</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+            <version>5.2.3</version>
+        </dependency>
+
     </dependencies>
 
     <repositories>

+ 293 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/bizmgr/KprDangyangWaterBizFun.java

@@ -0,0 +1,293 @@
+package io.github.pnoker.gateway.bizmgr;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.TypeReference;
+import io.github.pnoker.gateway.comtool.ThreadPoolTaskTool;
+import io.github.pnoker.gateway.comtool.ThreadTask;
+import io.github.pnoker.gateway.comtool.TimeTool;
+import io.github.pnoker.gateway.dbdao.DBMgrProxy;
+import io.github.pnoker.gateway.dbdao.services.intef.DeviceKindService;
+import io.github.pnoker.gateway.dbdao.services.intef.TypeDefineService;
+import io.github.pnoker.gateway.utils.HttpUtil;
+import io.github.pnoker.gateway.utils.InfulxDbUtil;
+import org.apache.http.client.methods.HttpPatch;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.influxdb.dto.Point;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
+import org.springframework.util.ObjectUtils;
+import org.springframework.util.StringUtils;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.*;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+/**
+ * @ClassName KprDangyangWaterBizFun
+ * @Description: TODO 当阳数据采集
+ * @Author LX
+ * @Date 2024/9/3
+ * @Version V1.0
+ **/
+public class KprDangyangWaterBizFun {
+
+    private static final Logger log = LoggerFactory.getLogger(KprDangyangWaterBizFun.class);
+
+    private final static String mStrClassName = "KprDangyangWaterBizFun";
+    private final static String EMPTY_NULL = "NULL";
+
+    //TODO 每隔一段时间刷新集合值
+    public static List<Map<String,Object>> deviceKindList = new ArrayList<>();//设备类型字典
+    public static List<Map<String,Object>> typeDefineList = new ArrayList<>();//设备类型详细字典
+
+    public static DeviceKindService deviceKindService(){
+        return DBMgrProxy.getInstance().applyDeviceKineApi();
+    }
+
+    public static TypeDefineService typeDefineService(){
+        return DBMgrProxy.getInstance().applyTypeDefineApi();
+    }
+
+    public static String dangyangToken = null;//调用数据接口token
+
+    public static InfulxDbUtil infulxDbUtil = null;//infulx工具类对象
+    public static JSONArray deviceType = null;//设备类型集合
+    public static String username = null;//token调用账号
+    public static String password = null;//token调用密码
+    public static String tokenUrl = null;//token接口地址
+    public static String realtimeDataListUrl = null;//实时数据接口地址
+    public static String hisDataListUrl = null;//历史数据接口地址
+    public static String listUrl = null;//设备列表接口地址
+
+    private static boolean checkApplicationParam(){
+        if(deviceType==null||infulxDbUtil==null|| StringUtils.isEmpty(dangyangToken)
+                || StringUtils.isEmpty(realtimeDataListUrl)
+                || StringUtils.isEmpty(hisDataListUrl)
+                || StringUtils.isEmpty(listUrl)
+                || StringUtils.isEmpty(tokenUrl)
+                || StringUtils.isEmpty(username)
+                || StringUtils.isEmpty(password)){
+            return false;
+        }else{
+            return true;
+        }
+    }
+
+    //TODO 刷新获取字典信息
+    public static void flushDefine(){
+        deviceKindList = deviceKindService().batchQueryWithsEx("","",new HashMap<>(),new HashMap<>(),
+                "","");
+
+        Map<String,Object> andWhere = new HashMap<>();
+        andWhere.put("kind",0);
+        typeDefineList = typeDefineService().batchQueryWithsEx("","",andWhere,new HashMap<>()
+                ,"","");
+    }
+
+    //TODO 获取token
+    public static JSONObject getDangyangToken(){
+        try {
+            Map<String, String> headers = new HashMap<>();
+            headers.put("Content-type", "application/json");
+            headers.put("Tenant-Id", "1");
+            JSONObject paramObj = new JSONObject();
+            paramObj.put("username",username);
+            paramObj.put("password",password);
+            String tokenStr = HttpUtil.sendPost(tokenUrl,paramObj.toJSONString(), headers);
+            JSONObject resObj = JSONObject.parseObject(tokenStr);
+            if(resObj!=null&&(resObj.getInteger("code")==0)){
+                return resObj.getJSONObject("data");
+            }else{
+                log.error("调用设备列表失败:"+tokenStr);
+                return null;
+            }
+        }catch(Exception ex){
+            log.error("获取token数据异常:"+ex.getLocalizedMessage());
+            return null;
+        }
+    }
+
+    //TODO 获取实时数据
+    /**
+     * ①首先查询所有的设备列表
+     * ②以列表数据为基准查询实时数据和历史数据
+     * @param
+     */
+    public static void checkRealtimeData(){
+        try{
+            if(!checkApplicationParam()){
+                log.error("获取配置参数错误");
+                return;
+            }
+            Map<String, String> headers = new HashMap<>();
+            headers.put("Authorization", "Bearer "+dangyangToken);
+            for (int i = 0; i <deviceType.size(); i++) {
+                List<Map<String,Object>> totalList = new ArrayList<>();//当前类型设备列表总集
+                //TODO 外层循环是要查一个类型的所有设备列表
+                JSONObject itemType = deviceType.getJSONObject(i);
+
+                Map<String,String> paramsTotal = new HashMap<>();
+                paramsTotal.put("pageNo","1");
+                paramsTotal.put("pageSize","1");
+                paramsTotal.put("deviceType",itemType.getString("key"));
+
+                JSONObject totalRes = JSONObject.parseObject(HttpUtil.sendGet(
+                        listUrl,paramsTotal,headers));
+                if(totalRes!=null&&totalRes.getInteger("code")==0&&!totalRes.getJSONObject("data").getJSONArray("list").isEmpty()) {
+                    //TODO 优化 以分页方式查询所有,初始分页行数定为200查询速率较好
+                    int nTotals = totalRes.getJSONObject("data").getInteger("total");
+                    int pageNum = nTotals % 200 == 0 ? nTotals / 200 : (nTotals / 200) + 1;//总页数
+                    Integer limit = 200;
+                    if (pageNum <= 1) {
+                        limit = nTotals;//说明总数比第一页小
+                    }
+                    for (int k = 1; k <= pageNum; k++) {
+                        Map<String,String> paramsPage = new HashMap<>();
+                        paramsPage.put("pageNo",String.valueOf(k));
+                        paramsPage.put("pageSize",String.valueOf(limit));
+                        paramsPage.put("deviceType",itemType.getString("key"));
+                        JSONObject pageRes = JSONObject.parseObject(HttpUtil.sendGet(
+                                listUrl,paramsPage,headers));
+                        if(pageRes!=null&&pageRes.getInteger("code")==0&&!pageRes.getJSONObject("data").getJSONArray("list").isEmpty()){
+                            //TODO 将分页获取的列表数据添加至总集中
+                            totalList.addAll(JSON.parseObject(pageRes.getJSONObject("data").getJSONArray("list").toJSONString()
+                                    , new TypeReference<List<Map<String, Object>>>(){}));
+                        }else{
+                            log.error(TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT)
+                                    +"获取设备列表失败:"+itemType.getString("key")+";"+(pageRes==null?null:pageRes.toJSONString())
+                            +";param:"+ JSON.toJSONString(paramsPage));
+                        }
+                    }
+
+                    //TODO 放入定时线程执行设备数据备份
+                    new Timer().schedule(new TimerTask() {
+                        @Override
+                        public void run() {
+                            createExcel(itemType.getString("key"), totalList);
+                        }
+                    }, 5000);
+
+                    //TODO 获取到当前类型的设备列表总集后,查询总集的实时数据,并添加到infulxdb
+                    // 根据 采集频率 collectionFrequency (秒)字段进行分组
+                    // 要根据采集频率取建立定时任务
+                    Map<Integer, List<Map<String, Object>>> groupedByFrequency = totalList.stream()
+                            .collect(Collectors.groupingBy(map -> (Integer) map.get("collectionFrequency")));
+                    //TODO 创建任务池
+                    ThreadPoolTaskScheduler scheduler = ThreadPoolTaskTool.createTaskScheduler(groupedByFrequency.keySet().size(),
+                            "schedule_dangyang_"+itemType.getString("key"));
+                    for (Integer groupKey:groupedByFrequency.keySet()){
+                        String taskId = itemType.getString("key")+"_"+groupKey;
+                        //TODO 任务时间间隔/分 = 采集频率(秒)/60
+                        Integer fc = groupKey;
+                        if(groupKey<60){
+                            fc = 60;
+                        }
+                        Integer taskTime = fc/60;
+
+                        ThreadTask threadTask = new ThreadTask(taskId,taskTime
+                        ,itemType.getString("key"),groupedByFrequency.get(groupKey));
+                        ThreadPoolTaskTool.scheduleCronTask(scheduler,taskId,threadTask,"0 */"+taskTime+" * * * ?");
+                    }
+                }else{
+                    log.error(TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT)
+                            +"获取设备列表总数失败:"+itemType.getString("key")+";"+(totalRes==null?null:totalRes.toJSONString())
+                            +";param:"+ JSON.toJSONString(paramsTotal));
+                }
+            }
+        }catch(Exception ex){
+            log.error(TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT)
+                    +"获取实时数据异常:"+ex.getLocalizedMessage());
+        }
+    }
+
+    public static void createExcel(String deviceType,List<Map<String,Object>> totalList){
+        // 创建一个新的工作簿
+        Workbook workbook = new XSSFWorkbook();
+
+        // 创建一个新的工作表
+        Sheet sheet = workbook.createSheet(deviceType);
+
+
+            //创建行头
+            Row headerRow = sheet.createRow(0);
+            Cell cell = headerRow.createCell(0);
+            cell.setCellValue("设备类型");
+            Cell cell1 = headerRow.createCell(1);
+            cell1.setCellValue("设备编号");
+            Cell cell2 = headerRow.createCell(2);
+            cell2.setCellValue("设备名称");
+            Cell cell3 = headerRow.createCell(3);
+            cell3.setCellValue("水厂名称");
+            Cell cell4 = headerRow.createCell(4);
+            cell4.setCellValue("是否启动");
+            Cell cell5 = headerRow.createCell(5);
+            cell5.setCellValue("经度");
+            Cell cell6 = headerRow.createCell(6);
+            cell6.setCellValue("纬度");
+            Cell cell7 = headerRow.createCell(7);
+            cell7.setCellValue("采集频率/秒");
+
+
+        int k = 1;
+        for (Map<String,Object> map:totalList) {
+            Row row = sheet.createRow((k));
+            //创建行内容
+            Cell cellData = row.createCell(0);
+            cellData.setCellValue(String.valueOf(map.get("deviceType")));
+            Cell cellData1 = row.createCell(1);
+            cellData1.setCellValue(String.valueOf(map.get("deviceCode")));
+            Cell cellData2 = row.createCell(2);
+            cellData2.setCellValue(String.valueOf(map.get("deviceName")));
+            Cell cellData3 = row.createCell(3);
+            cellData3.setCellValue(String.valueOf(map.get("waterworks")));
+            Cell cellData4 = row.createCell(4);
+            cellData4.setCellValue(String.valueOf(map.get("enableFlag")));
+            Cell cellData5 = row.createCell(5);
+            cellData5.setCellValue(String.valueOf(map.get("longitude")));
+            Cell cellData6 = row.createCell(6);
+            cellData6.setCellValue(String.valueOf(map.get("latitude")));
+            Cell cellData7 = row.createCell(7);
+            cellData7.setCellValue(String.valueOf(map.get("collectionFrequency")));
+
+//// 填充数据
+//            Object[][] data = {
+//                    {1, "John Doe", 30},
+//                    {2, "Jane Smith", 25},
+//                    {3, "Mike Brown", 35}
+//            };
+
+            // 自动调整列宽
+            for (int h = 0; h < map.keySet().size(); h++) {
+                sheet.autoSizeColumn(h);
+            }
+
+            k++;
+        }
+
+        // 将工作簿写入文件
+        try (FileOutputStream fileOut = new FileOutputStream("./"+deviceType+".xlsx")) {
+            workbook.write(fileOut);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        // 关闭工作簿
+        try {
+            workbook.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        System.out.println("Excel file generated successfully!");
+    }
+}

+ 90 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/bizmgr/baseInit/KprBaseInitFun.java

@@ -0,0 +1,90 @@
+package io.github.pnoker.gateway.bizmgr.baseInit;
+
+import io.github.pnoker.gateway.dbdao.DBMgrProxy;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.*;
+
+/**
+ * @ClassName KprBaseInitFun
+ * @Description: TODO ,专门用于获取配置文件内容的工具类
+ * @Author LX
+ * @Date 2024/9/4
+ * @Version V1.0
+ **/
+public class KprBaseInitFun {
+
+    //TODO 当阳相关
+    public Map<String,List<String>> dangyangParams = new HashMap<>();
+
+    public Map<String,String> measurementMap = new HashMap<>();
+
+    private static volatile KprBaseInitFun msInstance = null;
+    public static KprBaseInitFun getInstance(){
+        if (msInstance == null){
+            synchronized (DBMgrProxy.class){
+                if (msInstance == null)
+                    msInstance = new KprBaseInitFun();
+            }
+        }
+        return msInstance;
+    }
+
+    public KprBaseInitFun(){
+        init();
+    }
+
+    public void init(){
+        try {
+            InputStream inputStream = getConfigStream("application.yml");
+            Properties properties = new Properties();
+            properties.load(inputStream);
+            List<String> WATER_METER= Arrays.asList(properties.getProperty("watermeter").split(","));
+            List<String> FLOW_METER=Arrays.asList(properties.getProperty("flowmeter").split(","));
+            List<String> PRESS_METER=Arrays.asList(properties.getProperty("pressmeter").split(","));
+            List<String> WATER_QUALITY=Arrays.asList(properties.getProperty("waterquality").split(","));
+            List<String> WATER_PUMP=Arrays.asList(properties.getProperty("waterpump").split(","));
+            List<String> ELEC_CTRL_VALVE=Arrays.asList(properties.getProperty("elecctrlvalve").split(","));
+            List<String> LIQUID_LEVEL_METER=Arrays.asList(properties.getProperty("liquidlevelmeter").split(","));
+
+            dangyangParams.put("WATER_METER",WATER_METER);
+            dangyangParams.put("FLOW_METER",FLOW_METER);
+            dangyangParams.put("PRESS_METER",PRESS_METER);
+            dangyangParams.put("WATER_QUALITY",WATER_QUALITY);
+            dangyangParams.put("WATER_PUMP",WATER_PUMP);
+            dangyangParams.put("ELEC_CTRL_VALVE",ELEC_CTRL_VALVE);
+            dangyangParams.put("LIQUID_LEVEL_METER",LIQUID_LEVEL_METER);
+
+            measurementMap.put("WATER_METER",properties.getProperty("WATER_METER"));
+            measurementMap.put("FLOW_METER",properties.getProperty("FLOW_METER"));
+            measurementMap.put("PRESS_METER",properties.getProperty("PRESS_METER"));
+            measurementMap.put("WATER_QUALITY",properties.getProperty("WATER_QUALITY"));
+            measurementMap.put("WATER_PUMP",properties.getProperty("WATER_PUMP"));
+            measurementMap.put("ELEC_CTRL_VALVE",properties.getProperty("ELEC_CTRL_VALVE"));
+            measurementMap.put("LIQUID_LEVEL_METER",properties.getProperty("LIQUID_LEVEL_METER"));
+        }catch(Exception ex){
+            ex.printStackTrace();
+        }
+    }
+
+    public InputStream getConfigStream(String configFileName) {
+        InputStream inputStream = null;
+        try {
+            File configFile = new File(configFileName);
+            inputStream = new FileInputStream(configFile);
+            if (inputStream == null) {
+                // 尝试从 JAR 文件类目录加载
+                inputStream = getClass().getClassLoader().getResourceAsStream(configFileName);
+            }
+        } catch (FileNotFoundException e) {
+            // 处理异常,例如打印日志或退出程序
+            try {
+                inputStream = getClass().getClassLoader().getResourceAsStream(configFileName);
+            }catch(Exception ex){}
+        }
+        return inputStream;
+    }
+}

+ 137 - 13
dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/ScheduleTaskMgr.java

@@ -1,6 +1,13 @@
 package io.github.pnoker.gateway.comtool;
 
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import io.github.pnoker.gateway.bizmgr.KprDangyangWaterBizFun;
 import io.github.pnoker.gateway.dbdao.DBMgrProxy;
+import io.github.pnoker.gateway.utils.InfulxDbUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.scheduling.annotation.EnableAsync;
 import org.springframework.scheduling.annotation.EnableScheduling;
 import org.springframework.scheduling.annotation.Scheduled;
@@ -12,6 +19,9 @@ import javax.annotation.Resource;
 import java.sql.Time;
 import java.util.Timer;
 import java.util.TimerTask;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
 
 /**
  * @ClassName ScheduleTaskMgr
@@ -30,30 +40,144 @@ public class ScheduleTaskMgr {
         mStrClassName = this.getClass().getSimpleName();
     }
 
+    private static final Logger log = LoggerFactory.getLogger(ScheduleTaskMgr.class);
+
     @Resource
     private XuchangWaterConfig xuchangWaterConfig;
 
-    //TODO 启动时,判断当前是否超过两点  如果超过 ,查询昨日是否有数据插入, 如果没有,则在启动时执行一下xuchangWaterConfig.init()
+    /**
+     * 许昌相关
+     */
+
+//    //TODO 启动时,判断当前是否超过两点  如果超过 ,查询昨日是否有数据插入, 如果没有,则在启动时执行一下xuchangWaterConfig.init()
+//    @PostConstruct
+//    public void postInit(){
+//        new Timer().schedule(new TimerTask() {
+//            @Override
+//            public void run() {
+//                DBMgrProxy.getInstance().init();
+//            }
+//        },3000);
+//        new Timer().schedule(new TimerTask() {
+//                @Override
+//                public void run() {
+//                    xuchangWaterConfig.init();
+//                }
+//            },10000);
+//    }
+//
+//
+//    //    @Scheduled(cron = "0 15 10 * * ?")
+//    @Scheduled(cron = "0 10 12 * * ?")
+//    public void checkXuchangMeter(){
+//        xuchangWaterConfig.init();
+//    }
+
+    //TODO 当阳相关
+
+    @Resource(name = "infulxDbUtil")
+    private InfulxDbUtil infulxDbUtil;
+
+    @Value("${dangyang.device.type:}")
+    private String deviceTypeStr = ""; // 设备类型集合
+    @Value("${dangyang.http.username:}")
+    private String username = ""; // token调用账号
+    @Value("${dangyang.http.password:}")
+    private String password = ""; // token调用密码
+    @Value("${dangyang.http.token:}")
+    private String tokenUrl = ""; // token接口地址
+    @Value("${dangyang.http.realtimeDataList:}")
+    private String realtimeDataListUrl = ""; // 实时数据接口地址
+    @Value("${dangyang.http.hisDataList:}")
+    private String hisDataListUrl = ""; // 历史数据接口地址
+    @Value("${dangyang.http.list:}")
+    private String listUrl = ""; // 设备列表接口地址
+
+
+    /**
+     *  当阳相关
+     */
+    //TODO 启动后5秒初始化所有配置参数
     @PostConstruct
-    public void postInit(){
+    public void initDangyangApplication(){
         new Timer().schedule(new TimerTask() {
             @Override
             public void run() {
-                DBMgrProxy.getInstance().init();
+                try {
+                    KprDangyangWaterBizFun.infulxDbUtil = infulxDbUtil;
+                    KprDangyangWaterBizFun.deviceType = JSONArray.parseArray(deviceTypeStr);
+                    KprDangyangWaterBizFun.username = username;
+                    KprDangyangWaterBizFun.password = password;
+                    KprDangyangWaterBizFun.tokenUrl = tokenUrl;
+                    KprDangyangWaterBizFun.realtimeDataListUrl = realtimeDataListUrl;
+                    KprDangyangWaterBizFun.hisDataListUrl = hisDataListUrl;
+                    KprDangyangWaterBizFun.listUrl = listUrl;
+                }catch(Exception ex){
+                    log.error("当阳启动时初始化配置参数失败:"+ex.getLocalizedMessage());
+                }
             }
-        },3000);
-        new Timer().schedule(new TimerTask() {
-                @Override
-                public void run() {
-                    xuchangWaterConfig.init();
+        },5000);
+    }
+
+    //TODO 根据失效时间定时获取token
+    //TODO 启动后8秒获取第一次token,在以失效时间为基础-5分钟为下一次获取token的条件
+    private ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
+    private static final long INITIAL_DELAY = 8; // 初始延迟8秒
+    private static final long BUFFER_TIME = 5 * 60 * 1000; // 5分钟的缓冲时间(以毫秒为单位)
+
+    @PostConstruct
+    public void getToken() {
+        scheduler.schedule(new TokenTask(), INITIAL_DELAY, TimeUnit.SECONDS);
+    }
+
+    private class TokenTask implements Runnable {
+        @Override
+        public void run() {
+            // 获取 accessToken 和 expiresTime
+            JSONObject data = KprDangyangWaterBizFun.getDangyangToken();
+            if (data != null) {
+                String accessToken = data.getString("accessToken");
+                Long expiresTime = data.getLong("expiresTime");
+
+                KprDangyangWaterBizFun.dangyangToken = accessToken;
+
+                // 打印获取到的 token 和过期时间
+                System.out.println("Access Token: " + accessToken);
+                System.out.println("Expires Time: " + expiresTime);
+
+                // 计算下一次获取 token 的延迟时间
+                long delayMillis = expiresTime - System.currentTimeMillis() - BUFFER_TIME;
+                long delaySeconds = delayMillis / 1000; // 转换为秒
+
+                // 调度下一次任务
+                if (delaySeconds > 0) {
+                    scheduler.schedule(this, delaySeconds, TimeUnit.SECONDS);
+                } else {
+                    // 如果计算出来的延迟时间已经过期,立即执行下一次任务
+                    scheduler.schedule(this, 0, TimeUnit.SECONDS);
                 }
-            },10000);
+            }
+        }
     }
 
+    //可以做动态关联,暂时不用了
+//    @PostConstruct
+//    public void initDeviceDefine(){
+//        new Timer().schedule(new TimerTask() {
+//            @Override
+//            public void run() {
+//                KprDangyangWaterBizFun.flushDefine();
+//            }
+//        },5000);
+//    }
 
-    //    @Scheduled(cron = "0 15 10 * * ?")
-    @Scheduled(cron = "0 10 12 * * ?")
-    public void checkXuchangMeter(){
-        xuchangWaterConfig.init();
+    @PostConstruct
+    public void initTest(){
+        new Timer().schedule(new TimerTask() {
+            @Override
+            public void run() {
+                KprDangyangWaterBizFun.checkRealtimeData();
+            }
+        },10000);
     }
 }

+ 42 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/ThreadPoolTaskTool.java

@@ -0,0 +1,42 @@
+package io.github.pnoker.gateway.comtool;
+
+import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
+import org.springframework.scheduling.support.CronTrigger;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ScheduledFuture;
+
+/**
+ * @ClassName ThreadPoolTaskTool
+ * @Description: TODO 任务池
+ * @Author LX
+ * @Date 2024/9/3
+ * @Version V1.0
+ **/
+public class ThreadPoolTaskTool {
+    public static Map<String, ScheduledFuture<?>> scheduledTasks = new ConcurrentHashMap<>();//全局唯一
+
+
+    //TODO 创建任务池
+    /**
+     *
+     * @param poolSize 任务池大小
+     * @param threadNamePrefix 任务名前缀
+     * @return
+     */
+    public static ThreadPoolTaskScheduler createTaskScheduler(int poolSize,String threadNamePrefix) {
+        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
+        scheduler.setPoolSize(poolSize);
+        scheduler.setThreadNamePrefix(threadNamePrefix);
+        scheduler.initialize();
+        return scheduler;
+    }
+
+    //TODO 根据corn表达式执行指定任务池的任务
+    public static void scheduleCronTask(ThreadPoolTaskScheduler taskScheduler,String taskId,ThreadTask threadTask,String cronExpression) {
+        CronTrigger cronTrigger = new CronTrigger(cronExpression);
+        ScheduledFuture<?> future = taskScheduler.schedule(threadTask, cronTrigger);
+        scheduledTasks.put(taskId, future);
+    }
+}

+ 231 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/ThreadTask.java

@@ -0,0 +1,231 @@
+package io.github.pnoker.gateway.comtool;
+
+import com.alibaba.fastjson.JSONObject;
+import io.github.pnoker.gateway.bizmgr.KprDangyangWaterBizFun;
+import io.github.pnoker.gateway.bizmgr.baseInit.KprBaseInitFun;
+import io.github.pnoker.gateway.dbdao.DBMgrProxy;
+import io.github.pnoker.gateway.dbdao.services.intef.DeviceKindService;
+import io.github.pnoker.gateway.dbdao.services.intef.TypeDefineService;
+import io.github.pnoker.gateway.utils.HttpUtil;
+import org.influxdb.dto.Point;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.ObjectUtils;
+
+import java.math.BigDecimal;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.*;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+/**
+ * @ClassName ThreadTask
+ * @Description: TODO 当阳任务线程
+ * @Author LX
+ * @Date 2024/9/3
+ * @Version V1.0
+ **/
+public class ThreadTask implements Runnable{
+    private static final Logger log = LoggerFactory.getLogger(ThreadTask.class);
+
+    private final String taskId;
+
+    private final Integer collectionFrequency;//采集频率
+
+    private String deviceType;
+
+    private List<Map<String,Object>> deviceList = new ArrayList<>();
+
+
+
+    public ThreadTask(String taskId,Integer collectionFrequency,String deviceType,List<Map<String,Object>> deviceList) {
+        this.taskId = taskId;
+        this.collectionFrequency = collectionFrequency;
+        this.deviceType = deviceType;
+        this.deviceList = deviceList;
+    }
+
+    @Override
+    public void run() {
+        try {
+            List<JSONObject> deviceRealtimeDataList = new ArrayList<>();
+            for (Map<String, Object> map : deviceList) {
+                JSONObject devicerealtimeDataTotal = null;
+                try {
+
+                    Map<String, String> paramRealtime = new HashMap<>();
+                    paramRealtime.put("deviceType", deviceType);
+                    paramRealtime.put("deviceCode", String.valueOf(map.get("deviceCode")));
+                    Map<String, String> headers = new HashMap<>();
+                    headers.put("Authorization", "Bearer " + KprDangyangWaterBizFun.dangyangToken);
+                    devicerealtimeDataTotal = JSONObject.parseObject(HttpUtil.sendGet(
+                            KprDangyangWaterBizFun.realtimeDataListUrl, paramRealtime, headers));
+                } catch (Exception ex) {
+                    log.error("任务线程" + taskId + " 调用异常:" + ex.getLocalizedMessage());
+                }
+                try {
+                    if (devicerealtimeDataTotal != null && devicerealtimeDataTotal.getInteger("code") == 0 &&
+                            devicerealtimeDataTotal.getJSONObject("data") != null
+                            && devicerealtimeDataTotal.getJSONObject("data").getJSONArray("list") != null
+                            && !devicerealtimeDataTotal.getJSONObject("data").getJSONArray("list").isEmpty()) {
+                        //TODO 查询数据不为空,插入infulxdb
+                        JSONObject deviceRealtimeData = devicerealtimeDataTotal.getJSONObject("data")
+                                .getJSONArray("list").getJSONObject(0);
+                        adjustTime(deviceRealtimeData, collectionFrequency);//整点rand处理
+                        deviceRealtimeDataList.add(deviceRealtimeData);
+                    } else {
+                        log.error("任务线程" + taskId + " 执行设备"
+                                + String.valueOf(map.get("deviceCode")) +
+                                "失败:" + (devicerealtimeDataTotal == null ?
+                                null : devicerealtimeDataTotal.toJSONString()));
+                    }
+                } catch (Exception ex) {
+                    log.error("任务线程" + taskId + " " + String.valueOf(map.get("deviceCode")) + "查询异常:" + ex.getLocalizedMessage() + ";resJson:" + devicerealtimeDataTotal.toJSONString());
+                }
+            }
+            //TODO 开始插入数据库
+            //第三方对应的字段集
+            List<String> params = KprBaseInitFun.getInstance().dangyangParams.get(deviceType);
+            for(JSONObject jsonObject : deviceRealtimeDataList){
+                //deviceType为表名
+                //time为当前数据time的纳秒时间戳,已经做过整点处理了
+                Point pointNanos = createPointFromJson(deviceType,jsonObject,params);
+                KprDangyangWaterBizFun.infulxDbUtil.insert(pointNanos);
+            }
+
+        }catch(Exception ex){
+            ex.printStackTrace();
+        }
+    }
+
+    public static Point createPointFromJson(String deviceType, JSONObject jsonObject,List<String> params) {
+        // 获取时间戳
+        long nanoTimestamp = convertToNanoTimestamp(jsonObject.getString("time"));
+
+        // 创建 Point.Builder 对象
+        Point.Builder pointBuilder = Point.measurement(KprBaseInitFun.getInstance().measurementMap.get(deviceType))
+                .tag("dev_id",jsonObject.getString("deviceCode"))
+                .time(nanoTimestamp, TimeUnit.NANOSECONDS);
+
+        // 遍历 JSON 对象的键值对,并添加到 Point.Builder 中
+        for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
+            String key = entry.getKey();
+            if (!key.equals("time")&&!key.equals("deviceCode")) {
+                processField(pointBuilder,key, entry.getValue(),params);
+            }
+        }
+
+        // 构建 Point 对象
+        try {
+            return pointBuilder.build();
+        }catch(Exception ex){
+
+        }
+        return null;
+    }
+
+    //指定列处理
+    private static void processField(Point.Builder pointBuilder, String key, Object value,List<String> params) {
+        if (value == null) {
+            return; // 跳过空值
+        }
+        //String[]长度如果为0,则说明本系统没有对应字段,则用它本身,反之用第二个元素作为字段名
+        List<String[]> newParams = params.stream()
+                .map(s -> s.split("___"))
+                .collect(Collectors.toList());
+
+        for (String[] clies:newParams){
+            boolean exists = Arrays.asList(clies).contains(key);
+            if(exists){
+                String newKey = clies.length>1?clies[1]:clies[0];
+                if (value instanceof Integer) {
+                    pointBuilder.addField(newKey, (Integer) value);
+                } else if (value instanceof Long) {
+                    pointBuilder.addField(newKey, (Long) value);
+                } else if (value instanceof Boolean) {
+                    pointBuilder.addField(newKey, (Boolean) value);
+                } else if (value instanceof String) {
+                    pointBuilder.addField(newKey, (String) value);
+                }else if (value instanceof BigDecimal) {
+                    pointBuilder.addField(newKey, ((BigDecimal) value).doubleValue());
+                }else{
+                    pointBuilder.addField(newKey, (String.valueOf(value)) );
+                }
+                break;
+            }
+        }
+
+//        switch (key) {
+//            case "flow":
+//                    pointBuilder.addField("flow_cur", ((BigDecimal) value).doubleValue());
+//                break;
+//            default:
+//                if (value instanceof Integer) {
+//                    pointBuilder.addField(key, (Integer) value);
+//                } else if (value instanceof Long) {
+//                    pointBuilder.addField(key, (Long) value);
+//                } else if (value instanceof Boolean) {
+//                    pointBuilder.addField(key, (Boolean) value);
+//                } else if (value instanceof String) {
+//                    pointBuilder.addField(key, (String) value);
+//                }else if (value instanceof BigDecimal) {
+//                    pointBuilder.addField(key, ((BigDecimal) value).doubleValue());
+//                }
+//                else {
+////                    System.err.println("Unsupported data type for key " + key + ": " + value.getClass().getName());
+//                }
+//                break;
+//        }
+    }
+
+
+    //获取CST 纳秒时间戳
+    private static long convertToNanoTimestamp(String dateTimeString) {
+        // 定义日期时间格式
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        // 解析字符串为 LocalDateTime 对象
+        LocalDateTime dateTime = LocalDateTime.parse(dateTimeString, formatter);
+        // 指定时区为CST(Asia/Shanghai)
+        ZoneId shanghaiZoneId = ZoneId.of("Asia/Shanghai");
+        // 将LocalDateTime对象转换为ZonedDateTime对象
+        ZonedDateTime zonedDateTime = dateTime.atZone(shanghaiZoneId);
+        // 转换为秒级别的时间戳
+        long epochSecond = dateTime.toEpochSecond(ZoneOffset.UTC);
+        // 将ZonedDateTime对象转换为Instant对象(UTC时间点)
+        Instant instant = zonedDateTime.toInstant();
+        // 计算从1970年1月1日00:00:00 UTC以来的纳秒数
+        long nanosecondsSinceEpoch = ChronoUnit.NANOS.between(Instant.EPOCH, instant);
+        return nanosecondsSinceEpoch;
+    }
+
+    private static final SimpleDateFormat outputDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+    public static void adjustTime(JSONObject jsonObject, int collectionFrequency) throws ParseException {
+        String timeStr = jsonObject.getString("time");
+        Long oriLong =  TimeTool.convertDateStr2UTC(timeStr);
+        Date originalDate = new Date(oriLong);
+
+        // 计算最近的整分钟时间
+        Date roundedDate = getNearestTime(originalDate, collectionFrequency);
+
+        // 格式化回字符串
+        String adjustedTimeStr = outputDateFormat.format(roundedDate);
+
+        // 更新 JSON 对象中的时间
+        jsonObject.put("time", adjustedTimeStr);
+    }
+
+    private static Date getNearestTime(Date date, int collectionFrequency) {
+        long milliseconds = date.getTime();
+        long minutes = milliseconds / (60 * 1000);
+        long remainder = minutes % collectionFrequency;
+        long adjustment = remainder < collectionFrequency / 2 ? -remainder : collectionFrequency - remainder;
+
+        // 调整到最近的整分钟时间
+        long adjustedMinutes = minutes + adjustment;
+        return new Date(adjustedMinutes * 60 * 1000);
+    }
+}

+ 10 - 3
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/DBMgrProxy.java

@@ -1,9 +1,7 @@
 package io.github.pnoker.gateway.dbdao;
 
 import io.github.pnoker.gateway.SpringContextUtil;
-import io.github.pnoker.gateway.dbdao.services.intef.XuChangCustomerMeterDayReadService;
-import io.github.pnoker.gateway.dbdao.services.intef.XuChangCustomerWaterConfigService;
-import io.github.pnoker.gateway.dbdao.services.intef.XuChangCustomerWaterInfoService;
+import io.github.pnoker.gateway.dbdao.services.intef.*;
 
 /**
  * @ClassName DBMgrProxy
@@ -17,6 +15,9 @@ public class DBMgrProxy {
     private volatile XuChangCustomerWaterInfoService xuChangCustomerWaterInfoService= null;
     private volatile XuChangCustomerMeterDayReadService xuChangCustomerMeterDayReadService= null;
 
+    private volatile DeviceKindService deviceKindService= null;
+    private volatile TypeDefineService typeDefineService= null;
+
     private static volatile DBMgrProxy msInstance = null;
     public static DBMgrProxy getInstance(){
         if (msInstance == null){
@@ -38,9 +39,15 @@ public class DBMgrProxy {
             xuChangCustomerWaterInfoService = (XuChangCustomerWaterInfoService)SpringContextUtil.getBean(XuChangCustomerWaterInfoService.class);
         if (xuChangCustomerMeterDayReadService == null)
             xuChangCustomerMeterDayReadService = (XuChangCustomerMeterDayReadService)SpringContextUtil.getBean(XuChangCustomerMeterDayReadService.class);
+        if (deviceKindService == null)
+            deviceKindService = (DeviceKindService)SpringContextUtil.getBean(DeviceKindService.class);
+        if (typeDefineService == null)
+            typeDefineService = (TypeDefineService)SpringContextUtil.getBean(TypeDefineService.class);
     }
 
     public XuChangCustomerWaterConfigService applyXuchangCustomerWaterConfigApi() { return xuchangCustomerWaterConfigService; }
     public XuChangCustomerWaterInfoService applyXuchangCustomerWaterInfoApi() { return xuChangCustomerWaterInfoService; }
     public XuChangCustomerMeterDayReadService applyXuChangCustomerMeterDayReadApi() { return xuChangCustomerMeterDayReadService; }
+    public DeviceKindService applyDeviceKineApi() { return deviceKindService; }
+    public TypeDefineService applyTypeDefineApi() { return typeDefineService; }
 }

+ 87 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/mapper/DeviceKindMapper.java

@@ -0,0 +1,87 @@
+package io.github.pnoker.gateway.dbdao.mapper;
+
+import io.github.pnoker.gateway.dbdao.providers.DeviceKindProvider;
+import io.github.pnoker.gateway.dbdao.tables.DeviceKindTable;
+import org.apache.ibatis.annotations.*;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName XuChangCustomerWaterConfigMapper
+ * @Description: TODO 许昌户表配置信息
+ * @Author LX
+ * @Date 2024/2/2
+ * @Version V1.0
+ **/
+public interface DeviceKindMapper extends DeviceKindTable {
+    @SelectProvider(type = DeviceKindProvider.class, method = "listAllWiths")
+    List<Map<String, Object>> listAllWiths(@Param("table") String table
+            , @Param("filed") String filed
+            , @Param("limit") int limit
+            , @Param("offset") int offset
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("order") String order
+            , @Param("extend") String extend);
+
+    @SelectProvider(type = DeviceKindProvider.class, method = "totalCounts")
+    int totalCounts(@Param("table") String table,
+                    @Param("andWheres") Map<String, Object> andWheres,
+                    @Param("orWheres") Map<String, Object> orWheres,
+                    @Param("extend") String extend);
+
+    @SelectProvider(type = DeviceKindProvider.class, method = "batchQueryIn")
+    List<Map<String, Object>> batchQueryIn(@Param("table") String table
+            , @Param("filed") String filed
+            , @Param("ids") List<? extends Object> ids
+            , @Param("order") String order
+            , @Param("extend") String extend);
+
+    @SelectProvider(type = DeviceKindProvider.class, method = "batchQueryWiths")
+    List<Map<String, Object>> batchQueryWiths(@Param("table") String table
+            , @Param("filed") String filed
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("order") String order
+            , @Param("extend") String extend);
+
+    @SelectProvider(type = DeviceKindProvider.class, method = "existsLine")
+    boolean existLine(@Param("table") String table
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("extend") String extend);
+
+    @InsertProvider(type = DeviceKindProvider.class, method = "batchInsertsOrUpdate")
+    int batchInsertOrUpdate(@Param("inserts") List<Map<String, Object>> inserts
+            , @Param("uniques") List<Object> uniques
+            , @Param("updates") List<Object> updates);
+
+    @InsertProvider(type = DeviceKindProvider.class, method = "insertOrUpdateEx")
+    int insertOrUpdate(@Param("inserts") Map<String, Object> inserts
+            , @Param("uniques") List<? extends Object> uniques
+            , @Param("updates") List<? extends Object> updates);
+
+    @InsertProvider(type = DeviceKindProvider.class, method = "inserts")
+    int inserts(@Param("inserts") Map<String, Object> inserts);
+
+    /**
+     * update和delete返回受影响条数需要配合useAffectedRows=true
+     * @param datas
+     * @param andWheres
+     * @return
+     */
+    @UpdateProvider(type = DeviceKindProvider.class, method = "updateWiths")
+    int updateWiths(@Param("datas") Map<String, Object> datas
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("extend") String extend);
+
+    @DeleteProvider(type = DeviceKindProvider.class, method = "deleteInIds")
+    int batchDeleteIn(@Param("ids") List<? extends Object> ids, @Param("extend") String extend);
+
+    @SelectProvider(type = DeviceKindProvider.class, method = "getByUniqueId")
+    Map<String, Object> getOne(@Param("table") String table
+            , @Param("filed") String filed
+            , @Param("id") Object id);
+}

+ 87 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/mapper/TypeDefineMapper.java

@@ -0,0 +1,87 @@
+package io.github.pnoker.gateway.dbdao.mapper;
+
+import io.github.pnoker.gateway.dbdao.providers.TypeDefineProvider;
+import io.github.pnoker.gateway.dbdao.tables.DeviceKindTable;
+import org.apache.ibatis.annotations.*;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName XuChangCustomerWaterConfigMapper
+ * @Description: TODO 许昌户表配置信息
+ * @Author LX
+ * @Date 2024/2/2
+ * @Version V1.0
+ **/
+public interface TypeDefineMapper extends DeviceKindTable {
+    @SelectProvider(type = TypeDefineProvider.class, method = "listAllWiths")
+    List<Map<String, Object>> listAllWiths(@Param("table") String table
+            , @Param("filed") String filed
+            , @Param("limit") int limit
+            , @Param("offset") int offset
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("order") String order
+            , @Param("extend") String extend);
+
+    @SelectProvider(type = TypeDefineProvider.class, method = "totalCounts")
+    int totalCounts(@Param("table") String table,
+                    @Param("andWheres") Map<String, Object> andWheres,
+                    @Param("orWheres") Map<String, Object> orWheres,
+                    @Param("extend") String extend);
+
+    @SelectProvider(type = TypeDefineProvider.class, method = "batchQueryIn")
+    List<Map<String, Object>> batchQueryIn(@Param("table") String table
+            , @Param("filed") String filed
+            , @Param("ids") List<? extends Object> ids
+            , @Param("order") String order
+            , @Param("extend") String extend);
+
+    @SelectProvider(type = TypeDefineProvider.class, method = "batchQueryWiths")
+    List<Map<String, Object>> batchQueryWiths(@Param("table") String table
+            , @Param("filed") String filed
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("order") String order
+            , @Param("extend") String extend);
+
+    @SelectProvider(type = TypeDefineProvider.class, method = "existsLine")
+    boolean existLine(@Param("table") String table
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("extend") String extend);
+
+    @InsertProvider(type = TypeDefineProvider.class, method = "batchInsertsOrUpdate")
+    int batchInsertOrUpdate(@Param("inserts") List<Map<String, Object>> inserts
+            , @Param("uniques") List<Object> uniques
+            , @Param("updates") List<Object> updates);
+
+    @InsertProvider(type = TypeDefineProvider.class, method = "insertOrUpdateEx")
+    int insertOrUpdate(@Param("inserts") Map<String, Object> inserts
+            , @Param("uniques") List<? extends Object> uniques
+            , @Param("updates") List<? extends Object> updates);
+
+    @InsertProvider(type = TypeDefineProvider.class, method = "inserts")
+    int inserts(@Param("inserts") Map<String, Object> inserts);
+
+    /**
+     * update和delete返回受影响条数需要配合useAffectedRows=true
+     * @param datas
+     * @param andWheres
+     * @return
+     */
+    @UpdateProvider(type = TypeDefineProvider.class, method = "updateWiths")
+    int updateWiths(@Param("datas") Map<String, Object> datas
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("extend") String extend);
+
+    @DeleteProvider(type = TypeDefineProvider.class, method = "deleteInIds")
+    int batchDeleteIn(@Param("ids") List<? extends Object> ids, @Param("extend") String extend);
+
+    @SelectProvider(type = TypeDefineProvider.class, method = "getByUniqueId")
+    Map<String, Object> getOne(@Param("table") String table
+            , @Param("filed") String filed
+            , @Param("id") Object id);
+}

+ 60 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/providers/DeviceKindProvider.java

@@ -0,0 +1,60 @@
+package io.github.pnoker.gateway.dbdao.providers;
+
+
+import io.github.pnoker.gateway.dbdao.tables.DeviceKindTable;
+
+/**
+ * @ClassName XuChangCustomerWaterConfigProvider
+ * @Description: TODO
+ * @Author LX
+ * @Date 2024/2/2
+ * @Version V1.0
+ **/
+public class DeviceKindProvider extends BaseSqlProvider implements DeviceKindTable {
+    @Override
+    public String getRTableName() {
+        return R_INFO.TABLE;
+    }
+
+    @Override
+    public String getWTableName() {
+        return W_INFO.TABLE;
+    }
+
+    @Override
+    public String getRUniqueId() {
+        return R_INFO.UNIQUE_ID;
+    }
+
+    @Override
+    public String getWUniqueId() {
+        return W_INFO.UNIQUE_ID;
+    }
+
+    @Override
+    public String getSAllFiled() {
+        return R_INFO.ALL_FILED;
+    }
+
+    @Override
+    public String getRPrimaryKey() {
+        return R_INFO.PRIMARY_KEY;
+    }
+
+    @Override
+    public String getWPrimaryKey() {
+        return W_INFO.PRIMARY_KEY;
+    }
+
+    @Override
+    public boolean isWJsonForFiled(String filedName) {
+        return false;
+    }
+
+    @Override
+    protected boolean isWTimeForFiled(String filedName) {
+//        if (W_INFO.CREATE_TIME.equalsIgnoreCase(filedName)) //create_time定义为long型用于高效排序
+//            return false;
+        return (filedName.endsWith("time"));
+    }
+}

+ 60 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/providers/TypeDefineProvider.java

@@ -0,0 +1,60 @@
+package io.github.pnoker.gateway.dbdao.providers;
+
+
+import io.github.pnoker.gateway.dbdao.tables.TypeDefineTable;
+
+/**
+ * @ClassName XuChangCustomerWaterConfigProvider
+ * @Description: TODO
+ * @Author LX
+ * @Date 2024/2/2
+ * @Version V1.0
+ **/
+public class TypeDefineProvider extends BaseSqlProvider implements TypeDefineTable {
+    @Override
+    public String getRTableName() {
+        return R_INFO.TABLE;
+    }
+
+    @Override
+    public String getWTableName() {
+        return W_INFO.TABLE;
+    }
+
+    @Override
+    public String getRUniqueId() {
+        return R_INFO.UNIQUE_ID;
+    }
+
+    @Override
+    public String getWUniqueId() {
+        return W_INFO.UNIQUE_ID;
+    }
+
+    @Override
+    public String getSAllFiled() {
+        return R_INFO.ALL_FILED;
+    }
+
+    @Override
+    public String getRPrimaryKey() {
+        return R_INFO.PRIMARY_KEY;
+    }
+
+    @Override
+    public String getWPrimaryKey() {
+        return W_INFO.PRIMARY_KEY;
+    }
+
+    @Override
+    public boolean isWJsonForFiled(String filedName) {
+        return false;
+    }
+
+    @Override
+    protected boolean isWTimeForFiled(String filedName) {
+//        if (W_INFO.CREATE_TIME.equalsIgnoreCase(filedName)) //create_time定义为long型用于高效排序
+//            return false;
+        return (filedName.endsWith("time"));
+    }
+}

+ 196 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/DeviceKindServiceImpl.java

@@ -0,0 +1,196 @@
+package io.github.pnoker.gateway.dbdao.services;
+
+import io.github.pnoker.gateway.comtool.CommTool;
+import io.github.pnoker.gateway.dbdao.mapper.DeviceKindMapper;
+import io.github.pnoker.gateway.dbdao.services.intef.DeviceKindService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName DeviceKindServiceImpl
+ * @Description: TODO
+ * @Author LX
+ * @Date 2024/2/2
+ * @Version V1.0
+ **/
+@Service
+public class DeviceKindServiceImpl implements DeviceKindService {
+    private String mStrClassName = "";
+    private String mBusinessType = "";
+    private String logTag = "";
+
+    private static final Logger log = LoggerFactory.getLogger(DeviceKindServiceImpl.class);
+
+    public DeviceKindServiceImpl() {
+        mStrClassName = this.getClass().getSimpleName();
+        mBusinessType = "DeviceKind";
+        logTag = "XuchangCustomerWaterConfig";
+    }
+
+    @SuppressWarnings("all")
+    @Autowired
+    private DeviceKindMapper deviceKindMapper;
+
+    @Override
+    public int totalCountsEx(String table, Map<String, Object> andWheres, Map<String, Object> orWheres, String extend) {
+        int nCode = 0;
+        String strMsg = "Success";
+        try {
+            return deviceKindMapper.totalCounts(table, andWheres, orWheres, extend);
+        }catch (Exception e){
+            nCode = 2;
+            strMsg = e.getLocalizedMessage();
+            log.error(nCode+
+                            mBusinessType+
+                            mStrClassName
+                    + String.format("Total %s lines from database, code:{%d} msg:{%s} ...", logTag, nCode, strMsg));
+            return 0;
+        }finally {
+            log.info(nCode+
+                            mBusinessType+
+                            mStrClassName
+                    +String.format("Total %s lines from database, code:{%d} msg:{%s} ...", logTag, nCode, strMsg));
+        }
+    }
+
+    @Override
+    public List<Map<String, Object>> batchQueryWithsEx(String table, String filed, Map<String, Object> andWheres, Map<String, Object> orWheres, String order, String extend) {
+        int nCode = 0;
+        String strMsg = "Success";
+        List<Map<String, Object>> arrRes = null;
+        try {
+            arrRes = deviceKindMapper.batchQueryWiths(table, filed, andWheres, orWheres, order, extend);
+        }catch (Exception e){
+            nCode = 1;
+            strMsg = e.getLocalizedMessage();
+        }finally {
+            log.error(String.format("Batch Query %s:{andWhere.size=%d, orWhere.size=%d, orderBy=%s, extend=%s, back.size=%d} from database, code:{%d} msg:{%s} ..."
+                            , logTag
+                            , CommTool.mapSize(andWheres)
+                            , CommTool.mapSize(orWheres)
+                            , order, extend
+                            , CommTool.listSize(arrRes)
+                            , nCode, strMsg));
+        }
+        return arrRes;
+    }
+
+    @Override
+    public List<Map<String, Object>> listAllWiths(int limit, int offset, Map<String, Object> andWheres, Map<String, Object> orWheres, String orderBy, String extend) {
+        int nCode = 0;
+        String strMsg = "Success";
+        List<Map<String, Object>> arrRes = null;
+        try {
+            arrRes = deviceKindMapper.listAllWiths("", "", limit, offset, andWheres, orWheres, orderBy, extend);
+        }catch (Exception e){
+            nCode = 2;
+            strMsg = e.getLocalizedMessage();
+            log.error(nCode+
+                            mBusinessType+
+                            mStrClassName
+                    +String.format("Total %s lines from database, code:{%d} msg:{%s} ...", logTag, nCode, strMsg));
+        }finally {
+            log.info(nCode+
+                            mBusinessType+
+                            mStrClassName
+                    +String.format("Total %s lines from database, code:{%d} msg:{%s} ...", logTag, nCode, strMsg));
+        }
+        return arrRes;
+    }
+
+    @Override
+    public List<Map<String, Object>> batchQueryIn(List<?> ids, String orderBy, String extend) {
+        return null;
+    }
+
+    @Override
+    public List<Map<String, Object>> batchQueryWiths(Map<String, Object> andWheres, Map<String, Object> orWheres, String orderBy, String extend) {
+        return null;
+    }
+
+    @Override
+    public int totalCounts(Map<String, Object> andWheres, Map<String, Object> orWheres) {
+        return 0;
+    }
+
+    @Override
+    public Map<String, Object> getOne(Object id) {
+        int nCode = 0;
+        String strMsg = "Success";
+        try {
+            return deviceKindMapper.getOne("", "", id);
+        }catch (Exception e){
+            nCode = 2;
+            strMsg = e.getLocalizedMessage();
+            log.error(nCode+
+                            mBusinessType+
+                            mStrClassName
+                    +String.format("Total %s lines from database, code:{%d} msg:{%s} ...", logTag, nCode, strMsg));
+            return null;
+        }finally {
+            log.info(nCode+
+                            mBusinessType+
+                            mStrClassName
+                    +String.format("Total %s lines from database, code:{%d} msg:{%s} ...", logTag, nCode, strMsg));
+        }
+    }
+
+    @Override
+    public int insertByMap(Map<String, Object> maps) {
+        int nCode = 0;
+        String strMsg = "Success";
+        try {
+            return deviceKindMapper.inserts(maps);
+        }catch (Exception e){
+            nCode = 2;
+            strMsg = e.getLocalizedMessage();
+            log.error(nCode+
+                            mBusinessType+
+                            mStrClassName
+                    +String.format("Total %s lines from database, code:{%d} msg:{%s} ...", logTag, nCode, strMsg));
+            return -1;
+        }finally {
+            log.info(nCode+
+                            mBusinessType+
+                            mStrClassName
+                    +String.format("Total %s lines from database, code:{%d} msg:{%s} ...", logTag, nCode, strMsg));
+        }
+    }
+
+    @Override
+    public int updateWiths(Map<String, Object> datas, Map<String, Object> andWheres) {
+        int nCode = 0;
+        String strMsg = "Success";
+        try {
+            return deviceKindMapper.updateWiths(datas, andWheres, null, "");
+        }catch (Exception e){
+            nCode = 2;
+            strMsg = e.getLocalizedMessage();
+            log.error(nCode+
+                            mBusinessType+
+                            mStrClassName
+                    +String.format("Total %s lines from database, code:{%d} msg:{%s} ...", logTag, nCode, strMsg));
+            return -1;
+        }finally {
+            log.info(nCode+
+                            mBusinessType+
+                            mStrClassName
+                    +String.format("Total %s lines from database, code:{%d} msg:{%s} ...", logTag, nCode, strMsg));
+        }
+    }
+
+    @Override
+    public int delete(Object id) {
+        return 0;
+    }
+
+    @Override
+    public int batchDeleteIn(List<?> ids, String extend) {
+        return 0;
+    }
+}

+ 196 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/TypeDefineServiceImpl.java

@@ -0,0 +1,196 @@
+package io.github.pnoker.gateway.dbdao.services;
+
+import io.github.pnoker.gateway.comtool.CommTool;
+import io.github.pnoker.gateway.dbdao.mapper.TypeDefineMapper;
+import io.github.pnoker.gateway.dbdao.services.intef.TypeDefineService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName TypeDefineServiceImpl
+ * @Description: TODO
+ * @Author LX
+ * @Date 2024/2/2
+ * @Version V1.0
+ **/
+@Service
+public class TypeDefineServiceImpl implements TypeDefineService {
+    private String mStrClassName = "";
+    private String mBusinessType = "";
+    private String logTag = "";
+
+    private static final Logger log = LoggerFactory.getLogger(TypeDefineServiceImpl.class);
+
+    public TypeDefineServiceImpl() {
+        mStrClassName = this.getClass().getSimpleName();
+        mBusinessType = "TypeDefine";
+        logTag = "XuchangCustomerWaterConfig";
+    }
+
+    @SuppressWarnings("all")
+    @Autowired
+    private TypeDefineMapper typeDefineMapper;
+
+    @Override
+    public int totalCountsEx(String table, Map<String, Object> andWheres, Map<String, Object> orWheres, String extend) {
+        int nCode = 0;
+        String strMsg = "Success";
+        try {
+            return typeDefineMapper.totalCounts(table, andWheres, orWheres, extend);
+        }catch (Exception e){
+            nCode = 2;
+            strMsg = e.getLocalizedMessage();
+            log.error(nCode+
+                            mBusinessType+
+                            mStrClassName
+                    + String.format("Total %s lines from database, code:{%d} msg:{%s} ...", logTag, nCode, strMsg));
+            return 0;
+        }finally {
+            log.info(nCode+
+                            mBusinessType+
+                            mStrClassName
+                    +String.format("Total %s lines from database, code:{%d} msg:{%s} ...", logTag, nCode, strMsg));
+        }
+    }
+
+    @Override
+    public List<Map<String, Object>> batchQueryWithsEx(String table, String filed, Map<String, Object> andWheres, Map<String, Object> orWheres, String order, String extend) {
+        int nCode = 0;
+        String strMsg = "Success";
+        List<Map<String, Object>> arrRes = null;
+        try {
+            arrRes = typeDefineMapper.batchQueryWiths(table, filed, andWheres, orWheres, order, extend);
+        }catch (Exception e){
+            nCode = 1;
+            strMsg = e.getLocalizedMessage();
+        }finally {
+            log.error(String.format("Batch Query %s:{andWhere.size=%d, orWhere.size=%d, orderBy=%s, extend=%s, back.size=%d} from database, code:{%d} msg:{%s} ..."
+                            , logTag
+                            , CommTool.mapSize(andWheres)
+                            , CommTool.mapSize(orWheres)
+                            , order, extend
+                            , CommTool.listSize(arrRes)
+                            , nCode, strMsg));
+        }
+        return arrRes;
+    }
+
+    @Override
+    public List<Map<String, Object>> listAllWiths(int limit, int offset, Map<String, Object> andWheres, Map<String, Object> orWheres, String orderBy, String extend) {
+        int nCode = 0;
+        String strMsg = "Success";
+        List<Map<String, Object>> arrRes = null;
+        try {
+            arrRes = typeDefineMapper.listAllWiths("", "", limit, offset, andWheres, orWheres, orderBy, extend);
+        }catch (Exception e){
+            nCode = 2;
+            strMsg = e.getLocalizedMessage();
+            log.error(nCode+
+                            mBusinessType+
+                            mStrClassName
+                    +String.format("Total %s lines from database, code:{%d} msg:{%s} ...", logTag, nCode, strMsg));
+        }finally {
+            log.info(nCode+
+                            mBusinessType+
+                            mStrClassName
+                    +String.format("Total %s lines from database, code:{%d} msg:{%s} ...", logTag, nCode, strMsg));
+        }
+        return arrRes;
+    }
+
+    @Override
+    public List<Map<String, Object>> batchQueryIn(List<?> ids, String orderBy, String extend) {
+        return null;
+    }
+
+    @Override
+    public List<Map<String, Object>> batchQueryWiths(Map<String, Object> andWheres, Map<String, Object> orWheres, String orderBy, String extend) {
+        return null;
+    }
+
+    @Override
+    public int totalCounts(Map<String, Object> andWheres, Map<String, Object> orWheres) {
+        return 0;
+    }
+
+    @Override
+    public Map<String, Object> getOne(Object id) {
+        int nCode = 0;
+        String strMsg = "Success";
+        try {
+            return typeDefineMapper.getOne("", "", id);
+        }catch (Exception e){
+            nCode = 2;
+            strMsg = e.getLocalizedMessage();
+            log.error(nCode+
+                            mBusinessType+
+                            mStrClassName
+                    +String.format("Total %s lines from database, code:{%d} msg:{%s} ...", logTag, nCode, strMsg));
+            return null;
+        }finally {
+            log.info(nCode+
+                            mBusinessType+
+                            mStrClassName
+                    +String.format("Total %s lines from database, code:{%d} msg:{%s} ...", logTag, nCode, strMsg));
+        }
+    }
+
+    @Override
+    public int insertByMap(Map<String, Object> maps) {
+        int nCode = 0;
+        String strMsg = "Success";
+        try {
+            return typeDefineMapper.inserts(maps);
+        }catch (Exception e){
+            nCode = 2;
+            strMsg = e.getLocalizedMessage();
+            log.error(nCode+
+                            mBusinessType+
+                            mStrClassName
+                    +String.format("Total %s lines from database, code:{%d} msg:{%s} ...", logTag, nCode, strMsg));
+            return -1;
+        }finally {
+            log.info(nCode+
+                            mBusinessType+
+                            mStrClassName
+                    +String.format("Total %s lines from database, code:{%d} msg:{%s} ...", logTag, nCode, strMsg));
+        }
+    }
+
+    @Override
+    public int updateWiths(Map<String, Object> datas, Map<String, Object> andWheres) {
+        int nCode = 0;
+        String strMsg = "Success";
+        try {
+            return typeDefineMapper.updateWiths(datas, andWheres, null, "");
+        }catch (Exception e){
+            nCode = 2;
+            strMsg = e.getLocalizedMessage();
+            log.error(nCode+
+                            mBusinessType+
+                            mStrClassName
+                    +String.format("Total %s lines from database, code:{%d} msg:{%s} ...", logTag, nCode, strMsg));
+            return -1;
+        }finally {
+            log.info(nCode+
+                            mBusinessType+
+                            mStrClassName
+                    +String.format("Total %s lines from database, code:{%d} msg:{%s} ...", logTag, nCode, strMsg));
+        }
+    }
+
+    @Override
+    public int delete(Object id) {
+        return 0;
+    }
+
+    @Override
+    public int batchDeleteIn(List<?> ids, String extend) {
+        return 0;
+    }
+}

+ 27 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/intef/DeviceKindService.java

@@ -0,0 +1,27 @@
+package io.github.pnoker.gateway.dbdao.services.intef;
+
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName XuChangCustomerWaterConfigService
+ * @Description: TODO
+ * @Author LX
+ * @Date 2024/2/2
+ * @Version V1.0
+ **/
+public interface DeviceKindService extends BaseDBService{
+    int totalCountsEx(String table
+            , Map<String, Object> andWheres
+            , Map<String, Object> orWheres
+            , String extend);
+
+    List<Map<String, Object>> batchQueryWithsEx(@Param("table") String table
+            , @Param("filed") String filed
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("order") String order
+            , @Param("extend") String extend);
+}

+ 27 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/intef/TypeDefineService.java

@@ -0,0 +1,27 @@
+package io.github.pnoker.gateway.dbdao.services.intef;
+
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName XuChangCustomerWaterConfigService
+ * @Description: TODO
+ * @Author LX
+ * @Date 2024/2/2
+ * @Version V1.0
+ **/
+public interface TypeDefineService extends BaseDBService{
+    int totalCountsEx(String table
+            , Map<String, Object> andWheres
+            , Map<String, Object> orWheres
+            , String extend);
+
+    List<Map<String, Object>> batchQueryWithsEx(@Param("table") String table
+            , @Param("filed") String filed
+            , @Param("andWheres") Map<String, Object> andWheres
+            , @Param("orWheres") Map<String, Object> orWheres
+            , @Param("order") String order
+            , @Param("extend") String extend);
+}

+ 20 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/tables/DeviceKindTable.java

@@ -0,0 +1,20 @@
+package io.github.pnoker.gateway.dbdao.tables;
+
+public interface DeviceKindTable {
+    interface R_INFO{
+        String TABLE = "k2_device_kind";
+        String PRIMARY_KEY = "uid";//赋值优先级:1)单主键字段 2)单唯一索引字段 3)自增ID 4)联合主键字段
+        String UNIQUE_ID = "uid";//赋值优先级:1)单主键字段 2)单唯一索引字段 3)自增ID
+
+        String ALL_FILED = "*";
+        String DEFAULT_ORDER = "id DESC";
+        String DEFAULT_EXTEND = "";
+    }
+
+    interface W_INFO{
+        String TABLE = "k2_device_kind";
+        String PRIMARY_KEY = "uid";//赋值优先级:赋值优先级:1)单主键字段 2)单唯一索引字段 3)自增ID 4)联合主键字段
+        String UNIQUE_ID = "uid";//赋值优先级:1)单主键字段 2)单唯一索引字段 3)自增ID
+
+    }
+}

+ 20 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/tables/TypeDefineTable.java

@@ -0,0 +1,20 @@
+package io.github.pnoker.gateway.dbdao.tables;
+
+public interface TypeDefineTable {
+    interface R_INFO{
+        String TABLE = "k2_type_define";
+        String PRIMARY_KEY = "key";//赋值优先级:1)单主键字段 2)单唯一索引字段 3)自增ID 4)联合主键字段
+        String UNIQUE_ID = "key";//赋值优先级:1)单主键字段 2)单唯一索引字段 3)自增ID
+
+        String ALL_FILED = "*";
+        String DEFAULT_ORDER = "id DESC";
+        String DEFAULT_EXTEND = "";
+    }
+
+    interface W_INFO{
+        String TABLE = "k2_type_define";
+        String PRIMARY_KEY = "key";//赋值优先级:赋值优先级:1)单主键字段 2)单唯一索引字段 3)自增ID 4)联合主键字段
+        String UNIQUE_ID = "key";//赋值优先级:1)单主键字段 2)单唯一索引字段 3)自增ID
+
+    }
+}

+ 102 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/utils/HttpUtil.java

@@ -0,0 +1,102 @@
+package io.github.pnoker.gateway.utils;
+
+import org.springframework.remoting.RemoteAccessException;
+import org.springframework.retry.annotation.Backoff;
+import org.springframework.retry.annotation.Retryable;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.Map;
+
+/**
+ * @ClassName HttpUtil
+ * @Description: TODO
+ * @Author LX
+ * @Date 2024/9/3
+ * @Version V1.0
+ **/
+public class HttpUtil {
+    // GET 请求
+    @Retryable(value = {RemoteAccessException.class}, maxAttempts = 3, backoff = @Backoff(delay = 200L, multiplier = 1))
+    public static String sendGet(String urlString,Map<String,String> params,Map<String, String> headers) throws Exception {
+        String paramStr = "";
+        if(params !=null){
+            int i = 0;
+            for (Map.Entry<String, String> param : params.entrySet()) {
+                if(i==0){
+                    paramStr += "?"+param.getKey()+"="+URLEncoder.encode(param.getValue(), "UTF-8");
+                }else{
+                    paramStr += "&"+param.getKey()+"="+URLEncoder.encode(param.getValue(), "UTF-8");
+                }
+                i++;
+            }
+        }
+        URL url = new URL(urlString+paramStr);
+        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+        conn.setRequestMethod("GET");
+        conn.setConnectTimeout(5000);
+        conn.setReadTimeout(5000);
+
+        // 设置请求头
+        if (headers != null) {
+            for (Map.Entry<String, String> header : headers.entrySet()) {
+                conn.setRequestProperty(header.getKey(), header.getValue());
+            }
+        }
+
+        int responseCode = conn.getResponseCode();
+        if (responseCode == HttpURLConnection.HTTP_OK) {
+            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+            String inputLine;
+            StringBuilder response = new StringBuilder();
+            while ((inputLine = in.readLine()) != null) {
+                response.append(inputLine);
+            }
+            in.close();
+            return response.toString();
+        } else {
+            throw new Exception("GET request not worked, Response Code: " + responseCode+";url:"+urlString);
+        }
+    }
+
+    // POST 请求
+    @Retryable(value = {RemoteAccessException.class}, maxAttempts = 3, backoff = @Backoff(delay = 200L, multiplier = 1))
+    public static String sendPost(String urlString, String postData, Map<String, String> headers) throws Exception {
+        URL url = new URL(urlString);
+        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+        conn.setRequestMethod("POST");
+        conn.setConnectTimeout(5000);
+        conn.setReadTimeout(5000);
+        conn.setDoOutput(true);
+
+        // 设置请求头
+        if (headers != null) {
+            for (Map.Entry<String, String> header : headers.entrySet()) {
+                conn.setRequestProperty(header.getKey(), header.getValue());
+            }
+        }
+
+        try (OutputStream os = conn.getOutputStream()) {
+            byte[] input = postData.getBytes("utf-8");
+            os.write(input, 0, input.length);
+        }
+
+        int responseCode = conn.getResponseCode();
+        if (responseCode == HttpURLConnection.HTTP_OK) {
+            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
+            StringBuilder response = new StringBuilder();
+            String responseLine;
+            while ((responseLine = in.readLine()) != null) {
+                response.append(responseLine.trim());
+            }
+            in.close();
+            return response.toString();
+        } else {
+            throw new Exception("POST request not worked, Response Code: " + responseCode);
+        }
+    }
+}

+ 62 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/utils/InfulxDbUtil.java

@@ -0,0 +1,62 @@
+package io.github.pnoker.gateway.utils;
+
+import io.github.pnoker.gateway.comtool.ResponseCode;
+import org.influxdb.InfluxDB;
+import org.influxdb.InfluxDBFactory;
+import org.influxdb.dto.Point;
+import org.influxdb.dto.Query;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.util.Timer;
+import java.util.TimerTask;
+
+/**
+ * @ClassName InfulxDbUtil
+ * @Description: TODO influxDb连接工具类
+ * @Author LX
+ * @Date 2024/9/3
+ * @Version V1.0
+ **/
+@Component("infulxDbUtil")
+public class InfulxDbUtil {
+    @Value("${dangyang.inluxdb.serverUrl:}")
+    private String serverUrl = ""; // InfluxDB 服务器地址
+
+    @Value("${dangyang.inluxdb.username:}")
+    private String username = ""; // InfluxDB 用户名
+
+    @Value("${dangyang.inluxdb.password:}")
+    private String password = ""; // InfluxDB 密码
+
+    @Value("${dangyang.inluxdb.database:}")
+    private String database = ""; // 数据库名称
+
+    private InfluxDB influxDB = null;
+
+    @PostConstruct
+    public void initInfluxDataBase(){
+        new Timer().schedule(new TimerTask() {
+            @Override
+            public void run() {
+                influxDB = InfluxDBFactory.connect(serverUrl, username, password);
+                // 创建数据库
+                influxDB.query(new Query("CREATE DATABASE " + database));
+
+                // 设置要使用的数据库
+                influxDB.setDatabase(database);
+            }
+        },3000);
+    }
+
+    public ResponseCode insert(Point point){
+        try {
+            influxDB.write(point);
+            return ResponseCode.RESULT_NORMAL;
+        }catch(Exception ex){
+            return ResponseCode.BUSINESS_DB_REQ_FAILED;
+        }
+    }
+
+}

+ 70 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/utils/TestUtil.java

@@ -0,0 +1,70 @@
+package io.github.pnoker.gateway.utils;
+
+import com.alibaba.fastjson.JSONObject;
+import org.influxdb.InfluxDB;
+import org.influxdb.InfluxDBFactory;
+import org.influxdb.dto.Point;
+import org.influxdb.dto.Query;
+import org.influxdb.dto.QueryResult;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @ClassName TestUtil
+ * @Description: TODO
+ * @Author LX
+ * @Date 2024/9/3
+ * @Version V1.0
+ **/
+public class TestUtil {
+    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+    public static void main(String[] args) throws Exception{
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("time","2024-09-03 09:54:00");
+        Date timeStr = dateFormat.parse(jsonObject.getString("time"));
+        // 连接到 InfluxDB
+        String serverURL = "http://localhost:8086"; // InfluxDB 服务器地址
+        String username = "admin"; // InfluxDB 用户名
+        String password = "yourpassword"; // InfluxDB 密码
+        String database = "mydb"; // 数据库名称
+
+        InfluxDB influxDB = InfluxDBFactory.connect(serverURL, username, password);
+
+        try {
+            // 创建数据库
+            influxDB.query(new Query("CREATE DATABASE " + database));
+
+            // 设置要使用的数据库
+            influxDB.setDatabase(database);
+
+            // 写入数据
+            Point point = Point.measurement("cpu")
+                    .time(System.currentTimeMillis(), TimeUnit.MILLISECONDS)
+                    .addField("usage", 0.64)
+                    .addField("host", "server01")
+                    .build();
+            influxDB.write(point);
+
+            // 查询数据
+            Query query = new Query("SELECT * FROM cpu", database);
+            QueryResult result = influxDB.query(query);
+
+            // 处理查询结果
+            for (QueryResult.Result res : result.getResults()) {
+                for (QueryResult.Series series : res.getSeries()) {
+                    System.out.println("Series: " + series.getName());
+                    System.out.println("Columns: " + series.getColumns());
+                    for (List<Object> values : series.getValues()) {
+                        System.out.println("Values: " + values);
+                    }
+                }
+            }
+        } finally {
+            // 关闭连接
+            influxDB.close();
+        }
+    }
+}

+ 60 - 1
dc3-gateway/src/main/resources/application.yml

@@ -128,7 +128,7 @@ spring:
             #   fallbackUri: 'forward:/fallback'
   datasource:
       driver-class-name: org.postgis.DriverWrapper
-      jdbc-url: jdbc:postgresql_postGIS://119.96.165.176:5432/watersmart?useSSL=false&useAffectedRows=false&allowMultiQueries=true
+      jdbc-url: jdbc:postgresql_postGIS://192.168.0.4:5432/watersmart?useSSL=false&useAffectedRows=false&allowMultiQueries=true
       username: postgres
       password: kpr.23417.postgres
       data:
@@ -152,3 +152,62 @@ xuchang:
   user: zzsfy
   pwd: D41D8CD98F00B204E980
   url: http://42.227.69.38:8004/WebServiceOfNBIoT.asmx
+
+#当阳influxdb配置
+dangyang:
+#influxdb相关配置
+  inluxdb:
+    database: iot
+    serverUrl: http://192.168.0.4:8086
+    username: kpr
+    password: kpr.2024dy.influxdb
+#设备数据相关接口地址
+  http:
+    username: shkpr
+    password: shkpr
+    token: http://192.168.0.9:48085/admin-api/system/auth/login
+    realtimeDataList: http://192.168.0.9:48085/admin-api/data/device/realtimeDataList
+    hisDataList: http://192.168.0.9:48085/admin-api/data/device/hisDataList
+    list: http://192.168.0.9:48085/admin-api/data/device/list
+#设备类型列表配置
+  device:
+    type: >
+              [{
+                	"key": "FLOW_METER",
+                	"name": "流量计"
+                }, {
+                	"key": "WATER_QUALITY",
+                	"name": "水质仪"
+                }, {
+                	"key": "WATER_PUMP",
+                	"name": "水泵"
+                }, {
+                	"key": "WATER_METER",
+                	"name": "水表"
+                }, {
+                	"key": "PRESS_METER",
+                	"name": "压力计"
+                }, {
+                	"key": "LIQUID_LEVEL_METER",
+                	"name": "液位计"
+                }, {
+                	"key": "ELEC_CTRL_VALVE",
+                	"name": "电控阀"
+                }]
+#当阳远程物联网接口返回字段信息 ___后跟的是自己的字段
+
+watermeter: ftotal___flow_total_pos,rtotal___flow_total_rev,flow___flow_cur,press___press_cur,soc___battery
+flowmeter: ftotal___flow_total_pos,rtotal___flow_total_rev,flow___flow_cur,speed___flow_speed,tub,alarm___alarm,csq___csq,press___press_cur
+pressmeter: press___press_cur
+waterquality: ph___ph,wd___dev_temperature,yl___chlorine,zd___turbidity
+waterpump: power___power,currentA___ia,currentB___ib,currentC___ic,voltageA___ua,voltageB___ub,voltageC___uc,soc___battery,dn___quantity,runTime,runFrequency___frequency
+elecctrlvalve: RP16___battery_voltage,RW01___flow_total_pos,RW03___flow_speed,RW02___flow_cur
+liquidlevelmeter: level___level
+
+WATER_METER: WaterMeter
+FLOW_METER: WaterMeter
+PRESS_METER: WaterMeter
+WATER_QUALITY: WaterQuality
+WATER_PUMP: WaterPump
+ELEC_CTRL_VALVE: ValveMeter
+LIQUID_LEVEL_METER: LiquidLevel