Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
T
terminal-protocol-proxy-service
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
fox-energy
backend
terminal-protocol-proxy-service
Commits
728e4d5f
Commit
728e4d5f
authored
Jan 03, 2023
by
xieshaojun
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
init
parent
7f857659
Pipeline
#40430
failed with stages
in 12 minutes and 18 seconds
Changes
109
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
109 changed files
with
4860 additions
and
2 deletions
+4860
-2
.gitignore
.gitignore
+31
-0
.gitlab-ci.yml
.gitlab-ci.yml
+50
-0
README.md
README.md
+4
-2
pom.xml
pom.xml
+193
-0
ProtocolProxyApplication.java
src/main/java/vc/thinker/ProtocolProxyApplication.java
+24
-0
MqttCallbackImpl.java
...c/thinker/absctacts/mqtt/connection/MqttCallbackImpl.java
+154
-0
MqttConnectionProperties.java
...r/absctacts/mqtt/connection/MqttConnectionProperties.java
+51
-0
MqttResponse.java
...n/java/vc/thinker/absctacts/mqtt/entity/MqttResponse.java
+35
-0
MqttResponseBytes.java
...a/vc/thinker/absctacts/mqtt/entity/MqttResponseBytes.java
+35
-0
AbstractCommonBytesHandleMqttProtocol.java
.../mqtt/protocol/AbstractCommonBytesHandleMqttProtocol.java
+50
-0
AbstractCommonEntityHandleMqttProtocol.java
...mqtt/protocol/AbstractCommonEntityHandleMqttProtocol.java
+76
-0
AbstractCommonHandleMqttProtocol.java
...tacts/mqtt/protocol/AbstractCommonHandleMqttProtocol.java
+62
-0
AbstractMqttProtocol.java
...thinker/absctacts/mqtt/protocol/AbstractMqttProtocol.java
+62
-0
AbstractNotSubscriptionMqttProtocol.java
...ts/mqtt/protocol/AbstractNotSubscriptionMqttProtocol.java
+29
-0
IMqttProtocol.java
...ava/vc/thinker/absctacts/mqtt/protocol/IMqttProtocol.java
+50
-0
ConcurrentKeyMqttPushService.java
.../absctacts/mqtt/publish/ConcurrentKeyMqttPushService.java
+36
-0
MqttCommandPush.java
...va/vc/thinker/absctacts/mqtt/publish/MqttCommandPush.java
+44
-0
TopicMqttPushService.java
.../thinker/absctacts/mqtt/publish/TopicMqttPushService.java
+36
-0
TopicDefinition.java
...java/vc/thinker/absctacts/mqtt/topic/TopicDefinition.java
+23
-0
SslUtil.java
src/main/java/vc/thinker/absctacts/mqtt/utils/SslUtil.java
+95
-0
StringFormatUtils.java
...va/vc/thinker/absctacts/mqtt/utils/StringFormatUtils.java
+44
-0
IMeterReportEntity.java
...inker/absctacts/protocolproxy/dto/IMeterReportEntity.java
+33
-0
IServiceExecuteCmd.java
...inker/absctacts/protocolproxy/dto/IServiceExecuteCmd.java
+60
-0
IServiceExecuteResult.java
...er/absctacts/protocolproxy/dto/IServiceExecuteResult.java
+32
-0
MeterInfo.java
...ava/vc/thinker/absctacts/protocolproxy/dto/MeterInfo.java
+17
-0
MeterReportEntity.java
...hinker/absctacts/protocolproxy/dto/MeterReportEntity.java
+58
-0
ServiceExecuteCmd.java
...hinker/absctacts/protocolproxy/dto/ServiceExecuteCmd.java
+21
-0
ServiceExecuteResult.java
...ker/absctacts/protocolproxy/dto/ServiceExecuteResult.java
+35
-0
DataType.java
...va/vc/thinker/absctacts/protocolproxy/enums/DataType.java
+28
-0
IMeterAttrDefine.java
...inker/absctacts/protocolproxy/enums/IMeterAttrDefine.java
+16
-0
IMeterDataDefine.java
...inker/absctacts/protocolproxy/enums/IMeterDataDefine.java
+16
-0
IMeterEventDefine.java
...nker/absctacts/protocolproxy/enums/IMeterEventDefine.java
+10
-0
IProtocolType.java
.../thinker/absctacts/protocolproxy/enums/IProtocolType.java
+23
-0
ServiceExecuteResultType.java
...sctacts/protocolproxy/enums/ServiceExecuteResultType.java
+22
-0
IMeterServiceDefine.java
...acts/protocolproxy/enums/service/IMeterServiceDefine.java
+25
-0
IServiceParamDefine.java
...acts/protocolproxy/enums/service/IServiceParamDefine.java
+26
-0
NoParam.java
...hinker/absctacts/protocolproxy/enums/service/NoParam.java
+23
-0
ParamDefine.java
...er/absctacts/protocolproxy/enums/service/ParamDefine.java
+25
-0
VerifyException.java
...er/absctacts/protocolproxy/exception/VerifyException.java
+17
-0
ExecTimeoutException.java
...ctacts/protocolproxy/exceptions/ExecTimeoutException.java
+24
-0
MeterCodeFormatException.java
...ts/protocolproxy/exceptions/MeterCodeFormatException.java
+21
-0
MeterOfflineException.java
...tacts/protocolproxy/exceptions/MeterOfflineException.java
+21
-0
ServiceExecTimeoutException.java
...protocolproxy/exceptions/ServiceExecTimeoutException.java
+24
-0
AbstractThirdPartyProtocol.java
...ts/protocolproxy/protocol/AbstractThirdPartyProtocol.java
+73
-0
AbstractThirdPartyProtocolSyncMeterInfo.java
...oxy/protocol/AbstractThirdPartyProtocolSyncMeterInfo.java
+86
-0
IThirdPartyProtocol.java
...absctacts/protocolproxy/protocol/IThirdPartyProtocol.java
+38
-0
IThirdPartyProtocolSyncMeterInfo.java
...tocolproxy/protocol/IThirdPartyProtocolSyncMeterInfo.java
+36
-0
AkkaConfig.java
src/main/java/vc/thinker/config/akka/AkkaConfig.java
+59
-0
SpringActorProducer.java
...vc/thinker/config/akka/extension/SpringActorProducer.java
+39
-0
SpringExtension.java
...ava/vc/thinker/config/akka/extension/SpringExtension.java
+33
-0
ExceptionAdvice.java
src/main/java/vc/thinker/exception/ExceptionAdvice.java
+32
-0
MqttProtocolConfig.java
src/main/java/vc/thinker/mqtt/config/MqttProtocolConfig.java
+52
-0
ThinkerMqttConnectionProperties.java
.../thinker/mqtt/config/ThinkerMqttConnectionProperties.java
+23
-0
ThinkerProdMqttConnectionProperties.java
...nker/mqtt/config/ThinkerProdMqttConnectionProperties.java
+23
-0
ThinkerTestMqttConnectionProperties.java
...nker/mqtt/config/ThinkerTestMqttConnectionProperties.java
+23
-0
ThinkerProdProtocolClient.java
...hinker/mqtt/forwardthinker/ThinkerProdProtocolClient.java
+30
-0
ThinkerTestDataProtocol.java
.../thinker/mqtt/forwardthinker/ThinkerTestDataProtocol.java
+39
-0
ThirdPartyReportDataActor.java
...tt/forwardthinker/actor/up/ThirdPartyReportDataActor.java
+45
-0
FoxGatewayTopicDefinition.java
.../mqtt/forwardthinker/enums/FoxGatewayTopicDefinition.java
+46
-0
ThirdPartyProxyClientProtocol.java
...inker/mqtt/proxyclient/ThirdPartyProxyClientProtocol.java
+51
-0
MeterChangeActor.java
...thinker/mqtt/proxyclient/actor/down/MeterChangeActor.java
+62
-0
MeterListPullResponseActor.java
...tt/proxyclient/actor/down/MeterListPullResponseActor.java
+36
-0
ThirdPartyServiceExecuteActor.java
...proxyclient/actor/down/ThirdPartyServiceExecuteActor.java
+72
-0
MeterListPullActor.java
...thinker/mqtt/proxyclient/actor/up/MeterListPullActor.java
+35
-0
ThirdPartyReportActor.java
...nker/mqtt/proxyclient/actor/up/ThirdPartyReportActor.java
+36
-0
ThirdPartyServiceExecuteResponseActor.java
...lient/actor/up/ThirdPartyServiceExecuteResponseActor.java
+36
-0
BaseResponse.java
...vc/thinker/mqtt/proxyclient/entity/down/BaseResponse.java
+14
-0
MeterChange.java
.../vc/thinker/mqtt/proxyclient/entity/down/MeterChange.java
+15
-0
MeterListResponse.java
...inker/mqtt/proxyclient/entity/down/MeterListResponse.java
+18
-0
PlateFormMeterInfo.java
...nker/mqtt/proxyclient/entity/down/PlateFormMeterInfo.java
+15
-0
ServiceExecCmd.java
.../thinker/mqtt/proxyclient/entity/down/ServiceExecCmd.java
+20
-0
MeterData.java
...java/vc/thinker/mqtt/proxyclient/entity/up/MeterData.java
+176
-0
MeterListPull.java
.../vc/thinker/mqtt/proxyclient/entity/up/MeterListPull.java
+17
-0
ServiceExecResult.java
...thinker/mqtt/proxyclient/entity/up/ServiceExecResult.java
+27
-0
ThirdPartyProxyReport.java
...ker/mqtt/proxyclient/entity/up/ThirdPartyProxyReport.java
+27
-0
ThirdPartyProxyTopicDefinition.java
...qtt/proxyclient/enums/ThirdPartyProxyTopicDefinition.java
+53
-0
ThirdPartyProxyClientService.java
...qtt/proxyclient/service/ThirdPartyProxyClientService.java
+82
-0
AbstractResponse.java
src/main/java/vc/thinker/response/AbstractResponse.java
+120
-0
SimpleResponse.java
src/main/java/vc/thinker/response/SimpleResponse.java
+21
-0
ProtocolType.java
src/main/java/vc/thinker/thirdpartyproxy/ProtocolType.java
+62
-0
CentralAirMeterAttrDefine.java
...y/protocolimpls/centralAir/CentralAirMeterAttrDefine.java
+38
-0
CentralAirProtocol.java
...rtyproxy/protocolimpls/centralAir/CentralAirProtocol.java
+62
-0
TerminalReportData.java
...rtyproxy/protocolimpls/centralAir/TerminalReportData.java
+50
-0
DataReportInfoDTO.java
...proxy/protocolimpls/centralAir/dto/DataReportInfoDTO.java
+27
-0
DataReportParamDTO.java
...roxy/protocolimpls/centralAir/dto/DataReportParamDTO.java
+26
-0
TestMeterAttrDefine.java
...irdpartyproxy/protocolimpls/test/TestMeterAttrDefine.java
+36
-0
TestMeterEventDefine.java
...rdpartyproxy/protocolimpls/test/TestMeterEventDefine.java
+30
-0
TestProtocol.java
...nker/thirdpartyproxy/protocolimpls/test/TestProtocol.java
+58
-0
StartTool.java
src/main/java/vc/thinker/tools/StartTool.java
+22
-0
CompletableFutureObserver.java
...main/java/vc/thinker/utils/CompletableFutureObserver.java
+47
-0
DES.java
src/main/java/vc/thinker/utils/DES.java
+90
-0
LocalDateTimeUtils.java
src/main/java/vc/thinker/utils/LocalDateTimeUtils.java
+228
-0
Resolve.java
src/main/java/vc/thinker/utils/Resolve.java
+35
-0
ResolveMultipart.java
src/main/java/vc/thinker/utils/ResolveMultipart.java
+43
-0
SpringContextHolder.java
src/main/java/vc/thinker/utils/SpringContextHolder.java
+109
-0
StringFormaterUtils.java
src/main/java/vc/thinker/utils/StringFormaterUtils.java
+21
-0
SynchronizeSignal.java
src/main/java/vc/thinker/utils/SynchronizeSignal.java
+56
-0
DependsInfoTools.java
.../java/vc/thinker/utils/dependhandle/DependsInfoTools.java
+119
-0
KeyValueHandlerRelation.java
...c/thinker/utils/dependhandle/KeyValueHandlerRelation.java
+24
-0
SetValueHandler.java
...n/java/vc/thinker/utils/dependhandle/SetValueHandler.java
+18
-0
CentralAirController.java
src/main/java/vc/thinker/web/CentralAirController.java
+53
-0
EnumValidate.java
src/main/java/vc/thinker/web/validator/EnumValidate.java
+13
-0
ProtocolValidator.java
...main/java/vc/thinker/web/validator/ProtocolValidator.java
+32
-0
ValidatorEnum.java
src/main/java/vc/thinker/web/validator/ValidatorEnum.java
+29
-0
TerminalDataReportVO.java
src/main/java/vc/thinker/web/vo/TerminalDataReportVO.java
+39
-0
application.yml
src/main/resources/application.yml
+40
-0
banner.txt
src/main/resources/banner.txt
+19
-0
bootstrap.yml
src/main/resources/bootstrap.yml
+6
-0
logback-spring.xml
src/main/resources/logback-spring.xml
+57
-0
No files found.
.gitignore
0 → 100644
View file @
728e4d5f
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**
!**/src/test/**
### 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/
### VS Code ###
.vscode/
.gitlab-ci.yml
0 → 100644
View file @
728e4d5f
image
:
registry.cn-shenzhen.aliyuncs.com/thinker-open/maven:3.6-jdk14
variables
:
MAVEN_OPTS
:
"
-Dmaven.repo.local=.m2/repository"
MAVEN_CLI_OPTS
:
"
compile
jib:build
"
KUBECONFIG
:
"
/etc/deploy/config"
# Cache downloaded dependencies and plugins between builds.
# To keep cache across branches add 'key: "$CI_JOB_NAME"'
cache
:
paths
:
-
.m2/repository
stages
:
-
build
-
deploy
build:jdk13-master
:
stage
:
build
services
:
-
docker:18.09-dind
variables
:
DOCKER_HOST
:
tcp://localhost:2375
DOCKER_DRIVER
:
overlay2
script
:
-
mvn $MAVEN_CLI_OPTS -Djib.to.auth.username=${docker_username} -Djib.to.auth.password=${docker_password}
only
:
-
master
docker-compose-down-and-up
:
stage
:
deploy
tags
:
-
thinker-cloud-app
script
:
-
echo ">>>>docker-compose down and up"
-
cd /data/thinker-devops-cloud/backend
-
docker-compose pull thinker-protocol-proxy-service
-
docker-compose up -d thinker-protocol-proxy-service
-
docker system prune -f
-
echo ">>>>done"
variables
:
GIT_STRATEGY
:
clone
GIT_CHECKOUT
:
"
false"
cache
:
{}
only
:
-
master
README.md
View file @
728e4d5f
端数据上报代理
\ No newline at end of file
# 协议代理服务
协议代理服务,第三方物联网设备私有协议,在此服务中进行编码适配
\ No newline at end of file
pom.xml
0 → 100644
View file @
728e4d5f
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns=
"http://maven.apache.org/POM/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<parent>
<groupId>
vc.thinker
</groupId>
<artifactId>
spring-cloud-cabbage-parent
</artifactId>
<version>
1.0.14-SNAPSHOT
</version>
</parent>
<artifactId>
terminal-protocol-proxy-service
</artifactId>
<name>
${artifactId}
</name>
<description>
富士康设备服务
</description>
<packaging>
jar
</packaging>
<properties>
<image>
registry-vpc.cn-shenzhen.aliyuncs.com/thinker-vc/terminal-protocol-proxy-service
</image>
<baseimage>
registry-vpc.cn-shenzhen.aliyuncs.com/thinker-open/openjdk14-openj9
</baseimage>
<mainClass>
vc.thinker.ProtocolProxyApplication
</mainClass>
</properties>
<dependencies>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
fastjson
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-web
</artifactId>
</dependency>
<dependency>
<groupId>
org.apache.commons
</groupId>
<artifactId>
commons-lang3
</artifactId>
<optional>
true
</optional>
</dependency>
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger2
</artifactId>
</dependency>
<dependency>
<groupId>
io.springfox
</groupId>
<artifactId>
springfox-swagger-ui
</artifactId>
</dependency>
<dependency>
<groupId>
org.projectlombok
</groupId>
<artifactId>
lombok
</artifactId>
</dependency>
<dependency>
<groupId>
org.freemarker
</groupId>
<artifactId>
freemarker
</artifactId>
</dependency>
<dependency>
<groupId>
org.apache.poi
</groupId>
<artifactId>
poi
</artifactId>
</dependency>
<dependency>
<groupId>
org.apache.poi
</groupId>
<artifactId>
poi-ooxml
</artifactId>
</dependency>
<dependency>
<groupId>
org.bouncycastle
</groupId>
<artifactId>
bcprov-jdk16
</artifactId>
</dependency>
<dependency>
<groupId>
com.typesafe.akka
</groupId>
<artifactId>
akka-actor_2.11
</artifactId>
</dependency>
<dependency>
<groupId>
com.typesafe.akka
</groupId>
<artifactId>
akka-slf4j_2.11
</artifactId>
</dependency>
<dependency>
<groupId>
org.eclipse.paho
</groupId>
<artifactId>
org.eclipse.paho.client.mqttv3
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-websocket
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.kafka
</groupId>
<artifactId>
spring-kafka
</artifactId>
</dependency>
<dependency>
<groupId>
org.apache.kafka
</groupId>
<artifactId>
kafka-clients
</artifactId>
</dependency>
<dependency>
<groupId>
org.jeasy
</groupId>
<artifactId>
easy-rules-core
</artifactId>
</dependency>
<dependency>
<groupId>
net.sf.dozer
</groupId>
<artifactId>
dozer
</artifactId>
<exclusions>
<exclusion>
<groupId>
org.slf4j
</groupId>
<artifactId>
slf4j-log4j12
</artifactId>
</exclusion>
<exclusion>
<groupId>
org.slf4j
</groupId>
<artifactId>
jcl-over-slf4j
</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>
io.craftsman
</groupId>
<artifactId>
dozer-jdk8-support
</artifactId>
</dependency>
<!-- Alibaba Spring Context extension -->
<dependency>
<groupId>
com.alibaba.spring
</groupId>
<artifactId>
spring-context-support
</artifactId>
<version>
1.0.2
</version>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
transmittable-thread-local
</artifactId>
<version>
2.2.0
</version>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-test
</artifactId>
<scope>
test
</scope>
</dependency>
<dependency>
<groupId>
cn.hutool
</groupId>
<artifactId>
hutool-all
</artifactId>
<version>
5.7.12
</version>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-test
</artifactId>
</dependency>
<dependency>
<groupId>
junit
</groupId>
<artifactId>
junit
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework
</groupId>
<artifactId>
spring-test
</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-compiler-plugin
</artifactId>
</plugin>
<plugin>
<groupId>
com.google.cloud.tools
</groupId>
<artifactId>
jib-maven-plugin
</artifactId>
<version>
1.6.1
</version>
<configuration>
<from>
<image>
${baseimage}
</image>
</from>
<to>
<image>
${image}
</image>
</to>
<container>
<creationTime>
USE_CURRENT_TIMESTAMP
</creationTime>
<mainClass>
${mainClass}
</mainClass>
</container>
</configuration>
</plugin>
<plugin>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-maven-plugin
</artifactId>
<configuration>
<mainClass>
${mainClass}
</mainClass>
<includeSystemScope>
true
</includeSystemScope>
</configuration>
<executions>
<execution>
<goals>
<goal>
repackage
</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
src/main/java/vc/thinker/ProtocolProxyApplication.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.scheduling.annotation.EnableAsync
;
import
org.springframework.scheduling.annotation.EnableScheduling
;
/**
* <p>
* 服务
* </p>
*
* @author HeTongHao
* @since 2019-07-19
*/
@EnableAsync
@SpringBootApplication
@EnableScheduling
public
class
ProtocolProxyApplication
{
public
static
void
main
(
String
[]
args
)
{
SpringApplication
.
run
(
ProtocolProxyApplication
.
class
,
args
);
}
}
src/main/java/vc/thinker/absctacts/mqtt/connection/MqttCallbackImpl.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
mqtt
.
connection
;
import
com.alibaba.fastjson.JSONObject
;
import
lombok.extern.slf4j.Slf4j
;
import
org.eclipse.paho.client.mqttv3.*
;
import
org.eclipse.paho.client.mqttv3.persist.MemoryPersistence
;
import
vc.thinker.absctacts.mqtt.protocol.IMqttProtocol
;
/**
* Mqtt 回调实现
*
* @author HeTongHao
* @since 2019-10-29 16:00
*/
@Slf4j
public
class
MqttCallbackImpl
implements
MqttCallback
{
public
MqttCallbackImpl
(
MqttConnectionProperties
connectionProperties
,
IMqttProtocol
mqttProtocol
)
throws
MqttException
{
this
.
connectionProperties
=
connectionProperties
;
this
.
mqttProtocol
=
mqttProtocol
;
this
.
reconnectionInterval
=
connectionProperties
.
getReconnectionInterval
();
initMqttClient
();
}
private
final
MqttConnectionProperties
connectionProperties
;
private
final
IMqttProtocol
mqttProtocol
;
private
MqttClient
mqttClient
;
/**
* 重连时间,秒
*/
private
int
reconnectionInterval
;
@Override
public
void
connectionLost
(
Throwable
throwable
)
{
log
.
error
(
"mqtt connectionLost"
,
throwable
);
log
.
info
(
"mqtt 连接异常,{}稍后重新连接"
,
reconnectionInterval
);
try
{
Thread
.
sleep
(
reconnectionInterval
*
1000L
);
}
catch
(
InterruptedException
e
)
{
log
.
info
(
""
,
e
);
}
if
(
mqttClient
!=
null
&&
!
mqttClient
.
isConnected
())
{
try
{
mqttClient
.
close
();
}
catch
(
MqttException
e
)
{
e
.
printStackTrace
();
}
try
{
log
.
info
(
"mqtt 重新连接"
);
initMqttClient
();
}
catch
(
Exception
e
)
{
if
(
reconnectionInterval
<
connectionProperties
.
getReconnectionIntervalMax
())
{
reconnectionInterval
+=
connectionProperties
.
getReconnectionIncreasing
();
}
connectionLost
(
e
);
}
}
}
@Override
public
void
messageArrived
(
String
topic
,
MqttMessage
mqttMessage
)
{
if
(
mqttMessage
.
isRetained
())
{
return
;
}
String
q
=
new
String
(
mqttMessage
.
getPayload
());
if
(
isClientStatus
(
topic
))
{
log
.
info
(
"topic:{},payload:{}"
,
topic
,
q
);
clientConnected
(
q
);
}
else
{
mqttProtocol
.
handleMessage
(
topic
,
mqttMessage
.
getPayload
());
}
}
@Override
public
void
deliveryComplete
(
IMqttDeliveryToken
iMqttDeliveryToken
)
{
}
private
MqttClient
newMqttClient
()
throws
MqttException
{
MemoryPersistence
persistence
=
new
MemoryPersistence
();
MqttClient
mqttClient
=
new
MqttClient
(
connectionProperties
.
getBroker
()
,
connectionProperties
.
getClientId
()
+
"-"
+
System
.
currentTimeMillis
(),
persistence
);
mqttClient
.
setCallback
(
this
);
return
mqttClient
;
}
private
void
initMqttClient
()
throws
MqttException
{
this
.
mqttClient
=
newMqttClient
();
mqttProtocol
.
setMqttClient
(
mqttClient
);
connect
(
mqttClient
,
mqttProtocol
.
subscribe
());
}
/**
* 连接配制
*
* @return
*/
private
MqttConnectOptions
getConnOpts
()
{
MqttConnectOptions
connOpts
=
new
MqttConnectOptions
();
connOpts
.
setCleanSession
(
false
);
connOpts
.
setUserName
(
connectionProperties
.
getUsername
());
connOpts
.
setPassword
(
connectionProperties
.
getPassword
().
toCharArray
());
try
{
// ssl
// connOpts.setSocketFactory(SslUtil.getSocketFactory(
// ResourceUtils.getURL("classpath:").getPath() + certFile));
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
connOpts
.
setKeepAliveInterval
(
30
);
connOpts
.
setConnectionTimeout
(
60
*
5
);
connOpts
.
setCleanSession
(
true
);
connOpts
.
setAutomaticReconnect
(
true
);
return
connOpts
;
}
/**
* 判断连接状态
*
* @param topic
* @return
*/
private
boolean
isClientStatus
(
String
topic
)
{
return
topic
.
endsWith
(
"connected"
);
}
/**
* 连接
*
* @throws MqttSecurityException
* @throws MqttException
*/
private
void
connect
(
MqttClient
mqttClient
,
String
[]
topic
)
throws
MqttSecurityException
,
MqttException
{
mqttClient
.
connect
(
getConnOpts
());
mqttClient
.
subscribe
(
topic
);
log
.
info
(
"mqtt client [{}] connect [{}] Success"
,
connectionProperties
.
getClientId
(),
connectionProperties
.
getBroker
());
}
/**
* 客户端连接状态处理
*
* @param q
*/
private
void
clientConnected
(
String
q
)
{
JSONObject
session
=
JSONObject
.
parseObject
(
q
);
String
clientId
=
session
.
getString
(
"clientid"
);
if
(
session
.
containsKey
(
"ipaddress"
))
{
log
.
info
(
"{} 连接服务器"
,
clientId
);
}
else
{
log
.
info
(
"{} 断开服务器"
,
clientId
);
}
}
}
src/main/java/vc/thinker/absctacts/mqtt/connection/MqttConnectionProperties.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
mqtt
.
connection
;
import
lombok.Data
;
/**
* Mqtt连接基础信息
*
* @author xfy
* @since 2021/6/21 18:11
**/
@Data
public
class
MqttConnectionProperties
{
/**
* broker地址
*/
private
String
broker
;
/**
* 客户端id
*/
private
String
clientId
;
/**
* 用户名
*/
private
String
username
;
/**
* 密码
*/
private
String
password
;
/**
* 清除session
*/
private
boolean
cleanSession
;
/**
* 重连初始时间,秒
*/
private
int
reconnectionInterval
=
3
;
/**
* 重连时间最大值
*/
private
final
int
reconnectionIntervalMax
=
30
;
/**
* 重连时间递增
*/
private
final
int
reconnectionIncreasing
=
0
;
}
src/main/java/vc/thinker/absctacts/mqtt/entity/MqttResponse.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
mqtt
.
entity
;
import
lombok.AllArgsConstructor
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
lombok.experimental.Accessors
;
import
java.io.Serial
;
import
java.io.Serializable
;
/**
* Mqtt响应对象
*
* @author xfy
* @since 2021/6/22 18:00
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors
(
chain
=
true
)
public
class
MqttResponse
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
4548586577055536060L
;
/**
* topic
*/
private
String
topic
;
/**
* 消息体
*/
private
String
message
;
}
src/main/java/vc/thinker/absctacts/mqtt/entity/MqttResponseBytes.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
mqtt
.
entity
;
import
lombok.AllArgsConstructor
;
import
lombok.Data
;
import
lombok.NoArgsConstructor
;
import
lombok.experimental.Accessors
;
import
java.io.Serial
;
import
java.io.Serializable
;
/**
* Mqtt响应对象
*
* @author xfy
* @since 2021/6/22 18:00
**/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors
(
chain
=
true
)
public
class
MqttResponseBytes
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
4548586577055536060L
;
/**
* topic
*/
private
String
topic
;
/**
* 消息体
*/
private
byte
[]
message
;
}
src/main/java/vc/thinker/absctacts/mqtt/protocol/AbstractCommonBytesHandleMqttProtocol.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
mqtt
.
protocol
;
import
akka.actor.ActorRef
;
import
akka.actor.Props
;
import
lombok.extern.slf4j.Slf4j
;
import
vc.thinker.absctacts.mqtt.connection.MqttConnectionProperties
;
import
vc.thinker.absctacts.mqtt.entity.MqttResponseBytes
;
import
vc.thinker.absctacts.mqtt.topic.TopicDefinition
;
import
vc.thinker.absctacts.mqtt.utils.StringFormatUtils
;
/**
* 抽象的Mqtt协议
*
* @author HeTongHao
* @since 2019-10-29 16:00
*/
@Slf4j
public
abstract
class
AbstractCommonBytesHandleMqttProtocol
extends
AbstractCommonEntityHandleMqttProtocol
{
public
AbstractCommonBytesHandleMqttProtocol
(
MqttConnectionProperties
mqttConnectionProperties
)
{
super
(
mqttConnectionProperties
);
}
/**
* 处理消息
*
* @param topic 监听到消息的Topic
* @param message 监听到的消息
*/
@Override
public
void
handleMessage
(
String
topic
,
byte
[]
message
)
{
ActorRef
ref
;
try
{
ref
=
actorRefMap
.
get
(
topic
);
if
(
ref
==
null
)
{
TopicDefinition
topicDefinition
=
resolveByTopic
(
topic
);
assert
topicDefinition
!=
null
:
"未定义topic"
;
ref
=
actorSystem
.
actorOf
(
springExtensionProps
(
topicDefinition
));
actorRefMap
.
put
(
topic
,
ref
);
}
ref
.
tell
(
new
MqttResponseBytes
(
topic
,
message
),
ActorRef
.
noSender
());
}
catch
(
Exception
e
)
{
log
.
error
(
"消息处理失败,{}"
,
e
.
getMessage
());
}
}
private
Props
springExtensionProps
(
TopicDefinition
topicDefinition
)
{
return
springExtension
.
props
(
StringFormatUtils
.
classNameLowercaseFirst
(
topicDefinition
.
getActorClass
()));
}
}
src/main/java/vc/thinker/absctacts/mqtt/protocol/AbstractCommonEntityHandleMqttProtocol.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
mqtt
.
protocol
;
import
akka.actor.ActorRef
;
import
akka.actor.Props
;
import
com.google.common.collect.Maps
;
import
lombok.extern.slf4j.Slf4j
;
import
vc.thinker.absctacts.mqtt.connection.MqttConnectionProperties
;
import
vc.thinker.absctacts.mqtt.entity.MqttResponse
;
import
vc.thinker.absctacts.mqtt.topic.TopicDefinition
;
import
vc.thinker.absctacts.mqtt.utils.StringFormatUtils
;
import
java.util.Map
;
/**
* 抽象的Mqtt协议
*
* @author HeTongHao
* @since 2019-10-29 16:00
*/
@Slf4j
public
abstract
class
AbstractCommonEntityHandleMqttProtocol
extends
AbstractMqttProtocol
{
public
AbstractCommonEntityHandleMqttProtocol
(
MqttConnectionProperties
mqttConnectionProperties
)
{
super
(
mqttConnectionProperties
);
}
/**
* 当前 Topic 与Actor实例的映射
*/
protected
final
Map
<
String
,
ActorRef
>
actorRefMap
=
Maps
.
newHashMap
();
/**
* 根据topic 解析一个topic定义枚举
*
* @param topic 消息接收的topic
* @return topic定义枚举
*/
protected
abstract
TopicDefinition
resolveByTopic
(
String
topic
);
/**
* 处理消息
*
* @param topic 监听到消息的Topic
* @param message 监听到的消息
*/
@Override
public
void
handleMessage
(
String
topic
,
byte
[]
message
)
{
ActorRef
ref
;
try
{
ref
=
actorRefMap
.
get
(
topic
);
if
(
ref
==
null
)
{
TopicDefinition
topicDefinition
=
resolveByTopic
(
topic
);
assert
topicDefinition
!=
null
:
"未定义topic"
;
ref
=
actorSystem
.
actorOf
(
springExtensionProps
(
topicDefinition
));
actorRefMap
.
put
(
topic
,
ref
);
}
ref
.
tell
(
response
(
topic
,
message
),
ActorRef
.
noSender
());
}
catch
(
Exception
e
)
{
log
.
error
(
"消息处理失败,{}"
,
e
.
getMessage
());
}
}
/**
* Mqtt响应体
*
* @param topic topic
* @param message message
*/
protected
Object
response
(
String
topic
,
byte
[]
message
)
{
return
new
MqttResponse
(
topic
,
new
String
(
message
));
}
private
Props
springExtensionProps
(
TopicDefinition
topicDefinition
)
{
return
springExtension
.
props
(
StringFormatUtils
.
classNameLowercaseFirst
(
topicDefinition
.
getActorClass
()));
}
}
src/main/java/vc/thinker/absctacts/mqtt/protocol/AbstractCommonHandleMqttProtocol.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
mqtt
.
protocol
;
import
akka.actor.ActorRef
;
import
com.google.common.collect.Maps
;
import
lombok.extern.slf4j.Slf4j
;
import
vc.thinker.absctacts.mqtt.connection.MqttConnectionProperties
;
import
vc.thinker.absctacts.mqtt.topic.TopicDefinition
;
import
vc.thinker.absctacts.mqtt.utils.StringFormatUtils
;
import
java.util.Map
;
/**
* 抽象的Mqtt协议
*
* @author HeTongHao
* @since 2019-10-29 16:00
*/
@Slf4j
public
abstract
class
AbstractCommonHandleMqttProtocol
extends
AbstractMqttProtocol
{
public
AbstractCommonHandleMqttProtocol
(
MqttConnectionProperties
mqttConnectionProperties
)
{
super
(
mqttConnectionProperties
);
}
/**
* 当前 Topic 与Actor实例的映射
*/
private
final
Map
<
String
,
ActorRef
>
actorRefMap
=
Maps
.
newHashMap
();
/**
* 根据topic 解析一个topic定义枚举
*
* @param topic 消息接收的topic
* @return topic定义枚举
*/
protected
abstract
TopicDefinition
resolveByTopic
(
String
topic
);
/**
* 处理消息
*
* @param topic 监听到消息的Topic
* @param message 监听到的消息
*/
@Override
public
void
handleMessage
(
String
topic
,
byte
[]
message
)
{
ActorRef
ref
;
try
{
ref
=
actorRefMap
.
get
(
topic
);
if
(
ref
==
null
)
{
TopicDefinition
topicDefinition
=
resolveByTopic
(
topic
);
assert
topicDefinition
!=
null
:
"未定义topic"
;
ref
=
actorSystem
.
actorOf
(
springExtension
.
props
(
StringFormatUtils
.
classNameLowercaseFirst
(
topicDefinition
.
getActorClass
()))
);
actorRefMap
.
put
(
topic
,
ref
);
}
ref
.
tell
(
new
String
(
message
),
ActorRef
.
noSender
());
}
catch
(
Exception
e
)
{
log
.
error
(
"消息处理失败,{}"
,
e
.
getMessage
());
}
}
}
src/main/java/vc/thinker/absctacts/mqtt/protocol/AbstractMqttProtocol.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
mqtt
.
protocol
;
import
akka.actor.ActorSystem
;
import
org.eclipse.paho.client.mqttv3.MqttClient
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
vc.thinker.absctacts.mqtt.connection.MqttConnectionProperties
;
import
vc.thinker.absctacts.mqtt.publish.MqttCommandPush
;
import
vc.thinker.config.akka.extension.SpringExtension
;
/**
* 抽象的Mqtt协议
*
* @author HeTongHao
* @since 2019-10-29 16:00
*/
public
abstract
class
AbstractMqttProtocol
implements
IMqttProtocol
{
@Autowired
protected
ActorSystem
actorSystem
;
@Autowired
protected
SpringExtension
springExtension
;
protected
final
MqttConnectionProperties
mqttConnectionProperties
;
/**
* mqtt连接
*/
private
MqttClient
mqttClient
;
/**
* 默认mqtt推送组件
*/
private
MqttCommandPush
mqttCommandPush
;
@Override
public
MqttConnectionProperties
getProperties
()
{
return
mqttConnectionProperties
;
}
public
AbstractMqttProtocol
(
MqttConnectionProperties
mqttConnectionProperties
)
{
this
.
mqttConnectionProperties
=
mqttConnectionProperties
;
}
@Override
public
void
setMqttClient
(
MqttClient
mqttClient
)
{
this
.
mqttClient
=
mqttClient
;
this
.
mqttCommandPush
=
new
MqttCommandPush
(
mqttClient
);
}
@Override
public
MqttCommandPush
getMqttCommandPush
()
{
return
mqttCommandPush
==
null
?
mqttCommandPush
=
new
MqttCommandPush
(
mqttClient
)
:
mqttCommandPush
;
}
/**
* 处理消息
*
* @param topic 监听到消息的Topic
* @param message 监听到的消息
*/
@Override
public
abstract
void
handleMessage
(
String
topic
,
byte
[]
message
);
}
src/main/java/vc/thinker/absctacts/mqtt/protocol/AbstractNotSubscriptionMqttProtocol.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
mqtt
.
protocol
;
import
cn.hutool.core.util.IdUtil
;
import
lombok.extern.slf4j.Slf4j
;
import
vc.thinker.absctacts.mqtt.connection.MqttConnectionProperties
;
/**
* 抽象不订阅的Mqtt协议
*
* @author HeTongHao
* @since 2019-10-29 16:00
*/
@Slf4j
public
abstract
class
AbstractNotSubscriptionMqttProtocol
extends
AbstractMqttProtocol
{
public
AbstractNotSubscriptionMqttProtocol
(
MqttConnectionProperties
mqttConnectionProperties
)
{
super
(
mqttConnectionProperties
);
}
@Override
public
String
[]
subscribe
()
{
// 订阅一个不存在的Topic 防止启动报错
return
new
String
[]{
IdUtil
.
randomUUID
()};
}
@Override
public
void
handleMessage
(
String
topic
,
byte
[]
message
)
{
}
}
src/main/java/vc/thinker/absctacts/mqtt/protocol/IMqttProtocol.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
mqtt
.
protocol
;
import
org.eclipse.paho.client.mqttv3.MqttClient
;
import
vc.thinker.absctacts.mqtt.connection.MqttConnectionProperties
;
import
vc.thinker.absctacts.mqtt.publish.MqttCommandPush
;
/**
* mqtt 协议
*
* @author HeTongHao
* @since 2019-10-29 16:00
*/
public
interface
IMqttProtocol
{
/**
* 订阅Topic列表
*
* @return Topic列表
*/
String
[]
subscribe
();
/**
* 处理业务消息
*
* @param topic 监听到消息的Topic
* @param message 监听到的消息
*/
void
handleMessage
(
String
topic
,
byte
[]
message
);
/**
* 得到消息推送
*
* @return 可以实现Mqtt消息推送
*/
MqttCommandPush
getMqttCommandPush
();
/**
* 设置这个协议对应的连接
*
* @param mqttClient Mqtt连接
*/
void
setMqttClient
(
MqttClient
mqttClient
);
/**
* 获取Mqtt连接配置
*
* @return MqttConnectionProperties
*/
MqttConnectionProperties
getProperties
();
}
src/main/java/vc/thinker/absctacts/mqtt/publish/ConcurrentKeyMqttPushService.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
mqtt
.
publish
;
import
akka.actor.ActorRef
;
import
akka.actor.ActorSystem
;
import
com.google.common.collect.Maps
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
vc.thinker.absctacts.mqtt.topic.TopicDefinition
;
import
vc.thinker.absctacts.mqtt.utils.StringFormatUtils
;
import
vc.thinker.config.akka.extension.SpringExtension
;
import
java.util.Map
;
/**
* @author HeTongHao
* @since 2021/7/9 14:35
*/
public
class
ConcurrentKeyMqttPushService
{
@Autowired
protected
ActorSystem
actorSystem
;
@Autowired
protected
SpringExtension
springExtension
;
/**
* topic 与actor映射
*/
protected
final
Map
<
String
,
ActorRef
>
topicDefinitionActorRefMap
=
Maps
.
newConcurrentMap
();
public
ActorRef
getActorRef
(
TopicDefinition
topicDefinition
,
String
key
)
{
return
topicDefinitionActorRefMap
.
computeIfAbsent
(
topicDefinition
+
key
,
k
->
actorSystem
.
actorOf
(
springExtension
.
props
(
StringFormatUtils
.
classNameLowercaseFirst
(
topicDefinition
.
getActorClass
()))));
}
public
void
push
(
TopicDefinition
topicDefinition
,
String
key
,
Object
message
)
{
getActorRef
(
topicDefinition
,
key
).
tell
(
message
,
ActorRef
.
noSender
());
}
}
src/main/java/vc/thinker/absctacts/mqtt/publish/MqttCommandPush.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
mqtt
.
publish
;
import
lombok.extern.slf4j.Slf4j
;
import
org.eclipse.paho.client.mqttv3.MqttClient
;
import
org.eclipse.paho.client.mqttv3.MqttException
;
import
org.eclipse.paho.client.mqttv3.MqttMessage
;
/**
* mqtt 指令发送
*
* @author HeTongHao
* @since 2019-10-29 16:00
*/
@Slf4j
public
class
MqttCommandPush
{
public
MqttCommandPush
(
MqttClient
mqttClient
)
{
this
.
mqttClient
=
mqttClient
;
}
private
final
MqttClient
mqttClient
;
public
MqttClient
getMqttClient
()
{
return
mqttClient
;
}
public
void
sendMqttMessage
(
String
topic
,
byte
[]
payload
)
{
MqttMessage
message
=
new
MqttMessage
();
message
.
setPayload
(
payload
);
message
.
setQos
(
1
);
message
.
setRetained
(
false
);
try
{
if
(
mqttClient
==
null
)
{
log
.
error
(
"命令推送失败 mqttClient is null"
);
}
else
if
(
mqttClient
.
isConnected
())
{
mqttClient
.
publish
(
topic
,
message
);
}
else
{
mqttClient
.
connect
();
mqttClient
.
publish
(
topic
,
message
);
}
}
catch
(
MqttException
e
)
{
e
.
printStackTrace
();
}
}
}
src/main/java/vc/thinker/absctacts/mqtt/publish/TopicMqttPushService.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
mqtt
.
publish
;
import
akka.actor.ActorRef
;
import
akka.actor.ActorSystem
;
import
com.google.common.collect.Maps
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
vc.thinker.absctacts.mqtt.topic.TopicDefinition
;
import
vc.thinker.absctacts.mqtt.utils.StringFormatUtils
;
import
vc.thinker.config.akka.extension.SpringExtension
;
import
java.util.Map
;
/**
* @author HeTongHao
* @since 2021/7/9 14:35
*/
public
class
TopicMqttPushService
{
@Autowired
protected
ActorSystem
actorSystem
;
@Autowired
protected
SpringExtension
springExtension
;
/**
* topic 与actor映射
*/
protected
final
Map
<
TopicDefinition
,
ActorRef
>
topicDefinitionActorRefMap
=
Maps
.
newConcurrentMap
();
public
ActorRef
getActorRef
(
TopicDefinition
topicDefinition
)
{
return
topicDefinitionActorRefMap
.
computeIfAbsent
(
topicDefinition
,
k
->
actorSystem
.
actorOf
(
springExtension
.
props
(
StringFormatUtils
.
classNameLowercaseFirst
(
k
.
getActorClass
()))));
}
public
void
push
(
TopicDefinition
topicDefinition
,
Object
message
)
{
getActorRef
(
topicDefinition
).
tell
(
message
,
ActorRef
.
noSender
());
}
}
src/main/java/vc/thinker/absctacts/mqtt/topic/TopicDefinition.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
mqtt
.
topic
;
/**
* topic定义
*
* @author HeTongHao
* @since 2021/7/9 14:13
*/
public
interface
TopicDefinition
{
/**
* topic定义
*
* @return topic定义
*/
String
getTopic
();
/**
* 对应处理该topic的actor
*
* @return 对应处理该topic的actor
*/
Class
<?>
getActorClass
();
}
src/main/java/vc/thinker/absctacts/mqtt/utils/SslUtil.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
mqtt
.
utils
;
import
org.bouncycastle.jce.provider.BouncyCastleProvider
;
import
org.bouncycastle.openssl.PEMReader
;
import
org.bouncycastle.openssl.PasswordFinder
;
import
javax.net.ssl.KeyManagerFactory
;
import
javax.net.ssl.SSLContext
;
import
javax.net.ssl.SSLSocketFactory
;
import
javax.net.ssl.TrustManagerFactory
;
import
java.io.ByteArrayInputStream
;
import
java.io.InputStreamReader
;
import
java.nio.file.Files
;
import
java.nio.file.Paths
;
import
java.security.KeyPair
;
import
java.security.KeyStore
;
import
java.security.Security
;
import
java.security.cert.X509Certificate
;
public
class
SslUtil
{
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
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
(
crtFile
)))));
X509Certificate
cert
=
(
X509Certificate
)
reader
.
readObject
();
reader
.
close
();
// load client private 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
();
// 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
(
TrustManagerFactory
.
getDefaultAlgorithm
());
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"
);
context
.
init
(
kmf
.
getKeyManagers
(),
tmf
.
getTrustManagers
(),
null
);
return
context
.
getSocketFactory
();
}
public
static
SSLSocketFactory
getSocketFactory
(
final
String
caCrtFile
)
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
();
// 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
(
TrustManagerFactory
.
getDefaultAlgorithm
());
tmf
.
init
(
caKs
);
// finally, create SSL socket factory
SSLContext
context
=
SSLContext
.
getInstance
(
"TLSv1"
);
context
.
init
(
null
,
tmf
.
getTrustManagers
(),
null
);
return
context
.
getSocketFactory
();
}
}
\ No newline at end of file
src/main/java/vc/thinker/absctacts/mqtt/utils/StringFormatUtils.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
mqtt
.
utils
;
import
org.slf4j.helpers.MessageFormatter
;
/**
* String格式化简化操作类
*
* @author HeTongHao
* @since 2019-08-27 10:59
*/
public
class
StringFormatUtils
{
/**
* 用{}作为占位符,格式化字符串
*
* @param format
* @param argArray
* @return
*/
public
static
String
format
(
String
format
,
Object
...
argArray
)
{
return
MessageFormatter
.
arrayFormat
(
format
,
argArray
).
getMessage
();
}
/**
* 首字母小写
*
* @param str
* @return
*/
public
static
String
lowercaseFirst
(
String
str
)
{
String
firstChar
=
str
.
substring
(
0
,
1
);
return
str
.
replaceFirst
(
firstChar
,
firstChar
.
toLowerCase
());
}
/**
* 类名首字母小写
*
* @param clazz
* @return
*/
public
static
String
classNameLowercaseFirst
(
Class
clazz
)
{
return
lowercaseFirst
(
clazz
.
getSimpleName
());
}
}
src/main/java/vc/thinker/absctacts/protocolproxy/dto/IMeterReportEntity.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
dto
;
import
vc.thinker.absctacts.protocolproxy.enums.IMeterDataDefine
;
import
java.time.LocalDateTime
;
import
java.util.Map
;
/**
* @author HeTongHao
* @since 2021/7/9 17:08
*/
public
interface
IMeterReportEntity
{
/**
* 设备唯一code
*
* @return 设备唯一code
*/
String
getDeviceCode
();
/**
* 数据采集时间
*
* @return 数据采集时间
*/
LocalDateTime
getCollectTime
();
/**
* 数据上报集
*
* @return 数据上报集
*/
Map
<
IMeterDataDefine
,
Object
>
getDataMap
();
}
src/main/java/vc/thinker/absctacts/protocolproxy/dto/IServiceExecuteCmd.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
dto
;
import
vc.thinker.absctacts.protocolproxy.enums.DataType
;
import
vc.thinker.absctacts.protocolproxy.enums.service.IServiceParamDefine
;
import
java.util.Map
;
/**
* 服务执行命令
*
* @author HeTongHao
* @since 2021/7/9 17:08
*/
public
interface
IServiceExecuteCmd
{
/**
* 流水号id
*
* @return 流水号id
*/
String
getRequestId
();
/**
* 设备唯一code
*
* @return 设备唯一code
*/
String
getDeviceCode
();
/**
* 服务编号
*
* @return 服务编号
*/
String
getServiceCode
();
/**
* 参数集合
*
* @return 参数集合
*/
Map
<
String
,
Object
>
getParams
();
/**
* 参数集合
*
* @param paramDefine 参数定义
* @return 参数集合
*/
default
<
T
>
T
getParamValue
(
IServiceParamDefine
paramDefine
)
{
Object
result
=
this
.
getParams
().
get
(
paramDefine
.
getCode
());
if
(
result
instanceof
String
)
{
if
(
DataType
.
Int
.
equals
(
paramDefine
.
getDataType
()))
{
result
=
Integer
.
valueOf
((
String
)
result
);
}
else
if
(
DataType
.
Float
.
equals
(
paramDefine
.
getDataType
()))
{
result
=
Float
.
valueOf
((
String
)
result
);
}
}
return
(
T
)
result
;
}
}
src/main/java/vc/thinker/absctacts/protocolproxy/dto/IServiceExecuteResult.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
dto
;
import
vc.thinker.absctacts.protocolproxy.enums.ServiceExecuteResultType
;
/**
* 服务执行结果
*
* @author HeTongHao
* @since 2021/7/9 17:08
*/
public
interface
IServiceExecuteResult
{
/**
* 流水号id
*
* @return 流水号id
*/
String
getRequestId
();
/**
* get结果类型
*
* @return 结果类型
*/
ServiceExecuteResultType
getType
();
/**
* 消息
*
* @return 执行结果消息
*/
String
getMessage
();
}
src/main/java/vc/thinker/absctacts/protocolproxy/dto/MeterInfo.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
dto
;
import
lombok.Builder
;
import
lombok.Getter
;
/**
* 仪表信息
*
* @author HeTongHao
* @since 2022/8/19 15:59
*/
@Getter
@Builder
public
class
MeterInfo
{
private
String
id
;
private
String
code
;
}
src/main/java/vc/thinker/absctacts/protocolproxy/dto/MeterReportEntity.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
dto
;
import
com.google.common.collect.Maps
;
import
lombok.Getter
;
import
vc.thinker.absctacts.protocolproxy.enums.IMeterDataDefine
;
import
java.time.LocalDateTime
;
import
java.util.Map
;
/**
* @author HeTongHao
* @since 2021/7/9 17:47
*/
@Getter
public
class
MeterReportEntity
implements
IMeterReportEntity
{
private
MeterReportEntity
(
String
deviceCode
,
LocalDateTime
collectTime
,
Map
<
IMeterDataDefine
,
Object
>
dataMap
)
{
this
.
deviceCode
=
deviceCode
;
this
.
collectTime
=
collectTime
;
this
.
dataMap
=
dataMap
;
}
private
final
String
deviceCode
;
private
final
LocalDateTime
collectTime
;
private
final
Map
<
IMeterDataDefine
,
Object
>
dataMap
;
public
static
MeterReportEntityBuilder
builder
(
String
deviceId
,
LocalDateTime
collectTime
)
{
return
new
MeterReportEntityBuilder
(
deviceId
,
collectTime
);
}
public
static
class
MeterReportEntityBuilder
{
private
MeterReportEntityBuilder
(
String
deviceId
,
LocalDateTime
collectTime
)
{
this
.
deviceId
=
deviceId
;
this
.
collectTime
=
collectTime
;
}
private
final
String
deviceId
;
private
final
LocalDateTime
collectTime
;
private
final
Map
<
IMeterDataDefine
,
Object
>
dataMap
=
Maps
.
newConcurrentMap
();
public
<
DD
extends
IMeterDataDefine
>
MeterReportEntityBuilder
putValue
(
DD
dataDefine
,
Object
value
)
{
putData
(
dataDefine
,
value
);
return
this
;
}
public
<
DD
extends
IMeterDataDefine
>
MeterReportEntityBuilder
putValues
(
Map
<
DD
,
Object
>
dataDefineAndValueMap
)
{
dataDefineAndValueMap
.
forEach
(
this
::
putData
);
return
this
;
}
private
<
DD
extends
IMeterDataDefine
>
void
putData
(
DD
dataDefine
,
Object
value
)
{
dataMap
.
put
(
dataDefine
,
value
);
}
public
MeterReportEntity
build
()
{
return
new
MeterReportEntity
(
deviceId
,
collectTime
,
dataMap
);
}
}
}
src/main/java/vc/thinker/absctacts/protocolproxy/dto/ServiceExecuteCmd.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
dto
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
import
java.util.Map
;
/**
* 服务执行命令
*
* @author HeTongHao
* @since 2021/7/9 17:47
*/
@Getter
@AllArgsConstructor
public
class
ServiceExecuteCmd
implements
IServiceExecuteCmd
{
private
final
String
requestId
;
private
final
String
deviceCode
;
private
final
String
serviceCode
;
private
final
Map
<
String
,
Object
>
params
;
}
src/main/java/vc/thinker/absctacts/protocolproxy/dto/ServiceExecuteResult.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
dto
;
import
lombok.Getter
;
import
vc.thinker.absctacts.protocolproxy.enums.ServiceExecuteResultType
;
/**
* 服务执行结果
*
* @author HeTongHao
* @since 2021/8/11 17:47
*/
@Getter
public
class
ServiceExecuteResult
implements
IServiceExecuteResult
{
private
ServiceExecuteResult
(
String
requestId
,
ServiceExecuteResultType
type
,
String
message
)
{
this
.
requestId
=
requestId
;
this
.
type
=
type
;
this
.
message
=
message
;
}
private
final
String
requestId
;
private
final
ServiceExecuteResultType
type
;
private
final
String
message
;
public
static
ServiceExecuteResult
ok
(
IServiceExecuteCmd
cmd
)
{
return
new
ServiceExecuteResult
(
cmd
.
getRequestId
(),
ServiceExecuteResultType
.
ok
,
ServiceExecuteResultType
.
ok
.
getName
());
}
public
static
ServiceExecuteResult
fail
(
IServiceExecuteCmd
cmd
)
{
return
new
ServiceExecuteResult
(
cmd
.
getRequestId
(),
ServiceExecuteResultType
.
fail
,
ServiceExecuteResultType
.
fail
.
getName
());
}
public
static
ServiceExecuteResult
fail
(
IServiceExecuteCmd
cmd
,
String
message
)
{
return
new
ServiceExecuteResult
(
cmd
.
getRequestId
(),
ServiceExecuteResultType
.
fail
,
message
);
}
}
src/main/java/vc/thinker/absctacts/protocolproxy/enums/DataType.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
enums
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
/**
* 写入数据格式
*
* @author HeTongHao
* @since 2021/7/9 16:20
*/
@Getter
@AllArgsConstructor
public
enum
DataType
{
/**
* 整形
*/
Int
(
"整形"
),
/**
* 浮点型
*/
Float
(
"浮点型"
),
;
/**
* 类型名称
*/
private
final
String
name
;
}
src/main/java/vc/thinker/absctacts/protocolproxy/enums/IMeterAttrDefine.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
enums
;
/**
* 属性定义 枚举
*
* @author HeTongHao
* @since 2021/7/9 16:38
*/
public
interface
IMeterAttrDefine
extends
IMeterDataDefine
{
/**
* 数据类型
*
* @return 数据类型
*/
DataType
getDataType
();
}
src/main/java/vc/thinker/absctacts/protocolproxy/enums/IMeterDataDefine.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
enums
;
/**
* 数据项定义 枚举
*
* @author HeTongHao
* @since 2021/7/9 16:38
*/
public
interface
IMeterDataDefine
{
/**
* 数据编号
*
* @return 数据编号
*/
String
getCode
();
}
src/main/java/vc/thinker/absctacts/protocolproxy/enums/IMeterEventDefine.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
enums
;
/**
* 事件定义 枚举
*
* @author HeTongHao
* @since 2021/7/9 16:38
*/
public
interface
IMeterEventDefine
extends
IMeterDataDefine
{
}
src/main/java/vc/thinker/absctacts/protocolproxy/enums/IProtocolType.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
enums
;
/**
* 协议类型
*
* @author HeTongHao
* @since 2021/7/17 13:24
*/
public
interface
IProtocolType
{
/**
* 协议编号
*
* @return 协议编号
*/
String
getCode
();
/**
* 协议名称
*
* @return 协议名称
*/
String
getName
();
}
src/main/java/vc/thinker/absctacts/protocolproxy/enums/ServiceExecuteResultType.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
enums
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
/**
* 服务执行结果类型
*
* @author HeTongHao
* @since 2022/8/11 18:26
*/
@Getter
@AllArgsConstructor
public
enum
ServiceExecuteResultType
{
/**
* 服务执行结果类型
*/
ok
(
"执行成功"
),
fail
(
"执行失败"
),
;
private
final
String
name
;
}
src/main/java/vc/thinker/absctacts/protocolproxy/enums/service/IMeterServiceDefine.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
enums
.
service
;
import
java.util.List
;
/**
* 服务定义
*
* @author HeTongHao
* @since 2021/7/9 16:38
*/
public
interface
IMeterServiceDefine
{
/**
* 服务编号
*
* @return 服务编号
*/
String
getCode
();
/**
* 获取参数定义
*
* @return 参数定义
*/
List
<
IServiceParamDefine
>
getParamDefines
();
}
src/main/java/vc/thinker/absctacts/protocolproxy/enums/service/IServiceParamDefine.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
enums
.
service
;
import
vc.thinker.absctacts.protocolproxy.enums.DataType
;
/**
* 服务参数定义
*
* @author HeTongHao
* @since 2021/11/24 17:09
*/
public
interface
IServiceParamDefine
{
/**
* 覆盖,编号默认取枚举的名称
*
* @return 枚举的名称
*/
String
getCode
();
/**
* 参数数据类型
*
* @return 参数数据类型
*/
DataType
getDataType
();
}
src/main/java/vc/thinker/absctacts/protocolproxy/enums/service/NoParam.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
enums
.
service
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
import
vc.thinker.absctacts.protocolproxy.enums.DataType
;
/**
* 无参定义
*
* @author HeTongHao
* @since 2022/8/11 17:11
*/
@Getter
@AllArgsConstructor
public
enum
NoParam
implements
IServiceParamDefine
{
/**
* 无参定义
*/
Instance
(
"NoParam"
,
null
);
private
final
String
code
;
private
final
DataType
dataType
;
}
src/main/java/vc/thinker/absctacts/protocolproxy/enums/service/ParamDefine.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
enums
.
service
;
import
lombok.Getter
;
import
vc.thinker.absctacts.protocolproxy.enums.DataType
;
/**
* 参数定义
*
* @author HeTongHao
* @since 2022/8/11 17:11
*/
@Getter
public
class
ParamDefine
implements
IServiceParamDefine
{
private
ParamDefine
(
String
code
,
DataType
dataType
)
{
this
.
code
=
code
;
this
.
dataType
=
dataType
;
}
private
final
String
code
;
private
final
DataType
dataType
;
public
static
ParamDefine
build
(
String
code
,
DataType
dataType
)
{
return
new
ParamDefine
(
code
,
dataType
);
}
}
src/main/java/vc/thinker/absctacts/protocolproxy/exception/VerifyException.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
exception
;
import
vc.thinker.utils.StringFormaterUtils
;
/**
* @author HeTongHao
* @since 2021/7/16 17:42
*/
public
class
VerifyException
extends
Exception
{
public
VerifyException
(
String
message
)
{
super
(
message
);
}
public
VerifyException
(
String
message
,
Object
...
argArray
)
{
super
(
StringFormaterUtils
.
format
(
message
,
argArray
));
}
}
src/main/java/vc/thinker/absctacts/protocolproxy/exceptions/ExecTimeoutException.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
exceptions
;
/**
* 执行超时
*
* @author HeTongHao
* @since 2022/9/3 17:07
*/
public
class
ExecTimeoutException
extends
RuntimeException
{
public
ExecTimeoutException
()
{
}
public
ExecTimeoutException
(
String
message
)
{
super
(
message
);
}
public
ExecTimeoutException
(
String
message
,
Throwable
cause
)
{
super
(
message
,
cause
);
}
public
ExecTimeoutException
(
Throwable
cause
)
{
super
(
cause
);
}
}
src/main/java/vc/thinker/absctacts/protocolproxy/exceptions/MeterCodeFormatException.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
exceptions
;
/**
* 仪表编号格式异常
*
* @author HeTongHao
* @since 2022/9/1 17:34
*/
public
class
MeterCodeFormatException
extends
IllegalArgumentException
{
public
MeterCodeFormatException
(
String
message
)
{
super
(
message
);
}
public
MeterCodeFormatException
(
String
message
,
Throwable
cause
)
{
super
(
message
,
cause
);
}
public
MeterCodeFormatException
(
Throwable
cause
)
{
super
(
cause
);
}
}
src/main/java/vc/thinker/absctacts/protocolproxy/exceptions/MeterOfflineException.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
exceptions
;
/**
* 离线异常
*
* @author HeTongHao
* @since 2022/9/1 17:34
*/
public
class
MeterOfflineException
extends
RuntimeException
{
public
MeterOfflineException
(
String
message
)
{
super
(
message
);
}
public
MeterOfflineException
(
String
message
,
Throwable
cause
)
{
super
(
message
,
cause
);
}
public
MeterOfflineException
(
Throwable
cause
)
{
super
(
cause
);
}
}
src/main/java/vc/thinker/absctacts/protocolproxy/exceptions/ServiceExecTimeoutException.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
exceptions
;
/**
* 服务执行超时
*
* @author HeTongHao
* @since 2022/9/3 17:07
*/
public
class
ServiceExecTimeoutException
extends
ExecTimeoutException
{
public
ServiceExecTimeoutException
()
{
}
public
ServiceExecTimeoutException
(
String
message
)
{
super
(
message
);
}
public
ServiceExecTimeoutException
(
String
message
,
Throwable
cause
)
{
super
(
message
,
cause
);
}
public
ServiceExecTimeoutException
(
Throwable
cause
)
{
super
(
cause
);
}
}
src/main/java/vc/thinker/absctacts/protocolproxy/protocol/AbstractThirdPartyProtocol.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
protocol
;
import
com.google.common.collect.Lists
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
vc.thinker.absctacts.protocolproxy.dto.IMeterReportEntity
;
import
vc.thinker.absctacts.protocolproxy.dto.IServiceExecuteCmd
;
import
vc.thinker.absctacts.protocolproxy.dto.IServiceExecuteResult
;
import
vc.thinker.absctacts.protocolproxy.dto.ServiceExecuteResult
;
import
vc.thinker.absctacts.protocolproxy.enums.IMeterAttrDefine
;
import
vc.thinker.absctacts.protocolproxy.enums.IMeterEventDefine
;
import
vc.thinker.mqtt.proxyclient.entity.up.MeterData
;
import
vc.thinker.mqtt.proxyclient.entity.up.ThirdPartyProxyReport
;
import
vc.thinker.mqtt.proxyclient.service.ThirdPartyProxyClientService
;
import
vc.thinker.utils.LocalDateTimeUtils
;
import
java.util.List
;
import
java.util.stream.Collectors
;
/**
* 第三方协议
*
* @author HeTongHao
* @since 2021/7/9 16:20
*/
@Slf4j
public
abstract
class
AbstractThirdPartyProtocol
implements
IThirdPartyProtocol
{
@Autowired
protected
ThirdPartyProxyClientService
thirdPartyProxyClientService
;
@Override
public
void
report
(
List
<
IMeterReportEntity
>
meterReportEntityList
)
{
thirdPartyProxyClientService
.
report
(
new
ThirdPartyProxyReport
(
protocolType
().
getCode
()
,
meterReportEntityList
.
stream
()
.
map
(
this
::
meterReportEntityToMeterData
)
.
collect
(
Collectors
.
toList
())
)
);
}
/**
* 单组数据上报
*
* @param meterReportEntity meterReportEntity
*/
public
void
report
(
IMeterReportEntity
meterReportEntity
)
{
report
(
Lists
.
newArrayList
(
meterReportEntity
));
}
private
MeterData
meterReportEntityToMeterData
(
IMeterReportEntity
meterReportEntity
)
{
MeterData
meterData
=
new
MeterData
()
.
setDeviceCode
(
meterReportEntity
.
getDeviceCode
())
.
setTimestamp
(
LocalDateTimeUtils
.
parseToTimestamp
(
meterReportEntity
.
getCollectTime
()));
meterReportEntity
.
getDataMap
().
forEach
((
dataDefine
,
value
)
->
{
if
(
dataDefine
instanceof
IMeterAttrDefine
)
{
IMeterAttrDefine
meterAttrDefine
=
(
IMeterAttrDefine
)
dataDefine
;
meterData
.
putAttrData
(
meterAttrDefine
.
getCode
(),
value
);
}
else
if
(
dataDefine
instanceof
IMeterEventDefine
)
{
IMeterEventDefine
meterEventDefine
=
(
IMeterEventDefine
)
dataDefine
;
if
(
value
instanceof
Boolean
)
{
value
=
(
Boolean
)
value
?
1
:
0
;
}
meterData
.
putEventData
(
meterEventDefine
.
getCode
(),
value
);
}
});
return
meterData
;
}
@Override
public
IServiceExecuteResult
onExecutiveService
(
IServiceExecuteCmd
cmd
)
{
return
ServiceExecuteResult
.
fail
(
cmd
,
"未实现任何服务"
);
}
}
src/main/java/vc/thinker/absctacts/protocolproxy/protocol/AbstractThirdPartyProtocolSyncMeterInfo.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
protocol
;
import
cn.hutool.core.thread.ThreadUtil
;
import
com.google.common.collect.Maps
;
import
lombok.extern.slf4j.Slf4j
;
import
vc.thinker.absctacts.protocolproxy.dto.MeterInfo
;
import
vc.thinker.mqtt.proxyclient.entity.down.PlateFormMeterInfo
;
import
javax.annotation.PostConstruct
;
import
java.util.Collection
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeoutException
;
import
java.util.stream.Collectors
;
/**
* 第三方协议
*
* @author HeTongHao
* @since 2022/8/19 16:20
*/
@Slf4j
public
abstract
class
AbstractThirdPartyProtocolSyncMeterInfo
extends
AbstractThirdPartyProtocol
implements
IThirdPartyProtocolSyncMeterInfo
{
private
final
Map
<
String
,
MeterInfo
>
idMeterMap
=
Maps
.
newConcurrentMap
();
@PostConstruct
protected
void
initMeterList
()
{
ThreadUtil
.
execute
(()
->
{
int
retryCount
=
0
;
do
{
try
{
pullMeterList
();
return
;
}
catch
(
TimeoutException
e
)
{
log
.
warn
(
"[{}]协议拉取仪表超时,第{}次重试中..."
,
protocolType
().
getName
(),
++
retryCount
);
try
{
TimeUnit
.
SECONDS
.
sleep
(
10
);
}
catch
(
InterruptedException
ex
)
{
ex
.
printStackTrace
();
}
}
}
while
(
true
);
});
}
public
synchronized
Collection
<
MeterInfo
>
getMetes
()
{
return
idMeterMap
.
values
();
}
@Override
public
boolean
pullMeterList
()
throws
TimeoutException
{
try
{
List
<
PlateFormMeterInfo
>
plateFormMeterInfos
=
thirdPartyProxyClientService
.
pullMeterList
(
protocolType
().
getCode
());
Map
<
String
,
MeterInfo
>
idMeterMap
=
plateFormMeterInfos
.
stream
()
.
map
(
plateFormMeterInfo
->
MeterInfo
.
builder
()
.
id
(
plateFormMeterInfo
.
getId
())
.
code
(
plateFormMeterInfo
.
getCode
())
.
build
()
)
.
collect
(
Collectors
.
toMap
(
MeterInfo:
:
getId
,
meterInfo
->
meterInfo
));
synchronized
(
this
)
{
this
.
idMeterMap
.
clear
();
this
.
idMeterMap
.
putAll
(
idMeterMap
);
return
true
;
}
}
catch
(
TimeoutException
e
)
{
throw
e
;
}
catch
(
Exception
e
)
{
log
.
error
(
"[{}]协议拉取仪表异常:{}"
,
protocolType
().
getName
(),
e
.
getMessage
());
e
.
printStackTrace
();
return
false
;
}
}
@Override
public
void
putMeter
(
MeterInfo
meterInfo
)
{
this
.
idMeterMap
.
put
(
meterInfo
.
getId
(),
meterInfo
);
}
@Override
public
void
deleteMeter
(
String
id
)
{
this
.
idMeterMap
.
remove
(
id
);
}
}
src/main/java/vc/thinker/absctacts/protocolproxy/protocol/IThirdPartyProtocol.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
protocol
;
import
vc.thinker.absctacts.protocolproxy.dto.IMeterReportEntity
;
import
vc.thinker.absctacts.protocolproxy.dto.IServiceExecuteCmd
;
import
vc.thinker.absctacts.protocolproxy.dto.IServiceExecuteResult
;
import
vc.thinker.absctacts.protocolproxy.enums.IProtocolType
;
import
java.util.List
;
/**
* 第三方协议
*
* @author HeTongHao
* @since 2021/7/9 16:20
*/
public
interface
IThirdPartyProtocol
{
/**
* 协议类型
*
* @return 协议类型
*/
IProtocolType
protocolType
();
/**
* 上报一个或多个仪表的数据
*
* @param meterReportEntityList 仪表上报实体列表
*/
void
report
(
List
<
IMeterReportEntity
>
meterReportEntityList
);
/**
* 接受执行服务
*
* @param serviceExecuteCmd 服务执行命令
* @return 服务执行结果
*/
IServiceExecuteResult
onExecutiveService
(
IServiceExecuteCmd
serviceExecuteCmd
);
}
src/main/java/vc/thinker/absctacts/protocolproxy/protocol/IThirdPartyProtocolSyncMeterInfo.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
absctacts
.
protocolproxy
.
protocol
;
import
vc.thinker.absctacts.protocolproxy.dto.MeterInfo
;
import
java.util.concurrent.TimeoutException
;
/**
* 第三方协议
* 支持同步仪表信息,让代理及时更新需要采集的仪表列表
*
* @author HeTongHao
* @since 2022/8/19 16:20
*/
public
interface
IThirdPartyProtocolSyncMeterInfo
extends
IThirdPartyProtocol
{
/**
* 拉取仪表列表
*
* @return 仪表列表
* @throws TimeoutException 拉取超时
*/
boolean
pullMeterList
()
throws
TimeoutException
;
/**
* 更新仪表
*
* @param meterInfo 设备信息
*/
void
putMeter
(
MeterInfo
meterInfo
);
/**
* 删除仪表
*
* @param id 设备唯一id
*/
void
deleteMeter
(
String
id
);
}
src/main/java/vc/thinker/config/akka/AkkaConfig.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
config
.
akka
;
import
akka.actor.ActorSystem
;
import
com.typesafe.config.Config
;
import
com.typesafe.config.ConfigFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Lazy
;
import
vc.thinker.config.akka.extension.SpringExtension
;
import
vc.thinker.utils.SpringContextHolder
;
/**
* @author : xieshaojun
* @date : 2023/1/3 17:47
*/
@Configuration
public
class
AkkaConfig
{
@Autowired
private
ApplicationContext
applicationContext
;
@Bean
@Lazy
(
false
)
public
SpringContextHolder
springContextHolder
()
{
return
new
SpringContextHolder
();
}
/**
* Akka配置
*
* @return
*/
@Bean
public
Config
akkaConfiguration
()
{
return
ConfigFactory
.
load
();
}
/**
* spring 集成Akka
*
* @return
*/
@Bean
public
SpringExtension
springExtension
()
{
return
new
SpringExtension
();
}
/**
* Actor system singleton for this application.
*/
@Bean
public
ActorSystem
actorSystem
()
{
ActorSystem
system
=
ActorSystem
.
create
(
"AkkaTaskProcessing"
,
akkaConfiguration
());
springExtension
().
initialize
(
applicationContext
);
return
system
;
}
}
src/main/java/vc/thinker/config/akka/extension/SpringActorProducer.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
config
.
akka
.
extension
;
import
akka.actor.Actor
;
import
akka.actor.IndirectActorProducer
;
import
org.springframework.context.ApplicationContext
;
/**
* @author : xieshaojun
* @date : 2023/1/3 17:48
*/
public
class
SpringActorProducer
implements
IndirectActorProducer
{
private
final
ApplicationContext
applicationContext
;
private
final
String
actorBeanName
;
private
Object
arg0
;
public
SpringActorProducer
(
ApplicationContext
applicationContext
,
String
actorBeanName
)
{
this
.
applicationContext
=
applicationContext
;
this
.
actorBeanName
=
actorBeanName
;
}
public
SpringActorProducer
(
ApplicationContext
applicationContext
,
String
actorBeanName
,
Object
arg0
)
{
this
.
applicationContext
=
applicationContext
;
this
.
actorBeanName
=
actorBeanName
;
this
.
arg0
=
arg0
;
}
@Override
public
Actor
produce
()
{
return
arg0
!=
null
?
(
Actor
)
applicationContext
.
getBean
(
actorBeanName
,
arg0
)
:
(
Actor
)
applicationContext
.
getBean
(
actorBeanName
);
}
@Override
public
Class
<?
extends
Actor
>
actorClass
()
{
return
(
Class
<?
extends
Actor
>)
applicationContext
.
getType
(
actorBeanName
);
}
}
\ No newline at end of file
src/main/java/vc/thinker/config/akka/extension/SpringExtension.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
config
.
akka
.
extension
;
import
akka.actor.Extension
;
import
akka.actor.Props
;
import
org.springframework.context.ApplicationContext
;
/**
* @author : xieshaojun
* @date : 2023/1/3 17:48
*/
public
class
SpringExtension
implements
Extension
{
private
ApplicationContext
applicationContext
;
/**
* Used to initialize the Spring application context for the extension.
*/
public
void
initialize
(
ApplicationContext
applicationContext
)
{
this
.
applicationContext
=
applicationContext
;
}
/**
* Create a Props for the specified actorBeanName using the SpringActorProducer
* class.
*/
public
Props
props
(
String
actorBeanName
,
Object
arg0
)
{
return
Props
.
create
(
SpringActorProducer
.
class
,
applicationContext
,
actorBeanName
,
arg0
);
}
public
Props
props
(
String
actorBeanName
)
{
return
Props
.
create
(
SpringActorProducer
.
class
,
applicationContext
,
actorBeanName
);
}
}
src/main/java/vc/thinker/exception/ExceptionAdvice.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
exception
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.validation.BindException
;
import
org.springframework.validation.FieldError
;
import
org.springframework.web.bind.MethodArgumentNotValidException
;
import
org.springframework.web.bind.annotation.ExceptionHandler
;
import
org.springframework.web.bind.annotation.ResponseStatus
;
import
org.springframework.web.bind.annotation.RestController
;
import
org.springframework.web.bind.annotation.RestControllerAdvice
;
import
vc.thinker.response.AbstractResponse
;
import
vc.thinker.response.SimpleResponse
;
import
java.util.List
;
/**
* @author : xieshaojun
* @date : 2023/1/3 15:21
*/
@RestControllerAdvice
(
annotations
=
RestController
.
class
)
public
class
ExceptionAdvice
{
@ResponseStatus
(
HttpStatus
.
BAD_REQUEST
)
@ExceptionHandler
({
MethodArgumentNotValidException
.
class
,
BindException
.
class
})
public
AbstractResponse
handleBodyValidException
(
MethodArgumentNotValidException
e
)
{
AbstractResponse
errorResponse
=
new
SimpleResponse
();
List
<
FieldError
>
fieldErrors
=
e
.
getBindingResult
().
getFieldErrors
();
errorResponse
.
setErrorInfo
(
HttpStatus
.
BAD_REQUEST
.
value
(),
fieldErrors
.
get
(
0
).
getDefaultMessage
());
return
errorResponse
;
}
}
\ No newline at end of file
src/main/java/vc/thinker/mqtt/config/MqttProtocolConfig.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
config
;
import
com.google.common.collect.Maps
;
import
lombok.extern.slf4j.Slf4j
;
import
org.eclipse.paho.client.mqttv3.MqttCallback
;
import
org.eclipse.paho.client.mqttv3.MqttException
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnExpression
;
import
org.springframework.context.annotation.Configuration
;
import
vc.thinker.absctacts.mqtt.connection.MqttCallbackImpl
;
import
vc.thinker.absctacts.mqtt.protocol.IMqttProtocol
;
import
javax.annotation.PostConstruct
;
import
java.util.List
;
import
java.util.Map
;
/**
* Mqtt 协议配置
*
* @author HeTongHao
* @since 2019-10-29 16:00
*/
@Slf4j
@Configuration
@ConditionalOnExpression
(
"${mqtt.run:true}"
)
public
class
MqttProtocolConfig
{
/**
* 需要注册的协议列表
*/
private
final
List
<
IMqttProtocol
>
mqttProtocolList
;
/**
* mqtt授权服务
*/
private
final
Map
<
IMqttProtocol
,
MqttCallback
>
protocolCallbackMap
=
Maps
.
newHashMap
();
public
MqttProtocolConfig
(
List
<
IMqttProtocol
>
mqttProtocolList
)
{
this
.
mqttProtocolList
=
mqttProtocolList
;
}
@PostConstruct
private
void
initProtocol
()
{
mqttProtocolList
.
forEach
(
mqttProtocol
->
{
Class
<?>
clazz
=
mqttProtocol
.
getClass
();
try
{
protocolCallbackMap
.
put
(
mqttProtocol
,
new
MqttCallbackImpl
(
mqttProtocol
.
getProperties
(),
mqttProtocol
));
log
.
info
(
"[{}]协议注册成功!"
,
clazz
.
getSimpleName
());
}
catch
(
MqttException
e
)
{
log
.
error
(
"构建Mqtt回调组件失败,[{}]协议将不可用,errorMessage:{}"
,
clazz
.
getSimpleName
(),
e
.
getMessage
());
}
});
log
.
info
(
"注册协议总数:{}"
,
protocolCallbackMap
.
size
());
}
}
src/main/java/vc/thinker/mqtt/config/ThinkerMqttConnectionProperties.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
config
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnExpression
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.context.annotation.Configuration
;
import
vc.thinker.absctacts.mqtt.connection.MqttConnectionProperties
;
/**
* 新科云 Mqtt 属性配置
*
* @author HeTongHao
* @since 2019-10-29 16:00
*/
@Data
@Configuration
@EqualsAndHashCode
(
callSuper
=
true
)
@ConditionalOnExpression
(
"${mqtt.run:false}"
)
@ConfigurationProperties
(
prefix
=
"mqtt.connection.thinker"
)
public
class
ThinkerMqttConnectionProperties
extends
MqttConnectionProperties
{
}
src/main/java/vc/thinker/mqtt/config/ThinkerProdMqttConnectionProperties.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
config
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnExpression
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.context.annotation.Configuration
;
import
vc.thinker.absctacts.mqtt.connection.MqttConnectionProperties
;
/**
* 新科云 Mqtt 属性配置
*
* @author HeTongHao
* @since 2019-10-29 16:00
*/
@Data
@Configuration
@EqualsAndHashCode
(
callSuper
=
true
)
@ConditionalOnExpression
(
"${mqtt.run:false}"
)
@ConfigurationProperties
(
prefix
=
"mqtt.connection.thinker-prod"
)
public
class
ThinkerProdMqttConnectionProperties
extends
MqttConnectionProperties
{
}
src/main/java/vc/thinker/mqtt/config/ThinkerTestMqttConnectionProperties.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
config
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnExpression
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
org.springframework.context.annotation.Configuration
;
import
vc.thinker.absctacts.mqtt.connection.MqttConnectionProperties
;
/**
* 新科云 Mqtt 属性配置
*
* @author HeTongHao
* @since 2019-10-29 16:00
*/
@Data
@Configuration
@EqualsAndHashCode
(
callSuper
=
true
)
@ConditionalOnExpression
(
"${mqtt.run:false}"
)
@ConfigurationProperties
(
prefix
=
"mqtt.connection.thinker-test"
)
public
class
ThinkerTestMqttConnectionProperties
extends
MqttConnectionProperties
{
}
src/main/java/vc/thinker/mqtt/forwardthinker/ThinkerProdProtocolClient.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
forwardthinker
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnBean
;
import
org.springframework.scheduling.annotation.Scheduled
;
import
org.springframework.stereotype.Component
;
import
vc.thinker.absctacts.mqtt.protocol.AbstractNotSubscriptionMqttProtocol
;
import
vc.thinker.mqtt.config.ThinkerProdMqttConnectionProperties
;
import
vc.thinker.mqtt.forwardthinker.enums.FoxGatewayTopicDefinition
;
/**
* 富士康数据转发新科云 客户端
*
* @author HeTongHao
* @since 2022-06-28 16:00
*/
@Slf4j
@Component
@ConditionalOnBean
(
ThinkerProdMqttConnectionProperties
.
class
)
public
class
ThinkerProdProtocolClient
extends
AbstractNotSubscriptionMqttProtocol
{
public
ThinkerProdProtocolClient
(
ThinkerProdMqttConnectionProperties
mqttConnectionProperties
)
{
super
(
mqttConnectionProperties
);
}
@Scheduled
(
cron
=
"0 0/1 * * * ?"
)
public
void
timeReport
()
{
String
json
=
"[{\"deviceCode\":\"ZGZC_NXTX_001\",\"events\":{\"ddeedww\":1,\"21312312\":1,\"686787887\":1,\"78078078088\":1,\"532637828739\":1},\"timestamp\":"
+
System
.
currentTimeMillis
()
+
"}]"
;
super
.
getMqttCommandPush
().
sendMqttMessage
(
FoxGatewayTopicDefinition
.
report
.
genTopic
(
"CRRC_SMART_COCKPIT_SYSTEM"
),
json
.
getBytes
());
}
}
src/main/java/vc/thinker/mqtt/forwardthinker/ThinkerTestDataProtocol.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
forwardthinker
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnBean
;
import
org.springframework.stereotype.Component
;
import
vc.thinker.absctacts.mqtt.protocol.AbstractCommonBytesHandleMqttProtocol
;
import
vc.thinker.absctacts.mqtt.topic.TopicDefinition
;
import
vc.thinker.mqtt.config.ThinkerTestMqttConnectionProperties
;
import
vc.thinker.mqtt.forwardthinker.enums.FoxGatewayTopicDefinition
;
/**
* 富士康网关数据上报
*
* @author HeTongHao
* @since 2022-06-28 16:00
*/
@Slf4j
@Component
@ConditionalOnBean
(
ThinkerTestMqttConnectionProperties
.
class
)
public
class
ThinkerTestDataProtocol
extends
AbstractCommonBytesHandleMqttProtocol
{
public
ThinkerTestDataProtocol
(
ThinkerTestMqttConnectionProperties
mqttConnectionProperties
)
{
super
(
mqttConnectionProperties
);
}
@Override
public
String
[]
subscribe
()
{
return
new
String
[]{
FoxGatewayTopicDefinition
.
report
.
getTopic
(),
FoxGatewayTopicDefinition
.
report_version
.
getTopic
(),
};
}
@Override
protected
TopicDefinition
resolveByTopic
(
String
topic
)
{
String
protocolCode
=
FoxGatewayTopicDefinition
.
resolveProtocolCodeByTopic
(
topic
);
String
matchTopic
=
topic
.
replace
(
protocolCode
,
"+"
);
return
FoxGatewayTopicDefinition
.
RESOLVE_BY_TOPIC
.
resolve
(
matchTopic
);
}
}
src/main/java/vc/thinker/mqtt/forwardthinker/actor/up/ThirdPartyReportDataActor.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
forwardthinker
.
actor
.
up
;
import
akka.actor.AbstractActor
;
import
akka.japi.pf.ReceiveBuilder
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.config.ConfigurableBeanFactory
;
import
org.springframework.context.annotation.Scope
;
import
org.springframework.stereotype.Component
;
import
vc.thinker.absctacts.mqtt.entity.MqttResponseBytes
;
import
vc.thinker.mqtt.forwardthinker.ThinkerProdProtocolClient
;
import
vc.thinker.mqtt.forwardthinker.enums.FoxGatewayTopicDefinition
;
import
javax.annotation.Resource
;
import
java.util.List
;
/**
* 网关上报数据接收
*
* @author HeTongHao
* @since 2022/6/28 14:10
*/
@Slf4j
@Component
@Scope
(
ConfigurableBeanFactory
.
SCOPE_PROTOTYPE
)
public
class
ThirdPartyReportDataActor
extends
AbstractActor
{
@Resource
private
ThinkerProdProtocolClient
thinkerProdProtocolClient
;
/**
* 转发的网关编号列表
*/
private
static
final
List
<
String
>
PROTOCOL_CODES
=
List
.
of
(
"CRRC_SMART_COCKPIT_SYSTEM"
,
"WF_IOT_FUSE_SYSTEM"
);
public
ThirdPartyReportDataActor
()
{
receive
(
ReceiveBuilder
.
match
(
MqttResponseBytes
.
class
,
mqttResponse
->
{
String
protocolCode
=
FoxGatewayTopicDefinition
.
resolveProtocolCodeByTopic
(
mqttResponse
.
getTopic
());
// 指转发指定协议下的设备
if
(
PROTOCOL_CODES
.
contains
(
protocolCode
))
{
thinkerProdProtocolClient
.
getMqttCommandPush
()
.
sendMqttMessage
(
mqttResponse
.
getTopic
(),
mqttResponse
.
getMessage
());
}
}).
build
());
}
}
src/main/java/vc/thinker/mqtt/forwardthinker/enums/FoxGatewayTopicDefinition.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
forwardthinker
.
enums
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
import
vc.thinker.absctacts.mqtt.topic.TopicDefinition
;
import
vc.thinker.absctacts.mqtt.utils.StringFormatUtils
;
import
vc.thinker.mqtt.forwardthinker.actor.up.ThirdPartyReportDataActor
;
import
vc.thinker.utils.Resolve
;
/**
* Topic-actor 定义
*
* @author HeTongHao
* @since 2022-06-28 16:00
*/
@Getter
@AllArgsConstructor
public
enum
FoxGatewayTopicDefinition
implements
TopicDefinition
{
/**
* Topic-actor 定义
*/
report
(
"third-party/+/up/report"
,
ThirdPartyReportDataActor
.
class
),
report_version
(
"third-party/+/v2/up/report"
,
ThirdPartyReportDataActor
.
class
),
;
private
final
String
topic
;
private
final
Class
<?>
actorClass
;
public
static
final
Resolve
<
FoxGatewayTopicDefinition
,
String
>
RESOLVE_BY_TOPIC
=
new
Resolve
<>(
values
(),
FoxGatewayTopicDefinition:
:
getTopic
);
public
String
getActorInstanceName
()
{
return
StringFormatUtils
.
classNameLowercaseFirst
(
this
.
actorClass
);
}
public
String
genTopic
(
String
protocolCode
)
{
return
this
.
topic
.
replace
(
"+"
,
protocolCode
);
}
/**
* 根据topic解析第三方协议编号
*
* @param topic topic
* @return 第三方协议编号
*/
public
static
String
resolveProtocolCodeByTopic
(
String
topic
)
{
return
topic
.
split
(
"/"
)[
1
];
}
}
src/main/java/vc/thinker/mqtt/proxyclient/ThirdPartyProxyClientProtocol.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
proxyclient
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnBean
;
import
org.springframework.stereotype.Component
;
import
vc.thinker.absctacts.mqtt.protocol.AbstractCommonEntityHandleMqttProtocol
;
import
vc.thinker.absctacts.mqtt.topic.TopicDefinition
;
import
vc.thinker.mqtt.config.ThinkerMqttConnectionProperties
;
import
vc.thinker.mqtt.proxyclient.enums.ThirdPartyProxyTopicDefinition
;
/**
* 第三方协议代理协议 客户端
*
* @author HeTongHao
* @since 2019-10-29 16:00
*/
@Slf4j
@Component
@ConditionalOnBean
(
ThinkerMqttConnectionProperties
.
class
)
public
class
ThirdPartyProxyClientProtocol
extends
AbstractCommonEntityHandleMqttProtocol
{
public
ThirdPartyProxyClientProtocol
(
ThinkerMqttConnectionProperties
thinkerMqttConnectionProperties
)
{
super
(
thinkerMqttConnectionProperties
);
}
@Override
public
String
[]
subscribe
()
{
return
new
String
[]{
ThirdPartyProxyTopicDefinition
.
executeService
.
getTopic
(),
ThirdPartyProxyTopicDefinition
.
meterListPullResponse
.
getTopic
(),
ThirdPartyProxyTopicDefinition
.
meterChange
.
getTopic
()
};
}
@Override
protected
TopicDefinition
resolveByTopic
(
String
topic
)
{
String
protocolCode
=
ThirdPartyProxyTopicDefinition
.
resolveProtocolCodeByTopic
(
topic
);
String
matchTopic
=
topic
.
replace
(
protocolCode
,
"+"
);
return
ThirdPartyProxyTopicDefinition
.
RESOLVE_BY_TOPIC
.
resolve
(
matchTopic
);
}
/**
* 统一发送Mqtt消息入口
*
* @param topic topic定义
* @param protocolCode 第三方协议编号
* @param payload 数据荷载
*/
public
void
sendMessage
(
ThirdPartyProxyTopicDefinition
topic
,
String
protocolCode
,
byte
[]
payload
)
{
super
.
getMqttCommandPush
().
sendMqttMessage
(
topic
.
genTopic
(
protocolCode
),
payload
);
}
}
src/main/java/vc/thinker/mqtt/proxyclient/actor/down/MeterChangeActor.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
proxyclient
.
actor
.
down
;
import
akka.actor.AbstractActor
;
import
akka.japi.pf.ReceiveBuilder
;
import
com.alibaba.fastjson.JSONObject
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.config.ConfigurableBeanFactory
;
import
org.springframework.context.annotation.Scope
;
import
org.springframework.stereotype.Component
;
import
vc.thinker.absctacts.mqtt.entity.MqttResponse
;
import
vc.thinker.absctacts.protocolproxy.dto.MeterInfo
;
import
vc.thinker.absctacts.protocolproxy.protocol.IThirdPartyProtocolSyncMeterInfo
;
import
vc.thinker.mqtt.proxyclient.entity.down.MeterChange
;
import
vc.thinker.mqtt.proxyclient.entity.down.PlateFormMeterInfo
;
import
vc.thinker.mqtt.proxyclient.enums.ThirdPartyProxyTopicDefinition
;
import
javax.annotation.Resource
;
import
java.util.List
;
/**
* 仪表改变通知
*
* @author HeTongHao
* @since 2022/18/19 15:43
*/
@Slf4j
@Component
@Scope
(
ConfigurableBeanFactory
.
SCOPE_PROTOTYPE
)
public
class
MeterChangeActor
extends
AbstractActor
{
@Resource
private
List
<
IThirdPartyProtocolSyncMeterInfo
>
thirdPartyProtocols
;
public
MeterChangeActor
()
{
receive
(
ReceiveBuilder
.
match
(
MqttResponse
.
class
,
mqttResponse
->
{
String
topic
=
mqttResponse
.
getTopic
();
String
protocolType
=
ThirdPartyProxyTopicDefinition
.
resolveProtocolCodeByTopic
(
topic
);
for
(
IThirdPartyProtocolSyncMeterInfo
thirdPartyProtocol
:
thirdPartyProtocols
)
{
if
(
protocolType
.
equals
(
thirdPartyProtocol
.
protocolType
().
getCode
()))
{
MeterChange
meterChange
=
JSONObject
.
parseObject
(
mqttResponse
.
getMessage
(),
MeterChange
.
class
);
PlateFormMeterInfo
meterInfo
=
meterChange
.
getMeterInfo
();
// 发送到具体协议去执行
switch
(
meterChange
.
getOperateType
())
{
case
"PUT"
:
thirdPartyProtocol
.
putMeter
(
MeterInfo
.
builder
()
.
id
(
meterInfo
.
getId
())
.
code
(
meterInfo
.
getCode
())
.
build
()
);
break
;
case
"DELETE"
:
thirdPartyProtocol
.
deleteMeter
(
meterInfo
.
getId
());
break
;
default
:
log
.
error
(
"不支持操作:"
+
meterChange
.
getOperateType
());
}
break
;
}
}
}).
build
());
}
}
src/main/java/vc/thinker/mqtt/proxyclient/actor/down/MeterListPullResponseActor.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
proxyclient
.
actor
.
down
;
import
akka.actor.AbstractActor
;
import
akka.japi.pf.ReceiveBuilder
;
import
com.alibaba.fastjson.JSONObject
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.config.ConfigurableBeanFactory
;
import
org.springframework.context.annotation.Scope
;
import
org.springframework.stereotype.Component
;
import
vc.thinker.absctacts.mqtt.entity.MqttResponse
;
import
vc.thinker.mqtt.proxyclient.entity.down.MeterListResponse
;
import
vc.thinker.mqtt.proxyclient.service.ThirdPartyProxyClientService
;
import
javax.annotation.Resource
;
/**
* 仪表列表拉取响应
*
* @author HeTongHao
* @since 2022/18/19 15:43
*/
@Slf4j
@Component
@Scope
(
ConfigurableBeanFactory
.
SCOPE_PROTOTYPE
)
public
class
MeterListPullResponseActor
extends
AbstractActor
{
@Resource
private
ThirdPartyProxyClientService
thirdPartyProxyClientService
;
public
MeterListPullResponseActor
()
{
receive
(
ReceiveBuilder
.
match
(
MqttResponse
.
class
,
mqttResponse
->
{
MeterListResponse
meterListResponse
=
JSONObject
.
parseObject
(
mqttResponse
.
getMessage
(),
MeterListResponse
.
class
);
// 响应数据
thirdPartyProxyClientService
.
responseData
(
meterListResponse
.
getRequestId
(),
meterListResponse
.
getMeterList
());
}).
build
());
}
}
src/main/java/vc/thinker/mqtt/proxyclient/actor/down/ThirdPartyServiceExecuteActor.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
proxyclient
.
actor
.
down
;
import
akka.actor.AbstractActor
;
import
akka.japi.pf.ReceiveBuilder
;
import
cn.hutool.core.thread.ThreadUtil
;
import
com.alibaba.fastjson.JSONArray
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.config.ConfigurableBeanFactory
;
import
org.springframework.context.annotation.Scope
;
import
org.springframework.stereotype.Component
;
import
vc.thinker.absctacts.mqtt.entity.MqttResponse
;
import
vc.thinker.absctacts.protocolproxy.dto.IServiceExecuteResult
;
import
vc.thinker.absctacts.protocolproxy.dto.ServiceExecuteCmd
;
import
vc.thinker.absctacts.protocolproxy.protocol.IThirdPartyProtocol
;
import
vc.thinker.mqtt.proxyclient.entity.down.ServiceExecCmd
;
import
vc.thinker.mqtt.proxyclient.entity.up.ServiceExecResult
;
import
vc.thinker.mqtt.proxyclient.enums.ThirdPartyProxyTopicDefinition
;
import
vc.thinker.mqtt.proxyclient.service.ThirdPartyProxyClientService
;
import
javax.annotation.Resource
;
import
java.util.List
;
/**
* 新科云执行服务到此第三方代理
*
* @author HeTongHao
* @since 2021/8/11 15:43
*/
@Slf4j
@Component
@Scope
(
ConfigurableBeanFactory
.
SCOPE_PROTOTYPE
)
public
class
ThirdPartyServiceExecuteActor
extends
AbstractActor
{
@Resource
private
ThirdPartyProxyClientService
thirdPartyProxyClientService
;
@Resource
private
List
<
IThirdPartyProtocol
>
thirdPartyProtocols
;
public
ThirdPartyServiceExecuteActor
()
{
receive
(
ReceiveBuilder
.
match
(
MqttResponse
.
class
,
mqttResponse
->
{
String
topic
=
mqttResponse
.
getTopic
();
String
protocolType
=
ThirdPartyProxyTopicDefinition
.
resolveProtocolCodeByTopic
(
topic
);
for
(
IThirdPartyProtocol
thirdPartyProtocol
:
thirdPartyProtocols
)
{
if
(
protocolType
.
equals
(
thirdPartyProtocol
.
protocolType
().
getCode
()))
{
List
<
ServiceExecCmd
>
serviceExecuteCmds
=
JSONArray
.
parseArray
(
mqttResponse
.
getMessage
(),
ServiceExecCmd
.
class
);
// 发送到具体协议去执行
executeAndResponse
(
thirdPartyProtocol
,
serviceExecuteCmds
);
break
;
}
}
}).
build
());
}
/**
* 执行并响应结果
*
* @param thirdPartyProtocol 分发到的协议协议
* @param serviceExecuteCmds 待执行的命令列表
*/
private
void
executeAndResponse
(
IThirdPartyProtocol
thirdPartyProtocol
,
List
<
ServiceExecCmd
>
serviceExecuteCmds
)
{
serviceExecuteCmds
.
forEach
(
cmd
->
ThreadUtil
.
execute
(()
->
{
// 执行->获取结果
IServiceExecuteResult
result
=
thirdPartyProtocol
.
onExecutiveService
(
new
ServiceExecuteCmd
(
cmd
.
getRequestId
(),
cmd
.
getDeviceCode
(),
cmd
.
getServiceCode
(),
cmd
.
getParams
())
);
// 结果响应
thirdPartyProxyClientService
.
executeResponse
(
new
ServiceExecResult
(
thirdPartyProtocol
.
protocolType
().
getCode
(),
result
));
})
);
}
}
src/main/java/vc/thinker/mqtt/proxyclient/actor/up/MeterListPullActor.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
proxyclient
.
actor
.
up
;
import
akka.actor.AbstractActor
;
import
akka.japi.pf.ReceiveBuilder
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.config.ConfigurableBeanFactory
;
import
org.springframework.context.annotation.Scope
;
import
org.springframework.stereotype.Component
;
import
vc.thinker.mqtt.proxyclient.ThirdPartyProxyClientProtocol
;
import
vc.thinker.mqtt.proxyclient.entity.up.MeterListPull
;
import
vc.thinker.mqtt.proxyclient.enums.ThirdPartyProxyTopicDefinition
;
import
javax.annotation.Resource
;
/**
* 拉取仪表列表
*
* @author HeTongHao
* @since 2022/8/19 15:43
*/
@Slf4j
@Component
@Scope
(
ConfigurableBeanFactory
.
SCOPE_PROTOTYPE
)
public
class
MeterListPullActor
extends
AbstractActor
{
@Resource
private
ThirdPartyProxyClientProtocol
thirdPartyProxyClientProtocol
;
public
MeterListPullActor
()
{
receive
(
ReceiveBuilder
.
match
(
MeterListPull
.
class
,
meterListPull
->
thirdPartyProxyClientProtocol
.
sendMessage
(
ThirdPartyProxyTopicDefinition
.
meterListPull
,
meterListPull
.
getProtocolCode
()
,
meterListPull
.
getRequestId
().
getBytes
())
).
build
());
}
}
src/main/java/vc/thinker/mqtt/proxyclient/actor/up/ThirdPartyReportActor.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
proxyclient
.
actor
.
up
;
import
akka.actor.AbstractActor
;
import
akka.japi.pf.ReceiveBuilder
;
import
com.alibaba.fastjson.JSONArray
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.config.ConfigurableBeanFactory
;
import
org.springframework.context.annotation.Scope
;
import
org.springframework.stereotype.Component
;
import
vc.thinker.mqtt.proxyclient.ThirdPartyProxyClientProtocol
;
import
vc.thinker.mqtt.proxyclient.entity.up.ThirdPartyProxyReport
;
import
vc.thinker.mqtt.proxyclient.enums.ThirdPartyProxyTopicDefinition
;
import
javax.annotation.Resource
;
/**
* 第三方数据上报到新科云
*
* @author HeTongHao
* @since 2021/7/7 20:43
*/
@Slf4j
@Component
@Scope
(
ConfigurableBeanFactory
.
SCOPE_PROTOTYPE
)
public
class
ThirdPartyReportActor
extends
AbstractActor
{
@Resource
private
ThirdPartyProxyClientProtocol
thirdPartyProxyClientProtocol
;
public
ThirdPartyReportActor
()
{
receive
(
ReceiveBuilder
.
match
(
ThirdPartyProxyReport
.
class
,
thirdPartyProxyReport
->
thirdPartyProxyClientProtocol
.
sendMessage
(
ThirdPartyProxyTopicDefinition
.
report
,
thirdPartyProxyReport
.
getProtocolType
()
,
JSONArray
.
toJSONBytes
(
thirdPartyProxyReport
.
getPayload
()))
).
build
());
}
}
src/main/java/vc/thinker/mqtt/proxyclient/actor/up/ThirdPartyServiceExecuteResponseActor.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
proxyclient
.
actor
.
up
;
import
akka.actor.AbstractActor
;
import
akka.japi.pf.ReceiveBuilder
;
import
com.alibaba.fastjson.JSONArray
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.config.ConfigurableBeanFactory
;
import
org.springframework.context.annotation.Scope
;
import
org.springframework.stereotype.Component
;
import
vc.thinker.mqtt.proxyclient.ThirdPartyProxyClientProtocol
;
import
vc.thinker.mqtt.proxyclient.entity.up.ServiceExecResult
;
import
vc.thinker.mqtt.proxyclient.enums.ThirdPartyProxyTopicDefinition
;
import
javax.annotation.Resource
;
/**
* 拉取仪表列表
*
* @author HeTongHao
* @since 2022/8/19 15:43
*/
@Slf4j
@Component
@Scope
(
ConfigurableBeanFactory
.
SCOPE_PROTOTYPE
)
public
class
ThirdPartyServiceExecuteResponseActor
extends
AbstractActor
{
@Resource
private
ThirdPartyProxyClientProtocol
thirdPartyProxyClientProtocol
;
public
ThirdPartyServiceExecuteResponseActor
()
{
receive
(
ReceiveBuilder
.
match
(
ServiceExecResult
.
class
,
serviceExecResult
->
thirdPartyProxyClientProtocol
.
sendMessage
(
ThirdPartyProxyTopicDefinition
.
executeServiceResponse
,
serviceExecResult
.
getProtocolCode
()
,
JSONArray
.
toJSONBytes
(
serviceExecResult
))
).
build
());
}
}
src/main/java/vc/thinker/mqtt/proxyclient/entity/down/BaseResponse.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
proxyclient
.
entity
.
down
;
import
lombok.Data
;
/**
* 基础响应字段
*
* @author HeTongHao
* @since 2022/8/19 17:38
*/
@Data
public
class
BaseResponse
{
private
String
requestId
;
}
src/main/java/vc/thinker/mqtt/proxyclient/entity/down/MeterChange.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
proxyclient
.
entity
.
down
;
import
lombok.Data
;
/**
* 仪表信息
*
* @author HeTongHao
* @since 2022/8/19 17:37
*/
@Data
public
class
MeterChange
{
private
String
operateType
;
private
PlateFormMeterInfo
meterInfo
;
}
src/main/java/vc/thinker/mqtt/proxyclient/entity/down/MeterListResponse.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
proxyclient
.
entity
.
down
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
java.util.List
;
/**
* 仪表列表响应体
*
* @author HeTongHao
* @since 2022/8/19 17:37
*/
@Data
@EqualsAndHashCode
(
callSuper
=
true
)
public
class
MeterListResponse
extends
BaseResponse
{
private
List
<
PlateFormMeterInfo
>
meterList
;
}
src/main/java/vc/thinker/mqtt/proxyclient/entity/down/PlateFormMeterInfo.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
proxyclient
.
entity
.
down
;
import
lombok.Data
;
/**
* 仪表信息
*
* @author HeTongHao
* @since 2022/8/19 17:37
*/
@Data
public
class
PlateFormMeterInfo
{
private
String
id
;
private
String
code
;
}
src/main/java/vc/thinker/mqtt/proxyclient/entity/down/ServiceExecCmd.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
proxyclient
.
entity
.
down
;
import
lombok.Data
;
import
lombok.EqualsAndHashCode
;
import
java.util.Map
;
/**
* 服务执行命令
*
* @author HeTongHao
* @since 2021/7/9 17:47
*/
@Data
@EqualsAndHashCode
(
callSuper
=
true
)
public
class
ServiceExecCmd
extends
BaseResponse
{
private
String
deviceCode
;
private
String
serviceCode
;
private
Map
<
String
,
Object
>
params
;
}
src/main/java/vc/thinker/mqtt/proxyclient/entity/up/MeterData.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
proxyclient
.
entity
.
up
;
import
com.alibaba.fastjson.JSONArray
;
import
com.alibaba.fastjson.JSONObject
;
import
com.alibaba.fastjson.serializer.JSONSerializable
;
import
com.alibaba.fastjson.serializer.JSONSerializer
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Maps
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
java.io.Serial
;
import
java.io.Serializable
;
import
java.lang.reflect.Type
;
import
java.util.ArrayList
;
import
java.util.Map
;
import
java.util.Objects
;
/**
* 原始数据
*
* @author XFY
* @since 2022/10/24 18:03
**/
@Data
@Accessors
(
chain
=
true
)
public
class
MeterData
implements
Serializable
,
JSONSerializable
{
@Serial
private
static
final
long
serialVersionUID
=
-
6256921296477327221L
;
/**
* 时间戳
*/
private
Long
timestamp
;
private
Map
<
String
,
Object
>
meterDataMap
;
private
static
final
String
TIME_PREFIX
=
"T_"
;
private
static
final
String
DEVICE_CODE
=
"deviceCode"
;
public
MeterData
()
{
this
.
meterDataMap
=
Maps
.
newHashMap
();
}
/**
* 设置设备编号
*/
public
MeterData
setDeviceCode
(
String
deviceCode
)
{
meterDataMap
.
put
(
DEVICE_CODE
,
deviceCode
);
return
this
;
}
/**
* 获取设备编号
*/
public
String
getDeviceCode
()
{
return
String
.
valueOf
(
meterDataMap
.
get
(
DEVICE_CODE
));
}
/**
* 添加属性数据
*
* @param code 属性编号
* @param value 属性值
* @return MeterData
*/
public
MeterData
putAttrData
(
String
code
,
Object
value
)
{
Objects
.
requireNonNull
(
timestamp
,
"时间戳不能为空"
);
putAttrData
(
timestamp
,
code
,
value
);
return
this
;
}
/**
* 添加属性数据
*
* @param timestamp 时间戳
* @param code 属性编号
* @param value 属性值
* @return MeterData
*/
public
MeterData
putAttrData
(
Long
timestamp
,
String
code
,
Object
value
)
{
String
key
=
TIME_PREFIX
+
timestamp
;
DataBucket
dataBucket
=
(
DataBucket
)
meterDataMap
.
computeIfAbsent
(
key
,
k
->
new
DataBucket
());
dataBucket
.
putAttrData
(
code
,
value
);
return
this
;
}
/**
* 添加事件数据
*
* @param code 事件编号
* @param value 事件值
* @return MeterData
*/
public
MeterData
putEventData
(
String
code
,
Object
value
)
{
Objects
.
requireNonNull
(
timestamp
,
"时间戳不能为空"
);
putEventData
(
timestamp
,
code
,
value
);
return
this
;
}
/**
* 添加事件数据
*
* @param timestamp 时间戳
* @param code 事件编号
* @param value 事件值
* @return MeterData
*/
public
MeterData
putEventData
(
Long
timestamp
,
String
code
,
Object
value
)
{
String
key
=
TIME_PREFIX
+
timestamp
;
DataBucket
dataBucket
=
(
DataBucket
)
meterDataMap
.
computeIfAbsent
(
key
,
k
->
new
DataBucket
());
dataBucket
.
putEventData
(
code
,
value
);
return
this
;
}
public
static
void
main
(
String
[]
args
)
{
ArrayList
<
MeterData
>
list
=
Lists
.
newArrayList
();
MeterData
v2
=
new
MeterData
();
v2
.
setDeviceCode
(
"123"
).
setTimestamp
(
System
.
currentTimeMillis
());
v2
.
putAttrData
(
"AirGapSensor_1.airGap"
,
3.45
);
v2
.
putEventData
(
"AirGapSensor_1.boot_up"
,
1
);
list
.
add
(
v2
);
System
.
out
.
println
(
v2
);
System
.
out
.
println
(
JSONArray
.
toJSONString
(
list
));
}
/**
* 数据包封装
* 标识一个仪表的一次上报,内容可包含0个或多个属性、事件
*
* @author HeTongHao
* @since 2022/8/8 20:39
*/
@Data
@Accessors
(
chain
=
true
)
public
static
class
DataBucket
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
-
7756910224854163803L
;
/**
* 属性数据键值对
*/
private
Map
<
String
,
Object
>
datas
;
/**
* 事件数据键值对
*/
private
Map
<
String
,
Object
>
events
;
public
Map
<
String
,
Object
>
putAttrData
(
String
code
,
Object
value
)
{
if
(
datas
==
null
)
{
datas
=
Maps
.
newHashMap
();
}
datas
.
put
(
code
,
value
);
return
datas
;
}
public
Map
<
String
,
Object
>
putEventData
(
String
code
,
Object
value
)
{
if
(
events
==
null
)
{
events
=
Maps
.
newHashMap
();
}
events
.
put
(
code
,
value
);
return
events
;
}
}
@Override
public
void
write
(
JSONSerializer
serializer
,
Object
fieldName
,
Type
fieldType
,
int
features
)
{
serializer
.
write
(
meterDataMap
);
}
@Override
public
String
toString
()
{
return
JSONObject
.
toJSONString
(
meterDataMap
);
}
}
src/main/java/vc/thinker/mqtt/proxyclient/entity/up/MeterListPull.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
proxyclient
.
entity
.
up
;
import
lombok.Builder
;
import
lombok.Getter
;
/**
* 设备列表拉取
*
* @author HeTongHao
* @since 2022/8/19 17:24
*/
@Getter
@Builder
public
class
MeterListPull
{
private
String
protocolCode
;
private
String
requestId
;
}
src/main/java/vc/thinker/mqtt/proxyclient/entity/up/ServiceExecResult.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
proxyclient
.
entity
.
up
;
import
lombok.Getter
;
import
vc.thinker.absctacts.protocolproxy.dto.IServiceExecuteResult
;
import
vc.thinker.absctacts.protocolproxy.enums.ServiceExecuteResultType
;
/**
* 服务执行结果
*
* @author HeTongHao
* @since 2021/8/11 17:47
*/
@Getter
public
class
ServiceExecResult
{
public
ServiceExecResult
(
String
protocolCode
,
IServiceExecuteResult
serviceExecuteResult
)
{
this
.
protocolCode
=
protocolCode
;
this
.
requestId
=
serviceExecuteResult
.
getRequestId
();
// 当前只有两种,简单实现:
this
.
resCode
=
ServiceExecuteResultType
.
ok
.
equals
(
serviceExecuteResult
.
getType
())
?
"200"
:
"500"
;
this
.
resMsg
=
serviceExecuteResult
.
getMessage
();
}
private
final
String
protocolCode
;
private
final
String
requestId
;
private
final
String
resCode
;
private
final
String
resMsg
;
}
src/main/java/vc/thinker/mqtt/proxyclient/entity/up/ThirdPartyProxyReport.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
proxyclient
.
entity
.
up
;
import
lombok.AllArgsConstructor
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
java.util.List
;
/**
* 第三方代理上报对象
*
* @author HeTongHao
* @since 2021/7/7 20:56
*/
@Data
@Accessors
(
chain
=
true
)
@AllArgsConstructor
public
class
ThirdPartyProxyReport
{
/**
* 协议类型编号
*/
private
String
protocolType
;
/**
* 数据列表
*/
private
List
<
MeterData
>
payload
;
}
src/main/java/vc/thinker/mqtt/proxyclient/enums/ThirdPartyProxyTopicDefinition.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
proxyclient
.
enums
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
import
vc.thinker.absctacts.mqtt.topic.TopicDefinition
;
import
vc.thinker.mqtt.proxyclient.actor.down.MeterChangeActor
;
import
vc.thinker.mqtt.proxyclient.actor.down.MeterListPullResponseActor
;
import
vc.thinker.mqtt.proxyclient.actor.down.ThirdPartyServiceExecuteActor
;
import
vc.thinker.mqtt.proxyclient.actor.up.MeterListPullActor
;
import
vc.thinker.mqtt.proxyclient.actor.up.ThirdPartyReportActor
;
import
vc.thinker.mqtt.proxyclient.actor.up.ThirdPartyServiceExecuteResponseActor
;
import
vc.thinker.utils.Resolve
;
/**
* Topic-actor 定义
*
* @author HeTongHao
* @since 2022/8/10 11:16
*/
@Getter
@AllArgsConstructor
public
enum
ThirdPartyProxyTopicDefinition
implements
TopicDefinition
{
// 数据上报
report
(
"third-party/+/v2/up/report"
,
ThirdPartyReportActor
.
class
),
// 服务执行
executeService
(
"third-party/+/down/execute-service"
,
ThirdPartyServiceExecuteActor
.
class
),
executeServiceResponse
(
"third-party/+/up/execute-service/response"
,
ThirdPartyServiceExecuteResponseActor
.
class
),
// 仪表同步
meterListPull
(
"third-party/+/up/meter-list-pull"
,
MeterListPullActor
.
class
),
meterListPullResponse
(
"third-party/+/down/meter-list-pull/response"
,
MeterListPullResponseActor
.
class
),
meterChange
(
"third-party/+/down/meter-change"
,
MeterChangeActor
.
class
),
;
private
final
String
topic
;
private
final
Class
<?>
actorClass
;
public
String
genTopic
(
String
protocolCode
)
{
return
this
.
topic
.
replace
(
"+"
,
protocolCode
);
}
/**
* 根据topic解析第三方协议编号
*
* @param topic topic
* @return 第三方协议编号
*/
public
static
String
resolveProtocolCodeByTopic
(
String
topic
)
{
return
topic
.
split
(
"/"
)[
1
];
}
public
static
final
Resolve
<
ThirdPartyProxyTopicDefinition
,
String
>
RESOLVE_BY_TOPIC
=
new
Resolve
<>(
values
(),
ThirdPartyProxyTopicDefinition:
:
getTopic
);
}
src/main/java/vc/thinker/mqtt/proxyclient/service/ThirdPartyProxyClientService.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
mqtt
.
proxyclient
.
service
;
import
com.google.common.collect.Lists
;
import
org.springframework.stereotype.Service
;
import
vc.thinker.absctacts.mqtt.publish.TopicMqttPushService
;
import
vc.thinker.mqtt.proxyclient.entity.down.PlateFormMeterInfo
;
import
vc.thinker.mqtt.proxyclient.entity.up.MeterListPull
;
import
vc.thinker.mqtt.proxyclient.entity.up.ServiceExecResult
;
import
vc.thinker.mqtt.proxyclient.entity.up.ThirdPartyProxyReport
;
import
vc.thinker.mqtt.proxyclient.enums.ThirdPartyProxyTopicDefinition
;
import
vc.thinker.utils.CompletableFutureObserver
;
import
java.util.List
;
import
java.util.UUID
;
import
java.util.concurrent.CompletableFuture
;
import
java.util.concurrent.ExecutionException
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeoutException
;
/**
* 适配4G网关方式协议适配
*
* @author HeTongHao
* @since 2021/7/9 14:05
*/
@Service
public
class
ThirdPartyProxyClientService
extends
TopicMqttPushService
{
public
final
CompletableFutureObserver
<
Object
>
completableFutureObserver
=
new
CompletableFutureObserver
<>();
/**
* 响应数据
* 基于requestId 来实现同步响应数据
*
* @param requestId requestId
* @param data 数据对象
*/
public
void
responseData
(
String
requestId
,
Object
data
)
{
completableFutureObserver
.
onMessage
(
requestId
,
data
);
}
/**
* 上报数据
*
* @param thirdPartyProxyReport 上报数据
*/
public
void
report
(
ThirdPartyProxyReport
thirdPartyProxyReport
)
{
super
.
push
(
ThirdPartyProxyTopicDefinition
.
report
,
thirdPartyProxyReport
);
}
/**
* 服务执行响应
*
* @param serviceExecResult 服务执行响应结果
*/
public
void
executeResponse
(
ServiceExecResult
serviceExecResult
)
{
super
.
push
(
ThirdPartyProxyTopicDefinition
.
executeServiceResponse
,
serviceExecResult
);
}
/**
* 拉取仪表列表
*
* @param protocolCode 协议编号
*/
public
List
<
PlateFormMeterInfo
>
pullMeterList
(
String
protocolCode
)
throws
TimeoutException
{
String
requestId
=
UUID
.
randomUUID
().
toString
();
super
.
push
(
ThirdPartyProxyTopicDefinition
.
meterListPull
,
MeterListPull
.
builder
()
.
protocolCode
(
protocolCode
)
.
requestId
(
requestId
)
.
build
()
);
CompletableFuture
<
Object
>
subscribe
=
completableFutureObserver
.
subscribe
(
requestId
);
try
{
return
(
List
<
PlateFormMeterInfo
>)
subscribe
.
get
(
3
,
TimeUnit
.
SECONDS
);
}
catch
(
InterruptedException
|
ExecutionException
e
)
{
e
.
printStackTrace
();
return
Lists
.
newArrayList
();
}
catch
(
TimeoutException
e
)
{
throw
e
;
}
}
}
src/main/java/vc/thinker/response/AbstractResponse.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
response
;
import
com.fasterxml.jackson.annotation.JsonView
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
org.springframework.context.MessageSource
;
import
org.springframework.web.servlet.support.RequestContextUtils
;
import
javax.servlet.http.HttpServletRequest
;
import
java.util.Locale
;
/**
* @author : xieshaojun
* @date : 2023/1/3 17:59
*/
@Data
@Accessors
(
chain
=
true
)
public
abstract
class
AbstractResponse
{
@ApiModelProperty
(
hidden
=
true
)
private
MessageSource
messageSource
;
@ApiModelProperty
(
hidden
=
true
)
private
Locale
locale
;
@ApiModelProperty
(
"请求是否成功"
)
private
boolean
success
=
true
;
@ApiModelProperty
(
"自定义异常code"
)
private
String
code
;
@ApiModelProperty
(
"消息提示"
)
private
String
message
;
public
AbstractResponse
()
{
}
public
AbstractResponse
(
MessageSource
messageSource
,
HttpServletRequest
request
)
{
this
.
messageSource
=
messageSource
;
this
.
locale
=
RequestContextUtils
.
getLocale
(
request
);
}
/**
* 设置错误信息
*
* @param code 自定义异常code
* @param message 消息提示
*/
public
void
setErrorInfo
(
String
code
,
String
message
)
{
this
.
success
=
false
;
this
.
code
=
code
;
this
.
message
=
message
;
}
/**
* 设置错误信息
*
* @param code 自定义异常code
* @param message 消息提示
*/
public
void
setErrorInfo
(
int
code
,
String
message
)
{
this
.
success
=
false
;
this
.
code
=
String
.
valueOf
(
code
);
this
.
message
=
message
;
}
/**
* 设置错误信息
*
* @param code 自定义异常code
* @param messageCode 用于国际化的消息编号
* @param defaultMessage 如果找不到对应的消息,返回默认的消息
*/
public
void
setErrorInfo
(
String
code
,
String
messageCode
,
String
defaultMessage
)
{
if
(
messageSource
==
null
)
{
throw
new
RuntimeException
(
"未初始化 messageSource 字段"
);
}
this
.
success
=
false
;
this
.
code
=
code
;
this
.
message
=
messageSource
.
getMessage
(
messageCode
,
null
,
defaultMessage
,
locale
);
}
/**
* 设置错误信息
*
* @param code 自定义异常code
* @param messageCode 用于国际化的消息编号
* @param defaultMessage 如果找不到对应的消息,返回默认的消息
*/
public
void
setErrorInfo
(
int
code
,
String
messageCode
,
String
defaultMessage
)
{
setErrorInfo
(
String
.
valueOf
(
code
),
messageCode
,
defaultMessage
);
}
/**
* 设置错误信息
*
* @param code 自定义异常code
* @param messageCode 用于国际化的消息编号
* @param args 消息参数列表
* @param defaultMessage 如果找不到对应的消息,返回默认的消息
*/
public
void
setErrorInfo
(
String
code
,
String
messageCode
,
Object
[]
args
,
String
defaultMessage
)
{
this
.
success
=
false
;
this
.
code
=
code
;
this
.
message
=
messageSource
.
getMessage
(
messageCode
,
args
,
defaultMessage
,
locale
);
}
/**
* 设置错误信息
*
* @param code 自定义异常code
* @param messageCode 用于国际化的消息编号
* @param args 消息参数列表
* @param defaultMessage 如果找不到对应的消息,返回默认的消息
*/
public
void
setErrorInfo
(
int
code
,
String
messageCode
,
Object
[]
args
,
String
defaultMessage
)
{
setErrorInfo
(
String
.
valueOf
(
code
),
messageCode
,
args
,
defaultMessage
);
}
}
src/main/java/vc/thinker/response/SimpleResponse.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
response
;
import
org.springframework.context.MessageSource
;
import
javax.servlet.http.HttpServletRequest
;
/**
* @author : xieshaojun
* @date : 2023/1/3 17:58
*/
public
class
SimpleResponse
extends
AbstractResponse
{
public
SimpleResponse
()
{
}
public
SimpleResponse
(
MessageSource
messageSource
,
HttpServletRequest
request
)
{
super
(
messageSource
,
request
);
}
}
src/main/java/vc/thinker/thirdpartyproxy/ProtocolType.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
thirdpartyproxy
;
import
com.google.common.collect.Sets
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
import
vc.thinker.absctacts.protocolproxy.enums.IProtocolType
;
import
vc.thinker.web.validator.EnumValidate
;
import
java.util.Objects
;
import
java.util.Set
;
/**
* 第三方协议类型
*
* @author HeTongHao
* @since 2021/7/9 16:20
*/
@Getter
@AllArgsConstructor
public
enum
ProtocolType
implements
IProtocolType
,
EnumValidate
<
String
>
{
/**
* 第三方协议类型
*/
test
(
"test"
,
"测试"
),
/**
* 中央空调
*/
central_air_conditioning
(
"central-air-conditioning"
,
"中央空调"
)
;
static
{
int
total
=
values
().
length
;
Set
<
ProtocolType
>
distinctSet
=
Sets
.
newHashSet
(
values
());
if
(
distinctSet
.
size
()
!=
total
)
{
throw
new
IllegalArgumentException
(
"协议编号有重复,请检查"
);
}
}
/**
* 协议编号
*/
private
final
String
code
;
/**
* 协议名称
*/
private
final
String
name
;
@Override
public
boolean
existValidate
(
String
value
)
{
if
(
value
==
null
)
{
return
false
;
}
for
(
ProtocolType
protocolType
:
ProtocolType
.
values
())
{
if
(
Objects
.
equals
(
protocolType
.
getCode
(),
value
))
{
return
true
;
}
}
return
false
;
}
}
src/main/java/vc/thinker/thirdpartyproxy/protocolimpls/centralAir/CentralAirMeterAttrDefine.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
thirdpartyproxy
.
protocolimpls
.
centralAir
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
import
vc.thinker.absctacts.protocolproxy.enums.DataType
;
import
vc.thinker.absctacts.protocolproxy.enums.IMeterAttrDefine
;
/**
* 中央空调属性协议属性定义
*
* @author HeTongHao
* @since 2021/7/9 16:20
*/
@Getter
@AllArgsConstructor
public
enum
CentralAirMeterAttrDefine
implements
IMeterAttrDefine
{
/**
* 中央空调属性
*/
electricity
(
"electricity"
,
"电量"
,
DataType
.
Float
),
coldCapacity
(
"coldCapacity"
,
"冷量"
,
DataType
.
Int
),
systemCop
(
"systemCop"
,
"系统COP"
,
DataType
.
Float
),
supplyWaterTemp
(
"supplyWaterTemp"
,
"供水温度"
,
DataType
.
Float
),
returnWaterTemp
(
"returnWaterTemp"
,
"回水温度"
,
DataType
.
Float
),
;
/**
* 编号,设备下唯一
*/
private
final
String
code
;
/**
* 属性名称
*/
private
final
String
name
;
/**
* 数据类型
*/
private
final
DataType
dataType
;
}
src/main/java/vc/thinker/thirdpartyproxy/protocolimpls/centralAir/CentralAirProtocol.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
thirdpartyproxy
.
protocolimpls
.
centralAir
;
import
com.alibaba.fastjson.JSONObject
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Component
;
import
org.springframework.util.ObjectUtils
;
import
vc.thinker.absctacts.protocolproxy.dto.MeterReportEntity
;
import
vc.thinker.absctacts.protocolproxy.enums.IProtocolType
;
import
vc.thinker.absctacts.protocolproxy.protocol.AbstractThirdPartyProtocolSyncMeterInfo
;
import
vc.thinker.thirdpartyproxy.ProtocolType
;
import
vc.thinker.thirdpartyproxy.protocolimpls.centralAir.dto.DataReportInfoDTO
;
import
vc.thinker.thirdpartyproxy.protocolimpls.centralAir.dto.DataReportParamDTO
;
import
java.time.LocalDateTime
;
import
java.time.ZoneOffset
;
/**
* 中央空调代理上报网关协议
*
* @author HeTongHao
* @since 2021/7/9 17:13
*/
@Slf4j
@Component
@RequiredArgsConstructor
public
class
CentralAirProtocol
extends
AbstractThirdPartyProtocolSyncMeterInfo
implements
TerminalReportData
{
@Override
public
IProtocolType
protocolType
()
{
return
ProtocolType
.
central_air_conditioning
;
}
@Override
public
void
dataReport
(
DataReportInfoDTO
dataReportInfoDTO
)
{
LocalDateTime
time
=
LocalDateTime
.
ofEpochSecond
(
dataReportInfoDTO
.
getTimestamp
()/
1000L
,
0
,
ZoneOffset
.
of
(
"+8"
));
String
deviceId
=
lastDeviceId
(
dataReportInfoDTO
);
DataReportParamDTO
paramDTO
=
dataReportInfoDTO
.
getData
();
if
(
ObjectUtils
.
isEmpty
(
paramDTO
)){
return
;
}
MeterReportEntity
.
MeterReportEntityBuilder
builder
=
MeterReportEntity
.
builder
(
deviceId
,
time
);
if
(!
ObjectUtils
.
isEmpty
(
paramDTO
.
getElectricity
())){
builder
.
putValue
(
CentralAirMeterAttrDefine
.
electricity
,
dataReportInfoDTO
.
getData
().
getElectricity
());
}
if
(!
ObjectUtils
.
isEmpty
(
paramDTO
.
getColdCapacity
()))
{
builder
.
putValue
(
CentralAirMeterAttrDefine
.
coldCapacity
,
dataReportInfoDTO
.
getData
().
getColdCapacity
());
}
if
(!
ObjectUtils
.
isEmpty
(
paramDTO
.
getSystemCop
()))
{
builder
.
putValue
(
CentralAirMeterAttrDefine
.
systemCop
,
dataReportInfoDTO
.
getData
().
getSystemCop
());
}
if
(!
ObjectUtils
.
isEmpty
(
paramDTO
.
getSupplyWaterTemp
()))
{
builder
.
putValue
(
CentralAirMeterAttrDefine
.
supplyWaterTemp
,
dataReportInfoDTO
.
getData
().
getSupplyWaterTemp
());
}
if
(!
ObjectUtils
.
isEmpty
(
paramDTO
.
getReturnWaterTemp
()))
{
builder
.
putValue
(
CentralAirMeterAttrDefine
.
returnWaterTemp
,
dataReportInfoDTO
.
getData
().
getReturnWaterTemp
());
}
MeterReportEntity
meterReport
=
builder
.
build
();
System
.
out
.
println
(
"____"
+
JSONObject
.
toJSONString
(
meterReport
));
//report(meterReport);
}
}
src/main/java/vc/thinker/thirdpartyproxy/protocolimpls/centralAir/TerminalReportData.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
thirdpartyproxy
.
protocolimpls
.
centralAir
;
import
vc.thinker.absctacts.protocolproxy.exceptions.MeterCodeFormatException
;
import
vc.thinker.thirdpartyproxy.protocolimpls.centralAir.dto.DataReportInfoDTO
;
/**
* WfIot上报数据接口定义
*
* @author HeTongHao
* @since 2022/8/10 21:08
*/
public
interface
TerminalReportData
{
/**
* 根据设备dto生成最终的设备id
*
* @param dataReportInfoDTO 设备上报信息dto
* @return deviceId
*/
default
String
lastDeviceId
(
DataReportInfoDTO
dataReportInfoDTO
)
{
return
dataReportInfoDTO
.
getProtocolCode
()
+
"@"
+
dataReportInfoDTO
.
getDeviceAddress
();
}
/**
* 根据仪表编号拆分成网关编号与deviceId
*
* @param meterCode 仪表编号
* @return deviceId
*/
default
DataReportInfoDTO
splitCode
(
String
meterCode
)
{
String
[]
split
=
meterCode
.
split
(
"@"
);
int
codeItemNum
=
2
;
if
(
split
.
length
!=
codeItemNum
)
{
throw
new
MeterCodeFormatException
(
"CentralAir 仪表编号格式错误:"
+
meterCode
);
}
return
DataReportInfoDTO
.
builder
()
.
protocolCode
(
split
[
0
])
.
deviceAddress
(
split
[
1
])
.
build
();
}
/**
* 终端设备上报信息
*
* @param dataReportInfoDTO 设备参数信息
*/
void
dataReport
(
DataReportInfoDTO
dataReportInfoDTO
);
}
src/main/java/vc/thinker/thirdpartyproxy/protocolimpls/centralAir/dto/DataReportInfoDTO.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
thirdpartyproxy
.
protocolimpls
.
centralAir
.
dto
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Builder
;
import
lombok.Data
;
/**
* @author : xieshaojun
* @date : 2023/1/3 14:23
*/
@Data
@Builder
public
class
DataReportInfoDTO
{
@ApiModelProperty
(
"协议编号"
)
private
String
protocolCode
;
@ApiModelProperty
(
"设备唯一地址"
)
private
String
deviceAddress
;
@ApiModelProperty
(
"时间戳"
)
private
Long
timestamp
;
@ApiModelProperty
(
"协议数据"
)
private
DataReportParamDTO
data
;
}
src/main/java/vc/thinker/thirdpartyproxy/protocolimpls/centralAir/dto/DataReportParamDTO.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
thirdpartyproxy
.
protocolimpls
.
centralAir
.
dto
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
import
java.math.BigDecimal
;
/**
* @author : xieshaojun
* @date : 2023/1/3 14:24
*/
@Data
public
class
DataReportParamDTO
{
@ApiModelProperty
(
"电量"
)
private
BigDecimal
electricity
;
@ApiModelProperty
(
"冷量"
)
private
BigDecimal
coldCapacity
;
@ApiModelProperty
(
"系统COP"
)
private
BigDecimal
systemCop
;
@ApiModelProperty
(
"供水温度"
)
private
BigDecimal
supplyWaterTemp
;
@ApiModelProperty
(
"回水温度"
)
private
BigDecimal
returnWaterTemp
;
}
src/main/java/vc/thinker/thirdpartyproxy/protocolimpls/test/TestMeterAttrDefine.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
thirdpartyproxy
.
protocolimpls
.
test
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
import
vc.thinker.absctacts.protocolproxy.enums.DataType
;
import
vc.thinker.absctacts.protocolproxy.enums.IMeterAttrDefine
;
/**
* 测试协议属性定义
*
* @author HeTongHao
* @since 2021/7/9 16:20
*/
@Getter
@AllArgsConstructor
public
enum
TestMeterAttrDefine
implements
IMeterAttrDefine
{
/**
* 数据组
*/
current
(
"current"
,
"电压"
,
DataType
.
Float
),
voltage
(
"voltage"
,
"电流"
,
DataType
.
Float
),
Active_energy
(
"Active_energy"
,
"有功电能"
,
DataType
.
Float
),
;
/**
* 编号,设备下唯一
*/
private
final
String
code
;
/**
* 属性名称
*/
private
final
String
name
;
/**
* 数据类型
*/
private
final
DataType
dataType
;
}
src/main/java/vc/thinker/thirdpartyproxy/protocolimpls/test/TestMeterEventDefine.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
thirdpartyproxy
.
protocolimpls
.
test
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
import
vc.thinker.absctacts.protocolproxy.enums.IMeterEventDefine
;
/**
* 测试协议事件定义
*
* @author HeTongHao
* @since 2021/7/9 16:20
*/
@Getter
@AllArgsConstructor
public
enum
TestMeterEventDefine
implements
IMeterEventDefine
{
/**
* 数据组
*/
alert
(
"alert"
,
"告警"
),
shutdown
(
"shutdown"
,
"停机"
),
;
/**
* 编号,设备下唯一
*/
private
final
String
code
;
/**
* 属性名称
*/
private
final
String
name
;
}
src/main/java/vc/thinker/thirdpartyproxy/protocolimpls/test/TestProtocol.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
thirdpartyproxy
.
protocolimpls
.
test
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Maps
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Component
;
import
vc.thinker.absctacts.protocolproxy.dto.IMeterReportEntity
;
import
vc.thinker.absctacts.protocolproxy.dto.MeterReportEntity
;
import
vc.thinker.absctacts.protocolproxy.enums.IMeterDataDefine
;
import
vc.thinker.absctacts.protocolproxy.enums.IProtocolType
;
import
vc.thinker.absctacts.protocolproxy.protocol.AbstractThirdPartyProtocol
;
import
vc.thinker.thirdpartyproxy.ProtocolType
;
import
java.time.LocalDateTime
;
import
java.util.List
;
import
java.util.Map
;
/**
* @author HeTongHao
* @since 2021/7/9 17:13
*/
@Slf4j
@Component
public
class
TestProtocol
extends
AbstractThirdPartyProtocol
{
@Override
public
IProtocolType
protocolType
()
{
return
ProtocolType
.
test
;
}
// @Scheduled(cron = "* * * * * *")
public
void
report
()
{
super
.
report
(
MeterReportEntity
.
builder
(
"001"
,
LocalDateTime
.
now
())
.
putValue
(
TestMeterAttrDefine
.
voltage
,
111
)
.
putValue
(
TestMeterAttrDefine
.
current
,
100
)
.
putValue
(
TestMeterAttrDefine
.
Active_energy
,
123456.233
)
.
putValue
(
TestMeterEventDefine
.
alert
,
true
)
.
putValue
(
TestMeterEventDefine
.
shutdown
,
false
)
.
build
()
);
}
// @Scheduled(cron = "* * * * * *")
public
void
reportMulti
()
{
List
<
IMeterReportEntity
>
meterReportEntityList
=
Lists
.
newArrayList
();
for
(
int
i
=
0
;
i
<
3
;
i
++)
{
Map
<
IMeterDataDefine
,
Object
>
map
=
Maps
.
newLinkedHashMap
();
map
.
put
(
TestMeterAttrDefine
.
current
,
100
);
map
.
put
(
TestMeterAttrDefine
.
voltage
,
111
);
map
.
put
(
TestMeterAttrDefine
.
Active_energy
,
123456.233
);
map
.
put
(
TestMeterEventDefine
.
alert
,
true
);
map
.
put
(
TestMeterEventDefine
.
shutdown
,
false
);
meterReportEntityList
.
add
(
MeterReportEntity
.
builder
(
"001"
,
LocalDateTime
.
now
())
.
putValues
(
map
)
.
build
());
}
super
.
report
(
meterReportEntityList
);
}
}
src/main/java/vc/thinker/tools/StartTool.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
tools
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Component
;
import
javax.annotation.PostConstruct
;
/**
* 用于确定线上发版更新正常
* 打印一个版本
*
* @author HeTongHao
* @since 2022/12/20 11:03
*/
@Slf4j
@Component
public
class
StartTool
{
@PostConstruct
public
void
start
()
{
log
.
info
(
"启动:1"
);
}
}
src/main/java/vc/thinker/utils/CompletableFutureObserver.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
utils
;
import
com.google.common.collect.Maps
;
import
java.util.Map
;
import
java.util.concurrent.CompletableFuture
;
import
java.util.concurrent.ExecutionException
;
import
java.util.concurrent.TimeUnit
;
/**
* 合并未来的观察者
* 用于维护一批需要合并同步结果的线程关系
*
* @author HeTongHao
* @since 2022/8/10 16:43
*/
public
class
CompletableFutureObserver
<
T
>
{
private
final
Map
<
String
,
CompletableFuture
<
T
>>
completableFutureMap
=
Maps
.
newConcurrentMap
();
public
CompletableFuture
<
T
>
subscribe
(
String
key
)
{
CompletableFuture
<
T
>
completableFuture
=
new
CompletableFuture
<>();
completableFutureMap
.
put
(
key
,
completableFuture
);
return
completableFuture
;
}
public
void
onMessage
(
String
key
,
T
msg
)
{
CompletableFuture
<
T
>
completableFuture
=
completableFutureMap
.
get
(
key
);
if
(
completableFuture
!=
null
)
{
completableFuture
.
complete
(
msg
);
completableFutureMap
.
remove
(
key
);
}
}
public
static
void
main
(
String
[]
args
)
throws
ExecutionException
,
InterruptedException
{
CompletableFuture
<
String
>
completableFuture
=
new
CompletableFuture
<>();
new
Thread
(()
->
{
try
{
TimeUnit
.
SECONDS
.
sleep
(
2
);
}
catch
(
InterruptedException
e
)
{
e
.
printStackTrace
();
}
completableFuture
.
complete
(
"666"
);
}).
start
();
String
o
=
completableFuture
.
get
();
System
.
out
.
println
(
o
);
}
}
src/main/java/vc/thinker/utils/DES.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
utils
;
import
javax.crypto.Cipher
;
import
javax.crypto.SecretKey
;
import
javax.crypto.SecretKeyFactory
;
import
javax.crypto.spec.DESKeySpec
;
import
java.security.SecureRandom
;
/**
* DES加密介绍
* DES是一种对称加密算法,所谓对称加密算法即:加密和解密使用相同密钥的算法。DES加密算法出自IBM的研究,
* 后来被美国政府正式采用,之后开始广泛流传,但是近些年使用越来越少,因为DES使用56位密钥,以现代计算能力,
* 24小时内即可被破解。虽然如此,在某些简单应用中,我们还是可以使用DES加密算法,本文简单讲解DES的JAVA实现
* 。
* 注意:DES加密和解密过程中,密钥长度都必须是8的倍数
*/
public
class
DES
{
//测试
public
static
void
main
(
String
[]
args
)
{
//待加密内容
String
str
=
"测试内容"
;
//密码,长度要是8的倍数
String
password
=
"9588028820109132570743325311898426347857298773549468758875018579537757772163084478873699447306034466200616411960574122434059469100235892702736860872901247123456"
;
byte
[]
result
=
DES
.
encrypt
(
str
.
getBytes
(),
password
);
System
.
out
.
println
(
"加密后:"
+
new
String
(
result
));
//直接将如上内容解密
try
{
byte
[]
decryResult
=
DES
.
decrypt
(
result
,
password
);
System
.
out
.
println
(
"解密后:"
+
new
String
(
decryResult
));
}
catch
(
Exception
e1
)
{
e1
.
printStackTrace
();
}
}
/**
* 加密
*
* @param datasource byte[]
* @param password String
* @return byte[]
*/
public
static
byte
[]
encrypt
(
byte
[]
datasource
,
String
password
)
{
try
{
SecureRandom
random
=
new
SecureRandom
();
DESKeySpec
desKey
=
new
DESKeySpec
(
password
.
getBytes
());
//创建一个密匙工厂,然后用它把DESKeySpec转换成
SecretKeyFactory
keyFactory
=
SecretKeyFactory
.
getInstance
(
"DES"
);
SecretKey
securekey
=
keyFactory
.
generateSecret
(
desKey
);
//Cipher对象实际完成加密操作
Cipher
cipher
=
Cipher
.
getInstance
(
"DES"
);
//用密匙初始化Cipher对象
cipher
.
init
(
Cipher
.
ENCRYPT_MODE
,
securekey
,
random
);
//现在,获取数据并加密
//正式执行加密操作
return
cipher
.
doFinal
(
datasource
);
}
catch
(
Throwable
e
)
{
e
.
printStackTrace
();
}
return
null
;
}
/**
* 解密
*
* @param src byte[]
* @param password String
* @return byte[]
* @throws Exception
*/
public
static
byte
[]
decrypt
(
byte
[]
src
,
String
password
)
throws
Exception
{
// DES算法要求有一个可信任的随机数源
SecureRandom
random
=
new
SecureRandom
();
// 创建一个DESKeySpec对象
DESKeySpec
desKey
=
new
DESKeySpec
(
password
.
getBytes
());
// 创建一个密匙工厂
SecretKeyFactory
keyFactory
=
SecretKeyFactory
.
getInstance
(
"DES"
);
// 将DESKeySpec对象转换成SecretKey对象
SecretKey
securekey
=
keyFactory
.
generateSecret
(
desKey
);
// Cipher对象实际完成解密操作
Cipher
cipher
=
Cipher
.
getInstance
(
"DES"
);
// 用密匙初始化Cipher对象
cipher
.
init
(
Cipher
.
DECRYPT_MODE
,
securekey
,
random
);
// 真正开始解密操作
return
cipher
.
doFinal
(
src
);
}
}
\ No newline at end of file
src/main/java/vc/thinker/utils/LocalDateTimeUtils.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
utils
;
import
lombok.extern.slf4j.Slf4j
;
import
java.time.LocalDateTime
;
import
java.time.ZoneId
;
import
java.time.temporal.TemporalAdjusters
;
import
java.util.Date
;
/**
* @author : xieshaojun
* @date : 2023/1/3 17:55
*/
@Slf4j
public
class
LocalDateTimeUtils
{
/**
* 默认时区
*/
private
static
final
ZoneId
SYSTEM_ZONE_ID
=
ZoneId
.
systemDefault
();
/**
* LocalDateTime转换Date
*
* @param localDateTime
* @return
*/
public
static
Date
toDate
(
final
LocalDateTime
localDateTime
)
{
return
Date
.
from
(
localDateTime
.
atZone
(
SYSTEM_ZONE_ID
).
toInstant
());
}
/**
* Date转换LocalDateTime
*
* @param date
* @return
*/
public
static
LocalDateTime
toLocalDateTime
(
final
Date
date
)
{
return
LocalDateTime
.
ofInstant
(
date
.
toInstant
(),
SYSTEM_ZONE_ID
);
}
/**
* 获取一天的开始
*
* @return LocalDateTime
*/
public
static
LocalDateTime
getTheStartOfTheDay
()
{
return
LocalDateTime
.
now
().
withHour
(
0
).
withMinute
(
0
).
withSecond
(
0
).
withNano
(
0
);
}
/**
* 获取一天的结束
*
* @return LocalDateTime
*/
public
static
LocalDateTime
getTheEndOfTheDay
()
{
return
LocalDateTime
.
now
().
withHour
(
23
).
withMinute
(
59
).
withSecond
(
59
).
withNano
(
0
);
}
/**
* 设置一天的开始
*
* @param localDateTime
* @return LocalDateTime
*/
public
static
LocalDateTime
setTheStartOfTheDay
(
final
LocalDateTime
localDateTime
)
{
return
localDateTime
.
withHour
(
0
).
withMinute
(
0
).
withSecond
(
0
).
withNano
(
0
);
}
/**
* 设置一天的结束
*
* @param localDateTime
* @return LocalDateTime
*/
public
static
LocalDateTime
setTheEndOfTheDay
(
final
LocalDateTime
localDateTime
)
{
return
localDateTime
.
withHour
(
23
).
withMinute
(
59
).
withSecond
(
59
).
withNano
(
0
);
}
/**
* 设置一天的开始
*
* @param date
* @return Date
*/
public
static
Date
setTheStartOfTheDay
(
final
Date
date
)
{
return
toDate
(
setTheStartOfTheDay
(
toLocalDateTime
(
date
)));
}
/**
* 设置一天的结束
*
* @param date
* @return Date
*/
public
static
Date
setTheEndOfTheDay
(
final
Date
date
)
{
return
toDate
(
setTheEndOfTheDay
(
toLocalDateTime
(
date
)));
}
/**
* 填满时间的月
*/
public
static
Date
fillMonth
(
final
Date
date
)
{
return
toDate
(
toLocalDateTime
(
date
).
withMonth
(
12
));
}
/**
* 填满时间的日
*/
public
static
Date
fillDay
(
final
Date
date
)
{
return
toDate
(
toLocalDateTime
(
date
).
with
(
TemporalAdjusters
.
lastDayOfMonth
()));
}
/**
* 填满时间的月
*/
public
static
LocalDateTime
fillMonth
(
final
LocalDateTime
date
)
{
return
date
.
withMonth
(
12
);
}
/**
* 填满时间的日
*/
public
static
LocalDateTime
fillDay
(
final
LocalDateTime
date
)
{
return
date
.
with
(
TemporalAdjusters
.
lastDayOfMonth
());
}
/**
* 测试方法
*
* @param args
*/
public
static
void
main
(
String
[]
args
)
{
System
.
out
.
println
(
intervalDay
(
LocalDateTime
.
of
(
2017
,
8
,
5
,
00
,
00
),
LocalDateTime
.
of
(
2019
,
8
,
6
,
00
,
00
)));
}
/**
* 将LocalDateTime转为timestamp
*
* @param localDateTime
* @return
*/
public
static
long
parseToTimestamp
(
LocalDateTime
localDateTime
)
{
return
localDateTime
.
atZone
(
ZoneId
.
systemDefault
()).
toInstant
().
toEpochMilli
();
}
/**
* 设置时间的月的开始
*
* @param localDateTime
* @return LocalDateTime
*/
public
static
LocalDateTime
setTheStartOfTheMonth
(
final
LocalDateTime
localDateTime
)
{
return
setTheStartOfTheDay
(
localDateTime
).
withDayOfMonth
(
1
);
}
/**
* 设置时间的月的结束
*
* @param localDateTime
* @return LocalDateTime
*/
public
static
LocalDateTime
setTheEndOfTheMonth
(
final
LocalDateTime
localDateTime
)
{
return
setTheEndOfTheDay
(
localDateTime
).
withDayOfMonth
(
1
).
plusMonths
(
1
).
minusDays
(
1
);
}
/**
* 设置时间的年的开始
*
* @param localDateTime
* @return LocalDateTime
*/
public
static
LocalDateTime
setTheStartOfTheYear
(
final
LocalDateTime
localDateTime
)
{
return
setTheStartOfTheMonth
(
localDateTime
.
withMonth
(
1
));
}
/**
* 设置时间的年的结束
*
* @param localDateTime
* @return LocalDateTime
*/
public
static
LocalDateTime
setTheEndOfTheYear
(
final
LocalDateTime
localDateTime
)
{
return
setTheEndOfTheMonth
(
localDateTime
.
withMonth
(
12
));
}
/**
* 两个时间间隔的毫秒数
*
* @param subtractedTimestamp 被减时间
* @param subtractTimestamp 减时间
* @return 时间戳差值
*/
public
static
long
intervalTimestamp
(
LocalDateTime
subtractedTimestamp
,
LocalDateTime
subtractTimestamp
)
{
return
parseToTimestamp
(
subtractedTimestamp
)
-
parseToTimestamp
(
subtractTimestamp
);
}
/**
* 两个时间间隔的分钟
*
* @param subtractedTimestamp 被减时间
* @param subtractTimestamp 减时间
* @return 分钟差值
*/
public
static
long
intervalMinute
(
LocalDateTime
subtractedTimestamp
,
LocalDateTime
subtractTimestamp
)
{
return
intervalTimestamp
(
subtractedTimestamp
,
subtractTimestamp
)
/
1000
/
60
;
}
/**
* 两个时间间隔的分钟
*
* @param subtractedTimestamp 被减时间
* @param subtractTimestamp 减时间
* @return 分钟差值
*/
public
static
long
intervalDay
(
LocalDateTime
subtractedTimestamp
,
LocalDateTime
subtractTimestamp
)
{
return
intervalMinute
(
subtractedTimestamp
,
subtractTimestamp
)
/
60
/
24
;
}
}
src/main/java/vc/thinker/utils/Resolve.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
utils
;
import
com.google.common.collect.Maps
;
import
org.springframework.lang.Nullable
;
import
java.util.Map
;
import
java.util.function.Function
;
/**
* 枚举解析器
*
* @author HeTongHao
* @since 2021/6/17 16:34
*/
public
class
Resolve
<
T
,
K
>
{
private
final
Map
<
K
,
T
>
keyValueMap
=
Maps
.
newHashMap
();
/**
* 构造
*
* @param values 枚举数组
* @param resolveKey 根据那个字段解析
*/
public
Resolve
(
T
[]
values
,
Function
<
T
,
K
>
resolveKey
)
{
for
(
T
value
:
values
)
{
keyValueMap
.
put
(
resolveKey
.
apply
(
value
),
value
);
}
}
@Nullable
public
T
resolve
(
K
key
)
{
return
keyValueMap
.
get
(
key
);
}
}
src/main/java/vc/thinker/utils/ResolveMultipart.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
utils
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Maps
;
import
org.springframework.lang.Nullable
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.function.Function
;
/**
* 枚举解析器 解析出多个枚举
*
* @author HeTongHao
* @since 2021/6/17 16:34
*/
public
class
ResolveMultipart
<
T
,
K
>
{
private
final
Map
<
K
,
List
<
T
>>
keyValueMap
=
Maps
.
newHashMap
();
/**
* 构造
*
* @param values 枚举数组
* @param resolveKey 根据那个字段解析
*/
public
ResolveMultipart
(
T
[]
values
,
Function
<
T
,
K
>
resolveKey
)
{
for
(
T
value
:
values
)
{
keyValueMap
.
computeIfAbsent
(
resolveKey
.
apply
(
value
),
k
->
Lists
.
newLinkedList
()).
add
(
value
);
}
}
public
ResolveMultipart
(
List
<
T
>
values
,
Function
<
T
,
K
>
resolveKey
)
{
for
(
T
value
:
values
)
{
keyValueMap
.
computeIfAbsent
(
resolveKey
.
apply
(
value
),
k
->
Lists
.
newLinkedList
()).
add
(
value
);
}
}
@Nullable
public
List
<
T
>
resolve
(
K
key
)
{
return
keyValueMap
.
get
(
key
);
}
}
src/main/java/vc/thinker/utils/SpringContextHolder.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
utils
;
import
org.apache.commons.lang3.Validate
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.DisposableBean
;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.context.ApplicationContextAware
;
import
org.springframework.core.io.DefaultResourceLoader
;
import
java.io.IOException
;
/**
* @author : xieshaojun
* @date : 2023/1/3 17:51
*/
public
class
SpringContextHolder
implements
ApplicationContextAware
,
DisposableBean
{
private
static
ApplicationContext
applicationContext
=
null
;
private
static
Logger
logger
=
LoggerFactory
.
getLogger
(
SpringContextHolder
.
class
);
/**
* 取得存储在静态变量中的ApplicationContext.
*/
public
static
ApplicationContext
getApplicationContext
()
{
assertContextInjected
();
return
applicationContext
;
}
public
static
String
getRootRealPath
(){
String
rootRealPath
=
""
;
try
{
rootRealPath
=
getApplicationContext
().
getResource
(
""
).
getFile
().
getAbsolutePath
();
}
catch
(
IOException
e
)
{
logger
.
warn
(
"获取系统根目录失败"
);
}
return
rootRealPath
;
}
public
static
String
getResourceRootRealPath
(){
String
rootRealPath
=
""
;
try
{
rootRealPath
=
new
DefaultResourceLoader
().
getResource
(
""
).
getFile
().
getAbsolutePath
();
}
catch
(
IOException
e
)
{
logger
.
warn
(
"获取资源根目录失败"
);
}
return
rootRealPath
;
}
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
@SuppressWarnings
(
"unchecked"
)
public
static
<
T
>
T
getBean
(
String
name
)
{
assertContextInjected
();
return
(
T
)
applicationContext
.
getBean
(
name
);
}
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
public
static
<
T
>
T
getBean
(
Class
<
T
>
requiredType
)
{
assertContextInjected
();
return
applicationContext
.
getBean
(
requiredType
);
}
/**
* 清除SpringContextHolder中的ApplicationContext为Null.
*/
public
static
void
clearHolder
()
{
if
(
logger
.
isDebugEnabled
()){
logger
.
debug
(
"清除SpringContextHolder中的ApplicationContext:"
+
applicationContext
);
}
applicationContext
=
null
;
}
/**
* 实现ApplicationContextAware接口, 注入Context到静态变量中.
*/
@Override
public
void
setApplicationContext
(
ApplicationContext
applicationContext
)
{
// logger.debug("注入ApplicationContext到SpringContextHolder:{}", applicationContext);
if
(
SpringContextHolder
.
applicationContext
!=
null
)
{
logger
.
info
(
"SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:"
+
SpringContextHolder
.
applicationContext
);
}
SpringContextHolder
.
applicationContext
=
applicationContext
;
// NOSONAR
}
/**
* 实现DisposableBean接口, 在Context关闭时清理静态变量.
*/
@Override
public
void
destroy
()
throws
Exception
{
SpringContextHolder
.
clearHolder
();
}
/**
* 检查ApplicationContext不为空.
*/
private
static
void
assertContextInjected
()
{
Validate
.
validState
(
applicationContext
!=
null
,
"applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder."
);
}
}
src/main/java/vc/thinker/utils/StringFormaterUtils.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
utils
;
import
org.slf4j.helpers.MessageFormatter
;
/**
* @author : xieshaojun
* @date : 2023/1/3 17:54
*/
public
class
StringFormaterUtils
{
/**
* 用{}作为占位符,格式化字符串
*
* @param format
* @param argArray
* @return
*/
public
static
String
format
(
String
format
,
Object
...
argArray
)
{
return
MessageFormatter
.
arrayFormat
(
format
,
argArray
).
getMessage
();
}
}
src/main/java/vc/thinker/utils/SynchronizeSignal.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
utils
;
import
lombok.Data
;
import
java.time.Duration
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.locks.Condition
;
import
java.util.concurrent.locks.Lock
;
import
java.util.concurrent.locks.ReentrantLock
;
/**
* 同步信号通信
*
* @author HeTongHao
* @since 2020/7/9 19:50
*/
@Data
public
class
SynchronizeSignal
{
public
SynchronizeSignal
()
{
this
(
new
ReentrantLock
());
}
public
SynchronizeSignal
(
Lock
lock
)
{
this
.
lock
=
lock
;
this
.
condition
=
this
.
lock
.
newCondition
();
}
private
Lock
lock
;
private
Condition
condition
;
public
void
signal
()
{
lock
.
lock
();
try
{
condition
.
signal
();
}
finally
{
lock
.
unlock
();
}
}
public
boolean
await
(
Duration
duration
)
{
return
await
(
duration
.
toMillis
(),
TimeUnit
.
MILLISECONDS
);
}
public
boolean
await
(
long
time
,
TimeUnit
unit
)
{
lock
.
lock
();
try
{
return
condition
.
await
(
time
,
unit
);
}
catch
(
InterruptedException
e
)
{
e
.
printStackTrace
();
}
finally
{
lock
.
unlock
();
}
return
false
;
}
}
src/main/java/vc/thinker/utils/dependhandle/DependsInfoTools.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
utils
.
dependhandle
;
import
com.google.common.collect.Lists
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Objects
;
import
java.util.Optional
;
import
java.util.function.Function
;
import
java.util.function.UnaryOperator
;
import
java.util.stream.Collectors
;
/**
* 依赖属性查询工具
*
* @author HeTongHao
* @since 2021/1/5 21:02
*/
public
class
DependsInfoTools
{
/**
* 批量设置依赖信息
*
* @param handleList 需要处理的对象列表
* @param foreignKey 需要处理的对象的外键(拿这个外键去查依赖)
* @param selectDependList 根据所有外键查询依赖列表的过程
* @param primaryKey 查询出依赖的主键(与外键对应)
* @param setValueHandler 依赖属性设置过程
* @param <T> 需要处理的对象类型
* @param <D> 依赖对象类型
* @param <K> 主键与外键的类型
*/
public
static
<
T
,
D
,
K
>
void
batchSetDependInfo
(
List
<
T
>
handleList
,
Function
<
T
,
K
>
foreignKey
,
Function
<
List
<
K
>,
List
<
D
>>
selectDependList
,
Function
<
D
,
K
>
primaryKey
,
SetValueHandler
<
T
,
D
>
setValueHandler
)
{
if
(
handleList
.
isEmpty
())
{
return
;
}
List
<
K
>
idList
=
genIds
(
handleList
,
foreignKey
);
if
(!
idList
.
isEmpty
())
{
List
<
D
>
dependList
=
selectDependList
.
apply
(
idList
);
setDependProperty
(
handleList
,
foreignKey
,
dependList
,
primaryKey
,
setValueHandler
);
}
}
/**
* 批量设置依赖信息
*
* @param handleList 需要处理的对象列表
* @param selectDependList 根据所有外键查询依赖列表的过程
* @param primaryKey 查询出依赖的主键(与外键对应)
* @param keyValueHandlerRelations 外键与值处理的映射关系
* @param <T> 需要处理的对象类型
* @param <D> 依赖对象类型
* @param <K> 主键与外键的类型
*/
public
static
<
T
,
D
,
K
>
void
batchSetDependInfo
(
List
<
T
>
handleList
,
Function
<
List
<
K
>,
List
<
D
>>
selectDependList
,
Function
<
D
,
K
>
primaryKey
,
List
<
KeyValueHandlerRelation
<
T
,
D
,
K
>>
keyValueHandlerRelations
)
{
if
(
handleList
.
isEmpty
())
{
return
;
}
List
<
Function
<
T
,
K
>>
foreignKeys
=
keyValueHandlerRelations
.
stream
().
map
(
KeyValueHandlerRelation:
:
getForeignKey
).
collect
(
Collectors
.
toList
());
List
<
K
>
idList
=
genIds
(
handleList
,
foreignKeys
);
if
(!
idList
.
isEmpty
())
{
List
<
D
>
dependList
=
selectDependList
.
apply
(
idList
);
setDependProperty
(
handleList
,
dependList
,
primaryKey
,
keyValueHandlerRelations
);
}
}
@SafeVarargs
public
static
<
T
,
D
,
K
>
void
batchSetDependInfo
(
List
<
T
>
handleList
,
Function
<
List
<
K
>,
List
<
D
>>
selectDependList
,
Function
<
D
,
K
>
primaryKey
,
KeyValueHandlerRelation
<
T
,
D
,
K
>...
keyValueHandlerRelations
)
{
batchSetDependInfo
(
handleList
,
selectDependList
,
primaryKey
,
Lists
.
newArrayList
(
keyValueHandlerRelations
));
}
private
static
<
T
,
K
>
List
<
K
>
genIds
(
List
<
T
>
handleList
,
Function
<
T
,
K
>
foreignKey
)
{
return
handleList
.
isEmpty
()
?
Lists
.
newArrayList
()
:
handleList
.
parallelStream
().
map
(
foreignKey
).
filter
(
Objects:
:
nonNull
).
collect
(
Collectors
.
toList
());
}
private
static
<
T
,
K
>
List
<
K
>
genIds
(
List
<
T
>
handleList
,
List
<
Function
<
T
,
K
>>
foreignKeys
)
{
List
<
K
>
ids
=
Lists
.
newCopyOnWriteArrayList
();
if
(!
handleList
.
isEmpty
())
{
handleList
.
parallelStream
().
forEach
(
handle
->
foreignKeys
.
forEach
(
tkFunction
->
Optional
.
ofNullable
(
tkFunction
.
apply
(
handle
)).
ifPresent
(
ids:
:
add
)));
}
return
ids
;
}
private
static
<
T
,
D
,
K
>
void
setDependProperty
(
List
<
T
>
handleList
,
Function
<
T
,
K
>
foreignKey
,
List
<
D
>
dependList
,
Function
<
D
,
K
>
primaryKey
,
SetValueHandler
<
T
,
D
>
setValueHandler
)
{
dependList
.
forEach
(
depend
->
{
K
primaryId
=
primaryKey
.
apply
(
depend
);
handleList
.
parallelStream
().
forEach
(
setObject
->
Optional
.
ofNullable
(
foreignKey
.
apply
(
setObject
)).
ifPresent
(
foreignId
->
{
if
(
foreignId
.
equals
(
primaryId
))
{
setValueHandler
.
set
(
setObject
,
depend
);
}
})
);
});
}
private
static
<
T
,
D
,
K
>
void
setDependProperty
(
List
<
T
>
handleList
,
List
<
D
>
dependList
,
Function
<
D
,
K
>
primaryKey
,
List
<
KeyValueHandlerRelation
<
T
,
D
,
K
>>
keyValueHandlerRelations
)
{
Map
<
K
,
D
>
idDependsList
=
dependList
.
parallelStream
().
collect
(
Collectors
.
toMap
(
primaryKey
,
UnaryOperator
.
identity
()));
handleList
.
parallelStream
().
forEach
(
setObject
->
keyValueHandlerRelations
.
forEach
(
tdkKeyValueHandlerRelation
->
{
K
dependId
=
tdkKeyValueHandlerRelation
.
getForeignKey
().
apply
(
setObject
);
Optional
.
ofNullable
(
idDependsList
.
get
(
dependId
))
.
ifPresent
(
depend
->
tdkKeyValueHandlerRelation
.
getSetValueHandler
().
set
(
setObject
,
depend
));
}));
}
}
src/main/java/vc/thinker/utils/dependhandle/KeyValueHandlerRelation.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
utils
.
dependhandle
;
import
lombok.AllArgsConstructor
;
import
lombok.Data
;
import
java.util.function.Function
;
/**
* 外键与设置过程关系
*
* @author HeTongHao
* @since 2021/1/6 13:57
*/
@Data
@AllArgsConstructor
public
class
KeyValueHandlerRelation
<
T
,
D
,
K
>
{
public
static
<
T
,
D
,
K
>
KeyValueHandlerRelation
<
T
,
D
,
K
>
of
(
Function
<
T
,
K
>
foreignKey
,
SetValueHandler
<
T
,
D
>
setValueHandler
)
{
return
new
KeyValueHandlerRelation
<>(
foreignKey
,
setValueHandler
);
}
private
Function
<
T
,
K
>
foreignKey
;
private
SetValueHandler
<
T
,
D
>
setValueHandler
;
}
src/main/java/vc/thinker/utils/dependhandle/SetValueHandler.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
utils
.
dependhandle
;
/**
* 值设置过程
*
* @author HeTongHao
* @since 2021/1/6 10:02
*/
@FunctionalInterface
public
interface
SetValueHandler
<
T
,
D
>
{
/**
* 依赖设置过程
*
* @param setObject 被设置属性的对象
* @param value 待设置的值
*/
void
set
(
T
setObject
,
D
value
);
}
src/main/java/vc/thinker/web/CentralAirController.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
web
;
import
com.alibaba.fastjson.JSONObject
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
lombok.RequiredArgsConstructor
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.PutMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
vc.thinker.thirdpartyproxy.ProtocolType
;
import
vc.thinker.thirdpartyproxy.protocolimpls.centralAir.CentralAirProtocol
;
import
vc.thinker.thirdpartyproxy.protocolimpls.centralAir.dto.DataReportInfoDTO
;
import
vc.thinker.thirdpartyproxy.protocolimpls.centralAir.dto.DataReportParamDTO
;
import
vc.thinker.web.vo.TerminalDataReportVO
;
import
javax.validation.Valid
;
import
java.util.Objects
;
/**
* @author HeTongHao
* @since 2022/8/9 15:56
*/
@Api
@Slf4j
@RequestMapping
(
"/"
)
@RestController
@RequiredArgsConstructor
public
class
CentralAirController
{
@Autowired
private
CentralAirProtocol
centralAirProtocol
;
@ApiOperation
(
"设备数据上报接口"
)
@PutMapping
(
"data-report"
)
public
Boolean
dataReport
(
@RequestBody
@Valid
TerminalDataReportVO
reportVO
)
{
if
(
Objects
.
equals
(
reportVO
.
getProtocolCode
(),
ProtocolType
.
central_air_conditioning
.
getCode
())){
DataReportInfoDTO
dto
=
DataReportInfoDTO
.
builder
()
.
protocolCode
(
reportVO
.
getProtocolCode
())
.
deviceAddress
(
reportVO
.
getDeviceAddress
())
.
timestamp
(
reportVO
.
getTimestamp
())
.
data
(
JSONObject
.
parseObject
(
JSONObject
.
toJSONString
(
reportVO
.
getData
()),
DataReportParamDTO
.
class
))
.
build
();
this
.
centralAirProtocol
.
dataReport
(
dto
);
return
true
;
}
return
false
;
}
}
src/main/java/vc/thinker/web/validator/EnumValidate.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
web
.
validator
;
/**
* @author : xieshaojun
* @date : 2023/1/3 15:06
*/
public
interface
EnumValidate
<
T
>
{
/**
* 校验枚举值是否存在
*/
boolean
existValidate
(
T
value
);
}
src/main/java/vc/thinker/web/validator/ProtocolValidator.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
web
.
validator
;
import
javax.validation.ConstraintValidator
;
import
javax.validation.ConstraintValidatorContext
;
/**
* @author : xieshaojun
* @date : 2023/1/3 15:02
*/
public
class
ProtocolValidator
implements
ConstraintValidator
<
ValidatorEnum
,
String
>
{
private
Class
<?
extends
Enum
>
enumClass
;
@Override
public
void
initialize
(
ValidatorEnum
protocolValidatorEnum
)
{
enumClass
=
protocolValidatorEnum
.
enumClass
();
}
@Override
public
boolean
isValid
(
String
value
,
ConstraintValidatorContext
context
)
{
if
(
value
==
null
)
{
return
true
;
}
EnumValidate
[]
enums
=
(
EnumValidate
[])
enumClass
.
getEnumConstants
();
if
(
enums
==
null
||
enums
.
length
==
0
){
return
false
;
}
return
enums
[
0
].
existValidate
(
value
);
}
}
src/main/java/vc/thinker/web/validator/ValidatorEnum.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
web
.
validator
;
import
javax.validation.Constraint
;
import
javax.validation.Payload
;
import
java.lang.annotation.*
;
/**
* @author : xieshaojun
* @date : 2023/1/3 15:03
*/
@Target
({
ElementType
.
FIELD
,
ElementType
.
METHOD
,
ElementType
.
ANNOTATION_TYPE
})
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Constraint
(
validatedBy
=
{
ProtocolValidator
.
class
})
@Documented
public
@interface
ValidatorEnum
{
String
message
()
default
""
;
Class
<?>[]
groups
()
default
{};
Class
<?
extends
Payload
>[]
payload
()
default
{};
Class
<?>[]
target
()
default
{};
/**
* 允许的枚举
* @return
*/
Class
<?
extends
Enum
<?>>
enumClass
();
}
src/main/java/vc/thinker/web/vo/TerminalDataReportVO.java
0 → 100644
View file @
728e4d5f
package
vc
.
thinker
.
web
.
vo
;
import
com.alibaba.fastjson.JSONObject
;
import
io.swagger.annotations.ApiModelProperty
;
import
lombok.Data
;
import
vc.thinker.thirdpartyproxy.ProtocolType
;
import
vc.thinker.web.validator.ValidatorEnum
;
import
javax.validation.constraints.NotNull
;
import
java.io.Serial
;
import
java.io.Serializable
;
/**
* 端设备数据上报信息
* @author : xieshaojun
* @date : 2023/1/3 14:06
*/
@Data
public
class
TerminalDataReportVO
implements
Serializable
{
@Serial
private
static
final
long
serialVersionUID
=
-
3628045573564814316L
;
@ApiModelProperty
(
"协议编码"
)
@ValidatorEnum
(
message
=
"协议类型不支持"
,
enumClass
=
ProtocolType
.
class
)
private
String
protocolCode
;
@ApiModelProperty
(
"网关下设备唯一地址"
)
@NotNull
(
message
=
"网关下设备唯一地址不允许为空"
)
private
String
deviceAddress
;
@ApiModelProperty
(
"毫秒时间戳"
)
@NotNull
(
message
=
"毫秒时间戳不允许为空"
)
private
Long
timestamp
;
@ApiModelProperty
(
"协议数据"
)
private
JSONObject
data
;
}
src/main/resources/application.yml
0 → 100644
View file @
728e4d5f
server
:
port
:
9095
spring
:
application
:
name
:
protocol-proxy-service
task
:
execution
:
pool
:
core-size
:
20
queue-capacity
:
5
main
:
#重复Bean允许覆盖
allow-bean-definition-overriding
:
true
configuration
:
cache-enabled
:
true
## 输出执行的sql
#log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#mqtt
mqtt
:
#mqtt 是否开启
run
:
${ MQTT_RUN:
true
}
connection
:
thinker
:
broker
:
${ MQTT_CONNECTION_BROKER:tcp://120.79.30.193:1883}
clientId
:
${ MQTT_CONNECTION_CLIENTID:protocol-proxy-service}
username
:
${ MQTT_CONNECTION_USERNAME:thinker}
password
:
${ MQTT_CONNECTION_PASSWORD:123456}
cleanSession
:
${ MQTT_CONNECTION_CLEANSESSION:
false
}
thinker-test
:
broker
:
${ MQTT_CONNECTION_THINKER_TEST_BROKER:tcp://120.79.30.193:1883}
clientId
:
${ MQTT_CONNECTION_CLIENTID:protocol-proxy-service}
username
:
${ MQTT_CONNECTION_USERNAME:thinker}
password
:
${ MQTT_CONNECTION_PASSWORD:123456}
cleanSession
:
${ MQTT_CONNECTION_CLEANSESSION:
false
}
thinker-prod
:
broker
:
${ MQTT_CONNECTION_THINKER_PROD_BROKER:tcp://39.108.210.27:1883}
clientId
:
${ MQTT_CONNECTION_CLIENTID:protocol-proxy-service}
username
:
${ MQTT_CONNECTION_USERNAME:thinker}
password
:
${ MQTT_CONNECTION_PASSWORD:123456}
cleanSession
:
${ MQTT_CONNECTION_CLEANSESSION:
false
}
src/main/resources/banner.txt
0 → 100644
View file @
728e4d5f
██████████ ██ ██ ██ ███████ ██ ██ ███████
░░░░░██░░░ ░██ ░░ ░██ ░██░░░░██ ░██ ░██ ░██░░░░██ ██ ██
░██ ░██ ██ ███████ ░██ ██ █████ ██████ ░██ ░██ ██████ ██████ ██████ ██████ █████ ██████ ░██ ░██ ░██ ██████ ██████ ██ ██ ░░██ ██
░██ ░██████ ░██░░██░░░██░██ ██ ██░░░██░░██░░█ ░███████ ░░██░░█ ██░░░░██░░░██░ ██░░░░██ ██░░░██ ██░░░░██ ░██ ░███████ ░░██░░█ ██░░░░██░░██ ██ ░░███
░██ ░██░░░██░██ ░██ ░██░████ ░███████ ░██ ░ ░██░░░░ ░██ ░ ░██ ░██ ░██ ░██ ░██░██ ░░ ░██ ░██ ░██ ░██░░░░ ░██ ░ ░██ ░██ ░░███ ░██
░██ ░██ ░██░██ ░██ ░██░██░██ ░██░░░░ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██░██ ██░██ ░██ ░██ ░██ ░██ ░██ ░██ ██░██ ██
░██ ░██ ░██░██ ███ ░██░██░░██░░██████░███ ░██ ░███ ░░██████ ░░██ ░░██████ ░░█████ ░░██████ ███ ░██ ░███ ░░██████ ██ ░░██ ██
░░ ░░ ░░ ░░ ░░░ ░░ ░░ ░░ ░░░░░░ ░░░ ░░ ░░░ ░░░░░░ ░░ ░░░░░░ ░░░░░ ░░░░░░ ░░░ ░░ ░░░ ░░░░░░ ░░ ░░ ░░
vc.thinker @project.version@ build @maven.build.timestamp@
spring-boot ${spring-boot.version}
service-name ${spring.application.name}
http port ${server.port}
datasource ${spring.datasource.url}
redis ${spring.redis.host}:${spring.redis.port}
nacos ${spring.cloud.nacos.discovery.server-addr}
mqtt run->${mqtt.run} broker->${mqtt.connection.thinker.broker} clientId->${mqtt.connection.thinker.clientId}
\ No newline at end of file
src/main/resources/bootstrap.yml
0 → 100644
View file @
728e4d5f
spring
:
cloud
:
nacos
:
config
:
server-addr
:
${NACOS_SERVER:localhost:8848}
\ No newline at end of file
src/main/resources/logback-spring.xml
0 → 100644
View file @
728e4d5f
<?xml version="1.0" encoding="UTF-8"?>
<configuration
debug=
"false"
scan=
"false"
>
<property
name=
"log.path"
value=
"logs"
/>
<!-- 彩色日志格式 -->
<property
name=
"CONSOLE_LOG_PATTERN"
value=
"${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"
/>
<!-- 彩色日志依赖的渲染类 -->
<conversionRule
conversionWord=
"clr"
converterClass=
"org.springframework.boot.logging.logback.ColorConverter"
/>
<conversionRule
conversionWord=
"wex"
converterClass=
"org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"
/>
<conversionRule
conversionWord=
"wEx"
converterClass=
"org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"
/>
<!-- Console log output -->
<appender
name=
"console"
class=
"ch.qos.logback.core.ConsoleAppender"
>
<encoder>
<pattern>
${CONSOLE_LOG_PATTERN}
</pattern>
</encoder>
</appender>
<!-- Log file debug output -->
<appender
name=
"debug"
class=
"ch.qos.logback.core.rolling.RollingFileAppender"
>
<file>
${log.path}/debug.log
</file>
<rollingPolicy
class=
"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"
>
<fileNamePattern>
${log.path}/%d{yyyy-MM, aux}/debug.%d{yyyy-MM-dd}.%i.log.gz
</fileNamePattern>
<maxFileSize>
50MB
</maxFileSize>
<maxHistory>
30
</maxHistory>
</rollingPolicy>
<encoder>
<pattern>
%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n
</pattern>
</encoder>
</appender>
<!-- Log file error output -->
<appender
name=
"error"
class=
"ch.qos.logback.core.rolling.RollingFileAppender"
>
<file>
${log.path}/error.log
</file>
<rollingPolicy
class=
"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"
>
<fileNamePattern>
${log.path}/%d{yyyy-MM}/error.%d{yyyy-MM-dd}.%i.log.gz
</fileNamePattern>
<maxFileSize>
50MB
</maxFileSize>
<maxHistory>
30
</maxHistory>
</rollingPolicy>
<encoder>
<pattern>
%date [%thread] %-5level [%logger{50}] %file:%line - %msg%n
</pattern>
</encoder>
<filter
class=
"ch.qos.logback.classic.filter.ThresholdFilter"
>
<level>
ERROR
</level>
</filter>
</appender>
<logger
name=
"com.meller.mobdus-server"
level=
"INFO"
additivity=
"false"
>
<appender-ref
ref=
"console"
/>
</logger>
<root
level=
"INFO"
>
<appender-ref
ref=
"console"
/>
<appender-ref
ref=
"debug"
/>
<appender-ref
ref=
"error"
/>
</root>
</configuration>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment