Browse Source

代码同步

master
review512jwy@163.com 4 weeks ago
commit
30aac270e8
  1. 34
      .gitignore
  2. 118
      .mvn/wrapper/MavenWrapperDownloader.java
  3. BIN
      .mvn/wrapper/maven-wrapper.jar
  4. 2
      .mvn/wrapper/maven-wrapper.properties
  5. 53
      .workflow/branch-pipeline.yml
  6. 51
      .workflow/master-pipeline.yml
  7. 40
      .workflow/pr-pipeline.yml
  8. 15
      Dockerfile
  9. 68
      Readme.md
  10. 27
      TECHSOR_OFFICIAL.pem
  11. 2
      deploy.bat
  12. 20
      docker-compose.yaml
  13. 310
      mvnw
  14. 182
      mvnw.cmd
  15. 648
      pom.xml
  16. 15
      readmev2.md
  17. 3
      shell-build.sh
  18. 15
      src/main/docker/Dockerfile
  19. 17
      src/main/docker/docker-compose.yaml
  20. 37
      src/main/java/com/techsor/datacenter/receiver/TechsorDataCenterReceiverApplication.java
  21. 60
      src/main/java/com/techsor/datacenter/receiver/clients/DeltaClientMQTTS.java
  22. 120
      src/main/java/com/techsor/datacenter/receiver/clients/DeltaPushCallback.java
  23. 66
      src/main/java/com/techsor/datacenter/receiver/clients/ITAClientMQTT.java
  24. 121
      src/main/java/com/techsor/datacenter/receiver/clients/ITAPushCallback.java
  25. 50
      src/main/java/com/techsor/datacenter/receiver/clients/MetComClient.java
  26. 39
      src/main/java/com/techsor/datacenter/receiver/clients/NBIClient.java
  27. 41
      src/main/java/com/techsor/datacenter/receiver/clients/NittanClient.java
  28. 49
      src/main/java/com/techsor/datacenter/receiver/clients/OCRClient.java
  29. 38
      src/main/java/com/techsor/datacenter/receiver/clients/OVIPhoneClient.java
  30. 59
      src/main/java/com/techsor/datacenter/receiver/config/CachedBodyHttpServletRequest.java
  31. 95
      src/main/java/com/techsor/datacenter/receiver/config/DataCenterEnvConfig.java
  32. 87
      src/main/java/com/techsor/datacenter/receiver/config/DeltaClientConfig.java
  33. 76
      src/main/java/com/techsor/datacenter/receiver/config/DynamoDBConfig.java
  34. 16
      src/main/java/com/techsor/datacenter/receiver/config/JdbcTemplateConfig.java
  35. 87
      src/main/java/com/techsor/datacenter/receiver/config/MyFilter.java
  36. 137
      src/main/java/com/techsor/datacenter/receiver/config/RedisConfig.java
  37. 65
      src/main/java/com/techsor/datacenter/receiver/config/RestTemplateConfig.java
  38. 56
      src/main/java/com/techsor/datacenter/receiver/config/TaskExecutorConfig.java
  39. 186
      src/main/java/com/techsor/datacenter/receiver/config/datasource/DataSourceAdminConfig.java
  40. 18
      src/main/java/com/techsor/datacenter/receiver/config/datasource/DataSourceContextHolder.java
  41. 13
      src/main/java/com/techsor/datacenter/receiver/config/datasource/DynamicRouteDataSource.java
  42. 42
      src/main/java/com/techsor/datacenter/receiver/config/kafka/Main.java
  43. 22
      src/main/java/com/techsor/datacenter/receiver/config/kafka/RegionEnum.java
  44. 30
      src/main/java/com/techsor/datacenter/receiver/config/kafka/ZiFiClient.java
  45. 44
      src/main/java/com/techsor/datacenter/receiver/config/kafka/imp/ClientFactory.java
  46. 21
      src/main/java/com/techsor/datacenter/receiver/config/kafka/imp/ClientType.java
  47. 25
      src/main/java/com/techsor/datacenter/receiver/config/kafka/imp/KafkaMessage.java
  48. 138
      src/main/java/com/techsor/datacenter/receiver/config/kafka/imp/KafkaZiFiClient.java
  49. 38
      src/main/java/com/techsor/datacenter/receiver/config/kafka/model/Message.java
  50. 10
      src/main/java/com/techsor/datacenter/receiver/constants/CodeConstants.java
  51. 11
      src/main/java/com/techsor/datacenter/receiver/constants/CompanyConstants.java
  52. 19
      src/main/java/com/techsor/datacenter/receiver/constants/MsgConstants.java
  53. 7
      src/main/java/com/techsor/datacenter/receiver/constants/UrlConstants.java
  54. 43
      src/main/java/com/techsor/datacenter/receiver/controller/HealthController.java
  55. 43
      src/main/java/com/techsor/datacenter/receiver/controller/NotificationSinkController.java
  56. 32
      src/main/java/com/techsor/datacenter/receiver/controller/ReceiverController.java
  57. 25
      src/main/java/com/techsor/datacenter/receiver/entity/common/BaseTransDataEntity.java
  58. 15
      src/main/java/com/techsor/datacenter/receiver/entity/common/CommonTransDataEntity.java
  59. 57
      src/main/java/com/techsor/datacenter/receiver/entity/common/JsonResponse.java
  60. 16
      src/main/java/com/techsor/datacenter/receiver/entity/common/KafkaClientConfig.java
  61. 37
      src/main/java/com/techsor/datacenter/receiver/entity/common/KafkaZetaMessage.java
  62. 37
      src/main/java/com/techsor/datacenter/receiver/entity/common/MqttClientConfig.java
  63. 14
      src/main/java/com/techsor/datacenter/receiver/entity/common/MqttPublisherEntity.java
  64. 9
      src/main/java/com/techsor/datacenter/receiver/entity/common/MqttStartStatusEntity.java
  65. 12
      src/main/java/com/techsor/datacenter/receiver/entity/common/ResponseEntity.java
  66. 15
      src/main/java/com/techsor/datacenter/receiver/entity/common/ZAIotTransDataEntity.java
  67. 33
      src/main/java/com/techsor/datacenter/receiver/entity/company/CompanyEntity.java
  68. 46
      src/main/java/com/techsor/datacenter/receiver/entity/datasource/DatasourceConfigEntity.java
  69. 12
      src/main/java/com/techsor/datacenter/receiver/entity/datasource/RestfulParams.java
  70. 23
      src/main/java/com/techsor/datacenter/receiver/entity/dto/RedisCommandReceiverDTO.java
  71. 24
      src/main/java/com/techsor/datacenter/receiver/entity/metcom/MetcomEntity.java
  72. 13
      src/main/java/com/techsor/datacenter/receiver/entity/nittan/AuthEntity.java
  73. 9
      src/main/java/com/techsor/datacenter/receiver/entity/nittan/DeviceInfoEntity.java
  74. 10
      src/main/java/com/techsor/datacenter/receiver/entity/nittan/FacilityInfoEntity.java
  75. 8
      src/main/java/com/techsor/datacenter/receiver/entity/nittan/LocationInfoEntity.java
  76. 20
      src/main/java/com/techsor/datacenter/receiver/entity/nittan/NittanEntity.java
  77. 12
      src/main/java/com/techsor/datacenter/receiver/entity/nittan/NoticeInfoEntity.java
  78. 113
      src/main/java/com/techsor/datacenter/receiver/listener/DataSourceConfigListener.java
  79. 31
      src/main/java/com/techsor/datacenter/receiver/listener/DeltaMQTTListener.java
  80. 63
      src/main/java/com/techsor/datacenter/receiver/listener/DynamoDBListener.java
  81. 60
      src/main/java/com/techsor/datacenter/receiver/listener/MqttPublisherListener.java
  82. 71
      src/main/java/com/techsor/datacenter/receiver/listener/RedisNotificationMessageSubscriber.java
  83. 33
      src/main/java/com/techsor/datacenter/receiver/listener/RedisStatsSwitchListener.java
  84. 141
      src/main/java/com/techsor/datacenter/receiver/service/DataTransService.java
  85. 84
      src/main/java/com/techsor/datacenter/receiver/service/DuplicateDataProcessor.java
  86. 37
      src/main/java/com/techsor/datacenter/receiver/service/GlobalStateService.java
  87. 27
      src/main/java/com/techsor/datacenter/receiver/service/GlobalSwitchStatusComponent.java
  88. 87
      src/main/java/com/techsor/datacenter/receiver/service/GuavaRedisCache.java
  89. 12
      src/main/java/com/techsor/datacenter/receiver/service/IDataReceiveService.java
  90. 19
      src/main/java/com/techsor/datacenter/receiver/service/IDataSourceConfigService.java
  91. 14
      src/main/java/com/techsor/datacenter/receiver/service/IMQTTService.java
  92. 98
      src/main/java/com/techsor/datacenter/receiver/service/MQTTCrtService.java
  93. 42
      src/main/java/com/techsor/datacenter/receiver/service/MqttHistoryDynamoDBService.java
  94. 33
      src/main/java/com/techsor/datacenter/receiver/service/MqttHistoryService.java
  95. 40
      src/main/java/com/techsor/datacenter/receiver/service/MqttPublisherService.java
  96. 29
      src/main/java/com/techsor/datacenter/receiver/service/RestfulService.java
  97. 15
      src/main/java/com/techsor/datacenter/receiver/service/ZetaKafkaService.java
  98. 76
      src/main/java/com/techsor/datacenter/receiver/service/impl/DataReceiveServiceImpl.java
  99. 115
      src/main/java/com/techsor/datacenter/receiver/service/impl/DataSourceConfigServiceImpl.java
  100. 465
      src/main/java/com/techsor/datacenter/receiver/service/impl/MQTTServiceImpl.java

34
.gitignore

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

118
.mvn/wrapper/MavenWrapperDownloader.java

