Jelajahi Sumber

Initial commit

1037015548@qq.com 2 tahun lalu
induk
melakukan
b8614cd132
100 mengubah file dengan 8453 tambahan dan 0 penghapusan
  1. 49 0
      dc3-gateway/Dockerfile
  2. 253 0
      dc3-gateway/dc3-gateway.iml
  3. 264 0
      dc3-gateway/pom.xml
  4. 45 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/GatewayApplication.java
  5. 30 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/JPBean/JPKprXuChangWaterSS.java
  6. 52 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/SpringContextUtil.java
  7. 422 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/bizmgr/KprDangyangWaterBizFun.java
  8. 40 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/bizmgr/KprXuChangWaterBizFun.java
  9. 90 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/bizmgr/baseInit/KprBaseInitFun.java
  10. 187 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/CommTool.java
  11. 137 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/HttpTool.java
  12. 114 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/ResponseCode.java
  13. 192 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/ScheduleTaskMgr.java
  14. 244 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/ThreadHistoryTask.java
  15. 39 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/ThreadPoolTaskTool.java
  16. 238 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/ThreadTask.java
  17. 500 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/TimeTool.java
  18. 446 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/XuchangWaterConfig.java
  19. 75 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/config/ExceptionConfig.java
  20. 81 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/config/GatewayConfig.java
  21. 177 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/config/GlobalData.java
  22. 107 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/config/MainSourceConfiguration.java
  23. 57 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/config/RouteConfig.java
  24. 95 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/control/KprXuChangWaterController.java
  25. 53 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/DBMgrProxy.java
  26. 87 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/mapper/DeviceKindMapper.java
  27. 87 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/mapper/TypeDefineMapper.java
  28. 96 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/mapper/XuChangCustomerMeterDayReadMapper.java
  29. 87 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/mapper/XuChangCustomerWaterConfigMapper.java
  30. 94 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/mapper/XuChangCustomerWaterInfoMapper.java
  31. 40 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/mapper/XuChangDayReadNewMapper.java
  32. 1076 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/providers/BaseSqlProvider.java
  33. 60 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/providers/DeviceKindProvider.java
  34. 60 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/providers/TypeDefineProvider.java
  35. 60 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/providers/XuChangCustomerMeterDayReadProvider.java
  36. 60 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/providers/XuChangCustomerWaterConfigProvider.java
  37. 60 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/providers/XuChangCustomerWaterInfoProvider.java
  38. 196 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/DeviceKindServiceImpl.java
  39. 196 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/TypeDefineServiceImpl.java
  40. 216 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/XuChangCustomerMeterDayReadServiceImpl.java
  41. 178 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/XuChangCustomerWaterConfigServiceImpl.java
  42. 202 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/XuChangCustomerWaterInfoServiceImpl.java
  43. 29 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/intef/BaseDBService.java
  44. 27 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/intef/DeviceKindService.java
  45. 27 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/intef/TypeDefineService.java
  46. 33 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/intef/XuChangCustomerMeterDayReadService.java
  47. 27 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/intef/XuChangCustomerWaterConfigService.java
  48. 30 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/intef/XuChangCustomerWaterInfoService.java
  49. 20 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/tables/DeviceKindTable.java
  50. 20 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/tables/TypeDefineTable.java
  51. 19 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/tables/XuChangCustomerMeterDayReadTable.java
  52. 27 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/tables/XuChangCustomerWaterConfigTable.java
  53. 27 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/tables/XuChangCustomerWaterInfoTable.java
  54. 35 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/entity/bo/RequestHeaderBO.java
  55. 55 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/fallback/GatewayFallback.java
  56. 65 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/filter/BlackIpGlobalFilter.java
  57. 155 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/filter/factory/AuthenticGatewayFilterFactory.java
  58. 36 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/init/GatewayInitRunner.java
  59. 24 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/service/FilterService.java
  60. 30 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/service/impl/FilterServiceImpl.java
  61. 93 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/utils/GatewayUtil.java
  62. 102 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/utils/HttpUtil.java
  63. 62 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/utils/InfulxDbUtil.java
  64. 70 0
      dc3-gateway/src/main/java/io/github/pnoker/gateway/utils/TestUtil.java
  65. 45 0
      dc3-gateway/src/main/resources/application-dev.yml
  66. 17 0
      dc3-gateway/src/main/resources/application-prod.yml
  67. 21 0
      dc3-gateway/src/main/resources/application-test.yml
  68. 216 0
      dc3-gateway/src/main/resources/application.yml
  69. 45 0
      dc3-gateway/target/classes/application-dev.yml
  70. 17 0
      dc3-gateway/target/classes/application-prod.yml
  71. 21 0
      dc3-gateway/target/classes/application-test.yml
  72. 216 0
      dc3-gateway/target/classes/application.yml
  73. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/GatewayApplication.class
  74. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/JPBean/JPKprXuChangWaterSS.class
  75. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/SpringContextUtil.class
  76. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/bizmgr/KprDangyangWaterBizFun$1.class
  77. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/bizmgr/KprDangyangWaterBizFun$2.class
  78. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/bizmgr/KprDangyangWaterBizFun$3.class
  79. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/bizmgr/KprDangyangWaterBizFun$4.class
  80. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/bizmgr/KprDangyangWaterBizFun.class
  81. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/bizmgr/KprXuChangWaterBizFun.class
  82. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/bizmgr/baseInit/KprBaseInitFun.class
  83. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/CommTool.class
  84. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/HttpTool.class
  85. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/ResponseCode.class
  86. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/ScheduleTaskMgr$1.class
  87. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/ScheduleTaskMgr$2.class
  88. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/ScheduleTaskMgr$3.class
  89. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/ScheduleTaskMgr$TokenTask.class
  90. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/ScheduleTaskMgr.class
  91. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/ThreadHistoryTask.class
  92. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/ThreadPoolTaskTool.class
  93. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/ThreadTask.class
  94. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/TimeTool.class
  95. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/XuchangWaterConfig.class
  96. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/config/ExceptionConfig.class
  97. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/config/GatewayConfig.class
  98. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/config/GlobalData.class
  99. TEMPAT SAMPAH
      dc3-gateway/target/classes/io/github/pnoker/gateway/config/MainSourceConfiguration.class
  100. 0 0
      dc3-gateway/target/classes/io/github/pnoker/gateway/config/RouteConfig.class

+ 49 - 0
dc3-gateway/Dockerfile

@@ -0,0 +1,49 @@
+#
+# Copyright 2016-present the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# runtime
+FROM registry.cn-beijing.aliyuncs.com/dc3/alpine-java:dragonwell-8.13.14 AS runtime
+MAINTAINER pnoker <pnokers.icloud.com>
+
+ENV JAVA_OPS -server \
+             -Xms128m \
+             -Xmx1024m \
+             -Djava.security.egd=file:/dev/./urandom \
+             -XX:CompressedClassSpaceSize=128m \
+             -XX:MetaspaceSize=200m \
+             -XX:MaxMetaspaceSize=200m
+ENV GC_LOG   -XX:+PrintGCDetails \
+             -XX:+PrintGCDateStamps \
+             -XX:+PrintTenuringDistribution \
+             -XX:+PrintHeapAtGC \
+             -XX:+PrintReferenceGC \
+             -XX:+PrintGCApplicationStoppedTime \
+             -XX:+UseGCLogFileRotation \
+             -XX:NumberOfGCLogFiles=10 \
+             -XX:GCLogFileSize=10M \
+             -Xloggc:dc3/logs/gateway/gc/dc3-center-gateway.log
+
+RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
+
+WORKDIR /dc3-gateway
+
+ADD ./target/dc3-gateway.jar ./
+
+EXPOSE 8000
+VOLUME /dc3-gateway/dc3/logs
+
+CMD mkdir -p /dc3-gateway/dc3/logs/gateway/gc \
+    && java ${JAVA_OPS} ${GC_LOG} -jar dc3-gateway.jar

+ 253 - 0
dc3-gateway/dc3-gateway.iml

@@ -0,0 +1,253 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
+  <component name="FacetManager">
+    <facet type="Spring" name="Spring">
+      <configuration />
+    </facet>
+  </component>
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
+    <output url="file://$MODULE_DIR$/target/classes" />
+    <output-test url="file://$MODULE_DIR$/target/test-classes" />
+    <content url="file://$MODULE_DIR$">
+      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
+      <excludeFolder url="file://$MODULE_DIR$/target" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-webflux:2.7.11" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.7.11" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.7.11" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.7.11" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:2.7.11" level="project" />
+    <orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.2.12" level="project" />
+    <orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.2.12" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-to-slf4j:2.17.2" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.36" level="project" />
+    <orderEntry type="library" name="Maven: jakarta.annotation:jakarta.annotation-api:1.3.5" level="project" />
+    <orderEntry type="library" name="Maven: org.yaml:snakeyaml:2.0" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:2.7.11" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.13.5" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.5" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.13.5" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-reactor-netty:2.7.11" level="project" />
+    <orderEntry type="library" name="Maven: io.projectreactor.netty:reactor-netty-http:1.0.31" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-codec-http:4.1.91.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-buffer:4.1.91.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-codec:4.1.91.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-codec-http2:4.1.91.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-resolver-dns:4.1.91.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-resolver:4.1.91.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-codec-dns:4.1.91.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-resolver-dns-native-macos:osx-x86_64:4.1.91.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-resolver-dns-classes-macos:4.1.91.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-transport-native-epoll:linux-x86_64:4.1.91.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-transport-classes-epoll:4.1.91.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.projectreactor.netty:reactor-netty-core:1.0.31" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-web:5.3.27" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-beans:5.3.27" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-webflux:5.3.27" level="project" />
+    <orderEntry type="library" name="Maven: io.projectreactor:reactor-core:3.4.29" level="project" />
+    <orderEntry type="library" name="Maven: org.reactivestreams:reactive-streams:1.0.4" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-undertow:2.7.11" level="project" />
+    <orderEntry type="library" name="Maven: io.undertow:undertow-core:2.2.24.Final" level="project" />
+    <orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.4.3.Final" level="project" />
+    <orderEntry type="library" name="Maven: org.jboss.xnio:xnio-api:3.8.7.Final" level="project" />
+    <orderEntry type="library" name="Maven: org.wildfly.common:wildfly-common:1.5.4.Final" level="project" />
+    <orderEntry type="library" name="Maven: org.wildfly.client:wildfly-client-config:1.0.1.Final" level="project" />
+    <orderEntry type="library" scope="RUNTIME" name="Maven: org.jboss.xnio:xnio-nio:3.8.7.Final" level="project" />
+    <orderEntry type="library" name="Maven: org.jboss.threads:jboss-threads:3.1.0.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.undertow:undertow-servlet:2.2.24.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.undertow:undertow-websockets-jsr:2.2.24.Final" level="project" />
+    <orderEntry type="library" name="Maven: jakarta.servlet:jakarta.servlet-api:4.0.4" level="project" />
+    <orderEntry type="library" name="Maven: jakarta.websocket:jakarta.websocket-api:1.1.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:9.0.74" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter-gateway:3.1.7" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter:3.1.6" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-context:3.1.6" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.security:spring-security-crypto:5.7.8" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-commons:3.1.6" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.security:spring-security-rsa:1.0.11.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: org.bouncycastle:bcpkix-jdk15on:1.69" level="project" />
+    <orderEntry type="library" name="Maven: org.bouncycastle:bcprov-jdk15on:1.69" level="project" />
+    <orderEntry type="library" name="Maven: org.bouncycastle:bcutil-jdk15on:1.69" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-gateway-server:3.1.7" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-validation:2.7.11" level="project" />
+    <orderEntry type="library" name="Maven: io.projectreactor.addons:reactor-extra:3.4.10" level="project" />
+    <orderEntry type="library" name="Maven: net.devh:grpc-client-spring-boot-starter:2.14.0.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: net.devh:grpc-client-spring-boot-autoconfigure:2.14.0.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: net.devh:grpc-common-spring-boot:2.14.0.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: io.grpc:grpc-core:1.53.0" level="project" />
+    <orderEntry type="library" scope="RUNTIME" name="Maven: com.google.android:annotations:4.1.1.4" level="project" />
+    <orderEntry type="library" scope="RUNTIME" name="Maven: org.codehaus.mojo:animal-sniffer-annotations:1.21" level="project" />
+    <orderEntry type="library" name="Maven: io.grpc:grpc-netty-shaded:1.53.0" level="project" />
+    <orderEntry type="library" name="Maven: com.google.guava:guava:31.1-jre" level="project" />
+    <orderEntry type="library" name="Maven: com.google.guava:failureaccess:1.0.1" level="project" />
+    <orderEntry type="library" name="Maven: com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava" level="project" />
+    <orderEntry type="library" name="Maven: com.google.j2objc:j2objc-annotations:1.3" level="project" />
+    <orderEntry type="library" scope="RUNTIME" name="Maven: io.perfmark:perfmark-api:0.25.0" level="project" />
+    <orderEntry type="library" name="Maven: io.grpc:grpc-protobuf:1.53.0" level="project" />
+    <orderEntry type="library" name="Maven: io.grpc:grpc-api:1.53.0" level="project" />
+    <orderEntry type="library" name="Maven: io.grpc:grpc-context:1.53.0" level="project" />
+    <orderEntry type="library" name="Maven: com.google.protobuf:protobuf-java:3.21.7" level="project" />
+    <orderEntry type="library" name="Maven: com.google.api.grpc:proto-google-common-protos:2.9.0" level="project" />
+    <orderEntry type="library" name="Maven: io.grpc:grpc-protobuf-lite:1.53.0" level="project" />
+    <orderEntry type="library" name="Maven: io.grpc:grpc-stub:1.53.0" level="project" />
+    <orderEntry type="library" name="Maven: io.github.pnoker:dc3-starter-center-register-nacos-client:2023.4.5" level="project" />
+    <orderEntry type="library" name="Maven: com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-discovery:2021.0.5.0" level="project" />
+    <orderEntry type="library" name="Maven: com.alibaba.cloud:spring-cloud-alibaba-commons:2021.0.5.0" level="project" />
+    <orderEntry type="library" name="Maven: com.alibaba.nacos:nacos-client:2.2.0" level="project" />
+    <orderEntry type="library" name="Maven: com.alibaba.nacos:nacos-auth-plugin:2.2.0" level="project" />
+    <orderEntry type="library" name="Maven: com.alibaba.nacos:nacos-encryption-plugin:2.2.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpasyncclient:4.1.5" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore:4.4.16" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore-nio:4.4.16" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpclient:4.5.14" level="project" />
+    <orderEntry type="library" name="Maven: io.prometheus:simpleclient:0.15.0" level="project" />
+    <orderEntry type="library" name="Maven: io.prometheus:simpleclient_tracer_otel:0.15.0" level="project" />
+    <orderEntry type="library" name="Maven: io.prometheus:simpleclient_tracer_common:0.15.0" level="project" />
+    <orderEntry type="library" name="Maven: io.prometheus:simpleclient_tracer_otel_agent:0.15.0" level="project" />
+    <orderEntry type="library" name="Maven: com.alibaba.spring:spring-context-support:1.0.11" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-actuator:2.7.11" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-actuator-autoconfigure:2.7.11" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-actuator:2.7.11" level="project" />
+    <orderEntry type="library" name="Maven: io.micrometer:micrometer-core:1.9.10" level="project" />
+    <orderEntry type="library" name="Maven: org.hdrhistogram:HdrHistogram:2.1.12" level="project" />
+    <orderEntry type="library" scope="RUNTIME" name="Maven: org.latencyutils:LatencyUtils:2.0.3" level="project" />
+    <orderEntry type="library" name="Maven: com.github.ben-manes.caffeine:caffeine:2.9.3" level="project" />
+    <orderEntry type="library" name="Maven: org.checkerframework:checker-qual:3.19.0" level="project" />
+    <orderEntry type="library" name="Maven: com.google.errorprone:error_prone_annotations:2.10.0" level="project" />
+    <orderEntry type="library" name="Maven: io.github.pnoker:dc3-common-public:2023.4.5" level="project" />
+    <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-core:3.5.3.1" level="project" />
+    <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-annotation:3.5.3.1" level="project" />
+    <orderEntry type="library" name="Maven: com.github.jsqlparser:jsqlparser:4.4" level="project" />
+    <orderEntry type="library" name="Maven: commons-fileupload:commons-fileupload:1.5" level="project" />
+    <orderEntry type="library" name="Maven: io.jsonwebtoken:jjwt:0.9.1" level="project" />
+    <orderEntry type="library" name="Maven: org.bouncycastle:bcprov-jdk16:1.46" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-data-redis-reactive:2.7.11" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-data-redis:2.7.11" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.data:spring-data-redis:2.7.11" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.data:spring-data-keyvalue:2.7.11" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-oxm:5.3.27" level="project" />
+    <orderEntry type="library" name="Maven: io.lettuce:lettuce-core:6.1.10.RELEASE" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-common:4.1.91.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-handler:4.1.91.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-transport:4.1.91.Final" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter-loadbalancer:3.1.6" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-loadbalancer:3.1.6" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-cache:2.7.11" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-context-support:5.3.27" level="project" />
+    <orderEntry type="library" name="Maven: com.stoyanr:evictor:1.0.0" level="project" />
+    <orderEntry type="library" name="Maven: io.github.pnoker:dc3-api-auth:2023.4.5" level="project" />
+    <orderEntry type="library" name="Maven: io.github.pnoker:dc3-common-api:2023.4.5" level="project" />
+    <orderEntry type="library" name="Maven: javax.annotation:javax.annotation-api:1.3.2" level="project" />
+    <orderEntry type="library" name="Maven: io.grpc:grpc-netty:1.53.0" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-handler-proxy:4.1.91.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-codec-socks:4.1.91.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.netty:netty-transport-native-unix-common:4.1.91.Final" level="project" />
+    <orderEntry type="library" name="Maven: io.github.pnoker:dc3-common-log:2023.4.5" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-context:5.3.27" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-aop:5.3.27" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-expression:5.3.27" level="project" />
+    <orderEntry type="library" name="Maven: org.aspectj:aspectjweaver:1.9.7" level="project" />
+    <orderEntry type="library" name="Maven: io.github.pnoker:dc3-common-model:2023.4.5" level="project" />
+    <orderEntry type="library" name="Maven: com.influxdb:influxdb-client-java:6.8.0" level="project" />
+    <orderEntry type="library" name="Maven: com.influxdb:influxdb-client-core:6.8.0" level="project" />
+    <orderEntry type="library" name="Maven: com.influxdb:influxdb-client-utils:6.8.0" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.commons:commons-csv:1.9.0" level="project" />
+    <orderEntry type="library" name="Maven: com.google.code.gson:gson:2.9.1" level="project" />
+    <orderEntry type="library" name="Maven: io.reactivex.rxjava3:rxjava:3.1.5" level="project" />
+    <orderEntry type="library" name="Maven: com.squareup.retrofit2:adapter-rxjava3:2.9.0" level="project" />
+    <orderEntry type="library" name="Maven: com.squareup.retrofit2:converter-scalars:2.9.0" level="project" />
+    <orderEntry type="library" name="Maven: com.squareup.retrofit2:converter-gson:2.9.0" level="project" />
+    <orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:3.0.2" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.data:spring-data-mongodb:3.4.10" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-tx:5.3.27" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.data:spring-data-commons:2.7.11" level="project" />
+    <orderEntry type="library" name="Maven: org.mongodb:mongodb-driver-core:4.6.1" level="project" />
+    <orderEntry type="library" name="Maven: org.mongodb:bson:4.6.1" level="project" />
+    <orderEntry type="library" scope="RUNTIME" name="Maven: org.mongodb:bson-record-codec:4.6.1" level="project" />
+    <orderEntry type="library" name="Maven: com.baomidou:mybatis-plus-extension:3.5.3.1" level="project" />
+    <orderEntry type="library" name="Maven: org.hibernate.validator:hibernate-validator:6.2.5.Final" level="project" />
+    <orderEntry type="library" name="Maven: jakarta.validation:jakarta.validation-api:2.0.2" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml:classmate:1.5.1" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.13.5" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.13.5" level="project" />
+    <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.14.2" level="project" />
+    <orderEntry type="library" name="Maven: io.github.pnoker:dc3-common-exception:2023.4.5" level="project" />
+    <orderEntry type="library" name="Maven: io.github.pnoker:dc3-common-constant:2023.4.5" level="project" />
+    <orderEntry type="library" name="Maven: cn.hutool:hutool-all:5.8.15" level="project" />
+    <orderEntry type="library" name="Maven: com.alibaba:fastjson:1.2.47" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.retry:spring-retry:1.3.4" level="project" />
+    <orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-starter:2.0.1" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:2.7.11" level="project" />
+    <orderEntry type="library" name="Maven: com.zaxxer:HikariCP:4.0.3" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-jdbc:5.3.27" level="project" />
+    <orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-autoconfigure:2.0.1" level="project" />
+    <orderEntry type="library" name="Maven: org.mybatis:mybatis:3.5.1" level="project" />
+    <orderEntry type="library" name="Maven: org.mybatis:mybatis-spring:2.0.1" level="project" />
+    <orderEntry type="library" name="Maven: org.postgresql:postgresql:42.2.5" level="project" />
+    <orderEntry type="library" name="Maven: net.postgis:postgis-jdbc:2.5.0" level="project" />
+    <orderEntry type="library" name="Maven: net.postgis:postgis-geometry:2.5.0" level="project" />
+    <orderEntry type="library" name="Maven: org.influxdb:influxdb-java:2.21" level="project" />
+    <orderEntry type="library" name="Maven: com.squareup.retrofit2:retrofit:2.9.0" level="project" />
+    <orderEntry type="library" name="Maven: com.squareup.retrofit2:converter-moshi:2.9.0" level="project" />
+    <orderEntry type="library" name="Maven: com.squareup.moshi:moshi:1.8.0" level="project" />
+    <orderEntry type="library" name="Maven: org.msgpack:msgpack-core:0.8.21" level="project" />
+    <orderEntry type="library" name="Maven: com.squareup.okhttp3:okhttp:4.9.3" level="project" />
+    <orderEntry type="library" name="Maven: com.squareup.okio:okio:2.8.0" level="project" />
+    <orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-common:1.6.21" level="project" />
+    <orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib:1.6.21" level="project" />
+    <orderEntry type="library" name="Maven: org.jetbrains:annotations:13.0" level="project" />
+    <orderEntry type="library" name="Maven: com.squareup.okhttp3:logging-interceptor:4.9.3" level="project" />
+    <orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21" level="project" />
+    <orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.21" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.poi:poi-ooxml:5.2.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.poi:poi:5.2.3" level="project" />
+    <orderEntry type="library" name="Maven: commons-codec:commons-codec:1.15" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.commons:commons-math3:3.6.1" level="project" />
+    <orderEntry type="library" name="Maven: com.zaxxer:SparseBitSet:1.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.poi:poi-ooxml-lite:5.2.3" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.xmlbeans:xmlbeans:5.1.1" level="project" />
+    <orderEntry type="library" name="Maven: xml-apis:xml-apis:1.4.01" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.commons:commons-compress:1.21" level="project" />
+    <orderEntry type="library" name="Maven: commons-io:commons-io:2.11.0" level="project" />
+    <orderEntry type="library" name="Maven: com.github.virtuald:curvesapi:1.07" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.17.2" level="project" />
+    <orderEntry type="library" name="Maven: org.apache.commons:commons-collections4:4.4" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-configuration-processor:2.7.11" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-starter-test:2.7.11" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:2.7.11" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:2.7.11" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.jayway.jsonpath:json-path:2.7.0" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: net.minidev:json-smart:2.4.10" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: net.minidev:accessors-smart:2.4.9" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.ow2.asm:asm:9.3" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: jakarta.xml.bind:jakarta.xml.bind-api:2.3.3" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: jakarta.activation:jakarta.activation-api:1.2.2" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:3.22.0" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest:2.2" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter:5.8.2" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-api:5.8.2" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.opentest4j:opentest4j:1.2.0" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-commons:1.8.2" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.apiguardian:apiguardian-api:1.1.2" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-params:5.8.2" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-engine:5.8.2" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-engine:1.8.2" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:4.5.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy:1.12.23" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy-agent:1.12.23" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:3.2" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-junit-jupiter:4.5.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.skyscreamer:jsonassert:1.5.1" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-core:5.3.27" level="project" />
+    <orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.3.27" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:5.3.27" level="project" />
+    <orderEntry type="library" scope="TEST" name="Maven: org.xmlunit:xmlunit-core:2.9.1" level="project" />
+    <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.36" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: org.mapstruct:mapstruct:1.5.3.Final" level="project" />
+    <orderEntry type="library" scope="PROVIDED" name="Maven: org.projectlombok:lombok:1.18.26" level="project" />
+  </component>
+</module>

