commit 30aac270e8380862b5b3b96ec46eb748b6d37901 Author: review512jwy@163.com <“review512jwy@163.com”> Date: Fri Oct 31 11:33:14 2025 +0800 代码同步 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..db3a9fa --- /dev/null +++ b/.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/ diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000..a45eb6b --- /dev/null +++ b/.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(); + } + +} diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000..2cc7d4a Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..ffdc10e --- /dev/null +++ b/.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 diff --git a/.workflow/branch-pipeline.yml b/.workflow/branch-pipeline.yml new file mode 100644 index 0000000..9d2a292 --- /dev/null +++ b/.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: + - .* diff --git a/.workflow/master-pipeline.yml b/.workflow/master-pipeline.yml new file mode 100644 index 0000000..5d926c2 --- /dev/null +++ b/.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 diff --git a/.workflow/pr-pipeline.yml b/.workflow/pr-pipeline.yml new file mode 100644 index 0000000..3f7579d --- /dev/null +++ b/.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 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3fb8452 --- /dev/null +++ b/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 + + + + diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..86b1b81 --- /dev/null +++ b/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 + + diff --git a/TECHSOR_OFFICIAL.pem b/TECHSOR_OFFICIAL.pem new file mode 100644 index 0000000..d9e9076 --- /dev/null +++ b/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----- \ No newline at end of file diff --git a/deploy.bat b/deploy.bat new file mode 100644 index 0000000..e1729fc --- /dev/null +++ b/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 \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..12c842e --- /dev/null +++ b/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 + + diff --git a/mvnw b/mvnw new file mode 100644 index 0000000..a16b543 --- /dev/null +++ b/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 "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..c8d4337 --- /dev/null +++ b/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% diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..4fc48b3 --- /dev/null +++ b/pom.xml @@ -0,0 +1,648 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.2.12 + + + com.techsor + data.center.receiver + 0.0.1-SNAPSHOT + TECHSOR_dataCenter_receiver + + 17 + 381659385655.dkr.ecr.ap-northeast-1.amazonaws.com + 923770123186.dkr.ecr.ap-northeast-1.amazonaws.com + tokyo-build-receiver + 4.2.2.Final + + + + + software.amazon.awssdk + bom + 2.20.113 + pom + import + + + io.netty + netty-buffer + ${netty.version} + + + io.netty + netty-codec + ${netty.version} + + + io.netty + netty-codec-base + ${netty.version} + + + io.netty + netty-codec-compression + ${netty.version} + + + io.netty + netty-codec-dns + ${netty.version} + + + io.netty + netty-codec-haproxy + ${netty.version} + + + io.netty + netty-codec-http + ${netty.version} + + + io.netty + netty-codec-http2 + ${netty.version} + + + io.netty + netty-codec-http3 + ${netty.version} + + + io.netty + netty-codec-memcache + ${netty.version} + + + io.netty + netty-codec-mqtt + ${netty.version} + + + io.netty + netty-codec-redis + ${netty.version} + + + io.netty + netty-codec-smtp + ${netty.version} + + + io.netty + netty-codec-socks + ${netty.version} + + + io.netty + netty-codec-stomp + ${netty.version} + + + io.netty + netty-codec-xml + ${netty.version} + + + io.netty + netty-codec-protobuf + ${netty.version} + + + io.netty + netty-codec-marshalling + ${netty.version} + + + + + io.netty + netty-common + ${netty.version} + + + io.netty + netty-handler + ${netty.version} + + + io.netty + netty-handler-proxy + ${netty.version} + + + io.netty + netty-handler-ssl-ocsp + ${netty.version} + + + + + io.netty + netty-resolver + ${netty.version} + + + io.netty + netty-resolver-dns + ${netty.version} + + + io.netty + netty-resolver-dns-classes-macos + ${netty.version} + + + + io.netty + netty-transport + ${netty.version} + + + io.netty + netty-transport-classes-epoll + ${netty.version} + + + io.netty + netty-transport-classes-kqueue + ${netty.version} + + + io.netty + netty-transport-classes-io_uring + ${netty.version} + + + io.netty + netty-transport-native-unix-common + ${netty.version} + + + + + io.netty + netty-transport-native-epoll + linux-x86_64 + ${netty.version} + + + io.netty + netty-transport-native-epoll + linux-aarch_64 + ${netty.version} + + + io.netty + netty-transport-native-epoll + linux-riscv64 + ${netty.version} + + + + io.netty + netty-transport-native-io_uring + linux-x86_64 + ${netty.version} + + + io.netty + netty-transport-native-io_uring + linux-aarch_64 + ${netty.version} + + + io.netty + netty-transport-native-io_uring + linux-riscv64 + ${netty.version} + + + + io.netty + netty-transport-native-kqueue + osx-x86_64 + ${netty.version} + + + io.netty + netty-transport-native-kqueue + osx-aarch_64 + ${netty.version} + + + + io.netty + netty-resolver-dns-native-macos + osx-x86_64 + ${netty.version} + + + io.netty + netty-resolver-dns-native-macos + osx-aarch_64 + ${netty.version} + + + + io.netty + netty-codec-native-quic + linux-x86_64 + ${netty.version} + + + io.netty + netty-codec-native-quic + linux-aarch_64 + ${netty.version} + + + io.netty + netty-codec-native-quic + osx-x86_64 + ${netty.version} + + + io.netty + netty-codec-native-quic + osx-aarch_64 + ${netty.version} + + + io.netty + netty-codec-native-quic + windows-x86_64 + ${netty.version} + + + + + io.netty + netty-transport-rxtx + ${netty.version} + + + io.netty + netty-transport-sctp + ${netty.version} + + + io.netty + netty-transport-udt + ${netty.version} + + + io.netty + netty-codec-classes-quic + ${netty.version} + + + + + + org.springframework.boot + spring-boot-starter-jdbc + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + org.apache.tomcat.embed + tomcat-embed-core + + + + + + org.apache.tomcat.embed + tomcat-embed-core + 10.1.42 + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.springframework.boot + spring-boot-starter-integration + + + + + org.springframework.integration + spring-integration-mqtt + 5.5.1 + + + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.boot + spring-boot-starter-integration + + + + org.springframework.integration + spring-integration-redis + + + org.springframework.boot + spring-boot-starter-actuator + + + + org.springframework.boot + spring-boot-starter-test + test + + + software.amazon.awssdk + s3 + + + commons-io + commons-io + 2.19.0 + + + + com.mysql + mysql-connector-j + 9.3.0 + + + org.projectlombok + lombok + + + + + io.joynr.java.messaging.mqtt + paho-mqtt-client + 1.14.2 + + + + org.apache.commons + commons-text + 1.13.1 + + + + + + com.google.code.gson + gson + 2.13.1 + + + io.netty + netty-all + ${netty.version} + + + + org.bouncycastle + bcpkix-jdk18on + 1.81 + + + + com.squareup.okhttp3 + okhttp + 4.12.0 + + + + junit + junit + 4.13.2 + test + + + com.github.houbb + data-factory-core + 1.2.0 + + + + com.github.noconnor + junitperf + 1.22.1 + + + + + org.apache.commons + commons-pool2 + 2.11.1 + + + cn.hutool + hutool-all + 5.8.38 + + + com.github.derjust + spring-data-dynamodb + 5.1.0 + + + com.amazonaws + aws-java-sdk-dynamodb + + + + + + com.amazonaws + aws-java-sdk-dynamodb + 1.12.786 + + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.jayway.jsonpath + json-path + 2.9.0 + + + org.slf4j + jul-to-slf4j + + + + com.alibaba.fastjson2 + fastjson2 + 2.0.46 + + + + org.apache.kafka + kafka-clients + 4.0.0 + + + + + org.yaml + snakeyaml + 2.4 + + + + + net.minidev + json-smart + 2.5.2 + + + + + org.springframework + spring-context + 6.1.21 + + + + + org.springframework + spring-context-support + 6.1.21 + + + + + ch.qos.logback + logback-classic + 1.5.18 + compile + + + ch.qos.logback + logback-core + 1.5.18 + compile + + + + com.google.guava + guava + 33.4.8-jre + + + + + + data-center-receiver + + + org.springframework.boot + spring-boot-maven-plugin + + + + pl.project13.maven + git-commit-id-plugin + 4.9.10 + + + + revision + + + + + true + yyyy-MM-dd'T'HH:mm:ssZ + true + ${project.build.outputDirectory}/git.properties + + + + + + + + + + + + + + + + + + + + + + + + + + + + io.fabric8 + docker-maven-plugin + 0.38.1 + + + AKIA5OFH5OOZPCXZIRUQ + TMIN27+OxamT1FmBQSVKfUIWpOVldhxQx2Stxwix + + + + ${aws.ecr.registryTest}/${aws.ecr.repository}:latest + ${aws.ecr.registry} + + ${project.basedir}/Dockerfile + + + + + + + + + + + src/main/java + + **/*.xml + + + + + src/main/resources + + **/* + + + + + + + diff --git a/readmev2.md b/readmev2.md new file mode 100644 index 0000000..e13fa99 --- /dev/null +++ b/readmev2.md @@ -0,0 +1,15 @@ +# 二期说明 + +## 激活或者冷冻数据来源配置表 +aws lamdba 通过脚本 +调用receiver的接口 +` +/notification/receive +` +传入参数state,和List 类型的id,用于决定哪些数据来源的数据源激活还是冷冻; + +## 数据来源配置表生效 + +接上,会根据配置来实现对应数据源是MQTT接入还是RESTFUL方式接收数据。 + + diff --git a/shell-build.sh b/shell-build.sh new file mode 100644 index 0000000..4e46985 --- /dev/null +++ b/shell-build.sh @@ -0,0 +1,3 @@ +git pull +mvn clean +mvn package -DskipTests=true docker:build diff --git a/src/main/docker/Dockerfile b/src/main/docker/Dockerfile new file mode 100644 index 0000000..2a4fe0b --- /dev/null +++ b/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 + + + + diff --git a/src/main/docker/docker-compose.yaml b/src/main/docker/docker-compose.yaml new file mode 100644 index 0000000..f42529b --- /dev/null +++ b/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 diff --git a/src/main/java/com/techsor/datacenter/receiver/TechsorDataCenterReceiverApplication.java b/src/main/java/com/techsor/datacenter/receiver/TechsorDataCenterReceiverApplication.java new file mode 100644 index 0000000..a96b4e6 --- /dev/null +++ b/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(); + } + +} + diff --git a/src/main/java/com/techsor/datacenter/receiver/clients/DeltaClientMQTTS.java b/src/main/java/com/techsor/datacenter/receiver/clients/DeltaClientMQTTS.java new file mode 100644 index 0000000..ec6a7c8 --- /dev/null +++ b/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); + } + + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/clients/DeltaPushCallback.java b/src/main/java/com/techsor/datacenter/receiver/clients/DeltaPushCallback.java new file mode 100644 index 0000000..164f141 --- /dev/null +++ b/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); + + } + + +} \ No newline at end of file diff --git a/src/main/java/com/techsor/datacenter/receiver/clients/ITAClientMQTT.java b/src/main/java/com/techsor/datacenter/receiver/clients/ITAClientMQTT.java new file mode 100644 index 0000000..43a1f6d --- /dev/null +++ b/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); + } + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/clients/ITAPushCallback.java b/src/main/java/com/techsor/datacenter/receiver/clients/ITAPushCallback.java new file mode 100644 index 0000000..dd8b01f --- /dev/null +++ b/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.*; + +/** + * 发布消息的回调类 + *