@ -0,0 +1,118 @@
/*
* Copyright 2007-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.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.6";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if (mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if (mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if (!outputFile.getParentFile().exists()) {
if (!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}

BIN
.mvn/wrapper/maven-wrapper.jar

Binary file not shown.

2
.mvn/wrapper/maven-wrapper.properties

@ -0,0 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

53
.workflow/branch-pipeline.yml

@ -0,0 +1,53 @@
version: '1.0'
name: branch-pipeline
displayName: BranchPipeline
stages:
- stage:
name: compile
displayName: 编译
steps:
- step: build@maven
name: build_maven
displayName: Maven 构建
# 支持6、7、8、9、10、11六个版本
jdkVersion: 8
# 支持2.2.1、3.2.5、3.3.9、3.5.2、3.5.3、3.5.4、3.6.1、3.6.3八个版本
mavenVersion: 3.3.9
# 构建命令
commands:
- mvn -B clean package -Dmaven.test.skip=true
# 非必填字段,开启后表示将构建产物暂存,但不会上传到制品库中,7天后自动清除
artifacts:
# 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
- name: BUILD_ARTIFACT
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径,如通常jar包在target目录下。当前目录为代码库根目录
path:
- ./target
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
# 上游构建任务定义的产物名,默认BUILD_ARTIFACT
dependArtifact: BUILD_ARTIFACT
# 上传到制品库时的制品命名,默认output
artifactName: output
dependsOn: build_maven
- stage:
name: release
displayName: 发布
steps:
- step: publish@release_artifacts
name: publish_release_artifacts
displayName: '发布'
# 上游上传制品任务的产出
dependArtifact: output
# 发布制品版本号
version: '1.0.0.0'
# 是否开启版本号自增,默认开启
autoIncrement: true
triggers:
push:
branches:
exclude:
- master
include:
- .*

51
.workflow/master-pipeline.yml

@ -0,0 +1,51 @@
version: '1.0'
name: master-pipeline
displayName: MasterPipeline
stages:
- stage:
name: compile
displayName: 编译
steps:
- step: build@maven
name: build_maven
displayName: Maven 构建
# 支持6、7、8、9、10、11六个版本
jdkVersion: 8
# 支持2.2.1、3.2.5、3.3.9、3.5.2、3.5.3、3.5.4、3.6.1、3.6.3八个版本
mavenVersion: 3.3.9
# 构建命令
commands:
- mvn -B clean package -Dmaven.test.skip=true
# 非必填字段,开启后表示将构建产物暂存,但不会上传到制品库中,7天后自动清除
artifacts:
# 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
- name: BUILD_ARTIFACT
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径,如通常jar包在target目录下。当前目录为代码库根目录
path:
- ./target
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
# 上游构建任务定义的产物名,默认BUILD_ARTIFACT
dependArtifact: BUILD_ARTIFACT
# 上传到制品库时的制品命名,默认output
artifactName: output
dependsOn: build_maven
- stage:
name: release
displayName: 发布
steps:
- step: publish@release_artifacts
name: publish_release_artifacts
displayName: '发布'
# 上游上传制品任务的产出
dependArtifact: output
# 发布制品版本号
version: '1.0.0.0'
# 是否开启版本号自增,默认开启
autoIncrement: true
triggers:
push:
branches:
include:
- master

40
.workflow/pr-pipeline.yml

@ -0,0 +1,40 @@
version: '1.0'
name: pr-pipeline
displayName: PRPipeline
stages:
- stage:
name: compile
displayName: 编译
steps:
- step: build@maven
name: build_maven
displayName: Maven 构建
# 支持6、7、8、9、10、11六个版本
jdkVersion: 8
# 支持2.2.1、3.2.5、3.3.9、3.5.2、3.5.3、3.5.4、3.6.1、3.6.3八个版本
mavenVersion: 3.3.9
# 构建命令
commands:
- mvn -B clean package -Dmaven.test.skip=true
# 非必填字段,开启后表示将构建产物暂存,但不会上传到制品库中,7天后自动清除
artifacts:
# 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
- name: BUILD_ARTIFACT
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径,如通常jar包在target目录下。当前目录为代码库根目录
path:
- ./target
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
# 上游构建任务定义的产物名,默认BUILD_ARTIFACT
dependArtifact: BUILD_ARTIFACT
# 构建产物制品库,默认default,系统默认创建
artifactRepository: default
# 上传到制品库时的制品命名,默认output
artifactName: output
dependsOn: build_maven
triggers:
pr:
branches:
include:
- master

15
Dockerfile

@ -0,0 +1,15 @@
FROM registry.ap-northeast-1.aliyuncs.com/southwave/jdk17-template:latest
WORKDIR /app
COPY target/data-center-receiver.jar app.jar
EXPOSE 8200
# 使用UseCGroupMemoryLimitForHeap
# ENV JAVA_OPTS="-Xms5g -Xmx5g -XX:+UseParallelGC -XX:ParallelGCThreads=4 -XX:MaxGCPauseMillis=200 -XX:GCTimeRatio=19 -XX:NewRatio=3 -XX:+AlwaysPreTouch -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/app/gc.log"
# 使用shell方式的ENTRYPOINT来确保环境变量被展开
ENTRYPOINT java $JAVA_OPTS -jar app.jar -Djavax.net.debug=ssl --spring-profiles=$env

68
Readme.md

@ -0,0 +1,68 @@
# 介绍
组件用于订阅客户端数据。
组件运行在8201端口
数据库为data_center
# 功能
1. 订阅MQTT数据,并转发至本地8200端口的TECHSOR_dataCenter_sender服务处理
# 初始化
启动组件后,调用以下接口开启所有mqtt订阅:
GET localhost:8200/v1/mqtt/startAll
# 开发测试环境信息
Redis 信息
公网地址: r-uf63x4g5p6ir5xao87pd.redis.rds.aliyuncs.com
内网地址: r-uf63x4g5p6ir5xao87.redis.rds.aliyuncs.com
端口号:6379
密码:B2BGn4gK4htgkEwP
mysql信息
地址:rm-bp11k2zm2fr7864428o.mysql.rds.aliyuncs.com
端口号:3306
用户名:zhc
密码:Youqu48bnb1
Docker镜像仓库
sender推送地址及方法:
$ docker login --username=4099*****@qq.com registry.cn-shanghai.aliyuncs.com$ docker tag [ImageId] registry.cn-shanghai.aliyuncs.com/southwave/mini_data_center_sender:[镜像版本号]$ docker push registry.cn-shanghai.aliyuncs.com/southwave/mini_data_center_sender:[镜像版本号]
receiver推送地址及方法:
$ docker login --username=4099*****@qq.com registry.cn-shanghai.aliyuncs.com$ docker tag [ImageId] registry.cn-shanghai.aliyuncs.com/southwave/mini_data_center_receiver:[镜像版本号]$ docker push registry.cn-shanghai.aliyuncs.com/southwave/mini_data_center_receiver:[镜像版本号]
# 服务器1
47.122.21.64
root
证书:southwave_datacenter_test.pem
# 服务器2
47.122.2.42
root
证书:southwave_datacenter_test.pem
### docker 环境配置
#### 环境启动问题
aws上应该可以设置环境变量 `env`
`env`=dev
或者
`env`=stg
或者
`env`=prd
#### sender地址
aws 上设置环境变量 'sendUrl'
`sendUrl`=http://localhost:8021

27
TECHSOR_OFFICIAL.pem

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAoXT+WI0CFw06NjKINFhz5y9xs9CeQYHN0+G24fIePPEBPRhW
Faxg36GuFuYKxk59W+Ey8w5Stz8R1wckbU//uaio/P7QhNbl+OpVIKbU93SVW8x6
VH8roTSf+uYh6k6qO5ejAjqiicuEj8dZ8fQWyYSB4X/mLrXg5k5dxKyjhv5nM8RO
vvFHy/uvcdFOAeBbYrq9pHOkSP3BLU+wjutBDmxEdM9YLJk9qOM9bulxr1+QMXNY
4pjpWDlqfM1BpZZDhKzvUqLVjO+QwQ2E8mUgoK2PVY1umC5X8Jlcfy83A77+pKzl
ZKYpLgfLHj7rV5I12uoBx4mvLO1jw6XrNlIb9QIDAQABAoIBAGe+pDxEBwbG4hO3
LpvsBjWT38y6DSZsgNRX4cqXZ+Siu7gFLjNo+ypXWmSuVlgMUTK7pqBVIMNMjGsN
1NNEpz4l6Mf/9/6Tk1v5Ps/nQ0rqJ5q/7g7jVCaWiQGP5FUJTQtTqVOiV5SRKFG2
t83nmMjOEyLRqxdymNuDmW7pu33ebtDZxwm+QeN3nz6TwAbV7Geas5NC1UJLR0+C
nLQh0M9QELv7fKUPiznr6wE9CxB+1fx9es6HJxYK6Q4W+4mjd8CVXXMPDiQhTVEt
jnibk3UfxBQB7fkYP8PUukGq+Z4BgCszoAW0J8gFwiC8YMuzzQw3k83vPCiZZ+JQ
u0hgUPUCgYEA1lQi4mhKNtYMfbVtKEURajvUy5pZw4rzIyo+6XFjE25c3Q/nt3ot
d+vgh6dNCfRll95CB2RKOUoelj3nDeX+aM+QEwwQghLAtAdcRcIhG3DfIYBOJmiw
ugjbk5AW1bc38eQsjtRD7aZMyJjjr2bI7D2D5/MrjqdMZ6sxYdFRmpMCgYEAwNlB
h/Da5kY/z9qcXSnysr78ffU5BLGcxN2At+aXYGKyoR2YQqSME0y1jC9h0w+a7nAx
jCtkz+ozhBkP7o0vRZ8eGbP/65CbPrsY8P9Kpvk7dr2IRMTUjMFihhptGQFrLP3a
g+T2T+gQWS0v5HqiSot6znHZL+jND9elwx8nnFcCgYEAuemhmOL9/TMPArwtQ5El
2hCsNTBeTNBqt0Yd7ED+wAwrYVY6mVzRtARXb1Qf71KgDWwtulu0Rp2Uip6Hnfaz
CBeD0gHVD/9USNVZpOkP7s2pv1WcdJS7N6QXU5jZNekIDjruq7ZUdgCa+iYk2jE+
eC2kDb9RORzFmedVnpQDRSECgYBH26xTXyfxzhNQ/ABvpoXMnOWweYN5gEUOBgtE
eyPEwoIVDtYBXxbiyh6L0cv9vT7Zwex0cmbqIjZ37m7FUM5gft3UbgHaYNO4GDc+
9aF3fj7uC8mO9ljM6fIwTgCA5MpuxVh69QHi3HHbCL9jv15hsH9eFYX8GB7w3EXj
4uP7mQKBgQCFG7l/s1VDsLn9VNpkoUBjZMMdrLCyCWVrTEdeYtZ5LIx3etZxgbah
/rvryIDgc/j7riQgEDnqYk19Ee/HVxK1duJO6d/ywDcSlnNMaChrS8khsMrbK6yI
geqH+9jaaPUVacfeVe0MCIGLxnMiUucIUIyp3VV2OuJ2xx68xqw1wA==
-----END RSA PRIVATE KEY-----

2
deploy.bat

@ -0,0 +1,2 @@
scp -i ./TECHSOR_OFFICIAL.pem ./target/TECHSOR_dataCenter_receiver-0.0.1-SNAPSHOT.jar root@8.209.255.206:~
ssh -i ./TECHSOR_OFFICIAL.pem root@8.209.255.206

20
docker-compose.yaml

@ -0,0 +1,20 @@
version: '3.8'
# docker pull adoptopenjdk/openjdk8:ppc64le-debian-jdk8u212-b03
services:
app:
build: .
ports:
- "8200:8200"
environment:
JAVA_OPTS: "-Xms5g -Xmx5g -XX:+UseParallelGC -XX:ParallelGCThreads=4 -XX:MaxGCPauseMillis=200 -XX:GCTimeRatio=19 -XX:NewRatio=3 -XX:+AlwaysPreTouch -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/app/gc.log"
AGENT_PATH: "-agentpath:/app/liberror-detector-agent.so=packageName=org/springframework/integration,=filePath=./gcclogs/errorlog.log" # Replace this with your actual agent options if necessary
env: "dev" # Replace this with your actual spring profile if necessary
volumes:
- /Users/zhukovasky/IdeaProjects/Datacenter/TECHSOR_dataCenter_receiver/target/data-center-receiver.jar:/app/app.jar
- /Users/zhukovasky/IdeaProjects/Datacenter/TECHSOR_dataCenter_receiver/target/liberror-detector-agent.so:/app/liberror-detector-agent.so
- /Users/zhukovasky/IdeaProjects/Datacenter/TECHSOR_dataCenter_receiver/target/app/gc.log:/app/gc.log # Make sure this path is correct for your gc logs
- /Users/zhukovasky/IdeaProjects/Datacenter/TECHSOR_dataCenter_receiver/target/:/app/
entrypoint: java $AGENT_PATH $JAVA_OPTS -jar /app/app.jar -Djavax.net.debug=ssl --spring-profiles=$env

310
mvnw

@ -0,0 +1,310 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="`/usr/libexec/java_home`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$M2_HOME" ] &&
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`which java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

182
mvnw.cmd

@ -0,0 +1,182 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%" == "on" pause
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
exit /B %ERROR_CODE%

648
pom.xml

@ -0,0 +1,648 @@
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.12</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.techsor</groupId>
<artifactId>data.center.receiver</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>TECHSOR_dataCenter_receiver</name>
<properties>
<java.version>17</java.version>
<aws.ecr.registry>381659385655.dkr.ecr.ap-northeast-1.amazonaws.com</aws.ecr.registry>
<aws.ecr.registryTest>923770123186.dkr.ecr.ap-northeast-1.amazonaws.com</aws.ecr.registryTest>
<aws.ecr.repository>tokyo-build-receiver</aws.ecr.repository>
<netty.version>4.2.2.Final</netty.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bom</artifactId>
<version>2.20.113</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-buffer</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-base</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-compression</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-dns</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-haproxy</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-http</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-http2</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-http3</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-memcache</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-mqtt</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-redis</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-smtp</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-socks</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-stomp</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-xml</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-protobuf</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-marshalling</artifactId>
<version>${netty.version}</version>
</dependency>
<!-- 其他核心模块 -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-common</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler-proxy</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler-ssl-ocsp</artifactId>
<version>${netty.version}</version>
</dependency>
<!-- resolver & transport -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-resolver</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-resolver-dns</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-resolver-dns-classes-macos</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-classes-epoll</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-classes-kqueue</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-classes-io_uring</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-unix-common</artifactId>
<version>${netty.version}</version>
</dependency>
<!-- platform-specific native modules -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
<classifier>linux-x86_64</classifier>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
<classifier>linux-aarch_64</classifier>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
<classifier>linux-riscv64</classifier>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-io_uring</artifactId>
<classifier>linux-x86_64</classifier>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-io_uring</artifactId>
<classifier>linux-aarch_64</classifier>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-io_uring</artifactId>
<classifier>linux-riscv64</classifier>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-kqueue</artifactId>
<classifier>osx-x86_64</classifier>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-kqueue</artifactId>
<classifier>osx-aarch_64</classifier>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-resolver-dns-native-macos</artifactId>
<classifier>osx-x86_64</classifier>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-resolver-dns-native-macos</artifactId>
<classifier>osx-aarch_64</classifier>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-native-quic</artifactId>
<classifier>linux-x86_64</classifier>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-native-quic</artifactId>
<classifier>linux-aarch_64</classifier>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-native-quic</artifactId>
<classifier>osx-x86_64</classifier>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-native-quic</artifactId>
<classifier>osx-aarch_64</classifier>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-native-quic</artifactId>
<classifier>windows-x86_64</classifier>
<version>${netty.version}</version>
</dependency>
<!-- 特殊模块 -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-rxtx</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-sctp</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-udt</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-classes-quic</artifactId>
<version>${netty.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-core -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>10.1.42</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.integration/spring-integration-mqtt -->
<!-- https://mvnrepository.com/artifact/org.springframework.integration/spring-integration-mqtt -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-mqtt</artifactId>
<version>5.5.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.19.0</version>
</dependency>
<!-- MYSQL -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>9.3.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/io.joynr.java.messaging.mqtt/paho-mqtt-client -->
<dependency>
<groupId>io.joynr.java.messaging.mqtt</groupId>
<artifactId>paho-mqtt-client</artifactId>
<version>1.14.2</version>
</dependency>
<!-- JSON等格式的转义和反转义 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.13.1</version>
</dependency>
<!-- <dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>-->
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.13.1</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>${netty.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk18on -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk18on</artifactId>
<version>1.81</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.houbb</groupId>
<artifactId>data-factory-core</artifactId>
<version>1.2.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.noconnor/junitperf -->
<dependency>
<groupId>com.github.noconnor</groupId>
<artifactId>junitperf</artifactId>
<version>1.22.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.38</version>
</dependency>
<dependency>
<groupId>com.github.derjust</groupId>
<artifactId>spring-data-dynamodb</artifactId>
<version>5.1.0</version>
<exclusions>
<exclusion>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-dynamodb</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-dynamodb -->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-dynamodb</artifactId>
<version>1.12.786</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.46</version>
</dependency>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>4.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.yaml/snakeyaml -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>2.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/net.minidev/json-smart -->
<dependency>
<groupId>net.minidev</groupId>
<artifactId>json-smart</artifactId>
<version>2.5.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.21</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context-support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>6.1.21</version>
</dependency>
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.18</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.5.18</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.4.8-jre</version>
</dependency>
</dependencies>
<build>
<finalName>data-center-receiver</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- https://mvnrepository.com/artifact/pl.project13.maven/git-commit-id-plugin -->
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<version>4.9.10</version>
<executions>
<execution>
<goals>
<goal>revision</goal>
</goals>
</execution>
</executions>
<configuration>
<verbose>true</verbose>
<dateFormat>yyyy-MM-dd'T'HH:mm:ssZ</dateFormat>
<generateGitPropertiesFile>true</generateGitPropertiesFile>
<generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties</generateGitPropertiesFilename>
</configuration>
</plugin>
<!--&lt;!&ndash;正式环境&ndash;&gt;-->
<!-- <plugin>-->
<!-- <groupId>io.fabric8</groupId>-->
<!-- <artifactId>docker-maven-plugin</artifactId>-->
<!-- <version>0.38.1</version>-->
<!-- <configuration>-->
<!-- <authConfig>-->
<!-- <username>AKIAVRXFMB43XVQ3GXAL</username>-->
<!-- <password>G0FaGcizm8FlgLxZsL+8xBwfPSzQF71294nrtE2y</password>-->
<!-- </authConfig>-->
<!-- <images>-->
<!-- <image>-->
<!-- <name>${aws.ecr.registry}/${aws.ecr.repository}:latest</name>-->
<!-- <registry>${aws.ecr.registry}</registry>-->
<!-- <build>-->
<!-- <dockerFile>${project.basedir}/Dockerfile</dockerFile>-->
<!-- </build>-->
<!-- </image>-->
<!-- </images>-->
<!-- </configuration>-->
<!-- </plugin>-->
<!-- 测试环境-->
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.38.1</version>
<configuration>
<authConfig>
<username>AKIA5OFH5OOZPCXZIRUQ</username>
<password>TMIN27+OxamT1FmBQSVKfUIWpOVldhxQx2Stxwix</password>
</authConfig>
<images>
<image>
<name>${aws.ecr.registryTest}/${aws.ecr.repository}:latest</name>
<registry>${aws.ecr.registry}</registry>
<build>
<dockerFile>${project.basedir}/Dockerfile</dockerFile>
</build>
</image>
</images>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*</include>
</includes>
</resource>
</resources>
</build>
</project>

15
readmev2.md

@ -0,0 +1,15 @@
# 二期说明
## 激活或者冷冻数据来源配置表
aws lamdba 通过脚本
调用receiver的接口
`
/notification/receive
`
传入参数state,和List<Long> 类型的id,用于决定哪些数据来源的数据源激活还是冷冻;
## 数据来源配置表生效
接上,会根据配置来实现对应数据源是MQTT接入还是RESTFUL方式接收数据。

3
shell-build.sh

@ -0,0 +1,3 @@
git pull
mvn clean
mvn package -DskipTests=true docker:build

15
src/main/docker/Dockerfile

@ -0,0 +1,15 @@
FROM openjdk:8-jre
WORKDIR /app
COPY ../../../target/data-center-receiver.jar app.jar
EXPOSE 8200
# 使用UseCGroupMemoryLimitForHeap
ENV JAVA_OPTS="-Xms5g -Xmx5g -XX:+UseParallelGC -XX:ParallelGCThreads=4 -XX:MaxGCPauseMillis=200 -XX:GCTimeRatio=19 -XX:NewRatio=3 -XX:+AlwaysPreTouch -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/app/gc.log"
# 使用shell方式的ENTRYPOINT来确保环境变量被展开
ENTRYPOINT java $JAVA_OPTS -jar app.jar -Djavax.net.debug=ssl --spring-profiles=$env

17
src/main/docker/docker-compose.yaml

@ -0,0 +1,17 @@
version: '3.8'
services:
app:
build: .
ports:
- "8200:8200"
environment:
JAVA_OPTS: "-Xms5g -Xmx5g -XX:+UseParallelGC -XX:ParallelGCThreads=4 -XX:MaxGCPauseMillis=200 -XX:GCTimeRatio=19 -XX:NewRatio=3 -XX:+AlwaysPreTouch -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/app/gc.log"
AGENT_PATH: "-agentpath:/app/liberror-detector-agent.so=packageName=org.eclipse.paho.client.mqttv3,=filePath=./gclogs/errorlog.log" # Replace this with your actual agent options if necessary
env: "dev" # Replace this with your actual spring profile if necessary
volumes:
- /Users/zhukovasky/IdeaProjects/Datacenter/TECHSOR_dataCenter_receiver/target/data-center-receiver.jar:/app/app.jar
- /Users/zhukovasky/IdeaProjects/Datacenter/TECHSOR_dataCenter_receiver/target/liberror-detector-agent.so:/app/liberror-detector-agent.so
- /Users/zhukovasky/IdeaProjects/Datacenter/TECHSOR_dataCenter_receiver/target/app/gc.log:/app/gc.log # Make sure this path is correct for your gc logs
entrypoint: java $AGENT_PATH $JAVA_OPTS -jar /app/app.jar -Djavax.net.debug=ssl --spring-profiles=$env

37
src/main/java/com/techsor/datacenter/receiver/TechsorDataCenterReceiverApplication.java

@ -0,0 +1,37 @@
package com.techsor.datacenter.receiver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.bridge.SLF4JBridgeHandler;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.integration.annotation.IntegrationComponentScan;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.scheduling.annotation.EnableScheduling;
import jakarta.annotation.PostConstruct;
@EnableScheduling
@IntegrationComponentScan
@EnableIntegration
@SpringBootApplication(scanBasePackages = {"com.techsor.*"},exclude = { HibernateJpaAutoConfiguration.class})
public class TechsorDataCenterReceiverApplication {
private static final Logger logger = LoggerFactory.getLogger(TechsorDataCenterReceiverApplication.class);
public static void main(String[] args) {
logger.info("application started success!!");
SpringApplication.run(TechsorDataCenterReceiverApplication.class, args);
logger.info("application started success!!");
}
@PostConstruct
public void init() {
// Remove existing handlers attached to the j.u.l root logger
SLF4JBridgeHandler.removeHandlersForRootLogger();
// Bridge/join j.u.l. to SLF4J
SLF4JBridgeHandler.install();
}
}

60
src/main/java/com/techsor/datacenter/receiver/clients/DeltaClientMQTTS.java

@ -0,0 +1,60 @@
package com.techsor.datacenter.receiver.clients;
import com.techsor.datacenter.receiver.config.DeltaClientConfig;
import com.techsor.datacenter.receiver.entity.common.MqttPublisherEntity;
import com.techsor.datacenter.receiver.utils.SslUtil;
import jakarta.annotation.Resource;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.ScheduledExecutorService;
@Component("deltaClientMQTT")
public class DeltaClientMQTTS {
private static final Logger logger = LoggerFactory.getLogger(DeltaClientMQTTS.class);
// public String TOPIC = "Publish_Topic";
//// public String HOST = "ssl://8.209.255.206:8883";
// public String HOST = "ssl://127.0.0.1:8883";
public String randomKey; //a random
@Resource(name = "client")
private MqttClient client;
@Resource
private MqttConnectOptions options;
@Autowired
private DeltaClientConfig deltaClientConfig;
@Resource
private DeltaPushCallback deltaPushCallback;
public void reconnect(MqttClient mqttClient) throws MqttException {
mqttClient.reconnect();
}
public void start() throws Exception {
client.setCallback(deltaPushCallback);
client.connect(options);
//subscribe
int[] Qos = {1};
String[] topic1 = {this
.deltaClientConfig.getTOPIC()};
client.subscribe(topic1, Qos);
}
}

120
src/main/java/com/techsor/datacenter/receiver/clients/DeltaPushCallback.java

@ -0,0 +1,120 @@
package com.techsor.datacenter.receiver.clients;
import com.google.gson.Gson;
import com.techsor.datacenter.receiver.config.DataCenterEnvConfig;
import com.techsor.datacenter.receiver.constants.CompanyConstants;
import com.techsor.datacenter.receiver.constants.UrlConstants;
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity;
import com.techsor.datacenter.receiver.entity.common.MqttPublisherEntity;
import com.techsor.datacenter.receiver.service.MqttHistoryDynamoDBService;
import com.techsor.datacenter.receiver.service.MqttHistoryService;
import com.techsor.datacenter.receiver.utils.DefaultHttpRequestUtil;
import com.techsor.datacenter.receiver.utils.SpringUtils;
import lombok.SneakyThrows;
import org.eclipse.paho.client.mqttv3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
/**
* 发布消息的回调类
*
* 必须实现MqttCallback的接口并实现对应的相关接口方法CallBack 类将实现 MqttCallBack
* 每个客户机标识都需要一个回调实例在此示例中构造函数传递客户机标识以另存为实例数据
* 在回调中将它用来标识已经启动了该回调的哪个实例
* 必须在回调类中实现三个方法
*
* public void messageArrived(MqttTopic topic, MqttMessage message)接收已经预订的发布
*
* public void connectionLost(Throwable cause)在断开连接时调用
*
* public void deliveryComplete(MqttDeliveryToken token))
* 接收到已经发布的 QoS 1 QoS 2 消息的传递令牌时调用
* MqttClient.connect 激活此回调
*
*/
@Component
public class DeltaPushCallback implements MqttCallback, MqttCallbackExtended{
@Resource
private MqttPublisherEntity mqttPublisherEntity;
@Resource
private MqttClient client;
@Resource
private MqttHistoryService mqttHistoryService;
@Resource
private DefaultHttpRequestUtil defaultHttpRequestUtil;
@Resource
private DataCenterEnvConfig dataCenterEnvConfig;
@Resource
MqttHistoryDynamoDBService mqttHistoryDynamoDBService;
private static final Logger logger = LoggerFactory.getLogger(DeltaPushCallback.class);
@SneakyThrows
public void connectionLost(Throwable cause) {
// 连接丢失后,一般在这里面进行重连,由于设置了自动重连,断开连接后会自动重连,然后进入connectComplete中
logger.error("Connection Lost,Trying to reconnect... ClientId: "+this.client.getClientId());
Boolean isConnected = client.isConnected();
logger.warn("client connect status:"+isConnected);
}
/**
* 连接成功会进入到这里
* @param reconnect
* @param serverURI
*/
@SneakyThrows
@Override
public void connectComplete(boolean reconnect, String serverURI) {
// 可以做订阅主题
logger.info("Connect success");
Boolean isConnected = client.isConnected();
logger.warn("client connect status:"+isConnected);
if (isConnected){
logger.info("Subscribe to :"+mqttPublisherEntity.getTopic());
client.subscribe(mqttPublisherEntity.getTopic(),0);
}
}
public void deliveryComplete(IMqttDeliveryToken token) {
logger.debug("deliveryComplete---------" + token.isComplete());
}
public void messageArrived(String topic, MqttMessage message) throws Exception {
BaseTransDataEntity mqttHistoryEntity = new BaseTransDataEntity();
mqttHistoryEntity.setContent(new String(message.getPayload()));
mqttHistoryEntity.setTs(System.currentTimeMillis()+"");
mqttHistoryEntity.setCompany(CompanyConstants.DELTA);
mqttHistoryService.insertHistory(mqttHistoryEntity);
this.mqttHistoryDynamoDBService.save(mqttHistoryEntity);
try {
forwardMessage(mqttHistoryEntity);
}catch (Exception e){
logger.warn("Not correct data");
}
}
//转发收到的数据到 数据转发平台
private void forwardMessage(BaseTransDataEntity mqttHistoryEntity){
//只转发终端数据
Gson gson = new Gson();
String jsonParams = gson.toJson(mqttHistoryEntity);
logger.info("Send Data To: {},{}", this.dataCenterEnvConfig.getReceiveUrl(),jsonParams);
this.defaultHttpRequestUtil.postJson(this.dataCenterEnvConfig.getReceiveUrl(),jsonParams);
}
}

66
src/main/java/com/techsor/datacenter/receiver/clients/ITAClientMQTT.java

@ -0,0 +1,66 @@
package com.techsor.datacenter.receiver.clients;
import com.techsor.datacenter.receiver.entity.common.MqttPublisherEntity;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ITAClientMQTT {
private static final Logger logger = LoggerFactory.getLogger(ITAClientMQTT.class);
public String TOPIC = "#";
public String HOST = "";
public String randomKey; //a random
private String clientID;
private MqttClient client;
private MqttConnectOptions options;
private String userName = "";
private String passWord = "";
private MqttPublisherEntity publisherEntity;
public ITAClientMQTT(MqttPublisherEntity publisherEntity, String randomKey){
this.publisherEntity = publisherEntity;
this.HOST = publisherEntity.getHost();
this.userName = publisherEntity.getUsername();
this.passWord = publisherEntity.getPassword();
this.TOPIC = publisherEntity.getTopic();
this.randomKey = randomKey;
this.clientID = this.userName+":"+this.passWord+randomKey;
}
public void reconnect(MqttClient mqttClient) throws MqttException {
mqttClient.reconnect();
}
public void start() throws MqttException {
logger.info("重新连接成功,Connect to MQTT: {} Client ID: {}",this.HOST,clientID);
logger.info("Username: {}",userName);
client = new MqttClient(HOST, clientID, new MemoryPersistence());
options = new MqttConnectOptions();
options.setCleanSession(false);
options.setUserName(userName);
options.setPassword(passWord.toCharArray());
options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1);
// Set Timeout
options.setConnectionTimeout(20);
// Set mqtt-heartbeat interval
options.setKeepAliveInterval(10);
options.setAutomaticReconnect(true);
client.setCallback(new ITAPushCallback(publisherEntity,randomKey,client));
client.connect(options);
//subscribe
int[] Qos = {0};
String[] topic1 = {TOPIC};
client.subscribe(topic1, Qos);
}
}

121
src/main/java/com/techsor/datacenter/receiver/clients/ITAPushCallback.java

@ -0,0 +1,121 @@
package com.techsor.datacenter.receiver.clients;
import cn.hutool.json.JSONUtil;
import com.google.gson.Gson;
import com.techsor.datacenter.receiver.config.DataCenterEnvConfig;
import com.techsor.datacenter.receiver.constants.CompanyConstants;
import com.techsor.datacenter.receiver.constants.UrlConstants;
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity;
import com.techsor.datacenter.receiver.entity.common.MqttPublisherEntity;
import com.techsor.datacenter.receiver.service.MqttHistoryDynamoDBService;
import com.techsor.datacenter.receiver.service.MqttHistoryService;
import com.techsor.datacenter.receiver.utils.DefaultHttpRequestUtil;
import com.techsor.datacenter.receiver.utils.SpringUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;
/**
* 发布消息的回调类
* <p>
* 必须实现MqttCallback的接口并实现对应的相关接口方法CallBack 类将实现 MqttCallBack
* 每个客户机标识都需要一个回调实例在此示例中构造函数传递客户机标识以另存为实例数据
* 在回调中将它用来标识已经启动了该回调的哪个实例
* 必须在回调类中实现三个方法
* <p>
* public void messageArrived(MqttTopic topic, MqttMessage message)接收已经预订的发布
* <p>
* public void connectionLost(Throwable cause)在断开连接时调用
* <p>
* public void deliveryComplete(MqttDeliveryToken token))
* 接收到已经发布的 QoS 1 QoS 2 消息的传递令牌时调用
* MqttClient.connect 激活此回调
*/
@Slf4j
public class ITAPushCallback implements MqttCallback, MqttCallbackExtended {
private DataCenterEnvConfig dataCenterEnvConfig;
private String randomKey;
private MqttPublisherEntity mqttPublisherEntity;
private MqttClient client;
private MqttHistoryService mqttHistoryService;
private DefaultHttpRequestUtil defaultHttpRequestUtil;
private MqttHistoryDynamoDBService mqttHistoryDynamoDBService;
public ITAPushCallback(MqttPublisherEntity mqttPublisherEntity, String randomKey, MqttClient client) {
this.randomKey = randomKey;
this.mqttPublisherEntity = mqttPublisherEntity;
this.client = client;
this.mqttHistoryService = SpringUtils.getBean("mqttHistoryService", MqttHistoryService.class);
this.defaultHttpRequestUtil = SpringUtils.getBean("defaultHttpRequestUtil", DefaultHttpRequestUtil.class);
this.dataCenterEnvConfig = SpringUtils.getBean("dataCenterEnvConfig", DataCenterEnvConfig.class);
this.mqttHistoryDynamoDBService=SpringUtils.getBean("mqttHistoryDynamoDBService",MqttHistoryDynamoDBService.class);
}
@SneakyThrows
public void connectionLost(Throwable cause) {
// 连接丢失后,一般在这里面进行重连,由于设置了自动重连,断开连接后会自动重连,然后进入connectComplete中
log.error("Connection Lost,Trying to reconnect... ClientId: {}", this.client.getClientId());
Boolean isConnected = client.isConnected();
log.warn("client connect status: {}", isConnected);
}
/**
* 连接成功会进入到这里
*
* @param reconnect
* @param serverURI
*/
@SneakyThrows
@Override
public void connectComplete(boolean reconnect, String serverURI) {
// 可以做订阅主题
log.info("Connect success");
Boolean isConnected = client.isConnected();
log.warn("client connect status: {}", isConnected);
if (isConnected) {
log.info("Subscribe to :{}", mqttPublisherEntity.getTopic());
client.subscribe(mqttPublisherEntity.getTopic(), 0);
}
}
public void deliveryComplete(IMqttDeliveryToken token) {
log.info("deliveryComplete--------- {}", token.isComplete());
}
public void messageArrived(String topic, MqttMessage message) throws Exception {
log.info("message arrived {}", JSONUtil.toJsonStr(message));
BaseTransDataEntity mqttHistoryEntity = new BaseTransDataEntity();
mqttHistoryEntity.setContent(new String(message.getPayload()));
mqttHistoryEntity.setTs(System.currentTimeMillis() + "");
mqttHistoryEntity.setCompany(CompanyConstants.ZIFISENSE);
mqttHistoryService.insertHistory(mqttHistoryEntity);
//保存到dynamodb中
this.mqttHistoryDynamoDBService.save(mqttHistoryEntity);
try {
forwardMessage(mqttHistoryEntity);
} catch (Exception e) {
log.error("Not correct data:{}", e.getMessage(), e);
}
}
//转发收到的数据到 数据转发平台
private void forwardMessage(BaseTransDataEntity mqttHistoryEntity) {
//只转发终端数据
if (mqttHistoryEntity.getContent().contains("msUid")) {
Gson gson = new Gson();
String jsonParams = gson.toJson(mqttHistoryEntity);
log.info("Send Data To: {}", UrlConstants.RECEIVER_URL);
log.info("Send Data : {}", jsonParams);
this.defaultHttpRequestUtil.postJson(this.dataCenterEnvConfig.getReceiveUrl(), jsonParams);
}
}
}

50
src/main/java/com/techsor/datacenter/receiver/clients/MetComClient.java

@ -0,0 +1,50 @@
package com.techsor.datacenter.receiver.clients;
import com.google.gson.Gson;
import com.techsor.datacenter.receiver.constants.CompanyConstants;
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity;
import com.techsor.datacenter.receiver.entity.common.JsonResponse;
import com.techsor.datacenter.receiver.entity.metcom.MetcomEntity;
import com.techsor.datacenter.receiver.service.DataTransService;
import com.techsor.datacenter.receiver.service.MqttHistoryDynamoDBService;
import com.techsor.datacenter.receiver.service.RestfulService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
@RestController
@CrossOrigin(originPatterns = "*", methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT})
public class MetComClient {
private static final Logger logger = LoggerFactory.getLogger(MetComClient.class);
@Resource
private RestfulService historyDAO;
@Resource
private DataTransService dataTransService;
@Resource
private MqttHistoryDynamoDBService mqttHistoryDynamoDBService;
//MetCom 3D室内定位数据转发接口
@PutMapping(value = "api/v2/to_dbm/metcom/user/location/{userId}")
public JsonResponse nittan(@PathVariable("userId") String userId, @RequestBody String rawJson) throws Exception {
//合并uuid及其他参数
MetcomEntity metcomEntity = new Gson().fromJson(rawJson,MetcomEntity.class);
metcomEntity.setUuid(userId);
rawJson = new Gson().toJson(metcomEntity);
//记录数据转发历史
historyDAO.insertHistory(rawJson, CompanyConstants.METCOM);
BaseTransDataEntity baseTransDataEntity=new BaseTransDataEntity();
baseTransDataEntity.setCompany(CompanyConstants.METCOM);
baseTransDataEntity.setContent(rawJson);
baseTransDataEntity.setTs(String.valueOf(System.currentTimeMillis()));
this.mqttHistoryDynamoDBService.save(baseTransDataEntity);
//转发数据
this.dataTransService.transferData(userId,CompanyConstants.METCOM,rawJson);
return JsonResponse.buildSuccess("");
}
}

39
src/main/java/com/techsor/datacenter/receiver/clients/NBIClient.java

@ -0,0 +1,39 @@
package com.techsor.datacenter.receiver.clients;
import com.techsor.datacenter.receiver.constants.CompanyConstants;
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity;
import com.techsor.datacenter.receiver.entity.common.JsonResponse;
import com.techsor.datacenter.receiver.service.DataTransService;
import com.techsor.datacenter.receiver.service.MqttHistoryDynamoDBService;
import com.techsor.datacenter.receiver.service.RestfulService;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
@RestController
@CrossOrigin(originPatterns = "*", methods = {RequestMethod.GET, RequestMethod.POST})
public class NBIClient {
@Resource
private RestfulService oviPhoneDAO;
@Resource
private DataTransService dataTransService;
@Resource
private MqttHistoryDynamoDBService mqttHistoryDynamoDBService;
//nbi数据转发测试接口,直接转发数据
@RequestMapping(value = "api/v1/nbi/raw", method = RequestMethod.POST)
public JsonResponse ReceiveRawData(@RequestBody String rawJson) {
oviPhoneDAO.insertHistory(rawJson,CompanyConstants.NBI);
BaseTransDataEntity baseTransDataEntity=new BaseTransDataEntity();
baseTransDataEntity.setCompany(CompanyConstants.NBI);
baseTransDataEntity.setContent(rawJson);
baseTransDataEntity.setTs(String.valueOf(System.currentTimeMillis()));
this.mqttHistoryDynamoDBService.save(baseTransDataEntity);
this.dataTransService.transferData("",CompanyConstants.NBI,rawJson);
return JsonResponse.buildSuccess(rawJson);
}
}

41
src/main/java/com/techsor/datacenter/receiver/clients/NittanClient.java

@ -0,0 +1,41 @@
package com.techsor.datacenter.receiver.clients;
import com.techsor.datacenter.receiver.constants.CompanyConstants;
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity;
import com.techsor.datacenter.receiver.entity.common.JsonResponse;
import com.techsor.datacenter.receiver.service.DataTransService;
import com.techsor.datacenter.receiver.service.MqttHistoryDynamoDBService;
import com.techsor.datacenter.receiver.service.RestfulService;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
@RestController
@CrossOrigin(originPatterns = "*", methods = {RequestMethod.GET, RequestMethod.POST})
public class NittanClient {
@Resource
private RestfulService historyDAO;
@Resource
private DataTransService dataTransService;
@Resource
private MqttHistoryDynamoDBService mqttHistoryDynamoDBService;
//nittan数据转发接口
@RequestMapping(value = "api/v1/to_dbm/nittan", method = RequestMethod.POST)
public JsonResponse nittan(@RequestBody String rawJson) throws Exception {
//记录数据转发历史
historyDAO.insertHistory(rawJson, CompanyConstants.NITTAN);
BaseTransDataEntity baseTransDataEntity=new BaseTransDataEntity();
baseTransDataEntity.setCompany(CompanyConstants.NITTAN);
baseTransDataEntity.setContent(rawJson);
baseTransDataEntity.setTs(String.valueOf(System.currentTimeMillis()));
this.mqttHistoryDynamoDBService.save(baseTransDataEntity);
this.dataTransService.transferData("",CompanyConstants.NITTAN,rawJson);
return JsonResponse.buildSuccess("");
}
}

49
src/main/java/com/techsor/datacenter/receiver/clients/OCRClient.java

@ -0,0 +1,49 @@
package com.techsor.datacenter.receiver.clients;
import com.techsor.datacenter.receiver.constants.CompanyConstants;
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity;
import com.techsor.datacenter.receiver.entity.common.JsonResponse;
import com.techsor.datacenter.receiver.service.DataTransService;
import com.techsor.datacenter.receiver.service.MqttHistoryDynamoDBService;
import com.techsor.datacenter.receiver.service.RestfulService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
@RestController
@CrossOrigin(originPatterns = "*", methods = {RequestMethod.GET, RequestMethod.POST})
public class OCRClient {
private static final Logger logger = LoggerFactory.getLogger(OCRClient.class);
@Resource
private RestfulService historyDAO;
@Resource
private MqttHistoryDynamoDBService mqttHistoryDynamoDBService;
@Resource
private DataTransService dataTransService;
/**
* OCR 数据接口
* @param rawJson
* @return
* @throws Exception
*/
@RequestMapping(value = "api/v1/to_dbm/ocr", method = RequestMethod.POST)
public JsonResponse nittan(@RequestBody String rawJson) throws Exception {
//记录数据转发历史
historyDAO.insertHistory(rawJson, CompanyConstants.OCR);
BaseTransDataEntity baseTransDataEntity=new BaseTransDataEntity();
baseTransDataEntity.setCompany(CompanyConstants.OCR);
baseTransDataEntity.setContent(rawJson);
baseTransDataEntity.setTs(String.valueOf(System.currentTimeMillis()));
this.mqttHistoryDynamoDBService.save(baseTransDataEntity);
this.dataTransService.transferData("",CompanyConstants.OCR,rawJson);
return JsonResponse.buildSuccess("");
}
}

38
src/main/java/com/techsor/datacenter/receiver/clients/OVIPhoneClient.java

@ -0,0 +1,38 @@
package com.techsor.datacenter.receiver.clients;
import com.techsor.datacenter.receiver.constants.CompanyConstants;
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity;
import com.techsor.datacenter.receiver.entity.common.JsonResponse;
import com.techsor.datacenter.receiver.service.DataTransService;
import com.techsor.datacenter.receiver.service.MqttHistoryDynamoDBService;
import com.techsor.datacenter.receiver.service.RestfulService;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
@RestController
@CrossOrigin(originPatterns = "*", methods = {RequestMethod.GET, RequestMethod.POST})
public class OVIPhoneClient {
@Resource
private RestfulService oviPhoneDAO;
@Resource
private MqttHistoryDynamoDBService mqttHistoryDynamoDBService;
@Resource
private DataTransService dataTransService;
//nittan数据转发测试接口,直接转发数据
@RequestMapping(value = "api/v1/oviphone/raw", method = RequestMethod.POST)
public JsonResponse ReceiveRawData(@RequestBody String rawJson) {
oviPhoneDAO.insertHistory(rawJson,CompanyConstants.OVIPHONE);
BaseTransDataEntity baseTransDataEntity=new BaseTransDataEntity();
baseTransDataEntity.setCompany(CompanyConstants.OVIPHONE);
baseTransDataEntity.setContent(rawJson);
baseTransDataEntity.setTs(String.valueOf(System.currentTimeMillis()));
this.mqttHistoryDynamoDBService.save(baseTransDataEntity);
this.dataTransService.transferData("",CompanyConstants.OVIPHONE,rawJson);
return JsonResponse.buildSuccess(rawJson);
}
}

59
src/main/java/com/techsor/datacenter/receiver/config/CachedBodyHttpServletRequest.java

@ -0,0 +1,59 @@
package com.techsor.datacenter.receiver.config;
import java.io.*;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
public class CachedBodyHttpServletRequest extends HttpServletRequestWrapper {
byte[] cachedBody;
public CachedBodyHttpServletRequest(HttpServletRequest request) throws IOException {
super(request);
InputStream requestInputStream = request.getInputStream();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = requestInputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, len);
}
this.cachedBody = byteArrayOutputStream.toByteArray();
}
@Override
public ServletInputStream getInputStream() throws IOException {
return new CachedBodyServletInputStream(this.cachedBody);
}
private static class CachedBodyServletInputStream extends ServletInputStream {
private ByteArrayInputStream byteArrayInputStream;
public CachedBodyServletInputStream(byte[] data) {
this.byteArrayInputStream = new ByteArrayInputStream(data);
}
@Override
public boolean isFinished() {
return byteArrayInputStream.available() == 0;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
throw new UnsupportedOperationException();
}
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
}
}

95
src/main/java/com/techsor/datacenter/receiver/config/DataCenterEnvConfig.java

@ -0,0 +1,95 @@
package com.techsor.datacenter.receiver.config;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
/**
* 系统配置
* */
@Configuration
public class DataCenterEnvConfig {
private String receiveUrl;
@Value("${data.center.receive.address}")
private String apiAddress;
@Value("${data.center.receive.api:#{'/v1/main_receiver'}}")
private String apiUrl;
@Value("${data.center.process.api:#{'/v1/generic/process'}}")
private String processApiUrl;
@Value("${data.center.ioserver_process.api:#{'/v1/generic/ioserver_process'}}")
private String processIoserverUrl;
@Value("${data.center.ioserver_process.api:#{'/v1/generic/st150_process'}}")
private String processGW150Url;
@Value("${data.center.zaiot_process.api:#{'/v1/generic/zaiot_process'}}")
private String zaiotProcessApiUrl;
public String getReceiveUrl() {
return apiAddress+apiUrl;
}
public void setReceiveUrl(String receiveUrl) {
this.receiveUrl = receiveUrl;
}
public String getApiAddress() {
return apiAddress;
}
public void setApiAddress(String apiAddress) {
this.apiAddress = apiAddress;
}
public String getApiUrl() {
return apiUrl;
}
public void setApiUrl(String apiUrl) {
this.apiUrl = apiUrl;
}
public String getProcessApiUrl() {
return apiAddress+processApiUrl;
}
public void setProcessApiUrl(String processApiUrl) {
this.processApiUrl = processApiUrl;
}
public String getProcessIoserverUrl() {
return apiAddress+processIoserverUrl;
}
public void setProcessIoserverUrl(String processIoserverUrl) {
this.processIoserverUrl = processIoserverUrl;
}
public String getZaiotProcessApiUrl() {
return apiAddress+zaiotProcessApiUrl;
}
public void setZaiotProcessApiUrl(String zaiotProcessApiUrl) {
this.zaiotProcessApiUrl = zaiotProcessApiUrl;
}
public String getProcessGW150Url() {
return processGW150Url;
}
public void setProcessGW150Url(String processGW150Url) {
this.processGW150Url = processGW150Url;
}
public String getGW150ProcessUrl() {
return apiAddress+this.processGW150Url;
}
}

87
src/main/java/com/techsor/datacenter/receiver/config/DeltaClientConfig.java

@ -0,0 +1,87 @@
package com.techsor.datacenter.receiver.config;
import com.techsor.datacenter.receiver.entity.common.MqttPublisherEntity;
import com.techsor.datacenter.receiver.utils.SslUtil;
import lombok.Data;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Random;
@Configuration
@Data
public class DeltaClientConfig {
private static final Logger logger = LoggerFactory.getLogger(DeltaClientConfig.class);
@Value("${delta.topic:Publish_Topic}")
private String TOPIC;
// public String HOST = "ssl://8.209.255.206:8883";
@Value("${delta.host:ssl://127.0.0.1:8883}")
private String HOST = "ssl://127.0.0.1:8883";
@Value("${delta.userName:techsor}")
private String userName = "techsor";
@Value("${delta.usepassWordrName:techsorAsd123456}")
private String passWord = "techsorAsd123456";
@Value("${delta.enableSSL:false}")
private boolean enableSSL;
@Bean
public MqttPublisherEntity deltaMqttPublisherEntity(){
MqttPublisherEntity publisherEntity = new MqttPublisherEntity();
publisherEntity.setHost(this.HOST);
publisherEntity.setUsername(this.userName);
publisherEntity.setPassword(this.passWord);
publisherEntity.setTopic(this.TOPIC);
return publisherEntity;
}
@Bean
public MqttConnectOptions options() throws Exception {
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(false);
options.setUserName(userName);
options.setPassword(passWord.toCharArray());
options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1);
options.setHttpsHostnameVerificationEnabled(false);
//Set ssl
if(enableSSL){
options.setSocketFactory(SslUtil.getSocketFactory("/ssl/ca.pem", "/ssl/client.pem", "/ssl/client.key", ""));
}
// Set Timeout
options.setConnectionTimeout(0);
// Set mqtt-heartbeat interval
options.setKeepAliveInterval(60);
options.setAutomaticReconnect(true);
return options;
}
@Bean
public String clientID(){
String clientID = this.userName+":"+this.passWord+getRandoms();
return clientID;
}
@Bean
public MqttClient client(String clientID) throws MqttException {
logger.info("Connect to MQTTs:"+this.HOST+" Client ID:"+clientID);
logger.info("Username:"+userName);
MqttClient client = new MqttClient(HOST, clientID, new MemoryPersistence());
return client;
}
public int getRandoms(){
// 创建一个Random对象
Random random = new Random();
// 生成一个范围在100到999之间的随机数(包括100,但不包括1000)
int randomNumber = random.nextInt(900) + 100;
return randomNumber;
}
}