+ 264 - 0
dc3-gateway/pom.xml

@@ -0,0 +1,264 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  ~ Copyright 2016-present the original author or authors.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      https://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>io.github.pnoker</groupId>
+        <artifactId>iot-dc3</artifactId>
+        <version>2023.4.5</version>
+    </parent>
+
+    <name>${project.artifactId}</name>
+    <artifactId>dc3-gateway</artifactId>
+    <version>2023.4.5</version>
+    <packaging>jar</packaging>
+
+    <inceptionYear>2016-2022</inceptionYear>
+    <url>https://github.com/pnoker/iot-dc3</url>
+    <description>
+        IOT DC3 平台网关,用于限流、权限验证、服务转发、方向代理 等。
+    </description>
+
+    <developers>
+        <developer>
+            <id>pnoker</id>
+            <name>pnoker</name>
+            <email>pnokers@icloud.com</email>
+            <organization>pnoker.github.io</organization>
+        </developer>
+    </developers>
+
+    <licenses>
+        <license>
+            <name>The Apache Software License, Version 2.0</name>
+            <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
+            <distribution>repo</distribution>
+        </license>
+    </licenses>
+
+    <scm>
+        <url>https://github.com/pnoker/iot-dc3</url>
+        <connection>https://github.com/pnoker/iot-dc3.git</connection>
+        <developerConnection>https://github.com/pnoker/iot-dc3.git</developerConnection>
+    </scm>
+
+    <dependencies>
+
+        <!-- Undertow Web 容器 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-webflux</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-netty</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-undertow</artifactId>
+        </dependency>
+
+        <!-- Gateway -->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-gateway</artifactId>
+        </dependency>
+
+        <!-- gRpc Client -->
+        <dependency>
+            <groupId>net.devh</groupId>
+            <artifactId>grpc-client-spring-boot-starter</artifactId>
+        </dependency>
+
+        <!-- DC3 Center Register Client Starter -->
+        <dependency>
+            <groupId>io.github.pnoker</groupId>
+            <artifactId>dc3-starter-center-register-nacos-client</artifactId>
+        </dependency>
+
+        <!-- Redis reactive -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
+        </dependency>
+
+        <!-- &lt;!&ndash; Resilience4j reactive &ndash;&gt;
+         <dependency>
+             <groupId>org.springframework.cloud</groupId>
+             <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
+         </dependency>-->
+
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
+        </dependency>
+
+        <!-- DC3 Api Auth -->
+        <dependency>
+            <groupId>io.github.pnoker</groupId>
+            <artifactId>dc3-api-auth</artifactId>
+        </dependency>
+
+        <!-- DC3 Common Log -->
+        <dependency>
+            <groupId>io.github.pnoker</groupId>
+            <artifactId>dc3-common-log</artifactId>
+        </dependency>
+
+        <!-- DC3 Common Model -->
+        <dependency>
+            <groupId>io.github.pnoker</groupId>
+            <artifactId>dc3-common-model</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.47</version>
+        </dependency>
+
+        <!--重连-->
+        <dependency>
+            <groupId>org.springframework.retry</groupId>
+            <artifactId>spring-retry</artifactId>
+        </dependency>
+
+        <!-- 数据库 -->
+        <dependency>
+            <groupId>org.mybatis.spring.boot</groupId>
+            <artifactId>mybatis-spring-boot-starter</artifactId>
+            <version>2.0.1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.postgresql</groupId>
+            <artifactId>postgresql</artifactId>
+            <version>42.2.5</version>
+            <!--<scope>runtime</scope>-->
+        </dependency>
+
+        <dependency>
+            <groupId>net.postgis</groupId>
+            <artifactId>postgis-jdbc</artifactId>
+            <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>
+        <repository>
+            <id>public</id>
+            <name>Aliyun Public Repository</name>
+            <url>https://maven.aliyun.com/repository/public</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </repository>
+        <repository>
+            <id>spring</id>
+            <name>Aliyun Spring Repository</name>
+            <url>https://maven.aliyun.com/repository/spring</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </repository>
+        <repository>
+            <id>maven</id>
+            <name>Maven Central Repository</name>
+            <url>https://repo.maven.apache.org/maven2</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </repository>
+        <repository>
+            <id>sonatype</id>
+            <name>Sonatype Repository</name>
+            <url>https://s01.oss.sonatype.org/content/groups/public</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+                <updatePolicy>always</updatePolicy>
+            </snapshots>
+        </repository>
+    </repositories>
+
+    <pluginRepositories>
+        <pluginRepository>
+            <id>public-plugin</id>
+            <name>Aliyun Public Plugin Repository</name>
+            <url>https://maven.aliyun.com/repository/public</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </pluginRepository>
+
+        <pluginRepository>
+            <id>spring-plugin</id>
+            <name>Aliyun Spring Plugin Repository</name>
+            <url>https://maven.aliyun.com/repository/spring-plugin</url>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </pluginRepository>
+    </pluginRepositories>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 45 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/GatewayApplication.java

@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.github.pnoker.gateway;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.retry.annotation.EnableRetry;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+/**
+ * 平台网关服务入口
+ *
+ * @author pnoker
+ * @since 2022.1.0
+ */
+@SpringBootApplication
+//@EnableDiscoveryClient
+/**
+ * 取消服务注册autoRegister = false
+ */
+@EnableDiscoveryClient(autoRegister = false)
+@EnableTransactionManagement
+@EnableRetry
+public class GatewayApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(GatewayApplication.class, args);
+    }
+
+}

+ 30 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/JPBean/JPKprXuChangWaterSS.java

@@ -0,0 +1,30 @@
+package io.github.pnoker.gateway.JPBean;
+
+import io.github.pnoker.gateway.comtool.TimeTool;
+import lombok.Data;
+import org.springframework.util.StringUtils;
+
+/**
+ * @ClassName JPKprXuChangWaterSS
+ * @Description: TODO
+ * @Author LX
+ * @Date 2024/2/3
+ * @Version V1.0
+ **/
+@Data
+public class JPKprXuChangWaterSS {
+    private String freezeDate;
+
+    public boolean checkValid(){
+        if(StringUtils.isEmpty(freezeDate)){
+            return false;
+        }
+        try{
+            TimeTool.convertDateStr2UTC(freezeDate);
+        }catch (Exception ex){
+            //TODO 说明格式不对
+            return false;
+        }
+        return true;
+    }
+}

+ 52 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/SpringContextUtil.java

@@ -0,0 +1,52 @@
+package io.github.pnoker.gateway;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+@Component
+//@Lazy(false) //true为懒加载,在第一次被引用的时候才会创建;false为Spring容器在启动时会立即创建
+//若要明确指定为懒加载,则必须使用@Lazy(true),否则bean对象默认取值lazy-init="false"即@Lazy(false)
+public class SpringContextUtil implements ApplicationContextAware {
+    //Spring应用上下文环境
+    private static ApplicationContext applicationContext;
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        SpringContextUtil.applicationContext = applicationContext;
+    }
+
+    public static ApplicationContext getApplicationContext(){
+        return applicationContext;
+    }
+
+    public static boolean containsBean(String beanName){
+        return applicationContext.containsBean(beanName);
+    }
+
+    public static boolean isSingleton(String beanName) throws NoSuchBeanDefinitionException {
+        return applicationContext.isSingleton(beanName);
+    }
+
+    public static Class getType(String beanName) throws NoSuchBeanDefinitionException {
+        return applicationContext.getType(beanName);
+    }
+
+    public static String[] getAliases(String beanName) throws NoSuchBeanDefinitionException {
+        return applicationContext.getAliases(beanName);
+    }
+
+    public static Object getBean(String beanName) throws BeansException {
+        return applicationContext.getBean(beanName);
+    }
+
+    public static <T> T getBean(Class<T> className) throws BeansException {
+        return applicationContext.getBean(className);
+    }
+
+    public static <T> T getBean(String beanName, Class<T> className) throws BeansException {
+        return applicationContext.getBean(beanName, className);
+    }
+}

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

@@ -0,0 +1,422 @@
+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.ThreadHistoryTask;
+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.ScheduledExecutorService;
+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 获取一个月历史数据
+    public static void checkOneMonth(){
+        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));
+                        }
+                    }
+
+                    List<Map<String, Object>> nullFrequencyList = totalList.stream()
+                            .filter(map -> !map.containsKey("collectionFrequency") || map.get("collectionFrequency") == null)
+                            .collect(Collectors.toList());
+                    // 输出结果
+                    nullFrequencyList.forEach(System.out::println);
+
+                    //TODO 获取到当前类型的设备列表总集后,查询总集的历史数据,并添加到infulxdb
+                    // 根据 采集频率 collectionFrequency (秒)字段进行分组
+                    // 要根据采集频率取建立定时任务
+                    Map<Integer, List<Map<String, Object>>> groupedByFrequency = totalList.stream()
+                            .collect(Collectors.groupingBy(map -> {
+                                Object frequency = map.get("collectionFrequency");
+                                return (frequency == null) ? 0 : (Integer) frequency;
+                            }));
+                    //TODO 创建任务池
+                    ScheduledExecutorService scheduler = ThreadPoolTaskTool.createTaskScheduler(groupedByFrequency.keySet().size());
+
+                    for (Integer groupKey:groupedByFrequency.keySet()){
+                        String taskId = itemType.getString("key")+"_history"+"_"+groupKey;
+                        //TODO 任务时间间隔
+                        if (groupKey==0||groupKey<0){
+                            continue;
+                        }
+                        ThreadHistoryTask threadHistoryTask = new ThreadHistoryTask(taskId,groupKey
+                                ,itemType.getString("key"),groupedByFrequency.get(groupKey));
+                        ThreadPoolTaskTool.scheduleHistroyTask(scheduler,taskId,threadHistoryTask,getInitialDelay()
+                                , 24 * 60 * 60);
+                    }
+                }
+            }
+        }catch(Exception ex){
+            ex.printStackTrace();
+            log.error(TimeTool.convertUTC2DateStr(TimeTool.getCurMsUTC(),TimeTool.TIMESTAMP_FORMAT)
+                    +"获取历史数据异常:"+ex.getLocalizedMessage());
+        }
+    }
+
+    private static long getInitialDelay() {
+        Calendar now = Calendar.getInstance();
+        Calendar nextRun = (Calendar) now.clone();
+
+        // 设置为明天的0点
+        nextRun.set(Calendar.HOUR_OF_DAY, 2);
+        nextRun.set(Calendar.MINUTE, 0);
+        nextRun.set(Calendar.SECOND, 0);
+        nextRun.set(Calendar.MILLISECOND, 0);
+
+        // 如果现在已经过了0点,设置为明天的0点
+        if (now.after(nextRun)) {
+            nextRun.add(Calendar.DAY_OF_MONTH, 1);
+        }
+
+        // 计算从现在到下一个0点的延迟时间(以秒为单位)
+        return (nextRun.getTimeInMillis() - now.getTimeInMillis()) / 1000;
+    }
+
+    //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 放入定时线程执行设备数据备份
+                    Timer timer = new Timer();
+                    timer.schedule(new TimerTask() {
+                        @Override
+                        public void run() {
+                            createExcel(itemType.getString("key"), totalList);
+                            scheduleHourlyTask(timer,itemType.getString("key"), totalList);
+                        }
+                    }, 5000);
+
+
+                    //TODO 获取到当前类型的设备列表总集后,查询总集的实时数据,并添加到infulxdb
+                    // 根据 采集频率 collectionFrequency (秒)字段进行分组
+                    // 要根据采集频率取建立定时任务
+                    Map<Integer, List<Map<String, Object>>> groupedByFrequency = totalList.stream()
+                            .collect(Collectors.groupingBy(map -> {
+                                Object frequency = map.get("collectionFrequency");
+                                return (frequency == null) ? 0 : (Integer) frequency;
+                            }));
+                    //TODO 创建任务池
+                    ScheduledExecutorService scheduler = ThreadPoolTaskTool.createTaskScheduler(groupedByFrequency.keySet().size());
+                    for (Integer groupKey:groupedByFrequency.keySet()){
+                        String taskId = itemType.getString("key")+"_"+groupKey;
+                        //TODO 任务时间间隔
+                        if (groupKey==0||groupKey<0){
+                            continue;
+                        }
+                        ThreadTask threadTask = new ThreadTask(taskId,groupKey
+                        ,itemType.getString("key"),groupedByFrequency.get(groupKey));
+//                        if(itemType.getString("key").equals("ELEC_CTRL_VALVE")) {
+                            ThreadPoolTaskTool.scheduleSecTask(scheduler, taskId, threadTask, groupKey);
+//                        }
+                    }
+                }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());
+        }
+    }
+
+    //TODO 每小时更新设备列表信息excel
+    private static void scheduleHourlyTask(Timer timer,String key,List<Map<String,Object>> totalList) {
+        // 创建一个每小时执行的任务
+        TimerTask hourlyTask = new TimerTask() {
+            @Override
+            public void run() {
+                createExcel(key, totalList);
+            }
+        };
+
+        // 设置任务每小时执行一次
+        long delay = 0; // 不延迟,立即开始
+        long period = 3600000; // 每小时执行一次(3600000毫秒 = 1小时)
+        timer.scheduleAtFixedRate(hourlyTask, delay, period);
+    }
+
+    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!");
+    }
+}

+ 40 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/bizmgr/KprXuChangWaterBizFun.java

@@ -0,0 +1,40 @@
+package io.github.pnoker.gateway.bizmgr;
+
+
+import io.github.pnoker.gateway.JPBean.JPKprXuChangWaterSS;
+import io.github.pnoker.gateway.dbdao.DBMgrProxy;
+import io.github.pnoker.gateway.dbdao.services.intef.XuChangCustomerMeterDayReadService;
+
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName KprXuChangWaterBizFun
+ * @Description: TODO
+ * @Author LX
+ * @Date 2024/2/3
+ * @Version V1.0
+ **/
+public class KprXuChangWaterBizFun {
+    private final static String mStrClassName = "KprAuditDashBoardFun";
+    private final static String EMPTY_NULL = "NULL";
+
+    public static XuChangCustomerMeterDayReadService getXuChangCustomerMeterDayReadService(){
+        return DBMgrProxy.getInstance().applyXuChangCustomerMeterDayReadApi();
+    }
+
+    private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+    public static List<Map<String,Object>> dataCenterTogether(JPKprXuChangWaterSS oJsonParam){
+        List<Map<String,Object>> oRes = new ArrayList<>();
+        try{
+            oRes = getXuChangCustomerMeterDayReadService().selectXuChangDayReadList(oJsonParam.getFreezeDate());
+        }catch(Exception ex){
+            oRes = null;
+            return oRes;
+        }
+        return oRes;
+    }
+}

+ 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;
+    }
+}

+ 187 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/CommTool.java

@@ -0,0 +1,187 @@
+package io.github.pnoker.gateway.comtool;
+
+import org.springframework.util.StringUtils;
+
+import java.security.MessageDigest;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class CommTool {
+    public static final char[] HEX_DIGITS;
+    static {
+        HEX_DIGITS = "0123456789ABCDEF".toCharArray();
+    }
+
+    public static String getPlatformByAgent(String strClientType, String strUserAgent){
+        return getPlatformByAgent(!StringUtils.isEmpty(strClientType)?strClientType:strUserAgent);
+    }
+
+    public static String getPlatformByAgent(String strUserAgent){
+        String type = "_";
+        if (StringUtils.isEmpty(strUserAgent))
+            return type;
+
+        if(strUserAgent.contains("Android") || strUserAgent.contains("Linux")) {
+            type = "apk";
+        } else if (strUserAgent.contains("iPhone") || strUserAgent.contains("iPod") || strUserAgent.contains("iPad")){
+            type = "ios";
+        } else if (strUserAgent.indexOf("micromessenger") > -1){
+            type = "wx";
+        } else if (strUserAgent.indexOf("Windows") > -1){
+            type = "pc";
+        }else if (strUserAgent.contains("tri.")){
+            type = strUserAgent;
+        }
+        return type;
+    }
+
+    public static boolean isMobilePlatform(String platform){
+        return ("apk".equals(platform) || "ios".equals(platform) || "wx".equals(platform));
+    }
+
+    public static boolean isTheThisFormatMatch(final String strFormatFilter, String strDesData){
+        if (!StringUtils.isEmpty(strFormatFilter) && !StringUtils.isEmpty(strDesData)) {
+            //正则表达式的模式
+            Pattern p = Pattern.compile(strFormatFilter);
+            //正则表达式的匹配器
+            Matcher m = p.matcher(strDesData);
+            //进行正则匹配
+            return m.matches();
+        }
+        return false;
+    }
+
+    public static int listSize(List<? extends Object> listSrc){
+        return (listSrc==null)?0:listSrc.size();
+    }
+
+    public static int collectionSize(Collection<? extends Object> cc){
+        return (cc==null)?0:cc.size();
+    }
+
+    public static int mapSize(Map<? extends Object, ? extends Object> mapSrc){
+        return (mapSrc==null)?0:mapSrc.size();
+    }
+
+    public static int lenString(String strSrc) {
+        if (StringUtils.isEmpty(strSrc))
+            return 0;
+        return strSrc.length();
+    }
+
+    public static boolean strBetweenLen(String strSrc, int nMinLen, int nMaxLen){
+        if (strSrc == null || nMinLen > nMaxLen)
+            return false;
+        return strSrc.length() >= nMinLen && strSrc.length() <= nMaxLen;
+    }
+
+    /**
+     * 从订单id中提取订单的创建时间,并以yyyyMMddHHmmss时间格式返回
+     * @param strOrderId
+     * @return
+     */
+    public static String getOrderTmStrFromOrderID(String strOrderId){
+        try {
+            String time = "";
+            int nStartIndex = 3; //所有工单的标识为前三个字符标识
+            time = strOrderId.substring(nStartIndex, nStartIndex+TimeTool.TIMESTAMP_FORMAT_EX2.length());
+            return time.trim();
+        }catch (Exception e){}
+        return "";
+    }
+
+    public static String list2QueryIn(List<? extends Object> listSrc){
+        StringBuilder str = new StringBuilder("");
+        if (listSrc != null && listSrc.size() > 0){
+            str.append("(");
+            int nStart = 0;
+            for (Object item:listSrc){
+                if (nStart++ > 0)
+                    str.append(",");
+                if (item instanceof String){
+                    str.append("'"+item+"'");
+                }else{
+                    str.append(item);
+                }
+            }
+            str.append(")");
+        }
+        return str.toString();
+    }
+
+    public static int totalCharCountsInStr(String srcStr, char chDes){
+        int nums = 0;
+        if (StringUtils.isEmpty(srcStr))
+            return nums;
+
+        char[] arr = srcStr.toCharArray();
+        for (char ch:arr){
+            if (ch == chDes)
+                nums++;
+        }
+        return nums;
+    }
+
+
+    public static String escapeInHex(final String src) {
+        StringBuilder tmp = new StringBuilder("");
+        if (StringUtils.isEmpty(src))
+            return tmp.toString();
+
+        int i;
+        char j;
+        tmp.ensureCapacity(src.length() * 6);
+        for (i = 0; i < src.length(); i++) {
+            j = src.charAt(i);
+            if (Character.isDigit(j) || Character.isLowerCase(j) || Character.isUpperCase(j))
+                tmp.append(j);
+            else if (j < 256) {
+                tmp.append(j);
+                /*tmp.append("%");
+                if (j < 16)
+                    tmp.append("0");
+                tmp.append(Integer.toString(j, 16));
+                */
+            } else {
+                //tmp.append("%u");
+                //tmp.append(Integer.toString(j, 16));
+                tmp.append("&#x");
+                tmp.append(Integer.toString(j, 16));
+                tmp.append(";");
+            }
+        }
+        return tmp.toString();
+    }
+
+    private static final String PHONE_MATCH_FILTER = "^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}$";
+    public static String adjustMobilePhone(String phone){
+        if (!StringUtils.isEmpty(phone)
+                && phone.length() == 11
+                && isTheThisFormatMatch(PHONE_MATCH_FILTER, phone)){
+            return phone;
+        }
+        return "";
+    }
+
+    private static String exchangeMD5(String md5){
+        StringBuilder res = new StringBuilder("");
+        int len = md5.length()/2;
+        for (int i=0; i<len; i++){
+            int index = i*2;
+            res.append(Integer.toHexString((Integer.parseInt(String.valueOf(md5.charAt(index+1)), 16)<<4 | Integer.parseInt(String.valueOf(md5.charAt(index)), 16)) % 16).toUpperCase());
+        }
+        //for (int i = 0,j = md5.length()-1; i<=j; i++,j--){
+        //    res.append(Integer.toHexString(((0x0F & md5.charAt(i)) ^ (0x0F & md5.charAt(j)))).toUpperCase());
+        //}
+        return res.toString();
+    }
+
+
+    public static List safeList(List<? extends Object> listSrc){
+        if (listSrc == null)
+            return new ArrayList();
+        else
+            return listSrc;
+    }
+}

File diff ditekan karena terlalu besar
+ 137 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/HttpTool.java


+ 114 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/ResponseCode.java

@@ -0,0 +1,114 @@
+package io.github.pnoker.gateway.comtool;
+
+/**
+ * RESULT_开头的为响应体中的结果码rescode
+ * STATUS_开头的为HTTP Status响应码
+ */
+public enum ResponseCode {
+    RESULT_NORMAL(0, "Normal result."),
+    RESULT_BAD(1, "Bad result,see the message/data for reason."),
+
+    STATUS_SUCCESS(200, "Success"),
+    STATUS_BAD_REQUEST(600, "Bad Request,see the message/data for reason."),
+    STATUS_ACCESS_DENY(603, "Access denied."),
+    STATUS_NOT_FOUND_URI(604, "No mapping found for HTTP request with URI."),
+    STATUS_METHOD_NOT_ALLOWED(605, "Method Not Allowed."),
+    STATUS_HTTP_TYPE_NOT_ACCEPTABLE(606, "Http media type not acceptable."),
+    STATUS_HTTP_TYPE_NOT_SUPPORTED(615, "Http media type not supported."),
+    STATUS_INTERNAL_SERVER_ERROR(700, "Internal Server Error."),
+    STATUS_SERVER_RUN_ERROR(1000,"The server is abnormal."),
+    STATUS_NULL_POINT_EXCEPTION(1001, "Empty param or param is null."),
+    STATUS_ERROR_DATA_TYPE(1002, "The data type is wrong."),
+    STATUS_IO_EXCEPTION(1003, "IO exception."),
+    STATUS_NO_SUCH_METHOD(1004, "No such method."),
+    STATUS_INDEX_OUT_OF_BOUNDS(1005, "Index out of bounds."),
+    STATUS_ERROR_JSON_FORMAT(1006, "Error JSON data format."),
+    STATUS_NOT_POST_REQUEST(1007, "Not post request."),
+    STATUS_NOT_DELETE_REQUEST(1008, "Not delete request."),
+    STATUS_ERROR_PARAM_FORMAT(1009, "Error parameter format."),
+    STATUS_INVALID_CONTENT_TYPE(1010, "Error Content-Type."),
+    STATUS_NOT_MATCHED_URI(1011, "No mapping found for HTTP request with URI."),
+    STATUS_ERROR_REQUEST_METHOD(1012, "Error request method."),
+    STATUS_NO_USER_ACCOUNT(1013, "No such user or has not login."),
+    STATUS_SERVER_NET_DISCONN_OR_BUSY(1014, "The network of server is down or busy. Please try again later."),
+    STATUS_MAX_CONCURRENT_REQUEST_COUNT(1015, "Exceeded the maximum number of concurrent requests. Please try again later."),
+    STATUS_INVALID_HEADER(1016, "Invalid headers, please check the headers of request."),
+    STATUS_INVALID_SIGN(1017, "Illegal signature, please check and request again."),
+
+    STATUS_EMPTY_TOKEN(2000,"Empty token."),
+    STATUS_INVALID_TOKEN(2001, "Invalidate Token, please re-login."),
+    STATUS_EXPIRED_TOKEN(2002, "Expired Token, please re-login."),
+    STATUS_NOT_LOGGED_IN(2003, "Not logged in."),
+    STATUS_DENY_OPERATE_USER(2004, "No permission to operate."),
+    STATUS_TOO_OLD_TOKEN(2005, "The token is too old, please use your new token."),
+    STATUS_INVALID_OLD_PWD(2006, "The original password is wrong."),
+
+    RESULT_ERROR_SIGN(3000, "Illegal signature"),
+    RESULT_REPEAT_SEQUENCE(3001, "Repeat the request, please check the request sequence number."),
+    RESULT_REQUEST_TIMEOUT(3002, "Request timed out."),
+    RESULT_REQUEST_TOO_BUSY(3003, "Request too busy, please try again later."),
+    RESULT_REPEAT_RECORDS(3004, "Repeat the records, please check the request."),
+    RESULT_REFERENCE_NOT_EXIST(3006, "Reference the not exist, please check the request."),
+
+    RESULT_INVALID_ORDER(4000, "The order number is inconsistent."),//错误或不合法的工单号
+    RESULT_DUPLICATE_ORDER(4001,"The order is already exists."), //指定工单已存在
+    RESULT_ORDER_ACCEPTED(4002, "The order is already accepted."),//指定工单已被接收
+    RESULT_ORDER_DEALED(4003, "The order is already deal."),//指定工单已被处理
+    RESULT_ORDER_ODD_STATUS(4004, "The order status is incorrect.No permission to operation."),//指定工单状态错误,暂无权限做次操作
+    RESULT_ORDER_OWN_CHANGED(4005, "The owner of order is changed.No permission to operation."),//指定工单归属已变更,暂无限操作
+
+    RESULT_USER_ALREADY_REG(8000, "This phone is already registered."),
+    RESULT_DENY_FOR_SAME_PASS(8001, "Two passwords cannot be the same."),
+    RESULT_REFRESH_TOKEN_FAILED(8002, "Refresh token failed, please login again."),
+    RESULT_TOKEN_INVALID_SIGN(8003, "Refresh token failed, invalid signature"),
+    RESULT_INVALID_USER_INFO(8004, "User information verification failed."),
+    RESULT_EXISTS_USER_NAME(8005, "Username already exists."),
+    RESULT_USER_NOT_REG(8006, "This phone is not registered."),
+    RESULT_INNER_JS_SERVER_AUTH_FAILED(8007, "Inner js service verify failed."),
+
+    RESULT_SERVER_NET_DISCONN_OR_BUSY(9000, "The network of server is down or busy. Please try again later."),
+
+    RESULT_INVALID_PUSH_TASK(9100, "The push task is inconsistent."),
+    RESULT_PUSH_TASK_CLOSE(9101, "The push task will be closed."),
+    RESULT_PUSH_TASK_RETRY(9102, "The push task will be next push in the queue."),
+    RESULT_PUSH_FAILED_ERROR_RECEIVER(9103, "Push task failed because of error receiver."),
+    RESULT_PUSH_FAILED_ERROR_OTHERS(9104, "Push task failed because of other errors."),
+    RESULT_PUSH_FAILED_NO_WAY(9105, "Push task failed because of no support the push way."),
+
+    RESULT_FILE_INVALID_TYPE(10000, "Illegal file type."),
+    RESULT_FILE_RW_FILED(10001, "File read/write error."),
+    RESULT_FILE_SIZE_EXCEED(10002, "File size limit exceeded."),
+    RESULT_FILE_PARSE_FAILED(10003, "File parse failed."),
+    RESULT_FILE_EMPTY_ROWS(10004, "File is empty rows."),
+
+    RESULT_NOT_SUPPORT_GEO_WFS_TYPE(20000, "The operation for this geo wfs type is not supported."),
+    RESULT_NOT_SUPPORT_GEO_WFS_WS(20001, "The operation for this geo wfs workspace is not supported."),
+    RESULT_GEO_WFS_TYPE_EMPTY_DATA(20002, "The empty data for this geo wfs type."),
+    RESULT_LABEL_ALREADY_USED(20003, "The Label is already in use."),
+    RESULT_REQ_TO_GEO_SERVER_FAILED(20004, "The request to GeoServer Failed."),
+
+    RESULT_FAST_DFS_UPLOAD_FAILED(30000, "Upload File To FastDfs Failed."),
+
+    BUSINESS_DB_REQ_FAILED(65530,"The DB operation failed."),
+    BUSINESS_API_ABOLISH(65531,"The Api has been abolished."),
+    BUSINESS_BUSY(65532,"Business is busy, please try again."),
+    SERVICE_OFFLINE(65533, "Service offline, please turn off offline mode"),
+    STATUS_UNKNOWN(65534,"Unknown reason,see the message/data for reason."),
+    RESULT_UNKNOWN(65535,"Unknown reason,see the message/data for reason.");
+
+    private String name;
+    private int index;
+    private ResponseCode(int indexC, String strN){
+        index = indexC;
+        name = strN;
+    }
+
+    public int toInt() {return index;}
+    public String toStrCode() {return String.valueOf(index);}
+    public String toStrMsg() {return name;}
+
+    @Override
+    public String toString() {
+        return "StatusCode: " + index + " Message: " + name;
+    }
+}

+ 192 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/ScheduleTaskMgr.java

@@ -0,0 +1,192 @@
+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;
+import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.PostMapping;
+
+import javax.annotation.PostConstruct;
+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
+ * @Description: TODO 定时任务
+ * @Author LX
+ * @Date 2024/2/20
+ * @Version V1.0
+ **/
+@Component
+@EnableScheduling   // 1.开启定时任务
+@EnableAsync        // 2.开启多线程
+public class ScheduleTaskMgr {
+    private final String mBusinessType = "class";
+    private String mStrClassName;
+    public ScheduleTaskMgr() {
+        mStrClassName = this.getClass().getSimpleName();
+    }
+
+    private static final Logger log = LoggerFactory.getLogger(ScheduleTaskMgr.class);
+
+    @Resource
+    private XuchangWaterConfig xuchangWaterConfig;
+
+    /**
+     * 许昌相关
+     */
+
+//    //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 initDangyangApplication(){
+        new Timer().schedule(new TimerTask() {
+            @Override
+            public void run() {
+                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());
+                }
+            }
+        },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);
+                }
+            }
+        }
+    }
+
+    //可以做动态关联,暂时不用了
+//    @PostConstruct
+//    public void initDeviceDefine(){
+//        new Timer().schedule(new TimerTask() {
+//            @Override
+//            public void run() {
+//                KprDangyangWaterBizFun.flushDefine();
+//            }
+//        },5000);
+//    }
+
+    @PostConstruct
+    public void initReal(){
+        new Timer().schedule(new TimerTask() {
+            @Override
+            public void run() {
+                KprDangyangWaterBizFun.checkRealtimeData();
+            }
+        },10000);
+    }
+    @PostConstruct
+    public void initHistory(){
+        new Timer().schedule(new TimerTask() {
+            @Override
+            public void run() {
+                KprDangyangWaterBizFun.checkOneMonth();
+            }
+        },11000);
+    }
+}

+ 244 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/ThreadHistoryTask.java

@@ -0,0 +1,244 @@
+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.utils.HttpUtil;
+import org.influxdb.dto.Point;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+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 ThreadHistoryTask implements Runnable{
+    private static final Logger log = LoggerFactory.getLogger(ThreadHistoryTask.class);
+
+    private final String taskId;
+
+    private final Integer collectionFrequency;//采集频率
+
+    private String deviceType;
+
+    private List<Map<String,Object>> deviceList = new ArrayList<>();
+
+
+
+    public ThreadHistoryTask(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 {
+            LocalDateTime nowTime = LocalDateTime.now();
+            String nowTimeStr = nowTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+            String oneMonthStr = nowTime.minusMonths(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
+            List<JSONObject> deviceRealtimeDataList = new ArrayList<>();
+            int pageSize = 1000;
+            for (Map<String, Object> map : deviceList) {
+                int pageNo = 1;
+                while (true) {
+                    JSONObject devicerealtimeDataTotal = null;
+                    try {
+                        Map<String, String> paramRealtime = new HashMap<>();
+                        paramRealtime.put("deviceType", deviceType);
+                        paramRealtime.put("deviceCode", String.valueOf(map.get("deviceCode")));
+                        paramRealtime.put("pageNo", String.valueOf(pageNo));
+                        paramRealtime.put("pageSize", String.valueOf(pageSize));
+                        paramRealtime.put("startTime", oneMonthStr);
+                        paramRealtime.put("endTime", nowTimeStr);
+                        Map<String, String> headers = new HashMap<>();
+                        headers.put("Authorization", "Bearer " + KprDangyangWaterBizFun.dangyangToken);
+                        devicerealtimeDataTotal = JSONObject.parseObject(HttpUtil.sendGet(
+                                KprDangyangWaterBizFun.hisDataListUrl, paramRealtime, headers));
+                    } catch (Exception ex) {
+                        log.error("历史任务线程" + taskId + " 调用异常:" + ex.getLocalizedMessage());
+                    }
+                    if (devicerealtimeDataTotal == null || devicerealtimeDataTotal.getInteger("code") != 0 ||
+                            devicerealtimeDataTotal.getJSONObject("data") == null
+                            || devicerealtimeDataTotal.getJSONObject("data").getJSONArray("list") == null
+                            || devicerealtimeDataTotal.getJSONObject("data").getJSONArray("list").isEmpty()) {
+                        break;
+                    }
+                    try {
+                        //TODO 查询数据不为空,插入infulxdb
+                        for (int i = 0; i <devicerealtimeDataTotal.getJSONObject("data")
+                                .getJSONArray("list").size(); i++) {
+                            JSONObject deviceRealtimeData = devicerealtimeDataTotal.getJSONObject("data")
+                                    .getJSONArray("list").getJSONObject(i);
+                            adjustTime(deviceRealtimeData, collectionFrequency);//整点rand处理
+                            deviceRealtimeDataList.add(deviceRealtimeData);
+                        }
+                    } catch (Exception ex) {
+                        log.error("历史任务线程" + taskId + " " + String.valueOf(map.get("deviceCode")) + "查询异常:" + ex.getLocalizedMessage() + ";resJson:" + devicerealtimeDataTotal.toJSONString());
+                    }
+                    pageNo++;
+                }
+            }
+            //TODO 开始插入数据库
+            //第三方对应的字段集
+            List<String> params = KprBaseInitFun.getInstance().dangyangParams.get(deviceType);
+            for(JSONObject jsonObject : deviceRealtimeDataList){
+                //deviceType为表名
+                //time为当前数据time的纳秒时间戳,已经做过整点处理了
+                Point pointNanos = createPointFromJson(deviceType,jsonObject,params);
+                if(pointNanos!=null) {
+                    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"));
+        if(nanoTimestamp==0L){
+            return null;
+        }
+        // 创建 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);
+            }
+        }
+        if(!pointBuilder.hasFields()){
+            return null;
+        }
+
+        // 构建 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);
+        long currentTimeNanos = System.currentTimeMillis() * 1_000_000L;
+        if(nanosecondsSinceEpoch>currentTimeNanos){
+            return 0L;
+        }
+        return nanosecondsSinceEpoch;
+    }
+
+    private static final SimpleDateFormat outputDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+    public static void adjustTime(JSONObject deviceRealtimeData, int collectionFrequency) {
+        // 获取原始时间字符串
+        String timeString = deviceRealtimeData.getString("time");
+
+        // 定义日期时间格式
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+        // 解析为 LocalDateTime 对象
+        LocalDateTime originalTime = LocalDateTime.parse(timeString, formatter);
+
+        // 计算最接近的时间间隔
+        long seconds = originalTime.getSecond();
+        long adjustedSeconds = Math.round((double) seconds / collectionFrequency) * collectionFrequency;
+
+        // 创建新的时间
+        LocalDateTime adjustedTime = originalTime.truncatedTo(ChronoUnit.MINUTES).plusSeconds(adjustedSeconds);
+
+        // 更新 JSON 对象中的时间
+        deviceRealtimeData.put("time", adjustedTime.format(formatter));
+    }
+
+}

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

@@ -0,0 +1,39 @@
+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.*;
+
+/**
+ * @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 任务池大小
+     * @return
+     */
+    public static ScheduledExecutorService createTaskScheduler(int poolSize) {
+        ScheduledExecutorService  scheduler =  Executors.newScheduledThreadPool(poolSize);
+
+        return scheduler;
+    }
+    public static void scheduleSecTask(ScheduledExecutorService scheduler,String taskId,ThreadTask threadTask,Integer collectionFrequency) {
+        ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(threadTask, 0, collectionFrequency, TimeUnit.SECONDS);
+        scheduledTasks.put(taskId, future);
+    }
+    public static void scheduleHistroyTask(ScheduledExecutorService scheduler,String taskId,ThreadHistoryTask threadTask,Long initialDelay,Integer collectionFrequency) {
+        ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(threadTask, initialDelay, collectionFrequency, TimeUnit.SECONDS);
+        scheduledTasks.put(taskId, future);
+    }
+}

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

@@ -0,0 +1,238 @@
+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);//时间间隔round处理
+                        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);
+                if(pointNanos!=null) {
+                    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"));
+        if(nanoTimestamp==0L){
+            return null;
+        }
+        // 创建 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);
+            }
+        }
+        if(!pointBuilder.hasFields()){
+            return null;
+        }
+
+        // 构建 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);
+        long currentTimeNanos = System.currentTimeMillis() * 1_000_000L;
+        if(nanosecondsSinceEpoch>currentTimeNanos){
+            return 0L;
+        }
+        return nanosecondsSinceEpoch;
+    }
+
+    private static final SimpleDateFormat outputDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+    public static void adjustTime(JSONObject deviceRealtimeData, int collectionFrequency) {
+        // 获取原始时间字符串
+        String timeString = deviceRealtimeData.getString("time");
+
+        // 定义日期时间格式
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+        // 解析为 LocalDateTime 对象
+        LocalDateTime originalTime = LocalDateTime.parse(timeString, formatter);
+
+        // 计算最接近的时间间隔
+        long seconds = originalTime.getSecond();
+        long adjustedSeconds = Math.round((double) seconds / collectionFrequency) * collectionFrequency;
+
+        // 创建新的时间
+        LocalDateTime adjustedTime = originalTime.truncatedTo(ChronoUnit.MINUTES).plusSeconds(adjustedSeconds);
+
+        // 更新 JSON 对象中的时间
+        deviceRealtimeData.put("time", adjustedTime.format(formatter));
+    }
+
+}

+ 500 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/TimeTool.java

