Browse Source

/*tcpserver*/

master
htjcAdmin 9 months ago
commit
7a02e26ca0
39 changed files with 4292 additions and 0 deletions
  1. +35
    -0
      .gitignore
  2. +29
    -0
      Dockerfile
  3. +4
    -0
      README.md
  4. +310
    -0
      mvnw
  5. +182
    -0
      mvnw.cmd
  6. +129
    -0
      pom.xml
  7. +15
    -0
      src/main/java/com/inspect/tcpserver/TcpserverApplication.java
  8. +26
    -0
      src/main/java/com/inspect/tcpserver/cofiguration/ClientStart.java
  9. +58
    -0
      src/main/java/com/inspect/tcpserver/cofiguration/FastJson2JsonRedisSerializer.java
  10. +25
    -0
      src/main/java/com/inspect/tcpserver/cofiguration/ServerStart.java
  11. +94
    -0
      src/main/java/com/inspect/tcpserver/cofiguration/WebConfig.java
  12. +24
    -0
      src/main/java/com/inspect/tcpserver/constant/Constant.java
  13. +68
    -0
      src/main/java/com/inspect/tcpserver/controller/ClientController.java
  14. +61
    -0
      src/main/java/com/inspect/tcpserver/controller/DeviceServerController.java
  15. +84
    -0
      src/main/java/com/inspect/tcpserver/domain/AjaxResult.java
  16. +30
    -0
      src/main/java/com/inspect/tcpserver/domain/DeviceServerProperties.java
  17. +83
    -0
      src/main/java/com/inspect/tcpserver/domain/HttpStatus.java
  18. +34
    -0
      src/main/java/com/inspect/tcpserver/domain/Result.java
  19. +23
    -0
      src/main/java/com/inspect/tcpserver/domain/UpSystemServerProperties.java
  20. +560
    -0
      src/main/java/com/inspect/tcpserver/tcp/BaseControl.java
  21. +12
    -0
      src/main/java/com/inspect/tcpserver/tcp/BinaryModel.java
  22. +258
    -0
      src/main/java/com/inspect/tcpserver/tcp/ByteUtils.java
  23. +13
    -0
      src/main/java/com/inspect/tcpserver/tcp/CommonUtils.java
  24. +29
    -0
      src/main/java/com/inspect/tcpserver/tcp/ConnectionListener.java
  25. +248
    -0
      src/main/java/com/inspect/tcpserver/tcp/DownXml2Json.java
  26. +61
    -0
      src/main/java/com/inspect/tcpserver/tcp/MyDecoder.java
  27. +535
    -0
      src/main/java/com/inspect/tcpserver/tcp/NettyClient.java
  28. +97
    -0
      src/main/java/com/inspect/tcpserver/tcp/NettyClientHandler.java
  29. +491
    -0
      src/main/java/com/inspect/tcpserver/tcp/NettyServer.java
  30. +83
    -0
      src/main/java/com/inspect/tcpserver/tcp/NettyServerHandler.java
  31. +74
    -0
      src/main/java/com/inspect/tcpserver/tcp/SystemType.java
  32. +268
    -0
      src/main/java/com/inspect/tcpserver/tcp/UpJson2Xml.java
  33. +46
    -0
      src/main/java/com/inspect/tcpserver/util/SpringApplicationContext.java
  34. +41
    -0
      src/main/resources/application-dev.yml
  35. +42
    -0
      src/main/resources/application-prod.yml
  36. +42
    -0
      src/main/resources/application-test.yml
  37. +3
    -0
      src/main/resources/application.yml
  38. +62
    -0
      src/main/resources/logback.xml
  39. +13
    -0
      src/test/java/com/inspect/tcpserver/TcpserverApplicationTests.java

+ 35
- 0
.gitignore View File

@ -0,0 +1,35 @@
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/
/tcpServer.log
/.mvn/
/tcpServer.2022-04-21.log
/log/

+ 29
- 0
Dockerfile View File

@ -0,0 +1,29 @@
FROM openjdk:8
MAINTAINER zk <546285615@qq.com>
# Set environment variables.
ENV HOME /work
ENV JAVA_OPTS "-Xms512m -Xmx512m -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
ADD ./target/tcpserver-0.0.1-SNAPSHOT.jar /work/tcpserver.jar
ENV DEFAULT_OPTS ""
ENV OTHER_OPTS ""
# 开放端口
EXPOSE 22508
#设置时区
RUN echo "Asia/Shanghai" > /etc/timezone;
# 配置容器启动后执行的命令
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -jar /work/tcpserver.jar $DEFAULT_OPTS $OTHER_OPTS" ]
# Define working directory.
WORKDIR /work
# Define default command.
CMD ["bash"]

+ 4
- 0
README.md View File

@ -0,0 +1,4 @@
电力500协议中转站

+ 310
- 0
mvnw View File

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

+ 182
- 0
mvnw.cmd View File

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

+ 129
- 0
pom.xml View File

@ -0,0 +1,129 @@
<?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>
<groupId>com.dliip</groupId>
<artifactId>inspect-tcpserver</artifactId>
<version>1.0.0</version>
<name>inspect-tcpserver</name>
<description>inspect-tcpserver</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.7.RELEASE</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId >
<artifactId>xstream</artifactId>
<version>1.4.19</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.66.Final</version>
</dependency>
<dependency>
<groupId>net.sf.kxml</groupId>
<artifactId>kxml2</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>xmlpull</groupId>
<artifactId>xmlpull</artifactId>
<version>1.1.3.4d_b4_min</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>biz.paluch.logging</groupId>
<artifactId>logstash-gelf</artifactId>
<version>1.13.0</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.7.RELEASE</version>
<configuration>
<mainClass>com.inspect.tcpserver.TcpserverApplication</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

+ 15
- 0
src/main/java/com/inspect/tcpserver/TcpserverApplication.java View File

@ -0,0 +1,15 @@
package com.inspect.tcpserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication
@EnableAsync
public class TcpserverApplication {
public static void main(String[] args) {
SpringApplication.run(TcpserverApplication.class, args);
}
}

+ 26
- 0
src/main/java/com/inspect/tcpserver/cofiguration/ClientStart.java View File

@ -0,0 +1,26 @@
package com.inspect.tcpserver.cofiguration;
import com.inspect.tcpserver.tcp.NettyClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
@Configuration
@ConditionalOnProperty(name = "boot.client", havingValue = "true")
public class ClientStart implements CommandLineRunner {
private Logger logger = LoggerFactory.getLogger(ClientStart.class);
@Resource
NettyClient nettyClient;
@Override
public void run(String... args) {
nettyClient.ConnectServer();
}
}

+ 58
- 0
src/main/java/com/inspect/tcpserver/cofiguration/FastJson2JsonRedisSerializer.java View File

@ -0,0 +1,58 @@
package com.inspect.tcpserver.cofiguration;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.util.Assert;
import java.nio.charset.Charset;
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {
@SuppressWarnings("unused")
private ObjectMapper objectMapper = new ObjectMapper();
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private Class<T> clazz;
static {
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
}
public FastJson2JsonRedisSerializer(Class<T> clazz) {
super();
this.clazz = clazz;
}
@Override
public byte[] serialize(T t) throws SerializationException {
if (t == null) {
return new byte[0];
}
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
}
@Override
public T deserialize(byte[] bytes) throws SerializationException {
if (bytes == null || bytes.length <= 0) {
return null;
}
String str = new String(bytes, DEFAULT_CHARSET);
return JSON.parseObject(str, clazz);
}
public void setObjectMapper(ObjectMapper objectMapper) {
Assert.notNull(objectMapper, "'objectMapper' must not be null");
this.objectMapper = objectMapper;
}
protected JavaType getJavaType(Class<?> clazz) {
return TypeFactory.defaultInstance().constructType(clazz);
}
}

+ 25
- 0
src/main/java/com/inspect/tcpserver/cofiguration/ServerStart.java View File

@ -0,0 +1,25 @@
package com.inspect.tcpserver.cofiguration;
import com.inspect.tcpserver.tcp.NettyServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
@ConditionalOnProperty(name = "boot.server", havingValue = "true")
@Configuration
public class ServerStart implements CommandLineRunner {
private Logger logger = LoggerFactory.getLogger(ServerStart.class);
@Resource
NettyServer nettyServer;
@Override
public void run(String... args) throws Exception {
nettyServer.startServer();
}
}

+ 94
- 0
src/main/java/com/inspect/tcpserver/cofiguration/WebConfig.java View File

@ -0,0 +1,94 @@
package com.inspect.tcpserver.cofiguration;
import com.inspect.tcpserver.constant.Constant;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.StandardCharsets;
@Configuration
public class WebConfig {
@Bean
public <T> RedisTemplate<String, T> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, T> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
serializer.setObjectMapper(mapper);
// 使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
// Hash的key也采用StringRedisSerializer的序列化方式
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
@Bean
public RabbitTemplate rabbitTemplate(CachingConnectionFactory connectionFactory) {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
return rabbitTemplate;
}
/**
* 申明交换机
*/
@Bean(Constant.EX_CHANGE_NAME)
public Exchange directExchange() {
// 申明路由交换机durable:在rabbitmq重启后交换机还在
return ExchangeBuilder.directExchange(Constant.EX_CHANGE_NAME).durable(true).build();
}
/**
* 申明Blog队列
*
* @return
*/
@Bean(Constant.QUEUE_NAME)
public Queue deviceQueue() {
return new Queue(Constant.QUEUE_NAME, true);
}
/**
* 绑定交换机-路由键
*
* @return
*/
@Bean
public Binding bindRouting(Queue deviceQueue, Exchange directExchange) {
return BindingBuilder.bind(deviceQueue).to(directExchange).with(Constant.ROUTING_KEY_NAME).noargs();
}
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
return restTemplate;
}
}

+ 24
- 0
src/main/java/com/inspect/tcpserver/constant/Constant.java View File

@ -0,0 +1,24 @@
package com.inspect.tcpserver.constant;
public class Constant {
/**
* 设备上报的mq routing key 路由键
*/
public static final String ROUTING_KEY_NAME = "springboot.montdata";
/**
* 设备上报的交换机名
*/
public static final String EX_CHANGE_NAME = "exchange-montdata";
/**
* 设备上报的队列
*/
public static final String QUEUE_NAME = "queue-montdata";
/**
* 和基础数据定义的预置点转发type 类型
*/
public static final String MODEL_UP_TYPE = "modelup-1024";
}

+ 68
- 0
src/main/java/com/inspect/tcpserver/controller/ClientController.java View File

@ -0,0 +1,68 @@
package com.inspect.tcpserver.controller;
import com.alibaba.fastjson.JSONObject;
import com.inspect.tcpserver.domain.AjaxResult;
import com.inspect.tcpserver.tcp.NettyClient;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.UUID;
@RestController
@RequestMapping("/client")
public class ClientController {
private Logger logger = LoggerFactory.getLogger(ClientController.class);
@Resource
NettyClient nettyClient;
@GetMapping("gray")
public String gray() {
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
MDC.put("traceId", uuid);
logger.info("这是一个来自springboot,logback的info级别的日志");
logger.warn("这是一条来自springboot,logback的warn级别的日志");
logger.warn("这是一条来自springboot,logback的warn级别的日志2");
logger.error("这是一条来自springboot,logback的error级别的日志", new Exception("系统错误"));
return "success";
}
/**
* 调用客户端发送消息
*/
@PostMapping("sendMsg")
public AjaxResult sendMsg(@RequestBody String msg) {
try {
if (StringUtils.isBlank(msg)) {
return AjaxResult.fail("500", "发送消息msg为空");
}
// 此处只是为了判断传入的格式是否正确
JSONObject jsonObject = JSONObject.parseObject(msg);
if (null == jsonObject) {
return AjaxResult.fail("500", "发送消息json对象为空");
}
logger.info("巡视主机客户端接收到消息,发送到上级。{}", msg);
msg = msg.replaceAll("sendCode", "SendCode");
msg = msg.replaceAll("receiveCode", "ReceiveCode");
msg = msg.replaceAll("type", "Type");
nettyClient.sendJsonMessage(msg);
return AjaxResult.success();
} catch (Exception e) {
logger.error("客户端发送消息捕获异常", e);
return AjaxResult.fail(500, "数据格式不正确");
}
}
}