76
src/main/java/com/techsor/datacenter/receiver/config/DynamoDBConfig.java

@ -0,0 +1,76 @@
//package com.techsor.datacenter.receiver.config;
//
//
//import com.amazonaws.auth.AWSCredentials;
//import com.amazonaws.auth.AWSCredentialsProvider;
//import com.amazonaws.auth.AWSStaticCredentialsProvider;
//import com.amazonaws.auth.BasicAWSCredentials;
//import com.amazonaws.regions.Regions;
//import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
//import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
//import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
//import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperConfig;
//import org.socialsignin.spring.data.dynamodb.core.DynamoDBTemplate;
//import org.socialsignin.spring.data.dynamodb.mapping.DynamoDBMappingContext;
//import org.socialsignin.spring.data.dynamodb.repository.config.DynamoDBMapperConfigFactory;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//
////@Configuration
////public class DynamoDBConfig {
////
//// @Value("${amazon.aws.accesskey}")
//// private String amazonAWSAccessKey;
////
//// @Value("${amazon.aws.secretkey}")
//// private String amazonAWSSecretKey;
////
//// public AWSCredentialsProvider amazonAWSCredentialsProvider() {
//// return new AWSStaticCredentialsProvider(amazonAWSCredentials());
//// }
////
//// @Bean
//// public AWSCredentials amazonAWSCredentials() {
//// return new BasicAWSCredentials(amazonAWSAccessKey, amazonAWSSecretKey);
//// }
//// @Value("${amazon.dynamodb.tableName:mqtt_history}")
//// private String dynamoDBTableName ;
////
//// @Bean
//// public DynamoDBMapperConfig.TableNameOverride tableNameOverrider() {
//// return DynamoDBMapperConfig.TableNameOverride.withTableNameReplacement(this.dynamoDBTableName);
//// }
////
//// @Bean
//// public DynamoDBMapperConfig dynamoCustomDBMapperConfig(DynamoDBMapperConfig.TableNameOverride tableNameOverrider) {
//// DynamoDBMapperConfig.Builder builder = new DynamoDBMapperConfig.Builder();
//// builder.withTableNameOverride(tableNameOverrider);
//// return builder.build();
////
//// }
////
//// @Bean
//// public DynamoDBMapper dynamoCustomDBMapper(AmazonDynamoDB amazonDynamoDB, DynamoDBMapperConfig dynamoCustomDBMapperConfig) {
//// return new DynamoDBMapper(amazonDynamoDB, dynamoCustomDBMapperConfig);
//// }
////
//// @Bean
//// public AmazonDynamoDB amazonDynamoDB() {
//// return AmazonDynamoDBClientBuilder.standard().withCredentials(amazonAWSCredentialsProvider())
//// .withRegion(Regions.AP_NORTHEAST_1).build();
//// }
////
//// @Bean
//// public DynamoDBMappingContext dynamoDBMappingContext() {
//// return new DynamoDBMappingContext();
//// }
////
//// @Bean
//// public DynamoDBTemplate dynamoDBTemplate(AmazonDynamoDB amazonDynamoDB, DynamoDBMapper dynamoCustomDBMapper ,DynamoDBMapperConfig dynamoCustomDBMapperConfig) {
////
//// return new DynamoDBTemplate(amazonDynamoDB, dynamoCustomDBMapper,dynamoCustomDBMapperConfig);
//// }
//
//
//}

16
src/main/java/com/techsor/datacenter/receiver/config/JdbcTemplateConfig.java

@ -0,0 +1,16 @@
//package com.techsor.datacenter.receiver.config;
//
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.jdbc.core.JdbcTemplate;
//
//import javax.sql.DataSource;
//
//@Configuration
//public class JdbcTemplateConfig {
//
// @Bean
// public JdbcTemplate jdbcTemplate(DataSource dataSource){
// return new JdbcTemplate(dataSource);
// }
//}

87
src/main/java/com/techsor/datacenter/receiver/config/MyFilter.java

@ -0,0 +1,87 @@
package com.techsor.datacenter.receiver.config;
import com.google.gson.Gson;
import com.jayway.jsonpath.JsonPath;
import com.techsor.datacenter.receiver.entity.datasource.DatasourceConfigEntity;
import com.techsor.datacenter.receiver.service.GlobalStateService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.GenericFilterBean;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
@Component
public class MyFilter extends GenericFilterBean {
@Autowired
private GlobalStateService globalStateService;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest=(HttpServletRequest)request;
HttpServletResponse httpServletResponse=(HttpServletResponse)response;
String uri=httpServletRequest.getRequestURI();
if (this.globalStateService.checkUrlExist(uri)) {
StringBuilder stringBuilder = new StringBuilder();
// 使用包装器包装原始的 HttpServletRequest
CachedBodyHttpServletRequest wrappedRequest = new CachedBodyHttpServletRequest(httpServletRequest);
// 获取请求体
String body = new String(wrappedRequest.cachedBody, StandardCharsets.UTF_8);
body=StringUtils.replaceAll(body, "\n", "");
body=StringUtils.replaceAll(body, "\t", "");
body=StringUtils.replaceAll(body, "\\s+", "");
DatasourceConfigEntity dataSrcEntity = this.globalStateService.getDatasourceConfig(uri);
if(StringUtils.isEmpty(dataSrcEntity.getDeviceIdPosition())){
httpServletResponse.setStatus(200);
Map<String,String> errorMap=new HashMap<>();
errorMap.put("code","-1");
errorMap.put("msg","deviceId position id null");
Gson gson=new Gson();
httpServletResponse.setContentType("application/json;charset=UTF-8");
httpServletResponse.getWriter().write(gson.toJson(errorMap));
httpServletResponse.getWriter().flush();
return;
}
Gson currentGson=new Gson();
Map resultMao=currentGson.fromJson(body, Map.class);
String resultBody=currentGson.toJson(resultMao);
String deviceId= JsonPath.read(resultBody,dataSrcEntity.getDeviceIdPosition());
if(StringUtils.isEmpty(deviceId)){
httpServletResponse.setStatus(200);
Map<String,String> errorMap=new HashMap<>();
httpServletResponse.setContentType("application/json;charset=UTF-8");
errorMap.put("code","-1");
errorMap.put("msg","deviceId is null");
Gson gson=new Gson();
httpServletResponse.getWriter().write(gson.toJson(errorMap));
httpServletResponse.getWriter().flush();
return;
}
String contextPath=httpServletRequest.getContextPath();
wrappedRequest.getRequestDispatcher(contextPath+"/api/generic/process?MyDeviceId="+deviceId).forward(wrappedRequest, response);
}else{
chain.doFilter(request, response);
}
}
}

137
src/main/java/com/techsor/datacenter/receiver/config/RedisConfig.java

@ -0,0 +1,137 @@
package com.techsor.datacenter.receiver.config;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.techsor.datacenter.receiver.listener.RedisNotificationMessageSubscriber;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.integration.redis.util.RedisLockRegistry;
import java.time.Duration;
@Configuration
public class RedisConfig {
@Value("${spring.redis.database}")
private int database;
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.password}")
private String password;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private long timeout;
@Value("${spring.redis.lettuce.shutdown-timeout}")
private long shutDownTimeout;
@Value("${spring.redis.lettuce.pool.max-idle}")
private int maxIdle;
@Value("${spring.redis.lettuce.pool.min-idle}")
private int minIdle;
@Value("${spring.redis.lettuce.pool.max-active}")
private int maxActive;
@Value("${spring.redis.lettuce.pool.max-wait}")
private long maxWait;
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
@Bean
public LettuceConnectionFactory lettuceConnectionFactory() {
GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
genericObjectPoolConfig.setMaxIdle(maxIdle);
genericObjectPoolConfig.setMinIdle(minIdle);
genericObjectPoolConfig.setMaxTotal(maxActive);
genericObjectPoolConfig.setMaxWaitMillis(maxWait);
genericObjectPoolConfig.setTimeBetweenEvictionRunsMillis(100);
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setDatabase(database);
redisStandaloneConfiguration.setHostName(host);
redisStandaloneConfiguration.setPort(port);
redisStandaloneConfiguration.setPassword(RedisPassword.of(password));
LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
.commandTimeout(Duration.ofMillis(timeout))
.shutdownTimeout(Duration.ofMillis(shutDownTimeout))
.poolConfig(genericObjectPoolConfig)
.build();
LettuceConnectionFactory factory = new LettuceConnectionFactory(redisStandaloneConfiguration, clientConfig);
return factory;
}
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(lettuceConnectionFactory);
//使用Jackson2JsonRedisSerializer替换默认的JdkSerializationRedisSerializer来序列化和反序列化redis的value值
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
jackson2JsonRedisSerializer.setObjectMapper(mapper);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
@Value("${redis.lock.expire}")
private Integer lockAttempTimeout ;
@Bean
public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory){
return new RedisLockRegistry(redisConnectionFactory, "redis-receiver-lock",lockAttempTimeout);
}
@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(listenerAdapter, new PatternTopic("notificationReceiver"));
return container;
}
@Bean
MessageListenerAdapter listenerAdapter(RedisNotificationMessageSubscriber subscriber) {
return new MessageListenerAdapter(subscriber);
}
}

65
src/main/java/com/techsor/datacenter/receiver/config/RestTemplateConfig.java

@ -0,0 +1,65 @@
package com.techsor.datacenter.receiver.config;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import java.util.concurrent.TimeUnit;
/***
* 使用okhttp connectionFactory
* **/
@Configuration
public class RestTemplateConfig {
@Value("${ok.http.connect-timeout}")
private Integer connectTimeout;
@Value("${ok.http.read-timeout}")
private Integer readTimeout;
@Value("${ok.http.write-timeout}")
private Integer writeTimeout;
@Value("${ok.http.max-idle-connections}")
private Integer maxIdleConnections;
@Value("${ok.http.keep-alive-duration}")
private Long keepAliveDuration;
/**
* 声明 RestTemplate
*/
@Bean
public RestTemplate httpRestTemplate() {
ClientHttpRequestFactory factory = httpRequestFactory();
RestTemplate restTemplate = new RestTemplate(factory);
return restTemplate;
}
public ClientHttpRequestFactory httpRequestFactory() {
return new OkHttp3ClientHttpRequestFactory(okHttpConfigClient());
}
public OkHttpClient okHttpConfigClient(){
return new OkHttpClient().newBuilder()
.connectionPool(pool())
.connectTimeout(connectTimeout, TimeUnit.SECONDS)
.readTimeout(readTimeout, TimeUnit.SECONDS)
.writeTimeout(writeTimeout, TimeUnit.SECONDS)
.hostnameVerifier((hostname, session) -> true)
.build();
}
public ConnectionPool pool() {
return new ConnectionPool(maxIdleConnections, keepAliveDuration, TimeUnit.SECONDS);
}
}

56
src/main/java/com/techsor/datacenter/receiver/config/TaskExecutorConfig.java

@ -0,0 +1,56 @@
package com.techsor.datacenter.receiver.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
public class TaskExecutorConfig {
@Bean("threadPoolTaskExecutor")
public TaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(4);
executor.setMaxPoolSize(10);
executor.setThreadNamePrefix("my_executor_thread");
executor.initialize();
return executor;
}
@Bean("taskScheduler")
public TaskScheduler taskScheduler(){
ThreadPoolTaskScheduler threadPoolTaskScheduler
= new ThreadPoolTaskScheduler();
threadPoolTaskScheduler.setPoolSize(5);
threadPoolTaskScheduler.setThreadNamePrefix(
"ThreadPoolTaskScheduler");
return threadPoolTaskScheduler;
}
@Bean("postSenderThreadTaskExecutor")
public Executor postSenderThreadTaskExecutor() {
int cpuCores = Runtime.getRuntime().availableProcessors();
int poolSize = cpuCores * 2; // 假设I/O密集型,可根据实际情况调整
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(poolSize);
executor.setMaxPoolSize(poolSize * 2); // 可以根据需要进一步调整
executor.setQueueCapacity(100); // 可以根据需要进一步调整
executor.setThreadNamePrefix("Async-");
executor.setKeepAliveSeconds(60); // 如果需要,可以设置keep-alive时间
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 设置拒绝策略
executor.initialize();
return executor;
}
}

186
src/main/java/com/techsor/datacenter/receiver/config/datasource/DataSourceAdminConfig.java

@ -0,0 +1,186 @@
package com.techsor.datacenter.receiver.config.datasource;
import com.zaxxer.hikari.HikariDataSource;
import jakarta.persistence.EntityManagerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DataSourceAdminConfig {
private static final Logger logger= LoggerFactory.getLogger(DataSourceAdminConfig.class);
@Value("${spring.datasource.admin.name}")
private String name;
@Value("${spring.datasource.admin.url}")
private String url;
@Value("${spring.datasource.admin.username}")
private String username;
@Value("${spring.datasource.admin.password}")
private String password;
@Value("${spring.datasource.admin.driverClassName}")
private String driverClassName;
@Value("${spring.datasource.admin.hikari.schema}")
private String schema;
@Value("${spring.datasource.admin.hikari.minimum-idle}")
private Integer mininumIdle;
@Value("${spring.datasource.admin.hikari.maximum-pool-size}")
private Integer maximuPoolSize;
@Value("${spring.datasource.admin.hikari.connection-timeout}")
private Integer connectionTimeout;
@Value("${dynamic.jdbc.url}")
private String dynamicJdbcUrl;
/**
* Retrieve the admin data source.
*/
@Primary
@Bean
public DataSource adminDatasource() {
HikariDataSource adminDatasource = DataSourceBuilder.create()
.url(url)
.username(username)
.password(password).driverClassName(driverClassName)
.type(HikariDataSource.class)
.build();
adminDatasource.setSchema(schema);
adminDatasource.setMinimumIdle(mininumIdle);
adminDatasource.setMaximumPoolSize(maximuPoolSize);
adminDatasource.setConnectionTimeout(connectionTimeout);
return adminDatasource;
}
@Bean
public DataSource thirdDatasource() {
String dbUrl=String.format(dynamicJdbcUrl,"data_center_aeon_admin");
HikariDataSource adminDatasource = DataSourceBuilder.create()
.url(dbUrl)
.username(username)
.password(password).driverClassName(driverClassName)
.type(HikariDataSource.class)
.build();
adminDatasource.setSchema("data_center_aeon_admin");
adminDatasource.setMinimumIdle(mininumIdle);
adminDatasource.setMaximumPoolSize(maximuPoolSize);
adminDatasource.setConnectionTimeout(connectionTimeout);
return adminDatasource;
}
/**
* Construct a JdbcTemplate for accessing the dynamic data source.
*/
@Bean
public JdbcTemplate jdbcTemplate(@Qualifier("adminDatasource") DataSource adminDatasource) {
return new JdbcTemplate(adminDatasource);
}
@Bean
public DataSource dynamicDataSource(JdbcTemplate jdbcTemplate,@Qualifier("adminDatasource") DataSource adminDatasource,@Qualifier("thirdDatasource") DataSource thirdDatasource) {
DynamicRouteDataSource dynamicDataSource = new DynamicRouteDataSource();
Map<Object, Object> targetDataSources = new HashMap<>();
String sql=" SELECT " +
" bcom.id,bcom.parent_id, " +
" bcom.company_name companyName " +
" FROM " +
" data_center_aeon_admin.basic_company bcom " +
" WHERE (bcom.parent_id=1 or bcom.parent_id=-1) and bcom.flag!=1";
jdbcTemplate.query(sql,rs->{
HikariDataSource dataSource1 = new HikariDataSource();
String dbName="data_center_aeon_"+rs.getInt("id");
String dbUrl=String.format(dynamicJdbcUrl,dbName);
dataSource1.setJdbcUrl(dbUrl);
dataSource1.setUsername(username);
dataSource1.setPassword(password);
dataSource1.setDriverClassName(driverClassName);
dataSource1.setSchema(dbName);
dataSource1.setMinimumIdle(mininumIdle);
dataSource1.setMaximumPoolSize(maximuPoolSize);
dataSource1.setConnectionTimeout(connectionTimeout);
if (rs.getInt("parent_id")==1 || rs.getInt("parent_id")==-1){
targetDataSources.put("dataSourceForCompany_"+rs.getInt("id"), dataSource1);
logger.info("Put dataSourceForCompany_"+rs.getInt("id")+" -- URL:"+dbUrl);
}else{
}
});
targetDataSources.put("dataSourceForCompany_0", thirdDatasource);
dynamicDataSource.setTargetDataSources(targetDataSources);
dynamicDataSource.setDefaultTargetDataSource(adminDatasource); // 设置默认数据源
return dynamicDataSource;
}
@Bean
public JdbcTemplate dynamicJdbcTemplate(@Qualifier("dynamicDataSource") DataSource dynamicDataSource) {
return new JdbcTemplate(dynamicDataSource);
}
// 新增这个Bean,让Spring容器有EntityManagerFactoryBuilder可用
@Bean
public EntityManagerFactoryBuilder entityManagerFactoryBuilder() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
// 如果你有特别的jpa配置,可以设置下面这行:
// vendorAdapter.setGenerateDdl(true);
// vendorAdapter.setShowSql(true);
return new EntityManagerFactoryBuilder(vendorAdapter, new HashMap<>(), null);
}
@Primary
@Bean(name = {"adminEntityManagerFactory", "entityManagerFactory"})
public LocalContainerEntityManagerFactoryBean adminEntityManagerFactory(
EntityManagerFactoryBuilder builder,
@Qualifier("adminDatasource") DataSource adminDatasource) {
return builder
.dataSource(adminDatasource)
.packages("com.techsor.datacenter.receiver.entity")
.persistenceUnit("adminPU")
.build();
}
@Primary
@Bean(name = "adminTransactionManager")
public PlatformTransactionManager adminTransactionManager(
@Qualifier("adminEntityManagerFactory") EntityManagerFactory adminEntityManagerFactory) {
return new JpaTransactionManager(adminEntityManagerFactory);
}
}

18
src/main/java/com/techsor/datacenter/receiver/config/datasource/DataSourceContextHolder.java

@ -0,0 +1,18 @@
package com.techsor.datacenter.receiver.config.datasource;
public class DataSourceContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void setCurrentDataSourceKey(String dataSourceKey) {
contextHolder.set(dataSourceKey);
}
public static String getCurrentDataSourceKey() {
return contextHolder.get();
}
public static void clearCurrentDataSourceKey() {
contextHolder.remove();
}
}

13
src/main/java/com/techsor/datacenter/receiver/config/datasource/DynamicRouteDataSource.java

@ -0,0 +1,13 @@
package com.techsor.datacenter.receiver.config.datasource;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicRouteDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
// Retrieve the key of the data source to be used by the current thread.
return DataSourceContextHolder.getCurrentDataSourceKey();
}
}

42
src/main/java/com/techsor/datacenter/receiver/config/kafka/Main.java