@@ -0,0 +1,500 @@
+package io.github.pnoker.gateway.comtool;
+
+import org.springframework.util.StringUtils;
+
+import java.text.SimpleDateFormat;
+import java.time.*;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+public class TimeTool {
+    public static final long MS_HTTP_REQ_TIMEOUT = 120*1000;  //两分钟的毫秒数
+    public static final long MS_ONE_HALF_MIN = 90*1000;  //一分半钟的毫秒数
+    public static final long MS_ONE_MIN = 60*1000;       //一分钟的毫秒数
+    public static final long MIN_ONE_DAY = 24*60;        //一天中的分
+    public static final long SEC_ONE_DAY = 24*60*60;     //一天中的秒
+    public static final long MS_ONE_DAY = 24*60*60*1000; //一天中的毫秒
+    public static final long MS_ONE_YEAR = 365*MS_ONE_DAY;//一年中的毫秒
+    public static final long MS_ONE_HOUR = 60*60*1000;   //一小时的毫秒
+    public static final String YEAR_FORMAT = "yyyy";
+    public static final String YEAR_MONTH_FORMAT_EX = "yyyyMM";
+    public static final String YEAR_MONTH_FORMAT = "yyyy-MM";
+    public static final String YEAR_MONTH_DAY_FORMAT = "yyyy-MM-dd";
+    public static final String TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss";
+    public static final String TIMESTAMP_FORMAT_EX = "yyyy-MM-dd HH:mm:ss.SSS";
+    public static final String TIMESTAMP_FORMAT_EX2 = "yyyyMMddHHmmss";
+    public static final String TIMESTAMP_FORMAT_EX3 = "yyyyMMddHH";
+    public static final String TIMESTAMP_FORMAT_EX4 = "yyMMddHH";
+    public static final long UTC_MS_START_ONLINE = 1538323200000L;//2018-10-01 00:00:00
+    public static volatile long UTC_MS_TODAY_BEGIN = 0L;
+    public static volatile long UTC_MS_TODAY_END = 0L;
+    public static volatile long UTC_MS_THIS_MONTH_BEGIN = 0L;
+    public static volatile long UTC_MS_THIS_MONTH_END = 0L;
+
+    private static final DateTimeFormatter TIMESTAMP_FORMATTER = DateTimeFormatter.ofPattern(TIMESTAMP_FORMAT);
+    private static final DateTimeFormatter TIMESTAMP_EX_FORMATTER = DateTimeFormatter.ofPattern(TIMESTAMP_FORMAT_EX);
+    private static final DateTimeFormatter TIMESTAMP_EX2_FORMATTER = DateTimeFormatter.ofPattern(TIMESTAMP_FORMAT_EX2);
+    private static final DateTimeFormatter YEAR_MONTH_FORMATTER = DateTimeFormatter.ofPattern(YEAR_MONTH_FORMAT);
+    private static final DateTimeFormatter YEAR_MONTH_DAY_FORMATTER = DateTimeFormatter.ofPattern(YEAR_MONTH_DAY_FORMAT);
+
+    public static void refreshUTCTimeRes(){
+        UTC_MS_TODAY_BEGIN = getTodayBeginUTC();
+        UTC_MS_TODAY_END = getTodayEndUTC();
+        UTC_MS_THIS_MONTH_BEGIN = getMonthBeginUTC(System.currentTimeMillis());
+        UTC_MS_THIS_MONTH_END = getMonthEndUTC(System.currentTimeMillis());
+    }
+
+    private static LocalDateTime strTime2LocalDateTime(String time, String format) {
+        switch (format){
+            case YEAR_MONTH_FORMAT:
+                return LocalDateTime.parse(time, YEAR_MONTH_FORMATTER);
+            case YEAR_MONTH_DAY_FORMAT:
+                return LocalDateTime.parse(time, YEAR_MONTH_DAY_FORMATTER);
+            case TIMESTAMP_FORMAT:
+                return LocalDateTime.parse(time, TIMESTAMP_FORMATTER);
+            case TIMESTAMP_FORMAT_EX:
+                return LocalDateTime.parse(time, TIMESTAMP_EX_FORMATTER);
+            case TIMESTAMP_FORMAT_EX2:
+                return LocalDateTime.parse(time, TIMESTAMP_EX2_FORMATTER);
+            default:
+                return LocalDateTime.parse(time, DateTimeFormatter.ofPattern(format));
+        }
+    }
+
+    private static String localDateTime2StrTime(LocalDateTime localDateTime, String format) {
+        switch (format){
+            case YEAR_MONTH_FORMAT:
+                return localDateTime.format(YEAR_MONTH_FORMATTER);
+            case YEAR_MONTH_DAY_FORMAT:
+                return localDateTime.format(YEAR_MONTH_DAY_FORMATTER);
+            case TIMESTAMP_FORMAT:
+                return localDateTime.format(TIMESTAMP_FORMATTER);
+            case TIMESTAMP_FORMAT_EX:
+                return localDateTime.format(TIMESTAMP_EX_FORMATTER);
+            case TIMESTAMP_FORMAT_EX2:
+                return localDateTime.format(TIMESTAMP_EX2_FORMATTER);
+            default:
+                return localDateTime.format(DateTimeFormatter.ofPattern(format));
+        }
+    }
+
+    private static LocalDateTime utcMsTime2LocalDateTime(long lUTC) {
+        if (!isMsUTC(lUTC)){
+            lUTC = lUTC*1000;
+        }
+        Instant instant = Instant.ofEpochMilli(lUTC);
+        ZoneId zone = ZoneId.systemDefault();
+        return LocalDateTime.ofInstant(instant, zone);
+    }
+
+    private static long localDateTime2UtcMsTime(LocalDateTime localDateTime) {
+        ZoneId zone = ZoneId.systemDefault();
+        Instant instant = localDateTime.atZone(zone).toInstant();
+        return instant.toEpochMilli();
+    }
+
+    private static long strTime2UtcMsTime(String dateStr, String format){
+        return localDateTime2UtcMsTime(strTime2LocalDateTime(dateStr, format));
+    }
+
+    private static String utcMsTime2StrTime(long lUTC, String format){
+        return localDateTime2StrTime(utcMsTime2LocalDateTime(lUTC), format);
+    }
+
+    public static long convertDateStr2UTC(String dateStr){
+        try {
+            dateStr = dateStr.trim();
+            int len = dateStr.length();
+            if (len >= 23)
+                return strTime2UtcMsTime(dateStr, TIMESTAMP_FORMAT_EX);
+            else if (len >= 19)
+                return strTime2UtcMsTime(dateStr, TIMESTAMP_FORMAT);
+            else if (len >= 14)
+                return strTime2UtcMsTime(dateStr, TIMESTAMP_FORMAT_EX2);
+            else if (len >= 10)//即dataStr为yyyy-MM-dd
+                return strTime2UtcMsTime(String.format("%s 00:00:00", dateStr), TIMESTAMP_FORMAT);
+            else if (len >= 7)//即dataStr为yyyy-MM
+                return strTime2UtcMsTime(String.format("%s-01 00:00:00", dateStr), TIMESTAMP_FORMAT);
+            else if (len >= 6)//即dataStr为yyyyMM
+                return strTime2UtcMsTime(String.format("%s01000000", dateStr), TIMESTAMP_FORMAT_EX2);
+            else if (len >= 4)//即dataStr为yyyy
+                return strTime2UtcMsTime(String.format("%s-01-01 00:00:00", dateStr), TIMESTAMP_FORMAT);
+        }catch (Exception e){}
+        return 0L;
+    }
+
+    /**
+     * 指定UTC是否为精确到毫秒的UTC时间
+     * @param lUTC
+     * @return
+     */
+    public static boolean isMsUTC(long lUTC){
+        return lUTC > 10000000000L;
+    }
+
+    public static long getCurSecUTC(){
+        return (System.currentTimeMillis()/1000)*1000;
+    }
+
+    public static long getCurMsUTC(){
+        return System.currentTimeMillis();
+    }
+
+    /**
+     *
+     * @param lUTC  UTC时间格式(单位:毫秒)
+     * @param strDateFormat 日期格式模板:如:yyyy-MM-dd HH:mm:ss
+     * @return
+     */
+    public static String convertUTC2DateStr(long lUTC, String strDateFormat){
+        try {
+            return utcMsTime2StrTime(lUTC<=0?System.currentTimeMillis():lUTC
+                    , StringUtils.isEmpty(strDateFormat)?TIMESTAMP_FORMAT:strDateFormat);
+        }catch (Exception e){}
+        return "";
+    }
+
+    /**
+     * 从当前时间算起,还有多少毫秒今天将结束
+     * @return 所剩的毫秒数
+     */
+    public static long hasMsWhenTodayEnd(){
+        long lR = UTC_MS_TODAY_END+1-System.currentTimeMillis();
+        if (lR <= 0)
+            lR = 1;
+        return lR;
+    }
+
+    /**
+     * 获取过期时间
+     * @param nSeconds 从当前时间算起,nSeconds秒后过期
+     * @return UTC时间格式(单位:毫秒)
+     */
+    public static long createExpiredTime(long nSeconds){
+        nSeconds = nSeconds<0?0:nSeconds;
+        long nowMillis = System.currentTimeMillis();
+        return nowMillis+(nSeconds*1000);
+    }
+
+    /**
+     * 获取当天的开始时间
+     * @return UTC时间格式(单位:毫秒)
+     * 返回时间格式为:00:00:00.000所对应的时间戳
+     */
+    public static long getTodayBeginUTC(){
+        return LocalDateTime.of(LocalDate.now(), LocalTime.MIN)
+                .atZone(ZoneId.systemDefault())
+                .toInstant()
+                .toEpochMilli();
+        /*Calendar todayStart = Calendar.getInstance();
+        todayStart.set(Calendar.HOUR_OF_DAY, 0);
+        todayStart.set(Calendar.MINUTE, 0);
+        todayStart.set(Calendar.SECOND, 0);
+        todayStart.set(Calendar.MILLISECOND, 0);
+        return todayStart.getTime().getTime();*/
+    }
+
+    /**
+     * 获取当天距离最近的整点时刻
+     * @return UTC时间格式(单位:毫秒)
+     * @return
+     */
+    public static long getTodayLastHourUTC(){
+        return LocalDateTime.now().withMinute(0).withSecond(0).withNano(0)
+                .atZone(ZoneId.systemDefault())
+                .toInstant()
+                .toEpochMilli();
+    }
+
+    /**
+     * 获取指定时间当日的起始时刻(即00:00:00.000)
+     * @param tmMS
+     * @return
+     */
+    public static long getBeginUTCOfTime(long tmMS){
+        if (!isMsUTC(tmMS)){
+            tmMS = tmMS*1000;
+        }
+        LocalDateTime startOfDay = LocalDateTime.ofInstant(Instant.ofEpochMilli(tmMS), ZoneId.systemDefault()).with(LocalTime.MIN);
+        return startOfDay.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
+    }
+
+    /**
+     * 获取指定时间当日的结束时刻(即23:59:59.999)
+     * @param tmMS
+     * @return
+     */
+    public static long getEndUTCOfTime(long tmMS){
+        if (!isMsUTC(tmMS)){
+            tmMS = tmMS*1000;
+        }
+        LocalDateTime startOfDay = LocalDateTime.ofInstant(Instant.ofEpochMilli(tmMS), ZoneId.systemDefault()).with(LocalTime.MAX);
+        return startOfDay.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
+    }
+    /**
+     * 获取当天的结束时间
+     * @return UTC时间格式(单位:毫秒)
+     * 返回时间格式为:23:59:59.999所对应的时间戳
+     */
+    public static long getTodayEndUTC(){
+        return LocalDateTime.of(LocalDate.now(), LocalTime.MAX)
+                .atZone(ZoneId.systemDefault())
+                .toInstant()
+                .toEpochMilli();
+        /*Calendar todayStart = Calendar.getInstance();
+        todayStart.set(Calendar.HOUR_OF_DAY, 23);
+        todayStart.set(Calendar.MINUTE, 59);
+        todayStart.set(Calendar.SECOND, 59);
+        todayStart.set(Calendar.MILLISECOND, 999);
+        return todayStart.getTime().getTime();*/
+    }
+
+    /**
+     * 获取当前时间所在月份的开始时间戳
+     * @param curTime
+     * @return UTC时间格式(单位:毫秒)
+     * 返回时间格式为:xxxx-xx-01 00:00:00.000所对应的时间戳
+     */
+    public static long getMonthBeginUTC(long curTime){
+        Calendar c = Calendar.getInstance();
+        if (!isMsUTC(curTime))
+            curTime = curTime*1000;
+        try {
+            c.setTime(new Date(curTime));
+            c.set(Calendar.DAY_OF_MONTH, 1);
+            c.set(Calendar.HOUR_OF_DAY, 0);
+            c.set(Calendar.MINUTE, 0);
+            c.set(Calendar.SECOND,0);
+            c.set(Calendar.MILLISECOND, 0);
+            return c.getTimeInMillis();
+        }catch (Exception e){}
+        return 0L;
+    }
+
+    /**
+     * 获取当前时间所在月份的结束时间戳
+     * @param curTime
+     * @return UTC时间格式(单位:毫秒)
+     * 返回时间格式为:xxxx-xx-31 23:59:59.999所对应的时间戳
+     */
+    public static long getMonthEndUTC(long curTime){
+        Calendar c = Calendar.getInstance();
+        if (!isMsUTC(curTime))
+            curTime = curTime*1000;
+        try {
+            c.setTime(new Date(curTime));
+            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);
+            c.set(Calendar.MILLISECOND, 999);
+            return c.getTimeInMillis();
+        }catch (Exception e){}
+        return 0L;
+    }
+
+    /**
+     * 获取指定时间段内的所有月份列表
+     * @param startTime 起始时间,UTC时间格式,秒或毫秒
+     * @param endTime 结束时间,UTC时间格式,秒或毫秒
+     * @return 月份字符串列表
+     * ["2018-01", "2018-02"]
+     */
+    public static List<String> getMonthListBetween(long startTime, long endTime){
+        ArrayList<String> arrMonth = new ArrayList<>();
+        if (!isMsUTC(startTime))
+            startTime = startTime*1000;
+        if (!isMsUTC(endTime))
+            endTime = endTime*1000;
+        try{
+            String strStart = (new SimpleDateFormat(YEAR_MONTH_FORMAT)).format(new Date(startTime));
+            String strEnd = (new SimpleDateFormat(YEAR_MONTH_FORMAT)).format(new Date(endTime));
+            Date dtStart = (new SimpleDateFormat(YEAR_MONTH_FORMAT)).parse(strStart);
+            Date dtEnd = (new SimpleDateFormat(YEAR_MONTH_FORMAT)).parse(strEnd);
+
+            Calendar dPos = Calendar.getInstance();
+            dPos.setTime(dtStart);                  //设置日期起始时间
+            while (dPos.getTime().before(dtEnd)) {
+                arrMonth.add((new SimpleDateFormat(YEAR_MONTH_FORMAT)).format(dPos.getTime()));
+                dPos.add(Calendar.MONTH, 1);//进行当前日期月份加1
+            }
+            arrMonth.add(strEnd);
+        }catch (Exception e){e.printStackTrace();}
+        return arrMonth;
+    }
+
+    /**
+     * 获取指定时间段内的所有月份列表
+     * @param startTime 起始时间,UTC时间格式,秒或毫秒
+     * @param endTime 结束时间,UTC时间格式,秒或毫秒
+     * @return 月份字符串列表
+     * ["201801", "201802"]
+     */
+    public static List<String> getMonthListBetweenEx(long startTime, long endTime){
+        ArrayList<String> arrMonth = new ArrayList<>();
+        if (!isMsUTC(startTime))
+            startTime = startTime*1000;
+        if (!isMsUTC(endTime))
+            endTime = endTime*1000;
+        try{
+            String strStart = (new SimpleDateFormat(YEAR_MONTH_FORMAT_EX)).format(new Date(startTime));
+            String strEnd = (new SimpleDateFormat(YEAR_MONTH_FORMAT_EX)).format(new Date(endTime));
+            Date dtStart = (new SimpleDateFormat(YEAR_MONTH_FORMAT_EX)).parse(strStart);
+            Date dtEnd = (new SimpleDateFormat(YEAR_MONTH_FORMAT_EX)).parse(strEnd);
+
+            Calendar dPos = Calendar.getInstance();
+            dPos.setTime(dtStart);                  //设置日期起始时间
+            while (dPos.getTime().before(dtEnd)) {
+                arrMonth.add((new SimpleDateFormat(YEAR_MONTH_FORMAT_EX)).format(dPos.getTime()));
+                dPos.add(Calendar.MONTH, 1);//进行当前日期月份加1
+            }
+            arrMonth.add(strEnd);
+        }catch (Exception e){e.printStackTrace();}
+        return arrMonth;
+    }
+
+    /**
+     * 获取指定时间段内的所有月份列表UTC
+     * @param startTime 起始时间,UTC时间格式,秒或毫秒
+     * @param endTime 结束时间,UTC时间格式,秒或毫秒
+     * @return 月份UTC时间戳列表(精确到毫秒)
+     * [2018-01-01 00:00:00.000对应的UTC, 2018-02-01 00:00:00.000对应的UTC]
+     */
+    public static List<Long> getMonthUTCListBetween(long startTime, long endTime){
+        ArrayList<Long> arrMonth = new ArrayList<>();
+        if (!isMsUTC(startTime))
+            startTime = startTime*1000;
+        if (!isMsUTC(endTime))
+            endTime = endTime*1000;
+        try{
+            String strStart = (new SimpleDateFormat(YEAR_MONTH_FORMAT)).format(new Date(startTime));
+            String strEnd = (new SimpleDateFormat(YEAR_MONTH_FORMAT)).format(new Date(endTime));
+            Date dtStart = (new SimpleDateFormat(YEAR_MONTH_FORMAT)).parse(strStart);
+            Date dtEnd = (new SimpleDateFormat(YEAR_MONTH_FORMAT)).parse(strEnd);
+
+            Calendar dPos = Calendar.getInstance();
+            dPos.setTime(dtStart);                  //设置日期起始时间
+            while (dPos.getTime().before(dtEnd)) {
+                arrMonth.add(dPos.getTimeInMillis());
+                dPos.add(Calendar.MONTH, 1);//进行当前日期月份加1
+            }
+            arrMonth.add(dtEnd.getTime());
+        }catch (Exception e){e.printStackTrace();}
+        return arrMonth;
+    }
+
+    /**
+     * 获取指定时间段内的所有月份列表
+     * @param startTime 起始月份,如:2018-01-01 00:00:00
+     * @param endTime 结束月份,如:2018-02-01 00:00:00
+     * @return 月份字符串列表
+     * ["2018-01", "2018-02"]
+     */
+    public static List<String> getMonthListBetween(String startTime, String endTime){
+        try {
+            //Date d1 = new SimpleDateFormat(YEAR_MONTH_FORMAT).parse(startTime);
+            //Date d2 = new SimpleDateFormat(YEAR_MONTH_FORMAT).parse(endTime);
+            return getMonthListBetween(convertDateStr2UTC(startTime), convertDateStr2UTC(endTime));
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 获取指定时间段内的所有月份列表
+     * @param startTime 起始月份,如:2018-01-01 00:00:00
+     * @param endTime 结束月份,如:2018-02-01 00:00:00
+     * @return 月份字符串列表
+     * ["201801", "201802"]
+     */
+    public static List<String> getMonthListBetweenEx(String startTime, String endTime){
+        try {
+            //Date d1 = new SimpleDateFormat(YEAR_MONTH_FORMAT_EX).parse(startTime);
+            //Date d2 = new SimpleDateFormat(YEAR_MONTH_FORMAT_EX).parse(endTime);
+            return getMonthListBetweenEx(convertDateStr2UTC(startTime), convertDateStr2UTC(endTime));
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * 获取指定时间段内的所有月份列表UTC
+     * @param startTime 起始月份,如:2018-01-01 00:00:00
+     * @param endTime 结束月份,如:2018-02-01 00:00:00
+     * @return 月份UTC时间戳列表(精确到秒)
+     * [2018-01-01 00:00:00.000对应的UTC, 2018-02-01 00:00:00.000对应的UTC]
+     */
+    public static List<Long> getMonthUTCListBetween(String startTime, String endTime){
+        try {
+            Date d1 = new SimpleDateFormat(YEAR_MONTH_FORMAT).parse(startTime);
+            Date d2 = new SimpleDateFormat(YEAR_MONTH_FORMAT).parse(endTime);
+            return getMonthUTCListBetween(d1.getTime(), d2.getTime());
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    /**
+     * yyyyMMddhhmmss时间字符串转yyyy-MM-dd HH:mm:ss时间字符串
+     * @param strDateStr
+     * @return
+     */
+    public static String addSplitForDateStr(String strDateStr){
+        if (!StringUtils.isEmpty(strDateStr)){
+            try {
+                return localDateTime2StrTime(strTime2LocalDateTime(strDateStr, TIMESTAMP_FORMAT_EX2), TIMESTAMP_FORMAT);
+            }catch (Exception e){}
+        }
+        return "";
+    }
+
+    /**
+     * 修改指定时间的月份
+     * @param curTime
+     * @param month  > 0 在指定时间上加数个月;< 0 在指定时间上减数个月;
+     * @return
+     */
+    public static long getTimeChgMonth(long curTime, int month){
+        if (month == 0)
+            return curTime;
+        Calendar c = Calendar.getInstance();
+        if (!isMsUTC(curTime))
+            curTime = curTime*1000;
+        try {
+            c.setTime(new Date(curTime));
+            c.add(Calendar.MONTH, month);
+            return c.getTimeInMillis();
+        }catch (Exception e){}
+        return 0L;
+    }
+
+    public static String convertDateObj2DateStr(Date dateObj, String strDateFormat){
+        try {
+            int len = strDateFormat.length();
+            if (len >= 21)
+                return new SimpleDateFormat(TIMESTAMP_FORMAT_EX).format(dateObj);
+            else if (len >= 17)
+                return new SimpleDateFormat(TIMESTAMP_FORMAT).format(dateObj);
+            else if (len >= 12)
+                return new SimpleDateFormat(TIMESTAMP_FORMAT_EX2).format(dateObj);
+            else {
+                int splitCounts = CommTool.totalCharCountsInStr(strDateFormat, '-');
+                if (splitCounts <= 0)
+                    splitCounts = CommTool.totalCharCountsInStr(strDateFormat, '/');
+                if (splitCounts >= 2)
+                    return new SimpleDateFormat(YEAR_MONTH_DAY_FORMAT).format(dateObj);
+                else if (splitCounts >= 1)
+                    return new SimpleDateFormat(YEAR_MONTH_FORMAT).format(dateObj);
+                else
+                    return new SimpleDateFormat(YEAR_MONTH_FORMAT_EX).format(dateObj);
+            }
+        }catch (Exception e){}
+        return new SimpleDateFormat(YEAR_MONTH_DAY_FORMAT).format(dateObj);
+    }
+}

+ 446 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/comtool/XuchangWaterConfig.java

@@ -0,0 +1,446 @@
+package io.github.pnoker.gateway.comtool;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import io.github.pnoker.gateway.dbdao.DBMgrProxy;
+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.tables.XuChangCustomerWaterConfigTable;
+import io.github.pnoker.gateway.dbdao.tables.XuChangCustomerWaterInfoTable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.remoting.RemoteAccessException;
+
+import org.springframework.retry.annotation.Backoff;
+import org.springframework.retry.annotation.Retryable;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+
+import java.io.*;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.charset.StandardCharsets;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+
+/**
+ * @ClassName XuchangWaterConfig
+ * @Description: TODO 许昌800只户表数据查询
+ * @Author LX
+ * @Date 2024/1/30
+ * @Version V1.0
+ **/
+@Configuration
+public class XuchangWaterConfig {
+
+    private static final Logger log = LoggerFactory.getLogger(XuchangWaterConfig.class);
+
+    private static volatile String url = "";
+    private static volatile String user = "";
+    private static volatile String pwd = "";
+
+    private static XuChangCustomerWaterConfigService getXuChangCustomerWaterConfigApi(){
+        return DBMgrProxy.getInstance().applyXuchangCustomerWaterConfigApi();
+    }
+
+    private static XuChangCustomerWaterInfoService getXuChangCustomerWaterInfoApi(){
+        return DBMgrProxy.getInstance().applyXuchangCustomerWaterInfoApi();
+    }
+
+    private static XuChangCustomerMeterDayReadService getXuChangCustomerMeterDayReadApi(){
+        return DBMgrProxy.getInstance().applyXuChangCustomerMeterDayReadApi();
+    }
+
+    //TODO 初始化方法
+    //TODO 远程WebService查询智能水表接口
+    public void init() {
+        try {
+            YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
+//此处是为了找到对应yaml文件的位置
+            yaml.setResources(new ClassPathResource( "application.yml"));
+            Properties properties = yaml.getObject();
+            if(StringUtils.isEmpty(user)) {
+                user = properties.getProperty("xuchang.user");
+            }
+            if(StringUtils.isEmpty(pwd)) {
+                pwd = properties.getProperty("xuchang.pwd");
+            }
+            if(StringUtils.isEmpty(url)) {
+                url = properties.getProperty("xuchang.url");
+            }
+            //TODO 首先查询config配置信息, 通过配置信息查询用户以及日用量记录
+            List<Map<String,Object>> configList = new ArrayList<>();
+            int nTotals = getXuChangCustomerWaterConfigApi().totalCountsEx("", null, null, "");
+            if(nTotals>0){
+                //TODO 优化 以分页方式查询所有,初始分页行数定为3000查询速率较好
+                int pageNum = nTotals%3000==0?nTotals/3000:(nTotals/3000)+1;//总页数
+
+                Integer limit = 3000;
+                if(pageNum<=1){
+                    limit = nTotals;//说明总数比第一页小
+                }
+                for (int i = 0; i < pageNum; i++) {
+                    Integer offset = i*limit;
+                    List<Map<String,Object>> arrTmpDbs = getXuChangCustomerWaterConfigApi().listAllWiths(
+                            limit,
+                            offset,
+                            null,
+                            null,
+                            XuChangCustomerWaterConfigTable.R_INFO.DEFAULT_ORDER,
+                            "");
+                    if(!CollectionUtils.isEmpty(arrTmpDbs)){
+                        configList.addAll(arrTmpDbs);
+                    }
+                }
+            }
+
+            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+            //TODO 得到配置列表后 , 查询相应信息的用户信息和户表信息并进行数据插入
+            //TODO 用户信息相关集合
+            List<Map<String,Object>> dataMaps = new ArrayList<>();
+            List<Map<String,Object>> upDataMaps = new ArrayList<>();
+            List<Map<String,Object>> upAndWheres = new ArrayList<>();//修改条件
+
+            //TODO 日用量信息相关集合
+            List<Map<String,Object>> dayReadDataMaps = new ArrayList<>();
+            List<Map<String,Object>> dayReadUpDataMaps = new ArrayList<>();
+            List<Map<String,Object>> dayReadUpAndWheres = new ArrayList<>();//修改条件
+            for(Map<String,Object> map:configList){
+                //TODO 查询用户信息是否存在 , 若存在则修改 , 不存在则新增
+                JSONArray userArray = getUserInfo(user,pwd,!StringUtils.isEmpty(map.get("user_code"))?map.get("user_code").toString():"");
+                if(userArray!=null&&userArray.size()>0){
+                    JSONObject userObj = JSONObject.parseObject(userArray.get(0).toString());
+                    Map<String,Object> andWheres = new HashMap<>();
+                    andWheres.put(XuChangCustomerWaterInfoTable.R_INFO.METER_ADDR,userObj.getString("meterAddr"));
+                    List<Map<String,Object>> userListRes = getXuChangCustomerWaterInfoApi().listAllWiths(1,0,andWheres,null,"","");
+                    if(CollectionUtils.isEmpty(userListRes)){
+                        //TODO 新增
+                        Map<String,Object> dataMap = new HashMap<>();
+                        dataMap.put("uid","UI"+UUID.randomUUID());
+                        dataMap.put("user_code",userObj.getString("usercode"));
+                        dataMap.put("user_name",userObj.getString("username"));
+                        dataMap.put("door_plate",userObj.getString("doorplate"));
+                        dataMap.put("address",userObj.getString("address"));
+                        dataMap.put("meter_addr",userObj.getString("meterAddr"));
+                        dataMap.put("meter_type_name",userObj.getString("meterTypeName"));
+                        dataMap.put("phone",userObj.getString("phone"));
+                        dataMap.put("reserve",userObj.getString("reserve"));
+                        dataMap.put("remnant",userObj.getString("remnant"));
+                        dataMap.put("gis",map.get("gis"));
+                        dataMap.put("territory",userObj.getString("territory"));
+                        dataMaps.add(dataMap);
+                    }else{
+                        //TODO 修改
+                        Map<String,Object> dataMap = new HashMap<>();
+                        dataMap.put("user_code",userObj.getString("usercode"));
+                        dataMap.put("user_name",userObj.getString("username"));
+                        dataMap.put("door_plate",userObj.getString("doorplate"));
+                        dataMap.put("address",userObj.getString("address"));
+                        dataMap.put("meter_addr",userObj.getString("meterAddr"));
+                        dataMap.put("meter_type_name",userObj.getString("meterTypeName"));
+                        dataMap.put("phone",userObj.getString("phone"));
+                        dataMap.put("reserve",userObj.getString("reserve"));
+                        dataMap.put("remnant",userObj.getString("remnant"));
+                        dataMap.put("gis",map.get("gis"));
+                        dataMap.put("territory",userObj.getString("territory"));
+                        Map<String,Object> aw = new HashMap<>();
+                        aw.put("uid",userListRes.get(0).get("uid"));
+
+                        upAndWheres.add(aw);
+                        upDataMaps.add(dataMap);
+                    }
+                }
+
+                //TODO 用户信息新增/修改完毕后, 然后新增/修改日用量表信息
+                LocalDateTime now = LocalDateTime.now();
+                JSONArray dayReadArray = getFreezeDayDosage(user,pwd,now.minusDays(1).format(formatter),now.format(formatter),
+                        String.valueOf(map.get(XuChangCustomerWaterConfigTable.R_INFO.METER_ADDR)==null?"":map.get(XuChangCustomerWaterConfigTable.R_INFO.METER_ADDR)),1,1000);
+                if(dayReadArray!=null&&dayReadArray.size()>0){
+                    JSONObject dayReadObj = JSONObject.parseObject(dayReadArray.get(0).toString());
+                    Map<String,Object> andWheres = new HashMap<>();
+                    andWheres.put("insert_date",TimeTool.convertDateStr2UTC(dayReadObj.getString("insertDate")));
+                    List<Map<String,Object>> dayReadRes = getXuChangCustomerMeterDayReadApi().listAllWiths(1,0,andWheres,null,"","");
+                    if(CollectionUtils.isEmpty(dayReadRes)) {
+                        //TODO 新增
+                        Map<String,Object> dataMap = new HashMap<>();
+                        dataMap.put("uid","UR"+UUID.randomUUID());
+                        dataMap.put("meter_addr",dayReadObj.getString("meterAddr"));
+                        dataMap.put("begin_date",dayReadObj.getString("beginDate"));
+                        dataMap.put("freeze_date",dayReadObj.getString("freezeDate"));
+                        dataMap.put("begin_number",dayReadObj.getString("beginNumber"));
+                        dataMap.put("end_number",dayReadObj.getString("endNumber"));
+                        dataMap.put("use_number",dayReadObj.getString("useNumber"));
+                        dataMap.put("insert_date", TimeTool.convertDateStr2UTC(dayReadObj.getString("insertDate")));
+
+                        dayReadDataMaps.add(dataMap);
+                    }else{
+                        //TODO 修改
+                        Map<String,Object> dataMap = new HashMap<>();
+                        dataMap.put("meter_addr",dayReadObj.getString("meterAddr"));
+                        dataMap.put("begin_date",dayReadObj.getString("beginDate"));
+                        dataMap.put("freeze_date",dayReadObj.getString("freezeDate"));
+                        dataMap.put("begin_number",dayReadObj.getDoubleValue("beginNumber"));
+                        dataMap.put("end_number",dayReadObj.getDoubleValue("endNumber"));
+                        dataMap.put("use_number",dayReadObj.getDoubleValue("useNumber"));
+                        Map<String,Object> aw = new HashMap<>();
+                        aw.put("uid",dayReadRes.get(0).get("uid"));
+                        aw.put("insert_date",dayReadRes.get(0).get("insert_date"));
+
+                        dayReadUpDataMaps.add(dataMap);
+                        dayReadUpAndWheres.add(aw);
+                    }
+                }
+            }
+            int nRes = 0;
+            if(!CollectionUtils.isEmpty(dataMaps)) {
+                nRes = getXuChangCustomerWaterInfoApi().bacthInserts(dataMaps);
+            }
+            if(!CollectionUtils.isEmpty(upDataMaps)){
+                nRes = getXuChangCustomerWaterInfoApi().bacthUpdates(upDataMaps,upAndWheres);
+            }
+            log.info(0+"XuchangWaterConfig"
+                    +String.format("XuchangWaterInfo_Success" + " nRes: %s====>"
+                            ,nRes));
+
+            int nReadRes = 0;
+            if(!CollectionUtils.isEmpty(dayReadDataMaps)) {
+                nReadRes = getXuChangCustomerMeterDayReadApi().bacthInserts(dayReadDataMaps);
+            }
+            if(!CollectionUtils.isEmpty(dayReadUpDataMaps)){
+                nReadRes = getXuChangCustomerMeterDayReadApi().bacthUpdates(dayReadUpDataMaps,dayReadUpAndWheres);
+            }
+            log.info(0+"XuchangWaterConfig"
+                    +String.format("XuchangMeterDayRead_Success" + " nReadRes: %s====>"
+                    ,nReadRes));
+        }catch(Exception ex){
+            ex.printStackTrace();
+            log.error(2+ "XuchangWaterConfig"
+                    +String.format("XuchangWater_Error" + " errorMsg: %s====>"
+                            , ex.getLocalizedMessage()));
+        }
+    }
+
+
+    //TODO 获取表当前数据
+    @Retryable(value = {RemoteAccessException.class}, maxAttempts = 3, backoff = @Backoff(delay = 200L, multiplier = 1))
+    public static JSONArray creatPostAndTransData(String A,String B,int C,String D,int page,int pageSize) {
+        String line = "";
+        // 用来存储接收到的返回值
+        StringBuffer resultStringBuffer = new StringBuffer();
+        OutputStreamWriter out = null;
+        try {
+            // 根据url连接接口
+            URL realUrl = new URL(url);
+            URLConnection urlConnection = realUrl.openConnection();
+            // 根据需要,将传来的接口参数组装为xml文本
+            String xmlInfo = getGetReadNowDataXmlInfo(A,B,C,D,page,pageSize);
+            byte[] xmlInfoBytes = xmlInfo.getBytes();
+            urlConnection.setDoInput(true);
+            urlConnection.setDoOutput(true);
+            urlConnection.setUseCaches(false);
+            urlConnection.setRequestProperty("Content-Type","text/xml; charset=utf-8");
+            urlConnection.setRequestProperty("Content-length",String.valueOf(xmlInfoBytes.length));
+            out = new OutputStreamWriter(urlConnection.getOutputStream());
+            out.write(new String(xmlInfo.getBytes(StandardCharsets.ISO_8859_1)));
+            out.flush();
+            out.close();
+            // 开始接收返回值
+            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
+            for (line = bufferedReader.readLine(); line != null;line = bufferedReader.readLine()) {
+                resultStringBuffer.append(line);
+            }
+            // 从返回的文本中,截取出我们需要的内容
+            int beginIndex = resultStringBuffer.indexOf("<NBIoT_GetReadNowDataResult>") + 28;
+            int endIndex = resultStringBuffer.lastIndexOf("</NBIoT_GetReadNowDataResult>");
+            String jsonString = resultStringBuffer.toString().substring(beginIndex,endIndex);
+            JSONObject result = JSONObject.parseObject(jsonString);
+            String outResult = result.getString("outResult");
+            JSONArray jsonArray = null;
+            if(!StringUtils.isEmpty(outResult)&&"1".equals(outResult)){
+                jsonArray = result.getJSONArray("outData");
+            }else{
+                log.error("waterErrorCode:"+outResult+";waterErrorMsg:"+result.getString("outMsg"));
+            }
+            // List<Map> list = JSONObject.parseArray(jsonArray.toString(),Map.class);
+            return jsonArray;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        } finally {
+            try {
+                if (out != null) {
+                    out.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    //TODO TODO 获取表日用量
+    @Retryable(value = {RemoteAccessException.class}, maxAttempts = 3, backoff = @Backoff(delay = 200L, multiplier = 1))
+    public static JSONArray getFreezeDayDosage(String A,String B,String C,String D,String F,int page,int pageSize) {
+        String line = "";
+        // 用来存储接收到的返回值
+        StringBuffer resultStringBuffer = new StringBuffer();
+        OutputStreamWriter out = null;
+        try {
+            // 根据url连接接口
+            URL realUrl = new URL(url);
+            URLConnection urlConnection = realUrl.openConnection();
+            // 根据需要,将传来的接口参数组装为xml文本
+            String xmlInfo = getGetFreezeDayDosageXmlInfo(A,B,C,D,F,page,pageSize);
+            byte[] xmlInfoBytes = xmlInfo.getBytes();
+            urlConnection.setDoInput(true);
+            urlConnection.setDoOutput(true);
+            urlConnection.setUseCaches(false);
+            urlConnection.setRequestProperty("Content-Type","text/xml; charset=utf-8");
+            urlConnection.setRequestProperty("Content-length",String.valueOf(xmlInfoBytes.length));
+            out = new OutputStreamWriter(urlConnection.getOutputStream());
+            out.write(new String(xmlInfo.getBytes(StandardCharsets.ISO_8859_1)));
+            out.flush();
+            out.close();
+            // 开始接收返回值
+            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
+            for (line = bufferedReader.readLine(); line != null;line = bufferedReader.readLine()) {
+                resultStringBuffer.append(line);
+            }
+            // 从返回的文本中,截取出我们需要的内容
+            int beginIndex = resultStringBuffer.indexOf("<NBIoT_GetFreezeDayDosageResult>") + 32;
+            int endIndex = resultStringBuffer.lastIndexOf("</NBIoT_GetFreezeDayDosageResult>");
+            String jsonString = resultStringBuffer.toString().substring(beginIndex,endIndex);
+            JSONObject result = JSONObject.parseObject(jsonString);
+            String outResult = result.getString("outResult");
+            JSONArray jsonArray = null;
+            if(!StringUtils.isEmpty(outResult)&&"1".equals(outResult)){
+                jsonArray = result.getJSONArray("outData");
+            }else{
+                log.error("waterErrorCode:"+outResult+";waterErrorMsg:"+result.getString("outMsg"));
+            }
+            // List<Map> list = JSONObject.parseArray(jsonArray.toString(),Map.class);
+            return jsonArray;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        } finally {
+            try {
+                if (out != null) {
+                    out.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    //TODO TODO 获取用户信息
+    @Retryable(value = {RemoteAccessException.class}, maxAttempts = 3, backoff = @Backoff(delay = 200L, multiplier = 1))
+    public static JSONArray getUserInfo(String A,String B,String C) {
+        String line = "";
+        // 用来存储接收到的返回值
+        StringBuffer resultStringBuffer = new StringBuffer();
+        OutputStreamWriter out = null;
+        try {
+            // 根据url连接接口
+            URL realUrl = new URL(url);
+            URLConnection urlConnection = realUrl.openConnection();
+            // 根据需要,将传来的接口参数组装为xml文本
+            String xmlInfo = getGetUserInfoXML(A,B,C);
+            byte[] xmlInfoBytes = xmlInfo.getBytes();
+            urlConnection.setDoInput(true);
+            urlConnection.setDoOutput(true);
+            urlConnection.setUseCaches(false);
+            urlConnection.setRequestProperty("Content-Type","text/xml; charset=utf-8");
+            urlConnection.setRequestProperty("Content-length",String.valueOf(xmlInfoBytes.length));
+            out = new OutputStreamWriter(urlConnection.getOutputStream());
+            out.write(new String(xmlInfo.getBytes(StandardCharsets.ISO_8859_1)));
+            out.flush();
+            out.close();
+            // 开始接收返回值
+            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
+            for (line = bufferedReader.readLine(); line != null;line = bufferedReader.readLine()) {
+                resultStringBuffer.append(line);
+            }
+            // 从返回的文本中,截取出我们需要的内容
+            int beginIndex = resultStringBuffer.indexOf("<NBIoT_GetUserInfoResult>") + 25;
+            int endIndex = resultStringBuffer.lastIndexOf("</NBIoT_GetUserInfoResult>");
+            String jsonString = resultStringBuffer.toString().substring(beginIndex,endIndex);
+            JSONObject result = JSONObject.parseObject(jsonString);
+            String outResult = result.getString("outResult");
+            JSONArray jsonArray = null;
+            if(!StringUtils.isEmpty(outResult)&&"1".equals(outResult)){
+                jsonArray = result.getJSONArray("outData");
+            }else{
+                log.error("waterErrorCode:"+outResult+";waterErrorMsg:"+result.getString("outMsg"));
+            }
+            // List<Map> list = JSONObject.parseArray(jsonArray.toString(),Map.class);
+            return jsonArray;
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        } finally {
+            try {
+                if (out != null) {
+                    out.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private static String getGetReadNowDataXmlInfo(String A,String B,int C,String D,int page,int pageSize) {
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
+        stringBuilder.append("<soap:Envelope xmlns:xsi=\"http:/www.w3.org/201/XMLschema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLschema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">");
+        stringBuilder.append("    <soap:Body>");
+        stringBuilder.append("        <NBIoT_GetReadNowData xmlns=\"http://www.suntront.com/\">");
+        stringBuilder.append("            <user>"+A+"</user>");
+        stringBuilder.append("            <pwd>"+B+"</pwd>");
+        stringBuilder.append("            <pageSize>"+pageSize+"</pageSize>");
+        stringBuilder.append("            <currentPageIndex>"+page+"</currentPageIndex>");
+        stringBuilder.append("            <OrderType>"+C+"</OrderType>");
+        stringBuilder.append("            <meterAddr>"+D+"</meterAddr>");
+        stringBuilder.append("        </NBIoT_GetReadNowData>");
+        stringBuilder.append("    </soap:Body>");
+        stringBuilder.append("</soap:Envelope>");
+        return stringBuilder.toString();
+    }
+    private static String getGetFreezeDayDosageXmlInfo(String A,String B,String C,String D,String F,int page,int pageSize) {
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
+        stringBuilder.append("<soap:Envelope xmlns:xsi=\"http:/www.w3.org/201/XMLschema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLschema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">");
+        stringBuilder.append("    <soap:Body>");
+        stringBuilder.append("        <NBIoT_GetFreezeDayDosage xmlns=\"http://www.suntront.com/\">");
+        stringBuilder.append("            <user>"+A+"</user>");
+        stringBuilder.append("            <pwd>"+B+"</pwd>");
+        stringBuilder.append("            <pageSize>"+pageSize+"</pageSize>");
+        stringBuilder.append("            <currentPageIndex>"+page+"</currentPageIndex>");
+        stringBuilder.append("            <meterAddr>"+F+"</meterAddr>");
+        stringBuilder.append("            <beginDate>"+C+"</beginDate>");
+        stringBuilder.append("            <endDate>"+D+"</endDate>");
+        stringBuilder.append("        </NBIoT_GetFreezeDayDosage>");
+        stringBuilder.append("    </soap:Body>");
+        stringBuilder.append("</soap:Envelope>");
+        return stringBuilder.toString();
+    }
+    private static String getGetUserInfoXML(String A,String B,String C) {
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
+        stringBuilder.append("<soap:Envelope xmlns:xsi=\"http:/www.w3.org/201/XMLschema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLschema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">");
+        stringBuilder.append("    <soap:Body>");
+        stringBuilder.append("        <NBIoT_GetUserInfo xmlns=\"http://www.suntront.com/\">");
+        stringBuilder.append("            <user>"+A+"</user>");
+        stringBuilder.append("            <pwd>"+B+"</pwd>");
+        stringBuilder.append("            <userCode>"+C+"</userCode>");
+        stringBuilder.append("        </NBIoT_GetUserInfo>");
+        stringBuilder.append("    </soap:Body>");
+        stringBuilder.append("</soap:Envelope>");
+        return stringBuilder.toString();
+    }
+}

+ 75 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/config/ExceptionConfig.java

@@ -0,0 +1,75 @@
+/*
+ * Copyright 2016-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.github.pnoker.gateway.config;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.github.pnoker.common.entity.R;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
+import org.springframework.core.annotation.Order;
+import org.springframework.core.io.buffer.DataBufferFactory;
+import org.springframework.http.MediaType;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.lang.NonNull;
+import org.springframework.stereotype.Component;
+import org.springframework.web.server.ResponseStatusException;
+import org.springframework.web.server.ServerWebExchange;
+import org.springframework.web.server.handler.ResponseStatusExceptionHandler;
+import reactor.core.publisher.Mono;
+
+/**
+ * 网关异常通用处理器,只作用在webflux 环境下 , 优先级低于 {@link ResponseStatusExceptionHandler} 执行
+ *
+ * @author pnoker
+ * @since 2022.1.0
+ */
+@Slf4j
+@Order(-1)
+@Component
+@RequiredArgsConstructor
+public class ExceptionConfig implements ErrorWebExceptionHandler {
+
+    private final ObjectMapper objectMapper;
+
+    @NonNull
+    @Override
+    public Mono<Void> handle(ServerWebExchange exchange, @NonNull Throwable throwable) {
+        ServerHttpResponse response = exchange.getResponse();
+
+        if (response.isCommitted()) {
+            return Mono.error(throwable);
+        }
+
+        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
+        if (throwable instanceof ResponseStatusException) {
+            response.setStatusCode(((ResponseStatusException) throwable).getStatus());
+        }
+
+        return response.writeWith(Mono.fromSupplier(() -> {
+            DataBufferFactory bufferFactory = response.bufferFactory();
+            try {
+                return bufferFactory.wrap(objectMapper.writeValueAsBytes(R.fail(throwable.getMessage())));
+            } catch (JsonProcessingException e) {
+                log.error(e.getMessage(), e);
+                return bufferFactory.wrap(new byte[0]);
+            }
+        }));
+    }
+
+}

+ 81 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/config/GatewayConfig.java

@@ -0,0 +1,81 @@
+/*
+ * Copyright 2016-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.github.pnoker.gateway.config;
+
+import io.github.pnoker.gateway.fallback.GatewayFallback;
+import io.github.pnoker.gateway.filter.BlackIpGlobalFilter;
+import io.github.pnoker.gateway.filter.factory.AuthenticGatewayFilterFactory;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.ObjectProvider;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
+import org.springframework.cloud.client.loadbalancer.LoadBalanced;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.MediaType;
+import org.springframework.http.converter.HttpMessageConverter;
+import org.springframework.web.reactive.function.client.WebClient;
+import org.springframework.web.reactive.function.server.RequestPredicates;
+import org.springframework.web.reactive.function.server.RouterFunction;
+import org.springframework.web.reactive.function.server.RouterFunctions;
+import org.springframework.web.reactive.function.server.ServerResponse;
+
+import java.util.stream.Collectors;
+
+/**
+ * 网关配置
+ *
+ * @author pnoker
+ * @since 2022.1.0
+ */
+@Slf4j
+@Configuration
+public class GatewayConfig {
+    private final GatewayFallback gatewayFallback;
+
+    public GatewayConfig(GatewayFallback gatewayFallback) {
+        this.gatewayFallback = gatewayFallback;
+    }
+
+    @Bean
+    @LoadBalanced
+    public WebClient.Builder loadBalancedWebClientBuilder() {
+        return WebClient.builder();
+    }
+
+    @Bean
+    public BlackIpGlobalFilter blackIpGlobalFilter() {
+        return new BlackIpGlobalFilter();
+    }
+
+    @Bean
+    public AuthenticGatewayFilterFactory authenticGatewayFilterFactory() {
+        return new AuthenticGatewayFilterFactory();
+    }
+
+    @Bean
+    @ConditionalOnMissingBean
+    public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) {
+        return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList()));
+    }
+
+    @Bean
+    public RouterFunction<ServerResponse> routerFunction() {
+        return RouterFunctions.route(RequestPredicates.path("/fallback").and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), gatewayFallback);
+    }
+
+}

+ 177 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/config/GlobalData.java

@@ -0,0 +1,177 @@
+package io.github.pnoker.gateway.config;
+
+import org.springframework.util.StringUtils;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.Validator;
+import javax.validation.executable.ExecutableValidator;
+import java.util.*;
+
+public class GlobalData {
+    public final static String ORIGIN_KEY = "Y^c3b5d3z1";    //原始口令:阳春布德泽
+    private boolean mBHttpStatusAlready200 = true;          //HttpStatus返回码是不是总是返回200ok
+    private boolean  mBTokenIsUnique = false;
+    private boolean  mBSvrTestMode = false;
+
+    private Validator mValidForParam = null;
+    private ExecutableValidator mValidForFun = null;
+    private volatile boolean mBUseLocalCache = true;         //是否启用本地缓存
+    private String mStrServerId = "";                          //本服务的ID
+    private int mNOwnerMachineIndex = 0;                      //本服务所在的部署机器的索引编号
+    private int mNOwnerServiceIndex = 0;                      //本服务在部署机器上的服务索引编号
+    private int mNCpuCoresForEnableAsyncSubTask = 8;        //启动异步子任务的最小cpu核心数
+    private volatile boolean mBSwitchTraceLog = true;       //是否开启基于TraceId的日志记录
+    private boolean mBPostGisValid = false;
+
+    private String mStrOperatorAccount = "";
+    private String mStrOperatorPassword = "";
+    private String mStrInternalCallPassword = "";            //本机的内部通信可信任口令
+    private volatile String mStrGeoServerAddress = "";
+    private volatile String mStrKprProxyAddress = "";
+
+    private volatile Map<String, List<String>> dashboardKind2Module = new HashMap<>();
+    private static volatile GlobalData msInstance = null;
+    public static GlobalData getInstance(){
+        if (msInstance == null){
+            synchronized (GlobalData.class){
+                if (msInstance == null)
+                    msInstance = new GlobalData();
+            }
+        }
+        return msInstance;
+    }
+
+    private GlobalData() {
+    }
+
+    public void setCpuCoresForEnableAsyncSubTask(int nCpuCores){
+        this.mNCpuCoresForEnableAsyncSubTask = nCpuCores;
+    }
+
+    public boolean isEnableAsyncSubTask(){
+        //cpu核心数>=指定配置时才启用异步子任务(注:过多线程并发可增加线程间的切换开销,导致单个请求执行时间拉长)
+        return mNCpuCores >= mNCpuCoresForEnableAsyncSubTask;
+    }
+
+    private int mNCpuCores = 1;
+    public int getCpuCores() {
+        return mNCpuCores;
+    }
+
+    public void setCpuCores(int mNCpuCores) {
+        this.mNCpuCores = mNCpuCores;
+    }
+
+    public <T> boolean checkObjectByValidator(T object, Class<?>... classForObject){
+        if (mValidForParam != null){
+            Set<ConstraintViolation<T>> constraintViolations = mValidForParam.validate(object, classForObject);
+            if (!(constraintViolations == null || constraintViolations.size() <= 0))
+                return false;
+        }
+        return true;
+    }
+
+    public Validator getValidForParam() {
+        return mValidForParam;
+    }
+
+    public void setValidForParam(Validator mValidForParam) {
+        this.mValidForParam = mValidForParam;
+    }
+
+    public ExecutableValidator getValidForFun() {
+        return mValidForFun;
+    }
+
+    public void setValidForFun(ExecutableValidator mValidForFun) {
+        this.mValidForFun = mValidForFun;
+    }
+
+    public boolean isTokenMustUnique() {
+        return mBTokenIsUnique;
+    }
+
+    public void setTokenMustUnique(boolean mBTokenIsUnique) {
+        this.mBTokenIsUnique = mBTokenIsUnique;
+    }
+
+    public boolean isSvrTestMode() {
+        return mBSvrTestMode;
+    }
+
+    public void setSvrTestMode(boolean mBSvrTestMode) {
+        this.mBSvrTestMode = mBSvrTestMode;
+    }
+
+    public boolean isHttpStatusAlready200() {
+        return mBHttpStatusAlready200;
+    }
+
+    public void setHttpStatusAlready200(boolean mBHttpStatusAlready200) {
+        this.mBHttpStatusAlready200 = mBHttpStatusAlready200;
+    }
+
+    public boolean isUseLocalCache() { return mBUseLocalCache; }
+
+    public void setUseLocalCache(boolean mBUseLocalCache) { this.mBUseLocalCache = mBUseLocalCache; }
+
+    public String getServerId() { return mStrServerId; }
+
+    public void setServerId(String mStrServerId) { this.mStrServerId = mStrServerId; }
+
+    public int getNOwnerMachineIndex() { return mNOwnerMachineIndex; }
+
+    public void setNOwnerMachineIndex(int mNOwnerMachineIndex) { this.mNOwnerMachineIndex = mNOwnerMachineIndex; }
+
+    public int getNOwnerServiceIndex() { return mNOwnerServiceIndex; }
+
+    public void setNOwnerServiceIndex(int mNOwnerServiceIndex) { this.mNOwnerServiceIndex = mNOwnerServiceIndex; }
+
+    public boolean isSwitchTraceLog() { return mBSwitchTraceLog; }
+
+    public void setSwitchTraceLog(boolean mBSwitchTraceLog) { this.mBSwitchTraceLog = mBSwitchTraceLog; }
+
+    public String getStrOperatorAccount() { return mStrOperatorAccount; }
+
+    public void setStrOperatorAccount(String mStrOperatorAccount) { this.mStrOperatorAccount = mStrOperatorAccount; }
+
+    public String getStrOperatorPassword() { return mStrOperatorPassword; }
+
+    public void setStrOperatorPassword(String mStrOperatorPassword) { this.mStrOperatorPassword = mStrOperatorPassword; }
+
+    public String getInternalCallPassword() { return mStrInternalCallPassword; }
+
+    public void setInternalCallPassword(String mStrInternalCallPassword) { this.mStrInternalCallPassword = mStrInternalCallPassword; }
+
+    public boolean isPostGisValid() { return mBPostGisValid; }
+
+    public void setPostGisValid(boolean mBPostGisValid) { this.mBPostGisValid = mBPostGisValid; }
+
+    public void reInitDashboardModule(String kind, List<String> modules){
+        if (modules == null)
+            return;
+        dashboardKind2Module.put(kind, new ArrayList<>(modules));
+    }
+
+    public List<String> getDashboardModule(String kind){
+        if (StringUtils.isEmpty(kind))
+            return null;
+        return dashboardKind2Module.get(kind);
+    }
+
+    public String getGeoServerAddress() {
+        return mStrGeoServerAddress;
+    }
+
+    public void setGeoServerAddress(String mStrGeoServerAddress) {
+        this.mStrGeoServerAddress = mStrGeoServerAddress;
+    }
+
+    public String getKprProxyAddress() {
+        return mStrKprProxyAddress;
+    }
+
+    public void setKprProxyAddress(String mStrKprProxyAddress) {
+        this.mStrKprProxyAddress = mStrKprProxyAddress;
+    }
+}

+ 107 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/config/MainSourceConfiguration.java

@@ -0,0 +1,107 @@
+package io.github.pnoker.gateway.config;
+
+import com.zaxxer.hikari.HikariConfig;
+import com.zaxxer.hikari.HikariDataSource;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.mybatis.spring.SqlSessionFactoryBean;
+import org.mybatis.spring.SqlSessionTemplate;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+
+import javax.annotation.PostConstruct;
+import javax.sql.DataSource;
+
+@Configuration
+@MapperScan(basePackages = "io.github.pnoker.gateway.dbdao.mapper", sqlSessionTemplateRef = "mainSqlSessionTemplate")
+public class MainSourceConfiguration {
+    @Value("${spring.datasource.driver-class-name:}")
+    private String driveClass = "org.postgresql.Driver";
+
+    @Value("${spring.datasource.jdbc-url:}")
+    private String url = "";
+
+    @Value("${spring.datasource.username:}")
+    private String username = "";
+
+    @Value("${spring.datasource.password:}")
+    private String password = "";
+
+    @Value("${spring.datasource.data.maximum-pool-size:200}")
+    private Integer maxPoolSize;
+
+    @Value("${spring.datasource.data.minimum-idle:1}")
+    private Integer minIdle;
+
+    @Value("${spring.datasource.data.connection-test-query:}")
+    private String connectionTestQuery;
+
+    @Value("${spring.datasource.data.max-lifetime:120000}")
+    private Long maxLifetime;
+
+    @Value("${spring.datasource.data.idle-timeout:30000}")
+    private Long idleTimeout;
+
+    @Value("${spring.datasource.data.connection-timeout:30000}")
+    private Long connectionTimeout;
+
+    @Value("${spring.datasource.data.validation-timeout:30000}")
+    private Long validTimeout;
+
+    @Bean(name = "mainDatasource")
+    //@ConfigurationProperties(prefix = "spring.datasource.data")
+    public DataSource mainDataSource() {
+        return new HikariDataSource(getConfig());
+        //return DataSourceBuilder.create().build();
+        //Spring Boot 2.x默认使用HikariCP
+    }
+
+    private HikariConfig getConfig() {
+        HikariConfig hikariConfig = new HikariConfig();
+        hikariConfig.setDriverClassName(driveClass);
+        hikariConfig.setJdbcUrl(url);
+        hikariConfig.setUsername(username);
+        hikariConfig.setPassword(password);
+
+        hikariConfig.setMaximumPoolSize(maxPoolSize);
+        hikariConfig.setMinimumIdle(minIdle);
+        hikariConfig.setConnectionTestQuery(connectionTestQuery);
+        hikariConfig.setMaxLifetime(maxLifetime);
+        hikariConfig.setIdleTimeout(idleTimeout);
+        hikariConfig.setConnectionTimeout(connectionTimeout);
+        hikariConfig.setValidationTimeout(validTimeout);
+        return hikariConfig;
+    }
+
+    @Bean("mainSqlSessionFactory")
+    public SqlSessionFactory mainSqlSessionFactoryBean(@Qualifier("mainDatasource") DataSource dataSource) throws Exception {
+        SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
+        sessionFactoryBean.setDataSource(dataSource);
+
+        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
+        configuration.setCallSettersOnNulls(true);       //数据库中字段值为null时也要求返回
+        configuration.setMapUnderscoreToCamelCase(true); //开启驼峰映射
+        configuration.setCacheEnabled(false);
+        sessionFactoryBean.setConfiguration(configuration);
+        return sessionFactoryBean.getObject();
+    }
+
+    @Bean("mainSqlSessionTemplate")
+    public SqlSessionTemplate mainSqlSessionTemplate(@Qualifier("mainSqlSessionFactory") SqlSessionFactory sessionFactory) {
+        return new SqlSessionTemplate(sessionFactory);
+    }
+
+    @Bean(name = "mainDbTransactionManager")
+    public DataSourceTransactionManager mainDbTransactionManager(@Qualifier("mainDatasource") DataSource dataSource){
+        return new DataSourceTransactionManager(dataSource);
+    }
+
+    @PostConstruct
+    public void init(){
+        GlobalData.getInstance().setPostGisValid("org.postgis.DriverWrapper".equals(driveClass));
+    }
+}

+ 57 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/config/RouteConfig.java

@@ -0,0 +1,57 @@
+/*
+ * Copyright 2016-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.github.pnoker.gateway.config;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
+import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import reactor.core.publisher.Mono;
+
+import java.util.Objects;
+
+/**
+ * 自定义Route配置
+ *
+ * @author pnoker
+ * @since 2022.1.0
+ */
+@Slf4j
+@Configuration
+public class RouteConfig {
+
+    /**
+     * 根据 HostAddress 进行限流
+     *
+     * @return KeyResolver
+     */
+    @Bean
+    public KeyResolver hostKeyResolver() {
+        return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getHostString());
+    }
+
+    /**
+     * Redis 令牌桶 限流
+     *
+     * @return RedisRateLimiter
+     */
+    @Bean
+    RedisRateLimiter redisRateLimiter() {
+        return new RedisRateLimiter(100, 2000);
+    }
+}

+ 95 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/control/KprXuChangWaterController.java

@@ -0,0 +1,95 @@
+package io.github.pnoker.gateway.control;
+
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import io.github.pnoker.gateway.JPBean.JPKprXuChangWaterSS;
+import io.github.pnoker.gateway.bizmgr.KprXuChangWaterBizFun;
+import io.github.pnoker.gateway.comtool.CommTool;
+import io.github.pnoker.gateway.comtool.HttpTool;
+import io.github.pnoker.gateway.config.GlobalData;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.core.io.buffer.DataBufferUtils;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.reactive.function.client.WebClient;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+import retrofit2.http.POST;
+import io.github.pnoker.gateway.comtool.ResponseCode;
+
+import javax.servlet.http.HttpServletRequest;
+import java.nio.CharBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * @ClassName TestController
+ * @Description: TODO
+ * @Author LX
+ * @Date 2024/1/31
+ * @Version V1.0
+ **/
+@RestController
+@RequestMapping("/iot-cloud/gateway/xuchang/water")
+public class KprXuChangWaterController {
+
+    WebClient webClient = WebClient.builder().codecs(configurer->configurer.defaultCodecs().maxInMemorySize(262144)).build();
+
+    @RequestMapping(value = "/newlist",method = {RequestMethod.POST})
+    public Mono<JSONObject> testMono(ServerHttpRequest serverHttpRequest){
+        JSONObject oRes = new JSONObject();
+        long llReqBefore = System.currentTimeMillis();
+        oRes.set("rescode",ResponseCode.RESULT_BAD.toStrCode());
+        oRes.set("msg",".error");
+        oRes.set("resdata","");
+        oRes.set("timestamp", System.currentTimeMillis());
+        try {
+            //TODO webflux获取body
+            Flux<DataBuffer> body = serverHttpRequest.getBody();
+            AtomicReference<String> bodyRef = new AtomicReference<>();
+            body.subscribe(buffer -> {
+                CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
+                DataBufferUtils.release(buffer);
+                bodyRef.set(charBuffer.toString());
+            });
+            String bodyStr = bodyRef.get();
+            if(StringUtils.isEmpty(bodyStr)){
+                oRes.set("rescode", ResponseCode.STATUS_ERROR_JSON_FORMAT.toStrCode());
+                oRes.set("msg", ResponseCode.STATUS_ERROR_JSON_FORMAT.toStrMsg());
+                return Mono.just(oRes);
+            }
+            com.alibaba.fastjson.JSONObject jObj = com.alibaba.fastjson.JSONObject.parseObject(bodyStr);
+            JPKprXuChangWaterSS oJsonParam = jObj.toJavaObject(JPKprXuChangWaterSS.class);
+            if (oJsonParam == null
+                    || !oJsonParam.checkValid()) {
+                oRes.set("rescode", ResponseCode.STATUS_ERROR_JSON_FORMAT.toStrCode());
+                oRes.set("msg", ResponseCode.STATUS_ERROR_JSON_FORMAT.toStrMsg());
+                return Mono.just(oRes);
+            }
+
+
+            List<Map<String, Object>> resResultList = KprXuChangWaterBizFun.dataCenterTogether(oJsonParam);
+            if (!CollectionUtils.isEmpty(resResultList)) {
+                oRes.set("rescode", ResponseCode.RESULT_NORMAL.toStrCode());
+                oRes.set("msg", ".success");
+                oRes.set("resdata", com.alibaba.fastjson.JSONObject.toJSONString(resResultList, SerializerFeature.WriteMapNullValue));
+            }
+
+            return Mono.just(oRes);
+        }catch(Exception ex){
+            ex.printStackTrace();
+            oRes.set("rescode", ResponseCode.RESULT_BAD.toStrCode());
+            oRes.set("msg", ".error");
+            return Mono.just(oRes);
+        }
+    }
+
+}

+ 53 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/DBMgrProxy.java

@@ -0,0 +1,53 @@
+package io.github.pnoker.gateway.dbdao;
+
+import io.github.pnoker.gateway.SpringContextUtil;
+import io.github.pnoker.gateway.dbdao.services.intef.*;
+
+/**
+ * @ClassName DBMgrProxy
+ * @Description: TODO
+ * @Author LX
+ * @Date 2024/2/20
+ * @Version V1.0
+ **/
+public class DBMgrProxy {
+    private volatile XuChangCustomerWaterConfigService xuchangCustomerWaterConfigService= null;
+    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){
+            synchronized (DBMgrProxy.class){
+                if (msInstance == null)
+                    msInstance = new DBMgrProxy();
+            }
+        }
+        return msInstance;
+    }
+
+    private DBMgrProxy() {
+    }
+
+    public void init(){
+        if (xuchangCustomerWaterConfigService == null)
+            xuchangCustomerWaterConfigService = (XuChangCustomerWaterConfigService) SpringContextUtil.getBean(XuChangCustomerWaterConfigService.class);
+        if (xuChangCustomerWaterInfoService == null)
+            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);
+}

+ 96 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/mapper/XuChangCustomerMeterDayReadMapper.java

@@ -0,0 +1,96 @@
+package io.github.pnoker.gateway.dbdao.mapper;
+
+import io.github.pnoker.gateway.dbdao.providers.XuChangCustomerMeterDayReadProvider;
+import io.github.pnoker.gateway.dbdao.tables.XuChangCustomerMeterDayReadTable;
+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 XuChangCustomerMeterDayReadMapper extends XuChangCustomerMeterDayReadTable {
+    @SelectProvider(type = XuChangCustomerMeterDayReadProvider.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 = XuChangCustomerMeterDayReadProvider.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 = XuChangCustomerMeterDayReadProvider.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 = XuChangCustomerMeterDayReadProvider.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 = XuChangCustomerMeterDayReadProvider.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 = XuChangCustomerMeterDayReadProvider.class, method = "batchInsertsOrUpdate")
+    int batchInsertOrUpdate(@Param("inserts") List<Map<String, Object>> inserts
+            , @Param("uniques") List<Object> uniques
+            , @Param("updates") List<Object> updates);
+
+    @InsertProvider(type = XuChangCustomerMeterDayReadProvider.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 = XuChangCustomerMeterDayReadProvider.class, method = "inserts")
+    int inserts(@Param("inserts") Map<String, Object> inserts);
+
+    /**
+     * update和delete返回受影响条数需要配合useAffectedRows=true
+     * @param datas
+     * @param andWheres
+     * @return
+     */
+    @UpdateProvider(type = XuChangCustomerMeterDayReadProvider.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 = XuChangCustomerMeterDayReadProvider.class, method = "deleteInIds")
+    int batchDeleteIn(@Param("ids") List<? extends Object> ids, @Param("extend") String extend);
+
+    @SelectProvider(type = XuChangCustomerMeterDayReadProvider.class, method = "getByUniqueId")
+    Map<String, Object> getOne(@Param("table") String table
+            , @Param("filed") String filed
+            , @Param("id") Object id);
+
+    @InsertProvider(type = XuChangCustomerMeterDayReadProvider.class, method = "batchInserts")
+    int batchInserts(@Param("inserts") List<Map<String, Object>> inserts);
+
+    @UpdateProvider(type = XuChangCustomerMeterDayReadProvider.class, method = "batchUpdateWiths")
+    int batchUpdates(@Param("andWheres") List<Map<String, Object>> andWheres
+            , @Param("datas") List<Map<String, Object>> datas);
+
+
+}

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

@@ -0,0 +1,87 @@
+package io.github.pnoker.gateway.dbdao.mapper;
+
+import io.github.pnoker.gateway.dbdao.providers.XuChangCustomerWaterConfigProvider;
+import io.github.pnoker.gateway.dbdao.tables.XuChangCustomerWaterConfigTable;
+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 XuChangCustomerWaterConfigMapper extends XuChangCustomerWaterConfigTable {
+    @SelectProvider(type = XuChangCustomerWaterConfigProvider.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 = XuChangCustomerWaterConfigProvider.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 = XuChangCustomerWaterConfigProvider.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 = XuChangCustomerWaterConfigProvider.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 = XuChangCustomerWaterConfigProvider.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 = XuChangCustomerWaterConfigProvider.class, method = "batchInsertsOrUpdate")
+    int batchInsertOrUpdate(@Param("inserts") List<Map<String, Object>> inserts
+            , @Param("uniques") List<Object> uniques
+            , @Param("updates") List<Object> updates);
+
+    @InsertProvider(type = XuChangCustomerWaterConfigProvider.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 = XuChangCustomerWaterConfigProvider.class, method = "inserts")
+    int inserts(@Param("inserts") Map<String, Object> inserts);
+
+    /**
+     * update和delete返回受影响条数需要配合useAffectedRows=true
+     * @param datas
+     * @param andWheres
+     * @return
+     */
+    @UpdateProvider(type = XuChangCustomerWaterConfigProvider.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 = XuChangCustomerWaterConfigProvider.class, method = "deleteInIds")
+    int batchDeleteIn(@Param("ids") List<? extends Object> ids, @Param("extend") String extend);
+
+    @SelectProvider(type = XuChangCustomerWaterConfigProvider.class, method = "getByUniqueId")
+    Map<String, Object> getOne(@Param("table") String table
+            , @Param("filed") String filed
+            , @Param("id") Object id);
+}

+ 94 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/mapper/XuChangCustomerWaterInfoMapper.java

@@ -0,0 +1,94 @@
+package io.github.pnoker.gateway.dbdao.mapper;
+
+import io.github.pnoker.gateway.dbdao.providers.XuChangCustomerWaterInfoProvider;
+import io.github.pnoker.gateway.dbdao.tables.XuChangCustomerWaterInfoTable;
+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 XuChangCustomerWaterInfoMapper extends XuChangCustomerWaterInfoTable {
+    @SelectProvider(type = XuChangCustomerWaterInfoProvider.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 = XuChangCustomerWaterInfoProvider.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 = XuChangCustomerWaterInfoProvider.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 = XuChangCustomerWaterInfoProvider.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 = XuChangCustomerWaterInfoProvider.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 = XuChangCustomerWaterInfoProvider.class, method = "batchInsertsOrUpdate")
+    int batchInsertOrUpdate(@Param("inserts") List<Map<String, Object>> inserts
+            , @Param("uniques") List<Object> uniques
+            , @Param("updates") List<Object> updates);
+
+    @InsertProvider(type = XuChangCustomerWaterInfoProvider.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 = XuChangCustomerWaterInfoProvider.class, method = "inserts")
+    int inserts(@Param("inserts") Map<String, Object> inserts);
+
+    /**
+     * update和delete返回受影响条数需要配合useAffectedRows=true
+     * @param datas
+     * @param andWheres
+     * @return
+     */
+    @UpdateProvider(type = XuChangCustomerWaterInfoProvider.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 = XuChangCustomerWaterInfoProvider.class, method = "deleteInIds")
+    int batchDeleteIn(@Param("ids") List<? extends Object> ids, @Param("extend") String extend);
+
+    @SelectProvider(type = XuChangCustomerWaterInfoProvider.class, method = "getByUniqueId")
+    Map<String, Object> getOne(@Param("table") String table
+            , @Param("filed") String filed
+            , @Param("id") Object id);
+
+    @InsertProvider(type = XuChangCustomerWaterInfoProvider.class, method = "batchInserts")
+    int batchInserts(@Param("inserts") List<Map<String, Object>> inserts);
+
+    @UpdateProvider(type = XuChangCustomerWaterInfoProvider.class, method = "batchUpdateWiths")
+    int batchUpdates(@Param("andWheres") List<Map<String, Object>> andWheres
+            , @Param("datas") List<Map<String, Object>> datas);
+}

+ 40 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/mapper/XuChangDayReadNewMapper.java

@@ -0,0 +1,40 @@
+package io.github.pnoker.gateway.dbdao.mapper;
+
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @ClassName XuChangDayReadNewMapper
+ * @Description: TODO
+ * @Author LX
+ * @Date 2024/2/3
+ * @Version V1.0
+ **/
+public interface XuChangDayReadNewMapper {
+
+
+
+    /**
+     * @Author Lx
+     * @Description //TODO 简洁查询指定时间的日分析数据
+     * @Date 15:36 2024/2/3
+     * @Param
+     * @return
+     **/
+    @Select(" SELECT cwi.uid AS cwiUid,cwi.user_code AS userCode,cwi.user_name AS userName,cwi.door_plate AS doorPlate,\n" +
+            " cwi.address AS address,cwi.meter_addr AS meterAddr,cwi.meter_type_name AS meterTypeName,cwi.phone AS phone,\n" +
+            " cwi.reserve AS reserve,cwi.remnant AS remnant,cwi.gis AS gis,cwi.territory AS territory,\n" +
+            " cmdr.uid AS cmdrUid,\n" +
+            " cmdr.begin_date AS beginDate, \n" +
+            " cmdr.freeze_date AS freezeDate\n" +
+            " ,cmdr.begin_number AS beginNumber,cmdr.end_number AS endNumber,\n" +
+            " cmdr.use_number AS useNumber, cmdr.insert_date AS insertDate\n" +
+            " FROM \"k3_xuchang_customer_water_info\" AS cwi\n" +
+            " LEFT JOIN \n" +
+            " (SELECT * FROM \"k3_xuchang_customer_meter_day_read\" AS childcmdr WHERE childcmdr.freeze_date='${freezeDate}') AS cmdr\n" +
+            " ON cwi.meter_addr = cmdr.meter_addr\n")
+    List<Map<String,Object>> selectXuChangDayReadList(@Param("freezeDate") String freezeDate);
+}

File diff ditekan karena terlalu besar
+ 1076 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/providers/BaseSqlProvider.java


+ 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"));
+    }
+}

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

@@ -0,0 +1,60 @@
+package io.github.pnoker.gateway.dbdao.providers;
+
+
+import io.github.pnoker.gateway.dbdao.tables.XuChangCustomerMeterDayReadTable;
+
+/**
+ * @ClassName XuChangCustomerWaterConfigProvider
+ * @Description: TODO
+ * @Author LX
+ * @Date 2024/2/2
+ * @Version V1.0
+ **/
+public class XuChangCustomerMeterDayReadProvider extends BaseSqlProvider implements XuChangCustomerMeterDayReadTable {
+    @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/XuChangCustomerWaterConfigProvider.java

@@ -0,0 +1,60 @@
+package io.github.pnoker.gateway.dbdao.providers;
+
+
+import io.github.pnoker.gateway.dbdao.tables.XuChangCustomerWaterConfigTable;
+
+/**
+ * @ClassName XuChangCustomerWaterConfigProvider
+ * @Description: TODO
+ * @Author LX
+ * @Date 2024/2/2
+ * @Version V1.0
+ **/
+public class XuChangCustomerWaterConfigProvider extends BaseSqlProvider implements XuChangCustomerWaterConfigTable {
+    @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/XuChangCustomerWaterInfoProvider.java

@@ -0,0 +1,60 @@
+package io.github.pnoker.gateway.dbdao.providers;
+
+
+import io.github.pnoker.gateway.dbdao.tables.XuChangCustomerWaterInfoTable;
+
+/**
+ * @ClassName XuChangCustomerWaterConfigProvider
+ * @Description: TODO
+ * @Author LX
+ * @Date 2024/2/2
+ * @Version V1.0
+ **/
+public class XuChangCustomerWaterInfoProvider extends BaseSqlProvider implements XuChangCustomerWaterInfoTable {
+    @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;
+    }
+}

+ 216 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/XuChangCustomerMeterDayReadServiceImpl.java

@@ -0,0 +1,216 @@
+package io.github.pnoker.gateway.dbdao.services;
+
+import io.github.pnoker.gateway.dbdao.mapper.XuChangCustomerMeterDayReadMapper;
+import io.github.pnoker.gateway.dbdao.mapper.XuChangDayReadNewMapper;
+import io.github.pnoker.gateway.dbdao.services.intef.XuChangCustomerMeterDayReadService;
+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 XuChangCustomerWaterInfoServiceImpl
+ * @Description: TODO
+ * @Author LX
+ * @Date 2024/2/2
+ * @Version V1.0
+ **/
+@Service
+public class XuChangCustomerMeterDayReadServiceImpl implements XuChangCustomerMeterDayReadService {
+    private String mStrClassName = "";
+    private String mBusinessType = "";
+    private String logTag = "";
+    private static final Logger log = LoggerFactory.getLogger(XuChangCustomerMeterDayReadServiceImpl.class);
+
+    public XuChangCustomerMeterDayReadServiceImpl() {
+        mStrClassName = this.getClass().getSimpleName();
+        mBusinessType = " XuChangCustomerMeterDayRead";
+        logTag = "XuChangCustomerMeterDayRead";
+    }
+
+    @SuppressWarnings("all")
+    @Autowired
+    private XuChangCustomerMeterDayReadMapper xuChangCustomerMeterDayReadMapper;
+    @SuppressWarnings("all")
+    @Autowired
+    private XuChangDayReadNewMapper xuChangDayReadNewMapper;
+
+    @Override
+    public int totalCountsEx(String table, Map<String, Object> andWheres, Map<String, Object> orWheres, String extend) {
+        int nCode = 0;
+        String strMsg = "Success";
+        try {
+            return xuChangCustomerMeterDayReadMapper.totalCounts(table, andWheres, orWheres, extend);
+        }catch (Exception e){
+            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) {
+        return null;
+    }
+
+    @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 = xuChangCustomerMeterDayReadMapper.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));
+        }
+        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 xuChangCustomerMeterDayReadMapper.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 xuChangCustomerMeterDayReadMapper.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 xuChangCustomerMeterDayReadMapper.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;
+    }
+
+    @Override
+    public int bacthInserts(List<Map<String, Object>> maps) {
+        try {
+            int nRes = xuChangCustomerMeterDayReadMapper.batchInserts(maps);
+            if (nRes > 0) {
+                return nRes;
+            }
+        }catch(Exception ex){
+            ex.printStackTrace();
+            return 0;
+        }
+        return 0;
+    }
+
+    @Override
+    public int bacthUpdates(List<Map<String, Object>> maps,List<Map<String, Object>> andWheres) {
+        try {
+            int nRes = xuChangCustomerMeterDayReadMapper.batchUpdates(andWheres,maps);
+            if (nRes > 0) {
+                return nRes;
+            }
+        }catch(Exception ex){
+            ex.printStackTrace();
+            return 0;
+        }
+        return 0;
+    }
+
+    @Override
+    public List<Map<String, Object>> selectXuChangDayReadList(String freezeDate) {
+        int nCode = 0;
+        String strMsg = "Success";
+        List<Map<String, Object>> arrRes = null;
+        try {
+            arrRes = xuChangDayReadNewMapper.selectXuChangDayReadList(freezeDate);
+        }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 arrRes;
+    }
+}

+ 178 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/XuChangCustomerWaterConfigServiceImpl.java

@@ -0,0 +1,178 @@
+package io.github.pnoker.gateway.dbdao.services;
+
+import io.github.pnoker.gateway.dbdao.mapper.XuChangCustomerWaterConfigMapper;
+import io.github.pnoker.gateway.dbdao.services.intef.XuChangCustomerWaterConfigService;
+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 XuChangCustomerWaterConfigServiceImpl
+ * @Description: TODO
+ * @Author LX
+ * @Date 2024/2/2
+ * @Version V1.0
+ **/
+@Service
+public class XuChangCustomerWaterConfigServiceImpl implements XuChangCustomerWaterConfigService {
+    private String mStrClassName = "";
+    private String mBusinessType = "";
+    private String logTag = "";
+
+    private static final Logger log = LoggerFactory.getLogger(XuChangCustomerWaterConfigServiceImpl.class);
+
+    public XuChangCustomerWaterConfigServiceImpl() {
+        mStrClassName = this.getClass().getSimpleName();
+        mBusinessType = "XuChangCustomerWaterConfig";
+        logTag = "XuchangCustomerWaterConfig";
+    }
+
+    @SuppressWarnings("all")
+    @Autowired
+    private XuChangCustomerWaterConfigMapper xuChangCustomerWaterConfigMapper;
+
+    @Override
+    public int totalCountsEx(String table, Map<String, Object> andWheres, Map<String, Object> orWheres, String extend) {
+        int nCode = 0;
+        String strMsg = "Success";
+        try {
+            return xuChangCustomerWaterConfigMapper.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) {
+        return null;
+    }
+
+    @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 = xuChangCustomerWaterConfigMapper.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 xuChangCustomerWaterConfigMapper.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 xuChangCustomerWaterConfigMapper.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 xuChangCustomerWaterConfigMapper.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;
+    }
+}

+ 202 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/XuChangCustomerWaterInfoServiceImpl.java

@@ -0,0 +1,202 @@
+package io.github.pnoker.gateway.dbdao.services;
+
+import io.github.pnoker.gateway.dbdao.mapper.XuChangCustomerWaterInfoMapper;
+import io.github.pnoker.gateway.dbdao.services.intef.XuChangCustomerWaterInfoService;
+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 XuChangCustomerWaterInfoServiceImpl
+ * @Description: TODO
+ * @Author LX
+ * @Date 2024/2/2
+ * @Version V1.0
+ **/
+@Service
+public class XuChangCustomerWaterInfoServiceImpl implements XuChangCustomerWaterInfoService {
+    private String mStrClassName = "";
+    private String mBusinessType = "";
+    private String logTag = "";
+
+    private static final Logger log = LoggerFactory.getLogger(XuChangCustomerWaterInfoServiceImpl.class);
+
+    public XuChangCustomerWaterInfoServiceImpl() {
+        mStrClassName = this.getClass().getSimpleName();
+        mBusinessType = "XuChangCustomerWaterInfo";
+        logTag = "XuChangCustomerWaterInfo";
+    }
+
+    @SuppressWarnings("all")
+    @Autowired
+    private XuChangCustomerWaterInfoMapper xuChangCustomerWaterInfoMapper;
+
+    @Override
+    public int totalCountsEx(String table, Map<String, Object> andWheres, Map<String, Object> orWheres, String extend) {
+        int nCode = 0;
+        String strMsg = "Success";
+        try {
+            return xuChangCustomerWaterInfoMapper.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) {
+        return null;
+    }
+
+    @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 = xuChangCustomerWaterInfoMapper.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));
+        }
+        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 xuChangCustomerWaterInfoMapper.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 xuChangCustomerWaterInfoMapper.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 xuChangCustomerWaterInfoMapper.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 {
+            nCode = 2;
+            log.error(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;
+    }
+
+    @Override
+    public int bacthInserts(List<Map<String, Object>> maps) {
+        try {
+            int nRes = xuChangCustomerWaterInfoMapper.batchInserts(maps);
+            if (nRes > 0) {
+                return nRes;
+            }
+        }catch(Exception ex){
+            ex.printStackTrace();
+            return 0;
+        }
+        return 0;
+    }
+
+    @Override
+    public int bacthUpdates(List<Map<String, Object>> maps,List<Map<String, Object>> andWheres) {
+        try {
+            int nRes = xuChangCustomerWaterInfoMapper.batchUpdates(andWheres,maps);
+            if (nRes > 0) {
+                return nRes;
+            }
+        }catch(Exception ex){
+            ex.printStackTrace();
+            return 0;
+        }
+        return 0;
+    }
+}

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

@@ -0,0 +1,29 @@
+package io.github.pnoker.gateway.dbdao.services.intef;
+
+import java.util.List;
+import java.util.Map;
+
+public interface BaseDBService {
+    List<Map<String, Object>> listAllWiths(int limit
+            , int offset
+            , Map<String, Object> andWheres
+            , Map<String, Object> orWheres
+            , String orderBy
+            , String extend);
+
+    List<Map<String, Object>> batchQueryIn(List<? extends Object> ids
+            , String orderBy
+            , String extend);
+
+    List<Map<String, Object>> batchQueryWiths(Map<String, Object> andWheres
+            , Map<String, Object> orWheres
+            , String orderBy
+            , String extend);
+
+    int totalCounts(Map<String, Object> andWheres, Map<String, Object> orWheres);
+    Map<String, Object> getOne(Object id);
+    int insertByMap(Map<String, Object> maps);
+    int updateWiths(Map<String, Object> datas, Map<String, Object> andWheres);
+    int delete(Object id);
+    int batchDeleteIn(List<? extends Object> ids, String extend);
+}

+ 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);
+}

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

@@ -0,0 +1,33 @@
+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 XuChangCustomerMeterDayReadService 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);
+
+    int bacthInserts(List<Map<String, Object>> maps);
+    int bacthUpdates(List<Map<String, Object>> maps, List<Map<String, Object>> andWheres);
+
+    //TODO 简洁查询指定日期的日用量信息
+    List<Map<String,Object>> selectXuChangDayReadList(String freezeDate);
+}

+ 27 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/services/intef/XuChangCustomerWaterConfigService.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 XuChangCustomerWaterConfigService 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);
+}

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

@@ -0,0 +1,30 @@
+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 XuChangCustomerWaterInfoService 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);
+
+    int bacthInserts(List<Map<String, Object>> maps);
+    int bacthUpdates(List<Map<String, Object>> maps, List<Map<String, Object>> andWheres);
+}