+ 61
- 0
src/main/java/com/inspect/tcpserver/controller/DeviceServerController.java View File

@ -0,0 +1,61 @@
package com.inspect.tcpserver.controller;
import com.alibaba.fastjson.JSONObject;
import com.inspect.tcpserver.domain.AjaxResult;
import com.inspect.tcpserver.domain.DeviceServerProperties;
import com.inspect.tcpserver.tcp.NettyServer;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@RequestMapping("/deviceServer")
public class DeviceServerController {
@Resource
NettyServer server;
private Logger logger = LoggerFactory.getLogger(DeviceServerController.class);
@Resource
DeviceServerProperties deviceServerProperties;
/**
* 下发命令到设备端
*/
@PostMapping("/sendCommand")
public AjaxResult sendCommand(@RequestBody String json) {
try {
logger.info("设备接入层server-接口,接到命令:{}", json);
// 调用设备接入层下发命令到设备
JSONObject jsonObject = JSONObject.parseObject(json);
String sendCode = jsonObject.getString("SendCode");
String receiveCode = jsonObject.getString("ReceiveCode");
if (StringUtils.isEmpty(sendCode) || StringUtils.isEmpty(receiveCode)) {
logger.error("SendCoded或ReceiveCode为空");
return AjaxResult.fail(500, "SendCoded或ReceiveCode为空");
} else {
server.SendXmlMessage(jsonObject);// to device
return AjaxResult.success();
}
} catch (Exception e) {
logger.error("设备接入服务,处理命令下发捕获异常", e);
return AjaxResult.fail(500);
}
}
}

+ 84
- 0
src/main/java/com/inspect/tcpserver/domain/AjaxResult.java View File

@ -0,0 +1,84 @@
package com.inspect.tcpserver.domain;
import java.util.HashMap;
public class AjaxResult extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
public static final String CODE_TAG = "code";
public static final String MSG_TAG = "msg";
public static final String DATA_TAG = "data";
public AjaxResult() {
}
public AjaxResult(int code, String msg) {
super.put(CODE_TAG, code);
super.put(MSG_TAG, msg);
}
public AjaxResult(int code, String msg, Object data) {
super.put(CODE_TAG, code);
super.put(MSG_TAG, msg);
if (null != data) {
super.put(DATA_TAG, data);
}
}
@Override
public AjaxResult put(String key, Object value) {
super.put(key, value);
return this;
}
public static AjaxResult success() {
return AjaxResult.success("操作成功");
}
public static AjaxResult success(Object data) {
return AjaxResult.success("操作成功", data);
}
public static AjaxResult success(String msg) {
return AjaxResult.success(msg, null);
}
public static AjaxResult success(String msg, Object data) {
return new AjaxResult(HttpStatus.SUCCESS, msg, data);
}
public static AjaxResult error() {
return AjaxResult.error("操作失败");
}
public static AjaxResult error(String msg) {
return AjaxResult.error(msg, null);
}
public static AjaxResult error(String msg, Object data) {
return new AjaxResult(HttpStatus.ERROR, msg, data);
}
public static AjaxResult error(int code, String msg) {
return new AjaxResult(code, msg, null);
}
public static AjaxResult fail(Integer code, String msg, Object data) {
return new AjaxResult(code, msg, data);
}
public static AjaxResult fail(String msg, Object data) {
return new AjaxResult(HttpStatus.ERROR, msg, data);
}
public static AjaxResult fail(Integer code, String msg) {
return new AjaxResult(code, msg, null);
}
public static AjaxResult fail(Integer code) {
return new AjaxResult(code, null, null);
}
}

+ 30
- 0
src/main/java/com/inspect/tcpserver/domain/DeviceServerProperties.java View File

@ -0,0 +1,30 @@
package com.inspect.tcpserver.domain;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@PropertySource("classpath:application.yml")
@Component
public class DeviceServerProperties {
@Value("${deviceServer.serverIp}")
public String ip;
@Value("${deviceServer.serverPort}")
public Integer port;
@Value("${deviceServer.deviceServerCode}")
public String deviceServerCode;
@Value("${deviceServer.deviceCode}")
public String deviceCode;
@Value("${deviceServer.robotCode}")
public String robotCode;
@Value("${deviceServer.nestCode}")
public String nestCode;
}

+ 83
- 0
src/main/java/com/inspect/tcpserver/domain/HttpStatus.java View File

@ -0,0 +1,83 @@
package com.inspect.tcpserver.domain;
public class HttpStatus {
/**
* 操作成功
*/
public static final int SUCCESS = 200;
/**
* 对象创建成功
*/
public static final int CREATED = 201;
/**
* 请求已经被接受
*/
public static final int ACCEPTED = 202;
/**
* 操作已经执行成功但是没有返回数据
*/
public static final int NO_CONTENT = 204;
/**
* 资源已被移除
*/
public static final int MOVED_PERM = 301;
/**
* 重定向
*/
public static final int SEE_OTHER = 303;
/**
* 资源没有被修改
*/
public static final int NOT_MODIFIED = 304;
/**
* 参数列表错误缺少格式不匹配
*/
public static final int BAD_REQUEST = 400;
/**
* 未授权
*/
public static final int UNAUTHORIZED = 401;
/**
* 访问受限授权过期
*/
public static final int FORBIDDEN = 403;
/**
* 资源服务未找到
*/
public static final int NOT_FOUND = 404;
/**
* 不允许的http方法
*/
public static final int BAD_METHOD = 405;
/**
* 资源冲突或者资源被锁
*/
public static final int CONFLICT = 409;
/**
* 不支持的数据媒体类型
*/
public static final int UNSUPPORTED_TYPE = 415;
/**
* 系统内部错误
*/
public static final int ERROR = 500;
/**
* 接口未实现
*/
public static final int NOT_IMPLEMENTED = 501;
}

+ 34
- 0
src/main/java/com/inspect/tcpserver/domain/Result.java View File

@ -0,0 +1,34 @@
package com.inspect.tcpserver.domain;
public class Result {
private String code;
private String msg;
private String data;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}

+ 23
- 0
src/main/java/com/inspect/tcpserver/domain/UpSystemServerProperties.java View File

@ -0,0 +1,23 @@
package com.inspect.tcpserver.domain;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@PropertySource("classpath:application.yml")
@Component
public class UpSystemServerProperties {
@Value("${upSystemServer.serverIp}")
public String ip;
@Value("${upSystemServer.serverPort}")
public Integer port;
@Value("${upSystemServer.upCode}")
public String upCode;
@Value("${upSystemServer.iipCode}")
public String iipCode;
}

+ 560
- 0
src/main/java/com/inspect/tcpserver/tcp/BaseControl.java View File

@ -0,0 +1,560 @@
package com.inspect.tcpserver.tcp;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
import java.util.List;
public class BaseControl {
public String SendCode;
public String ReceiveCode;
public String Type;
public String Code;
public String Command;
public String Time;
}
class ResponseControl extends BaseControl {
public String Items;
}
class RegisterResponseControl extends BaseControl {
public List<RegisterResponseModel> Items;
}
//注册响应消息
@XStreamAlias("Item")
class RegisterResponseModel {
@XStreamAsAttribute
public String heart_beat_interval; //心跳间隔
@XStreamAsAttribute
public String patroldevice_run_interval; //巡视设备运行数据间隔
@XStreamAsAttribute
public String nest_run_interval; //无人机机巢运行数据间隔
@XStreamAsAttribute
public String weather_interval; //微气象数据间隔
@XStreamAsAttribute
public String env_interval; //环境数据间隔
}
class RobotControl extends BaseControl {
public List<RobotModel> Items;
}
//机器人无人机控制
@XStreamAlias("Item")
class RobotModel {
@XStreamAsAttribute
public String value;
}
class TaskSendControl extends BaseControl {
public List<TaskSendModel> Items;
}
//任务下发
@XStreamAlias("Item")
class TaskSendModel {
@XStreamAsAttribute
public String task_code; //任务编码
@XStreamAsAttribute
public String task_name; //任务名称
@XStreamAsAttribute
public String priority; //优先级
@XStreamAsAttribute
public String device_level; //设备层级
@XStreamAsAttribute
public String device_list; //设备列表 格式多个ID采用,分隔"
@XStreamAsAttribute
public String fixed_start_time; //定期开始时间
@XStreamAsAttribute
public String cycle_month; //周期
@XStreamAsAttribute
public String cycle_week; //周期
@XStreamAsAttribute
public String cycle_execute_time; //周期执行时间
@XStreamAsAttribute
public String cycle_start_time; //周期开始时间
@XStreamAsAttribute
public String cycle_end_time; //周期结束时间
@XStreamAsAttribute
public String interval_number; //间隔数量
@XStreamAsAttribute
public String interval_type; //间隔类型
@XStreamAsAttribute
public String interval_execute_time; //间隔执行时间
@XStreamAsAttribute
public String interval_start_time; //间隔开始时间
@XStreamAsAttribute
public String interval_end_time; //间隔结束时间
@XStreamAsAttribute
public String invalid_start_time; //不可用开始时间
@XStreamAsAttribute
public String invalid_end_time; //不可用结束时间
@XStreamAsAttribute
public String isenable; //是否可用
@XStreamAsAttribute
public String creator; //编制人
@XStreamAsAttribute
public String create_time; //编制时间
@XStreamAsAttribute
public String type; //类型
}
class LendonTaskControl extends BaseControl {
public List<LendonTaskModel> Items;
}
//联动任务下发
@XStreamAlias("Item")
class LendonTaskModel {
@XStreamAsAttribute
public String task_code; //任务编码
@XStreamAsAttribute
public String task_name; //任务名称
@XStreamAsAttribute
public String priority; //优先级
@XStreamAsAttribute
public String device_level; //设备层级
@XStreamAsAttribute
public String device_list; //设备列表 格式多个ID采用,分隔"
}
class AreaControl extends BaseControl {
public List<AreaModel> Items;
}
//检修区域
@XStreamAlias("Item")
class AreaModel {
@XStreamAsAttribute
public String config_code; //配置编码 检修区域配置编码
@XStreamAsAttribute
public String enable; //是否有效
@XStreamAsAttribute
public String start_time; //检修开始时间
@XStreamAsAttribute
public String end_time; //检修结束时间
@XStreamAsAttribute
public String device_level; //设备层级
@XStreamAsAttribute
public String device_list; //检修设备列表
@XStreamAsAttribute
public String coordinate_pixel; //检修区域坐标框
}
class ModelControl extends BaseControl {
public List<ModelPath> Items;
}
@XStreamAlias("Item")
class ModelPath {
@XStreamAsAttribute
public String device_file_path;
@XStreamAsAttribute
public String robot_file_path;
@XStreamAsAttribute
public String host_file_path;
@XStreamAsAttribute
public String video_file_path;
@XStreamAsAttribute
public String drone_file_path;
@XStreamAsAttribute
public String voice_file_path;
@XStreamAsAttribute
public String task_file_path;
@XStreamAsAttribute
public String overhaularea_file_path;
@XStreamAsAttribute
public String map_file_path;
@XStreamAsAttribute
public String total_num;
@XStreamAsAttribute
public String valid_num;
@XStreamAsAttribute
public String percent;
@XStreamAsAttribute
public String error_code;
@XStreamAsAttribute
public String task_patrolled_id;
}
//巡视结果统计查询
class ResultControl extends BaseControl {
public List<Result> Items;
}
@XStreamAlias("Item")
class Result {
@XStreamAsAttribute
public String begin_time;
@XStreamAsAttribute
public String end_time;
}
class PatrolDeviceStateControl extends BaseControl {
public List<PatrolDeviceStateModel> Items;
}
//巡视设备状态数据
@XStreamAlias("Item")
class PatrolDeviceStateModel {
@XStreamAsAttribute
public String patroldevice_name;//巡视设备名称
@XStreamAsAttribute
public String patroldevice_code;//巡视设备编码
@XStreamAsAttribute
public String time; //时间
@XStreamAsAttribute
public String type; //类型
@XStreamAsAttribute
public String value; //
@XStreamAsAttribute
public String value_unit; //值带单位
@XStreamAsAttribute
public String unit; //单位
}
class PatrolDeviceRuningControl extends BaseControl {
public List<PatrolDeviceRuningModel> Items;
}
//巡视设备运行数据
@XStreamAlias("Item")
class PatrolDeviceRuningModel {
@XStreamAsAttribute
public String patroldevice_name;//巡视设备名称
@XStreamAsAttribute
public String patroldevice_code;//巡视设备编码
@XStreamAsAttribute
public String time; //时间
@XStreamAsAttribute
public String type; //类型
@XStreamAsAttribute
public String value; //
@XStreamAsAttribute
public String value_unit; //值带单位
@XStreamAsAttribute
public String unit; //单位
}
class NestStateControl extends BaseControl {
public List<NestStateModel> Items;
}
//无人机机巢状态数据
@XStreamAlias("Item")
class NestStateModel {
@XStreamAsAttribute
public String nest_name; //机巢名称
@XStreamAsAttribute
public String nest_code; //机巢编码
@XStreamAsAttribute
public String time; //时间
@XStreamAsAttribute
public String type; //类型
@XStreamAsAttribute
public String value; //
@XStreamAsAttribute
public String value_unit; //值带单位
@XStreamAsAttribute
public String unit; //单位
}
class NestRuningControl extends BaseControl {
public List<NestRuningModel> Items;
}
//无人机机巢运行数据
@XStreamAlias("Item")
class NestRuningModel {
@XStreamAsAttribute
public String nest_name; //机巢名称
@XStreamAsAttribute
public String nest_code; //机巢编码
@XStreamAsAttribute
public String module_no; //模块序号
@XStreamAsAttribute
public String time; //时间
@XStreamAsAttribute
public String type; //类型
@XStreamAsAttribute
public String value; //
@XStreamAsAttribute
public String value_unit; //值带单位
@XStreamAsAttribute
public String unit; //单位
}
class RouteControl extends BaseControl {
public List<LocationModel> Items;
}
class LocationControl extends BaseControl {
public List<LocationModel> Items;
}
//巡视设备坐标
@XStreamAlias("Item")
class LocationModel {
@XStreamAsAttribute
public String patroldevice_name; //巡视设备名称
@XStreamAsAttribute
public String patroldevice_code; //巡视设备编码
@XStreamAsAttribute
public String time; //时间
@XStreamAsAttribute
public String coordinate_pixel; //坐标
@XStreamAsAttribute
public String coordinate_geography; //经纬度
}
class AlarmControl extends BaseControl {
public List<AlarmModel> Items;
}
//巡视设备异常告警数据
@XStreamAlias("Item")
class AlarmModel {
@XStreamAsAttribute
public String patroldevice_name; //巡视设备名称
@XStreamAsAttribute
public String patroldevice_code; //巡视设备编码
@XStreamAsAttribute
public String time; //时间
@XStreamAsAttribute
public String content; //告警描述
}
class EnvironmentControl extends BaseControl {
public List<EnvironmentModel> Items;
}
//环境数据
@XStreamAlias("Item")
class EnvironmentModel {
@XStreamAsAttribute
public String patroldevice_name; //巡视设备名称
@XStreamAsAttribute
public String patroldevice_code; //巡视设备编码
@XStreamAsAttribute
public String time; //时间
@XStreamAsAttribute
public String type; //类型
@XStreamAsAttribute
public String value; //
@XStreamAsAttribute
public String value_unit; //值带单位
@XStreamAsAttribute
public String unit; //单位
}
class TaskStateControl extends BaseControl {
public List<TaskStateModel> Items;
}
//任务状态数据
@XStreamAlias("Item")
class TaskStateModel {
@XStreamAsAttribute
public String task_patrolled_id; //巡视任务执行ID
@XStreamAsAttribute
public String task_name; //任务名称
@XStreamAsAttribute
public String task_code; //任务编码
@XStreamAsAttribute
public String task_state; //任务状态
@XStreamAsAttribute
public String plan_start_time; //计划开始时间
@XStreamAsAttribute
public String start_time; //开始时间
@XStreamAsAttribute
public String task_progress; //任务进度
@XStreamAsAttribute
public String task_estimated_time; //任务预计剩余时间
@XStreamAsAttribute
public String description; //描述
}
class TaskResultControl extends BaseControl {
public List<TaskResultModel> Items;
}
//巡视结果
@XStreamAlias("Item")
class TaskResultModel {
@XStreamAsAttribute
public String patroldevice_name; //巡视设备名称
@XStreamAsAttribute
public String patroldevice_code; //巡视设备编码
@XStreamAsAttribute
public String task_name; //任务名称
@XStreamAsAttribute
public String task_code; //任务编码
@XStreamAsAttribute
public String device_name; //设备点位名称
@XStreamAsAttribute
public String device_id; //设备点位ID
@XStreamAsAttribute
public String value_type; //值类型
@XStreamAsAttribute
public String value; //
@XStreamAsAttribute
public String value_unit; //值带单位
@XStreamAsAttribute
public String unit; //单位
@XStreamAsAttribute
public String time; //时间
@XStreamAsAttribute
public String recognition_type; //识别类型
@XStreamAsAttribute
public String file_type; //采集文件类型
@XStreamAsAttribute
public String file_path; //文件名称
@XStreamAsAttribute
public String rectangle; //图像框
@XStreamAsAttribute
public String task_patrolled_id; //巡视任务执行ID
@XStreamAsAttribute
public String valid; //结论
@XStreamAsAttribute
public String data_type; //巡视结果数据来源 0x01摄像机0x02机器人0x03无人机0x04声纹0x05在线监测
@XStreamAsAttribute
public String material_id; //实物ID
}
class AnalysisControl extends BaseControl {
public List<AnalysisModel> Items;
}
//静默监视告警数据
@XStreamAlias("Item")
class AnalysisModel {
@XStreamAsAttribute
public String patroldevice_name; //巡视设备名称
@XStreamAsAttribute
public String patroldevice_code; //巡视设备编码
@XStreamAsAttribute
public String task_name; //任务名称
@XStreamAsAttribute
public String task_code; //任务编码
@XStreamAsAttribute
public String device_name; //设备点位名称
@XStreamAsAttribute
public String device_id; //设备点位ID
@XStreamAsAttribute
public String alarm_level; //告警等级
@XStreamAsAttribute
public String alarm_type; //告警类型
@XStreamAsAttribute
public String recognition_type; //识别类型
@XStreamAsAttribute
public String file_type; //告警文件类型
@XStreamAsAttribute
public String task_patrolled_id; //巡视任务执行ID
@XStreamAsAttribute
public String file_path; //文件路径
@XStreamAsAttribute
public String time; //时间
@XStreamAsAttribute
public String content; //告警描述
@XStreamAsAttribute
public String value; //
@XStreamAsAttribute
public String value_unit; //值带单位
@XStreamAsAttribute
public String unit; //单位
}
class MonitorControl extends BaseControl {
public List<MonitorModel> Items;
}
//静默监视告警数据
@XStreamAlias("Item")
class MonitorModel {
@XStreamAsAttribute
public String patroldevice_name; //巡视设备名称
@XStreamAsAttribute
public String patroldevice_code; //巡视设备编码
@XStreamAsAttribute
public String alarm_level; //告警等级
@XStreamAsAttribute
public String monitor_type; //静默监视类型
@XStreamAsAttribute
public String file_type; //告警文件类型
@XStreamAsAttribute
public String content; //告警描述
@XStreamAsAttribute
public String file_path; //文件名称
@XStreamAsAttribute
public String time; //时间
}
class TotalControl extends BaseControl {
public List<TotalModel> Items;
}
//巡视结果统计
@XStreamAlias("Item")
class TotalModel {
@XStreamAsAttribute
public String total_num; //满足查询条件总数
@XStreamAsAttribute
public String valid_num; //查询有效数据
@XStreamAsAttribute
public String percent; //统计百分比有效值 保留小数点后3位
}
class ReportControl extends BaseControl {
public List<ReportModel> Items;
}
//巡视设备统计信息上报
@XStreamAlias("Item")
class ReportModel {
@XStreamAsAttribute
public String patroldevice_name; //巡视设备名称
@XStreamAsAttribute
public String patroldevice_code; //巡视设备编码
@XStreamAsAttribute
public String commission_time; //投运时间
@XStreamAsAttribute
public String report_time; //上报时间
@XStreamAsAttribute
public String type; //类型
@XStreamAsAttribute
public String value; //
@XStreamAsAttribute
public String value_unit; //值带单位
@XStreamAsAttribute
public String unit; //单位
}
class UpdateModelControl extends BaseControl {
public List<UpdateModel> Items;
}
//模型更新上报指令
@XStreamAlias("Item")
class UpdateModel {
@XStreamAsAttribute
public String time; //时间
@XStreamAsAttribute
public String type; //类型
@XStreamAsAttribute
public String file_path; //路径
}

+ 12
- 0
src/main/java/com/inspect/tcpserver/tcp/BinaryModel.java View File

@ -0,0 +1,12 @@
package com.inspect.tcpserver.tcp;
import io.netty.buffer.ByteBuf;
public class BinaryModel {
public long sendIndex;
public long receiveIndex;
public byte sourceFlag;
public int dataLength;
public ByteBuf dataBuf;
public String id;
}

+ 258
- 0
src/main/java/com/inspect/tcpserver/tcp/ByteUtils.java View File