@ -0,0 +1,42 @@
package com.techsor.datacenter.receiver.config.kafka;
import com.techsor.datacenter.receiver.config.kafka.ZiFiClient;
import com.techsor.datacenter.receiver.config.kafka.imp.ClientFactory;
import com.techsor.datacenter.receiver.config.kafka.imp.ClientType;
public class Main {
public static void main(String[] args) {
String host;
String apiKey;
String apiSecret;
String companyCode;
//hostname,连接的服务器地址,实际使用需要修改\com\zifisense\zetag\mq\api\RegionEnum.java里面的连接地址
host = "https://zetagintl.zifisense.com:9093";
//apiKey,现在支持一个企业有多ApiKey;在V1版本为企业编码
apiKey = "7c5554faf5744135b310a81a13bb487e";
// apiKey对应的apiSecret;在v1版本中,相当于企业秘钥
apiSecret = "691b57705c644b6ab080a89de7949f27";
//企业编号
companyCode = "00ebe81f74b34ce38b41266993487f3c";
//建立客户端
ZiFiClient c = ClientFactory.createClient(ClientType.KAFKA, host, apiKey, apiSecret, companyCode);
//订阅topic
c.subscribe();
/* 在v1版本中还需指定topic该方式已被弃用
// 描述需要获取哪些数据
String topic= "zetag-heartbeat-all";
c.subscribe(topic);
*/
while (true) {
//循环处理收到的数据
c.poll().forEach(message->{
System.out.printf("id = %s, value = %s%n", message.getMessageId(), message.getBody());
});
//commit之后才能继续消费下一批次数据
c.commit();
}
}
}

22
src/main/java/com/techsor/datacenter/receiver/config/kafka/RegionEnum.java

@ -0,0 +1,22 @@
package com.techsor.datacenter.receiver.config.kafka;
public enum RegionEnum {
CN("zetagos.zifisense.com:9093");
RegionEnum(String url) {
this.url = url;
}
private String url;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}

30
src/main/java/com/techsor/datacenter/receiver/config/kafka/ZiFiClient.java

@ -0,0 +1,30 @@
package com.techsor.datacenter.receiver.config.kafka;
import com.techsor.datacenter.receiver.config.kafka.RegionEnum;
import com.techsor.datacenter.receiver.config.kafka.model.Message;
import java.util.Collection;
public abstract class ZiFiClient {
public abstract void init(com.techsor.datacenter.receiver.config.kafka.RegionEnum region, String apiKey, String apiSecret, String companyCode);
public abstract void init(RegionEnum region, String apiKey, String apiSecret, String companyCode, String certPath);
public abstract void init(String host, String apiKey, String apiSecret, String companyCode);
public abstract void init(String host, String apiKey, String apiSecret, String companyCode, String certPath);
public abstract void subscribe(String topic);
public abstract void subscribe();
public abstract Collection<Message> poll();
public abstract void commit();
}

44
src/main/java/com/techsor/datacenter/receiver/config/kafka/imp/ClientFactory.java

@ -0,0 +1,44 @@
package com.techsor.datacenter.receiver.config.kafka.imp;
import com.techsor.datacenter.receiver.config.kafka.RegionEnum;
import com.techsor.datacenter.receiver.config.kafka.ZiFiClient;
import com.techsor.datacenter.receiver.config.kafka.imp.ClientType;
public class ClientFactory {
private static Object loadImplement(String className)
{
try {
ClassLoader cl = ClientFactory.class.getClassLoader();
Class<?> implClass;
implClass = Class.forName(className, true, cl);
return implClass.newInstance();
} catch (ClassNotFoundException e) {
throw new RuntimeException("Cannot load class " + className, e);
} catch (InstantiationException e) {
throw new RuntimeException("Cannot instantiate class " + className, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("Cannot access class " + className, e);
} catch (SecurityException e) {
throw new RuntimeException("Cannot access class " + className, e);
}
}
public static ZiFiClient createClient(com.techsor.datacenter.receiver.config.kafka.imp.ClientType type, RegionEnum region, String apiKey, String apiSecret, String companyCode){
ZiFiClient client = (ZiFiClient)loadImplement(type.getName());
client.init(region, apiKey, apiSecret, companyCode);
return client;
}
public static ZiFiClient createClient(com.techsor.datacenter.receiver.config.kafka.imp.ClientType type, String host, String apiKey, String apiSecret, String companyCode){
ZiFiClient client = (ZiFiClient)loadImplement(type.getName());
client.init(host, apiKey, apiSecret, companyCode);
return client;
}
public static ZiFiClient createClient(ClientType type, RegionEnum region, String apiKey, String apiSecret, String companyCode, String certPath){
ZiFiClient client = (ZiFiClient)loadImplement(type.getName());
client.init(region, apiKey, apiSecret, companyCode, certPath);
return client;
}
}

21
src/main/java/com/techsor/datacenter/receiver/config/kafka/imp/ClientType.java

@ -0,0 +1,21 @@
package com.techsor.datacenter.receiver.config.kafka.imp;
public enum ClientType {
KAFKA("com.techsor.datacenter.receiver.config.kafka.imp.KafkaZiFiClient");
ClientType(String name) {
this.name = name;
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

25
src/main/java/com/techsor/datacenter/receiver/config/kafka/imp/KafkaMessage.java

@ -0,0 +1,25 @@
package com.techsor.datacenter.receiver.config.kafka.imp;
import java.util.HashMap;
import java.util.Map;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import com.techsor.datacenter.receiver.config.kafka.model.Message;
public class KafkaMessage extends Message {
private static final String TOPIC_NAME = "topicName";
private static final String PARTITION = "partition";
private static final String TIME = "time";
public KafkaMessage(ConsumerRecord<String, String> record) {
setBody(record.value());
setMessageId(String.valueOf(record.offset()));
Map<String,String> head = new HashMap<>();
head.put(TOPIC_NAME, record.topic());
head.put(PARTITION, String.valueOf(record.partition()));
head.put(TIME, String.valueOf(record.timestamp()));
}
}

138
src/main/java/com/techsor/datacenter/receiver/config/kafka/imp/KafkaZiFiClient.java

@ -0,0 +1,138 @@
package com.techsor.datacenter.receiver.config.kafka.imp;
import com.techsor.datacenter.receiver.config.kafka.RegionEnum;
import com.techsor.datacenter.receiver.config.kafka.ZiFiClient;
import com.techsor.datacenter.receiver.config.kafka.model.Message;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.nio.file.Files;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Properties;
import java.util.regex.Pattern;
public class KafkaZiFiClient extends ZiFiClient {
private static final Logger logger = LoggerFactory.getLogger(KafkaZiFiClient.class);
private KafkaConsumer<String, String> consumer;
private static final Pattern TOPIC_PATTERN_V2 = Pattern.compile(".*-v2");
private KafkaConsumer<String, String> createConsumer(String url, String apiKey, String apiSecret, String certPath) {
Properties props = new Properties();
props.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, url);
props.setProperty(ConsumerConfig.GROUP_ID_CONFIG, apiKey);
props.setProperty(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false");
props.setProperty(ConsumerConfig.METADATA_MAX_AGE_CONFIG, "60000");
props.setProperty(ConsumerConfig.MAX_POLL_INTERVAL_MS_CONFIG, "300000");
props.setProperty(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG, "20000");
props.setProperty("security.protocol", "SASL_SSL");
props.setProperty("ssl.truststore.location", certPath);
props.setProperty("ssl.truststore.password", "zifisense");
props.setProperty("sasl.mechanism", "PLAIN");
props.setProperty("sasl.jaas.config", "org.apache.kafka.common.security.plain.PlainLoginModule required username=\"" + apiKey + "\" password=\"" + apiSecret + "\";");
props.setProperty("ssl.endpoint.identification.algorithm", "");
props.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
props.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
return new KafkaConsumer<>(props);
}
@Override
public void init(RegionEnum region, String apiKey, String apiSecret, String companyCode) {
this.init(region, apiKey, apiSecret, companyCode, getFilePath());
}
@Override
public void init(String host, String apiKey, String apiSecret, String companyCode) {
this.init(host, apiKey, apiSecret, companyCode, getFilePath());
}
@Override
public void init(String host, String apiKey, String apiSecret, String companyCode, String certPath) {
this.consumer = createConsumer(host, apiKey, apiSecret, certPath);
}
@Override
public void init(RegionEnum region, String apiKey, String apiSecret, String companyCode, String certPath) {
this.consumer = createConsumer(region.getUrl(), apiKey, apiSecret, certPath);
}
public String getFilePath() {
// String path = KafkaZiFiClient.class.getClassLoader().getResource("certificate/client.truststore.jks").getPath();
// if (path.startsWith("/")) {
// return path.substring(1);
// } else if (path.startsWith("file:/")) {
// return path.substring(6);
// } else {
// return path;
// }
try {
// 获取 JAR 内的证书文件流
InputStream inputStream = KafkaZiFiClient.class.getClassLoader().getResourceAsStream("certificate/client.truststore.jks");
if (inputStream == null) {
throw new RuntimeException("Certificate file not found!");
}
// 创建临时文件
File tempFile = Files.createTempFile("client.truststore", ".jks").toFile();
tempFile.deleteOnExit(); // JVM 退出时自动删除
// 将证书文件流写入临时文件
try (FileOutputStream outputStream = new FileOutputStream(tempFile)) {
byte[] buffer = new byte[1024]; // 缓冲区
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}
// 返回临时文件的绝对路径
logger.info("truststore path:{}", tempFile.getAbsolutePath());
return tempFile.getAbsolutePath();
} catch (Exception e) {
throw new RuntimeException("Failed to extract certificate file", e);
}
}
/**
* 订阅KAFKA v1版本接口数据v1版本接口需要使用topic来区分
*
* @deprecated 该方法订阅不到V2版本的接口若要订阅v2版本接口请使用 {@link #subscribe()}
*/
@Deprecated
@Override
public void subscribe(String topic) {
consumer.subscribe(Pattern.compile(".*-v1-" + topic));
}
@Override
public void subscribe() {
consumer.subscribe(TOPIC_PATTERN_V2);
}
@Override
public Collection<Message> poll() {
Collection<Message> messages = new ArrayList<Message>();
ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<String, String> record : records) {
messages.add(new KafkaMessage(record));
}
return messages;
}
@Override
public void commit() {
consumer.commitSync();
}
}

38
src/main/java/com/techsor/datacenter/receiver/config/kafka/model/Message.java

@ -0,0 +1,38 @@
package com.techsor.datacenter.receiver.config.kafka.model;
import java.util.Map;
public class Message {
private String body;
private Map<String,String> headers;
private String messageId;
public String getMessageId() {
return messageId;
}
public void setMessageId(String messageId) {
this.messageId = messageId;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public Map<String, String> getHeaders() {
return headers;
}
public void setHeaders(Map<String, String> headers) {
this.headers = headers;
}
}

10
src/main/java/com/techsor/datacenter/receiver/constants/CodeConstants.java

@ -0,0 +1,10 @@
package com.techsor.datacenter.receiver.constants;
public class CodeConstants {
public static int CODE_SUCCESS=200;
public static int CODE_SERVER_ERROR=500;
public static int CODE_WRONG_VERIFYCODE=601;
public static int CODE_USER_NOT_REGISTERED=602;
}

11
src/main/java/com/techsor/datacenter/receiver/constants/CompanyConstants.java

@ -0,0 +1,11 @@
package com.techsor.datacenter.receiver.constants;
public class CompanyConstants {
public final static String ZIFISENSE="zifisense";
public final static String NBI="nbi";
public final static String OVIPHONE="oviphone";
public final static String NITTAN="nittan";
public final static String OCR="ocr";
public final static String DELTA="delta";
public final static String METCOM="metcom";
}

19
src/main/java/com/techsor/datacenter/receiver/constants/MsgConstants.java

@ -0,0 +1,19 @@
package com.techsor.datacenter.receiver.constants;
public class MsgConstants {
public static String MSG_SERVER_ERROR="服务器问题,请联系管理员";
public static String MSG_WRONG_VERIFYCODE="验证码错误";
public static String MSG_USER_NOT_REGISTERED="用户未注册,请注册";
public static String REDIS_COMMAND_NOTIFICATION_TYPE="notification";
public static String REIDS_COMMAND_SWITCH_TYPE="switch";
public static final String SWITCH_STATUS_PREFIX="switch:stats:status";
public static final String REDIS_COMMAND_STAT_EVENT="startStat";
}

7
src/main/java/com/techsor/datacenter/receiver/constants/UrlConstants.java

@ -0,0 +1,7 @@
package com.techsor.datacenter.receiver.constants;
public class UrlConstants {
public static String RECEIVER_URL="http://localhost:8201/v1/main_receiver";
}

43
src/main/java/com/techsor/datacenter/receiver/controller/HealthController.java

@ -0,0 +1,43 @@
package com.techsor.datacenter.receiver.controller;
import com.alibaba.fastjson2.JSON;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
@RestController
public class HealthController {
@GetMapping("/healthcheck")
public String healhealthcheck(){
return "ok";
}
@GetMapping("/health")
public String health(){
RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
long startTime = runtimeMXBean.getStartTime();
Map<String,String> resultMap=new HashMap<>();
resultMap.put("status","UP");
resultMap.put("startUpDate",String.valueOf(startTime));
return JSON.toJSONString(resultMap);
}
@GetMapping("/version")
public String getVersion() throws IOException {
Properties properties = new Properties();
Resource currentResource = new ClassPathResource("git.properties");
properties.load(currentResource.getInputStream());
String version=properties.getProperty("git.commit.id.abbrev");
return version;
}
}

43
src/main/java/com/techsor/datacenter/receiver/controller/NotificationSinkController.java

@ -0,0 +1,43 @@
package com.techsor.datacenter.receiver.controller;
import com.google.common.collect.Maps;
import com.techsor.datacenter.receiver.service.IDataReceiveService;
import org.apache.commons.collections.MapUtils;
import org.springframework.core.task.TaskExecutor;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import java.util.List;
import java.util.Map;
/**
* 通知接收用于触发接收本地MQTTSink的数据
* **/
@RequestMapping("/notification")
@RestController
public class NotificationSinkController {
@Resource
private IDataReceiveService dataReceiveService;
@Resource(name="threadPoolTaskExecutor")
private TaskExecutor threadPoolTaskExecutor;
/**
* 给lambda提供接收通知接口用于触发数据来源监听
* */
@PostMapping("/receive")
public Object receiveNotification(@RequestParam(name="state") String state,
@RequestBody List<Long> params){
this.threadPoolTaskExecutor.execute(() -> dataReceiveService.receiveCurrentDataSrc(state,params));
Map resultMap=Maps.newHashMap();
resultMap.put("result",state);
return resultMap;
}
}

32
src/main/java/com/techsor/datacenter/receiver/controller/ReceiverController.java

@ -0,0 +1,32 @@
package com.techsor.datacenter.receiver.controller;
import com.google.gson.Gson;
import com.techsor.datacenter.receiver.service.DataTransService;
import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
@RequestMapping("/api/generic")
@RestController
public class ReceiverController {
@Resource
private DataTransService dataTransService;
//TODO
@PostMapping("/process")
public Object process(@RequestParam("MyDeviceId")String deviceId,@RequestBody(required = false) Object params){
//TODO
Gson gson=new Gson();
String json=gson.toJson(params);
this.dataTransService.transferData(deviceId,json);
Map<String,String> resultMap=new HashMap<>();
resultMap.put("code","0");
resultMap.put("msg","success");
return resultMap;
}
}

25
src/main/java/com/techsor/datacenter/receiver/entity/common/BaseTransDataEntity.java

@ -0,0 +1,25 @@
package com.techsor.datacenter.receiver.entity.common;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAutoGeneratedKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable;
import lombok.Data;
import java.util.UUID;
@Data
public class BaseTransDataEntity {
@DynamoDBHashKey
@DynamoDBAutoGeneratedKey()
private UUID hashId;
private Integer id;
private String content;
private String ts;
private String company; //zifisense:纵行, nbi:农博, oviphone:oviphone
private String dateKey; //日期,格式:yyyy-MM-dd
}

15
src/main/java/com/techsor/datacenter/receiver/entity/common/CommonTransDataEntity.java

@ -0,0 +1,15 @@
package com.techsor.datacenter.receiver.entity.common;
import lombok.Data;
@Data
public class CommonTransDataEntity {
private Integer id;
private String content;
private String ts;
private String dataSrcCode; //数据源编码
}

57
src/main/java/com/techsor/datacenter/receiver/entity/common/JsonResponse.java

@ -0,0 +1,57 @@
package com.techsor.datacenter.receiver.entity.common;
public class JsonResponse {
private int code;
private Object data;
private String msg;
public JsonResponse() {
}
public JsonResponse(int code, Object data) {
this.code = code;
this.data = data;
}
public JsonResponse(int code, Object data, String msg) {
this.code = code;
this.data = data;
this.msg = msg;
}
public static JsonResponse buildSuccess(Object data) {
return new JsonResponse(200, data);
}
public static JsonResponse buildError(String msg) {
return new JsonResponse(400, "", msg);
}
public static JsonResponse buildError(int code, String msg) {
return new JsonResponse(code, "", msg);
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}

16
src/main/java/com/techsor/datacenter/receiver/entity/common/KafkaClientConfig.java

@ -0,0 +1,16 @@
package com.techsor.datacenter.receiver.entity.common;
import lombok.Data;
@Data
public class KafkaClientConfig {
private String host;
private String apiKey;
private String apiSecret;
private String companyCode;
}

37
src/main/java/com/techsor/datacenter/receiver/entity/common/KafkaZetaMessage.java

@ -0,0 +1,37 @@
package com.techsor.datacenter.receiver.entity.common;
import lombok.Data;
import java.util.Map;
@Data
public class KafkaZetaMessage {
private Payload payload;
private Source source;
@lombok.Data
public static class Payload {
private Data data;
private String identify;
}
@lombok.Data
public static class Data {
private long upTime;
private long apTime;
private String parsedData; // JSON string, can be parsed into ParsedData object
private String apUid;
private String rawData;
private String msUid;
}
@lombok.Data
public static class Source {
private long createTime;
private long pushTime;
private String topicName;
}
}

37
src/main/java/com/techsor/datacenter/receiver/entity/common/MqttClientConfig.java

@ -0,0 +1,37 @@
package com.techsor.datacenter.receiver.entity.common;
import lombok.Data;
import java.util.List;
@Data
public class MqttClientConfig {
private String url;
private String clientId;
private String username;
private String password;
private String topic;
private boolean sslState;
private Integer connectionTimeout;
private String description;
//1
private String caPath;
//2
private String clientCrtPath;
//3
private String clientKeyPath;
private Integer Qos;
}

14
src/main/java/com/techsor/datacenter/receiver/entity/common/MqttPublisherEntity.java

@ -0,0 +1,14 @@
package com.techsor.datacenter.receiver.entity.common;
import lombok.Data;
import org.springframework.context.annotation.Bean;
@Data
public class MqttPublisherEntity {
private Integer id;
private String host;
private String username;
private String password;
private String topic;
private String description;
}

9
src/main/java/com/techsor/datacenter/receiver/entity/common/MqttStartStatusEntity.java

@ -0,0 +1,9 @@
package com.techsor.datacenter.receiver.entity.common;
import lombok.Data;
@Data
public class MqttStartStatusEntity {
private String HOST;
private String status;
}

12
src/main/java/com/techsor/datacenter/receiver/entity/common/ResponseEntity.java

@ -0,0 +1,12 @@
package com.techsor.datacenter.receiver.entity.common;
import lombok.Data;
import java.util.List;
@Data
public class ResponseEntity {
private int code;
private String msg;
private List<Object> data;
}

15
src/main/java/com/techsor/datacenter/receiver/entity/common/ZAIotTransDataEntity.java

@ -0,0 +1,15 @@
package com.techsor.datacenter.receiver.entity.common;
import lombok.Data;
@Data
public class ZAIotTransDataEntity {
private String content;
private String ts;
private String deviceId;
private String identify;
}

33
src/main/java/com/techsor/datacenter/receiver/entity/company/CompanyEntity.java

@ -0,0 +1,33 @@
package com.techsor.datacenter.receiver.entity.company;
import lombok.Data;
/**
* create table basic_company
* (
* id bigint auto_increment
* primary key,
* parent_id bigint null comment '父企业ID',
* company_name varchar(500) charset utf8mb4 null,
* flag int default 0 null comment '0-正常1-删除',
* create_time bigint null,
* creator_id bigint null,
* modify_time bigint null,
* modifier_id bigint null
* );
*
* **/
@Data
public class CompanyEntity {
private Long id;
private Long parentId;
private String companyName;
private Integer flag;
}

46
src/main/java/com/techsor/datacenter/receiver/entity/datasource/DatasourceConfigEntity.java

@ -0,0 +1,46 @@
package com.techsor.datacenter.receiver.entity.datasource;
import lombok.Data;
/**
* create table data_src_config
* (
* id bigint auto_increment
* primary key,
* code varchar(100) null comment '数据来源识别代码',
* api_key varchar(100) null comment 'api_key',
* name varchar(100) null comment '数据来源名称',
* method_type varchar(2) null comment '来源方式(0:MQTT;1:RESTFULL)',
* params varchar(1000) null comment '链接参数',
* state varchar(2) null comment '状态;(0:激活1:冻结)',
* created_by bigint null,
* created_timestamp timestamp null,
* updated_by bigint null,
* updated_timestamp timestamp null,
* company_id bigint not null
* )
* comment '数据来源配置表';
* */
@Data
public class DatasourceConfigEntity {
private Long id;
private String code;
private String apiKey;
private String name;
private String methodType;
private String params;
private String state;
private Long companyId;
private String deviceIdPosition;
}

12
src/main/java/com/techsor/datacenter/receiver/entity/datasource/RestfulParams.java

@ -0,0 +1,12 @@
package com.techsor.datacenter.receiver.entity.datasource;
import lombok.Data;
@Data
public class RestfulParams {
private String url;
private Object params;
}

23
src/main/java/com/techsor/datacenter/receiver/entity/dto/RedisCommandReceiverDTO.java

@ -0,0 +1,23 @@
package com.techsor.datacenter.receiver.entity.dto;
import lombok.Data;
import java.util.List;
/****
* 开关commandType为类型
* commandType=='notification',则是通知处理mqtt相关信息
* commandType=='switch',则是通知处理redis开关则value为on,off
* ***/
@Data
public class RedisCommandReceiverDTO {
private String commandType;
private String value;
private String state;
private List<Long> params;
}

24
src/main/java/com/techsor/datacenter/receiver/entity/metcom/MetcomEntity.java

@ -0,0 +1,24 @@
package com.techsor.datacenter.receiver.entity.metcom;
import lombok.Data;
@Data
//{
// “measured” : [計測時刻 (unix timestamp)],
// “spaceId” : “[DBM空間コード]”,
// “latitude” : [緯度(deg)],
// “longitude” : [経度(deg)],
// “floor” : [階数],
// “hae” : [楕円体高(m)],
// “hat” : [地上高(m)]
//}
public class MetcomEntity {
private String uuid;
private Long measured;
private String spaceId;
private double latitude;
private double longitude;
private int floor;
private float hae;
private float hat;
}

13
src/main/java/com/techsor/datacenter/receiver/entity/nittan/AuthEntity.java

@ -0,0 +1,13 @@
package com.techsor.datacenter.receiver.entity.nittan;
import lombok.Data;
@Data
public class AuthEntity{
private String subscription_id;
private String signature;
private String code;
private String version;
private Integer timestamp;
}

9
src/main/java/com/techsor/datacenter/receiver/entity/nittan/DeviceInfoEntity.java

@ -0,0 +1,9 @@
package com.techsor.datacenter.receiver.entity.nittan;
import lombok.Data;
@Data
public class DeviceInfoEntity{
private String device_name;
private String device_class;
}

10
src/main/java/com/techsor/datacenter/receiver/entity/nittan/FacilityInfoEntity.java

@ -0,0 +1,10 @@
package com.techsor.datacenter.receiver.entity.nittan;
import lombok.Data;
@Data
public class FacilityInfoEntity{
private String facility_id;
private String facility_maker;
private String facility_mode;
}

8
src/main/java/com/techsor/datacenter/receiver/entity/nittan/LocationInfoEntity.java

@ -0,0 +1,8 @@
package com.techsor.datacenter.receiver.entity.nittan;
import lombok.Data;
@Data
public class LocationInfoEntity{
private String location_address;
}

20
src/main/java/com/techsor/datacenter/receiver/entity/nittan/NittanEntity.java

@ -0,0 +1,20 @@
package com.techsor.datacenter.receiver.entity.nittan;
import lombok.Data;
import java.util.List;
@Data
public class NittanEntity {
private AuthEntity auth;
private String cmd;
private FacilityInfoEntity facility_info;
private List<NoticeInfoEntity> notice_info;
}

12
src/main/java/com/techsor/datacenter/receiver/entity/nittan/NoticeInfoEntity.java

@ -0,0 +1,12 @@
package com.techsor.datacenter.receiver.entity.nittan;
import lombok.Data;
@Data
public class NoticeInfoEntity {
private String notice_type;
private String notice_level;
private String notice_status;
private LocationInfoEntity location_info;
private DeviceInfoEntity device_info;
}

113
src/main/java/com/techsor/datacenter/receiver/listener/DataSourceConfigListener.java

@ -0,0 +1,113 @@
package com.techsor.datacenter.receiver.listener;
import com.google.gson.Gson;
import com.techsor.datacenter.receiver.config.datasource.DataSourceContextHolder;
import com.techsor.datacenter.receiver.entity.common.KafkaClientConfig;
import com.techsor.datacenter.receiver.entity.common.MqttClientConfig;
import com.techsor.datacenter.receiver.entity.company.CompanyEntity;
import com.techsor.datacenter.receiver.entity.datasource.DatasourceConfigEntity;
import com.techsor.datacenter.receiver.service.GlobalStateService;
import com.techsor.datacenter.receiver.service.IDataSourceConfigService;
import com.techsor.datacenter.receiver.service.IMQTTService;
import com.techsor.datacenter.receiver.service.ZetaKafkaService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Component
public class DataSourceConfigListener implements ApplicationListener<ApplicationStartedEvent> {
private static final Logger logger= LoggerFactory.getLogger(DataSourceConfigListener.class);
@Resource
private GlobalStateService globalStateService;
@Resource
private IMQTTService mqttService;
@Resource
private IDataSourceConfigService dataSourceConfigService;
@Resource
private ZetaKafkaService zetaKafkaService;
@Value("${base.companyId}")
private Integer baseComanyId;
/**
* 应用程序启动事件监听器此方法在应用程序启动完成后被自动调用用于根据数据库中的数据源配置来启动或停止数据接收客户端
*
* @param event 应用程序启动事件
*/
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
if (!(event instanceof ApplicationStartedEvent)){
return;
}
// Clearing data source to use the default one.
DataSourceContextHolder.clearCurrentDataSourceKey();
//Get companyId and parentId
List<CompanyEntity> companyEntityList=this.dataSourceConfigService.getRelatedTopCompany(baseComanyId.toString());
List<Long> companyIdList = new ArrayList<>();
for (CompanyEntity companyItem : companyEntityList){
companyIdList.add(companyItem.getId());
if (companyItem.getParentId()!=-1){
companyIdList.add(companyItem.getParentId());
}
}
DataSourceContextHolder.clearCurrentDataSourceKey();
companyIdList.forEach(iter-> {
logger.info("Not Error, debug Log:dataSourceForCompany" + iter);
DataSourceContextHolder.setCurrentDataSourceKey("dataSourceForCompany_" + iter);
List<DatasourceConfigEntity> resultList = this.dataSourceConfigService.getDataSourceConfigWithState();
logger.info("All datasource:"+new Gson().toJson(resultList));
for (int i = 0; i < resultList.size(); i++) {
DatasourceConfigEntity item = resultList.get(i);
// 检查数据源的状态,如果状态为"0",表示需要启动该数据源。
if (StringUtils.equals("0", item.getState())) {
//判断类型,MQTT
if (StringUtils.equals("0", item.getMethodType())) {
//mqtt
Gson gson = new Gson();
MqttClientConfig mqttClientConfig = gson.fromJson(item.getParams(), MqttClientConfig.class);
this.mqttService.addMQTTConsumerClient(iter,item.getId(), mqttClientConfig, item);
} else if (StringUtils.equals("1",item.getMethodType())) {
// 对于HTTP类型,将数据源配置添加到全局状态服务中管理。
this.globalStateService.addDatasourceConfig(item);
} else if (StringUtils.equals("2",item.getMethodType())) {
//kafka
Gson gson=new Gson();
KafkaClientConfig kafkaClientConfig = gson.fromJson(item.getParams(), KafkaClientConfig.class);
this.zetaKafkaService.addKafkaClient(iter, item.getId(), kafkaClientConfig, item);
}
} else {
if (StringUtils.equals("0", item.getMethodType())) {
//mqtt
this.mqttService.removeMQTTConsumerClient(item.getId());
} else {
this.globalStateService.removeDatasourceConfig(item);
}
}
}
DataSourceContextHolder.clearCurrentDataSourceKey();
});
}
}

31
src/main/java/com/techsor/datacenter/receiver/listener/DeltaMQTTListener.java

@ -0,0 +1,31 @@
package com.techsor.datacenter.receiver.listener;
import com.techsor.datacenter.receiver.clients.DeltaClientMQTTS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
@Component
public class DeltaMQTTListener implements ApplicationListener<ApplicationStartedEvent> {
private static final Logger logger= LoggerFactory.getLogger(MqttPublisherListener.class);
@Resource
private DeltaClientMQTTS deltaClientMQTT;
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
if (!(event instanceof ApplicationStartedEvent)){
return;
}
try {
deltaClientMQTT.start();
} catch (Exception e) {
logger.error("DeltaClientMQTTS runtime exception",e);
// throw new RuntimeException(e);
}
}
}

63
src/main/java/com/techsor/datacenter/receiver/listener/DynamoDBListener.java

@ -0,0 +1,63 @@
package com.techsor.datacenter.receiver.listener;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBQueryExpression;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.QueryRequest;
import com.amazonaws.services.dynamodbv2.util.TableUtils;
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.socialsignin.spring.data.dynamodb.core.DynamoDBTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
import java.util.HashMap;
//@Component
public class DynamoDBListener implements ApplicationListener<ApplicationStartedEvent> {
private static final Logger logger= LoggerFactory.getLogger(DynamoDBListener.class);
@Resource
AmazonDynamoDB amazonDynamoDB;
@Resource
DynamoDBMapper dynamoDBMapper;
@Value("${amazon.dynamodb.tableName:mqtt_history}")
private String dynamoDBTableName;
/***
* 生成创建表的请求这里使用DynamoDBMapper的generateCreateTableRequest方法
* 为BaseTransDataEntity类生成创建表的请求同时指定读写吞吐量
* 等待表变为活动状态这是为了确保表已经完全创建并可以使用
* */
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
if (!(event instanceof ApplicationStartedEvent)){
return;
}
logger.info("DynamoDBListner started successfully!!!");
// 生成创建表的请求。这里使用DynamoDBMapper的generateCreateTableRequest方法
// 为BaseTransDataEntity类生成创建表的请求,同时指定读写吞吐量。
CreateTableRequest ctr = dynamoDBMapper.generateCreateTableRequest(BaseTransDataEntity.class)
.withProvisionedThroughput(new ProvisionedThroughput(1L, 1L));
ctr.setTableName(dynamoDBTableName);
TableUtils.createTableIfNotExists(amazonDynamoDB, ctr);
try {
// 等待表变为活动状态。这是为了确保表已经完全创建并可以使用。
TableUtils.waitUntilActive(amazonDynamoDB, ctr.getTableName());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
logger.info("DynamoDBListener createTableIfNotExists successfully!!!");
logger.info("DynamoDBListener save successfully!!!");
}
}

60
src/main/java/com/techsor/datacenter/receiver/listener/MqttPublisherListener.java

@ -0,0 +1,60 @@
package com.techsor.datacenter.receiver.listener;
import com.techsor.datacenter.receiver.clients.ITAClientMQTT;
import com.techsor.datacenter.receiver.entity.common.MqttPublisherEntity;
import com.techsor.datacenter.receiver.entity.common.MqttStartStatusEntity;
import com.techsor.datacenter.receiver.service.MqttPublisherService;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
import java.util.List;
import java.util.Random;
//@Component
public class MqttPublisherListener implements ApplicationListener<ApplicationStartedEvent> {
private static final Logger logger=LoggerFactory.getLogger(MqttPublisherListener.class);
@Resource
private MqttPublisherService mqttPublisherService;
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
if (!(event instanceof ApplicationStartedEvent)){
return;
}
List publisherList = mqttPublisherService.getList();
for (int i=0;i<publisherList.size();i++){
ITAClientMQTT clientMQTT = new ITAClientMQTT((MqttPublisherEntity) publisherList.get(i),getRandoms()+"");
MqttStartStatusEntity statusItem = new MqttStartStatusEntity();
statusItem.setHOST(((MqttPublisherEntity) publisherList.get(i)).getHost());
try {
clientMQTT.start();
statusItem.setStatus("Success");
}catch (MqttException e) {
logger.error("Failed,please check log. {}",e);
statusItem.setStatus("Failed,please check log.");
}
}
}
public int getRandoms(){
// 创建一个Random对象
Random random = new Random();
// 生成一个范围在100到999之间的随机数(包括100,但不包括1000)
int randomNumber = random.nextInt(900) + 100;
return randomNumber;
}
}

71
src/main/java/com/techsor/datacenter/receiver/listener/RedisNotificationMessageSubscriber.java

@ -0,0 +1,71 @@
package com.techsor.datacenter.receiver.listener;
import com.alibaba.fastjson2.JSON;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.techsor.datacenter.receiver.constants.MsgConstants;
import com.techsor.datacenter.receiver.entity.dto.RedisCommandReceiverDTO;
import com.techsor.datacenter.receiver.service.GlobalSwitchStatusComponent;
import com.techsor.datacenter.receiver.service.GuavaRedisCache;
import com.techsor.datacenter.receiver.service.IDataReceiveService;
import com.techsor.datacenter.receiver.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.springframework.core.task.TaskExecutor;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
import java.util.Objects;
@Slf4j
@Component
public class RedisNotificationMessageSubscriber implements MessageListener {
@Resource
private IDataReceiveService dataReceiveService;
@Resource
private GlobalSwitchStatusComponent globalSwitchStatusComponent;
@Resource(name="threadPoolTaskExecutor")
private TaskExecutor threadPoolTaskExecutor;
@Resource
private GuavaRedisCache guavaRedisCache;
@Override
public void onMessage(Message message, byte[] pattern) {
String commandMessage = new String(message.getBody());
if (StringUtils.isEmpty(commandMessage)){
log.warn("Empty message received.");
return;
}
log.info("Message received: {}" , commandMessage);
commandMessage = commandMessage.substring(1, commandMessage.length() - 1);
commandMessage=StringEscapeUtils.unescapeJson(commandMessage);
RedisCommandReceiverDTO redisCommandReceiverDTO=JSON.parseObject(commandMessage, RedisCommandReceiverDTO.class);
if (redisCommandReceiverDTO==null){
log.warn("Failed to parse message: {}",commandMessage);
return;
}
if (StringUtils.equals(redisCommandReceiverDTO.getCommandType(), MsgConstants.REDIS_COMMAND_NOTIFICATION_TYPE)){
this.threadPoolTaskExecutor.execute(() -> dataReceiveService.receiveCurrentDataSrc(redisCommandReceiverDTO.getState(),redisCommandReceiverDTO.getParams()));
}else{
//redis统计事件,每隔5分钟会被触发
log.warn("redisCommandReceiverDTO.getCommandType():"+redisCommandReceiverDTO.getCommandType());
log.warn("MsgConstants.REDIS_COMMAND_STAT_EVENT:"+MsgConstants.REDIS_COMMAND_STAT_EVENT);
if (StringUtils.equalsIgnoreCase(redisCommandReceiverDTO.getCommandType(), MsgConstants.REDIS_COMMAND_STAT_EVENT)) {
this.guavaRedisCache.syncToRedis();
}else{
if (StringUtils.equals(redisCommandReceiverDTO.getCommandType(), MsgConstants.REIDS_COMMAND_SWITCH_TYPE)){
String value=redisCommandReceiverDTO.getValue();
this.globalSwitchStatusComponent.updateSwitchStatus(Objects.equals(value, "on"));
}else{
log.warn("Unknown command type: {}",redisCommandReceiverDTO.getCommandType());
}
}
}
}
}

33
src/main/java/com/techsor/datacenter/receiver/listener/RedisStatsSwitchListener.java

@ -0,0 +1,33 @@
package com.techsor.datacenter.receiver.listener;
import com.techsor.datacenter.receiver.constants.MsgConstants;
import com.techsor.datacenter.receiver.service.GlobalSwitchStatusComponent;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
import java.util.Objects;
@Component
public class RedisStatsSwitchListener implements ApplicationListener<ApplicationStartedEvent> {
@Resource
private RedisTemplate<String,Object> redisTemplate;
@Resource
private GlobalSwitchStatusComponent globalSwitchStatusComponent;
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
if (!(event instanceof ApplicationStartedEvent)){
return;
}
Object switchStatus = redisTemplate.opsForValue().get(MsgConstants.SWITCH_STATUS_PREFIX);
if (Objects.nonNull(switchStatus)){
this.globalSwitchStatusComponent.updateSwitchStatus(Boolean.parseBoolean(String.valueOf(switchStatus)));
}
}
}