+ 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
+
+    }
+}

+ 19 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/tables/XuChangCustomerMeterDayReadTable.java

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

+ 27 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/tables/XuChangCustomerWaterConfigTable.java

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

+ 27 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/dbdao/tables/XuChangCustomerWaterInfoTable.java

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

+ 35 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/entity/bo/RequestHeaderBO.java

@@ -0,0 +1,35 @@
+/*
+ * Copyright 2016-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.github.pnoker.gateway.entity.bo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * Request Header BO
+ *
+ * @author pnoker
+ * @since 2022.1.0
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class RequestHeaderBO {
+    private String salt;
+    private String token;
+}

+ 55 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/fallback/GatewayFallback.java

@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.github.pnoker.gateway.fallback;
+
+import io.github.pnoker.common.entity.R;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.server.HandlerFunction;
+import org.springframework.web.reactive.function.server.ServerRequest;
+import org.springframework.web.reactive.function.server.ServerResponse;
+import reactor.core.publisher.Mono;
+
+import java.util.Optional;
+
+
+/**
+ * GatewayFallback
+ *
+ * @author pnoker
+ * @since 2022.1.0
+ */
+@Slf4j
+@Component
+public class GatewayFallback implements HandlerFunction<ServerResponse> {
+
+    @Override
+    public Mono<ServerResponse> handle(ServerRequest serverRequest) {
+        log.info(serverRequest.toString());
+        Optional<Object> originalUris = serverRequest.attribute(ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
+        originalUris.ifPresent(originalUri -> log.error("Request Url:{} , Service Fallback", originalUri));
+        R<String> response = R.fail("No available server for this request");
+        return ServerResponse
+                .status(HttpStatus.INTERNAL_SERVER_ERROR.value())
+                .contentType(MediaType.APPLICATION_JSON)
+                .body(BodyInserters.fromValue(response));
+    }
+}

+ 65 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/filter/BlackIpGlobalFilter.java

@@ -0,0 +1,65 @@
+/*
+ * Copyright 2016-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.github.pnoker.gateway.filter;
+
+import io.github.pnoker.api.center.auth.BlackIpApiGrpc;
+import io.github.pnoker.api.center.auth.IpQuery;
+import io.github.pnoker.api.center.auth.RBlackIpDTO;
+import io.github.pnoker.common.constant.service.AuthServiceConstant;
+import io.github.pnoker.gateway.utils.GatewayUtil;
+import lombok.extern.slf4j.Slf4j;
+import net.devh.boot.grpc.client.inject.GrpcClient;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.core.Ordered;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+/**
+ * 自定义Ip黑名单过滤器
+ *
+ * @author pnoker
+ * @since 2022.1.0
+ */
+@Slf4j
+public class BlackIpGlobalFilter implements GlobalFilter, Ordered {
+
+    @GrpcClient(AuthServiceConstant.SERVICE_NAME)
+    private BlackIpApiGrpc.BlackIpApiBlockingStub blackIpApiBlockingStub;
+
+    @Override
+    public int getOrder() {
+        return 0;
+    }
+
+    @Override
+    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+        ServerHttpRequest request = exchange.getRequest();
+        String remoteIp = GatewayUtil.getRemoteIp(request);
+
+        RBlackIpDTO rBlackIpDTO = blackIpApiBlockingStub.checkBlackIpValid(IpQuery.newBuilder().setIp(remoteIp).build());
+        if (rBlackIpDTO.getResult().getOk()) {
+            log.error("Forbidden Ip: {}", remoteIp);
+            exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
+            return exchange.getResponse().setComplete();
+        }
+
+        return chain.filter(exchange);
+    }
+}