@ -0,0 +1,258 @@
package com.inspect.tcpserver.tcp;
import java.io.*;
import java.nio.charset.Charset;
import java.util.Arrays;
public class ByteUtils {
private static final byte[] BUILD_BYTE_TABLE = new byte[]{(byte) 128, (byte) 64, (byte) 32, (byte) 16, (byte) 8, (byte) 4, (byte) 2, (byte) 1};
private ByteUtils() {
}
public static String byte2Hex(byte[] bytes) {
StringBuffer stringBuffer = new StringBuffer();
String temp = null;
for (int i = 0; i < bytes.length; i++) {
temp = Integer.toHexString(bytes[i] & 0xFF);
if (temp.length() == 1) {
//1得到一位的进行补0操作
stringBuffer.append("0");
}
stringBuffer.append(temp);
}
return stringBuffer.toString();
}
public static byte[] shortToByte(short number) {
byte[] b = new byte[2];
for (int i = 1; i >= 0; i--) {
b[i] = (byte) (number % 256);
number >>= 8;
}
return b;
}
public static short byteToShort(byte[] b) {
return (short) ((((b[0] & 0xff) << 8) | b[1] & 0xff));
}
public static byte[] intToByte(int number) {
byte[] b = new byte[4];
for (int i = 3; i >= 0; i--) {
b[i] = (byte) (number % 256);
number >>= 8;
}
return b;
}
public static int byteToInt(byte[] b) {
return ((((b[0] & 0xff) << 24) | ((b[1] & 0xff) << 16) | ((b[2] & 0xff) << 8) | (b[3] & 0xff)));
}
public static byte[] longToByte(long number) {
byte[] b = new byte[8];
for (int i = 7; i >= 0; i--) {
b[i] = (byte) (number % 256);
number >>= 8;
}
return b;
}
public static long byteToLong(byte[] b) {
return ((((long) b[0] & 0xff) << 56) | (((long) b[1] & 0xff) << 48) | (((long) b[2] & 0xff) << 40) | (((long) b[3] & 0xff) << 32) | (((long) b[4] & 0xff) << 24)
| (((long) b[5] & 0xff) << 16) | (((long) b[6] & 0xff) << 8) | ((long) b[7] & 0xff));
}
public static byte[] doubleToByte(double d) {
byte[] bytes = new byte[8];
long l = Double.doubleToLongBits(d);
for (int i = 0; i < bytes.length; i++) {
bytes[i] = Long.valueOf(l).byteValue();
l = l >> 8;
}
return bytes;
}
public static double byteToDouble(byte[] b) {
long l;
l = b[0];
l &= 0xff;
l |= ((long) b[1] << 8);
l &= 0xffff;
l |= ((long) b[2] << 16);
l &= 0xffffff;
l |= ((long) b[3] << 24);
l &= 0xffffffffl;
l |= ((long) b[4] << 32);
l &= 0xffffffffffl;
l |= ((long) b[5] << 40);
l &= 0xffffffffffffl;
l |= ((long) b[6] << 48);
l &= 0xffffffffffffffl;
l |= ((long) b[7] << 56);
return Double.longBitsToDouble(l);
}
public static byte[] floatToByte(float d) {
byte[] bytes = new byte[4];
int l = Float.floatToIntBits(d);
for (int i = 0; i < bytes.length; i++) {
bytes[i] = Integer.valueOf(l).byteValue();
l = l >> 8;
}
return bytes;
}
public static float byteToFloat(byte[] b) {
int l;
l = b[0];
l &= 0xff;
l |= ((long) b[1] << 8);
l &= 0xffff;
l |= ((long) b[2] << 16);
l &= 0xffffff;
l |= ((long) b[3] << 24);
l &= 0xffffffffl;
return Float.intBitsToFloat(l);
}
public static byte[] stringToByte(String s, Charset charset) {
return s.getBytes(charset);
}
public static String byteToString(byte[] b, Charset charset) {
return new String(b, charset);
}
public static byte[] objectToByte(Object obj) throws IOException {
ByteArrayOutputStream buff = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(buff);
out.writeObject(obj);
try {
return buff.toByteArray();
} finally {
out.close();
}
}
public static Object byteToObject(byte[] b) throws IOException, ClassNotFoundException {
ByteArrayInputStream buff = new ByteArrayInputStream(b);
ObjectInputStream in = new ObjectInputStream(buff);
Object obj = in.readObject();
try {
return obj;
} finally {
in.close();
}
}
public static boolean equalsBit(byte a, byte b) {
return Arrays.equals(byteToBitArray(a), byteToBitArray(b));
}
public static boolean equalsBit(byte[] a, byte[] b) {
if (a == b) {
return true;
}
if (a == null || b == null) {
return false;
}
int length = a.length;
if (b.length != length) {
return false;
}
for (int count = 0; count < a.length; count++) {
if (!equalsBit(a[count], b[count])) {
return false;
}
}
return true;
}
public static String bitString(byte b) {
StringBuilder buff = new StringBuilder();
boolean[] array = byteToBitArray(b);
for (int i = 0; i < array.length; i++) {
buff.append(array[i] ? 1 : 0);
}
return buff.toString();
}
public static boolean[] byteToBitArray(byte b) {
boolean[] buff = new boolean[8];
int index = 0;
for (int i = 7; i >= 0; i--) {
buff[index++] = ((b >>> i) & 1) == 1;
}
return buff;
}
public static boolean byteBitValue(byte b, int index) {
return byteToBitArray(b)[index];
}
public static byte buildNewByte(boolean[] values) {
byte b = 0;
for (int i = 0; i < 8; i++) {
if (values[i]) {
b |= BUILD_BYTE_TABLE[i];
}
}
return b;
}
public static byte changeByteBitValue(byte b, int index, boolean newValue) {
boolean[] bitValues = byteToBitArray(b);
bitValues[index] = newValue;
return buildNewByte(bitValues);
}
public static byte[] ipAddressBytes(String address) {
if (address == null || address.length() < 0 || address.length() > 15) {
throw new IllegalArgumentException("Invalid IP address.");
}
final int ipSize = 4;// 最大IP位数
final char ipSpace = '.';// IP数字的分隔符
int[] ipNums = new int[ipSize];
StringBuilder number = new StringBuilder();// 当前操作的数字
StringBuilder buff = new StringBuilder(address);
int point = 0;// 当前操作的数字下标,最大到3.
char currentChar;
for (int i = 0; i < buff.length(); i++) {
currentChar = buff.charAt(i);
if (ipSpace == currentChar) {
// 当前位置等于最大于序号后,还有字符没有处理表示这是一个错误的IP.
if (point == ipSize - 1 && buff.length() - (i + 1) > 0) {
throw new IllegalArgumentException("Invalid IP address.");
}
ipNums[point++] = Integer.parseInt(number.toString());
number.delete(0, number.length());
} else {
number.append(currentChar);
}
}
ipNums[point] = Integer.parseInt(number.toString());
byte[] ipBuff = new byte[ipSize];
int pointNum = 0;
for (int i = 0; i < 4; i++) {
pointNum = Math.abs(ipNums[i]);
if (pointNum > 255) {
throw new IllegalArgumentException("Invalid IP address.");
}
ipBuff[i] = (byte) (pointNum & 0xff);
}
return ipBuff;
}
}

+ 13
- 0
src/main/java/com/inspect/tcpserver/tcp/CommonUtils.java View File

@ -0,0 +1,13 @@
package com.inspect.tcpserver.tcp;
import java.text.SimpleDateFormat;
import java.util.Date;
public class CommonUtils {
public static String GetNowDateString() {
Date date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return formatter.format(date);
}
}

+ 29
- 0
src/main/java/com/inspect/tcpserver/tcp/ConnectionListener.java View File

@ -0,0 +1,29 @@
package com.inspect.tcpserver.tcp;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.EventLoop;
import java.util.concurrent.TimeUnit;
public class ConnectionListener implements ChannelFutureListener {
private NettyClient nettyClient;
public ConnectionListener(NettyClient nettyClient) {
this.nettyClient = nettyClient;
}
@Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {
if (!channelFuture.isSuccess()) {
final EventLoop loop = channelFuture.channel().eventLoop();
loop.schedule(new Runnable() {
@Override
public void run() {
nettyClient.ConnectServer();
}
}, 3L, TimeUnit.SECONDS);
}
}
}

+ 248
- 0
src/main/java/com/inspect/tcpserver/tcp/DownXml2Json.java View File

@ -0,0 +1,248 @@
package com.inspect.tcpserver.tcp;
import com.alibaba.fastjson.JSON;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.Xpp3Driver;
import com.thoughtworks.xstream.security.AnyTypePermission;
public class DownXml2Json {
/**
* 默认为对上级的客户端的别名
*/
private String alias;
public DownXml2Json(String alias) {
this.alias = alias;
}
//任务下发
public String TaskSendControlXml2Json(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, TaskSendControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
TaskSendControl obj = (TaskSendControl) xStream.fromXML(xml);
String resultJson = JSON.toJSONString(obj);
return resultJson;
}
//联动任务下发
public String LendonTaskControlXml2Json(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, LendonTaskControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
LendonTaskControl obj = (LendonTaskControl) xStream.fromXML(xml);
String resultJson = JSON.toJSONString(obj);
return resultJson;
}
//检修去下发
public String AreaControlXml2Json(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, AreaControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
AreaControl obj = (AreaControl) xStream.fromXML(xml);
String resultJson = JSON.toJSONString(obj);
return resultJson;
}
//机器人控制下发
public String RobotControlXml2Json(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, RobotControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
RobotControl obj = (RobotControl) xStream.fromXML(xml);
String resultJson = JSON.toJSONString(obj);
return resultJson;
}
//无人机控制下发
public String UavControlXml2Json(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, RobotControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
RobotControl obj = (RobotControl) xStream.fromXML(xml);
String resultJson = JSON.toJSONString(obj);
return resultJson;
}
//任务控制和同步指令
public String BaseControlXml2Json(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, BaseControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
BaseControl obj = (BaseControl) xStream.fromXML(xml);
String resultJson = JSON.toJSONString(obj);
return resultJson;
}
//上级查询巡视结果指令
public String ResultControlXml2Json(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, ResultControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
ResultControl obj = (ResultControl) xStream.fromXML(xml);
String resultJson = JSON.toJSONString(obj);
return resultJson;
}
//模型同步同步指令
public String ModelControlXml2Json(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, ModelControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
BaseControl obj = (BaseControl) xStream.fromXML(xml);
String resultJson = JSON.toJSONString(obj);
return resultJson;
}
//巡检设备状态数据
public String PatrolDeviceStateControlXml2Json(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, PatrolDeviceStateControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
PatrolDeviceStateControl obj = (PatrolDeviceStateControl) xStream.fromXML(xml);
String resultJson = JSON.toJSONString(obj);
return resultJson;
}
//巡检设备运行数据
public String PatrolDeviceRuningControlXml2Json(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, PatrolDeviceRuningControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
PatrolDeviceRuningControl obj = (PatrolDeviceRuningControl) xStream.fromXML(xml);
String resultJson = JSON.toJSONString(obj);
return resultJson;
}
//机巢状态数据
public String NestStateControlXml2Json(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, NestStateControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
NestStateControl obj = (NestStateControl) xStream.fromXML(xml);
String resultJson = JSON.toJSONString(obj);
return resultJson;
}
//机巢运行数据
public String NestRuningControlXml2Json(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, NestRuningControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
NestRuningControl obj = (NestRuningControl) xStream.fromXML(xml);
String resultJson = JSON.toJSONString(obj);
return resultJson;
}
//坐标数据
public String LocationControlXml2Json(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, LocationControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
LocationControl obj = (LocationControl) xStream.fromXML(xml);
String resultJson = JSON.toJSONString(obj);
return resultJson;
}
//巡视路线
public String RouteControlXml2Json(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, RouteControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
RouteControl obj = (RouteControl) xStream.fromXML(xml);
String resultJson = JSON.toJSONString(obj);
return resultJson;
}
//设备告警数据
public String AlarmControlXml2Json(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, AlarmControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
AlarmControl obj = (AlarmControl) xStream.fromXML(xml);
String resultJson = JSON.toJSONString(obj);
return resultJson;
}
//环境数据
public String EnvironmentControlXml2Json(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, EnvironmentControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
EnvironmentControl obj = (EnvironmentControl) xStream.fromXML(xml);
String resultJson = JSON.toJSONString(obj);
return resultJson;
}
//任务状态
public String TaskStateControlXml2Json(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, TaskStateControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
TaskStateControl obj = (TaskStateControl) xStream.fromXML(xml);
String resultJson = JSON.toJSONString(obj);
return resultJson;
}
//巡视结果
public String TaskResultControlXml2Json(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, TaskResultControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
TaskResultControl obj = (TaskResultControl) xStream.fromXML(xml);
String resultJson = JSON.toJSONString(obj);
return resultJson;
}
//巡检告警数据
public String AnalysisControlXml2Json(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, AnalysisControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
AnalysisControl obj = (AnalysisControl) xStream.fromXML(xml);
String resultJson = JSON.toJSONString(obj);
return resultJson;
}
}

+ 61
- 0
src/main/java/com/inspect/tcpserver/tcp/MyDecoder.java View File

@ -0,0 +1,61 @@
package com.inspect.tcpserver.tcp;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import java.util.List;
public class MyDecoder extends ByteToMessageDecoder {
private final String PACKET_FLAG = "EB90";
private final int BASE_LENGTH = 2 + 8 + 8 + 1 + 4 + 2;
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
if (in.readableBytes() >= BASE_LENGTH) {
//skip
if (in.readableBytes() > 512 * 1024) {
in.skipBytes(in.readableBytes());
}
int index;
String flag;
while (true) {
index = in.readerIndex();
in.markReaderIndex();
byte[] dst = new byte[2];
in.readBytes(dst, 0, 2);
flag = ByteUtils.byte2Hex(dst);
if (PACKET_FLAG.equalsIgnoreCase(flag)) {
break;
}
in.resetReaderIndex();
if (in.readableBytes() < BASE_LENGTH) {
return;
}
}
long sendIndex = in.readLongLE();
long receiveIndex = in.readLongLE();
byte sourceFlag = in.readByte();
int xmlLength = in.readIntLE();
// int readableBytes = in.readableBytes();
// if(readableBytes<xmlLength)
if (in.readableBytes() < xmlLength) {
in.readerIndex(index);
return;
}
byte[] payload = new byte[xmlLength];
in.readBytes(payload);
in.readShortLE();
BinaryModel binaryModel = new BinaryModel();
binaryModel.receiveIndex = receiveIndex;
binaryModel.sendIndex = sendIndex;
binaryModel.sourceFlag = sourceFlag;
binaryModel.dataLength = xmlLength;
binaryModel.dataBuf = Unpooled.copiedBuffer(payload);
out.add(binaryModel);
}
}
}

+ 535
- 0
src/main/java/com/inspect/tcpserver/tcp/NettyClient.java View File

@ -0,0 +1,535 @@
package com.inspect.tcpserver.tcp;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.inspect.tcpserver.domain.Result;
import com.inspect.tcpserver.domain.UpSystemServerProperties;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.Xpp3Driver;
import com.thoughtworks.xstream.security.AnyTypePermission;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.CharsetUtil;
import io.netty.util.internal.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.util.TimerTask;
import java.util.concurrent.*;
@Component
public class NettyClient {
private Logger logger = LoggerFactory.getLogger(NettyClient.class);
// 客户端只需要一个 时间循环组 , NioEventLoopGroup 线程池
private static final EventLoopGroup eventLoopGroup = new NioEventLoopGroup(1);
;
private String serverIP;
private int serverPort;
private long sendIndex = 0; //若重启系统后还要延续之前的序列号则需要把序列号存入redis中
private long receiveIndex = 0;
private String sendCode;
private String receiveCode;
private UpJson2Xml up;
private DownXml2Json down;
private NettyClientHandler client;
private ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(4);
private ExecutorService executorService = new ThreadPoolExecutor(1, 5, 5L, TimeUnit.SECONDS, new ArrayBlockingQueue(4), Executors.defaultThreadFactory());
@Resource
UpSystemServerProperties upSystemServerProperties;
@Resource
private RestTemplate restTemplate;
@Resource
private RedisTemplate<String, String> redisTemplate;
@Value("${iip_server.send.url}")
String iipSendUrl;
@Value("${up_time_interval_setting}")
String upTimeIntervalSetting;
/**
* 接收/发送报文xml外层别名
*/
private String alias = "PatrolHost";
/**
* 设备层需要的编码,上报或下发的时候转
*/
private String deviceAlias = "PatrolDevice";
public NettyClient() {
up = new UpJson2Xml(alias);
down = new DownXml2Json(alias);
}
//释放资源
public void Close() {
if (eventLoopGroup != null) {
eventLoopGroup.shutdownGracefully();
}
scheduledExecutor.shutdown();
}
//连接服务器
@Async
public void ConnectServer() {
this.serverIP = upSystemServerProperties.ip;
this.serverPort = upSystemServerProperties.port;
this.sendCode = upSystemServerProperties.iipCode;
this.receiveCode = upSystemServerProperties.upCode;
try {
// 客户端启动对象
Bootstrap bootstrap = new Bootstrap();
// 设置相关参数
bootstrap.group(eventLoopGroup);
bootstrap.channel(NioSocketChannel.class);
bootstrap.option(ChannelOption.TCP_NODELAY, true);
bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000);
bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
bootstrap.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
client = new NettyClientHandler(NettyClient.this);
ch.pipeline().addLast(new MyDecoder());
ch.pipeline().addLast(client);
}
});
// 开始连接服务器, 并进行同步操作
// ChannelFuture 类分析 , Netty 异步模型
// sync 作用是该方法不会再次阻塞
ChannelFuture channelFuture = bootstrap.connect(serverIP, serverPort).addListener(new ConnectionListener(this)).sync();
logger.info("nettyClient连接服务器成功");
// 关闭通道, 开始监听
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//发送消息
public void SendMsg(boolean request, String xml) {
if (client != null && !StringUtil.isNullOrEmpty(xml)) {
ByteBuf byteBuf = Unpooled.copiedBuffer(xml, CharsetUtil.UTF_8);
int length = byteBuf.readableBytes();
ByteBuf allBuf = Unpooled.buffer(length + ConfigType.dataLegth);
allBuf.writeByte(0xEB);
allBuf.writeByte(0x90);
allBuf.writeLongLE(sendIndex);
allBuf.writeLongLE(receiveIndex);
allBuf.writeByte(request ? 0x00 : 0x01);
allBuf.writeIntLE(length);
allBuf.writeBytes(byteBuf);
allBuf.writeByte(0xEB);
allBuf.writeByte(0x90);
// 存入缓存
redisTemplate.opsForValue().set(String.valueOf(this.sendIndex), allBuf.toString(CharsetUtil.US_ASCII), 60L, TimeUnit.SECONDS);
client.sendMsg(allBuf);
this.sendIndex++;
} else {
logger.warn("与上级系统连接失败");
}
}
//重新发送
public void resetSendMsg(long sendIndex) {
if (client != null) {
// 获取缓存的中的值
String msg = redisTemplate.opsForValue().get(String.valueOf(sendIndex));
if (!StringUtil.isNullOrEmpty(msg)) {
ByteBuf allBuf = Unpooled.copiedBuffer(msg, CharsetUtil.US_ASCII);
client.sendMsg(allBuf);
}
}
}
//线程处理接收函数
public void ReceiveMsg(BinaryModel binaryModel) {
executorService.execute(() ->
{
try {
ThreadDealMsg(binaryModel);
} catch (Exception e) {
e.printStackTrace();
}
});
}
//处理接收消息
private void ThreadDealMsg(BinaryModel binaryModel) throws DocumentException {
String xml = binaryModel.dataBuf.toString(CharsetUtil.UTF_8);
logger.info("收到上级系统消息:{}", xml);
this.receiveIndex = binaryModel.sendIndex;
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8)));
Element root = document.getRootElement();
int type = 0;
if (null != root.element("Type") && !StringUtil.isNullOrEmpty(root.element("Type").getText())) {
type = Integer.parseInt(root.element("Type").getText());
}
int command = 0;
if (null != root.element("Command") && !StringUtil.isNullOrEmpty(root.element("Command").getText())) {
command = Integer.parseInt(root.element("Command").getText());
}
if (type == SystemType.system) {
if (command == SystemType.no_response || command == SystemType.has_response) {
if (null != root.element("Code")) {
if (root.element("Code").getText() == ResponseType.retry) {
resetSendMsg(binaryModel.receiveIndex);
}
}
}
}
// 发送给上级的响应
String response = "";
String json = null;
switch (type) {
case SystemType.system:
switch (command) {
case SystemType.has_response:
dealRegister(xml);
break;
case SystemType.no_response:
//心跳处理
break;
}
break;
case RobotType.robotVl:
case RobotType.robot:
case RobotType.robotCar:
case RobotType.robotFz:
case RobotType.robotIr:
case RobotType.robotPtz:
json = down.RobotControlXml2Json(xml);
break;
case UAVType.uav:
case UAVType.uavXj:
case UAVType.uavKz:
case UAVType.uavYt:
case UAVType.nest:
json = down.UavControlXml2Json(xml);
break;
case TaskType.taskControl:
json = down.BaseControlXml2Json(xml);
break;
case TaskType.taskSend:
json = down.TaskSendControlXml2Json(xml);
break;
case TaskType.lendonTask:
json = down.LendonTaskControlXml2Json(xml);
break;
case TaskType.taskArea:
json = down.AreaControlXml2Json(xml);
break;
case ModelType.modelSync:
json = down.BaseControlXml2Json(xml);
break;
case QueryType.queryResult:
json = down.ResultControlXml2Json(xml);
break;
default:
logger.warn("client-handle-接收到的type:{},不在处理范围内,不予处理", type);
}
// 将上级下发的指令转发到业务端处理接收业务端处理后的结果上报给上级系统
if (type != SystemType.system && !StringUtil.isNullOrEmpty(json)) {
//调用业务端处理
ResponseEntity<com.inspect.tcpserver.domain.Result> ajaxResultResponseEntity = restTemplate.postForEntity(iipSendUrl, json, com.inspect.tcpserver.domain.Result.class);
HttpStatus statusCode = ajaxResultResponseEntity.getStatusCode();
if (statusCode.equals(HttpStatus.OK)) {
// 调用业务端处理成功
Result body = ajaxResultResponseEntity.getBody();
if (null == body) {
logger.error("接收上级系统下发的指令,转发到应用业务端处理后,返回的响应体为空");
return;
}
String bodyCode = body.getCode();
String msg = body.getMsg();
String data = body.getData();
logger.info("接收到上级系统下发指令,转发到巡视主机,成功,返回code:{},msg:{},data:{}", bodyCode, msg, data);
// 响应巡视主机
JSONObject item = JSONObject.parseObject(data);
response = createDownResponse(item);
} else {
// 调用业务端处理失败
logger.warn("下发指令,失败,httpCode:{}", statusCode);
response = createDownFailResponse();
}
// 将xml消息转为json格式字符串
String msg = up.ModelJson2Xml(response);
// 上报上级系统会话类型为响应
SendMsg(false, msg);
}
}
//处理注册应答
public void dealRegister(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, RegisterResponseControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
RegisterResponseControl obj = (RegisterResponseControl) xStream.fromXML(xml);
TimerSendControl(obj);
logger.info("客户端 接收到服务端注册回馈,服务注册完成");
}
//处理心跳
public void TimerSendControl(RegisterResponseControl response) {
try {
if (response.Code.equals(ResponseType.succeed)) {
int heart = Integer.parseInt(response.Items.get(0).heart_beat_interval);
int patroldevice = Integer.parseInt(response.Items.get(0).patroldevice_run_interval);
int nest = Integer.parseInt(response.Items.get(0).nest_run_interval);
int weather = Integer.parseInt(response.Items.get(0).weather_interval);
SendHeart();
// 定时心跳报活
scheduledExecutor.scheduleWithFixedDelay(new TimerTask() {
@Override
public void run() {
SendHeart();
}
}, 0, heart, TimeUnit.SECONDS);
// 上级系统返回的定时信息存入redis
cacheTimeInterval(heart, patroldevice, nest, weather);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 缓存上级系统返回的定时任务间隔
*
* @param heart
* @param patroldevice
* @param nest
* @param weather
*/
private void cacheTimeInterval(int heart, int patroldevice, int nest, int weather) {
JSONObject json = new JSONObject();
json.put("heart", heart);
json.put("patroldevice", patroldevice);
json.put("nest", nest);
json.put("weather", weather);
redisTemplate.opsForValue().set(upTimeIntervalSetting, json.toJSONString());
}
private String createRegHeart(boolean isheart) {
ResponseControl obj = new ResponseControl();
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, ResponseControl.class);
obj.SendCode = sendCode;
obj.ReceiveCode = receiveCode;
obj.Type = String.valueOf(SystemType.system);
obj.Code = "";
obj.Command = String.valueOf(isheart ? SystemType.heart_request : SystemType.register_request);
obj.Time = CommonUtils.GetNowDateString();
obj.Items = "";
String resultXML = xStream.toXML(obj);
return resultXML;
}
/**
* 创建下发失败指令返回
*
* @param
* @return
*/
private String createDownFailResponse() {
JSONObject object = new JSONObject();
object.put("SendCode", sendCode);
object.put("ReceiveCode", receiveCode);
object.put("Type", SystemType.system);
object.put("Code", ResponseType.fault);
object.put("Command", SystemType.no_response);
JSONArray jsonArray = new JSONArray();
object.put("Items", jsonArray);
object.put("Time", CommonUtils.GetNowDateString());
return object.toString();
}
/**
* 创建下发成功指令返回
*
* @param
* @return
*/
private String createDownResponse(JSONObject item) {
JSONObject object = new JSONObject();
object.put("SendCode", sendCode);
object.put("ReceiveCode", receiveCode);
object.put("Type", SystemType.system);
object.put("Code", ResponseType.succeed);
if (null == item) {
object.put("Command", SystemType.no_response);
JSONArray jsonArray = new JSONArray();
object.put("Items", jsonArray);
} else {
object.put("Command", SystemType.has_response);
JSONArray jsonArray = new JSONArray();
jsonArray.add(item);
object.put("Items", jsonArray);
}
object.put("Time", CommonUtils.GetNowDateString());
return object.toString();
}
public void SendRegister() {
String xml = createRegHeart(false);
SendMsg(true, xml);
}
public void SendHeart() {
String xml = createRegHeart(true);
SendMsg(true, xml);
}
/**
* 处理身份
* 处理sendcode 为本机
* receiveCode 为无人机或机器人处理系统
*
* @return
*/
public JSONObject handleIdentity(JSONObject obj) {
// 从服务端发出的请求sendcode 应为服务端
obj.put("SendCode", sendCode);
obj.put("ReceiveCode", receiveCode);
return obj;
}
/**
* 发送消息
*
* @param json
*/
public void sendJsonMessage(String json) {
JSONObject obj = JSONObject.parseObject(json);
if (obj != null) {
// 处理身份
obj = handleIdentity(obj);
json = obj.toJSONString();
int type = Integer.parseInt(obj.get("Type").toString());
String xml = null;
switch (type) {
case PushType.environment:
xml = up.EnvironmentControlJson2Xml(json);
logger.info("向上级系统发送环境数据。{}", xml);
break;
case PushType.alarm:
xml = up.AlarmControlJson2Xml(json);
logger.info("向上级系统发送巡视设备异常告警数据。{}", xml);
break;
case PushType.analysisAlarm:
xml = up.AnalysisControlJson2Xml(json);
logger.info("向上级系统发送告警数据。{}", xml);
break;
case PushType.location:
xml = up.LocationControlJson2Xml(json);
logger.info("向上级系统发送巡视设备坐标。{}", xml);
break;
case PushType.monitor:
xml = up.MonitorControlJson2Xml(json);
logger.info("向上级系统发送静默监视告警数据。{}", xml);
break;
case PushType.nestRuning:
xml = up.NestRuningJson2Xml(json);
logger.info("向上级系统发送无人机机巢运行数据。{}", xml);
break;
case PushType.nestState:
xml = up.NestStateJson2Xml(json);
logger.info("向上级系统发送无人机机巢状态数据。{}", xml);
break;
case PushType.patrolDeviceState:
xml = up.PatrolDeviceStateControlJson2Xml(json);
logger.info("向上级系统发送巡视设备状态数据。{}", xml);
break;
case PushType.patrolDeviceRuning:
xml = up.PatrolDeviceRuningControlJson2Xml(json);
logger.info("向上级系统发送巡视设备运行数据。{}", xml);
break;
case PushType.result:
xml = up.TaskResultControlJson2Xml(json);
logger.info("向上级系统发送巡视结果。{}", xml);
break;
case PushType.taskState:
xml = up.TaskStateControlJson2Xml(json);
logger.info("向上级系统发送任务状态数据。{}", xml);
break;
case PushType.total:
xml = up.ReportControlJson2Xml(json);
logger.info("向上级系统发送巡视设备统计信息上报。{}", xml);
break;
case PushType.route:
xml = up.RouteControlJson2Xml(json);
logger.info("向上级系统发送巡视路线。{}", xml);
break;
case SystemType.system:
xml = up.ModelJson2Xml(json);
logger.info("向上级系统发送系统数据。{}", xml);
break;
case ModelType.modelUpdate:
xml = up.UpdateModelJson2Xml(json);
//xml = up.ModelJson2Xml(json, UpdateModelControl.class);
logger.info("向上级系统发送模型更新上报指令。{}", xml);
break;
default:
logger.warn("应用向上级系统发送消息,type:{}不在处理范围内,不予处理", type);
}
if (!StringUtils.isEmpty(xml)) {
// 将设备别名转换为上级别名
xml = xml.replaceAll(deviceAlias, alias);
SendMsg(true, xml);
}
}
}
}

+ 97
- 0
src/main/java/com/inspect/tcpserver/tcp/NettyClientHandler.java View File

@ -0,0 +1,97 @@
package com.inspect.tcpserver.tcp;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.EventLoop;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;
/**
* Handler 处理者, NioEventLoop 线程中处理业务逻辑的类
* <p>
* 继承 : 该业务逻辑处理者 ( Handler ) 必须继承 Netty 中的 ChannelInboundHandlerAdapter
* 才可以设置给 NioEventLoop 线程
* <p>
* 规范 : Handler 类中需要按照业务逻辑处理规范进行开发
*/
public class NettyClientHandler extends ChannelInboundHandlerAdapter {
private Logger logger = LoggerFactory.getLogger(NettyClientHandler.class);
private NettyClient nettyClient;
public ChannelHandlerContext Context;
public NettyClientHandler(NettyClient nettyClient) {
this.nettyClient = nettyClient;
}
public void sendMsg(ByteBuf byteBuf) {
if (Context != null) {
Context.writeAndFlush(byteBuf);
} else {
logger.info("client发送消息时,content为空,未连接服务端,取消发送");
}
}
// channel 处于不活动状态时调用
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
final EventLoop loop = ctx.channel().eventLoop();
loop.schedule(new Runnable() {
@Override
public void run() {
nettyClient.ConnectServer();
}
}, 3L, TimeUnit.SECONDS);
super.channelInactive(ctx);
}
/**
* 当客户端连接服务器完成就会触发该方法
*
* @param ctx
* @throws Exception
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
Context = ctx;
try {
nettyClient.SendRegister();
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
/**
* 读取数据 : 在服务器端读取客户端发送的数据
*
* @param ctx 通道处理者上下文对象 : 封装了 管道 ( Pipeline ) , 通道 ( Channel ), 客户端地址信息
* 管道 ( Pipeline ) : 注重业务逻辑处理 , 可以关联很多 Handler
* 通道 ( Channel ) : 注重数据读写
* @param msg 服务器返回的数据
* @throws Exception
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
nettyClient.ReceiveMsg((BinaryModel) msg);
}
/**
* 异常处理 , 上面的方法中都抛出了 Exception 异常, 在该方法中进行异常处理
*
* @param ctx
* @param cause
* @throws Exception
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
//如果出现异常, 就关闭该通道
ctx.close();
}
}

+ 491
- 0
src/main/java/com/inspect/tcpserver/tcp/NettyServer.java View File

@ -0,0 +1,491 @@
package com.inspect.tcpserver.tcp;
import com.alibaba.fastjson.JSONObject;
import com.inspect.tcpserver.constant.Constant;
import com.inspect.tcpserver.controller.ClientController;
import com.inspect.tcpserver.domain.DeviceServerProperties;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.Xpp3Driver;
import com.thoughtworks.xstream.security.AnyTypePermission;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.CharsetUtil;
import io.netty.util.internal.StringUtil;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;
/**
* @author yww
* <p>
* 服务启动监听器
**/
@Component
public class NettyServer {
private Logger logger = LoggerFactory.getLogger(NettyServer.class);
/**
* 接收/发送报文xml外层别名
*/
private String alias = "PatrolDevice";
@Resource
ClientController clientController;
private EventLoopGroup bossGroup;
private EventLoopGroup workGroup;
private Map<String, String> clients = new HashMap<>(); //机器人id,通道id
private long sendIndex = 0; //若重启系统后还要延续之前的序列号则需要把序列号存入redis中
private long receiveIndex = 0;
private DownXml2Json down = new DownXml2Json(alias);
private UpJson2Xml up = new UpJson2Xml(alias);
private NettyServerHandler nettyServerHandler;
private ExecutorService executorService = new ThreadPoolExecutor(1, 10, 5L, TimeUnit.SECONDS, new ArrayBlockingQueue(4), Executors.defaultThreadFactory());
@Resource
DeviceServerProperties deviceServerProperties;
@Resource
private RedisTemplate<String, String> redisTemplate;
@Resource
private RestTemplate restTemplate;
@Resource
private RabbitTemplate rabbitTemplate;
@Value("${iip_server.authDevice.url}")
String iipAuthDeviceUrl;
private String serverIP;
private int serverPort;
private int num = 410;
public void init() {
this.serverIP = deviceServerProperties.ip;
this.serverPort = deviceServerProperties.port;
up = new UpJson2Xml(alias);
down = new DownXml2Json(alias);
}
@Async
public void startServer() {
// 初始化
init();
//new 一个主线程组
bossGroup = new NioEventLoopGroup(1);
//new 一个工作线程组
workGroup = new NioEventLoopGroup(10);
ServerBootstrap bootstrap = new ServerBootstrap()
.group(bossGroup, workGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new MyDecoder());
nettyServerHandler = new NettyServerHandler(NettyServer.this);
ch.pipeline().addLast(nettyServerHandler);
}
})
.localAddress(serverPort)
//设置队列大小
.option(ChannelOption.SO_BACKLOG, 1024)
// 两小时内没有数据的通信时,TCP会自动发送一个活动探测数据报文
.childOption(ChannelOption.SO_KEEPALIVE, true);
//绑定端口,开始接收进来的连接
try {
ChannelFuture future = bootstrap.bind(serverPort).sync();
logger.info("nettyServer启动");
future.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
close();
}
}
//释放资源
public void close() {
if (bossGroup != null) {
bossGroup.shutdownGracefully();
}
if (workGroup != null) {
workGroup.shutdownGracefully();
}
}
//发送消息
public void SendMsg(String client, boolean request, String xml) {
logger.info("==========client===========" + client + "是否在线=" + clients.containsKey(client));
if (clients.containsKey(client) && !StringUtil.isNullOrEmpty(xml)) {
ByteBuf byteBuf = Unpooled.copiedBuffer(xml, CharsetUtil.UTF_8);
int length = byteBuf.readableBytes();
ByteBuf allBuf = Unpooled.buffer(length + ConfigType.dataLegth);
allBuf.writeByte(0xEB);
allBuf.writeByte(0x90);
allBuf.writeLongLE(sendIndex);
allBuf.writeLongLE(receiveIndex);
allBuf.writeByte(request ? 0x00 : 0x01);
allBuf.writeIntLE(length);
allBuf.writeBytes(byteBuf);
allBuf.writeByte(0xEB);
allBuf.writeByte(0x90);
// 存入缓存
redisTemplate.opsForValue().set(String.valueOf(this.sendIndex), allBuf.toString(CharsetUtil.US_ASCII), 60L, TimeUnit.SECONDS);
nettyServerHandler.SendMsg(clients.get(client), allBuf);
logger.info("发送到机器人发送会话序列号:{},接收会话序列号:{}", sendIndex, receiveIndex);
this.sendIndex++;
} else {
logger.warn("设备接入层下发消息时,设备不在线");
}
}
//开启线程处理消息
public void ReceiveMsg(BinaryModel binaryModel) {
executorService.execute(() ->
{
try {
ThreadDealMsg(binaryModel);
} catch (Exception e) {
e.printStackTrace();
}
});
}
//重新发送
public void resetSendMsg(long sendIndex, String sendCode) {
// 获取缓存的中的值
String msg = redisTemplate.opsForValue().get(String.valueOf(sendIndex));
if (!StringUtil.isNullOrEmpty(msg)) {
ByteBuf allBuf = Unpooled.copiedBuffer(msg, CharsetUtil.US_ASCII);
SendMsg(sendCode, true, msg);
}
}
//处理接收消息
private void ThreadDealMsg(BinaryModel binaryModel) throws DocumentException {
String xml = binaryModel.dataBuf.toString(CharsetUtil.UTF_8);
logger.info("接收到机器人发送会话序列号:{},接收会话序列号:{}", binaryModel.sendIndex, binaryModel.receiveIndex);
this.receiveIndex = binaryModel.sendIndex;
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8)));
Element root = document.getRootElement();
String sendCode = root.element("SendCode").getText();
clients.put(sendCode, binaryModel.id);//按照正常得逻辑是注册成功后在添加进关系中
int type = 0;
if (null != root.element("Type") && !StringUtil.isNullOrEmpty(root.element("Type").getText())) {
type = Integer.parseInt(root.element("Type").getText());
}
int command = 0;
if (null != root.element("Command") && !StringUtil.isNullOrEmpty(root.element("Command").getText())) {
command = Integer.parseInt(root.element("Command").getText());
}
//判断是否重发
if (type == SystemType.system) {
if (command == SystemType.has_response || command == SystemType.no_response) {
if (null != root.element("Code")) {
if (root.element("Code").getText() == ResponseType.retry) {
resetSendMsg(binaryModel.receiveIndex, sendCode);
}
}
}
}
String json = null;
switch (type) {
case SystemType.system:
switch (command) {
case SystemType.register_request:
// 处理注册请求响应
logger.info("收到接入侧注册信息:{}", xml);
dealRegister(xml);
logger.info("收到接入侧注册信息:{}", xml);
break;
case SystemType.heart_request:
// 处理心跳请求响应
logger.info("收到接入侧心跳信息:{}", xml);
SendHeart(xml);
break;
case SystemType.has_response:
// 处理有返回值的消息响应
if (null != root.element("Items") && null != root.element("Items").element("Item")) {
// 处理设备上报的模型同步响应
if (null != root.element("Items").element("Item").attribute("device_file_path")) {
logger.info("收到接入侧模型同步数据:{}", xml);
json = down.ModelControlXml2Json(xml);
JSONObject jsonObject = JSONObject.parseObject(json);
jsonObject.put("Type", Constant.MODEL_UP_TYPE);
rabbitTemplate.convertAndSend(Constant.EX_CHANGE_NAME, Constant.ROUTING_KEY_NAME, jsonObject.toJSONString());
}
// 任务控制响应任务执行ID
if (null != root.element("Items").element("Item").attribute("task_patrolled_id")) {
logger.info("收到接入侧任务下发或控制回复数据:{}", xml);
json = down.ModelControlXml2Json(xml);
JSONObject jsonObject = JSONObject.parseObject(json);
jsonObject.put("SendCode", "");
jsonObject.put("SendCode", "");
clientController.sendMsg(jsonObject.toJSONString());
}
} else {
logger.warn("接收到的系统类信息报文中,root:{},中不包含items或items中没有item,不予处理", root);
}
break;
default:
logger.warn("不予处理的消息体,{}", xml);
logger.warn("接收到的系统类信息报文中,command:{},不在处理范围内,不予处理", command);
}
break;
case PushType.patrolDeviceState:
json = down.PatrolDeviceStateControlXml2Json(xml);
logger.info("收到接入侧设备状态数据:{}", xml);
break;
case PushType.patrolDeviceRuning:
json = down.PatrolDeviceRuningControlXml2Json(xml);
logger.info("收到接入侧设备运行数据:{}", xml);
break;
case PushType.nestState:
json = down.NestStateControlXml2Json(xml);
logger.info("收到接入侧机巢状态数据{}", xml);
break;
case PushType.nestRuning:
json = down.NestRuningControlXml2Json(xml);
logger.info("收到接入侧机巢运行数据{}", xml);
break;
case PushType.location:
json = down.LocationControlXml2Json(xml);
logger.info("收到接入侧设备坐标{}", xml);
break;
case PushType.route:
json = down.RouteControlXml2Json(xml);
logger.info("收到接入侧设备路线{}", xml);
break;
case PushType.alarm:
json = down.AlarmControlXml2Json(xml);
logger.info("收到接入侧设备异常告警{}", xml);
break;
case PushType.environment:
json = down.EnvironmentControlXml2Json(xml);
logger.info("收到接入侧设备上报环境数据{}", xml);
break;
case PushType.taskState:
json = down.TaskStateControlXml2Json(xml);
logger.info("收到接入侧设备任务状态{}", xml);
break;
case PushType.result:
json = down.TaskResultControlXml2Json(xml);
logger.info("收到接入侧巡视结果{}", xml);
break;
default:
logger.warn("不予处理的消息体,{}", xml);
logger.warn("server-handle-接收到的type:{},不在处理范围内,不予处理", type);
}
if (type != SystemType.system && !StringUtil.isNullOrEmpty(json)) {
//rabbitmq推送到消息队列中基于springboot_xggd
rabbitTemplate.convertAndSend(Constant.EX_CHANGE_NAME, Constant.ROUTING_KEY_NAME, json);
String receiveCode = root.element("ReceiveCode").getText();
ResponseMsg(receiveCode, sendCode);
}
}
public void ResponseMsg(String sendCode, String receiveCode) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, ResponseControl.class);
xStream.autodetectAnnotations(true);
ResponseControl responseControl = new ResponseControl();
responseControl.SendCode = sendCode;
responseControl.ReceiveCode = receiveCode;
responseControl.Type = String.valueOf(SystemType.system);
responseControl.Code = ResponseType.succeed;
responseControl.Command = String.valueOf(SystemType.no_response);
responseControl.Time = CommonUtils.GetNowDateString();
responseControl.Items = "";
String xml = xStream.toXML(responseControl);
SendMsg(receiveCode, false, xml);
}
//处理注册应答
public void dealRegister(String xml) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
//xStream.alias(alias,BaseControl.class);
xStream.alias("PatrolHost", BaseControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
BaseControl obj = (BaseControl) xStream.fromXML(xml);
RegisterResponseControl responseControl = new RegisterResponseControl();
responseControl.SendCode = obj.ReceiveCode;
responseControl.ReceiveCode = obj.SendCode;
responseControl.Type = String.valueOf(SystemType.system);
responseControl.Command = String.valueOf(SystemType.has_response);
responseControl.Time = CommonUtils.GetNowDateString();
// 调用基础服务鉴权设备
if (authDevice(obj.SendCode)) {
//鉴权通过_xggd
responseControl.Code = ResponseType.succeed;
responseControl.Items = new ArrayList<>();
RegisterResponseModel model = new RegisterResponseModel();
model.patroldevice_run_interval = ConfigType.patroldevice_run_interval;
model.heart_beat_interval = ConfigType.heart_beat_interval;
model.env_interval = ConfigType.env_interval;
//model.weather_interval= ConfigType.weather_interval;
// 当连接客户端为无人机机巢时报文中增加机巢运行数据上报间隔
if (obj.SendCode.equals(deviceServerProperties.nestCode)) {
model.nest_run_interval = ConfigType.nest_run_interval;
}
responseControl.Items.add(model);
// 推送消息到mq
JSONObject jsonObject = new JSONObject();
jsonObject.put("patroldevice_code", obj.SendCode);
jsonObject.put("Type", "heartbeat");
jsonObject.put("eventType", "connect");
jsonObject.put("heart_beat_interval", ConfigType.heart_beat_interval);
rabbitTemplate.convertAndSend(Constant.EX_CHANGE_NAME, Constant.ROUTING_KEY_NAME, jsonObject.toJSONString());
} else {
// 鉴权不通过
responseControl.Code = ResponseType.fault;
}
SendRegisterResponse(responseControl, obj.SendCode);
}
/**
* 鉴权巡视设备
*
* @param sendCode 巡视设备机器人无人机唯一标识
* @return
*/
public boolean authDevice(String sendCode) {
// // 调用基础服务的鉴权巡视设备接口
// String url = String.format(iipAuthDeviceUrl,sendCode);
//
// String resultString = restTemplate.getForObject(url,String.class);
//
// Result result = JSONObject.parseObject(resultString, Result.class);
//
// // 判断鉴权结果
// if(StringUtils.equals(result.getCode(),"200")){
// logger.info("设备鉴权成功,result:{}",result);
// return true;
// }
//
// logger.warn("设备鉴权失败 sendCode:{},resutl:{}",sendCode,result);
// return false;
return true;
}
public void SendRegisterResponse(RegisterResponseControl responseControl, String sendCode) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, RegisterResponseControl.class);
xStream.autodetectAnnotations(true);
String xml = xStream.toXML(responseControl);
SendMsg(sendCode, false, xml);
}
public void SendHeart(String xml) {
logger.info("接收到机器人巡视系统心跳消息:{}", xml);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.alias(alias, BaseControl.class);
xStream.autodetectAnnotations(true);
xStream.ignoreUnknownElements();
xStream.addPermission(AnyTypePermission.ANY);
BaseControl obj = (BaseControl) xStream.fromXML(xml);
ResponseMsg(obj.ReceiveCode, obj.SendCode);
// 推送消息到mq
JSONObject jsonObject = new JSONObject();
jsonObject.put("SendCode", obj.SendCode);
jsonObject.put("Type", "heartbeat");
jsonObject.put("eventType", "heart");
jsonObject.put("heart_beat_interval", ConfigType.heart_beat_interval);
rabbitTemplate.convertAndSend(Constant.EX_CHANGE_NAME, Constant.ROUTING_KEY_NAME, jsonObject.toJSONString());
}
/**
* 判断机器人是否在线
*/
public boolean isOnline(String code) {
return clients.containsKey(code);
}
public void SendXmlMessage(JSONObject obj) {
int type = obj.getInteger("Type");
String receiveCode = obj.getString("ReceiveCode");
String json = obj.toJSONString();
String xml = null;
switch (type) {
case RobotType.robotVl:
case RobotType.robot:
case RobotType.robotCar:
case RobotType.robotFz:
case RobotType.robotIr:
case RobotType.robotPtz:
xml = up.RobotJson2Xml(json);
break;
case UAVType.uav:
case UAVType.uavXj:
case UAVType.uavKz:
case UAVType.uavYt:
case UAVType.nest:
xml = up.UavControlJson2Xml(json);
break;
case TaskType.taskControl:
xml = up.ResponseJson2Xml(json);
break;
case TaskType.taskSend:
xml = up.TaskSendJson2Xml(json);
break;
case TaskType.taskArea:
xml = up.AreaJson2Xml(json);
break;
case ModelType.modelSync:
xml = up.ResponseJson2Xml(json);
break;
case TaskType.lendonTask:
xml = up.LendonTaskJson2Xml(json);
break;
default:
logger.warn("应用向设备接入发送消息,type:{}不在处理范围内,不予处理", type);
}
if (!StringUtils.isEmpty(xml)) {
logger.info("向设备接入侧下发命令:{}", xml);
SendMsg(receiveCode, true, xml);
}
}
}

+ 83
- 0
src/main/java/com/inspect/tcpserver/tcp/NettyServerHandler.java View File

@ -0,0 +1,83 @@
package com.inspect.tcpserver.tcp;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
/**
* @author yww
* <p>
* netty服务端处理器
**/
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
public Logger logger = LoggerFactory.getLogger(NettyServerHandler.class);
private NettyServer nettyServer;
private Map<String, ChannelHandlerContext> ids = new HashMap<>();
public NettyServerHandler(NettyServer nettyServer) {
this.nettyServer = nettyServer;
}
public void SendMsg(String id, ByteBuf byteBuf) {
if (ids.containsKey(id)) {
ids.get(id).writeAndFlush(byteBuf);
}
}
/**
* 客户端连接会触发
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
String id = ctx.channel().id().asShortText();
ids.put(id, ctx);
logger.warn("设备连接,id:{}", id);
}
/**
* 客户端断开会触发
*/
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
ctx.close();
String id = ctx.channel().id().asShortText();
logger.warn("设备断开,id:{}", id);
if (ids.containsKey(id)) {
ids.remove(id);
}
super.channelInactive(ctx);
}
/**
* 客户端发消息会触发
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
logger.warn("channelRead!!!");
String id = ctx.channel().id().asShortText();
BinaryModel binaryModel = (BinaryModel) msg;
binaryModel.id = id;
nettyServer.ReceiveMsg((BinaryModel) msg);
}
/**
* 发生异常触发
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx.close();
String id = ctx.channel().id().asShortText();
if (ids.containsKey(id)) {
ids.remove(id);
}
}
}

+ 74
- 0
src/main/java/com/inspect/tcpserver/tcp/SystemType.java View File

@ -0,0 +1,74 @@
package com.inspect.tcpserver.tcp;
public class SystemType {
public static final int system = 251;
public static final int register_request = 1;
public static final int heart_request = 2;
public static final int has_response = 4;
public static final int no_response = 3;
}
class RobotType {
public static final int robot = 1;
public static final int robotCar = 2;
public static final int robotPtz = 3;
public static final int robotFz = 4;
public static final int robotVl = 21;
public static final int robotIr = 22;
}
class UAVType {
public static final int uav = 20001;
public static final int uavKz = 20002;
public static final int uavYt = 20003;
public static final int uavXj = 20004;
public static final int nest = 20005;
}
class TaskType {
public static final int taskControl = 41;
public static final int taskSend = 101;
public static final int lendonTask = 102;
public static final int taskArea = 81;
}
class ModelType {
public static final int modelSync = 61;
public static final int modelUpdate = 11;
}
class QueryType {
public static final int queryResult = 121;
}
class ResponseType {
public static final String retry = "100";
public static final String succeed = "200";
public static final String reject = "400";
public static final String fault = "500";
}
class PushType {
public static final int patrolDeviceState = 1;
public static final int patrolDeviceRuning = 2;
public static final int nestState = 20001;
public static final int nestRuning = 10004;
public static final int location = 3;
public static final int route = 4;
public static final int alarm = 5;
public static final int environment = 21;
public static final int taskState = 41;
public static final int result = 61;
public static final int analysisAlarm = 62;
public static final int monitor = 63;
public static final int total = 81;
}
class ConfigType {
public static final int dataLegth = 25;
public static final String heart_beat_interval = "300";
public static final String patroldevice_run_interval = "300";
public static final String nest_run_interval = "300";
public static final String env_interval = "300";
public static final String weather_interval = "300";
}

+ 268
- 0
src/main/java/com/inspect/tcpserver/tcp/UpJson2Xml.java View File

@ -0,0 +1,268 @@
package com.inspect.tcpserver.tcp;
import com.alibaba.fastjson.JSON;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.Xpp3Driver;
public class UpJson2Xml
{
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
/**
* 默认为对上级的客户端的别名
*/
private String alias;
public UpJson2Xml(String alias) {
// 设备接入服务
this.alias = alias;
}
public <T> String ModelJson2Xml(String json, Class<T> clazz) {
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, clazz.getClass());
T obj = JSON.parseObject(json,clazz);
return xStream.toXML(obj);
}
//模型更新上报指令
public String UpdateModelJson2Xml(String json)
{
UpdateModelControl obj=JSON.parseObject(json,UpdateModelControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, UpdateModelControl.class);
String resultXML = xStream.toXML(obj);
return resultXML;
}
//任务控制和模型同步
public String ResponseJson2Xml(String json)
{
ResponseControl obj=JSON.parseObject(json,ResponseControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, ResponseControl.class);
obj.Items="";
String resultXML = xStream.toXML(obj);
return resultXML;
}
//模型同步
public String ModelJson2Xml(String json)
{
BaseControl obj=JSON.parseObject(json,ModelControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, ModelControl.class);
String resultXML = xStream.toXML(obj);
return resultXML;
}
//机器人控制指令
public String RobotJson2Xml(String json)
{
RobotControl obj=JSON.parseObject(json,RobotControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, RobotControl.class);
String resultXML = xStream.toXML(obj);
return resultXML;
}
//无人机控制指令
public String UavControlJson2Xml(String json)
{
RobotControl obj=JSON.parseObject(json,RobotControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, RobotControl.class);
String resultXML = xStream.toXML(obj);
return resultXML;
}
//任务下发指令
public String TaskSendJson2Xml(String json)
{
TaskSendControl obj=JSON.parseObject(json,TaskSendControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, TaskSendControl.class);
String resultXML = xStream.toXML(obj);
return resultXML;
}
//联动任务下发指令
public String LendonTaskJson2Xml(String json)
{
LendonTaskControl obj=JSON.parseObject(json,LendonTaskControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, LendonTaskControl.class);
String resultXML = xStream.toXML(obj);
return resultXML;
}
//检修区域指令
public String AreaJson2Xml(String json)
{
AreaControl obj=JSON.parseObject(json,AreaControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, AreaControl.class);
String resultXML = xStream.toXML(obj);
return resultXML;
}
//-----------------------------------------上行数据----------------------------------//
//巡视设备状态数据
public String PatrolDeviceStateControlJson2Xml(String json)
{
PatrolDeviceStateControl obj=JSON.parseObject(json,PatrolDeviceStateControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, PatrolDeviceStateControl.class);
String resultXML = xStream.toXML(obj);
return resultXML;
}
//巡视设备运行数据
public String PatrolDeviceRuningControlJson2Xml(String json)
{
PatrolDeviceRuningControl obj=JSON.parseObject(json,PatrolDeviceRuningControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, PatrolDeviceRuningControl.class);
String resultXML = xStream.toXML(obj);
return resultXML;
}
//无人机机巢状态数据
public String NestStateJson2Xml(String json)
{
NestStateControl obj=JSON.parseObject(json,NestStateControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, NestStateControl.class);
String resultXML = xStream.toXML(obj);
return resultXML;
}
//无人机机巢运行数据
public String NestRuningJson2Xml(String json)
{
NestRuningControl obj=JSON.parseObject(json,NestRuningControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, NestRuningControl.class);
String resultXML = xStream.toXML(obj);
return resultXML;
}
//巡视设备坐标
public String LocationControlJson2Xml(String json)
{
LocationControl obj=JSON.parseObject(json,LocationControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, LocationControl.class);
String resultXML = xStream.toXML(obj);
return resultXML;
}
//巡视路线
public String RouteControlJson2Xml(String json)
{
RouteControl obj=JSON.parseObject(json,RouteControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, RouteControl.class);
String resultXML = xStream.toXML(obj);
return resultXML;
}
//巡视设备异常告警数据
public String AlarmControlJson2Xml(String json)
{
AlarmControl obj=JSON.parseObject(json,AlarmControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, AlarmControl.class);
String resultXML = xStream.toXML(obj);
return resultXML;
}
//环境数据
public String EnvironmentControlJson2Xml(String json)
{
EnvironmentControl obj=JSON.parseObject(json,EnvironmentControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, EnvironmentControl.class);
String resultXML = xStream.toXML(obj);
return resultXML;
}
//任务状态数据
public String TaskStateControlJson2Xml(String json)
{
TaskStateControl obj=JSON.parseObject(json,TaskStateControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, TaskStateControl.class);
String resultXML = xStream.toXML(obj);
return resultXML;
}
//巡视结果
public String TaskResultControlJson2Xml(String json)
{
TaskResultControl obj=JSON.parseObject(json,TaskResultControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, TaskResultControl.class);
String resultXML = xStream.toXML(obj);
return resultXML;
}
//静默监视告警数据
public String MonitorControlJson2Xml(String json)
{
MonitorControl obj=JSON.parseObject(json,MonitorControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, MonitorControl.class);
String resultXML = xStream.toXML(obj);
return resultXML;
}
//巡视设备统计信息上报
public String ReportControlJson2Xml(String json)
{
ReportControl obj=JSON.parseObject(json,ReportControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, ReportControl.class);
String resultXML = xStream.toXML(obj);
return resultXML;
}
//巡检告警数据
public String AnalysisControlJson2Xml(String json)
{
AnalysisControl obj=JSON.parseObject(json,AnalysisControl.class);
XStream xStream = new XStream(new Xpp3Driver(new NoNameCoder()));
xStream.autodetectAnnotations(true);
xStream.alias(alias, AnalysisControl.class);
String resultXML = xStream.toXML(obj);
return resultXML;
}
}

+ 46
- 0
src/main/java/com/inspect/tcpserver/util/SpringApplicationContext.java View File

@ -0,0 +1,46 @@
package com.inspect.tcpserver.util;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
@Service
public class SpringApplicationContext implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
SpringApplicationContext.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
checkApplicationContext();
return applicationContext;
}
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
checkApplicationContext();
return (T) applicationContext.getBean(name);
}
@SuppressWarnings("unchecked")
public static <T> T getBean(Class<T> clazz) {
checkApplicationContext();
return (T) applicationContext.getBeansOfType(clazz);
}
public static void cleanApplicationContext() {
applicationContext = null;
}
private static void checkApplicationContext() {
if (applicationContext == null) {
throw new IllegalStateException(
"applicationContext未注入,请在spring的context.xml中定义SpringContextHolder");
}
}
}

+ 41
- 0
src/main/resources/application-dev.yml View File

@ -0,0 +1,41 @@
spring:
application:
name: tcpServer
redis:
host: 127.0.0.1
rabbitmq:
host: 10.10.18.13
port: 5673
username: guest
password: guest
server:
port: 22508
deviceServer:
serverIp: 127.0.0.1
serverPort: 10011
deviceServerCode: "192.168.1.66"
robotCode: "E100-001"
nestCode: "UAV001"
deviceCode: "192.168.1.15"
upSystemServer:
serverIp: 127.0.0.1
serverPort: 10012
upCode: "192.168.1.99"
iipCode: "192.168.1.66"
iip_server:
send:
url: http://127.0.0.1:9901/client/send
authDevice:
url: http://127.0.0.1:9902/eqpbook/checkPatrolDeviceIsExist/%s
up_time_interval_setting: time_interval_up_system_setting
boot:
client: false
server: true