141
src/main/java/com/techsor/datacenter/receiver/service/DataTransService.java

@ -0,0 +1,141 @@
package com.techsor.datacenter.receiver.service;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.techsor.datacenter.receiver.config.DataCenterEnvConfig;
import com.techsor.datacenter.receiver.constants.CompanyConstants;
import com.techsor.datacenter.receiver.constants.UrlConstants;
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity;
import com.techsor.datacenter.receiver.entity.common.CommonTransDataEntity;
import com.techsor.datacenter.receiver.entity.common.ZAIotTransDataEntity;
import com.techsor.datacenter.receiver.utils.DefaultHttpRequestUtil;
import com.techsor.datacenter.receiver.utils.MyHTTPResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import jakarta.annotation.Resource;
@Slf4j
@Service
public class DataTransService {
private static final Logger logger= LoggerFactory.getLogger(DataTransService.class);
@Resource
private DefaultHttpRequestUtil defaultHttpRequestUtil;
@Autowired
private RedisTemplate redisTemplate;
@Resource
private DataCenterEnvConfig dataCenterEnvConfig;
public void transferData(String userId,String companyName,String rawJson){
logger.warn("Start Process:{},",rawJson);
BaseTransDataEntity baseTransDataEntity = new BaseTransDataEntity();
baseTransDataEntity.setCompany(companyName);
baseTransDataEntity.setTs(System.currentTimeMillis()+"");
baseTransDataEntity.setContent(rawJson);
Gson gson = new Gson();
String jsonParams = gson.toJson(baseTransDataEntity);
if(StringUtils.isEmpty(userId)){
logger.debug("Send Data :{} ,To: {}", jsonParams,dataCenterEnvConfig.getReceiveUrl());
}else{
logger.debug("Send Data :{} by:{},To: {}", jsonParams,userId,dataCenterEnvConfig.getReceiveUrl());
}
this.defaultHttpRequestUtil.postJson(dataCenterEnvConfig.getReceiveUrl(),jsonParams);
}
@Resource
private DuplicateDataProcessor duplicateDataProcessor;
public MyHTTPResponse transferData(String srcCode,String rawJson){
String redisKey = Objects.toString(srcCode, "") + Objects.toString(rawJson, "");
boolean redisResp = redisTemplate.opsForValue().setIfAbsent(redisKey, System.currentTimeMillis(), 60, TimeUnit.SECONDS);
MyHTTPResponse response=new MyHTTPResponse<>();
if (redisResp) {
CommonTransDataEntity baseTransDataEntity = new CommonTransDataEntity();
baseTransDataEntity.setDataSrcCode(srcCode);
baseTransDataEntity.setTs(System.currentTimeMillis()+"");
baseTransDataEntity.setContent(rawJson);
Gson gson = new Gson();
String jsonParams = gson.toJson(baseTransDataEntity);
try{
if (rawJson.contains("PNs") && rawJson.contains("Objs")){
//单独处理IoServer数据
logger.debug("CustomSend Data :{} ,To: {}", jsonParams,dataCenterEnvConfig.getProcessIoserverUrl());
response = this.defaultHttpRequestUtil.postJson(dataCenterEnvConfig.getProcessIoserverUrl(), jsonParams);
}else if (isGW150(rawJson)){
//单独处理ST-150网关数据
logger.debug("CustomSend Data :{} ,To: {}", jsonParams,dataCenterEnvConfig.getProcessIoserverUrl());
response = this.defaultHttpRequestUtil.postJson(dataCenterEnvConfig.getGW150ProcessUrl(), jsonParams);
}else{
logger.debug("CustomSend Data :{} ,To: {}", jsonParams,dataCenterEnvConfig.getProcessApiUrl());
response = this.defaultHttpRequestUtil.postJson(dataCenterEnvConfig.getProcessApiUrl(), jsonParams);
}
}catch (Exception e){
response.setCode(500);
log.error("transferData error:{}",rawJson,e);
}
logger.debug("transferData response:{}",new Gson().toJson(response));
}
return response;
}
public MyHTTPResponse transferDataZaiot(String deviceId, String rawJson, String identify) {
String redisKey = Objects.toString(deviceId, "") + Objects.toString(rawJson, "");
boolean redisResp = redisTemplate.opsForValue().setIfAbsent(redisKey, System.currentTimeMillis(), 60, TimeUnit.SECONDS);
if (redisResp) {
MyHTTPResponse response=new MyHTTPResponse<>();
ZAIotTransDataEntity zAIotTransDataEntity = new ZAIotTransDataEntity();
zAIotTransDataEntity.setDeviceId(deviceId);
zAIotTransDataEntity.setTs(System.currentTimeMillis()+"");
zAIotTransDataEntity.setContent(rawJson);
zAIotTransDataEntity.setIdentify(identify);
Gson gson = new Gson();
String zaiotProcessJsonParams = gson.toJson(zAIotTransDataEntity);
logger.debug("zaiot_process Data :{} ,To: {}", zaiotProcessJsonParams, dataCenterEnvConfig.getZaiotProcessApiUrl());
try{
response = this.defaultHttpRequestUtil.postJson(dataCenterEnvConfig.getZaiotProcessApiUrl(), zaiotProcessJsonParams);
}catch (Exception e){
response.setCode(500);
logger.error("zaiot_process error:{}",zaiotProcessJsonParams,e);
}
return response;
}
return null;
}
/**
* 检查JSON字符串是否包含特定的字段用于判断是否符合GW150数据格式
*
* @param jsonStr 待检查的JSON字符串
* @return 如果JSON字符串同时包含字段"d""ts"则返回true否则返回false
*/
private Boolean isGW150(String jsonStr){
// 解析JSON字符串为JsonObject,以便进行字段检查
JsonObject json = JsonParser.parseString(jsonStr).getAsJsonObject();
// 检查JSON对象中是否包含字段"d"
boolean hasD = json.has("d");
// 检查JSON对象中是否包含字段"ts"
boolean hasTs = json.has("ts");
// 如果同时存在字段"d"和"ts",则认为是GW150数据格式,返回true,否则返回false
return hasD && hasTs;
}
}