+ 155 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/filter/factory/AuthenticGatewayFilterFactory.java

@@ -0,0 +1,155 @@
+/*
+ * Copyright 2016-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.github.pnoker.gateway.filter.factory;
+
+import cn.hutool.core.text.CharSequenceUtil;
+import cn.hutool.core.util.ObjectUtil;
+import io.github.pnoker.api.center.auth.*;
+import io.github.pnoker.api.common.EnableFlagDTOEnum;
+import io.github.pnoker.common.constant.common.RequestConstant;
+import io.github.pnoker.common.constant.service.AuthServiceConstant;
+import io.github.pnoker.common.entity.R;
+import io.github.pnoker.common.exception.UnAuthorizedException;
+import io.github.pnoker.common.utils.DecodeUtil;
+import io.github.pnoker.common.utils.JsonUtil;
+import io.github.pnoker.gateway.entity.bo.RequestHeaderBO;
+import io.github.pnoker.gateway.utils.GatewayUtil;
+import lombok.extern.slf4j.Slf4j;
+import net.devh.boot.grpc.client.inject.GrpcClient;
+import org.springframework.cloud.gateway.filter.GatewayFilter;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.stereotype.Component;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+import javax.annotation.PostConstruct;
+
+
+/**
+ * 自定义 Request Header 校验过滤器
+ *
+ * @author pnoker
+ * @since 2022.1.0
+ */
+@Slf4j
+@Component
+public class AuthenticGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
+
+    @Override
+    public GatewayFilter apply(Object config) {
+        return new AuthenticGatewayFilter();
+    }
+
+    @Component
+    static class AuthenticGatewayFilter implements GatewayFilter {
+        private static AuthenticGatewayFilter gatewayFilter;
+
+        @GrpcClient(AuthServiceConstant.SERVICE_NAME)
+        private UserLoginApiGrpc.UserLoginApiBlockingStub userLoginApiBlockingStub;
+        @GrpcClient(AuthServiceConstant.SERVICE_NAME)
+        private UserApiGrpc.UserApiBlockingStub userApiBlockingStub;
+        @GrpcClient(AuthServiceConstant.SERVICE_NAME)
+        private TenantApiGrpc.TenantApiBlockingStub tenantApiBlockingStub;
+        @GrpcClient(AuthServiceConstant.SERVICE_NAME)
+        private TokenApiGrpc.TokenApiBlockingStub tokenApiBlockingStub;
+
+        @PostConstruct
+        public void init() {
+            gatewayFilter = this;
+        }
+
+        @Override
+        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+            ServerHttpRequest request = exchange.getRequest();
+
+            try {
+                String tenantHeader = GatewayUtil.getRequestHeader(request, RequestConstant.Header.X_AUTH_TENANT);
+                String tenant = DecodeUtil.byteToString(DecodeUtil.decode(tenantHeader));
+                if (ObjectUtil.isEmpty(tenant)) {
+                    throw new UnAuthorizedException(RequestConstant.Message.INVALID_REQUEST);
+                }
+
+                RTenantDTO rTenantDTO = gatewayFilter.tenantApiBlockingStub.selectByCode(CodeQuery.newBuilder().setCode(tenant).build());
+                if (!rTenantDTO.getResult().getOk() || !EnableFlagDTOEnum.ENABLE.equals(rTenantDTO.getData().getEnableFlag())) {
+                    throw new UnAuthorizedException(RequestConstant.Message.INVALID_REQUEST);
+                }
+
+                String userHeader = GatewayUtil.getRequestHeader(request, RequestConstant.Header.X_AUTH_LOGIN);
+                String user = DecodeUtil.byteToString(DecodeUtil.decode(userHeader));
+                if (ObjectUtil.isEmpty(user)) {
+                    throw new UnAuthorizedException(RequestConstant.Message.INVALID_REQUEST);
+                }
+
+                RUserLoginDTO rUserLoginDTO = gatewayFilter.userLoginApiBlockingStub.selectByName(NameQuery.newBuilder().setName(user).build());
+                if (!rUserLoginDTO.getResult().getOk() || !EnableFlagDTOEnum.ENABLE.equals(rUserLoginDTO.getData().getEnableFlag())) {
+                    throw new UnAuthorizedException(RequestConstant.Message.INVALID_REQUEST);
+                }
+
+                RUserDTO rUserDTO = gatewayFilter.userApiBlockingStub.selectById(IdQuery.newBuilder().setId(rUserLoginDTO.getData().getBase().getId()).build());
+                if (!rUserDTO.getResult().getOk()) {
+                    throw new UnAuthorizedException(RequestConstant.Message.INVALID_REQUEST);
+                }
+
+                String tokenHeader = GatewayUtil.getRequestHeader(request, RequestConstant.Header.X_AUTH_TOKEN);
+                RequestHeaderBO entityBO = JsonUtil.parseObject(DecodeUtil.decode(tokenHeader), RequestHeaderBO.class);
+                if (ObjectUtil.isEmpty(entityBO) || !CharSequenceUtil.isAllNotEmpty(entityBO.getSalt(), entityBO.getToken())) {
+                    throw new UnAuthorizedException(RequestConstant.Message.INVALID_REQUEST);
+                }
+
+                LoginQuery login = LoginQuery.newBuilder()
+                        .setTenant(rTenantDTO.getData().getTenantCode())
+                        .setName(rUserLoginDTO.getData().getLoginName())
+                        .setSalt(entityBO.getSalt())
+                        .setToken(entityBO.getToken()).build();
+                RTokenDTO rTokenDTO = gatewayFilter.tokenApiBlockingStub.checkTokenValid(login);
+                if (!rTokenDTO.getResult().getOk()) {
+                    throw new UnAuthorizedException(RequestConstant.Message.INVALID_REQUEST);
+                }
+
+                ServerHttpRequest build = request.mutate().headers(
+                        httpHeader -> {
+                            httpHeader.set(RequestConstant.Header.X_AUTH_TENANT_ID, rTenantDTO.getData().getBase().getId());
+                            httpHeader.set(RequestConstant.Header.X_AUTH_TENANT, rTenantDTO.getData().getTenantName());
+                            httpHeader.set(RequestConstant.Header.X_AUTH_USER_ID, rUserLoginDTO.getData().getBase().getId());
+                            httpHeader.set(RequestConstant.Header.X_AUTH_NICK, rUserDTO.getData().getNickName());
+                            httpHeader.set(RequestConstant.Header.X_AUTH_USER, rUserDTO.getData().getUserName());
+                        }
+                ).build();
+
+                exchange.mutate().request(build).build();
+            } catch (Exception e) {
+                ServerHttpResponse response = exchange.getResponse();
+                response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
+                response.setStatusCode(HttpStatus.UNAUTHORIZED);
+                log.error(e.getMessage(), e);
+
+                DataBuffer dataBuffer = response.bufferFactory().wrap(JsonUtil.toJsonBytes(R.fail(e.getMessage())));
+                return response.writeWith(Mono.just(dataBuffer));
+            }
+
+            return chain.filter(exchange);
+        }
+    }
+
+}