+ 42
- 0
src/main/resources/application-prod.yml View File

@ -0,0 +1,42 @@
spring:
application:
name: tcpServer
redis:
host: 199.199.199.1
rabbitmq:
host: 199.199.199.4
port: 5672
username: guest
password: guest
server:
port: 22508
deviceServer:
serverIp: 127.0.0.1
serverPort: 10011
deviceServerCode: "192.168.1.66"
robotCode: "192.168.1.15"
nestCode: "192.168.1.16"
deviceCode: "192.168.1.15"
upSystemServer:
serverIp: 192.168.1.99
serverPort: 10011
upCode: "192.168.1.99"
iipCode: "192.168.1.66"
iip_server:
send:
url: http://199.199.199.104:9901/client/send
authDevice:
url: http://199.199.199.199:9902/eqpbook/checkPatrolDeviceIsExist/%s
up_time_interval_setting: time_interval_up_system_setting
boot:
client: false
server: true

+ 42
- 0
src/main/resources/application-test.yml View File

@ -0,0 +1,42 @@
spring:
application:
name: tcpServer
redis:
host: 199.199.199.1
rabbitmq:
host: 199.199.199.4
port: 5672
username: guest
password: guest
server:
port: 22508
deviceServer:
serverIp: 127.0.0.1
serverPort: 10011
deviceServerCode: "192.168.1.66"
robotCode: "192.168.1.15"
nestCode: "192.168.1.16"
deviceCode: "192.168.1.15"
upSystemServer:
serverIp: 10.10.18.100
serverPort: 10011
upCode: "192.168.1.99"
iipCode: "192.168.1.66"
iip_server:
send:
url: http://199.199.199.104:9901/client/send
authDevice:
url: http://199.199.199.105:9902/eqpbook/checkPatrolDeviceIsExist/%s
up_time_interval_setting: time_interval_up_system_setting
boot:
client: true
server: true

+ 3
- 0
src/main/resources/application.yml View File

@ -0,0 +1,3 @@
spring:
profiles:
active: prod

+ 62
- 0
src/main/resources/logback.xml View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志输出格式 -->
<property name="log.pattern" value="请求traceId:[%X{traceId}] %d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>log/tcpServer.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>log/tcpServer.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 用于graylog收集日志信息使用-->
<appender name="GELF" class="biz.paluch.logging.gelf.logback.GelfLogbackAppender">
<!-- 改为自己的IP-->
<host>udp:10.10.18.185</host>
<port>12201</port>
<version>1.1</version>
<!-- 这里可以定义为服务名等-->
<facility>dliip-device</facility>
<!-- 手动添加字段 -->
<additionalFields>version=1.1,module=patrol</additionalFields>
<extractStackTrace>true</extractStackTrace>
<filterStackTrace>true</filterStackTrace>
<mdcProfiling>true</mdcProfiling>
<timestampPattern>yyyy-MM-dd HH:mm:ss,SSS</timestampPattern>
<maximumMessageSize>8192</maximumMessageSize>
<!-- This are fields using MDC -->
<mdcFields>mdcField1,mdcField2</mdcFields>
<dynamicMdcFields>mdc.*,(mdc|MDC)fields</dynamicMdcFields>
<includeFullMdc>true</includeFullMdc>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
</appender>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="GELF"/>
<appender-ref ref="file_info" />
<appender-ref ref="console" />
</root>
</configuration>

+ 13
- 0
src/test/java/com/inspect/tcpserver/TcpserverApplicationTests.java View File

@ -0,0 +1,13 @@
package com.inspect.tcpserver;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class TcpserverApplicationTests {
@Test
void contextLoads() {
}
}

Loading…
Cancel
Save