84
src/main/java/com/techsor/datacenter/receiver/service/DuplicateDataProcessor.java

@ -0,0 +1,84 @@
package com.techsor.datacenter.receiver.service;
import cn.hutool.crypto.digest.DigestAlgorithm;
import cn.hutool.crypto.digest.DigestUtil;
import com.techsor.datacenter.receiver.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
/**
* 处理数据去重的类使用Redis分布式锁来确保数据的唯一性
*/
@Slf4j
@Service
public class DuplicateDataProcessor {
private final static Logger myLogger = LoggerFactory.getLogger(DuplicateDataProcessor.class);
@Resource
private RedisLockRegistry redisLockRegistry;
@Resource
private RedisUtils redisUtils;
/**
* 移除重复数据
*
* @param content 需要去重的数据内容
* @return 布尔值表示是否成功去除重复数据true表示数据是唯一的false表示数据重复
*/
public boolean removeDuplicateData(String content) {
//获取lockKeyName
String lockKeyName= DigestUtil.digester(DigestAlgorithm.SHA1).digestHex(content);
//此处排除并发下为空的情况
if (StringUtils.isEmpty(lockKeyName)){
return false;
}
//定义返回结果
boolean result=false;
//获取分布式锁,进行去重
Lock lock=this.redisLockRegistry.obtain("receiver_"+lockKeyName);
try{
if (lock.tryLock(10, TimeUnit.SECONDS)){
log.debug("get lock success");
//有数据
if (this.redisUtils.hasKey("receiver_"+lockKeyName)){
result=false;
}else{
//没有数据,则写入redis
result=true;
this.redisUtils.add("receiver_"+lockKeyName,content,3600L,TimeUnit.SECONDS);
log.debug("add data to redis success,lockKeyName:{},content:{}",lockKeyName,content);
}
}else{
log.debug("get lock failed {}",content);
return false;
}
}catch (InterruptedException e){
// myLogger.error("an exception caught here :{}",e.getMessage(),e);
result=false;
}finally {
try{
lock.unlock();
}catch (Exception e){
// myLogger.error("an exception caught here :{}",e.getMessage(),e);
}
}
return result;
}
}

37
src/main/java/com/techsor/datacenter/receiver/service/GlobalStateService.java

@ -0,0 +1,37 @@
package com.techsor.datacenter.receiver.service;
import com.google.gson.Gson;
import com.techsor.datacenter.receiver.entity.datasource.DatasourceConfigEntity;
import com.techsor.datacenter.receiver.entity.datasource.RestfulParams;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Service
public class GlobalStateService {
private Map<String, DatasourceConfigEntity> datasourceConfigMap = new ConcurrentHashMap<>();
public void addDatasourceConfig(DatasourceConfigEntity datasourceConfigEntity) {
String params= datasourceConfigEntity.getParams();
Gson gson = new Gson();
RestfulParams restfulParams=gson.fromJson(params, RestfulParams.class);
datasourceConfigMap.put(restfulParams.getUrl(), datasourceConfigEntity);
}
public DatasourceConfigEntity getDatasourceConfig(String url){
return this.datasourceConfigMap.get(url);
}
public boolean checkUrlExist(String url){
return this.datasourceConfigMap.containsKey(url);
}
public void removeDatasourceConfig(DatasourceConfigEntity datasourceConfigEntity) {
String params= datasourceConfigEntity.getParams();
Gson gson = new Gson();
RestfulParams restfulParams=gson.fromJson(params, RestfulParams.class);
datasourceConfigMap.remove(restfulParams.getUrl());
}
}

27
src/main/java/com/techsor/datacenter/receiver/service/GlobalSwitchStatusComponent.java

@ -0,0 +1,27 @@
package com.techsor.datacenter.receiver.service;
import org.springframework.stereotype.Component;
import jakarta.annotation.PostConstruct;
import java.util.concurrent.atomic.AtomicBoolean;
@Component
public class GlobalSwitchStatusComponent {
private AtomicBoolean switchStatus;
@PostConstruct
public void init(){
this.switchStatus=new AtomicBoolean(false);
}
public void updateSwitchStatus(boolean switchStatus){
this.switchStatus=new AtomicBoolean(switchStatus);
}
public boolean getSwitchStatus(){
return this.switchStatus.get();
}
}

87
src/main/java/com/techsor/datacenter/receiver/service/GuavaRedisCache.java

@ -0,0 +1,87 @@
package com.techsor.datacenter.receiver.service;
import com.alibaba.fastjson2.JSON;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import jakarta.annotation.PostConstruct;
import java.time.Duration;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import static com.google.common.cache.CacheBuilder.newBuilder;
@Slf4j
@Component
public class GuavaRedisCache {
private final LoadingCache<String, Integer> cache;
private final RedisTemplate<String, Object> redisTemplate;
private final GlobalSwitchStatusComponent globalSwitchStatusComponent;
@Autowired
public GuavaRedisCache(RedisTemplate<String, Object> redisTemplate, GlobalSwitchStatusComponent globalSwitchStatusComponent ) {
this.redisTemplate = redisTemplate;
this.globalSwitchStatusComponent = globalSwitchStatusComponent;
this.cache = CacheBuilder.newBuilder()
.maximumSize(10000)
.expireAfterWrite(7, TimeUnit.MINUTES)
.concurrencyLevel(1000)
.build(new CacheLoader<String,Integer>() {
@Override
public Integer load(String s) throws Exception {
return 0;
}
});
}
public void incrementDailyDeviceIdCount(String deviceId) {
String key = getKeyForToday();
cache.put(key + ":" + deviceId, cache.getUnchecked(key + ":" + deviceId) + 1);
}
public String getKeyForToday() {
LocalDate today = LocalDate.now();
// 设置日本时区
ZoneId japanZone = ZoneId.of("Asia/Tokyo");
// 获取日本时区的当前日期和时间
ZonedDateTime nowInJapan = ZonedDateTime.now(japanZone);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate yesterdayInJapan = nowInJapan.toLocalDate();
return "receiver:device:counts:" + formatter.format(yesterdayInJapan);
}
//由guava同步到redis
public void syncToRedis() {
String requestId =UUID.randomUUID().toString();
MDC.put("requestId", requestId);
log.info("Syncing cache to Redis=============================>");
log.info("Current Cache Size Data {}", cache.size());
log.info("Current Cache Value :{}", JSON.toJSON(cache.asMap()));
cache.asMap().forEach((key, value) -> {
String[] parts = key.split(":");
String redisKey = parts[0] + ":" + parts[1] + ":" + parts[2] + ":" + parts[3];
String deviceId = parts[4];
redisTemplate.opsForHash().increment(redisKey, deviceId, value);
redisTemplate.expire(redisKey, Duration.ofDays(2)); // 设置键2天后过期
});
log.info("Syncing cache to Redis done");
this.cache.invalidateAll();
MDC.clear();
}
}

12
src/main/java/com/techsor/datacenter/receiver/service/IDataReceiveService.java

@ -0,0 +1,12 @@
package com.techsor.datacenter.receiver.service;
import java.util.List;
public interface IDataReceiveService {
/****
* 本方法用于接收aws lambda触发的通知用于触发数据来源监听或者停止监听
* */
public void receiveCurrentDataSrc(String state, List<Long> params);
}

19
src/main/java/com/techsor/datacenter/receiver/service/IDataSourceConfigService.java

@ -0,0 +1,19 @@
package com.techsor.datacenter.receiver.service;
import com.techsor.datacenter.receiver.entity.company.CompanyEntity;
import com.techsor.datacenter.receiver.entity.datasource.DatasourceConfigEntity;
import java.util.List;
public interface IDataSourceConfigService {
public List<DatasourceConfigEntity> getDataSourceConfig(List<Long> datasourceIds) ;
public List<DatasourceConfigEntity> getDataSourceConfigWithState() ;
public List<CompanyEntity> getRelatedTopCompany(String baseCompanyId);
}

14
src/main/java/com/techsor/datacenter/receiver/service/IMQTTService.java

@ -0,0 +1,14 @@
package com.techsor.datacenter.receiver.service;
import com.techsor.datacenter.receiver.entity.common.MqttClientConfig;
import com.techsor.datacenter.receiver.entity.datasource.DatasourceConfigEntity;
public interface IMQTTService {
//增加MQTT客户端
void addMQTTConsumerClient(Long companyId,Long id, MqttClientConfig config, DatasourceConfigEntity datasourceConfigEntity);
//根据ID去除MQTT客户端
public void removeMQTTConsumerClient(Long id);
}

98
src/main/java/com/techsor/datacenter/receiver/service/MQTTCrtService.java

@ -0,0 +1,98 @@
package com.techsor.datacenter.receiver.service;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* 用于处理与MQTT证书相关的服务包括从AWS S3下载证书文件
*/
@Slf4j
@Service
public class MQTTCrtService {
@Value("${amazon.aws.accesskey}")
private String awsAccessKeyId;
@Value("${amazon.aws.secretkey}")
private String awsAccessSecret;
@Value("${amazon.aws.bucket}")
private String awsBucketAdress;
public static final String CERT_FILE_PATH="tokyobuilding-certs/";
/**
* 从AWS S3下载指定路径的文件到本地系统
*
* @param filePath S3中文件的路径
* @return 下载文件的本地路径
*/
public String getFilePath(String filePath) {
if (StringUtils.isEmpty(filePath)) {
return "";
}
String bucket = awsBucketAdress;
// 创建获取对象的请求
GetObjectRequest getObjectRequest = GetObjectRequest.builder()
.bucket(bucket)
.key(CERT_FILE_PATH + filePath)
.build();
String tmpDir = System.getProperty("java.io.tmpdir");
// 下载文件到本地路径
Region region = Region.AP_NORTHEAST_1;
S3Client s3 = S3Client
.builder().region(region)
.credentialsProvider(StaticCredentialsProvider
.create(AwsBasicCredentials.create(awsAccessKeyId, awsAccessSecret)))
.build();
String localPath = tmpDir + File.separator + "certs" + File.separator + System.currentTimeMillis() + File.separator + filePath;
s3.getObject(getObjectRequest, (response, inputStream) -> {
if (response.sdkHttpResponse().isSuccessful()) {
// Handle the response here
Path path = Paths.get(localPath);
if (path.getParent() != null) {
FileUtils.forceMkdir(path.getParent().toFile());
}
try (OutputStream outputStream = FileUtils.openOutputStream(path.toFile())) {
byte[] bytes = new byte[1024];
int len;
while ((len = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, len);
}
} catch (IOException e) {
log.error("下载文件失败", e);
}
} else {
throw new RuntimeException("Failed to get object from AWS S3");
}
return null;
});
return localPath;
}
}

42
src/main/java/com/techsor/datacenter/receiver/service/MqttHistoryDynamoDBService.java

@ -0,0 +1,42 @@
package com.techsor.datacenter.receiver.service;
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity;
import com.techsor.datacenter.receiver.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.socialsignin.spring.data.dynamodb.core.DynamoDBTemplate;
import org.springframework.stereotype.Component;
import jakarta.annotation.Resource;
import java.util.Objects;
//@Component
//@Repository
//@EnableScan
//public interface MqttHistoryDynamoDBService extends DynamoDBCrudRepository<BaseTransDataEntity, UUID> {
//
//}
@Slf4j
@Component
public class MqttHistoryDynamoDBService {
//@Resource
private DynamoDBTemplate dynamoDBTemplate;
@Resource
private DuplicateDataProcessor duplicateDataProcessor;
public void save(BaseTransDataEntity baseTransDataEntity) {
// if (Objects.isNull(baseTransDataEntity)){
// return;
// }
//
// boolean flag=this.duplicateDataProcessor.removeDuplicateData(baseTransDataEntity.getContent());
// log.debug("save data to dynamoDB flag:{},{}",baseTransDataEntity.getContent(),flag);
// if (!flag){
// return;
// }
// baseTransDataEntity.setDateKey(DateUtils.getCurrentDate());
// this.dynamoDBTemplate.save(baseTransDataEntity);
// log.debug("save data to dynamoDB success");
}
}

33
src/main/java/com/techsor/datacenter/receiver/service/MqttHistoryService.java

@ -0,0 +1,33 @@
package com.techsor.datacenter.receiver.service;
import com.techsor.datacenter.receiver.entity.common.BaseTransDataEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
@Service("mqttHistoryService")
public class MqttHistoryService {
private static final Logger logger = LoggerFactory.getLogger(MqttHistoryService.class);
@Resource
private JdbcTemplate jdbcTemplate;
public void insertHistory(BaseTransDataEntity mqttHistoryEntity){
logger.info("insertHistory is disabled now ");
//编写sql语句
String sql = "insert into mqtt_history(content,ts) values(\'"+mqttHistoryEntity.getContent()+"\',\'"+mqttHistoryEntity.getTs()+"\')";
logger.info("Execute SQL: {}",sql);
//调用他的update方法
Integer result = jdbcTemplate.update(sql);
if (result==1){
logger.info("Save succeed.");
}else{
logger.warn("Save failed, content:"+mqttHistoryEntity.getContent());
}
}
}

40
src/main/java/com/techsor/datacenter/receiver/service/MqttPublisherService.java

@ -0,0 +1,40 @@
package com.techsor.datacenter.receiver.service;
import com.techsor.datacenter.receiver.entity.common.MqttPublisherEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
@Service
public class MqttPublisherService {
@Resource
private JdbcTemplate jdbcTemplate ;
public List<MqttPublisherEntity> getList(){
String sql = "SELECT * FROM mqtt_publisher";
List<MqttPublisherEntity> dataList = (List<MqttPublisherEntity>) jdbcTemplate.query(sql, new RowMapper<MqttPublisherEntity>(){
@Override
public MqttPublisherEntity mapRow(ResultSet rs, int rowNum) throws SQLException {
MqttPublisherEntity dataItem = new MqttPublisherEntity();
dataItem.setId(rs.getInt("id"));
dataItem.setHost(rs.getString("host"));
dataItem.setUsername(rs.getString("username"));
dataItem.setPassword(rs.getString("password"));
dataItem.setTopic(rs.getString("topic"));
dataItem.setDescription(rs.getString("description"));
return dataItem;
}
});
return dataList;
}
}

29
src/main/java/com/techsor/datacenter/receiver/service/RestfulService.java

@ -0,0 +1,29 @@
package com.techsor.datacenter.receiver.service;
import org.apache.commons.text.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
@Service
public class RestfulService {
@Resource
private JdbcTemplate jdbcTemplate;
private static final Logger logger = LoggerFactory.getLogger(RestfulService.class);
public void insertHistory(String content,String company) {
content = StringEscapeUtils.escapeJson(content);
String sql = "insert into restful_history (content,company,ts) values (\""+content+"\",\""+company+"\",\""+System.currentTimeMillis()/1000+"\")";
logger.debug("insertHistory : "+sql);
logger.debug("From : "+company);
jdbcTemplate.execute(sql);
}
}

15
src/main/java/com/techsor/datacenter/receiver/service/ZetaKafkaService.java

@ -0,0 +1,15 @@
package com.techsor.datacenter.receiver.service;
import com.techsor.datacenter.receiver.entity.common.KafkaClientConfig;
import com.techsor.datacenter.receiver.entity.datasource.DatasourceConfigEntity;
import org.springframework.stereotype.Service;
@Service
public interface ZetaKafkaService {
void addKafkaClient(Long companyId, Long configId, KafkaClientConfig config, DatasourceConfigEntity datasourceConfigEntity);
public void removeKafkaClient(Long companyId,Long configId);
}

76
src/main/java/com/techsor/datacenter/receiver/service/impl/DataReceiveServiceImpl.java

@ -0,0 +1,76 @@
package com.techsor.datacenter.receiver.service.impl;
import com.google.gson.Gson;
import com.techsor.datacenter.receiver.config.datasource.DataSourceContextHolder;
import com.techsor.datacenter.receiver.entity.common.MqttClientConfig;
import com.techsor.datacenter.receiver.entity.datasource.DatasourceConfigEntity;
import com.techsor.datacenter.receiver.service.GlobalStateService;
import com.techsor.datacenter.receiver.service.IDataReceiveService;
import com.techsor.datacenter.receiver.service.IDataSourceConfigService;
import com.techsor.datacenter.receiver.service.IMQTTService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import java.util.List;
/**
* 数据接收服务实现用于管理数据源的接收状态
*/
@Slf4j
@Service
public class DataReceiveServiceImpl implements IDataReceiveService {
@Resource
private IDataSourceConfigService dataSourceConfigService;
@Resource
private GlobalStateService globalStateService;
@Resource
private IMQTTService mqttService;
@Value("${base.companyId}")
private Long baseComanyId;
/**
* 根据提供的状态和数据源ID列表启动或停止相应的数据接收客户端
*
* @param state 数据源的期望状态"0"表示启动其他值表示停止
* @param params 数据源ID的列表用于指定哪些数据源需要被处理
*/
@Override
public void receiveCurrentDataSrc(String state, List<Long> params) {
DataSourceContextHolder.setCurrentDataSourceKey("dataSourceForCompany_" + baseComanyId);
List<DatasourceConfigEntity> resultList = this.dataSourceConfigService.getDataSourceConfig(params);
for (int i = 0; i < resultList.size(); i++) {
DatasourceConfigEntity item = resultList.get(i);
if (StringUtils.equals("0",state)){
//判断类型,MQTT
if (StringUtils.equals("0",item.getMethodType())) {
//mqtt
Gson gson=new Gson();
MqttClientConfig mqttClientConfig=gson.fromJson(item.getParams(), MqttClientConfig.class);
this.mqttService.addMQTTConsumerClient(baseComanyId,item.getId(),mqttClientConfig,item);
}else{
//http
this.globalStateService.addDatasourceConfig(item);
}
}else{
if (StringUtils.equals("0",item.getMethodType())) {
//mqtt
this.mqttService.removeMQTTConsumerClient(item.getId());
}else{
this.globalStateService.removeDatasourceConfig(item);
}
}
}
}
}