+ 36 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/init/GatewayInitRunner.java

@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.github.pnoker.gateway.init;
+
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.stereotype.Component;
+
+/**
+ * 初始化
+ *
+ * @author pnoker
+ * @since 2022.1.0
+ */
+@Component
+public class GatewayInitRunner implements ApplicationRunner {
+
+    @Override
+    public void run(ApplicationArguments args) throws Exception {
+        // nothing to do
+    }
+}

+ 24 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/service/FilterService.java

@@ -0,0 +1,24 @@
+/*
+ * Copyright 2016-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.github.pnoker.gateway.service;
+
+/**
+ * @author pnoker
+ * @since 2022.1.0
+ */
+public interface FilterService {
+}

+ 30 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/service/impl/FilterServiceImpl.java

@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.github.pnoker.gateway.service.impl;
+
+import io.github.pnoker.gateway.service.FilterService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author pnoker
+ * @since 2022.1.0
+ */
+@Slf4j
+@Service
+public class FilterServiceImpl implements FilterService {
+}

+ 93 - 0
dc3-gateway/src/main/java/io/github/pnoker/gateway/utils/GatewayUtil.java

@@ -0,0 +1,93 @@
+/*
+ * Copyright 2016-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.github.pnoker.gateway.utils;
+
+import cn.hutool.core.net.NetUtil;
+import cn.hutool.core.text.CharSequenceUtil;
+import cn.hutool.core.util.ObjectUtil;
+import io.github.pnoker.common.constant.common.ExceptionConstant;
+import io.github.pnoker.common.exception.NotFoundException;
+import org.springframework.http.HttpCookie;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+
+import java.net.InetSocketAddress;
+import java.util.Objects;
+
+/**
+ * 网关通用工具类
+ *
+ * @author pnoker
+ * @since 2022.1.0
+ */
+public class GatewayUtil {
+
+    private GatewayUtil() {
+        throw new IllegalStateException(ExceptionConstant.UTILITY_CLASS);
+    }
+
+    /**
+     * 获取远程客户端 IP
+     *
+     * @param request ServerHttpRequest
+     * @return Remote Ip
+     */
+    public static String getRemoteIp(ServerHttpRequest request) {
+        String ip = "";
+        String[] headers = {"X-Original-Forwarded-For", "X-Forwarded-For", "X-Real-IP", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR"};
+        for (String header : headers) {
+            ip = request.getHeaders().getFirst(header);
+            if (!NetUtil.isUnknown(ip)) {
+                return NetUtil.getMultistageReverseProxyIp(ip);
+            }
+        }
+        InetSocketAddress remoteAddress = request.getRemoteAddress();
+        if (!Objects.isNull(remoteAddress)) {
+            ip = remoteAddress.getHostString();
+        }
+        return NetUtil.getMultistageReverseProxyIp(ip);
+    }
+
+    /**
+     * 获取 Request Header
+     *
+     * @param request ServerHttpRequest
+     * @param key     header key
+     * @return request header value
+     */
+    public static String getRequestHeader(ServerHttpRequest request, String key) {
+        String header = request.getHeaders().getFirst(key);
+        if (!CharSequenceUtil.isNotEmpty(header)) {
+            throw new NotFoundException("Invalid request header of " + key);
+        }
+        return header;
+    }
+
+    /**
+     * 获取 Request Cookie
+     *
+     * @param request ServerHttpRequest
+     * @param key     cookie key
+     * @return request cookie value
+     */
+    public static String getRequestCookie(ServerHttpRequest request, String key) {
+        HttpCookie cookie = request.getCookies().getFirst(key);
+        if (ObjectUtil.isNull(cookie) || !CharSequenceUtil.isNotEmpty(cookie.getValue())) {
+            throw new NotFoundException("Invalid request cookie of " + key);
+        }
+        return cookie.getValue();
+    }
+}

+ 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();
+        }
+    }
+}