+ * 必须实现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 激活此回调。 + */ +@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); + } + + } +} \ No newline at end of file diff --git a/src/main/java/com/techsor/datacenter/receiver/clients/MetComClient.java b/src/main/java/com/techsor/datacenter/receiver/clients/MetComClient.java new file mode 100644 index 0000000..e87ac11 --- /dev/null +++ b/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(""); + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/clients/NBIClient.java b/src/main/java/com/techsor/datacenter/receiver/clients/NBIClient.java new file mode 100644 index 0000000..9b6b9ca --- /dev/null +++ b/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); + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/clients/NittanClient.java b/src/main/java/com/techsor/datacenter/receiver/clients/NittanClient.java new file mode 100644 index 0000000..4dc3c4d --- /dev/null +++ b/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(""); + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/clients/OCRClient.java b/src/main/java/com/techsor/datacenter/receiver/clients/OCRClient.java new file mode 100644 index 0000000..07fac67 --- /dev/null +++ b/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(""); + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/clients/OVIPhoneClient.java b/src/main/java/com/techsor/datacenter/receiver/clients/OVIPhoneClient.java new file mode 100644 index 0000000..e46a92e --- /dev/null +++ b/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); + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/config/CachedBodyHttpServletRequest.java b/src/main/java/com/techsor/datacenter/receiver/config/CachedBodyHttpServletRequest.java new file mode 100644 index 0000000..022402f --- /dev/null +++ b/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(); + } + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/config/DataCenterEnvConfig.java b/src/main/java/com/techsor/datacenter/receiver/config/DataCenterEnvConfig.java new file mode 100644 index 0000000..5885559 --- /dev/null +++ b/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; + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/config/DeltaClientConfig.java b/src/main/java/com/techsor/datacenter/receiver/config/DeltaClientConfig.java new file mode 100644 index 0000000..c425790 --- /dev/null +++ b/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; + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/config/DynamoDBConfig.java b/src/main/java/com/techsor/datacenter/receiver/config/DynamoDBConfig.java new file mode 100644 index 0000000..19f87d2 --- /dev/null +++ b/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); +//// } +// +// +//} \ No newline at end of file diff --git a/src/main/java/com/techsor/datacenter/receiver/config/JdbcTemplateConfig.java b/src/main/java/com/techsor/datacenter/receiver/config/JdbcTemplateConfig.java new file mode 100644 index 0000000..99047b7 --- /dev/null +++ b/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); +// } +//} diff --git a/src/main/java/com/techsor/datacenter/receiver/config/MyFilter.java b/src/main/java/com/techsor/datacenter/receiver/config/MyFilter.java new file mode 100644 index 0000000..385e814 --- /dev/null +++ b/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 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 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); + } + + + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/config/RedisConfig.java b/src/main/java/com/techsor/datacenter/receiver/config/RedisConfig.java new file mode 100644 index 0000000..e5eaed6 --- /dev/null +++ b/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 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 redisTemplate(LettuceConnectionFactory lettuceConnectionFactory) { + RedisTemplate 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); + } + +} + diff --git a/src/main/java/com/techsor/datacenter/receiver/config/RestTemplateConfig.java b/src/main/java/com/techsor/datacenter/receiver/config/RestTemplateConfig.java new file mode 100644 index 0000000..88962cb --- /dev/null +++ b/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); + } + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/config/TaskExecutorConfig.java b/src/main/java/com/techsor/datacenter/receiver/config/TaskExecutorConfig.java new file mode 100644 index 0000000..f9a7de5 --- /dev/null +++ b/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; + } + + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/config/datasource/DataSourceAdminConfig.java b/src/main/java/com/techsor/datacenter/receiver/config/datasource/DataSourceAdminConfig.java new file mode 100644 index 0000000..79659cf --- /dev/null +++ b/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 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); + } + + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/config/datasource/DataSourceContextHolder.java b/src/main/java/com/techsor/datacenter/receiver/config/datasource/DataSourceContextHolder.java new file mode 100644 index 0000000..6abd90c --- /dev/null +++ b/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 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(); + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/config/datasource/DynamicRouteDataSource.java b/src/main/java/com/techsor/datacenter/receiver/config/datasource/DynamicRouteDataSource.java new file mode 100644 index 0000000..add2ca7 --- /dev/null +++ b/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(); + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/config/kafka/Main.java b/src/main/java/com/techsor/datacenter/receiver/config/kafka/Main.java new file mode 100644 index 0000000..831271a --- /dev/null +++ b/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(); + } + + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/config/kafka/RegionEnum.java b/src/main/java/com/techsor/datacenter/receiver/config/kafka/RegionEnum.java new file mode 100644 index 0000000..3af9b09 --- /dev/null +++ b/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; + } + + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/config/kafka/ZiFiClient.java b/src/main/java/com/techsor/datacenter/receiver/config/kafka/ZiFiClient.java new file mode 100644 index 0000000..f79a02e --- /dev/null +++ b/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 poll(); + + public abstract void commit(); + + + + + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/config/kafka/imp/ClientFactory.java b/src/main/java/com/techsor/datacenter/receiver/config/kafka/imp/ClientFactory.java new file mode 100644 index 0000000..b9a13b6 --- /dev/null +++ b/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; + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/config/kafka/imp/ClientType.java b/src/main/java/com/techsor/datacenter/receiver/config/kafka/imp/ClientType.java new file mode 100644 index 0000000..15bab80 --- /dev/null +++ b/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; + } + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/config/kafka/imp/KafkaMessage.java b/src/main/java/com/techsor/datacenter/receiver/config/kafka/imp/KafkaMessage.java new file mode 100644 index 0000000..a3870d4 --- /dev/null +++ b/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 record) { + setBody(record.value()); + setMessageId(String.valueOf(record.offset())); + Map head = new HashMap<>(); + head.put(TOPIC_NAME, record.topic()); + head.put(PARTITION, String.valueOf(record.partition())); + head.put(TIME, String.valueOf(record.timestamp())); + } + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/config/kafka/imp/KafkaZiFiClient.java b/src/main/java/com/techsor/datacenter/receiver/config/kafka/imp/KafkaZiFiClient.java new file mode 100644 index 0000000..1afb414 --- /dev/null +++ b/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 consumer; + private static final Pattern TOPIC_PATTERN_V2 = Pattern.compile(".*-v2"); + + private KafkaConsumer 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 poll() { + Collection messages = new ArrayList(); + ConsumerRecords records = consumer.poll(Duration.ofMillis(100)); + for (ConsumerRecord record : records) { + messages.add(new KafkaMessage(record)); + } + return messages; + } + + @Override + public void commit() { + consumer.commitSync(); + } + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/config/kafka/model/Message.java b/src/main/java/com/techsor/datacenter/receiver/config/kafka/model/Message.java new file mode 100644 index 0000000..4b1adda --- /dev/null +++ b/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 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 getHeaders() { + return headers; + } + + public void setHeaders(Map headers) { + this.headers = headers; + } + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/constants/CodeConstants.java b/src/main/java/com/techsor/datacenter/receiver/constants/CodeConstants.java new file mode 100644 index 0000000..9e404a2 --- /dev/null +++ b/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; + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/constants/CompanyConstants.java b/src/main/java/com/techsor/datacenter/receiver/constants/CompanyConstants.java new file mode 100644 index 0000000..fe15ce0 --- /dev/null +++ b/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"; +} diff --git a/src/main/java/com/techsor/datacenter/receiver/constants/MsgConstants.java b/src/main/java/com/techsor/datacenter/receiver/constants/MsgConstants.java new file mode 100644 index 0000000..8891460 --- /dev/null +++ b/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"; +} diff --git a/src/main/java/com/techsor/datacenter/receiver/constants/UrlConstants.java b/src/main/java/com/techsor/datacenter/receiver/constants/UrlConstants.java new file mode 100644 index 0000000..57b50ea --- /dev/null +++ b/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"; +} diff --git a/src/main/java/com/techsor/datacenter/receiver/controller/HealthController.java b/src/main/java/com/techsor/datacenter/receiver/controller/HealthController.java new file mode 100644 index 0000000..7f4dae6 --- /dev/null +++ b/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 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; + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/controller/NotificationSinkController.java b/src/main/java/com/techsor/datacenter/receiver/controller/NotificationSinkController.java new file mode 100644 index 0000000..d72c5ca --- /dev/null +++ b/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 params){ + + this.threadPoolTaskExecutor.execute(() -> dataReceiveService.receiveCurrentDataSrc(state,params)); + + + Map resultMap=Maps.newHashMap(); + resultMap.put("result",state); + return resultMap; + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/controller/ReceiverController.java b/src/main/java/com/techsor/datacenter/receiver/controller/ReceiverController.java new file mode 100644 index 0000000..1b1c2d3 --- /dev/null +++ b/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 resultMap=new HashMap<>(); + resultMap.put("code","0"); + resultMap.put("msg","success"); + return resultMap; + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/common/BaseTransDataEntity.java b/src/main/java/com/techsor/datacenter/receiver/entity/common/BaseTransDataEntity.java new file mode 100644 index 0000000..87ac329 --- /dev/null +++ b/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 + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/common/CommonTransDataEntity.java b/src/main/java/com/techsor/datacenter/receiver/entity/common/CommonTransDataEntity.java new file mode 100644 index 0000000..9858580 --- /dev/null +++ b/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; //数据源编码 + + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/common/JsonResponse.java b/src/main/java/com/techsor/datacenter/receiver/entity/common/JsonResponse.java new file mode 100644 index 0000000..cc126c4 --- /dev/null +++ b/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; + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/common/KafkaClientConfig.java b/src/main/java/com/techsor/datacenter/receiver/entity/common/KafkaClientConfig.java new file mode 100644 index 0000000..6d98b55 --- /dev/null +++ b/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; + +} \ No newline at end of file diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/common/KafkaZetaMessage.java b/src/main/java/com/techsor/datacenter/receiver/entity/common/KafkaZetaMessage.java new file mode 100644 index 0000000..83c9dcc --- /dev/null +++ b/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; + } + + +} + diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/common/MqttClientConfig.java b/src/main/java/com/techsor/datacenter/receiver/entity/common/MqttClientConfig.java new file mode 100644 index 0000000..b447b2b --- /dev/null +++ b/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; +} \ No newline at end of file diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/common/MqttPublisherEntity.java b/src/main/java/com/techsor/datacenter/receiver/entity/common/MqttPublisherEntity.java new file mode 100644 index 0000000..18bc3aa --- /dev/null +++ b/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; +} diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/common/MqttStartStatusEntity.java b/src/main/java/com/techsor/datacenter/receiver/entity/common/MqttStartStatusEntity.java new file mode 100644 index 0000000..ef775da --- /dev/null +++ b/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; +} diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/common/ResponseEntity.java b/src/main/java/com/techsor/datacenter/receiver/entity/common/ResponseEntity.java new file mode 100644 index 0000000..fc9d521 --- /dev/null +++ b/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 data; +} diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/common/ZAIotTransDataEntity.java b/src/main/java/com/techsor/datacenter/receiver/entity/common/ZAIotTransDataEntity.java new file mode 100644 index 0000000..4485e6b --- /dev/null +++ b/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; + + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/company/CompanyEntity.java b/src/main/java/com/techsor/datacenter/receiver/entity/company/CompanyEntity.java new file mode 100644 index 0000000..e10aa11 --- /dev/null +++ b/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; + + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/datasource/DatasourceConfigEntity.java b/src/main/java/com/techsor/datacenter/receiver/entity/datasource/DatasourceConfigEntity.java new file mode 100644 index 0000000..5c4c14a --- /dev/null +++ b/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; + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/datasource/RestfulParams.java b/src/main/java/com/techsor/datacenter/receiver/entity/datasource/RestfulParams.java new file mode 100644 index 0000000..a9ac4a0 --- /dev/null +++ b/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; +} diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/dto/RedisCommandReceiverDTO.java b/src/main/java/com/techsor/datacenter/receiver/entity/dto/RedisCommandReceiverDTO.java new file mode 100644 index 0000000..90938b2 --- /dev/null +++ b/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 params; +} diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/metcom/MetcomEntity.java b/src/main/java/com/techsor/datacenter/receiver/entity/metcom/MetcomEntity.java new file mode 100644 index 0000000..e168e45 --- /dev/null +++ b/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; +} diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/nittan/AuthEntity.java b/src/main/java/com/techsor/datacenter/receiver/entity/nittan/AuthEntity.java new file mode 100644 index 0000000..39959a1 --- /dev/null +++ b/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; + +} \ No newline at end of file diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/nittan/DeviceInfoEntity.java b/src/main/java/com/techsor/datacenter/receiver/entity/nittan/DeviceInfoEntity.java new file mode 100644 index 0000000..b43e956 --- /dev/null +++ b/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; +} \ No newline at end of file diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/nittan/FacilityInfoEntity.java b/src/main/java/com/techsor/datacenter/receiver/entity/nittan/FacilityInfoEntity.java new file mode 100644 index 0000000..750179f --- /dev/null +++ b/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; +} \ No newline at end of file diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/nittan/LocationInfoEntity.java b/src/main/java/com/techsor/datacenter/receiver/entity/nittan/LocationInfoEntity.java new file mode 100644 index 0000000..877e151 --- /dev/null +++ b/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; +} diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/nittan/NittanEntity.java b/src/main/java/com/techsor/datacenter/receiver/entity/nittan/NittanEntity.java new file mode 100644 index 0000000..7ad6059 --- /dev/null +++ b/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 notice_info; +} + + + + + + + diff --git a/src/main/java/com/techsor/datacenter/receiver/entity/nittan/NoticeInfoEntity.java b/src/main/java/com/techsor/datacenter/receiver/entity/nittan/NoticeInfoEntity.java new file mode 100644 index 0000000..751de93 --- /dev/null +++ b/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; +} \ No newline at end of file diff --git a/src/main/java/com/techsor/datacenter/receiver/listener/DataSourceConfigListener.java b/src/main/java/com/techsor/datacenter/receiver/listener/DataSourceConfigListener.java new file mode 100644 index 0000000..bed0b11 --- /dev/null +++ b/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 { + 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 companyEntityList=this.dataSourceConfigService.getRelatedTopCompany(baseComanyId.toString()); + List 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 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(); + }); + + } + + + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/listener/DeltaMQTTListener.java b/src/main/java/com/techsor/datacenter/receiver/listener/DeltaMQTTListener.java new file mode 100644 index 0000000..2489fae --- /dev/null +++ b/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 { + 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); + } + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/listener/DynamoDBListener.java b/src/main/java/com/techsor/datacenter/receiver/listener/DynamoDBListener.java new file mode 100644 index 0000000..2898069 --- /dev/null +++ b/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 { + 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!!!"); + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/listener/MqttPublisherListener.java b/src/main/java/com/techsor/datacenter/receiver/listener/MqttPublisherListener.java new file mode 100644 index 0000000..d8c30e4 --- /dev/null +++ b/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 { + + 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 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()); + } + } + } + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/listener/RedisStatsSwitchListener.java b/src/main/java/com/techsor/datacenter/receiver/listener/RedisStatsSwitchListener.java new file mode 100644 index 0000000..179a1f1 --- /dev/null +++ b/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 { + + @Resource + private RedisTemplate 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))); + } + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/service/DataTransService.java b/src/main/java/com/techsor/datacenter/receiver/service/DataTransService.java new file mode 100644 index 0000000..f784f30 --- /dev/null +++ b/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; + } + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/service/DuplicateDataProcessor.java b/src/main/java/com/techsor/datacenter/receiver/service/DuplicateDataProcessor.java new file mode 100644 index 0000000..3ee6f7d --- /dev/null +++ b/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; + } + + + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/service/GlobalStateService.java b/src/main/java/com/techsor/datacenter/receiver/service/GlobalStateService.java new file mode 100644 index 0000000..a8e79fe --- /dev/null +++ b/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 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()); + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/service/GlobalSwitchStatusComponent.java b/src/main/java/com/techsor/datacenter/receiver/service/GlobalSwitchStatusComponent.java new file mode 100644 index 0000000..15e7151 --- /dev/null +++ b/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(); + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/service/GuavaRedisCache.java b/src/main/java/com/techsor/datacenter/receiver/service/GuavaRedisCache.java new file mode 100644 index 0000000..17fd587 --- /dev/null +++ b/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 cache; + private final RedisTemplate redisTemplate; + + + private final GlobalSwitchStatusComponent globalSwitchStatusComponent; + @Autowired + public GuavaRedisCache(RedisTemplate redisTemplate, GlobalSwitchStatusComponent globalSwitchStatusComponent ) { + this.redisTemplate = redisTemplate; + this.globalSwitchStatusComponent = globalSwitchStatusComponent; + this.cache = CacheBuilder.newBuilder() + .maximumSize(10000) + .expireAfterWrite(7, TimeUnit.MINUTES) + .concurrencyLevel(1000) + .build(new CacheLoader() { + @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(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/techsor/datacenter/receiver/service/IDataReceiveService.java b/src/main/java/com/techsor/datacenter/receiver/service/IDataReceiveService.java new file mode 100644 index 0000000..e066337 --- /dev/null +++ b/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 params); +} diff --git a/src/main/java/com/techsor/datacenter/receiver/service/IDataSourceConfigService.java b/src/main/java/com/techsor/datacenter/receiver/service/IDataSourceConfigService.java new file mode 100644 index 0000000..46898b4 --- /dev/null +++ b/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 getDataSourceConfig(List datasourceIds) ; + + + public List getDataSourceConfigWithState() ; + + public List getRelatedTopCompany(String baseCompanyId); + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/service/IMQTTService.java b/src/main/java/com/techsor/datacenter/receiver/service/IMQTTService.java new file mode 100644 index 0000000..e37f256 --- /dev/null +++ b/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); +} + diff --git a/src/main/java/com/techsor/datacenter/receiver/service/MQTTCrtService.java b/src/main/java/com/techsor/datacenter/receiver/service/MQTTCrtService.java new file mode 100644 index 0000000..136102f --- /dev/null +++ b/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; + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/service/MqttHistoryDynamoDBService.java b/src/main/java/com/techsor/datacenter/receiver/service/MqttHistoryDynamoDBService.java new file mode 100644 index 0000000..c55f374 --- /dev/null +++ b/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 { +// +//} +@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"); + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/service/MqttHistoryService.java b/src/main/java/com/techsor/datacenter/receiver/service/MqttHistoryService.java new file mode 100644 index 0000000..96ffc80 --- /dev/null +++ b/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()); + } + } + + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/service/MqttPublisherService.java b/src/main/java/com/techsor/datacenter/receiver/service/MqttPublisherService.java new file mode 100644 index 0000000..66dd3cf --- /dev/null +++ b/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 getList(){ + String sql = "SELECT * FROM mqtt_publisher"; + List dataList = (List) jdbcTemplate.query(sql, new RowMapper(){ + @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; + } + + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/service/RestfulService.java b/src/main/java/com/techsor/datacenter/receiver/service/RestfulService.java new file mode 100644 index 0000000..67ed1ab --- /dev/null +++ b/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); + } + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/service/ZetaKafkaService.java b/src/main/java/com/techsor/datacenter/receiver/service/ZetaKafkaService.java new file mode 100644 index 0000000..1624045 --- /dev/null +++ b/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); + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/service/impl/DataReceiveServiceImpl.java b/src/main/java/com/techsor/datacenter/receiver/service/impl/DataReceiveServiceImpl.java new file mode 100644 index 0000000..ad96e30 --- /dev/null +++ b/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 params) { + DataSourceContextHolder.setCurrentDataSourceKey("dataSourceForCompany_" + baseComanyId); + List 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); + } + + } + } + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/service/impl/DataSourceConfigServiceImpl.java b/src/main/java/com/techsor/datacenter/receiver/service/impl/DataSourceConfigServiceImpl.java new file mode 100644 index 0000000..dce239d --- /dev/null +++ b/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 getDataSourceConfig(List 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 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 getDataSourceConfigWithState() { + + //查询激活后的数据源配置 + String sql="select * from data_src_config where state='0' and flag=0 "; + + List 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 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 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; + } + + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/service/impl/MQTTServiceImpl.java b/src/main/java/com/techsor/datacenter/receiver/service/impl/MQTTServiceImpl.java new file mode 100644 index 0000000..c66e2ae --- /dev/null +++ b/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 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> retryRequests = new ConcurrentLinkedQueue<>(); + private final ScheduledExecutorService scheduleRetryTaskExecutor = Executors.newScheduledThreadPool(1); + private static final int MAX_RETRY_ATTEMPTS = 5; + private final Map, Integer> retryAttempts = new ConcurrentHashMap<>(); + + private RedisTemplate 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 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 request = retryRequests.poll(); // 获取并移除此队列的头部 + if (request != null) { + retryFailedMessage(request); + } + } + }, 0, 5, TimeUnit.SECONDS); + } + + + private void retryFailedMessage(Pair 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 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 { + private final int maxSize; + + public MqttConsumerCache(int maxSize) { + super(maxSize + 1, 1.0f, true); + this.maxSize = maxSize; + } + + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + boolean shouldRemove = size() > maxSize; + + if (shouldRemove) { + MqttConsumer consumer = eldest.getValue(); + consumer.stop(); + } + + return shouldRemove; + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/service/impl/ZetaKafkaServiceImpl.java b/src/main/java/com/techsor/datacenter/receiver/service/impl/ZetaKafkaServiceImpl.java new file mode 100644 index 0000000..f4ef593 --- /dev/null +++ b/src/main/java/com/techsor/datacenter/receiver/service/impl/ZetaKafkaServiceImpl.java @@ -0,0 +1,147 @@ +package com.techsor.datacenter.receiver.service.impl; + +import com.google.gson.Gson; +import com.jayway.jsonpath.JsonPath; +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; +import com.techsor.datacenter.receiver.entity.common.*; +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.ZetaKafkaService; +import com.techsor.datacenter.receiver.utils.DefaultHttpRequestUtil; +import com.techsor.datacenter.receiver.utils.MyHTTPResponse; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.task.TaskExecutor; +import org.springframework.stereotype.Service; + +import jakarta.annotation.Resource; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; + +@Service +public class ZetaKafkaServiceImpl implements ZetaKafkaService { + + + private static final Logger logger = LoggerFactory.getLogger(ZetaKafkaServiceImpl.class); + + + @Resource(name="threadPoolTaskExecutor") + private TaskExecutor threadPoolTaskExecutor; + + private LinkedHashMap consumerCache = new LinkedHashMap(); + + @Resource + private GuavaRedisCache guavaRedisCache; + + @Resource + private DataTransService dataTransService; + + @Resource + private DefaultHttpRequestUtil defaultHttpRequestUtil; + + + + + + @Override + public void addKafkaClient(Long companyId, Long configId, KafkaClientConfig config, DatasourceConfigEntity datasourceConfigEntity) { + this.threadPoolTaskExecutor.execute(() -> doAddKafkaClient(companyId, configId, config, datasourceConfigEntity)); + } + + private void doAddKafkaClient(Long companyId, Long configId, KafkaClientConfig config, DatasourceConfigEntity datasourceConfigEntity){ + String key="company_"+companyId+"_ds_"+configId; + if (!consumerCache.containsKey(key)) { + try { + if (Objects.isNull(config)){ + return; + } + + ZiFiClient client = ClientFactory.createClient(ClientType.KAFKA, config.getHost(), config.getApiKey(), config.getApiSecret(), config.getCompanyCode()); + consumerCache.put(key, client); + // v2版本消息订阅不再区分topic;需要使用返回体"payload"结构中的"identify"字段区分数据身份 + client.subscribe(); + logger.info("add kafka client success, host:{}, apiKey:{}, apiSecret:{}, companyCode:{}", + config.getHost(), + config.getApiKey(), + config.getApiSecret(), + config.getCompanyCode()); + + Gson gson = new Gson(); + + while (true) { + //循环处理收到的数据 + client.poll().forEach(message->{ + logger.info("id = {}, value = {}", message.getMessageId(), message.getBody()); + KafkaZetaMessage kafkaZetaMessage = gson.fromJson(message.getBody(), KafkaZetaMessage.class); + String identify = kafkaZetaMessage.getPayload().getIdentify(); + if(StringUtils.equalsIgnoreCase("ms-upload-data", identify) || + StringUtils.equalsIgnoreCase("industry-device-alarm-data", identify) || + StringUtils.equalsIgnoreCase("industry-device-alarm-handle-result", identify) + ){ + + String deviceIdPosition = ""; + if (StringUtils.equalsIgnoreCase("industry-device-alarm-handle-result", identify)){ + deviceIdPosition = "$.payload.data.msSn"; + }else{ + deviceIdPosition = datasourceConfigEntity.getDeviceIdPosition(); + } + + String trimData = StringUtils.trim(message.getBody()); + String deviceId = JsonPath.read(trimData, deviceIdPosition); + if (StringUtils.isEmpty(deviceId)) { + logger.warn("deviceId is null:==>{}", datasourceConfigEntity); + return; + } + guavaRedisCache.incrementDailyDeviceIdCount(deviceId); + MyHTTPResponse response=dataTransService.transferDataZaiot(deviceId, trimData, identify); + if (null != response){ + if(response.getCode()!=200){ + logger.error("transferData error:{}",trimData); + } + } + } + }); + //commit之后才能继续消费下一批次数据 + client.commit(); + } + + } catch (Exception e) { + logger.error("MqttConsumer start failed:{}", config, e); + } + + } + } + + @Override + public void removeKafkaClient(Long companyId, Long configId) { + + } +} + + +//class KafkaClientCache extends LinkedHashMap { +// private final int maxSize; +// +// public KafkaClientCache(int maxSize) { +// super(maxSize + 1, 1.0f, true); +// this.maxSize = maxSize; +// } +// +// @Override +// protected boolean removeEldestEntry(Map.Entry eldest) { +// boolean shouldRemove = size() > maxSize; +// +// if (shouldRemove) { +// MqttConsumer consumer = eldest.getValue(); +// consumer.stop(); +// } +// +// return shouldRemove; +// } +//} \ No newline at end of file diff --git a/src/main/java/com/techsor/datacenter/receiver/utils/DateUtils.java b/src/main/java/com/techsor/datacenter/receiver/utils/DateUtils.java new file mode 100644 index 0000000..41a0d6e --- /dev/null +++ b/src/main/java/com/techsor/datacenter/receiver/utils/DateUtils.java @@ -0,0 +1,19 @@ +package com.techsor.datacenter.receiver.utils; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; + +public class DateUtils { + + + + public static String getCurrentDate(){ + ZoneId zoneId = ZoneId.of("Asia/Tokyo"); + LocalDateTime now = LocalDateTime.now(zoneId); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + String formatDateTime = now.format(formatter); + return formatDateTime; + } + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/utils/DefaultHttpRequestUtil.java b/src/main/java/com/techsor/datacenter/receiver/utils/DefaultHttpRequestUtil.java new file mode 100644 index 0000000..592aca7 --- /dev/null +++ b/src/main/java/com/techsor/datacenter/receiver/utils/DefaultHttpRequestUtil.java @@ -0,0 +1,40 @@ +package com.techsor.datacenter.receiver.utils; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.*; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import cn.hutool.http.HttpRequest; +import cn.hutool.json.JSONUtil; +import jakarta.annotation.Resource; + +@Component("defaultHttpRequestUtil") +public class DefaultHttpRequestUtil { + private static final Logger logger = LoggerFactory.getLogger(DefaultHttpRequestUtil.class); + + + @Resource + private RestTemplate restTemplate; + + + + public MyHTTPResponse postJson(String url,String params){ + logger.warn("Start Process: {}",params); +// HttpHeaders headers = new HttpHeaders(); +// MediaType APPLICATION_JSON = MediaType.parseMediaType("application/json; charset=UTF-8"); +// headers.setContentType(APPLICATION_JSON); +// HttpEntity formEntity = new HttpEntity(params, headers); + + String responseJson = HttpRequest.post(url) + .body(params) + .execute() + .body(); + MyHTTPResponse response = JSONUtil.parseObj(responseJson).toBean(MyHTTPResponse.class); + return response; + } + + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/utils/JsonUtils.java b/src/main/java/com/techsor/datacenter/receiver/utils/JsonUtils.java new file mode 100644 index 0000000..6e6fcc1 --- /dev/null +++ b/src/main/java/com/techsor/datacenter/receiver/utils/JsonUtils.java @@ -0,0 +1,31 @@ +package com.techsor.datacenter.receiver.utils; + +import com.alibaba.fastjson2.JSONObject; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class JsonUtils { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + public static boolean isJson(String jsonString) { + try { + final JsonNode jsonNode = objectMapper.readTree(jsonString); + return true; + } catch (Exception e) { + return false; + } + } + public static boolean isJsonArray(String jsonString) { + try { + final JsonNode jsonNode = objectMapper.readTree(jsonString); + return jsonNode.isArray(); // 检查 JSON 是否为数组 + } catch (Exception e) { + return false; + } + } + + + +} + diff --git a/src/main/java/com/techsor/datacenter/receiver/utils/MyHTTPResponse.java b/src/main/java/com/techsor/datacenter/receiver/utils/MyHTTPResponse.java new file mode 100644 index 0000000..a5fe9c7 --- /dev/null +++ b/src/main/java/com/techsor/datacenter/receiver/utils/MyHTTPResponse.java @@ -0,0 +1,48 @@ +package com.techsor.datacenter.receiver.utils; + +public class MyHTTPResponse { + + private Integer code = 200; + + private String msg; + + private T data; + + public MyHTTPResponse() { + } + + public MyHTTPResponse(Integer code, String msg) { + this.code = code; + this.msg = msg; + } + + public MyHTTPResponse(Integer code, String msg, T data) { + this.code = code; + this.msg = msg; + this.data = data; + } + + public Integer getCode() { + return code; + } + + public void setCode(Integer code) { + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/utils/MyRequest.java b/src/main/java/com/techsor/datacenter/receiver/utils/MyRequest.java new file mode 100644 index 0000000..712adb4 --- /dev/null +++ b/src/main/java/com/techsor/datacenter/receiver/utils/MyRequest.java @@ -0,0 +1,4 @@ +package com.techsor.datacenter.receiver.utils; + +public class MyRequest { +} diff --git a/src/main/java/com/techsor/datacenter/receiver/utils/MyResponse.java b/src/main/java/com/techsor/datacenter/receiver/utils/MyResponse.java new file mode 100644 index 0000000..386d9e4 --- /dev/null +++ b/src/main/java/com/techsor/datacenter/receiver/utils/MyResponse.java @@ -0,0 +1,41 @@ +package com.techsor.datacenter.receiver.utils; + +import com.techsor.datacenter.receiver.entity.common.ResponseEntity; +import com.techsor.datacenter.receiver.constants.CodeConstants; +import com.techsor.datacenter.receiver.constants.MsgConstants; + +import java.util.List; + +public class MyResponse { + + private static ResponseEntity responseEntity; + + //成功请求返回值 + public static ResponseEntity success(List data){ + responseEntity = new ResponseEntity(); + responseEntity.setCode(CodeConstants.CODE_SUCCESS); + responseEntity.setMsg(""); + responseEntity.setData(data); + + return responseEntity; + } + + public static ResponseEntity serverError(List data){ + responseEntity = new ResponseEntity(); + responseEntity.setCode(CodeConstants.CODE_SERVER_ERROR); + responseEntity.setMsg(MsgConstants.MSG_SERVER_ERROR); + responseEntity.setData(data); + + return responseEntity; + } + + //自定义返回 + public static ResponseEntity commonResponse(List data,int code,String msg){ + responseEntity = new ResponseEntity(); + responseEntity.setCode(code); + responseEntity.setMsg(msg); + responseEntity.setData(data); + + return responseEntity; + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/utils/RandomUtils.java b/src/main/java/com/techsor/datacenter/receiver/utils/RandomUtils.java new file mode 100644 index 0000000..1db2859 --- /dev/null +++ b/src/main/java/com/techsor/datacenter/receiver/utils/RandomUtils.java @@ -0,0 +1,34 @@ +package com.techsor.datacenter.receiver.utils; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Calendar; + +public class RandomUtils { + + public static int unique3DigitGenerator(){ + // 获取IP地址的最后一部分 + InetAddress inetAddress = null; + try { + inetAddress = InetAddress.getLocalHost(); + } catch (UnknownHostException e) { + throw new RuntimeException(e); + } + String ipAddress = inetAddress.getHostAddress(); + String[] ipParts = ipAddress.split("\\."); + int lastOctet = Integer.parseInt(ipParts[ipParts.length - 1]); + + // 获取当前的秒数 + Calendar calendar = Calendar.getInstance(); + int second = calendar.get(Calendar.SECOND); + + // 计算三位数字 + int uniqueNumber = (lastOctet + second * 5) % 1000; + if (uniqueNumber < 100) { + uniqueNumber += 100; // 确保它是三位数 + } + return uniqueNumber; + } + + +} diff --git a/src/main/java/com/techsor/datacenter/receiver/utils/RedisUtils.java b/src/main/java/com/techsor/datacenter/receiver/utils/RedisUtils.java new file mode 100644 index 0000000..f141489 --- /dev/null +++ b/src/main/java/com/techsor/datacenter/receiver/utils/RedisUtils.java @@ -0,0 +1,191 @@ +package com.techsor.datacenter.receiver.utils; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.Date; +import java.util.concurrent.TimeUnit; + +@Slf4j +@Component +public class RedisUtils { + @Autowired + private RedisTemplate redisTemplate; + + private final String DEFAULT_KEY_PREFIX = ""; + + + + /** + * 数据缓存至redis + * + * @param key + * @param value + * @return + */ + public void add(K key, String value) { + try { + if (value != null) { + redisTemplate + .opsForValue() + .set(DEFAULT_KEY_PREFIX + key, value); + } + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new RuntimeException("数据缓存至redis失败"); + } + } + + /** + * 数据缓存至redis并设置过期时间 + * + * @param key + * @param value + * @return + */ + public void add(K key, String value, long timeout, TimeUnit unit) { + try { + if (value != null) { + redisTemplate + .opsForValue() + .set(DEFAULT_KEY_PREFIX + key, value, timeout, unit); + } + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new RuntimeException("数据缓存至redis失败"); + } + } + + /** + * 写入 hash-set,已经是key-value的键值,不能再写入为hash-set + * + * @param key must not be {@literal null}. + * @param subKey must not be {@literal null}. + * @param value 写入的值 + */ + public void addHashCache(K key, SK subKey, V value) { + redisTemplate.opsForHash().put(DEFAULT_KEY_PREFIX + key, subKey, value); + } + + /** + * 写入 hash-set,并设置过期时间 + * + * @param key must not be {@literal null}. + * @param subKey must not be {@literal null}. + * @param value 写入的值 + */ + public void addHashCache(K key, SK subKey, V value, long timeout, TimeUnit unit) { + redisTemplate.opsForHash().put(DEFAULT_KEY_PREFIX + key, subKey, value); + redisTemplate.expire(DEFAULT_KEY_PREFIX + key, timeout, unit); + } + + /** + * 获取 hash-setvalue + * + * @param key must not be {@literal null}. + * @param subKey must not be {@literal null}. + */ + public Object getHashCache(K key, SK subKey) { + return redisTemplate.opsForHash().get(DEFAULT_KEY_PREFIX + key, subKey); + } + + + /** + * 功能描述:Get the value of {@code key}. + * + * @param key must not be {@literal null}. + * @return java.lang.String + * @date 2021/9/19 + **/ + public String get(K key) { + String value; + try { + value = redisTemplate.opsForValue().get(DEFAULT_KEY_PREFIX + key).toString(); + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new RuntimeException("从redis缓存中获取缓存数据失败"); + } + return value; + } + + public Integer getInteger(K key,Integer defaultValue) { + String value; + Integer intValue; + try { + value = redisTemplate.opsForValue().get(DEFAULT_KEY_PREFIX + key).toString(); + if (value==null){ + return defaultValue; + }else{ + return Integer.parseInt(value); + } + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new RuntimeException("从redis缓存中获取缓存数据失败"); + } + } + + public String getString(K key,String defaultValue) { + String value; + try { + value = redisTemplate.opsForValue().get(key).toString(); + if (value==null){ + return defaultValue; + }else{ + return value; + } + } catch (Exception e) { + log.error(e.getMessage(), e); + throw new RuntimeException("从redis缓存中获取缓存数据失败"); + } + } + + /** + * 删除key + */ + public void delete(String key) { + redisTemplate.delete(key); + } + + /** + * 批量删除key + */ + public void delete(Collection keys) { + redisTemplate.delete(keys); + } + + /** + * 序列化key + */ + public byte[] dump(String key) { + return redisTemplate.dump(key); + } + + /** + * 是否存在key + */ + public Boolean hasKey(String key) { + return redisTemplate.hasKey(key); + } + + /** + * 设置过期时间 + */ + public Boolean expire(String key, long timeout, TimeUnit unit) { + return redisTemplate.expire(key, timeout, unit); + } + + /** + * 设置过期时间 + */ + public Boolean expireAt(String key, Date date) { + return redisTemplate.expireAt(key, date); + } + + + +} + diff --git a/src/main/java/com/techsor/datacenter/receiver/utils/SpringUtils.java b/src/main/java/com/techsor/datacenter/receiver/utils/SpringUtils.java new file mode 100644 index 0000000..bd93ca5 --- /dev/null +++ b/src/main/java/com/techsor/datacenter/receiver/utils/SpringUtils.java @@ -0,0 +1,31 @@ +package com.techsor.datacenter.receiver.utils; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +@Component +public class SpringUtils implements ApplicationContextAware { + + private static ApplicationContext applicationContext = null; + + + + private SpringUtils(){ + + } + + public static T getBean(String beanName,Class clazz){ + + return (T) applicationContext.getBean(beanName,clazz); + } + + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + SpringUtils.applicationContext =applicationContext; + } +} diff --git a/src/main/java/com/techsor/datacenter/receiver/utils/SslUtil.java b/src/main/java/com/techsor/datacenter/receiver/utils/SslUtil.java new file mode 100644 index 0000000..3a22d40 --- /dev/null +++ b/src/main/java/com/techsor/datacenter/receiver/utils/SslUtil.java @@ -0,0 +1,247 @@ +package com.techsor.datacenter.receiver.utils; + +import com.techsor.datacenter.receiver.service.MQTTCrtService; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openssl.PEMDecryptorProvider; +import org.bouncycastle.openssl.PEMEncryptedKeyPair; +import org.bouncycastle.openssl.PEMKeyPair; +import org.bouncycastle.openssl.PEMParser; +import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; +import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder; +import org.springframework.core.io.FileSystemResource; + +import javax.net.ssl.*; +import java.io.BufferedInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.security.KeyPair; +import java.security.KeyStore; +import java.security.SecureRandom; +import java.security.Security; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +public class SslUtil { +// public static SSLSocketFactory getSocketFactoryOld(final String caCrtFile,final String clientCrtFile, +// final String keyFile,final String password) throws Exception { +// Security.addProvider(new BouncyCastleProvider()); +// //load ca certificate +// PEMReader reader = new PEMReader(new InputStreamReader(new ByteArrayInputStream(Files.readAllBytes(Paths.get(caCrtFile))))); +// X509Certificate caCert = (X509Certificate)reader.readObject(); +// reader.close(); +// +// //load client certificate +// reader = new PEMReader(new InputStreamReader(new ByteArrayInputStream(Files.readAllBytes(Paths.get(clientCrtFile))))); +// X509Certificate clientCert = (X509Certificate)reader.readObject(); +// reader.close(); +// //load client key +// reader = new PEMReader(new InputStreamReader(new ByteArrayInputStream(Files.readAllBytes(Paths.get(keyFile)))), +// new PasswordFinder() { +// +// @Override +// public char[] getPassword() { +// return password.toCharArray(); +// } +// }); +// +// KeyPair key = (KeyPair)reader.readObject(); +// +// reader.close(); +// +// KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); +// +// keyStore.load(null, null); +// keyStore.setCertificateEntry("ca-certificate", caCert); +// TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); +// tmf.init(keyStore); +// +// KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); +// ks.load(null, null); +// ks.setCertificateEntry("certificate", clientCert); +// ks.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(),new java.security.cert.Certificate[] {clientCert}); +// KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); +// kmf.init(ks,password.toCharArray()); +// +// SSLContext context = SSLContext.getInstance("TLSv1.2"); +// context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); +// return context.getSocketFactory(); +// +// } +// +// public static SSLSocketFactory getSocketFactory(final String caCrtFile, +// final String crtFile, final String keyFile, final String password) +// throws Exception { +// Security.addProvider(new BouncyCastleProvider()); +// +// // load CA certificate +// X509Certificate caCert = null; +// +//// FileInputStream fis = new FileInputStream(caCrtFile); +// // ClassPathResource resourcefis = new ClassPathResource(caCrtFile); +// FileSystemResource resourcefis = new FileSystemResource(getFileServerPath(caCrtFile)); +// InputStream fis = resourcefis.getInputStream(); +// +// BufferedInputStream bis = new BufferedInputStream(fis); +// CertificateFactory cf = CertificateFactory.getInstance("X.509"); +// +// while (bis.available() > 0) { +// caCert = (X509Certificate) cf.generateCertificate(bis); +// } +// +// // load client certificate +// //ClassPathResource resourcebis = new ClassPathResource(crtFile); +// FileSystemResource resourcebis = new FileSystemResource(getFileServerPath(crtFile)); +// bis = new BufferedInputStream(resourcebis.getInputStream()); +// X509Certificate cert = null; +// while (bis.available() > 0) { +// cert = (X509Certificate) cf.generateCertificate(bis); +// } +// +// // load client private key +// //ClassPathResource resourcekey = new ClassPathResource(keyFile); +// FileSystemResource resourcekey = new FileSystemResource(getFileServerPath(keyFile)); +// InputStream in = resourcekey.getInputStream(); +// InputStreamReader inReader=new InputStreamReader (in,"UTF-8"); +// +// PEMParser pemParser = new PEMParser(inReader); +// Object object = pemParser.readObject(); +// PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder() +// .build(password.toCharArray()); +// +// JcaPEMKeyConverter converter = new JcaPEMKeyConverter() +// .setProvider("BC"); +// KeyPair key; +// if (object instanceof PEMEncryptedKeyPair) { +// logger.debug("Encrypted key - we will use provided password"); +// key = converter.getKeyPair(((PEMEncryptedKeyPair) object) +// .decryptKeyPair(decProv)); +// } else { +// logger.debug("Unencrypted key - no password needed"); +// key = converter.getKeyPair((PEMKeyPair) object); +// } +// pemParser.close(); +// +// // CA certificate is used to authenticate server +// KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType()); +// caKs.load(null, null); +// caKs.setCertificateEntry("ca-certificate", caCert); +// TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509"); +// tmf.init(caKs); +// +// // client key and certificates are sent to server so it can authenticate +// // us +// KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); +// ks.load(null, null); +// ks.setCertificateEntry("certificate", cert); +// ks.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(), +// new java.security.cert.Certificate[] { cert }); +// KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory +// .getDefaultAlgorithm()); +// kmf.init(ks, password.toCharArray()); +// +// // finally, create SSL socket factory +// SSLContext context = SSLContext.getInstance("TLSv1.2"); +//// SSLContext context = SSLContext.getInstance("SSL"); +// context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); +// +// return context.getSocketFactory(); +// } +// +// public static SSLSocketFactory getSocketFactory(final String caCrtFile, +// final String crtFile, final String keyFile, final String password) throws Exception { +// Security.addProvider(new BouncyCastleProvider()); +// +// // Load CA certificate and client certificate +// X509Certificate caCert = loadCertificate(caCrtFile); +// X509Certificate cert = loadCertificate(crtFile); +// +// // Load client private key +// KeyPair key = loadPrivateKey(keyFile, password); +// +// // CA certificate is used to authenticate server +// TrustManagerFactory tmf = initTrustManagerFactory(caCert); +// +// // Client key and certificates are sent to server so it can authenticate us +// KeyManagerFactory kmf = initKeyManagerFactory(cert, key, password); +// +// // Finally, create SSL socket factory +// SSLContext context = SSLContext.getInstance("TLSv1.2"); +// context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); +// +// return context.getSocketFactory(); +// } + + // 创建一个 SSLSocketFactory,不验证 SSL 证书 + public static SSLSocketFactory getSocketFactory(final String caCrtFile, final String crtFile, final String keyFile, final String password) throws Exception { + TrustManager[] trustAllCerts = new TrustManager[]{ + new X509TrustManager() { + public X509Certificate[] getAcceptedIssuers() { + return null; + } + public void checkClientTrusted(X509Certificate[] certs, String authType) { + } + public void checkServerTrusted(X509Certificate[] certs, String authType) { + } + } + }; + + SSLContext sc = SSLContext.getInstance("TLS"); + sc.init(null, trustAllCerts, new SecureRandom()); + + return sc.getSocketFactory(); + } + + private static X509Certificate loadCertificate(String certFilePath) throws Exception { + try (InputStream is = new FileSystemResource(getFileServerPath(certFilePath)).getInputStream(); + BufferedInputStream bis = new BufferedInputStream(is)) { + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + return (X509Certificate) cf.generateCertificate(bis); + } + } + + private static KeyPair loadPrivateKey(String keyFilePath, String password) throws Exception { + try (InputStream in = new FileSystemResource(getFileServerPath(keyFilePath)).getInputStream(); + InputStreamReader inReader = new InputStreamReader(in, StandardCharsets.UTF_8); + PEMParser pemParser = new PEMParser(inReader)) { + + Object object = pemParser.readObject(); + PEMDecryptorProvider decProv = new JcePEMDecryptorProviderBuilder().build(password.toCharArray()); + + JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC"); + + if (object instanceof PEMEncryptedKeyPair) { + return converter.getKeyPair(((PEMEncryptedKeyPair) object).decryptKeyPair(decProv)); + } else { + return converter.getKeyPair((PEMKeyPair) object); + } + } + } + + private static TrustManagerFactory initTrustManagerFactory(X509Certificate caCert) throws Exception { + KeyStore caKs = KeyStore.getInstance(KeyStore.getDefaultType()); + caKs.load(null, null); + caKs.setCertificateEntry("ca-certificate", caCert); + TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509"); + tmf.init(caKs); + return tmf; + } + + private static KeyManagerFactory initKeyManagerFactory(X509Certificate cert, KeyPair key, String password) throws Exception { + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + ks.load(null, null); + ks.setCertificateEntry("certificate", cert); + ks.setKeyEntry("private-key", key.getPrivate(), password.toCharArray(), new java.security.cert.Certificate[]{cert}); + KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmf.init(ks, password.toCharArray()); + return kmf; + } + + private static String getFileServerPath(String filePath) { +// MQTTCrtService mqttCrtService = SpringUtils.getBean("MQTTCrtService", MQTTCrtService.class); +// return mqttCrtService.getFilePath(filePath); + return filePath; + } + + +} \ No newline at end of file diff --git a/src/main/java/com/techsor/datacenter/receiver/utils/StringUtils.java b/src/main/java/com/techsor/datacenter/receiver/utils/StringUtils.java new file mode 100644 index 0000000..12740a7 --- /dev/null +++ b/src/main/java/com/techsor/datacenter/receiver/utils/StringUtils.java @@ -0,0 +1,18 @@ +package com.techsor.datacenter.receiver.utils; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class StringUtils { + + //删除字符串中特殊字符 + public static String replaceBlank(String str) { + String dest = ""; + if (str != null) { + Pattern p = Pattern.compile("\\s*|\t|\r|\n"); + Matcher m = p.matcher(str); + dest = m.replaceAll(""); + } + return dest; + } +} diff --git a/src/main/liberror-detector-agent.dylib b/src/main/liberror-detector-agent.dylib new file mode 100644 index 0000000..d839792 Binary files /dev/null and b/src/main/liberror-detector-agent.dylib differ diff --git a/src/main/liberror-detector-agent.so b/src/main/liberror-detector-agent.so new file mode 100644 index 0000000..b4bf05d Binary files /dev/null and b/src/main/liberror-detector-agent.so differ diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties new file mode 100644 index 0000000..ebb672e --- /dev/null +++ b/src/main/resources/application-dev.properties @@ -0,0 +1,86 @@ +# +# +# +# + +# +# +# +# +#spring.redis.host=r-uf63x4g5p6ir5xao87pd.redis.rds.aliyuncs.com +#spring.redis.password=B2BGn4gK4htgkEwP +#spring.redis.port=6379 +#spring.redis.database=0 +#spring.redis.timeout=1000 +#spring.redis.lettuce.pool.max-active=8 +#spring.redis.lettuce.pool.min-idle=0 +#spring.redis.lettuce.pool.max-idle=10 +#spring.redis.lettuce.pool.max-wait=1000 +#spring.redis.lettuce.shutdown-timeout=1000 +# +#redis.lock.expire=${redisLockExpire:1000} +# +# +#data.center.receive.address=${dataCenterReceiverTargetUrl:http://localhost:8201} +#data.center.receive.api=/v1/main_receiver +# +#amazon.aws.accesskey=${awsaccesskey:AKIAVRXFMB43XVQ3GXAL} +#amazon.aws.secretkey=${secretkey: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} +#amazon.dynamodb.tableName=dataXXX +# +#delta.topic=${deltaTopic:Publish_Topic} +#delta.host=${deltaTopicHost:tcp://106.75.71.119:1883} +#delta.userName=${deltaUserName:techsor} +#delta.usepassWordrName=${deltaUsePassWordrName:techsorAsd123456} +#delta.enableSSL=${deltaEnableSSL:false} +# +# +#mqtt.keepAliveInterval=${mqttKeepalive:120} + +spring.datasource.admin.name=${springApplicationName:receiver} +spring.datasource.admin.url=${jdbcUrl:jdbc:mysql://rm-bp11k2zm2fr7864428o.mysql.rds.aliyuncs.com/data_center_aeon_admin} +spring.datasource.admin.username=${jdbcUsername:zhc} +spring.datasource.admin.password=${jdbcPassword:Youqu48bnb1} +spring.datasource.admin.driverClassName=com.mysql.jdbc.Driver +spring.datasource.admin.hikari.driverClassName=com.mysql.jdbc.Driver +spring.datasource.admin.hikari.schema=data_center_aeon_admin +spring.datasource.admin.hikari.minimum-idle: 5 +spring.datasource.admin.hikari.maximum-pool-size: ${rdsMaxPool:40} +spring.datasource.admin.hikari.connection-timeout:10000 +logging.level.com.zaxxer.hikari=DEBUG +logging.level.org.springframework=DEBUG + + +dynamic.jdbc.url=${dynamicJdbcUrl:jdbc:mysql://rm-bp11k2zm2fr7864428o.mysql.rds.aliyuncs.com/%s} + +spring.redis.host=r-uf63x4g5p6ir5xao87pd.redis.rds.aliyuncs.com +spring.redis.password=B2BGn4gK4htgkEwP +spring.redis.port=6379 +spring.redis.database=0 +spring.redis.timeout=1000 +spring.redis.lettuce.pool.max-active=8 +spring.redis.lettuce.pool.min-idle=0 +spring.redis.lettuce.pool.max-idle=10 +spring.redis.lettuce.pool.max-wait=1000 +spring.redis.lettuce.shutdown-timeout=1000 + +redis.lock.expire=${redisLockExpire:1000} + +data.center.receive.address=${dataCenterReceiverTargetUrl:} +data.center.receive.api=/v1/main_receiver + +amazon.aws.accesskey=${awsaccesskey:AKIAVRXFMB43XVQ3GXAL} +amazon.aws.secretkey=${secretkey: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} +amazon.aws.bucket=${awsBucket:tokyo-build-databucket-381659385655} +amazon.dynamodb.tableName=${dynamoTableName:mqtt_history} + + +delta.topic=${deltaTopic:"Publish_Topic"} +delta.host=${deltaTopicHost:tcp://106.75.71.119:1883} +delta.userName=${deltaUserName:"test"} +delta.usepassWordrName=${deltaUsePassWordrName:"test"} +delta.enableSSL=${deltaEnableSSL:false} + +mqtt.keepAliveInterval=${mqttKeepalive:120} + +base.companyId=${companyId:1} diff --git a/src/main/resources/application-prd.properties b/src/main/resources/application-prd.properties new file mode 100644 index 0000000..17d0066 --- /dev/null +++ b/src/main/resources/application-prd.properties @@ -0,0 +1,61 @@ + + + + +## ???? +#spring.datasource.url=${jdbcUrl} +#spring.datasource.username=${jdbcUsername} +#spring.datasource.password=${jdbcPassword} + +#spring.datasource.hikari.schema=data_center +#spring.datasource.hikari.minimum-idle: 5 +#spring.datasource.hikari.maximum-pool-size: ${rdsMaxPool:40} +#spring.datasource.hikari.connection-timeout:10000 + +spring.datasource.admin.name=${springApplicationName:reciever} +spring.datasource.admin.url=${jdbcUrl} +spring.datasource.admin.username=${jdbcUsername} +spring.datasource.admin.password=${jdbcPassword} +spring.datasource.admin.driverClassName=com.mysql.jdbc.Driver +spring.datasource.admin.hikari.driverClassName=com.mysql.jdbc.Driver +spring.datasource.admin.hikari.schema=data_center_aeon_admin +spring.datasource.admin.hikari.minimum-idle: 5 +spring.datasource.admin.hikari.maximum-pool-size: ${rdsMaxPool:40} +spring.datasource.admin.hikari.connection-timeout:10000 +logging.level.com.zaxxer.hikari=ERROR +logging.level.org.springframework=ERROR + + +dynamic.jdbc.url=${dynamicJdbcUrl} + +spring.redis.host=${redisHost} +spring.redis.password=${redisPassword} +spring.redis.port=${redisPort} +spring.redis.database=${redisDatabase} +spring.redis.timeout=${redisTimeout} +spring.redis.lettuce.pool.max-active=${redisMaxActive} +spring.redis.lettuce.pool.min-idle=${redisMinIdle} +spring.redis.lettuce.pool.max-idle=${redisMaxIdle} +spring.redis.lettuce.pool.max-wait=${redisMaxWait} +spring.redis.lettuce.shutdown-timeout=${redisShutdownTimeout} + +redis.lock.expire=${redisLockExpire:1000} + +data.center.receive.address=${dataCenterReceiverTargetUrl} +data.center.receive.api=/v1/main_receiver + +amazon.aws.accesskey=${awsaccesskey:AKIAVRXFMB43XVQ3GXAL} +amazon.aws.secretkey=${secretkey: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} +amazon.aws.bucket=${awsBucket:tokyo-build-databucket-381659385655} +amazon.dynamodb.tableName=${dynamoTableName:mqtt_history} + + +delta.topic=${deltaTopic} +delta.host=${deltaTopicHost} +delta.userName=${deltaUserName} +delta.usepassWordrName=${deltaUsePassWordrName} +delta.enableSSL=${deltaEnableSSL:false} + +mqtt.keepAliveInterval=${mqttKeepalive:120} + +base.companyId=${companyId:1} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..7a5e7e1 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,19 @@ +server.port=8200 + + +management.endpoints.web.exposure.include=* + + +spring.profiles.active=${env:dev} + +spring.application.name=data-center-receiver + +ok.http.connect-timeout=${okHttpConnectTimeout:6000} +ok.http.read-timeout=${okHttpConnectTimeoutt:6000} +ok.http.write-timeout=${okHttpConnectTimeout:6000} +ok.http.max-idle-connections=${okHttpMaxIdleConnections:100} +ok.http.keep-alive-duration=${okHttpKeepAliveDuration:300} + + + + diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..dc7d216 --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,67 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + ./logs/receiver.log + + + ./logs/receiver.%d{yyyy-MM-dd}.log + + 7 + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg %n + UTF-8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/ssl/ca.key b/src/main/resources/ssl/ca.key new file mode 100644 index 0000000..2596bf7 --- /dev/null +++ b/src/main/resources/ssl/ca.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAwEtpgcskTOXpBH91FGsoI2UB7Wgmjh7a0+TBMzqMbxNl0S5I +O52MuloDs17N2d0Ct7vvDgQx9ax6n53W+vY0zQ24dUSpp8/JCx1IxmUHBh4DbeJu +7wlVF4y1oS5uyPXrmuhbd87DI6OFlsRJeIJl7RU24QCNb1nI5LbmcVvk+S7Kekpd +Us6LwkSOQ5RgFMCUOuQhdCzfArJoviUiJW4ogAHF1H2fzfzyFd/u3xlDZv1pRmrA +YCs6JYbnB+90+uWG5UDblOe/YUXQW3n/CsHn0S7N9Wahr6rqngTqV/Jgko+llYrQ +d9thama8ZP28Y2RdMYgCxceHAwgv2izwiDP/xQIDAQABAoIBAAxuk7KlfIJQNuFo +kBwy1VR8ekRsAFod2o3qcycpuNyRh3qfoGHiTK/bk/OrxGk6ZauVRd5FHSnB7eeV +38k307ASHAPQ3ZsQzvGeAg95hpu5owUep4dithKgsTlrdBQf+gx4yzkSsAEE2GUn +6YwV+hr6zSJ806gISPmobXuUslf9tqmB7bSbzl9OYoKNA7iNUJP4Am/stT6qNj99 +ZhfLkxT8t8Fc9QevCPrqT4l4KVYI8XSdruutYjyywvQ/IcOXxzz42Z3lQo+9pQhU +qJ0LfMkLkoy0V3cVCwNIhHd7reR1CMbEko05sDX5Uy+bdu6eFAACKt7BY8opUyRV +sZZBRV0CgYEA74+WS3z+IS5K8RC9HKhFtcu/X/mOtUlR6YrbgtI/zu/EOT79hIQC +T7S7e7T6WiICgNY7u9Zgb5BXMGytmmSwvwmd+of9BF4eYju0ZtnPJzJUO212mruC +j0p9vMLM0Id/4ngeCtdGOtyKyxd4yBtlITenzsXw/icZ0K4/hOmG2asCgYEAzX19 +ExJS/D5+yoR/RniP06mIyXVaPZRuwuON7Btu8kWDSh3yRt+ivkvq15iWQK974BED +e5rAdvTU3MqfFNkt5yuwA94owR1dKEeq893N2JM7RN/a/Z+ZZaNuirChCeb+xR7q +EGERC799+sr4/Rj9Uu40YCvO44QxuMuROVp4fE8CgYEA0+h71kK2ubstZ5ia8GKZ +Z3rXypoCdrJo1uGR02MQNok5Vjo2H6Z2NPN2dLNeUaSL+lOHe1zi6U0REzDPUCeJ +gTOMnzTzx41J6zNNHT3GVLHceMUXiUAc+Yu3NeZLLprtsPL4ADb1VNQJoiUdHkW9 +a2jD89B8oRUNbN72KSg5tQkCgYBknVIVeX5qhcsdK/0Jq1R5BeS1B6HUzw3gnPzL +o68SLxkWvEz5iNytooxtXggLyiC0WIBFEEO2uzBSn19/HMvOCeUYL7nyvIb1hwnc +eDknFwgJNDaMwo2gZ4JjpBJlv9X0/KsMtApdnzh3CNUbUBYRehLpF+ooGn0iB4Km ++3ZNHwKBgCyDtxrQPyTQMl+BX3tkTlnzEx3Et3g+QUfJr2GDkPTbk4dF8f+avIoH +J9bFaH2uHpBDdlwIbxta0VVi6xtzPmGtLh87/ep2H/FYF6PvvnvClVDaUJrxxGz9 +o9S7b7cDkwSsHxtXfRgFiT1D0ui2pmVHTNPBSymC3gK/omEA5Yt2 +-----END RSA PRIVATE KEY----- diff --git a/src/main/resources/ssl/ca.pem b/src/main/resources/ssl/ca.pem new file mode 100644 index 0000000..03e3d66 --- /dev/null +++ b/src/main/resources/ssl/ca.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDXTCCAkWgAwIBAgIJAK3bUUbnPce4MA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV +BAYTAmpwMQ4wDAYDVQQIDAV0b2t5bzEOMAwGA1UEBwwFdG9reW8xFjAUBgNVBAoM +DW1pbmktc29sdXRpb24wHhcNMjMwNDIwMDY1MzI2WhcNMzMwNDE3MDY1MzI2WjBF +MQswCQYDVQQGEwJqcDEOMAwGA1UECAwFdG9reW8xDjAMBgNVBAcMBXRva3lvMRYw +FAYDVQQKDA1taW5pLXNvbHV0aW9uMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAwEtpgcskTOXpBH91FGsoI2UB7Wgmjh7a0+TBMzqMbxNl0S5IO52MuloD +s17N2d0Ct7vvDgQx9ax6n53W+vY0zQ24dUSpp8/JCx1IxmUHBh4DbeJu7wlVF4y1 +oS5uyPXrmuhbd87DI6OFlsRJeIJl7RU24QCNb1nI5LbmcVvk+S7KekpdUs6LwkSO +Q5RgFMCUOuQhdCzfArJoviUiJW4ogAHF1H2fzfzyFd/u3xlDZv1pRmrAYCs6JYbn +B+90+uWG5UDblOe/YUXQW3n/CsHn0S7N9Wahr6rqngTqV/Jgko+llYrQd9thama8 +ZP28Y2RdMYgCxceHAwgv2izwiDP/xQIDAQABo1AwTjAdBgNVHQ4EFgQUPi4gs33i +fRtYdxDUbv5G/5A+qvswHwYDVR0jBBgwFoAUPi4gs33ifRtYdxDUbv5G/5A+qvsw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAlCJ19X9IWW/rTMpep+MS +W1a2tGDtrTbzLOCkLM3+G9Sm7YreTWps26NeE+vDv+tAzk/Pk+4SuvfDDjeaRTZc +pH332Spls030+ceN84SsaQWfEp9c1c7HYSY/guYiV9i34wGMZv9oLNXTpVFh5Jwz +9SvcvTjazqjKHC3TtMCBRytoEPWV2M0O7cqQichsy4sQosag59PJn0fHcTKnRzey +YHY7uKCb7cGI7E+2hboTi9acT3IOgz/rpSO6HjTwyTqxKfvx8q48uVHXJna1ArkN +CAnZymlSSqHy7qa6kFui6FFJCYjK6jutMaAd/dhrXwvWltL1guT6wv7oGI1BPXvv +lQ== +-----END CERTIFICATE----- diff --git a/src/main/resources/ssl/ca.srl b/src/main/resources/ssl/ca.srl new file mode 100644 index 0000000..d0bc72a --- /dev/null +++ b/src/main/resources/ssl/ca.srl @@ -0,0 +1 @@ +B2B588B7E935B7F3 diff --git a/src/main/resources/ssl/client.csr b/src/main/resources/ssl/client.csr new file mode 100644 index 0000000..f92da50 --- /dev/null +++ b/src/main/resources/ssl/client.csr @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICmDCCAYACAQAwUzELMAkGA1UEBhMCQ04xETAPBgNVBAgMCFpoZWppYW5nMREw +DwYDVQQHDAhIYW5nemhvdTENMAsGA1UECgwERU1RWDEPMA0GA1UEAwwGY2xpZW50 +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuo7JJF6nJlO/LlmIeq9i +XhH/b6LWy09VkLRUSwhAbtFH82Sf9rPC+MbeeyyJu9Cult6BZLr/ICbUWODNMgzt +XYnnXP31LeiTbp8RA6tDlQE2XuzlXDsBMd4y+VgHo35YzIMxmIq+heWn6+SsIB+T +ULVVXrg5caJZoYC2+Le1A0Vd1U0IhduKVXD8DNF6nSX+QDb5JnRbweaEh8HZAO8u +uUQzoufoZGocm0rsjwZZxSS/zEJfb/4HTxPXFgCAFClD4GUt3JKanjFoHm+5YNwP +icCy0oU1K5+nlX31+lOWrYJfHOu22E6BIankRhcXKeFZyl3CE86TUFB0i79Bp0KI +xQIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBABA35MUPEb48AgVAN50jLFs4PRLZ +RS2LcTkwvUQ2B4tm1pceQZNnv3Ytc91fsz2E3sldn+3cfU8Pyt4NbfpnM7z66Q0c +VzqlH1UGqUuDvbcwvN9n92KiA5F1IQfV06cnWgKAe0VmLv7IYv4kNSKMO2YvCT8d +46VfetNxNjRHxtkcRa4noGxtH7uKu2IWsXlBlz40GgHKQ/jj4UUN0KIstWcmQvip +XpnqwBBMudsb4X+xJF5MpmwwixsGLtntT7lLtMEq0d7lUGTWnWqt2UwMl5rYr0UZ +OeZYfsG7vZIYQMK+3hlGunR2dq8JNrgJ+Ba+cOcMWLn31ap5dlqwDR5Rr1w= +-----END CERTIFICATE REQUEST----- diff --git a/src/main/resources/ssl/client.key b/src/main/resources/ssl/client.key new file mode 100644 index 0000000..bd5e6ec --- /dev/null +++ b/src/main/resources/ssl/client.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAuo7JJF6nJlO/LlmIeq9iXhH/b6LWy09VkLRUSwhAbtFH82Sf +9rPC+MbeeyyJu9Cult6BZLr/ICbUWODNMgztXYnnXP31LeiTbp8RA6tDlQE2Xuzl +XDsBMd4y+VgHo35YzIMxmIq+heWn6+SsIB+TULVVXrg5caJZoYC2+Le1A0Vd1U0I +hduKVXD8DNF6nSX+QDb5JnRbweaEh8HZAO8uuUQzoufoZGocm0rsjwZZxSS/zEJf +b/4HTxPXFgCAFClD4GUt3JKanjFoHm+5YNwPicCy0oU1K5+nlX31+lOWrYJfHOu2 +2E6BIankRhcXKeFZyl3CE86TUFB0i79Bp0KIxQIDAQABAoIBAAsPHdNfHQ+DlWi8 ++/8x2GX1MSw//fWtbUgXuIt+ILuxAk/mXik0vNEckOHCYSPWGhNte0QqZadVRe9C +3EckRwnte96iW19uUxcSrOKHy4jQupVj+7C8+rQnFOR9GG7TtZXiDRWa2/J6C7tL +If0Bgi0dosLrrtQSqLePNsmFsmBQKXINDbw06gGOJ+FelB9LrrUIqk/e3oBocV32 +hAFwXYZuBgSKGCgrCv2HDdMHTZuoSlLzTaVzH5DeWS1oW5Bv/3HRPWW4a8kFpm2+ +zRvL7ZG35Q041JWovXvpnIxGc8w9sPYGUvkBgi1b5h5QUKlEylFD1yaCYVcYcIyz +yDIa7V0CgYEA4+HGYgAFNQaNHqj/ZL9FzwIbI4P+fRuTCDaPAOxjPwTOZt6MEOkL +iQxJnKJqZYujEWcIXe5rjR5kI0+yRfTea6yYxrZXUvN6uPO0AtcmqHtsZ1XiTMbi +TUWm9jb9hWyabWzOxihmBt2blbIBMO3rnhIhsvrGBgCJ4N2at5BR1G8CgYEA0ZOu +uni/UnGbFq752nAsnzdMC+V2ke4nnV6VOgCfPuxvLlHTqGp8vuEsL7JIwNRdgaMg +RIl+pFz5GwweUtid0D3E8VUpD0xCFlTj+/OIX16fwlpQKDaGt4JwxDOvrdbIoYNa +FyXT1y+OxQruO4dx+Lv67YjSQ87VsKoZ7+dsGAsCgYA4JF2Ns1eVEsIdtaEGHyGB +uJEbFN/TzsFQmrBsl9BzrCl1qopzeBbBcueH0XPJBLfuB6ZGDgEtSTl+gZn4JjXN +7T3OZwnog9fOTSwiLwN1KsMwSjZwl+cVBn311uJqxrDdGJtwsm9AbcRxAuPMPDF6 +RhlLUQEMZYGShsYhR0sBvQKBgQDOHETaBQh8B1h0PY9h4bIwv4xdosUyjZqOLUfr +bFMw6gwJ7NWRK3EVtJPlMJxWcESpywlf/iz7bqhajleAOKMz+pumkI86CVBxb/lr +fz2eNYw+8t0kP0PMVE+c1gwvli1okqrWWxB078OkS7Sx/On8qrsEQuwvXcpQ3Wl2 +xA1NswKBgQCfv02fE0fb98jIik3wEldAikHgiKQVFYYkmziVi6L4yPjoBNiYGTib +0ou5nRsvEALfPZ+qoJ/S9y6IuT3VeZ/IEiTSCRNpVOv06+VnbsUmhDQF3vsH0GFR +CmuWUaJivj7ulFN8lybU9IY3omExY4muX5clJklsztUIS8t8JUs9fg== +-----END RSA PRIVATE KEY----- diff --git a/src/main/resources/ssl/client.pem b/src/main/resources/ssl/client.pem new file mode 100644 index 0000000..518e133 --- /dev/null +++ b/src/main/resources/ssl/client.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDFDCCAfwCCQCytYi36TW38zANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJq +cDEOMAwGA1UECAwFdG9reW8xDjAMBgNVBAcMBXRva3lvMRYwFAYDVQQKDA1taW5p +LXNvbHV0aW9uMB4XDTIzMDQyMDA2NTQzMFoXDTMzMDQxNzA2NTQzMFowUzELMAkG +A1UEBhMCQ04xETAPBgNVBAgMCFpoZWppYW5nMREwDwYDVQQHDAhIYW5nemhvdTEN +MAsGA1UECgwERU1RWDEPMA0GA1UEAwwGY2xpZW50MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAuo7JJF6nJlO/LlmIeq9iXhH/b6LWy09VkLRUSwhAbtFH +82Sf9rPC+MbeeyyJu9Cult6BZLr/ICbUWODNMgztXYnnXP31LeiTbp8RA6tDlQE2 +XuzlXDsBMd4y+VgHo35YzIMxmIq+heWn6+SsIB+TULVVXrg5caJZoYC2+Le1A0Vd +1U0IhduKVXD8DNF6nSX+QDb5JnRbweaEh8HZAO8uuUQzoufoZGocm0rsjwZZxSS/ +zEJfb/4HTxPXFgCAFClD4GUt3JKanjFoHm+5YNwPicCy0oU1K5+nlX31+lOWrYJf +HOu22E6BIankRhcXKeFZyl3CE86TUFB0i79Bp0KIxQIDAQABMA0GCSqGSIb3DQEB +CwUAA4IBAQBkc1Mc/mUt55o0M0PwOigAteaLSNJ1MCBnOgFBRQZNqJXjF1g4g3+s +qa5PKnzYEplJ6BJrVnqBAhcbf7X+39mBw+N+Ka0vZqQDe1Krwmr3hLbnKhbJ5coE +kNHYNKxFoBlJPb70gXMlicRa5n6ZIsVDu3+fojB0pbmZ2RXQ+/yHPr9DMrPc8mlG +fQqlMXD/rONjYZgxjLGVj/rX6jyoOHWxAnDT8aGzQPrrJsn+IQIPvqkviv10yho0 +D2ipjRqHTSYnPzskuWUq42+VO/YXrg6uLZVSWBka0ohKiIZaRBGNuSyKyaiwClqD +01gMgeB2+Z5TugHmPAOXdRM0PDJBDl7g +-----END CERTIFICATE----- diff --git a/src/main/resources/ssl/emqx.csr b/src/main/resources/ssl/emqx.csr new file mode 100644 index 0000000..95eac17 --- /dev/null +++ b/src/main/resources/ssl/emqx.csr @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIC+DCCAeACAQAwTzELMAkGA1UEBhMCQ04xETAPBgNVBAgMCFpoZWppYW5nMREw +DwYDVQQHDAhIYW5nemhvdTENMAsGA1UECgwERU1RWDELMAkGA1UEAwwCQ0EwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6KWq7obmS9C959ajjFjPcb2yk +bK5k1KbW000cMUG2mYETnmywmsD41PKEUowfDNdXYRLaVNLmnJu67cDnlSjtpfhy +xbgRnepJCeukk1GN2sPGz5dLdeDYPMphZrNVOOEtgDKw9YfsxQiHGuqXJW2gIiFS +YBzVVTvIGXYSbSKqct1p5wpcJu7nIjBSzeWnn5rjWLftuTI2zTRp8Dr1zhz071ne +n52CIwQO4KbRLF1NMese9JnXGajC9fAZzWxUSN/EIl8FIDzFKvgqim1rGImhGRZ9 +Vn0tQuSDCh6rvZPV6PS10ScmCkEj/n3ZDkz/aST4fyhyVEvDco97wdP64EDvAgMB +AAGgZDBiBgkqhkiG9w0BCQ4xVTBTMFEGA1UdEQRKMEiCRnRva3lvLWJ1aWxkLXBy +b2QtbmxiLTdkN2FlNDJjY2Y0ODcwOWIuZWxiLmFwLW5vcnRoZWFzdC0xLmFtYXpv +bmF3cy5jb20wDQYJKoZIhvcNAQELBQADggEBAIujjaTcCgiUTHfa7PSw8C8FO3V/ +VaTSDQg5jBVGxcQrnB1ZZXo435HcI7KYmBc7TwRQr/VuTLg2bUu9Ij34CWGseT3+ +NhaCZGJ0ND1RaAVgEL0DPx80HCovKWHXHcQXvN8EKj/8xs63E7svZYMC5k3dgT0R +SGPPJZtMdBOOQJjmGXR9b9qNeD46JPoh8cF8sIEk1dLmjF2iW6yupXC+pXqesNgF +WRqgn67p5r3jsXtbCd7i8oUFms97nARPAcPlfGAniY6GaYXKv7cI8TuAoWvK4mAc +NyD4CMixWr7ff6aSB/tjuyImZ4hgDihL/qRe+IRk2QrZRfJNwJauV6jHYGs= +-----END CERTIFICATE REQUEST----- diff --git a/src/main/resources/ssl/emqx.key b/src/main/resources/ssl/emqx.key new file mode 100644 index 0000000..c7c83f2 --- /dev/null +++ b/src/main/resources/ssl/emqx.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAuilqu6G5kvQvefWo4xYz3G9spGyuZNSm1tNNHDFBtpmBE55s +sJrA+NTyhFKMHwzXV2ES2lTS5pybuu3A55Uo7aX4csW4EZ3qSQnrpJNRjdrDxs+X +S3Xg2DzKYWazVTjhLYAysPWH7MUIhxrqlyVtoCIhUmAc1VU7yBl2Em0iqnLdaecK +XCbu5yIwUs3lp5+a41i37bkyNs00afA69c4c9O9Z3p+dgiMEDuCm0SxdTTHrHvSZ +1xmowvXwGc1sVEjfxCJfBSA8xSr4KoptaxiJoRkWfVZ9LULkgwoeq72T1ej0tdEn +JgpBI/592Q5M/2kk+H8oclRLw3KPe8HT+uBA7wIDAQABAoIBACHcBp25/JbN8xSr +qdwj3arqWUhOvCl6xB2usQe/rcQYh3GaDwrQGuknUjTfDr1XCJPMBDHR28o2Ed0e +AUgdySPwXBAEBkauAj7mnwWABgVXFOTEPTBscEjkRasRkuydO9eayZ2GCwL1k2d/ +bcuv8xB9JLJm6NekeQscFm2ji/qUOgyFi5fxSv1AzQRN6/SA6jmpdzJdpzpaz2lL +EVqs3RODtnuZvXU2/AfYAiwswfmZq3dVn4rM0mE6YJ0dmi5hxJNByHKDmR/N8Fpy +oOdhQXKCJ9mcNXVxzVYNIXs6z2mCLa9Ch/Zq4Ipf7LdaWa7afwJ/hef73nybKcD0 +jfre4YECgYEA7/lVfTqw9bJeupYY9tOwqW2tYOL1LSSt8Qp1w+w24Xhma6YlG7oy +YgGyBtCAZOUcVToZb23OxLT0FAy7EnTj/UOI0sVZ3wGeb4sPsffvbKpRS/VkUIyi +84Um0rCu2GNGd1Ch3ODDgjV8oyj/F1K56gtID2sJKZ6UCUl1gNNyI50CgYEAxpgY +E+Kk/KxvZSIvQe7No5LMTzps4HmCXF6Q6l8xAm/NyMfD2RWA7ayJeGVgaap/UB3f +1CcNGVu8aG6zAq2n0/ZTinBPkOQKo+7K5YAsBCRnspF69OzA3pxq3ddmeLEj4bPe +uhmTOX4h1LCYSyANbdj5EJ7LKo13pNzFpaLbzvsCgYAz9IqSw1s+xrCFuyuKfQiZ +lhpciKbGcFOMhVQ75+9132hlVCJin2x7FZzips+1iHka5qpNGrwSkI7rrFnwRAh8 +c9uyrnGnu6T+x1/Niz12DGXviSB/5AL/sEtYgFJKnSvLd1SkCrGphkUG2kBoX0vL +JUgjtmvUa/XnENV039KtbQKBgE9JZ8uAoCg02+B/rmhfZABbWnCDPfa87FvecXLx +AEsdwgXYI4vm9uttCBFmQADPzjZ5RuSXlrY6FtWG5Lc8B5YrcR0DS/Dn6ouaiazo +6CnbMv9q77EbWMFHp67cEZA8ALxaqKCaF1pLzkvxGUxdBp+FkaKeEzTw+AR9E/fW +NnXDAoGAanl2yFfPj7PDwmOuNE80wYzwWbvXmg/PSX/bLu27WKAc5YnsAecXGdDi +yVZqQyX6+M/prhKX45I/eUslv3FROjGqdf9+cCKvzk2I5MWtNl7i/P6yx1Y5hbLY +yTYLD2EmD5cERtxwd9hUut9Ilm2hsZyn7e9ZvVtnvwlRkNNJd9A= +-----END RSA PRIVATE KEY----- diff --git a/src/main/resources/ssl/emqx.pem b/src/main/resources/ssl/emqx.pem new file mode 100644 index 0000000..755c0c0 --- /dev/null +++ b/src/main/resources/ssl/emqx.pem @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDbDCCAlSgAwIBAgIJALK1iLfpNbfyMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV +BAYTAmpwMQ4wDAYDVQQIDAV0b2t5bzEOMAwGA1UEBwwFdG9reW8xFjAUBgNVBAoM +DW1pbmktc29sdXRpb24wHhcNMjMwNDIwMDY1NDEyWhcNMzMwNDE3MDY1NDEyWjBP +MQswCQYDVQQGEwJDTjERMA8GA1UECAwIWmhlamlhbmcxETAPBgNVBAcMCEhhbmd6 +aG91MQ0wCwYDVQQKDARFTVFYMQswCQYDVQQDDAJDQTCCASIwDQYJKoZIhvcNAQEB +BQADggEPADCCAQoCggEBALoparuhuZL0L3n1qOMWM9xvbKRsrmTUptbTTRwxQbaZ +gROebLCawPjU8oRSjB8M11dhEtpU0uacm7rtwOeVKO2l+HLFuBGd6kkJ66STUY3a +w8bPl0t14Ng8ymFms1U44S2AMrD1h+zFCIca6pclbaAiIVJgHNVVO8gZdhJtIqpy +3WnnClwm7uciMFLN5aefmuNYt+25MjbNNGnwOvXOHPTvWd6fnYIjBA7gptEsXU0x +6x70mdcZqML18BnNbFRI38QiXwUgPMUq+CqKbWsYiaEZFn1WfS1C5IMKHqu9k9Xo +9LXRJyYKQSP+fdkOTP9pJPh/KHJUS8Nyj3vB0/rgQO8CAwEAAaNVMFMwUQYDVR0R +BEowSIJGdG9reW8tYnVpbGQtcHJvZC1ubGItN2Q3YWU0MmNjZjQ4NzA5Yi5lbGIu +YXAtbm9ydGhlYXN0LTEuYW1hem9uYXdzLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEA +jwCx+wKE+/2mUV0Gzg0qKQBFoSPZt3AsfuXft/ByyByaTZMV9kFiI2mGAJ0MT+Ig +k6WAnWBSiXVM43Nauaj2UYOWPb+YdJafJpt1GY9nNVjxseTTsvcAY+I9pjZlc/8W +jN9YVHFldpNBHficOB1TAvjrcjGpAB01PeHeScpJNIxfFRszWFuU0NspUZWFgSPM +rUu4DAvtjnsKhV6RjOZHmuxZpoX8/TzXEnJ2i+Gtgk+oZelgl90YdLz2FbSNqq4O +d9lo/YWuVdW+2XmM8PwSbsRxkhoUiM3uvBV2HxHaxXzBwt6eAIjrqdF+Y4BCHWI1 +pdqjg/zYT+n1u7a7qlAKyA== +-----END CERTIFICATE----- diff --git a/src/main/resources/ssl/openssl.cnf b/src/main/resources/ssl/openssl.cnf new file mode 100644 index 0000000..e3acba9 --- /dev/null +++ b/src/main/resources/ssl/openssl.cnf @@ -0,0 +1,18 @@ +[req] +default_bits = 2048 +distinguished_name = req_distinguished_name +req_extensions = req_ext +x509_extensions = v3_req +prompt = no +[req_distinguished_name] +countryName = CN +stateOrProvinceName = Zhejiang +localityName = Hangzhou +organizationName = EMQX +commonName = CA +[req_ext] +subjectAltName = @alt_names +[v3_req] +subjectAltName = @alt_names +[alt_names] +DNS.1 = tokyo-build-prod-nlb-7d7ae42ccf48709b.elb.ap-northeast-1.amazonaws.com diff --git a/src/main/相关脚本/datacenter-simulator.py b/src/main/相关脚本/datacenter-simulator.py new file mode 100644 index 0000000..8d1400f --- /dev/null +++ b/src/main/相关脚本/datacenter-simulator.py @@ -0,0 +1,108 @@ +import time +import paho.mqtt.client as mqtt +import requests + +loopTime = 60 + +def send_loytech_message(): + broker = "tokyo-build-nlb-dca261c9e6c227bf.elb.ap-northeast-1.amazonaws.com" + port = 1883 + topic = "loytech_publish_test1" + + message1='[{"id":"TTN-HMI-1-1-TEST","type":"Boolean","reportedAt":"$UUID","value":false}]' + message2='[{"id":"TTN-HMI-1-2-TEST","type":"Analog","reportedAt":"$UUID","value":32.3}]' + message3='[{"id":"TTN-HMI-1-3-TEST","type":"Analog","reportedAt":"$UUID","value":888.8}]' + client_id = "pythonclient-1" + client = mqtt.Client(client_id, transport='tcp') + client.username_pw_set("test", "test") + client.connect(broker, port,60) + client.loop_start() + + message1 = message1.replace('$UUID',str(time.time()),1) + message2 = message2.replace('$UUID',str(time.time()),1) + message3 = message3.replace('$UUID',str(time.time()),1) + + client.publish(topic, message1) + print("publish:"+message1) + time.sleep(loopTime) + client.publish(topic, message2) + print("publish:"+message2) + time.sleep(loopTime) + client.publish(topic, message3) + print("publish:"+message3) + time.sleep(loopTime) + + client.loop_stop() + client.disconnect() + +def send_zeta_message(): + broker = "tokyo-build-nlb-dca261c9e6c227bf.elb.ap-northeast-1.amazonaws.com" + port = 1883 + topic = "zeta_test1" + + message1='{"msgDirect":"report","msgPriority":"normal","msgType":"real","msgId":0,"apTime":1694010627271,"msgEncrypt":"none","msgUid":"ffff173f","msgCmd":"ms","apUid":"ffff173f","msgParam":{"subCmd":"report","subType":"uploadData","msUid":"BB000033","data":"0101","dataEncrypt":"none"},"deviceAlias":"BB000033","deviceaddr":"$UUID"}' + message2='{"msgDirect":"report","msgPriority":"normal","msgType":"real","msgId":0,"apTime":1694010627271,"msgEncrypt":"none","msgUid":"ffff173f","msgCmd":"ms","apUid":"ffff173f","msgParam":{"subCmd":"report","subType":"uploadData","msUid":"BB000017","data":"01001020","dataEncrypt":"none"},"deviceAlias":"BB000017","deviceaddr":"$UUID"}' + message3='{"msgDirect":"report","msgPriority":"normal","msgType":"real","msgId":0,"apTime":1694010627271,"msgEncrypt":"none","msgUid":"ffff173f","msgCmd":"ms","apUid":"ffff173f","msgParam":{"subCmd":"report","subType":"uploadData","msUid":"BB000024","data":"0100000000000099","dataEncrypt":"none"},"deviceAlias":"BB000024","deviceaddr":"$UUID"}' + client_id = "pythonclient-2" + client = mqtt.Client(client_id, transport='tcp') + client.username_pw_set("test", "test") + client.connect(broker, port,60) + client.loop_start() + + message1 = message1.replace('$UUID',str(time.time()),1) + message2 = message2.replace('$UUID',str(time.time()),1) + message3 = message3.replace('$UUID',str(time.time()),1) + + client.publish(topic, message1) + print("publish:"+message1) + time.sleep(loopTime) + client.publish(topic, message2) + print("publish:"+message2) + time.sleep(loopTime) + client.publish(topic, message3) + print("publish:"+message3) + time.sleep(loopTime) + + client.loop_stop() + client.disconnect() + +def send_nittan_message(): + url = "http://tokyo-build-alb-106026535.ap-northeast-1.elb.amazonaws.com:8200/api/v2/to_dbm/nittan" + message1 = '{"facility_info":{"facility_maker":"NITTAN","facility_id":"Nihonbashi-Building","facility_mode":"Normal"},"auth":{"code":"10001","signature":"techsor","timestamp":"1681759000","subscription_id":"N22SHY3n","version":"0.2"},"cmd":"notice","notice_info":[{"device_info":{"device_name":"$UUID","device_class":"Smoke Detector"},"notice_level":1,"location_info":{"location_address":"01_P2_01_0001_A9_TEST"},"notice_status":"FireAlarm","notice_type":"Fire"}]}' + message2 = '{"facility_info":{"facility_maker":"NITTAN","facility_id":"Nihonbashi-Building","facility_mode":"Normal"},"auth":{"code":"10001","signature":"techsor","timestamp":"1681759000","subscription_id":"N22SHY3n","version":"0.2"},"cmd":"notice","notice_info":[{"device_info":{"device_name":"$UUID","device_class":"Smoke Detector"},"notice_level":5,"location_info":{"location_address":"01_P2_01_0001_A9_TEST"},"notice_status":"FireReset","notice_type":"Fire"}]}' + message3 = '{"facility_info":{"facility_maker":"NITTAN","facility_id":"Nihonbashi-Building","facility_mode":"Normal"},"auth":{"code":"10001","signature":"techsor","timestamp":"1681759000","subscription_id":"N22SHY3n","version":"0.2"},"cmd":"notice","notice_info":[{"device_info":{"device_name":"$UUID","device_class":"Smoke Control"},"notice_level":1,"location_info":{"location_address":"01_P2_01_0001_A9_TEST"},"notice_status":"ON","notice_type":"Interlock"}]}' + message4 = '{"facility_info":{"facility_maker":"NITTAN","facility_id":"Nihonbashi-Building","facility_mode":"Normal"},"auth":{"code":"10001","signature":"techsor","timestamp":"1681759000","subscription_id":"N22SHY3n","version":"0.2"},"cmd":"notice","notice_info":[{"device_info":{"device_name":"$UUID","device_class":"Smoke Control"},"notice_level":5,"location_info":{"location_address":"01_P2_01_0001_A9_TEST"},"notice_status":"OFF","notice_type":"Interlock"}]}' + # 设置请求头 + headers = { + "Content-Type": "application/json" + } + + message1 = message1.replace('$UUID',str(time.time()),1) + message2 = message2.replace('$UUID',str(time.time()),1) + message3 = message3.replace('$UUID',str(time.time()),1) + message4 = message4.replace('$UUID',str(time.time()),1) + + # 发送HTTP POST请求 + response = requests.post(url, data=message1, headers=headers) + print("publish:"+message1) + time.sleep(loopTime) + response = requests.post(url, data=message2, headers=headers) + print("publish:"+message2) + time.sleep(loopTime) + response = requests.post(url, data=message3, headers=headers) + print("publish:"+message3) + time.sleep(loopTime) + response = requests.post(url, data=message4, headers=headers) + print("publish:"+message4) + time.sleep(loopTime) + # 获取响应数据 + result = response.json() + # 输出响应结果 + print(result) + + +while(1): + send_loytech_message() + send_zeta_message() + send_nittan_message() + time.sleep(loopTime) \ No newline at end of file diff --git a/src/main/相关脚本/mqtt1RPS.py b/src/main/相关脚本/mqtt1RPS.py new file mode 100644 index 0000000..ca727eb --- /dev/null +++ b/src/main/相关脚本/mqtt1RPS.py @@ -0,0 +1,36 @@ +import time +import uuid +import paho.mqtt.client as mqtt + +def send_mqtt_message(): + broker = "tokyo-build-nlb-dca261c9e6c227bf.elb.ap-northeast-1.amazonaws.com" + port = 1883 + topic = "loytech_publish_test1" + loopTime = 1 + message='[{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":false},{"id":"BA0100","type":"Boolean","reportedAt":"$UUID","value":true}]' + client_id = "pythonclient-1" + client = mqtt.Client(client_id, transport='tcp') + client.username_pw_set("test", "test") + client.connect(broker, port,60) + client.loop_start() + message_count = 0 + start_time = time.time() + + while message_count < loopTime: + messageProcessed = message + while '$UUID' in messageProcessed: + messageProcessed = messageProcessed.replace('$UUID',str(time.time()),1) + + client.publish(topic, messageProcessed) + message_count += 1 + current_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + print("Sent message {} at {}".format(message_count, current_time)) + print(messageProcessed) + time.sleep(1) + end_time = time.time() + total_time = end_time - start_time + print("Total messages sent: {}".format(message_count)) + print("Total time taken: {} seconds".format(total_time)) + client.loop_stop() + client.disconnect() +send_mqtt_message() \ No newline at end of file diff --git a/src/main/相关脚本/readme.md b/src/main/相关脚本/readme.md new file mode 100644 index 0000000..4ca1449 --- /dev/null +++ b/src/main/相关脚本/readme.md @@ -0,0 +1,6 @@ +# datacenter-simulator.py + +每分钟模拟发送各个类别数据,测试用 + +# mqtt1RPS.py +1s发送一条loytech数据,每条数据包含800个设备数据 \ No newline at end of file diff --git a/src/test/java/com/techsor/datacenter/MQTTZetaDataSenderTest.java b/src/test/java/com/techsor/datacenter/MQTTZetaDataSenderTest.java new file mode 100644 index 0000000..cbf338d --- /dev/null +++ b/src/test/java/com/techsor/datacenter/MQTTZetaDataSenderTest.java @@ -0,0 +1,53 @@ +package com.techsor.datacenter; + +import com.alibaba.fastjson2.JSON; +import com.techsor.datacenter.receiver.TechsorDataCenterReceiverApplication; +import com.techsor.datacenter.receiver.constants.MsgConstants; +import com.techsor.datacenter.receiver.entity.dto.RedisCommandReceiverDTO; +import com.techsor.datacenter.receiver.service.DataTransService; +import com.techsor.datacenter.receiver.utils.DefaultHttpRequestUtil; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.text.StringEscapeUtils; +import org.eclipse.paho.client.mqttv3.MqttException; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import jakarta.annotation.Resource; +import java.util.Objects; + +//@RunWith(SpringRunner.class) +@SpringBootTest(classes = TechsorDataCenterReceiverApplication.class,webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT ) +public class MQTTZetaDataSenderTest { + + @Resource + private DataTransService dataTransService; + + // @JUnitPerfTest(threads = 10,warmUpMs = 20,maxExecutionsPerSecond = -1) + @Test + public void sendMessageData() throws MqttException { + String json = "{\"commandType\":\"startStat\"}"; + json = json.substring(1, json.length() - 1); + json= StringEscapeUtils.unescapeJson(json); + RedisCommandReceiverDTO redisCommandReceiverDTO= JSON.parseObject(json, RedisCommandReceiverDTO.class); + + if (StringUtils.equals(redisCommandReceiverDTO.getCommandType(), MsgConstants.REDIS_COMMAND_NOTIFICATION_TYPE)){ + System.out.println("swith"); + }else{ + //redis统计事件,每隔5分钟会被触发 + + if (StringUtils.equalsIgnoreCase(redisCommandReceiverDTO.getCommandType(), MsgConstants.REDIS_COMMAND_STAT_EVENT)) { + System.out.println("async"); + }else{ + if (StringUtils.equals(redisCommandReceiverDTO.getCommandType(), MsgConstants.REIDS_COMMAND_SWITCH_TYPE)){ + System.out.println("update status"); + }else{ + System.out.println("Unknown command type: {}"+redisCommandReceiverDTO.getCommandType()); + } + } + } + + } + +} diff --git a/src/test/java/com/techsor/datacenter/mqtt/MQTTDataSenderTest.java b/src/test/java/com/techsor/datacenter/mqtt/MQTTDataSenderTest.java new file mode 100644 index 0000000..637d483 --- /dev/null +++ b/src/test/java/com/techsor/datacenter/mqtt/MQTTDataSenderTest.java @@ -0,0 +1,85 @@ +package com.techsor.datacenter.mqtt; + +import com.github.houbb.data.factory.core.util.DataUtil; +import com.github.noconnor.junitperf.JUnitPerfRule; +import com.github.noconnor.junitperf.JUnitPerfTest; +import com.github.noconnor.junitperf.reporting.providers.ConsoleReportGenerator; +import com.google.gson.Gson; +import com.techsor.datacenter.mqtt.msg.DeltaMessage; +import com.techsor.datacenter.mqtt.msg.ZetaMessage; +import com.techsor.datacenter.receiver.TechsorDataCenterReceiverApplication; +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.MqttMessage; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.redis.core.RedisTemplate; + +import jakarta.annotation.Resource; +import java.nio.charset.StandardCharsets; + +@SpringBootTest(classes = TechsorDataCenterReceiverApplication.class,webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT ) +public class MQTTDataSenderTest { + @Rule + public JUnitPerfRule perfTestRule = new JUnitPerfRule(new ConsoleReportGenerator()); + + private MqttClient mqttClient; + + @Before + + public void setUp() throws MqttException { + this.mqttClient=new MqttClient("tcp://106.75.71.119:1883","testst"); + this.mqttClient.connect(new MqttConnectOptions(){ + { + + } + }); + } + + + // @JUnitPerfTest(threads = 10,warmUpMs = 20,maxExecutionsPerSecond = -1) + @Test + public void sendMessageData() throws MqttException { + + + this.mqttClient.publish("test",new MqttMessage(){ + { + ZetaMessage zetaMessage=DataUtil.build(ZetaMessage.class); + zetaMessage.getMsgParam().setMsUid("bf001002"); + zetaMessage.getMsgParam().setData("0101101a0241"); + Gson gson=new Gson(); + setPayload(gson.toJson(zetaMessage).getBytes(StandardCharsets.UTF_8)); + System.err.println(gson.toJson(zetaMessage)); + } + }); + + } + // @JUnitPerfTest(threads = 100,warmUpMs = 20,maxExecutionsPerSecond = -1) + @Test + public void sendDeltaMessage() throws MqttException { + this.mqttClient.publish("test",new MqttMessage(){ + { + + DeltaMessage deltaMessage=DataUtil.build(DeltaMessage.class); + deltaMessage.setId("TTN-HMI-12-2-4D-AI"); + Gson gson=new Gson(); + setPayload(gson.toJson(deltaMessage).getBytes(StandardCharsets.UTF_8)); + System.err.println(gson.toJson(deltaMessage)); + } + }); + } + + + @Autowired + private RedisTemplate redisTemplate; + + @Test + public void testRedisTemplate(){ + Object o=redisTemplate.opsForValue().get("test"); + System.err.println(o); + } +} diff --git a/src/test/java/com/techsor/datacenter/mqtt/MqttClientConfigTests.java b/src/test/java/com/techsor/datacenter/mqtt/MqttClientConfigTests.java new file mode 100644 index 0000000..061a69f --- /dev/null +++ b/src/test/java/com/techsor/datacenter/mqtt/MqttClientConfigTests.java @@ -0,0 +1,25 @@ +package com.techsor.datacenter.mqtt; + +import com.google.gson.Gson; +import com.techsor.datacenter.receiver.entity.common.MqttClientConfig; +import org.junit.Test; + +public class MqttClientConfigTests { + + @Test + public void test(){ + MqttClientConfig config = new MqttClientConfig(); + config.setClientId("xxxxx"); + config.setConnectionTimeout(1000); + config.setDescription("xxxxx"); + config.setPassword("test"); + config.setSslState(true); + config.setTopic("xxxxx"); + config.setUrl("tcp://106.75.71.119:1883"); + config.setUsername("test"); + Gson gson = new Gson(); + String jsonValue=gson.toJson(config); + System.out.println(jsonValue); + + } +} diff --git a/src/test/java/com/techsor/datacenter/mqtt/msg/DeltaMessage.java b/src/test/java/com/techsor/datacenter/mqtt/msg/DeltaMessage.java new file mode 100644 index 0000000..21389aa --- /dev/null +++ b/src/test/java/com/techsor/datacenter/mqtt/msg/DeltaMessage.java @@ -0,0 +1,25 @@ +package com.techsor.datacenter.mqtt.msg; + +import com.github.houbb.data.factory.api.annotation.DataFactory; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +@Data +public class DeltaMessage { + + @DataFactory + private String id; + private String type; + + private String Analog; + + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:SS") + private Date reportedAt; + + @DataFactory(min = 0,max = 100,precision = 2) + private Double value; + +} \ No newline at end of file diff --git a/src/test/java/com/techsor/datacenter/mqtt/msg/MsgParam.java b/src/test/java/com/techsor/datacenter/mqtt/msg/MsgParam.java new file mode 100644 index 0000000..e26b2cc --- /dev/null +++ b/src/test/java/com/techsor/datacenter/mqtt/msg/MsgParam.java @@ -0,0 +1,12 @@ +package com.techsor.datacenter.mqtt.msg; + +import lombok.Data; + +@Data +public class MsgParam { + private String subCmd; + private String subType; + private String msUid="TTN-HMI-12-1-4E-AI"; + private String data; + private String dataEncrypt; +} diff --git a/src/test/java/com/techsor/datacenter/mqtt/msg/ZetaMessage.java b/src/test/java/com/techsor/datacenter/mqtt/msg/ZetaMessage.java new file mode 100644 index 0000000..50a2be1 --- /dev/null +++ b/src/test/java/com/techsor/datacenter/mqtt/msg/ZetaMessage.java @@ -0,0 +1,28 @@ +package com.techsor.datacenter.mqtt.msg; + + +import com.techsor.datacenter.mqtt.msg.MsgParam; +import lombok.Data; + +@Data +public class ZetaMessage{ + private String msgDirect; + + private String msgPriority; + + private String msgType; + + private Long msgId; + + private Long apTime; + + private String msgEncrypt; + + private String msgUid; + + private String msgCmd; + + private String apUid; + + private MsgParam msgParam; +} diff --git a/src/test/java/com/techsor/datacenter/receiver/IdPositionTest.java b/src/test/java/com/techsor/datacenter/receiver/IdPositionTest.java new file mode 100644 index 0000000..3e6454c --- /dev/null +++ b/src/test/java/com/techsor/datacenter/receiver/IdPositionTest.java @@ -0,0 +1,56 @@ +package com.techsor.datacenter.receiver; + +import com.alibaba.fastjson2.JSON; +import com.google.gson.Gson; +import com.jayway.jsonpath.JsonPath; +import com.techsor.datacenter.receiver.utils.JsonUtils; +import org.apache.commons.lang3.StringUtils; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.Objects; + +public class IdPositionTest { + + @Test + public void test(){ + String messagePayload="{\"Sum\":1,\"Now\":1,\"PNs\":{\"1\":\"V\",\"2\":\"T\",\"3\":\"Q\"},\"PVs\":{\"1\":0,\"2\":\"2024-12-12 13:10:15.229\",\"3\":192},\"Objs\":[{\"N\":\"$DeviceStatusOfSCS1\",\"1\":0,\"2\":0,\"3\":65535},{\"N\":\"$DeviceControlOfSCS1\",\"1\":0,\"2\":0,\"3\":65535},{\"N\":\"TTY_3001_MT_AI0\",\"1\":0.0,\"2\":0,\"3\":65535},{\"N\":\"TTY_3001_MT_AI1\",\"1\":0.0,\"2\":0,\"3\":65535},{\"N\":\"TTY_3001_AT_KR22\",\"1\":0,\"2\":0,\"3\":65535},{\"N\":\"TTY_3001_AT_KR248\",\"1\":0,\"2\":0,\"3\":65535}]}"; + String deviceIdPosition = "$.Objs[0].N"; + + + 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 = messagePayload instanceof String + ? (String) messagePayload + : gson.toJson(messagePayload); + System.out.println(payloadStr); +// String trimData = StringUtils.trim(payloadStr); + + String trimData = "{\"Sum\":1,\"Now\":1,\"PNs\":{\"1\":\"V\",\"2\":\"T\",\"3\":\"Q\"},\"PVs\":{\"1\":0,\"2\":\"2024-12-12 13:10:15.229\",\"3\":192},\"Objs\":[{\"N\":\"$DeviceStatusOfSCS1\",\"1\":0,\"2\":0,\"3\":65535},{\"N\":\"$DeviceControlOfSCS1\",\"1\":0,\"2\":0,\"3\":65535},{\"N\":\"TTY_3001_MT_AI0\",\"1\":0.0,\"2\":0,\"3\":65535},{\"N\":\"TTY_3001_MT_AI1\",\"1\":0.0,\"2\":0,\"3\":65535},{\"N\":\"TTY_3001_AT_KR22\",\"1\":0,\"2\":0,\"3\":65535},{\"N\":\"TTY_3001_AT_KR248\",\"1\":0,\"2\":0,\"3\":65535}]}"; + deviceIdPosition = "$.Objs[0].N"; + String deviceId = JsonPath.read(trimData, deviceIdPosition); + System.out.println(deviceId); + } + + 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; + } +} diff --git a/src/test/java/com/techsor/datacenter/receiver/TechsorDataCenterReceiverApplicationTests.java b/src/test/java/com/techsor/datacenter/receiver/TechsorDataCenterReceiverApplicationTests.java new file mode 100644 index 0000000..df1a769 --- /dev/null +++ b/src/test/java/com/techsor/datacenter/receiver/TechsorDataCenterReceiverApplicationTests.java @@ -0,0 +1,26 @@ +package com.techsor.datacenter.receiver; + +import com.techsor.datacenter.receiver.service.MqttHistoryDynamoDBService; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.redis.core.RedisTemplate; + +import jakarta.annotation.Resource; + +@SpringBootTest(classes = TechsorDataCenterReceiverApplication.class,webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT ) +class TechsorDataCenterReceiverApplicationTests { + + @Resource + private RedisTemplate redisTemplate; + + @Resource + private MqttHistoryDynamoDBService mqttHistoryDynamoDBService; + @Test + void contextLoads() throws Exception { + System.err.println( + redisTemplate.opsForValue().get("test") + ); + + } + +}