115
src/main/java/com/techsor/datacenter/receiver/service/impl/DataSourceConfigServiceImpl.java

@ -0,0 +1,115 @@
package com.techsor.datacenter.receiver.service.impl;
import com.techsor.datacenter.receiver.entity.company.CompanyEntity;
import com.techsor.datacenter.receiver.entity.datasource.DatasourceConfigEntity;
import com.techsor.datacenter.receiver.service.IDataSourceConfigService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Service
public class DataSourceConfigServiceImpl implements IDataSourceConfigService {
@Resource
private JdbcTemplate jdbcTemplate;
@Resource
private JdbcTemplate dynamicJdbcTemplate;
/**
* create table data_src_config
* (
* id bigint auto_increment
* primary key,
* code varchar(100) null comment '数据来源识别代码',
* api_key varchar(100) null comment 'api_key',
* name varchar(100) null comment '数据来源名称',
* method_type varchar(2) null comment '来源方式(0:MQTT;1:RESTFULL)',
* params varchar(1000) null comment '链接参数',
* state varchar(2) null comment '状态;(0:激活1:冻结)',
* created_by bigint null,
* created_timestamp timestamp null,
* updated_by bigint null,
* updated_timestamp timestamp null,
* company_id bigint not null
* )
* comment '数据来源配置表';
* */
@Override
public List<DatasourceConfigEntity> getDataSourceConfig(List<Long> datasourceIds) {
if (CollectionUtils.isEmpty(datasourceIds)){
return new ArrayList<>();
}
//查询激活后的数据源配置
String sql="select * from data_src_config where id in (%s) ";
StringBuffer sb=new StringBuffer();
datasourceIds.stream().forEach(iter->{
sb.append(iter).append(",");
});
sb.deleteCharAt(sb.length()-1);
sql=String.format(sql,sb.toString());
List<DatasourceConfigEntity> resultList = this.dynamicJdbcTemplate.query(sql,
(rs, rowNum) -> {
DatasourceConfigEntity item = new DatasourceConfigEntity();
item.setId(rs.getLong("id"));
item.setCode(rs.getString("code"));
item.setApiKey(rs.getString("api_key"));
item.setName(rs.getString("name"));
item.setMethodType(rs.getString("method_type"));
item.setParams(rs.getString("params"));
item.setState(rs.getString("state"));
item.setDeviceIdPosition(rs.getString("device_id_position"));
return item;
});
return resultList;
}
@Override
public List<DatasourceConfigEntity> getDataSourceConfigWithState() {
//查询激活后的数据源配置
String sql="select * from data_src_config where state='0' and flag=0 ";
List<DatasourceConfigEntity> resultList = this.dynamicJdbcTemplate.query(sql,
(rs, rowNum) -> {
DatasourceConfigEntity item = new DatasourceConfigEntity();
item.setId(rs.getLong("id"));
item.setCode(rs.getString("code"));
item.setApiKey(rs.getString("api_key"));
item.setName(rs.getString("name"));
item.setMethodType(rs.getString("method_type"));
item.setParams(rs.getString("params"));
item.setState(rs.getString("state"));
item.setDeviceIdPosition(rs.getString("device_id_position"));
return item;
});
return resultList;
}
@Override
public List<CompanyEntity> getRelatedTopCompany(String baseCompanyId) {
String sql="SELECT bcom.id,bcom.parent_id FROM data_center_aeon_admin.basic_company bcom WHERE bcom.id="+baseCompanyId+" and bcom.flag!=1";
List<CompanyEntity> dataList = this.jdbcTemplate.query(sql, (rs, rowNum) -> {
CompanyEntity item = new CompanyEntity();
item.setId(rs.getLong("id"));
item.setParentId(rs.getLong("parent_id"));
return item;
});
return dataList;
}
}

465
src/main/java/com/techsor/datacenter/receiver/service/impl/MQTTServiceImpl.java

@ -0,0 +1,465 @@
package com.techsor.datacenter.receiver.service.impl;
import com.alibaba.fastjson2.JSON;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.jayway.jsonpath.JsonPath;
import com.techsor.datacenter.receiver.entity.common.MqttClientConfig;
import com.techsor.datacenter.receiver.entity.datasource.DatasourceConfigEntity;
import com.techsor.datacenter.receiver.service.DataTransService;
import com.techsor.datacenter.receiver.service.GuavaRedisCache;
import com.techsor.datacenter.receiver.service.IMQTTService;
import com.techsor.datacenter.receiver.service.MQTTCrtService;
import com.techsor.datacenter.receiver.utils.JsonUtils;
import com.techsor.datacenter.receiver.utils.MyHTTPResponse;
import com.techsor.datacenter.receiver.utils.RandomUtils;
import com.techsor.datacenter.receiver.utils.SslUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.AbstractMessageChannel;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.time.Duration;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.*;
/**
* MQTT服务实现类用于管理MQTT消费者客户端的添加和移除以及处理MQTT消息
*/
@Slf4j
@Service
public class MQTTServiceImpl implements IMQTTService {
private MqttConsumerCache consumerCache = new MqttConsumerCache(2000); // Max 1000 consumers in cache
@Resource
private DataTransService dataTransService;
@Value("${mqtt.keepAliveInterval}")
private Integer keepAliveInterval;
@Resource
MQTTCrtService mqttCrtService;
@Resource
private TaskScheduler taskScheduler;
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Resource
private Executor postSenderThreadTaskExecutor;
@Resource
private GuavaRedisCache guavaRedisCache;
/**
* 根据提供的MQTT客户端配置创建MQTT客户端工厂实例
*
* @param config MQTT客户端配置对象
* @return 创建的MQTT客户端工厂实例
* @throws Exception 如果创建过程中发生错误则抛出异常
*/
private MqttPahoClientFactory mqttClientFactory(MqttClientConfig config) throws Exception {
DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
MqttConnectOptions options = new MqttConnectOptions();
options.setServerURIs(new String[]{config.getUrl()});
options.setUserName(config.getUsername());
options.setPassword(config.getPassword().toCharArray());
options.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1);
if(config.isSslState()){
String caCrtFile=config.getCaPath();
String crtFile=config.getClientCrtPath();
String keyFile=config.getClientKeyPath();
String localCaCrtFilePath=this.mqttCrtService.getFilePath(caCrtFile);
String localCrtFile=this.mqttCrtService.getFilePath(crtFile);
String localKeyFile=this.mqttCrtService.getFilePath(keyFile);
options.setSocketFactory(SslUtil.getSocketFactory(localCaCrtFilePath, localCrtFile, localKeyFile, ""));
options.setHttpsHostnameVerificationEnabled(false);
}
if (Objects.nonNull(config.getConnectionTimeout())) {
if (config.getConnectionTimeout() > 0){
options.setConnectionTimeout(config.getConnectionTimeout());
}else {
options.setConnectionTimeout(1000);
}
}
// Set mqtt-heartbeat interval
options.setKeepAliveInterval(this.keepAliveInterval);
options.setAutomaticReconnect(true);
factory.setConnectionOptions(options);
return factory;
}
/**
* 添加一个MQTT消费者客户端到消费者缓存中并启动它
*
* @param id 消费者客户端的唯一标识
* @param config MQTT客户端配置
* @param datasourceConfigEntity 数据源配置实体
*/
@Override
public void addMQTTConsumerClient(Long companyId,Long id, MqttClientConfig config, DatasourceConfigEntity datasourceConfigEntity) {
if (!consumerCache.containsKey(String.valueOf(id))) {
MqttConsumer consumer = null;
try {
if (Objects.isNull(config)){
return;
}
consumer = new MqttConsumer(config, mqttClientFactory(config),this.dataTransService,
this.taskScheduler,datasourceConfigEntity,this.postSenderThreadTaskExecutor,
this.redisTemplate,
this.guavaRedisCache
);
} catch (Exception e) {
// throw new RuntimeException(e);
log.error("addMQTTConsumerClient error:{}",e.getMessage());
return;
}
consumerCache.put(String.valueOf(id), consumer);
consumer.start();
}
}
/**
* 从消费者缓存中移除指定的MQTT消费者客户端并停止它
*
* @param id 要移除的消费者客户端的唯一标识
*/
@Override
public void removeMQTTConsumerClient(Long id) {
String key=String.valueOf(id);
if (this.consumerCache.containsKey(key)){
this.consumerCache.get(key).stop();
this.consumerCache.remove(key);
}
}
}
/**
* MQTT消费者类负责接收MQTT消息并进行处理
*/
@Slf4j
class MqttConsumer {
private MqttPahoMessageDrivenChannelAdapter adapter;
private MqttClientConfig config;
private DatasourceConfigEntity datasourceConfigEntity;
private Executor postSenderThreadTaskExecutor;
private DataTransService dataTransService;
// 使用ConcurrentLinkedQueue代替List来存储需要重试的请求
private final ConcurrentLinkedQueue<Pair<String, String>> retryRequests = new ConcurrentLinkedQueue<>();
private final ScheduledExecutorService scheduleRetryTaskExecutor = Executors.newScheduledThreadPool(1);
private static final int MAX_RETRY_ATTEMPTS = 5;
private final Map<Pair<String, String>, Integer> retryAttempts = new ConcurrentHashMap<>();
private RedisTemplate<String, Object> redisTemplate;
private GuavaRedisCache guavaRedisCache;
/**
* 构造一个新的MQTT消费者实例
* 此构造函数初始化MQTT消费者并设置消息处理逻辑
*
* @param config MQTT客户端配置包含连接信息和客户端特定配置
* @param clientFactory 用于创建MQTT客户端的工厂根据提供的配置生成连接选项
* @param dataTransService 用于数据传输的服务处理接收到的MQTT消息
* @param taskScheduler 任务调度器用于调度异步任务例如消息重传
* @param datasourceConfigEntity 数据源配置实体包含数据处理规则和目标信息
* @param postSenderThreadTaskExecutor 用于执行后台任务的执行器如发送消息到目的地
*/
public MqttConsumer(MqttClientConfig config, MqttPahoClientFactory clientFactory,
DataTransService dataTransService,
TaskScheduler taskScheduler,
DatasourceConfigEntity datasourceConfigEntity,
Executor postSenderThreadTaskExecutor,
RedisTemplate<String, Object> redisTemplate,
GuavaRedisCache guavaRedisCache
) {
this.config = config;
if (StringUtils.isBlank(config.getClientId())) {
config.setClientId(UUID.randomUUID().toString());
}
String clientId = config.getClientId()+ RandomUtils.unique3DigitGenerator()+UUID.randomUUID().toString();
String topics=config.getTopic();
if (StringUtils.contains(topics,",")){
String[] topicArrays=topics.split(",");
this.adapter = new MqttPahoMessageDrivenChannelAdapter(clientId, clientFactory, topicArrays);
}else{
this.adapter = new MqttPahoMessageDrivenChannelAdapter(clientId, clientFactory, config.getTopic());
}
adapter.setCompletionTimeout(5000);
adapter.setRecoveryInterval(5000);
adapter.setConverter(new DefaultPahoMessageConverter());
if (!Objects.nonNull(config.getQos())){
adapter.setQos(1);
}else{
adapter.setQos(config.getQos());
}
this.dataTransService = dataTransService;
this.datasourceConfigEntity=datasourceConfigEntity;
this.postSenderThreadTaskExecutor=postSenderThreadTaskExecutor;
adapter.setTaskScheduler(taskScheduler);
final DataTransService finalDataTransService=dataTransService;
this.redisTemplate=redisTemplate;
this.guavaRedisCache=guavaRedisCache;
adapter.setOutputChannel(new AbstractMessageChannel() {
@Override
protected boolean sendInternal(Message<?> message, long timeout) {
// 在这里处理接收到的消息
log.debug("Received Message:{}", message.getPayload());
if (message.getPayload() == null) {
return true;
}
// 根据配置的设备ID位置,从消息中提取设备ID
String deviceIdPosition = datasourceConfigEntity.getDeviceIdPosition();
//此处做如下操作
if (StringUtils.isEmpty(deviceIdPosition)) {
log.warn("deviceIdPosition is null:==>{}", datasourceConfigEntity);
return true;
}
String[] deviceIdPositionArrays;
if (JsonUtils.isJsonArray(deviceIdPosition)){
deviceIdPositionArrays= JSON.parseArray(deviceIdPosition,String.class).toArray(new String[0]);
}else {
deviceIdPositionArrays=new String[]{deviceIdPosition};
}
//解析出多个设备ID
Gson gson = new Gson();
String payloadStr = message.getPayload() instanceof String
? (String) message.getPayload()
: gson.toJson(message.getPayload());
String trimData = StringUtils.trim(payloadStr);
if (!JsonUtils.isJson(trimData)) {
log.warn("data is not json:==>{}", datasourceConfigEntity, trimData);
return true;
}
if (JsonUtils.isJsonArray(trimData)) {
postSenderThreadTaskExecutor.execute(() -> {
JsonArray resultJsonArrays = gson.fromJson(trimData, JsonArray.class);
for (JsonElement element : resultJsonArrays) {
String currentJsonValue = gson.toJson(element);
//获取最终设备ID位置信息
String finalDevicePosition=extractDevicePosition(currentJsonValue,deviceIdPositionArrays);
String deviceId = JsonPath.read(currentJsonValue, finalDevicePosition);
if (StringUtils.isEmpty(deviceId)) {
log.warn("deviceId is null:==>{}", datasourceConfigEntity);
continue;
}
//计数
guavaRedisCache.incrementDailyDeviceIdCount(deviceId);
MyHTTPResponse response=finalDataTransService.transferData(deviceId, currentJsonValue);
if (response.getCode()!=200){
log.error("transferData error:{}",currentJsonValue);
synchronized (retryRequests){
retryRequests.add(Pair.of(deviceId,currentJsonValue));
}
}
}
});
} else {
if(StringUtils.isEmpty(trimData)){
return true;
}
if (!JsonUtils.isJson(trimData)) {
return true;
}
String deviceId = JsonPath.read(trimData, deviceIdPosition);
if (StringUtils.isEmpty(deviceId)) {
log.warn("deviceId is null:==>{}", datasourceConfigEntity);
return true;
}
guavaRedisCache.incrementDailyDeviceIdCount(deviceId);
MyHTTPResponse response=finalDataTransService.transferData(deviceId, trimData);
if (response.getCode()!=200){
log.error("transferData error:{}",trimData);
synchronized (retryRequests){
retryRequests.add(Pair.of(deviceId,trimData));
}
}
}
return true;
}
});
// 定时任务改为只处理队列的头部请求,避免一次处理整个队列
scheduleRetryTaskExecutor.scheduleWithFixedDelay(() -> {
if (!retryRequests.isEmpty()) {
Pair<String, String> request = retryRequests.poll(); // 获取并移除此队列的头部
if (request != null) {
retryFailedMessage(request);
}
}
}, 0, 5, TimeUnit.SECONDS);
}
private void retryFailedMessage(Pair<String, String> request) {
Integer attempts = retryAttempts.getOrDefault(request, 0);
if (attempts >= MAX_RETRY_ATTEMPTS) {
log.error("Reached max retry attempts, discarding it.");
retryAttempts.remove(request);
} else {
try {
sendAndRetry(request);
} catch (Exception e) {
log.error("Error retrying, request: {}", request, e);
}
}
}
private void sendAndRetry(Pair<String, String> request) {
MyHTTPResponse response = dataTransService.transferData(request.getLeft(), request.getRight());
if (response.getCode() != 200) {
log.error("Transfer data failed, retrying... Request: {}", request);
log.error("Response: {}", new Gson().toJson(response));
Integer attempts = retryAttempts.compute(request, (k, v) -> (v == null) ? 1 : v + 1);
if (attempts < MAX_RETRY_ATTEMPTS) {
retryRequests.offer(request); // 重新加入队列末尾
} else {
log.error("Reached max retry attempts, discarding request: {}", request);
retryAttempts.remove(request);
}
} else {
log.info("Data transferred successfully on retry. Request: {}", request);
retryAttempts.remove(request);
}
}
private String extractDevicePosition(String rootCurrentJsonValue,String[] deviceIdPositionArrays){
String result="";
for (int i = 0; i < deviceIdPositionArrays.length; i++) {
try{
Object value=JsonPath.read(rootCurrentJsonValue,deviceIdPositionArrays[i]);
if (!Objects.isNull(value)){
result = deviceIdPositionArrays[i];
break;
}
}catch (Exception e){
}
}
return result;
}
public MqttClientConfig getConfig() {
return this.config;
}
public String getKeyForToday() {
LocalDate today = LocalDate.now();
// 设置日本时区
ZoneId japanZone = ZoneId.of("Asia/Tokyo");
// 获取日本时区的当前日期和时间
ZonedDateTime nowInJapan = ZonedDateTime.now(japanZone);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// 计算昨天的日期
LocalDate yesterdayInJapan = nowInJapan.toLocalDate();
return "receiver:device:counts:" + formatter.format(yesterdayInJapan);
}
/**
* 启动MQTT消费者客户端开始接收和处理消息
*/
public void start() {
this.adapter.start();
log.info("MqttConsumer start success:{}", this.config);
}
/**
* 停止MQTT消费者客户端停止接收和处理消息
*/
public void stop() {
log.info("MqttConsumer stop success:{}", this.config);
safeDisconnectMqttClient();
}
private void safeDisconnectMqttClient() {
final int maxRetries = 3; // 最大重试次数
int retryCount = 0;
while (true) {
try {
if (this.adapter != null && this.adapter.isRunning()) {
this.adapter.stop(); // 尝试停止适配器
this.adapter.destroy(); // 销毁适配器
log.info("MQTT 客户端成功断开!!!!!!!!");
break; // 成功后退出循环
}
} catch (Exception e) {
log.info("尝试断开 MQTT 客户端时发生错误: " + e.getMessage());
retryCount++;
if (retryCount >= maxRetries) {
log.info("尝试断开 MQTT 客户端失败达到最大次数,停止重试。");
break; // 达到最大重试次数,退出循环
}
try {
Thread.sleep(2000); // 等待2秒后重试
} catch (InterruptedException ie) {
Thread.currentThread().interrupt(); // 保持良好的中断实践
log.info("重试等待被中断。");
break;
}
log.info("重试断开 MQTT 客户端。..............................");
}
}
}
}
/**
* MQTT消费者缓存类用于缓存和管理MQTT消费者客户端实例
* 当缓存达到最大容量时最老的消费者客户端将被自动移除并停止
*/
class MqttConsumerCache extends LinkedHashMap<String, MqttConsumer> {
private final int maxSize;
public MqttConsumerCache(int maxSize) {
super(maxSize + 1, 1.0f, true);
this.maxSize = maxSize;
}
@Override
protected boolean removeEldestEntry(Map.Entry<String, MqttConsumer> eldest) {
boolean shouldRemove = size() > maxSize;
if (shouldRemove) {
MqttConsumer consumer = eldest.getValue();
consumer.stop();
}
return shouldRemove;
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save