+ 45 - 0
dc3-gateway/src/main/resources/application-dev.yml

@@ -0,0 +1,45 @@
+#
+# Copyright 2016-present the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Development environment, customizable configuration
+spring:
+  env: dev
+  group: ${user.name}
+  redis:
+    host: ${REDIS_HOST:dc3-redis}
+    port: ${REDIS_PORT:36379}
+    password: ${REDIS_PASSWORD:dc3}
+  cache:
+    redis:
+      time-to-live: ${CACHE_REDIS_TIME_TO_LIVE:5S}
+  cloud:
+    #begin
+    #取消服务注册
+    service-registry:
+          auto-registration:
+            enabled: false
+    #end
+#    nacos:
+#      discovery:
+#        group: ${spring.group}
+#        watch-delay: 5000
+#        username: dc3
+#        password: dc3
+#        #服务器配置
+#        server-addr: 127.0.0.1:8849
+    nacos:
+          discovery:
+            enabled: false

+ 17 - 0
dc3-gateway/src/main/resources/application-prod.yml

@@ -0,0 +1,17 @@
+#
+# Copyright 2016-present the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Product environment, customizable configuration

+ 21 - 0
dc3-gateway/src/main/resources/application-test.yml

@@ -0,0 +1,21 @@
+#
+# Copyright 2016-present the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Test environment, customizable configuration
+spring:
+  cache:
+    redis:
+      time-to-live: ${CACHE_REDIS_TIME_TO_LIVE:15M}

+ 216 - 0
dc3-gateway/src/main/resources/application.yml

@@ -0,0 +1,216 @@
+#
+# Copyright 2016-present the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+server:
+  #服务器配置
+  port: 9309
+  undertow:
+    threads:
+      io: 2
+      worker: 20
+    buffer-size: 512
+
+grpc:
+  client:
+    dc3-center-auth:
+      enable-keep-alive: true
+      keep-alive-without-calls: true
+      negotiation-type: plaintext
+
+spring:
+  application:
+    name: @project.artifactId@
+  profiles:
+    active:
+      - ${NODE_ENV:dev}
+  transaction:
+    rollback-on-commit-failure: true
+  main:
+    allow-bean-definition-overriding: true
+  mvc:
+    throw-exception-if-no-handler-found: true
+  web:
+    resources:
+      add-mappings: false
+  redis:
+    database: 0
+  cache:
+    redis:
+      time-to-live: ${CACHE_REDIS_TIME_TO_LIVE:12H}
+  cloud:
+    gateway:
+      loadbalancer:
+        use404: true
+      discovery:
+        locator:
+          enabled: true
+          lower-case-service-id: true
+      routes:
+        # auth token
+        - id: auth_route_token
+          uri: lb://dc3-center-auth
+          predicates:
+            - Path=/api/v3/auth/token/**
+          filters:
+            - StripPrefix=2
+            - name: RequestRateLimiter
+              args:
+                key-resolver: '#{@hostKeyResolver}'
+                redis-rate-limiter.replenishRate: 10
+                redis-rate-limiter.burstCapacity: 20
+            #- name: CircuitBreaker
+            # args:
+            #   name: default
+            #   fallbackUri: 'forward:/fallback'
+        # auth other
+        - id: auth_route_other
+          uri: lb://dc3-center-auth
+          predicates:
+            - Path=/api/v3/auth/user/**,/api/v3/auth/black_ip/**,/api/v3/auth/tenant/**,/api/v3/auth/dictionary/**
+          filters:
+            - StripPrefix=2
+            - Authentic
+            - name: RequestRateLimiter
+              args:
+                key-resolver: '#{@hostKeyResolver}'
+                redis-rate-limiter.replenishRate: 10
+                redis-rate-limiter.burstCapacity: 20
+            #- name: CircuitBreaker
+            # args:
+            #   name: default
+            #   fallbackUri: 'forward:/fallback'
+        # manager
+        - id: manager_route
+          uri: lb://dc3-center-manager
+          predicates:
+            - Path=/api/v3/manager/**
+          filters:
+            - StripPrefix=2
+            - Authentic
+            - name: RequestRateLimiter
+              args:
+                key-resolver: '#{@hostKeyResolver}'
+                redis-rate-limiter.replenishRate: 10
+                redis-rate-limiter.burstCapacity: 20
+            #- name: CircuitBreaker
+            # args:
+            #   name: default
+            #   fallbackUri: 'forward:/fallback'
+        # data
+        - id: data_route
+          uri: lb://dc3-center-data
+          predicates:
+            - Path=/api/v3/data/**
+          filters:
+            - StripPrefix=2
+            - Authentic
+            - name: RequestRateLimiter
+              args:
+                key-resolver: '#{@hostKeyResolver}'
+                redis-rate-limiter.replenishRate: 10
+                redis-rate-limiter.burstCapacity: 20
+            #- name: CircuitBreaker
+            # args:
+            #   name: default
+            #   fallbackUri: 'forward:/fallback'
+  datasource:
+      driver-class-name: org.postgis.DriverWrapper
+      jdbc-url: jdbc:postgresql_postGIS://192.168.0.4:5432/watersmart?useSSL=false&useAffectedRows=false&allowMultiQueries=true
+      username: postgres
+      password: kpr.23417.postgres
+      data:
+        maximum-pool-size: 200
+        validation-query: SELECT 1
+        connection-test-query: SELECT 1
+        test-on-return: false
+        idle-timeout: 30000
+        connection-timeout: 30000
+  jpa:
+    show-sql: false
+
+logging:
+  level:
+    io.github.pnoker: DEBUG
+  file:
+    name: dc3/logs/gateway/${spring.application.name}.log
+
+#许昌八百支户表相关参数配置,密码为MD532位大写前二十位
+xuchang:
+  user: zzsfy
+  pwd: D41D8CD98F00B204E980
+  url: http://42.227.69.38:8004/WebServiceOfNBIoT.asmx
+
+#当阳influxdb配置
+dangyang:
+#influxdb相关配置
+  inluxdb:
+    database: iot_test
+#    serverUrl: http://192.168.0.4:8086
+#    username: kpr
+#    password: kpr.2024dy.influxdb
+    serverUrl: http://127.0.0.1:8086
+    username: admin
+    password: yourpassword
+#设备数据相关接口地址
+  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,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,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

+ 45 - 0
dc3-gateway/target/classes/application-dev.yml

@@ -0,0 +1,45 @@
+#
+# Copyright 2016-present the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Development environment, customizable configuration
+spring:
+  env: dev
+  group: admin
+  redis:
+    host: ${REDIS_HOST:dc3-redis}
+    port: ${REDIS_PORT:36379}
+    password: ${REDIS_PASSWORD:dc3}
+  cache:
+    redis:
+      time-to-live: ${CACHE_REDIS_TIME_TO_LIVE:5S}
+  cloud:
+    #begin
+    #取消服务注册
+    service-registry:
+          auto-registration:
+            enabled: false
+    #end
+#    nacos:
+#      discovery:
+#        group: ${spring.group}
+#        watch-delay: 5000
+#        username: dc3
+#        password: dc3
+#        #服务器配置
+#        server-addr: 127.0.0.1:8849
+    nacos:
+          discovery:
+            enabled: false

+ 17 - 0
dc3-gateway/target/classes/application-prod.yml

@@ -0,0 +1,17 @@
+#
+# Copyright 2016-present the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Product environment, customizable configuration

+ 21 - 0
dc3-gateway/target/classes/application-test.yml

@@ -0,0 +1,21 @@
+#
+# Copyright 2016-present the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Test environment, customizable configuration
+spring:
+  cache:
+    redis:
+      time-to-live: ${CACHE_REDIS_TIME_TO_LIVE:15M}

+ 216 - 0
dc3-gateway/target/classes/application.yml

@@ -0,0 +1,216 @@
+#
+# Copyright 2016-present the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+server:
+  #服务器配置
+  port: 9309
+  undertow:
+    threads:
+      io: 2
+      worker: 20
+    buffer-size: 512
+
+grpc:
+  client:
+    dc3-center-auth:
+      enable-keep-alive: true
+      keep-alive-without-calls: true
+      negotiation-type: plaintext
+
+spring:
+  application:
+    name: dc3-gateway
+  profiles:
+    active:
+      - ${NODE_ENV:dev}
+  transaction:
+    rollback-on-commit-failure: true
+  main:
+    allow-bean-definition-overriding: true
+  mvc:
+    throw-exception-if-no-handler-found: true
+  web:
+    resources:
+      add-mappings: false
+  redis:
+    database: 0
+  cache:
+    redis:
+      time-to-live: ${CACHE_REDIS_TIME_TO_LIVE:12H}
+  cloud:
+    gateway:
+      loadbalancer:
+        use404: true
+      discovery:
+        locator:
+          enabled: true
+          lower-case-service-id: true
+      routes:
+        # auth token
+        - id: auth_route_token
+          uri: lb://dc3-center-auth
+          predicates:
+            - Path=/api/v3/auth/token/**
+          filters:
+            - StripPrefix=2
+            - name: RequestRateLimiter
+              args:
+                key-resolver: '#{@hostKeyResolver}'
+                redis-rate-limiter.replenishRate: 10
+                redis-rate-limiter.burstCapacity: 20
+            #- name: CircuitBreaker
+            # args:
+            #   name: default
+            #   fallbackUri: 'forward:/fallback'
+        # auth other
+        - id: auth_route_other
+          uri: lb://dc3-center-auth
+          predicates:
+            - Path=/api/v3/auth/user/**,/api/v3/auth/black_ip/**,/api/v3/auth/tenant/**,/api/v3/auth/dictionary/**
+          filters:
+            - StripPrefix=2
+            - Authentic
+            - name: RequestRateLimiter
+              args:
+                key-resolver: '#{@hostKeyResolver}'
+                redis-rate-limiter.replenishRate: 10
+                redis-rate-limiter.burstCapacity: 20
+            #- name: CircuitBreaker
+            # args:
+            #   name: default
+            #   fallbackUri: 'forward:/fallback'
+        # manager
+        - id: manager_route
+          uri: lb://dc3-center-manager
+          predicates:
+            - Path=/api/v3/manager/**
+          filters:
+            - StripPrefix=2
+            - Authentic
+            - name: RequestRateLimiter
+              args:
+                key-resolver: '#{@hostKeyResolver}'
+                redis-rate-limiter.replenishRate: 10
+                redis-rate-limiter.burstCapacity: 20
+            #- name: CircuitBreaker
+            # args:
+            #   name: default
+            #   fallbackUri: 'forward:/fallback'
+        # data
+        - id: data_route
+          uri: lb://dc3-center-data
+          predicates:
+            - Path=/api/v3/data/**
+          filters:
+            - StripPrefix=2
+            - Authentic
+            - name: RequestRateLimiter
+              args:
+                key-resolver: '#{@hostKeyResolver}'
+                redis-rate-limiter.replenishRate: 10
+                redis-rate-limiter.burstCapacity: 20
+            #- name: CircuitBreaker
+            # args:
+            #   name: default
+            #   fallbackUri: 'forward:/fallback'
+  datasource:
+      driver-class-name: org.postgis.DriverWrapper
+      jdbc-url: jdbc:postgresql_postGIS://192.168.0.4:5432/watersmart?useSSL=false&useAffectedRows=false&allowMultiQueries=true
+      username: postgres
+      password: kpr.23417.postgres
+      data:
+        maximum-pool-size: 200
+        validation-query: SELECT 1
+        connection-test-query: SELECT 1
+        test-on-return: false
+        idle-timeout: 30000
+        connection-timeout: 30000
+  jpa:
+    show-sql: false
+
+logging:
+  level:
+    io.github.pnoker: DEBUG
+  file:
+    name: dc3/logs/gateway/${spring.application.name}.log
+
+#许昌八百支户表相关参数配置,密码为MD532位大写前二十位
+xuchang:
+  user: zzsfy
+  pwd: D41D8CD98F00B204E980
+  url: http://42.227.69.38:8004/WebServiceOfNBIoT.asmx
+
+#当阳influxdb配置
+dangyang:
+#influxdb相关配置
+  inluxdb:
+    database: iot_test
+#    serverUrl: http://192.168.0.4:8086
+#    username: kpr
+#    password: kpr.2024dy.influxdb
+    serverUrl: http://127.0.0.1:8086
+    username: admin
+    password: yourpassword
+#设备数据相关接口地址
+  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,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,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

TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/GatewayApplication.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/JPBean/JPKprXuChangWaterSS.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/SpringContextUtil.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/bizmgr/KprDangyangWaterBizFun$1.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/bizmgr/KprDangyangWaterBizFun$2.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/bizmgr/KprDangyangWaterBizFun$3.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/bizmgr/KprDangyangWaterBizFun$4.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/bizmgr/KprDangyangWaterBizFun.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/bizmgr/KprXuChangWaterBizFun.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/bizmgr/baseInit/KprBaseInitFun.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/CommTool.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/HttpTool.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/ResponseCode.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/ScheduleTaskMgr$1.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/ScheduleTaskMgr$2.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/ScheduleTaskMgr$3.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/ScheduleTaskMgr$TokenTask.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/ScheduleTaskMgr.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/ThreadHistoryTask.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/ThreadPoolTaskTool.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/ThreadTask.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/TimeTool.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/comtool/XuchangWaterConfig.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/config/ExceptionConfig.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/config/GatewayConfig.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/config/GlobalData.class


TEMPAT SAMPAH
dc3-gateway/target/classes/io/github/pnoker/gateway/config/MainSourceConfiguration.class


+ 0 - 0
dc3-gateway/target/classes/io/github/pnoker/gateway/config/RouteConfig.class


Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini