| @ -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/ | |||
| @ -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"] | |||
| @ -0,0 +1,4 @@ | |||
| 电力500协议中转站 | |||
| @ -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 "$@" | |||
| @ -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% | |||
| @ -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> | |||
| @ -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); | |||
| } | |||
| } | |||
| @ -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(); | |||
| } | |||
| } | |||
| @ -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); | |||
| } | |||
| } | |||
| @ -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(); | |||
| } | |||
| } | |||
| @ -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; | |||
| } | |||
| } | |||
| @ -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"; | |||
| } | |||
| @ -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, "数据格式不正确"); | |||
| } | |||
| } | |||
| } | |||
| @ -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); | |||
| } | |||
| } | |||
| } | |||
| @ -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); | |||
| } | |||
| } | |||
| @ -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; | |||
| } | |||
| @ -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; | |||
| } | |||
| @ -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; | |||
| } | |||
| } | |||
| @ -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; | |||
| } | |||
| @ -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; //路径 | |||
| } | |||
| @ -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; | |||
| } | |||
| @ -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; | |||
| } | |||
| } | |||
| @ -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); | |||
| } | |||
| } | |||
| @ -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); | |||
| } | |||
| } | |||
| } | |||
| @ -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; | |||
| } | |||
| } | |||
| @ -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); | |||
| } | |||
| } | |||
| } | |||
| @ -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); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @ -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(); | |||
| } | |||
| } | |||
| @ -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); | |||
| } | |||
| } | |||
| } | |||
| @ -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); | |||
| } | |||
| } | |||
| } | |||
| @ -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"; | |||
| } | |||
| @ -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; | |||
| } | |||
| } | |||
| @ -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"); | |||
| } | |||
| } | |||
| } | |||
| @ -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 | |||
| @ -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 | |||
| @ -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 | |||
| @ -0,0 +1,3 @@ | |||
| spring: | |||
| profiles: | |||
| active: prod | |||
| @ -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> | |||
| @ -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() { | |||
| } | |||
| } | |||