init
This commit is contained in:
commit
a1adfd9cbe
170
.gitignore
vendored
Normal file
170
.gitignore
vendored
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
#################
|
||||||
|
## Eclipse
|
||||||
|
#################
|
||||||
|
|
||||||
|
_site
|
||||||
|
*.iml
|
||||||
|
.idea/
|
||||||
|
target/
|
||||||
|
*.log
|
||||||
|
*.gz
|
||||||
|
out/
|
||||||
|
|
||||||
|
*.pydevproject
|
||||||
|
.project
|
||||||
|
.metadata
|
||||||
|
bin/
|
||||||
|
tmp/
|
||||||
|
*.tmp
|
||||||
|
*.bak
|
||||||
|
*.swp
|
||||||
|
*~.nib
|
||||||
|
.classpath
|
||||||
|
.settings/
|
||||||
|
.loadpath
|
||||||
|
|
||||||
|
# External tool builders
|
||||||
|
.externalToolBuilders/
|
||||||
|
|
||||||
|
# Locally stored "Eclipse launch configurations"
|
||||||
|
*.launch
|
||||||
|
|
||||||
|
# CDT-specific
|
||||||
|
.cproject
|
||||||
|
|
||||||
|
# PDT-specific
|
||||||
|
.buildpath
|
||||||
|
|
||||||
|
|
||||||
|
#################
|
||||||
|
## Visual Studio
|
||||||
|
#################
|
||||||
|
|
||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Rr]elease/
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.vspscc
|
||||||
|
.builds
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
#packages/
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish
|
||||||
|
|
||||||
|
# Others
|
||||||
|
[Bb]in
|
||||||
|
[Oo]bj
|
||||||
|
# sql
|
||||||
|
TestResults
|
||||||
|
*.Cache
|
||||||
|
ClientBin
|
||||||
|
stylecop.*
|
||||||
|
~$*
|
||||||
|
*.dbmdl
|
||||||
|
Generated_Code #added for RIA/Silverlight projects
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file to a newer
|
||||||
|
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
############
|
||||||
|
## Windows
|
||||||
|
############
|
||||||
|
|
||||||
|
# Windows image file caches
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
Desktop.ini
|
||||||
|
|
||||||
|
|
||||||
|
#############
|
||||||
|
## Python
|
||||||
|
#############
|
||||||
|
|
||||||
|
*.py[co]
|
||||||
|
|
||||||
|
# Packages
|
||||||
|
*.egg
|
||||||
|
*.egg-info
|
||||||
|
dist
|
||||||
|
build
|
||||||
|
eggs
|
||||||
|
parts
|
||||||
|
bin
|
||||||
|
var
|
||||||
|
sdist
|
||||||
|
develop-eggs
|
||||||
|
.installed.cfg
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
.coverage
|
||||||
|
.tox
|
||||||
|
|
||||||
|
#Translations
|
||||||
|
*.mo
|
||||||
|
|
||||||
|
#Mr Developer
|
||||||
|
.mr.developer.cfg
|
||||||
|
|
||||||
|
# Mac crap
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
.gradle
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
7
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
7
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
|
||||||
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
249
gradlew
vendored
Normal file
249
gradlew
vendored
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright © 2015-2021 the original authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# Gradle start up script for POSIX generated by Gradle.
|
||||||
|
#
|
||||||
|
# Important for running:
|
||||||
|
#
|
||||||
|
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||||
|
# noncompliant, but you have some other compliant shell such as ksh or
|
||||||
|
# bash, then to run this script, type that shell name before the whole
|
||||||
|
# command line, like:
|
||||||
|
#
|
||||||
|
# ksh Gradle
|
||||||
|
#
|
||||||
|
# Busybox and similar reduced shells will NOT work, because this script
|
||||||
|
# requires all of these POSIX shell features:
|
||||||
|
# * functions;
|
||||||
|
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||||
|
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||||
|
# * compound commands having a testable exit status, especially «case»;
|
||||||
|
# * various built-in commands including «command», «set», and «ulimit».
|
||||||
|
#
|
||||||
|
# Important for patching:
|
||||||
|
#
|
||||||
|
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||||
|
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||||
|
#
|
||||||
|
# The "traditional" practice of packing multiple parameters into a
|
||||||
|
# space-separated string is a well documented source of bugs and security
|
||||||
|
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||||
|
# options in "$@", and eventually passing that to Java.
|
||||||
|
#
|
||||||
|
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||||
|
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||||
|
# see the in-line comments for details.
|
||||||
|
#
|
||||||
|
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||||
|
# Darwin, MinGW, and NonStop.
|
||||||
|
#
|
||||||
|
# (3) This script is generated from the Groovy template
|
||||||
|
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
|
# within the Gradle project.
|
||||||
|
#
|
||||||
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
#
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
app_path=$0
|
||||||
|
|
||||||
|
# Need this for daisy-chained symlinks.
|
||||||
|
while
|
||||||
|
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||||
|
[ -h "$app_path" ]
|
||||||
|
do
|
||||||
|
ls=$( ls -ld "$app_path" )
|
||||||
|
link=${ls#*' -> '}
|
||||||
|
case $link in #(
|
||||||
|
/*) app_path=$link ;; #(
|
||||||
|
*) app_path=$APP_HOME$link ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# This is normally unused
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
APP_BASE_NAME=${0##*/}
|
||||||
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
|
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD=maximum
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "$( uname )" in #(
|
||||||
|
CYGWIN* ) cygwin=true ;; #(
|
||||||
|
Darwin* ) darwin=true ;; #(
|
||||||
|
MSYS* | MINGW* ) msys=true ;; #(
|
||||||
|
NONSTOP* ) nonstop=true ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
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
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD=java
|
||||||
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
|
case $MAX_FD in #(
|
||||||
|
max*)
|
||||||
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
|
warn "Could not query maximum file descriptor limit"
|
||||||
|
esac
|
||||||
|
case $MAX_FD in #(
|
||||||
|
'' | soft) :;; #(
|
||||||
|
*)
|
||||||
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
|
ulimit -n "$MAX_FD" ||
|
||||||
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, stacking in reverse order:
|
||||||
|
# * args from the command line
|
||||||
|
# * the main class name
|
||||||
|
# * -classpath
|
||||||
|
# * -D...appname settings
|
||||||
|
# * --module-path (only if needed)
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||||
|
|
||||||
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
|
if "$cygwin" || "$msys" ; then
|
||||||
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
|
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||||
|
|
||||||
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
|
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
for arg do
|
||||||
|
if
|
||||||
|
case $arg in #(
|
||||||
|
-*) false ;; # don't mess with options #(
|
||||||
|
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||||
|
[ -e "$t" ] ;; #(
|
||||||
|
*) false ;;
|
||||||
|
esac
|
||||||
|
then
|
||||||
|
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||||
|
fi
|
||||||
|
# Roll the args list around exactly as many times as the number of
|
||||||
|
# args, so each arg winds up back in the position where it started, but
|
||||||
|
# possibly modified.
|
||||||
|
#
|
||||||
|
# NB: a `for` loop captures its iteration list before it begins, so
|
||||||
|
# changing the positional parameters here affects neither the number of
|
||||||
|
# iterations, nor the values presented in `arg`.
|
||||||
|
shift # remove old arg
|
||||||
|
set -- "$@" "$arg" # push replacement arg
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# Collect all arguments for the java command:
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
|
# and any embedded shellness will be escaped.
|
||||||
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
|
# treated as '${Hostname}' itself on the command line.
|
||||||
|
|
||||||
|
set -- \
|
||||||
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
-classpath "$CLASSPATH" \
|
||||||
|
org.gradle.wrapper.GradleWrapperMain \
|
||||||
|
"$@"
|
||||||
|
|
||||||
|
# Stop when "xargs" is not available.
|
||||||
|
if ! command -v xargs >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "xargs is not available"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use "xargs" to parse quoted args.
|
||||||
|
#
|
||||||
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
#
|
||||||
|
# In Bash we could simply go:
|
||||||
|
#
|
||||||
|
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||||
|
# set -- "${ARGS[@]}" "$@"
|
||||||
|
#
|
||||||
|
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||||
|
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||||
|
# character that might be a shell metacharacter, then use eval to reverse
|
||||||
|
# that process (while maintaining the separation between arguments), and wrap
|
||||||
|
# the whole thing up as a single "set" statement.
|
||||||
|
#
|
||||||
|
# This will of course break if any of these variables contains a newline or
|
||||||
|
# an unmatched quote.
|
||||||
|
#
|
||||||
|
|
||||||
|
eval "set -- $(
|
||||||
|
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||||
|
xargs -n1 |
|
||||||
|
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||||
|
tr '\n' ' '
|
||||||
|
)" '"$@"'
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
92
gradlew.bat
vendored
Normal file
92
gradlew.bat
vendored
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem 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, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
|
||||||
|
@if "%DEBUG%"=="" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
|
@rem This is normally unused
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
|
echo. 1>&2
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
|
echo. 1>&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
|
echo. 1>&2
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
|
echo. 1>&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
set EXIT_CODE=%ERRORLEVEL%
|
||||||
|
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||||
|
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||||
|
exit /b %EXIT_CODE%
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
106
pom.xml
Normal file
106
pom.xml
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<?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.cisdi.data</groupId>
|
||||||
|
<artifactId>dacoo-data-sdk-yongfeng</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.13.2</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>org.springframework.boot</groupId>-->
|
||||||
|
<!-- <artifactId>spring-boot-starter-web</artifactId>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tomcat.embed</groupId>
|
||||||
|
<artifactId>tomcat-embed-core</artifactId>
|
||||||
|
<version>8.5.51</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tomcat.embed</groupId>
|
||||||
|
<artifactId>tomcat-embed-el</artifactId>
|
||||||
|
<version>8.5.51</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tomcat.embed</groupId>
|
||||||
|
<artifactId>tomcat-embed-websocket</artifactId>
|
||||||
|
<version>8.5.51</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tomcat</groupId>
|
||||||
|
<artifactId>tomcat-annotations-api</artifactId>
|
||||||
|
<version>8.5.51</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.cisdi.data</groupId>
|
||||||
|
<artifactId>dacoo-data-common</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.cisdi.data</groupId>
|
||||||
|
<artifactId>dacoo-data-sdk</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>netty-all</artifactId>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>netty-all</artifactId>
|
||||||
|
<version>4.1.97.Final</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-dbcp2</artifactId>
|
||||||
|
<version>2.8.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
<version>5.1.46</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<version>27.0-jre</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>easyexcel</artifactId>
|
||||||
|
<version>1.1.2-beta5</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.java-websocket</groupId>
|
||||||
|
<artifactId>Java-WebSocket</artifactId>
|
||||||
|
<version>1.3.8</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
|
||||||
|
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>1.18.28</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
28
rfid测试说明.txt
Normal file
28
rfid测试说明.txt
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
心跳报文
|
||||||
|
02486561727442656103
|
||||||
|
|
||||||
|
一个标签
|
||||||
|
02524630313030303103
|
||||||
|
|
||||||
|
--2条电文
|
||||||
|
0252463031303030310302524830333030303103
|
||||||
|
|
||||||
|
-- 4条电文
|
||||||
|
02524630313030303103025248303330303031030252463031303030310302524830333030303103
|
||||||
|
|
||||||
|
-- 4条电文心跳2:
|
||||||
|
025246303130303031030252483033303030310302524630313030303103025248303330303031030248656172744265610302486561727442656103
|
||||||
|
|
||||||
|
一个标签+心跳+ 一个标签
|
||||||
|
02524630313030303103024865617274426561030252463031303030310302524630313030303103025246303130303031030252463031303030310302524630313030303103025246303130303031030252483033303030310302524630313030303103025248303330303031030248656172744265610302486561727442656103
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- 启用心跳
|
||||||
|
{"enableHeartbeat":true,"heartbeatMaxLostCount":3,"heartbeatTimeInMs":5000}
|
||||||
|
|
||||||
|
--多个serverId
|
||||||
|
{"serverList":["10.233.8.22:2112","10.233.8.23:2112","10.233.8.24:2112","10.233.8.25:2112"]}
|
||||||
|
|
||||||
|
--启用心跳+ 多个server
|
||||||
|
{"enableHeartbeat":true,"heartbeatMaxLostCount":3,"heartbeatTimeInMs":5000,"serverList":["10.233.8.22:2112","10.233.8.23:2112","10.233.8.24:2112","10.233.8.25:2112"]}
|
2
settings.gradle
Normal file
2
settings.gradle
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
rootProject.name = 'dacoo-data-sdk-DI-client'
|
||||||
|
|
@ -0,0 +1,209 @@
|
|||||||
|
package com.cisdi.data.AMETEKSurfaceVision;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.cisdi.data.AMETEKSurfaceVision.gateway.SurfaceVisionAliveCheckTask;
|
||||||
|
import com.cisdi.data.AMETEKSurfaceVision.gateway.SurfaceVisionChannelInitializer;
|
||||||
|
import com.cisdi.data.AMETEKSurfaceVision.gateway.SurfaceVisionFrameDecoder;
|
||||||
|
import com.cisdi.data.AMETEKSurfaceVision.gateway.SurfaceVisionIoSession;
|
||||||
|
import com.cisdi.data.AMETEKSurfaceVision.gateway.SurfaceVisionSessionFactory;
|
||||||
|
import com.cisdi.data.AMETEKSurfaceVision.gateway.SurfaceVisionSocketReturnMessage;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import com.cisdi.data.sdk.consts.ServiceName;
|
||||||
|
import com.cisdi.data.sdk.enums.GatewayState;
|
||||||
|
import com.cisdi.data.sdk.gateway.base.SocketGatewayBase;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.IoSession;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.SessionFactory;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.TcpIoService;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.DefaultTcpIoService;
|
||||||
|
import com.cisdi.data.sdk.param.ListenSocketParam;
|
||||||
|
import com.cisdi.data.sdk.procotol.message.SocketReturnMessage;
|
||||||
|
import com.cisdi.data.sdk.service.RouteService;
|
||||||
|
import com.cisdi.data.sdk.vo.DeviceVo;
|
||||||
|
import com.cisdi.data.sdk.vo.ExeResultVo;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表检仪tcp协议 平台:server rfid:客户端
|
||||||
|
*
|
||||||
|
* @author tzz
|
||||||
|
*/
|
||||||
|
public class AMETEKSurfaceVisionGateway extends SocketGatewayBase {
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(AMETEKSurfaceVisionGateway.class);
|
||||||
|
private TcpIoService ioService = null;
|
||||||
|
private SessionFactory sessionFactory = null;
|
||||||
|
private AtomicBoolean shouldRun = new AtomicBoolean(false);
|
||||||
|
private String deviceId;
|
||||||
|
private BlockingQueue<SocketReturnMessage> sendQueue = new LinkedBlockingQueue<>(1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下发命令超时时间,单位毫秒
|
||||||
|
*/
|
||||||
|
private static int maxSendTime = 5000;
|
||||||
|
|
||||||
|
private static final int sleepInternal = 100;
|
||||||
|
//10毫秒
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
@Override
|
||||||
|
public ExeResultVo sendReturnMessage(SocketReturnMessage returnMsg) {
|
||||||
|
logger.info("send msg is :{}", returnMsg);
|
||||||
|
//阻塞队列,容量为1,若上一个命令未发送则阻塞
|
||||||
|
sendQueue.put(returnMsg);
|
||||||
|
|
||||||
|
ExeResultVo sendResult = new ExeResultVo();
|
||||||
|
sendResult.setSuccess(false);
|
||||||
|
|
||||||
|
try {
|
||||||
|
SurfaceVisionSocketReturnMessage sendMsg = new SurfaceVisionSocketReturnMessage();
|
||||||
|
BeanUtils.copyProperties(returnMsg, sendMsg);
|
||||||
|
sendMsg.setSendReturnFlag(false);
|
||||||
|
|
||||||
|
//发送下发命令
|
||||||
|
List<IoSession> sessions = sessionFactory.getSessions();
|
||||||
|
SurfaceVisionIoSession ioSession = (SurfaceVisionIoSession) sessions.get(0);
|
||||||
|
logger.info("send msg SurfaceVisionIoSession is :{}", ioSession);
|
||||||
|
ioSession.send(sendMsg);
|
||||||
|
|
||||||
|
//等待下发命令返回,若等待时间超过最大等待时长,直接返回下发失败,每隔sleepInternal时间判断一次
|
||||||
|
long sendTime = System.currentTimeMillis();
|
||||||
|
while (!sendMsg.getSendReturnFlag()) {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
if ((now - sendTime) > (maxSendTime)) {
|
||||||
|
sendResult.setMessage("下发命令响应超时,超时时间为:" + maxSendTime + "ms");
|
||||||
|
ioSession.setCurrentSend(null);
|
||||||
|
return sendResult;
|
||||||
|
}
|
||||||
|
Thread.sleep(sleepInternal);
|
||||||
|
}
|
||||||
|
ioSession.setCurrentSend(null);
|
||||||
|
logger.info("send result is :{}", sendMsg.getRealData());
|
||||||
|
|
||||||
|
sendResult = sendMsg.getRealData();
|
||||||
|
}catch (Exception e){
|
||||||
|
logger.error("下发中断,异常为: ", e);
|
||||||
|
sendResult.setMessage("下发异常中断");
|
||||||
|
}finally {
|
||||||
|
//空出阻塞队列
|
||||||
|
sendQueue.take();
|
||||||
|
}
|
||||||
|
return sendResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
if(state == GatewayState.RUNNING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//配置信息校验
|
||||||
|
ListenSocketParam socketParam = JSON.parseObject(getInstanceVo().getParameter(), ListenSocketParam.class);
|
||||||
|
|
||||||
|
maxSendTime = socketParam.getTimeout();
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(socketParam.getListenIp()) || socketParam.getListenPort() == null) {
|
||||||
|
throw new BusinessException("未正确配置监听ip地址和监听端口。");
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("AMETEKSurfaceVision网关:{}读取启动配置参数:{}",instanceVo.getRunId(), getInstanceVo().getParameter());
|
||||||
|
//读取网关连接配置参数
|
||||||
|
RouteService routeService = (RouteService) serviceProvider.getByName(ServiceName.Route);
|
||||||
|
List<DeviceVo> deviceVos = routeService.findByRunId(instanceVo.getRunId());
|
||||||
|
|
||||||
|
//一个网关连接只能配置一个设备
|
||||||
|
if(deviceVos.size() > 1) {
|
||||||
|
throw new BusinessException("网关Id:" +instanceVo.getRunId() + "为AMETEKSurfaceVision网关,只允许关联一个设备Id");
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceId = deviceVos.size() > 0 ? deviceVos.get(0).getDeviceId() : null;
|
||||||
|
|
||||||
|
if(StringUtils.isEmpty(deviceId)) {
|
||||||
|
throw new BusinessException("runId=" + getInstanceVo().getRunId() + "未正确配置网关和设备关联");
|
||||||
|
}
|
||||||
|
|
||||||
|
//创建session工厂并初始化
|
||||||
|
DefaultTcpIoService defaultIoService = new DefaultTcpIoService();
|
||||||
|
SessionFactory factory = new SurfaceVisionSessionFactory(deviceId);
|
||||||
|
factory.init(serviceProvider, this);
|
||||||
|
|
||||||
|
//初始化channel
|
||||||
|
SurfaceVisionChannelInitializer<SurfaceVisionFrameDecoder> channelInitializer =
|
||||||
|
new SurfaceVisionChannelInitializer<>(factory);
|
||||||
|
|
||||||
|
//初始化ioService
|
||||||
|
defaultIoService.init(instanceVo, factory, channelInitializer);
|
||||||
|
|
||||||
|
ioService = defaultIoService;
|
||||||
|
sessionFactory = factory;
|
||||||
|
|
||||||
|
//启动监听
|
||||||
|
boolean open = ioService.open();
|
||||||
|
|
||||||
|
if(open == true) {
|
||||||
|
state = GatewayState.RUNNING;
|
||||||
|
logger.info("AMETEKSurfaceVision网关:{}启动成功 参数:{}", instanceVo.getRunId(), getInstanceVo().getParameter());
|
||||||
|
instanceVo.setLogOpen(true);
|
||||||
|
//心跳机制
|
||||||
|
shouldRun.set(true);
|
||||||
|
//
|
||||||
|
// Integer keepAlive = socketParam.getKeepAlive();
|
||||||
|
//
|
||||||
|
// if(keepAlive == null || keepAlive < 10) {
|
||||||
|
// keepAlive = 10;
|
||||||
|
// }else if (keepAlive > 60) {
|
||||||
|
// keepAlive = 60;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// SurfaceVisionAliveCheckTask task = new SurfaceVisionAliveCheckTask(keepAlive, shouldRun, factory);
|
||||||
|
//
|
||||||
|
// Thread thread = new Thread(task, "ametek-surface-alive-check-thread-" + getInstanceVo().getRunId());
|
||||||
|
// thread.start();
|
||||||
|
}else {
|
||||||
|
logger.info("AMETEKSurfaceVision网关:{}启动失败 参数:{}", instanceVo.getRunId(), getInstanceVo().getParameter());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
if(state == GatewayState.CLOSED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//关闭channel
|
||||||
|
if(sessionFactory != null) {
|
||||||
|
for (IoSession ioSession : sessionFactory.getSessions()) {
|
||||||
|
SurfaceVisionIoSession imsIoSession = (SurfaceVisionIoSession)ioSession;
|
||||||
|
imsIoSession.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//关闭监听和会话
|
||||||
|
boolean close = ioService.close();
|
||||||
|
if(close == true) {
|
||||||
|
sessionFactory = null;
|
||||||
|
state = GatewayState.CLOSED;
|
||||||
|
shouldRun.set(false);
|
||||||
|
logger.info("AMETEKSurfaceVision网关:{}关闭成功", instanceVo.getRunId());
|
||||||
|
}else {
|
||||||
|
logger.info("AMETEKSurfaceVision网关:{}关闭失败", instanceVo.getRunId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getActiveDeviceIds() {
|
||||||
|
Set<String> set = Sets.newHashSet();
|
||||||
|
set.add(deviceId);
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package com.cisdi.data.AMETEKSurfaceVision;
|
||||||
|
|
||||||
|
import com.cisdi.data.AMETEKSurfaceVision.gateway.SurfaceVisionConstants;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.cisdi.data.sdk.gateway.message.SocketMessage;
|
||||||
|
import com.cisdi.data.sdk.procotol.SocketProtocol;
|
||||||
|
import com.cisdi.data.sdk.procotol.base.ProtocolBase;
|
||||||
|
import com.cisdi.data.sdk.procotol.message.SocketReturnMessage;
|
||||||
|
import com.cisdi.data.sdk.vo.DecodeVo;
|
||||||
|
import com.cisdi.data.sdk.vo.ReturnVo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表检仪协议发送给平台的数据编解码
|
||||||
|
*
|
||||||
|
* @author tzz
|
||||||
|
*/
|
||||||
|
public class AMETEKSurfaceVisionSocketProtocol extends ProtocolBase implements SocketProtocol {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public DecodeVo deCode(SocketMessage message) {
|
||||||
|
DecodeVo vo = new DecodeVo();
|
||||||
|
|
||||||
|
Object object = message.getPropsMap().get(SurfaceVisionConstants.S_V_SEND_PLATFORM_DATA);
|
||||||
|
|
||||||
|
Map<String, Object> map = (Map<String, Object>)object;
|
||||||
|
|
||||||
|
vo.setData(map);
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SocketReturnMessage enCode(ReturnVo returnVo) {
|
||||||
|
SocketReturnMessage message = new SocketReturnMessage();
|
||||||
|
message.setDeviceId(returnVo.getDeviceId());
|
||||||
|
message.setMsgId(returnVo.getMsgId());
|
||||||
|
message.setMsgKey(returnVo.getMsgKey());
|
||||||
|
message.getPropsMap().put(SurfaceVisionConstants.S_V_SEND_DATA, returnVo.getValue());
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,98 @@
|
|||||||
|
package com.cisdi.data.AMETEKSurfaceVision;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实例点位信息
|
||||||
|
*
|
||||||
|
* @author tzz
|
||||||
|
*/
|
||||||
|
public class DynamicCodeActionParamDTO {
|
||||||
|
public enum PropertyType {
|
||||||
|
BYTE,
|
||||||
|
BOOLEAN,
|
||||||
|
SHORT,
|
||||||
|
INT,
|
||||||
|
FLOAT,
|
||||||
|
DOUBLE,
|
||||||
|
STRING,
|
||||||
|
LONG,
|
||||||
|
PLACEHOLDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<PropertyConfig> propertyList;
|
||||||
|
|
||||||
|
public void appendProperty(PropertyConfig propertyConfig) {
|
||||||
|
|
||||||
|
if (propertyConfig == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propertyList == null) {
|
||||||
|
propertyList = new ArrayList<>();
|
||||||
|
}
|
||||||
|
propertyList.add(propertyConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PropertyConfig{
|
||||||
|
|
||||||
|
/** 属性Id*/
|
||||||
|
private String propertyId;
|
||||||
|
|
||||||
|
/** 属性类型*/
|
||||||
|
private PropertyType propertyType;
|
||||||
|
|
||||||
|
/**长度*/
|
||||||
|
private Integer length;
|
||||||
|
|
||||||
|
public String getPropertyId() {
|
||||||
|
return propertyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPropertyId(String propertyId) {
|
||||||
|
this.propertyId = propertyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PropertyType getPropertyType() {
|
||||||
|
return propertyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPropertyType(PropertyType propertyType) {
|
||||||
|
this.propertyType = propertyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getLength() {
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLength(Integer length) {
|
||||||
|
this.length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "PropertyConfig{" +
|
||||||
|
"propertyId='" + propertyId + '\'' +
|
||||||
|
", propertyType=" + propertyType +
|
||||||
|
", length=" + length +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PropertyConfig> getPropertyList() {
|
||||||
|
return propertyList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPropertyList(List<PropertyConfig> propertyList) {
|
||||||
|
this.propertyList = propertyList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "DynamicCodeActionParamDTO{" +
|
||||||
|
"propertyList=" + propertyList +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
package com.cisdi.data.AMETEKSurfaceVision.gateway;
|
||||||
|
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.IoSession;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.SessionFactory;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保活时间检测,如果超过指定时间,则关闭连接
|
||||||
|
* @author tzz
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class SurfaceVisionAliveCheckTask implements Runnable {
|
||||||
|
|
||||||
|
private SessionFactory sessionFactory;
|
||||||
|
private AtomicBoolean shouldRun = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会话允许的保活时间,单位秒
|
||||||
|
*/
|
||||||
|
private int keepAlive;
|
||||||
|
|
||||||
|
private static final double multiply = 2;
|
||||||
|
|
||||||
|
private static final int sleepInternal = 1000; // 1秒
|
||||||
|
|
||||||
|
public SurfaceVisionAliveCheckTask(int keepAlive, AtomicBoolean shouldRun, SessionFactory sessionFactory) {
|
||||||
|
super();
|
||||||
|
this.keepAlive = keepAlive;
|
||||||
|
this.shouldRun = shouldRun;
|
||||||
|
this.sessionFactory = sessionFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
log.info("启动SurfaceVision心跳及检测心跳线程");
|
||||||
|
|
||||||
|
while (shouldRun != null && shouldRun.get() == true) {
|
||||||
|
try {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
|
||||||
|
List<IoSession> sessions = sessionFactory.getSessions();
|
||||||
|
|
||||||
|
for (IoSession ioSession : sessions) {
|
||||||
|
SurfaceVisionIoSession session = (SurfaceVisionIoSession)ioSession;
|
||||||
|
log.info("{} 定时心跳发送检测", session.gwPrefix());
|
||||||
|
session.sendBeat();
|
||||||
|
|
||||||
|
// 超出指定倍数心跳时间,关闭通道
|
||||||
|
if((now - session.getLastAliveTime()) > (multiply * keepAlive * 1000)) {
|
||||||
|
session.close();
|
||||||
|
log.warn("{} 超出指定倍数{}心跳时间{},单位秒,关闭通道",
|
||||||
|
session.gwPrefix(), multiply, keepAlive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.sleep(sleepInternal);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn(e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("结束SurfaceVision保活超时检测线程");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
package com.cisdi.data.AMETEKSurfaceVision.gateway;
|
||||||
|
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.SessionFactory;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.AbstractChannelInitializer;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.AbstractIoChannelHandler;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.DefaultIoChannelHandler;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.ChannelHandler;
|
||||||
|
import io.netty.handler.timeout.IdleStateHandler;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表检仪协议通道初始化
|
||||||
|
*
|
||||||
|
* @author tzz
|
||||||
|
*/
|
||||||
|
public class SurfaceVisionChannelInitializer<I> extends AbstractChannelInitializer<I> {
|
||||||
|
private SessionFactory factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造通道初始化器对象
|
||||||
|
* @param factory 会话工厂
|
||||||
|
*/
|
||||||
|
public SurfaceVisionChannelInitializer(SessionFactory factory) {
|
||||||
|
this.factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
protected AbstractIoChannelHandler<I> getTailHandler() {
|
||||||
|
return new DefaultIoChannelHandler(factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<ChannelHandler> getHandlers() {
|
||||||
|
List<ChannelHandler> handlers = new ArrayList<ChannelHandler>();
|
||||||
|
handlers.add(new SurfaceVisionFrameDecoder());
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IdleStateHandler getIdleStateHandler() {
|
||||||
|
return new IdleStateHandler(15, 15, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ChannelHandler getSslChannelHandler(Channel socketChannel) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package com.cisdi.data.AMETEKSurfaceVision.gateway;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 存储表检仪协议常量信息
|
||||||
|
*
|
||||||
|
* @author tzz
|
||||||
|
*/
|
||||||
|
public final class SurfaceVisionConstants {
|
||||||
|
|
||||||
|
//下发命令返回消息头类型
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 非Query类型命令下发返回消息头,使用starWith判断
|
||||||
|
*/
|
||||||
|
public static final String RETURN_HEADER1 = "REPLY_";
|
||||||
|
/**
|
||||||
|
* 默认下发返回消息头(应为下发命令报错时消息返回头),使用equals判断
|
||||||
|
*/
|
||||||
|
public static final String RETURN_HEADER2 = "REPLY";
|
||||||
|
/**
|
||||||
|
* Query类型命令下发返回消息头,使用equals判断
|
||||||
|
*/
|
||||||
|
public static final String RETURN_HEADER3 = "RESULT";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 命令下发返回成功状态值,ok代表成功
|
||||||
|
*/
|
||||||
|
public static final String RETURN_OK = "OK";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息分隔符
|
||||||
|
*/
|
||||||
|
public static final String SEPARATE1 = "\\|";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息分隔符
|
||||||
|
*/
|
||||||
|
public static final char SEPARATE = '|';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息结束符(除|以外)
|
||||||
|
*/
|
||||||
|
public static final char[] END = {'$','\r','\n'};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query类型命令下发消息头,使用starWith判断
|
||||||
|
*/
|
||||||
|
public static final String QUERY = "QUERY";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下发命令计数器最大值
|
||||||
|
*/
|
||||||
|
public static final int MAX_COUNT = 100;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下发命令正常返回消息最小字段数
|
||||||
|
*/
|
||||||
|
public static final int MIN_NORMAL_RETURN = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下发命令数据KEY
|
||||||
|
*/
|
||||||
|
public static final String S_V_SEND_DATA = "surfaceVisionSendData";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回给平台数据KEY
|
||||||
|
*/
|
||||||
|
public static final String S_V_SEND_PLATFORM_DATA = "surfaceVisionSendPlatformData";
|
||||||
|
|
||||||
|
/** 心跳符,$的16进制 */
|
||||||
|
public static final byte BEAT_BYTE = 0x07;
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package com.cisdi.data.AMETEKSurfaceVision.gateway;
|
||||||
|
|
||||||
|
import com.cisdi.data.AMETEKSurfaceVision.DynamicCodeActionParamDTO.PropertyConfig;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表检仪编码
|
||||||
|
*
|
||||||
|
* @author zhongda
|
||||||
|
*/
|
||||||
|
public class SurfaceVisionEncoder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下发命令编码
|
||||||
|
* @param msgKey 消息头,也是平台电文ID
|
||||||
|
* @param propsMap 下发消息
|
||||||
|
* @param propertyConfigList 下发消息点位配置表
|
||||||
|
* @param count 下发消息replayId
|
||||||
|
*/
|
||||||
|
public static ByteBuf Encode(String msgKey, Map<String, Object> propsMap, List<PropertyConfig> propertyConfigList, int count) {
|
||||||
|
StringBuffer stringBuffer = new StringBuffer();
|
||||||
|
//组装消息头
|
||||||
|
stringBuffer.append(msgKey).append(SurfaceVisionConstants.SEPARATE);
|
||||||
|
//非Query命令添加replayId
|
||||||
|
if (!msgKey.startsWith(SurfaceVisionConstants.QUERY)){
|
||||||
|
stringBuffer.append(count).append(SurfaceVisionConstants.SEPARATE);
|
||||||
|
}
|
||||||
|
//组装消息体
|
||||||
|
for (PropertyConfig propertyConfig : propertyConfigList){
|
||||||
|
String key = propertyConfig.getPropertyId();
|
||||||
|
stringBuffer.append(propsMap.get(key))
|
||||||
|
.append(SurfaceVisionConstants.SEPARATE);
|
||||||
|
}
|
||||||
|
//组装消息结尾
|
||||||
|
stringBuffer.append(String.valueOf(SurfaceVisionConstants.END));
|
||||||
|
|
||||||
|
//UTF_8编码下发消息
|
||||||
|
byte[] bytes = stringBuffer.toString().getBytes(StandardCharsets.UTF_8);
|
||||||
|
ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(bytes);
|
||||||
|
|
||||||
|
return wrappedBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package com.cisdi.data.AMETEKSurfaceVision.gateway;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表检仪协议帧解码
|
||||||
|
*
|
||||||
|
* @author tzz
|
||||||
|
*/
|
||||||
|
public class SurfaceVisionFrameDecoder extends ByteToMessageDecoder {
|
||||||
|
/** 结束符除|第一位,$的16进制 */
|
||||||
|
private byte end = 0x24;
|
||||||
|
/** 结束符除|第二位,\r的16进制 */
|
||||||
|
private byte end1 = 0x0D;
|
||||||
|
/** 结束符除|第三位,\n的16进制 */
|
||||||
|
private byte end2 = 0x0A;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void decode(ChannelHandlerContext ctx, ByteBuf bufferIn, List<Object> out) throws Exception {
|
||||||
|
if (bufferIn.readableBytes() < 1){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final int beginIndex = bufferIn.readerIndex();
|
||||||
|
|
||||||
|
int length = 0;
|
||||||
|
for (int i = 0; i + 2 < bufferIn.readableBytes(); i += 1) {
|
||||||
|
byte curByte = bufferIn.getByte(beginIndex + i);
|
||||||
|
|
||||||
|
//判断是否为结束符,若为结束符读取从beginIndex开始的所有数据
|
||||||
|
if (curByte == end){
|
||||||
|
if (end1 == bufferIn.getByte(beginIndex + i + 1) &&
|
||||||
|
end2 == bufferIn.getByte(beginIndex + i + 2)){
|
||||||
|
length = i + 3;
|
||||||
|
byte[] bytes = new byte[i+3];
|
||||||
|
bufferIn.readBytes(bytes);
|
||||||
|
|
||||||
|
ByteBuf copiedBuff = Unpooled.copiedBuffer(bytes);
|
||||||
|
out.add(copiedBuff);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i + 3 == bufferIn.readableBytes()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//若未结束,重置读索引
|
||||||
|
bufferIn.readerIndex(beginIndex + length);
|
||||||
|
|
||||||
|
//解决可能得粘包和拆包问题
|
||||||
|
decode(ctx, bufferIn, out);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
package com.cisdi.data.AMETEKSurfaceVision.gateway;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tzz
|
||||||
|
*/
|
||||||
|
@ToString
|
||||||
|
public class SurfaceVisionFrameInputVo {
|
||||||
|
/** 电文ID */
|
||||||
|
private String msgKey;
|
||||||
|
/** 下发命令返回ID */
|
||||||
|
private Integer ReplayId;
|
||||||
|
/** 下发命令返回状态值,true:成功,false:失败 */
|
||||||
|
private Boolean status;
|
||||||
|
/** 下发命令返回描述 */
|
||||||
|
private String description;
|
||||||
|
/** 是否为心跳信息 */
|
||||||
|
private Boolean beatType = false;
|
||||||
|
/** 通过命令上传的返回的数据值,按照顺序填入 */
|
||||||
|
private List<String> data;
|
||||||
|
/** 通过命令上传的返回的数据值与配置点位的点位id对应,按照顺序对应 */
|
||||||
|
private Map<String, Object> returnData;
|
||||||
|
|
||||||
|
public String getMsgKey() {
|
||||||
|
return msgKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getReplayId() {
|
||||||
|
return ReplayId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getBeatType() {
|
||||||
|
return beatType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> getReturnData() {
|
||||||
|
return returnData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReturnData(Map<String, Object> returnData) {
|
||||||
|
this.returnData = returnData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBeatType(Boolean beatType) {
|
||||||
|
this.beatType = beatType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMsgKey(String msgKey) {
|
||||||
|
this.msgKey = msgKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReplayId(Integer replayId) {
|
||||||
|
ReplayId = replayId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(Boolean status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(List<String> data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,291 @@
|
|||||||
|
package com.cisdi.data.AMETEKSurfaceVision.gateway;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
|
||||||
|
import com.cisdi.data.AMETEKSurfaceVision.DynamicCodeActionParamDTO;
|
||||||
|
import com.cisdi.data.AMETEKSurfaceVision.DynamicCodeActionParamDTO.PropertyConfig;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import com.cisdi.data.sdk.consts.ServiceName;
|
||||||
|
import com.cisdi.data.sdk.gateway.message.SocketMessage;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.IoSession;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.AbstractIoSession;
|
||||||
|
import com.cisdi.data.sdk.service.DynamicCodecService;
|
||||||
|
import com.cisdi.data.sdk.service.SendService;
|
||||||
|
import com.cisdi.data.sdk.service.Service;
|
||||||
|
import com.cisdi.data.sdk.vo.ExeResultVo;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表检仪协议会话
|
||||||
|
*
|
||||||
|
* @author tzz
|
||||||
|
*/
|
||||||
|
public class SurfaceVisionIoSession extends AbstractIoSession implements IoSession {
|
||||||
|
private long lastAliveTime = System.currentTimeMillis();
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(SurfaceVisionIoSession.class);
|
||||||
|
private String deviceId = null;
|
||||||
|
private String gwPrefixCache = null;
|
||||||
|
private final static byte[] beat = {0x07,0x7C,0x24,0x0D,0x0A};
|
||||||
|
|
||||||
|
private int count = 1;
|
||||||
|
// 初始化为0的原子整型变量作为计数器,用作发送命令的replayId,初始值为1
|
||||||
|
|
||||||
|
/** 当前下发命令replayId */
|
||||||
|
private Integer currentCount = -1;
|
||||||
|
|
||||||
|
public void setCurrentSend(SurfaceVisionSocketReturnMessage currentSend) {
|
||||||
|
this.currentSend = currentSend;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 当前下发命令信息 */
|
||||||
|
private SurfaceVisionSocketReturnMessage currentSend = null;
|
||||||
|
|
||||||
|
public void increment() {
|
||||||
|
if (count < SurfaceVisionConstants.MAX_COUNT) {
|
||||||
|
count++;
|
||||||
|
// 自增1并返回新值
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
count = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCount() {
|
||||||
|
return count;
|
||||||
|
// 获取当前计数器的值
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public SurfaceVisionIoSession(String deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getDeviceIds() {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 获取当前下发电文点位配置信息 */
|
||||||
|
private List<PropertyConfig> getPropertyConfig(String msgKeyName){
|
||||||
|
//获取DynamicService
|
||||||
|
Service service = serviceProvider.getByName(ServiceName.DynamicCodec);
|
||||||
|
if (service == null || !(service instanceof DynamicCodecService)) {
|
||||||
|
throw new BusinessException("获取DynamicService失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取网关ID
|
||||||
|
String runId = socketGateway.getInstanceVo().getRunId();
|
||||||
|
|
||||||
|
//获取点位配置信息
|
||||||
|
DynamicCodecService dynamicCodecService = (DynamicCodecService)service;
|
||||||
|
String actionParam = dynamicCodecService.findByRunIdAndMsgKey(runId, msgKeyName);
|
||||||
|
DynamicCodeActionParamDTO dto = null;
|
||||||
|
try {
|
||||||
|
dto = JSON.parseObject(actionParam, DynamicCodeActionParamDTO.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new BusinessException("连接id:" + runId + "电文号:" + msgKeyName + "json转换错误", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dto == null || dto.getPropertyList() == null || dto.getPropertyList().isEmpty()) {
|
||||||
|
throw new BusinessException("连接id:" + runId + "电文号:" + msgKeyName + "属性列表为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回点位信息
|
||||||
|
return dto.getPropertyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRead(Object message) {
|
||||||
|
//获取表检仪上送或返回消息
|
||||||
|
ByteBuf inBuf = (ByteBuf) message;
|
||||||
|
|
||||||
|
int length = inBuf.readableBytes();
|
||||||
|
|
||||||
|
//将消息头和消息体拆包,解析出消息头信息
|
||||||
|
SurfaceVisionFrameInputVo vo = SurfaceVisionVoDecoder.Decode(inBuf);
|
||||||
|
logger.info("AMETEKSurfaceVision收到 msg: {}", vo);
|
||||||
|
|
||||||
|
//消息头,也是电文信息
|
||||||
|
String msgKey = vo.getMsgKey();
|
||||||
|
|
||||||
|
try {
|
||||||
|
//通过消息头判断返回消息类型
|
||||||
|
if(vo.getBeatType()){
|
||||||
|
//判断是否心跳信息
|
||||||
|
lastAliveTime = System.currentTimeMillis();
|
||||||
|
logger.info("接收到心跳消息,当前时间为:{}", lastAliveTime);
|
||||||
|
} else if (msgKey.startsWith(SurfaceVisionConstants.RETURN_HEADER1)) {
|
||||||
|
//非Query命令正常返回消息
|
||||||
|
//解码
|
||||||
|
SurfaceVisionVoDecoder.DecodeReturn(vo);
|
||||||
|
|
||||||
|
//组装返回信息,判断replayId是否一致
|
||||||
|
ExeResultVo sendResult = new ExeResultVo();
|
||||||
|
if (!currentCount.equals(vo.getReplayId())) {
|
||||||
|
logger.info("AMETEKSurfaceVision收到 msgkey: {} 消息:{}, ReplayId:{} 与实际发送下去的:{},不一致"
|
||||||
|
, msgKey, vo, vo.getReplayId(), currentCount);
|
||||||
|
sendResult.setSuccess(false);
|
||||||
|
sendResult.setMessage("返回消息replayId与发送消息replayId不符");
|
||||||
|
} else {
|
||||||
|
sendResult.setSuccess(vo.getStatus());
|
||||||
|
sendResult.setMessage(vo.getDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
//组装返回结果
|
||||||
|
returnData(sendResult);
|
||||||
|
} else if (SurfaceVisionConstants.RETURN_HEADER2.equals(msgKey)) {
|
||||||
|
//下发命令异常返回消息
|
||||||
|
//解码
|
||||||
|
SurfaceVisionVoDecoder.DecodeReturnError(vo);
|
||||||
|
|
||||||
|
ExeResultVo sendResult = new ExeResultVo();
|
||||||
|
sendResult.setSuccess(vo.getStatus());
|
||||||
|
sendResult.setMessage(vo.getDescription());
|
||||||
|
|
||||||
|
//组装返回结果
|
||||||
|
returnData(sendResult);
|
||||||
|
} else if (SurfaceVisionConstants.RETURN_HEADER3.equals(msgKey)) {
|
||||||
|
//Query命令返回
|
||||||
|
//解码
|
||||||
|
SurfaceVisionVoDecoder.DecodeReturnQuery(vo);
|
||||||
|
|
||||||
|
ExeResultVo sendResult = new ExeResultVo();
|
||||||
|
sendResult.setSuccess(vo.getStatus());
|
||||||
|
sendResult.setMessage(vo.getDescription());
|
||||||
|
|
||||||
|
Map<Object, Object> queryData = new HashMap<>();
|
||||||
|
queryData.putAll(vo.getReturnData());
|
||||||
|
sendResult.setData(queryData);
|
||||||
|
|
||||||
|
//组装返回结果
|
||||||
|
returnData(sendResult);
|
||||||
|
} else {
|
||||||
|
//主动上报消息
|
||||||
|
//解码
|
||||||
|
SurfaceVisionVoDecoder.DecodeData(vo, getPropertyConfig(msgKey));
|
||||||
|
Map<String, Object> realDataMap = vo.getReturnData();
|
||||||
|
|
||||||
|
//数据发送到平台
|
||||||
|
if (vo != null && serviceProvider != null && socketGateway != null) {
|
||||||
|
SendService service = (SendService) serviceProvider.getByName(ServiceName.Send);
|
||||||
|
|
||||||
|
//组装数据包
|
||||||
|
SocketMessage socketMessage = socketGateway.buildSocketMessage();
|
||||||
|
socketMessage.setDeviceId(deviceId);
|
||||||
|
|
||||||
|
socketMessage.getPropsMap().put(SurfaceVisionConstants.S_V_SEND_PLATFORM_DATA, realDataMap);
|
||||||
|
|
||||||
|
socketMessage.setMsgKey(msgKey);
|
||||||
|
|
||||||
|
//发送数据
|
||||||
|
service.sendMessage(socketMessage);
|
||||||
|
} else {
|
||||||
|
logger.info("AMETEKSurfaceVision收到 msgkey: {} 消息:{}, 但是不能发到平台", msgKey, JSON.toJSONString(realDataMap));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch (Exception e){
|
||||||
|
logger.error("AMETEKSurfaceVision接收消息匹配错误, msgKey: {}, msg:{}, error", msgKey, vo, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(socketGateway!= null && Boolean.TRUE.equals(socketGateway.getInstanceVo().getLogOpen())) {
|
||||||
|
logger.info("AMETEKSurfaceVision {} 报文长度:{} vo:{} ", getChannel(), length, JSON.toJSONString(vo));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 设置当前下发命令返回信息 */
|
||||||
|
private void returnData(ExeResultVo sendResult) {
|
||||||
|
if(currentSend == null){
|
||||||
|
throw new BusinessException("下发返回消息没有对应的下发命令");
|
||||||
|
}
|
||||||
|
currentSend.setRealData(sendResult);
|
||||||
|
currentSend.setSendReturnFlag(true);
|
||||||
|
currentSend = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOpen() {
|
||||||
|
super.onOpen();
|
||||||
|
logger.info("建立连接,channel:{}", getChannel());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClose() {
|
||||||
|
super.onClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
if(getChannel() != null) {
|
||||||
|
try {
|
||||||
|
getChannel().close().sync();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
logger.warn(e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String gwPrefix() {
|
||||||
|
if(gwPrefixCache != null) {
|
||||||
|
return gwPrefixCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
gwPrefixCache = "";
|
||||||
|
if(socketGateway != null && socketGateway.getInstanceVo() != null) {
|
||||||
|
gwPrefixCache = "网关Id:" + socketGateway.getInstanceVo().getRunId() + "连接:" + getChannel() + " ";
|
||||||
|
}else {
|
||||||
|
gwPrefixCache = "连接:" + getChannel() + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return gwPrefixCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLastAliveTime() {
|
||||||
|
return lastAliveTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void send(Object message) {
|
||||||
|
//下发命令
|
||||||
|
SurfaceVisionSocketReturnMessage returnMsg = (SurfaceVisionSocketReturnMessage) message;
|
||||||
|
String msgKey = returnMsg.getMsgKey();
|
||||||
|
|
||||||
|
//与AMETEKSurfaceVisionSocketProtocol类对应
|
||||||
|
Map<String, Object> propsMap = (Map<String, Object>)
|
||||||
|
returnMsg.getPropsMap().get(SurfaceVisionConstants.S_V_SEND_DATA);
|
||||||
|
|
||||||
|
//获取下发点位配置
|
||||||
|
List<PropertyConfig> propertyConfigList = getPropertyConfig(msgKey);
|
||||||
|
|
||||||
|
//获取计数器值作为下发命令replayId
|
||||||
|
int c = getCount();
|
||||||
|
logger.info("下发数据, 数据:{}, 点位配置:{}, 返回ID:{}", propsMap, propertyConfigList, c);
|
||||||
|
|
||||||
|
ByteBuf byteBuf = SurfaceVisionEncoder.Encode(msgKey, propsMap, propertyConfigList, c);
|
||||||
|
logger.info("下发数据的byteBuf:{}", byteBuf);
|
||||||
|
|
||||||
|
//下发命令编码后发送
|
||||||
|
getChannel().writeAndFlush(byteBuf);
|
||||||
|
|
||||||
|
logger.info("下发数据成功");
|
||||||
|
|
||||||
|
//缓存当前下发命令信息和replayId
|
||||||
|
currentSend = returnMsg;
|
||||||
|
currentCount = c;
|
||||||
|
|
||||||
|
//计数器自增
|
||||||
|
increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendBeat() {
|
||||||
|
logger.info("发送心跳");
|
||||||
|
ByteBuf byteBuf = Unpooled.wrappedBuffer(beat);
|
||||||
|
getChannel().writeAndFlush(byteBuf);
|
||||||
|
logger.info("心跳发送成功");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.cisdi.data.AMETEKSurfaceVision.gateway;
|
||||||
|
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.IoSession;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.AbstractSessionFactory;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表检仪协议会话工厂
|
||||||
|
*
|
||||||
|
* @author tzz
|
||||||
|
*/
|
||||||
|
public class SurfaceVisionSessionFactory extends AbstractSessionFactory {
|
||||||
|
private String deviceId;
|
||||||
|
|
||||||
|
public SurfaceVisionSessionFactory(String deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IoSession newSession() {
|
||||||
|
IoSession session = new SurfaceVisionIoSession(deviceId);
|
||||||
|
session.init(UUID.randomUUID().toString(), provider, socketGateway);
|
||||||
|
sessionSet.add(session);
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package com.cisdi.data.AMETEKSurfaceVision.gateway;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.cisdi.data.sdk.procotol.message.SocketReturnMessage;
|
||||||
|
import com.cisdi.data.sdk.vo.ExeResultVo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表检仪协议下发消息及返回信息
|
||||||
|
*
|
||||||
|
* @author tzz
|
||||||
|
*/
|
||||||
|
public class SurfaceVisionSocketReturnMessage extends SocketReturnMessage {
|
||||||
|
/** 下发消息返回消息 */
|
||||||
|
ExeResultVo realData;
|
||||||
|
/** 下发消息返回标志 */
|
||||||
|
boolean sendReturnFlag;
|
||||||
|
|
||||||
|
public SurfaceVisionSocketReturnMessage() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExeResultVo getRealData() {
|
||||||
|
return this.realData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRealData(ExeResultVo realData) {
|
||||||
|
this.realData = realData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getSendReturnFlag() {
|
||||||
|
return this.sendReturnFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSendReturnFlag(boolean sendReturnFlag) {
|
||||||
|
this.sendReturnFlag = sendReturnFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return JSON.toJSONString(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,226 @@
|
|||||||
|
package com.cisdi.data.AMETEKSurfaceVision.gateway;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.cisdi.data.AMETEKSurfaceVision.DynamicCodeActionParamDTO.PropertyConfig;
|
||||||
|
import com.cisdi.data.AMETEKSurfaceVision.DynamicCodeActionParamDTO.PropertyType;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import com.cisdi.data.sdk.procotol.message.SocketReturnMessage;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表检仪解码
|
||||||
|
*
|
||||||
|
* @author zhongda
|
||||||
|
*/
|
||||||
|
public class SurfaceVisionVoDecoder {
|
||||||
|
/** 将消息头和消息体拆包,解析出消息头信息 */
|
||||||
|
public static SurfaceVisionFrameInputVo Decode(ByteBuf in) {
|
||||||
|
SurfaceVisionFrameInputVo vo = new SurfaceVisionFrameInputVo();
|
||||||
|
//消息体部分
|
||||||
|
int length;
|
||||||
|
if (in == null) {
|
||||||
|
throw new BusinessException("ByteBuf 入参为null");
|
||||||
|
} else if (in.readableBytes() > 4) {
|
||||||
|
length = in.readableBytes();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new BusinessException("报文长度不匹配 ,期望:大于4,实际:" + in.readableBytes());
|
||||||
|
}
|
||||||
|
//去掉结束符
|
||||||
|
byte[] headerBytes = new byte[length - 4];
|
||||||
|
in.readBytes(headerBytes);
|
||||||
|
|
||||||
|
//将数据流转为字符串,UTF_8编码
|
||||||
|
String strData = new String(headerBytes, StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
//以分隔符分割数据
|
||||||
|
List<String> data = Arrays.asList(strData.split(SurfaceVisionConstants.SEPARATE1, -1));
|
||||||
|
|
||||||
|
//获取报文头
|
||||||
|
vo.setMsgKey(data.get(0));
|
||||||
|
|
||||||
|
//去掉报文头
|
||||||
|
vo.setData(data.subList(1, data.size()));
|
||||||
|
|
||||||
|
//判断是否为心跳帧
|
||||||
|
byte[] header = data.get(0).getBytes(StandardCharsets.UTF_8);
|
||||||
|
if (header.length == 1 && header[0] == SurfaceVisionConstants.BEAT_BYTE){
|
||||||
|
vo.setBeatType(true);
|
||||||
|
}
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 非Query命令正常返回消息解码 */
|
||||||
|
public static void DecodeReturn(SurfaceVisionFrameInputVo vo) {
|
||||||
|
List<String> data = vo.getData();
|
||||||
|
if (data.size() < SurfaceVisionConstants.MIN_NORMAL_RETURN){
|
||||||
|
throw new BusinessException("返回消息不标准,msg:" + JSON.toJSONString(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
vo.setReplayId(Integer.valueOf(data.get(0)));
|
||||||
|
vo.setStatus(SurfaceVisionConstants.RETURN_OK.equalsIgnoreCase(data.get(1)));
|
||||||
|
vo.setDescription(data.get(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 命令异常返回消息解码 */
|
||||||
|
public static void DecodeReturnError(SurfaceVisionFrameInputVo vo) {
|
||||||
|
List<String> data = vo.getData();
|
||||||
|
int size = data.size();
|
||||||
|
if (size < SurfaceVisionConstants.MIN_NORMAL_RETURN){
|
||||||
|
throw new BusinessException("返回消息不标准,msg:" + JSON.toJSONString(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuffer message = new StringBuffer();
|
||||||
|
message.append(data.get(size - 1))
|
||||||
|
.append(":")
|
||||||
|
.append(data.get(size - 2));
|
||||||
|
|
||||||
|
vo.setReplayId(0);
|
||||||
|
vo.setStatus(false);
|
||||||
|
vo.setDescription(message.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Query命令返回消息解码 */
|
||||||
|
public static void DecodeReturnQuery(SurfaceVisionFrameInputVo vo) {
|
||||||
|
List<String> data = vo.getData();
|
||||||
|
int size = data.size();
|
||||||
|
if (size < 2){
|
||||||
|
throw new BusinessException("返回查询消息不标准,msg:" + JSON.toJSONString(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> queryData = new HashMap<>();
|
||||||
|
queryData.put("result", data.get(size - 1));
|
||||||
|
|
||||||
|
vo.setReplayId(0);
|
||||||
|
vo.setStatus(true);
|
||||||
|
vo.setReturnData(queryData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 上送消息解码 */
|
||||||
|
public static void DecodeData(SurfaceVisionFrameInputVo vo, List<PropertyConfig> propertyConfigs) {
|
||||||
|
List<String> data = vo.getData();
|
||||||
|
|
||||||
|
//判断上送消息字段数是否与点位配置信息字段数一致
|
||||||
|
if (data.size() != propertyConfigs.size()){
|
||||||
|
StringBuffer stringBuffer = new StringBuffer();
|
||||||
|
stringBuffer.append("报文数据字段数与点位配置不一致 ,电文ID:")
|
||||||
|
.append(vo.getMsgKey())
|
||||||
|
.append(",电文字段数:")
|
||||||
|
.append(data.size())
|
||||||
|
.append(", 点位字段数:")
|
||||||
|
.append(propertyConfigs.size());
|
||||||
|
throw new BusinessException(stringBuffer.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> valueMap = new HashMap<>();
|
||||||
|
|
||||||
|
//按照点位配置字段顺序获取上送信息
|
||||||
|
for (int i = 0; i < data.size(); i++){
|
||||||
|
String value = data.get(i);
|
||||||
|
PropertyConfig propertyConfig = propertyConfigs.get(i);
|
||||||
|
|
||||||
|
PropertyType propertyType = propertyConfig.getPropertyType();
|
||||||
|
|
||||||
|
String propertyId = propertyConfig.getPropertyId();
|
||||||
|
|
||||||
|
formatValue(valueMap, value, propertyType, propertyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
vo.setReturnData(valueMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 更具字段类型格式化数据值 */
|
||||||
|
private static void formatValue(Map<String, Object> valueMap, String value, PropertyType propertyType, String propertyId) {
|
||||||
|
switch (propertyType){
|
||||||
|
case INT: {
|
||||||
|
valueMap.put(propertyId, Integer.valueOf(value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BYTE: {
|
||||||
|
valueMap.put(propertyId, Byte.valueOf(value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BOOLEAN: {
|
||||||
|
valueMap.put(propertyId, Boolean.valueOf(value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SHORT: {
|
||||||
|
valueMap.put(propertyId, Short.valueOf(value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case FLOAT: {
|
||||||
|
valueMap.put(propertyId, Float.valueOf(value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DOUBLE: {
|
||||||
|
valueMap.put(propertyId, Double.valueOf(value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LONG: {
|
||||||
|
valueMap.put(propertyId, Long.valueOf(value));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:{
|
||||||
|
valueMap.put(propertyId, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
//标签读取
|
||||||
|
SurfaceVisionFrameDecoder surfaceVisionFrameDecoder = new SurfaceVisionFrameDecoder();
|
||||||
|
// String str = "DEFECT|1|3|2011-03-19 15:21:45|2.54|1.73|252.76|$\r\n";
|
||||||
|
//粘包
|
||||||
|
String str = "DEFECT|1|3|2011-03-19 15:21:45||1.23||$\r\nDEFECT|1|3|2011-03-19 15:21:45||1.23||";
|
||||||
|
// String str = "DEFECT|1|3|2011-03-19 15:21:45|2.54|1.73|252.76|$\r\n";
|
||||||
|
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
|
||||||
|
ByteBuf copiedBuff = Unpooled.copiedBuffer(bytes);
|
||||||
|
List<Object> out = new ArrayList<Object>();
|
||||||
|
surfaceVisionFrameDecoder.decode(null, copiedBuff, out);
|
||||||
|
|
||||||
|
ByteBuf bufferIn = (ByteBuf) out.get(0);
|
||||||
|
|
||||||
|
SurfaceVisionFrameInputVo vo = Decode(bufferIn);
|
||||||
|
String msgKey = vo.getMsgKey();
|
||||||
|
|
||||||
|
SocketReturnMessage returnMsg = new SocketReturnMessage();
|
||||||
|
returnMsg.setMsgKey("1");
|
||||||
|
returnMsg.setMsgId("2");
|
||||||
|
returnMsg.setData(new byte[3]);
|
||||||
|
|
||||||
|
SurfaceVisionSocketReturnMessage sendMsg = new SurfaceVisionSocketReturnMessage();
|
||||||
|
BeanUtils.copyProperties(returnMsg, sendMsg);
|
||||||
|
|
||||||
|
sendMsg.setSendReturnFlag(true);
|
||||||
|
|
||||||
|
String msgKey1 = "test";
|
||||||
|
Map<String, Object> propsMap = new HashMap<>();
|
||||||
|
propsMap.put("id1", 1);
|
||||||
|
propsMap.put("id2", 2.33);
|
||||||
|
propsMap.put("id3", "value");
|
||||||
|
List<PropertyConfig> propertyConfigList = new ArrayList<>();
|
||||||
|
PropertyConfig propertyConfig1 = new PropertyConfig();
|
||||||
|
propertyConfig1.setPropertyId("id1");
|
||||||
|
propertyConfigList.add(propertyConfig1);
|
||||||
|
PropertyConfig propertyConfig2 = new PropertyConfig();
|
||||||
|
propertyConfig2.setPropertyId("id2");
|
||||||
|
propertyConfigList.add(propertyConfig2);
|
||||||
|
PropertyConfig propertyConfig3 = new PropertyConfig();
|
||||||
|
propertyConfig3.setPropertyId("id3");
|
||||||
|
propertyConfigList.add(propertyConfig3);
|
||||||
|
int count = 1;
|
||||||
|
|
||||||
|
SurfaceVisionEncoder.Encode(msgKey1, propsMap, propertyConfigList, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
354
src/main/java/com/cisdi/data/DHV/YFDHealthVibrationGateway.java
Normal file
354
src/main/java/com/cisdi/data/DHV/YFDHealthVibrationGateway.java
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
package com.cisdi.data.DHV;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.JSONArray;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.cisdi.data.DHV.gateway.vo.dhv.OtherParamVO;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import com.cisdi.data.sdk.consts.ServiceName;
|
||||||
|
import com.cisdi.data.sdk.enums.GatewayState;
|
||||||
|
import com.cisdi.data.sdk.gateway.base.PulledHttpGatewayBase;
|
||||||
|
import com.cisdi.data.sdk.param.PullHttpParam;
|
||||||
|
import com.cisdi.data.sdk.procotol.message.HttpReturnMessage;
|
||||||
|
import com.cisdi.data.sdk.service.RouteService;
|
||||||
|
import com.cisdi.data.sdk.vo.DeviceVo;
|
||||||
|
import com.cisdi.data.sdk.vo.ExeResultVo;
|
||||||
|
import com.cisdi.data.DHV.gateway.impl.dhv.YFDHVPullTask;
|
||||||
|
import com.cisdi.data.DHV.gateway.vo.PullHttpTaskStartVo;
|
||||||
|
import com.cisdi.data.DHV.gateway.vo.dhv.MPSVO;
|
||||||
|
import com.cisdi.data.DHV.gateway.vo.dhv.MPVVO;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author jianghc
|
||||||
|
* @function: YFDHealthVibrationGateway永锋现场-设备健康振动数据接入网关,入口
|
||||||
|
* @date 2022年05月05日 09:29
|
||||||
|
*/
|
||||||
|
public class YFDHealthVibrationGateway extends PulledHttpGatewayBase {
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(YFDHealthVibrationGateway.class);
|
||||||
|
|
||||||
|
//设备id
|
||||||
|
private String deviceId;
|
||||||
|
//设备当前是否运行
|
||||||
|
private AtomicBoolean shouldRun = null;
|
||||||
|
// 允许最小的拉取间隔为1毫秒
|
||||||
|
private static final int Min_Pull_Internal = 1;
|
||||||
|
// 允许最小的超时时间间隔,为1000毫秒
|
||||||
|
private static final int Min_Timeout = 1000;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExeResultVo sendReturnMessage(HttpReturnMessage httpReturnMessage) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
if (state == GatewayState.RUNNING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
startInternal();
|
||||||
|
state = GatewayState.RUNNING;
|
||||||
|
logger.info("永峰设备健康振动数据http拉取网关:{}启动成功", instanceVo.getRunId());
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("永峰设备健康振动数据http拉取网关:{}启动失败", instanceVo.getRunId());
|
||||||
|
logger.error(e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startInternal() {
|
||||||
|
httpParam = JSON.parseObject(instanceVo.getParameter(), PullHttpParam.class);
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(httpParam.getPullLocation())) {
|
||||||
|
throw new BusinessException("未正确配置拉取地址。");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (httpParam.getPullInternal() == null) {
|
||||||
|
throw new BusinessException("未正确配置拉取间隔");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (httpParam.getTimeout() == null) {
|
||||||
|
throw new BusinessException("未正确配置拉取超时时间");
|
||||||
|
}
|
||||||
|
|
||||||
|
httpParam.setPullInternal(httpParam.getPullInternal() < Min_Pull_Internal ?
|
||||||
|
Min_Pull_Internal : httpParam.getPullInternal());
|
||||||
|
|
||||||
|
httpParam.setTimeout(httpParam.getTimeout() < Min_Timeout ? Min_Timeout : httpParam.getTimeout());
|
||||||
|
|
||||||
|
RouteService routeService = (RouteService) serviceProvider.getByName(ServiceName.Route);
|
||||||
|
List<DeviceVo> deviceVos = routeService.findByRunId(instanceVo.getRunId());
|
||||||
|
|
||||||
|
if (deviceVos.size() > 1) {
|
||||||
|
throw new BusinessException("网关Id:" + instanceVo.getRunId() + "为永峰设备健康振动数据http拉取网关,只允许关联一个设备Id");
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceId = deviceVos.size() > 0 ? deviceVos.get(0).getDeviceId() : null;
|
||||||
|
|
||||||
|
logger.info("永峰设备健康振动数据http拉取网关:{}读取启动配置参数:{}", getInstanceVo().getRunId(), httpParam);
|
||||||
|
|
||||||
|
closePrevState();
|
||||||
|
shouldRun = new AtomicBoolean(true);
|
||||||
|
|
||||||
|
// DynamicCodecService dynamicCodecService = (DynamicCodecService) serviceProvider.getByName(ServiceName.DynamicCodec);
|
||||||
|
// if (dynamicCodecService == null || !(dynamicCodecService instanceof DynamicCodecService)) {
|
||||||
|
// throw new BusinessException("获取JDynamicCodecService失败");
|
||||||
|
// }
|
||||||
|
// String tagConfig = dynamicCodecService.findByRunIdAndMsgKeyNoCache(getInstanceVo().getRunId(),"mps.MPS");
|
||||||
|
// if (Strings.isEmpty(tagConfig)) {
|
||||||
|
// throw new BusinessException("未正确配置当前DHV所需配置");
|
||||||
|
// }else{
|
||||||
|
// logger.info("点位配置信息:"+tagConfig);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// 启动线程
|
||||||
|
PullHttpTaskStartVo startVo = new PullHttpTaskStartVo();
|
||||||
|
startVo.setDeviceId(deviceId);
|
||||||
|
startVo.setGatewayBase(this);
|
||||||
|
startVo.setServiceProvider(serviceProvider);
|
||||||
|
startVo.setHttpParam(httpParam);
|
||||||
|
startVo.setShouldRun(shouldRun);
|
||||||
|
|
||||||
|
//其他参数
|
||||||
|
OtherParamVO otherParamVO = null;
|
||||||
|
if (httpParam.getOtherParameter() != null && httpParam.getOtherParameter().trim().length() > 0) {
|
||||||
|
String otherParameter = httpParam.getOtherParameter();
|
||||||
|
otherParamVO = parseOtherParameter(otherParameter);
|
||||||
|
} else {
|
||||||
|
throw new BusinessException("永峰设备健康振动数据Http网关其他参数配置异常!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 启动拉取ids的线程
|
||||||
|
YFDHVPullTask idsTask = new YFDHVPullTask(startVo, otherParamVO);
|
||||||
|
Thread idsThread = new Thread(idsTask, "永峰-设备健康振动数据网关");
|
||||||
|
idsThread.start();
|
||||||
|
|
||||||
|
state = GatewayState.RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param otherParameter
|
||||||
|
* @return com.cisdi.data.yongfeng.gateway.vo.dhv.OtherParamVO
|
||||||
|
* @function: 解析其他参数
|
||||||
|
* @author jianghc
|
||||||
|
* @date 2022/5/6 16:41
|
||||||
|
*/
|
||||||
|
private OtherParamVO parseOtherParameter(String otherParameter) {
|
||||||
|
MPSVO mpsvo = new MPSVO();
|
||||||
|
List<MPVVO> mpvvoList = new ArrayList<>();
|
||||||
|
JSONObject jsonObject = null;
|
||||||
|
try {
|
||||||
|
jsonObject = JSONObject.parseObject(otherParameter);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new BusinessException("永峰设备健康振动数据Http网关其他参数配置异常!");
|
||||||
|
}
|
||||||
|
Object obj = jsonObject.get("mps");
|
||||||
|
if (obj != null && obj instanceof JSONObject) {
|
||||||
|
JSONObject databaseName = (JSONObject) obj;
|
||||||
|
Object dbNames = databaseName.get("databaseName");
|
||||||
|
if (dbNames instanceof JSONArray) {
|
||||||
|
JSONArray jsonArray = (JSONArray) dbNames;
|
||||||
|
List<String> dbNameList = new ArrayList<>();
|
||||||
|
for (int i = 0; i < jsonArray.size(); i++) {
|
||||||
|
dbNameList.add((String) jsonArray.get(i));
|
||||||
|
}
|
||||||
|
mpsvo.setDatabaseName(dbNameList);
|
||||||
|
} else if (dbNames instanceof String) {
|
||||||
|
List<String> dbNameList = new ArrayList<>();
|
||||||
|
dbNameList.add((String) dbNames);
|
||||||
|
mpsvo.setDatabaseName(dbNameList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Object obj1 = jsonObject.get("mpv");
|
||||||
|
if (obj1 != null && obj1 instanceof JSONArray) {
|
||||||
|
JSONArray jsonArray = (JSONArray) obj1;
|
||||||
|
for (int i = 0; i < jsonArray.size(); i++) {
|
||||||
|
JSONObject obj2 = (JSONObject) jsonArray.get(i);
|
||||||
|
MPVVO mpvvo = new MPVVO();
|
||||||
|
String databaseName = obj2.getString("databaseName");
|
||||||
|
if (databaseName != null && databaseName.trim().length() > 0) {
|
||||||
|
mpvvo.setDatabaseName(databaseName);
|
||||||
|
} else {
|
||||||
|
mpvvo.setDatabaseName(null);
|
||||||
|
}
|
||||||
|
String measuringPointNumberOrTechID = obj2.getString("measuringPointNumberOrTechID");
|
||||||
|
if (measuringPointNumberOrTechID != null && measuringPointNumberOrTechID.trim().length() > 0) {
|
||||||
|
mpvvo.setMeasuringPointNumberOrTechID(measuringPointNumberOrTechID);
|
||||||
|
} else {
|
||||||
|
if (databaseName != null && databaseName.trim().length() > 0) {
|
||||||
|
throw new BusinessException("永峰设备健康振动数据Http网关其他参数配置异常!");
|
||||||
|
}
|
||||||
|
mpvvo.setMeasuringPointNumberOrTechID(null);
|
||||||
|
}
|
||||||
|
String assignmentTechIDorName = obj2.getString("assignmentTechIDorName");
|
||||||
|
if (assignmentTechIDorName != null && assignmentTechIDorName.trim().length() > 0) {
|
||||||
|
mpvvo.setAssignmentTechIDorName(assignmentTechIDorName);
|
||||||
|
} else {
|
||||||
|
if (databaseName != null && databaseName.trim().length() > 0) {
|
||||||
|
throw new BusinessException("永峰设备健康振动数据Http网关其他参数配置异常!");
|
||||||
|
}
|
||||||
|
mpvvo.setAssignmentTechIDorName(null);
|
||||||
|
}
|
||||||
|
Boolean ShortMem = obj2.getBoolean("ShortMem");
|
||||||
|
if (ShortMem != null && ShortMem.equals(Boolean.TRUE)) {
|
||||||
|
mpvvo.setShortMem(Boolean.TRUE);
|
||||||
|
} else if (ShortMem != null && ShortMem.equals(Boolean.FALSE)) {
|
||||||
|
mpvvo.setShortMem(Boolean.FALSE);
|
||||||
|
} else {
|
||||||
|
mpvvo.setShortMem(null);
|
||||||
|
}
|
||||||
|
mpvvo.setMaxCount(obj2.getInteger("MaxCount"));
|
||||||
|
Boolean LongMem = obj2.getBoolean("LongMem");
|
||||||
|
if (LongMem != null && LongMem.equals(Boolean.TRUE)) {
|
||||||
|
mpvvo.setLongMem(Boolean.TRUE);
|
||||||
|
} else if (LongMem != null && LongMem.equals(Boolean.FALSE)) {
|
||||||
|
mpvvo.setLongMem(Boolean.FALSE);
|
||||||
|
} else {
|
||||||
|
mpvvo.setLongMem(null);
|
||||||
|
}
|
||||||
|
String StartDateTime = obj2.getString("StartDateTime");
|
||||||
|
if (StartDateTime != null && StartDateTime.trim().length() > 0) {
|
||||||
|
mpvvo.setStartDateTime(StartDateTime);
|
||||||
|
} else {
|
||||||
|
mpvvo.setStartDateTime(null);
|
||||||
|
}
|
||||||
|
String StopDateTime = obj2.getString("StopDateTime");
|
||||||
|
if (StopDateTime != null && StopDateTime.trim().length() > 0) {
|
||||||
|
mpvvo.setStopDateTime(StopDateTime);
|
||||||
|
} else {
|
||||||
|
mpvvo.setStopDateTime(null);
|
||||||
|
}
|
||||||
|
mpvvo.setMpktTech(obj2.getInteger("MpktTech"));
|
||||||
|
String Expand = obj2.getString("Expand");
|
||||||
|
if (Expand != null && Expand.trim().length() > 0) {
|
||||||
|
mpvvo.setExpand(Expand);
|
||||||
|
} else {
|
||||||
|
mpvvo.setExpand(null);
|
||||||
|
}
|
||||||
|
mpvvoList.add(mpvvo);
|
||||||
|
}
|
||||||
|
} else if (obj1 != null && obj1 instanceof JSONObject) {
|
||||||
|
JSONObject obj2 = (JSONObject) obj1;
|
||||||
|
MPVVO mpvvo = new MPVVO();
|
||||||
|
String databaseName = obj2.getString("databaseName");
|
||||||
|
if (databaseName != null && databaseName.trim().length() > 0) {
|
||||||
|
mpvvo.setDatabaseName(databaseName);
|
||||||
|
} else {
|
||||||
|
mpvvo.setDatabaseName(null);
|
||||||
|
}
|
||||||
|
String measuringPointNumberOrTechID = obj2.getString("measuringPointNumberOrTechID");
|
||||||
|
if (measuringPointNumberOrTechID != null && measuringPointNumberOrTechID.trim().length() > 0) {
|
||||||
|
mpvvo.setMeasuringPointNumberOrTechID(measuringPointNumberOrTechID);
|
||||||
|
} else {
|
||||||
|
if (databaseName != null && databaseName.trim().length() > 0) {
|
||||||
|
throw new BusinessException("永峰设备健康振动数据Http网关其他参数配置异常!");
|
||||||
|
}
|
||||||
|
mpvvo.setMeasuringPointNumberOrTechID(null);
|
||||||
|
}
|
||||||
|
String assignmentTechIDorName = obj2.getString("assignmentTechIDorName");
|
||||||
|
if (assignmentTechIDorName != null && assignmentTechIDorName.trim().length() > 0) {
|
||||||
|
mpvvo.setAssignmentTechIDorName(assignmentTechIDorName);
|
||||||
|
} else {
|
||||||
|
if (databaseName != null && databaseName.trim().length() > 0) {
|
||||||
|
throw new BusinessException("永峰设备健康振动数据Http网关其他参数配置异常!");
|
||||||
|
}
|
||||||
|
mpvvo.setAssignmentTechIDorName(null);
|
||||||
|
}
|
||||||
|
Boolean ShortMem = obj2.getBoolean("ShortMem");
|
||||||
|
if (ShortMem != null && ShortMem.equals(Boolean.TRUE)) {
|
||||||
|
mpvvo.setShortMem(Boolean.TRUE);
|
||||||
|
} else if (ShortMem != null && ShortMem.equals(Boolean.FALSE)) {
|
||||||
|
mpvvo.setShortMem(Boolean.FALSE);
|
||||||
|
} else {
|
||||||
|
mpvvo.setShortMem(null);
|
||||||
|
}
|
||||||
|
mpvvo.setMaxCount(obj2.getInteger("MaxCount"));
|
||||||
|
Boolean LongMem = obj2.getBoolean("LongMem");
|
||||||
|
if (LongMem != null && LongMem.equals(Boolean.TRUE)) {
|
||||||
|
mpvvo.setLongMem(Boolean.TRUE);
|
||||||
|
} else if (LongMem != null && LongMem.equals(Boolean.FALSE)) {
|
||||||
|
mpvvo.setLongMem(Boolean.FALSE);
|
||||||
|
} else {
|
||||||
|
mpvvo.setLongMem(null);
|
||||||
|
}
|
||||||
|
String StartDateTime = obj2.getString("StartDateTime");
|
||||||
|
if (StartDateTime != null && StartDateTime.trim().length() > 0) {
|
||||||
|
mpvvo.setStartDateTime(StartDateTime);
|
||||||
|
} else {
|
||||||
|
mpvvo.setStartDateTime(null);
|
||||||
|
}
|
||||||
|
String StopDateTime = obj2.getString("StopDateTime");
|
||||||
|
if (StopDateTime != null && StopDateTime.trim().length() > 0) {
|
||||||
|
mpvvo.setStopDateTime(StopDateTime);
|
||||||
|
} else {
|
||||||
|
mpvvo.setStopDateTime(null);
|
||||||
|
}
|
||||||
|
mpvvo.setMpktTech(obj2.getInteger("MpktTech"));
|
||||||
|
String Expand = obj2.getString("Expand");
|
||||||
|
if (Expand != null && Expand.trim().length() > 0) {
|
||||||
|
mpvvo.setExpand(Expand);
|
||||||
|
} else {
|
||||||
|
mpvvo.setExpand(null);
|
||||||
|
}
|
||||||
|
mpvvoList.add(mpvvo);
|
||||||
|
}
|
||||||
|
if ((mpsvo.getDatabaseName() == null || mpsvo.getDatabaseName().size() < 1) && (mpvvoList.size() < 1)) {
|
||||||
|
throw new BusinessException("永峰设备健康振动数据Http网关其他参数配置异常!");
|
||||||
|
}
|
||||||
|
String user = jsonObject.getString("user");
|
||||||
|
String pass = jsonObject.getString("pass");
|
||||||
|
String Authorization = null;
|
||||||
|
if (user != null) {
|
||||||
|
Authorization = "Basic " + new String(Base64.getEncoder().encode((user + ":" + pass).getBytes(StandardCharsets.UTF_8)));
|
||||||
|
} else {
|
||||||
|
Authorization = "Basic ";
|
||||||
|
}
|
||||||
|
String emptyanddefault = jsonObject.getString("emptyanddefault");
|
||||||
|
OtherParamVO otherParamVO = new OtherParamVO();
|
||||||
|
otherParamVO.setMpsvo(mpsvo);
|
||||||
|
otherParamVO.setMpvvoList(mpvvoList);
|
||||||
|
otherParamVO.setAuthorization(Authorization);
|
||||||
|
otherParamVO.setEmptyanddefault(emptyanddefault);
|
||||||
|
return otherParamVO;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
if (state == GatewayState.CLOSED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
closePrevState();
|
||||||
|
|
||||||
|
logger.info("永峰设备健康振动数据http拉取网关:{}关闭中", getInstanceVo().getRunId());
|
||||||
|
|
||||||
|
state = GatewayState.CLOSED;
|
||||||
|
|
||||||
|
logger.info("永峰设备健康振动数据http拉取网关:{}关闭成功", getInstanceVo().getRunId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void closePrevState() {
|
||||||
|
if (shouldRun != null) {
|
||||||
|
shouldRun.set(false);
|
||||||
|
shouldRun = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getActiveDeviceIds() {
|
||||||
|
Set<String> set = new HashSet<String>();
|
||||||
|
if (deviceId != null) {
|
||||||
|
set.add(deviceId);
|
||||||
|
}
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
1523
src/main/java/com/cisdi/data/DHV/doc/readme.md
Normal file
1523
src/main/java/com/cisdi/data/DHV/doc/readme.md
Normal file
File diff suppressed because it is too large
Load Diff
BIN
src/main/java/com/cisdi/data/DHV/doc/现场点位数据信息.xlsx
Normal file
BIN
src/main/java/com/cisdi/data/DHV/doc/现场点位数据信息.xlsx
Normal file
Binary file not shown.
BIN
src/main/java/com/cisdi/data/DHV/doc/设备健康振动协议使用说明.docx
Normal file
BIN
src/main/java/com/cisdi/data/DHV/doc/设备健康振动协议使用说明.docx
Normal file
Binary file not shown.
@ -0,0 +1,42 @@
|
|||||||
|
package com.cisdi.data.DHV.gateway.config;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import okhttp3.ConnectionPool;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author jianghc
|
||||||
|
* @function:
|
||||||
|
* @date 2022年05月07日 10:26
|
||||||
|
*/
|
||||||
|
public class YFHttpClient {
|
||||||
|
|
||||||
|
private static Map<Integer, OkHttpClient> map = Maps.newConcurrentMap();
|
||||||
|
|
||||||
|
|
||||||
|
public static OkHttpClient get(Integer timeout) {
|
||||||
|
|
||||||
|
OkHttpClient okHttpClient = map.get(timeout);
|
||||||
|
|
||||||
|
if(okHttpClient != null) {
|
||||||
|
return okHttpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
OkHttpClient.Builder builder = new OkHttpClient.Builder();
|
||||||
|
builder.connectTimeout(timeout, TimeUnit.MILLISECONDS)
|
||||||
|
.readTimeout(timeout, TimeUnit.MILLISECONDS)
|
||||||
|
.writeTimeout(timeout,TimeUnit.MILLISECONDS)
|
||||||
|
.connectionPool(new ConnectionPool(15, 1, TimeUnit.MINUTES))
|
||||||
|
.retryOnConnectionFailure(true);
|
||||||
|
|
||||||
|
okHttpClient = builder.build();
|
||||||
|
|
||||||
|
map.put(timeout, okHttpClient);
|
||||||
|
|
||||||
|
return okHttpClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.cisdi.data.DHV.gateway.impl;
|
||||||
|
|
||||||
|
import com.cisdi.data.DHV.gateway.vo.dhv.OtherParamVO;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import com.cisdi.data.DHV.gateway.vo.PullHttpTaskStartVo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author jianghc
|
||||||
|
* @function:
|
||||||
|
* @date 2022年05月05日 09:37
|
||||||
|
*/
|
||||||
|
public class HttpPullTaskBase {
|
||||||
|
/**
|
||||||
|
* 线程启动参数
|
||||||
|
*/
|
||||||
|
protected PullHttpTaskStartVo startVo = null;
|
||||||
|
|
||||||
|
protected void checkInitParam(PullHttpTaskStartVo taskStartVo, OtherParamVO otherParamVO) {
|
||||||
|
if(taskStartVo.getShouldRun() == null
|
||||||
|
|| taskStartVo.getShouldRun() == null
|
||||||
|
|| taskStartVo.getHttpParam() == null) {
|
||||||
|
throw new BusinessException("永峰设备健康振动数据Http拉取线程启动参数缺失。");
|
||||||
|
}
|
||||||
|
this.startVo = taskStartVo;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,575 @@
|
|||||||
|
package com.cisdi.data.DHV.gateway.impl.dhv;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONArray;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.cisdi.data.DHV.gateway.config.YFHttpClient;
|
||||||
|
import com.cisdi.data.DHV.gateway.impl.HttpPullTaskBase;
|
||||||
|
import com.cisdi.data.DHV.gateway.vo.PullHttpTaskStartVo;
|
||||||
|
import com.cisdi.data.DHV.gateway.vo.dhv.*;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
|
||||||
|
import com.cisdi.data.sdk.consts.ServiceName;
|
||||||
|
import com.cisdi.data.sdk.gateway.base.PulledHttpGatewayBase;
|
||||||
|
import com.cisdi.data.sdk.gateway.message.HttpMessage;
|
||||||
|
import com.cisdi.data.sdk.gateway.message.Message;
|
||||||
|
import com.cisdi.data.sdk.gateway.message.MessageBatch;
|
||||||
|
import com.cisdi.data.sdk.service.SendService;
|
||||||
|
import com.cisdi.data.sdk.service.ServiceProvider;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Response;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author jianghc
|
||||||
|
* @function:
|
||||||
|
* @date 2022年05月05日 10:32
|
||||||
|
*/
|
||||||
|
public class YFDHVPullTask extends HttpPullTaskBase implements Runnable {
|
||||||
|
|
||||||
|
private Logger logger = LoggerFactory.getLogger(YFDHVPullTask.class);
|
||||||
|
|
||||||
|
//请求测点状态的URL地址
|
||||||
|
private String[] DHV_MPS_URL = null;
|
||||||
|
|
||||||
|
//获取teachName的URL地址
|
||||||
|
private String[] DHV_MET_URL = null;
|
||||||
|
|
||||||
|
//请求测点总值的URL地址
|
||||||
|
private String[] DHV_MPV_URL = null;
|
||||||
|
|
||||||
|
//测点的ID
|
||||||
|
private String[] measuringPointNumberOrTechIDs = null;
|
||||||
|
|
||||||
|
//base64编码的user:password
|
||||||
|
private String Authorization;
|
||||||
|
|
||||||
|
//DHV请求必须携带的头部参数
|
||||||
|
private String emptyanddefault;
|
||||||
|
|
||||||
|
//超时时间
|
||||||
|
private Integer timeOut;
|
||||||
|
|
||||||
|
//其他参数中配置的数据库
|
||||||
|
private List<String> dbNames;
|
||||||
|
|
||||||
|
//判断当前是否获取了db-测点id-测点方法的一个标志,在网关启动的时候执行一次后变成true,并装入下面三个容器中
|
||||||
|
private boolean metPara = false;
|
||||||
|
private List<String> dbNameList;
|
||||||
|
private List<String> itemIdList;
|
||||||
|
private List<String> methodNameList;
|
||||||
|
|
||||||
|
//连接管理中的拉取地址,以上所有的URL地址都是用这个地址为前缀拼接成的
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
public YFDHVPullTask(PullHttpTaskStartVo pullHttpTaskStartVo, OtherParamVO otherParamVO) {
|
||||||
|
checkInitParam(pullHttpTaskStartVo, otherParamVO);
|
||||||
|
|
||||||
|
url = startVo.getHttpParam().getPullLocation();
|
||||||
|
if (url == null) {
|
||||||
|
logger.error("拉取地址不能为空!");
|
||||||
|
throw new BusinessException("拉取地址不能为空!");
|
||||||
|
}
|
||||||
|
if (url.endsWith("/")) {
|
||||||
|
url = url.substring(0, url.length() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbNames = otherParamVO.getMpsvo().getDatabaseName();
|
||||||
|
int dbNamesLen = dbNames.size();
|
||||||
|
if (dbNamesLen > 0) {
|
||||||
|
DHV_MPS_URL = new String[dbNamesLen];
|
||||||
|
for (int i = 0; i < dbNamesLen; i++) {
|
||||||
|
DHV_MPS_URL[i] = url + String.format(YFDHV.YF_DHV_MPS, dbNames.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Authorization = otherParamVO.getAuthorization();
|
||||||
|
|
||||||
|
emptyanddefault = otherParamVO.getEmptyanddefault() == null ? "1" : otherParamVO.getEmptyanddefault();
|
||||||
|
|
||||||
|
timeOut = startVo.getHttpParam().getTimeout();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
OkHttpClient httpClient = YFHttpClient.get(startVo.getHttpParam().getPullInternal());
|
||||||
|
if (DHV_MPS_URL != null) {
|
||||||
|
for (int i = 0; i < DHV_MPS_URL.length; i++) {
|
||||||
|
logger.info("MPS采集地址:" + DHV_MPS_URL[i]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.info("您尚未配置采集地址");
|
||||||
|
}
|
||||||
|
|
||||||
|
//在这个驱动中,我们只请求如下时间范围的数据,从当前时间往前数半个小时(第一次请求这样)
|
||||||
|
//以后每个半个小时请求一次,每次的请求时间范围是,上一次的请求时间到当前时间点,通常会比半个小时多一点点,
|
||||||
|
//多出来的时间是上一次请求的耗时时间
|
||||||
|
LocalDateTime endTime = null;
|
||||||
|
LocalDateTime startTime = null;
|
||||||
|
while (startVo.getShouldRun().get() == true) {
|
||||||
|
logger.info("即将采集设备数据......");
|
||||||
|
LocalDateTime end_time_temp = null;
|
||||||
|
if (endTime != null) {
|
||||||
|
end_time_temp = endTime;
|
||||||
|
}
|
||||||
|
endTime = LocalDateTime.now();
|
||||||
|
if (startTime == null) {
|
||||||
|
startTime = endTime.minusMinutes(30);
|
||||||
|
} else {
|
||||||
|
startTime = end_time_temp;
|
||||||
|
}
|
||||||
|
Map<String, String> mpsJsonStringMap = MPSRequest(httpClient);
|
||||||
|
if (DHV_MET_URL == null) {
|
||||||
|
Construct_DHV_MET_URL();
|
||||||
|
}
|
||||||
|
if (DHV_MPV_URL == null) {
|
||||||
|
METRequest(httpClient);
|
||||||
|
}
|
||||||
|
Map<String, JSONObject> mpvJsonArrayMap = MPVRequest(httpClient, startTime, endTime);
|
||||||
|
if (mpsJsonStringMap != null && mpsJsonStringMap.size() > 0) {
|
||||||
|
for (int i = 0; i < mpsJsonStringMap.size(); i++) {
|
||||||
|
String msgKey = dbNames.get(i) + YFDHV.YF_Separator + YFDHV.YF_MPS;
|
||||||
|
sendToNextMQ(mpsJsonStringMap.get(dbNames.get(i)), msgKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mpvJsonArrayMap != null && mpvJsonArrayMap.size() > 0) {
|
||||||
|
List<String> dbNameList = new ArrayList<>(mpvJsonArrayMap.keySet());
|
||||||
|
for (int i = 0; i < dbNameList.size(); i++) {
|
||||||
|
String dbName = dbNameList.get(i);
|
||||||
|
sendToNextMQ(mpvJsonArrayMap.get(dbName).toJSONString(), dbName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Thread.sleep(startVo.getHttpParam().getPullInternal());
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
logger.error("休眠异常");
|
||||||
|
throw new BusinessException("休眠异常");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param httpClient
|
||||||
|
* @return java.lang.String
|
||||||
|
* @function: 终极奥义之通过DHV_MPS_URL地址获取测点状态信息
|
||||||
|
* @author jianghc
|
||||||
|
* @date 2022/5/24 16:16
|
||||||
|
*/
|
||||||
|
private Map<String, String> MPSRequest(OkHttpClient httpClient) {
|
||||||
|
if (!metPara) {
|
||||||
|
dbNameList = new ArrayList<>();
|
||||||
|
itemIdList = new ArrayList<>();
|
||||||
|
}
|
||||||
|
if (DHV_MPS_URL == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Map<String, String> mpsJsonMap = new HashMap<>();
|
||||||
|
int DHV_MPS_URL_Len = DHV_MPS_URL.length;
|
||||||
|
|
||||||
|
for (int i = 0; i < DHV_MPS_URL_Len; i++) {
|
||||||
|
okhttp3.Request request = new okhttp3.Request.Builder()
|
||||||
|
.header("Authorization", Authorization)
|
||||||
|
.header("emptyanddefault", emptyanddefault)
|
||||||
|
.url(DHV_MPS_URL[i])
|
||||||
|
.get()
|
||||||
|
.build();
|
||||||
|
Response response = null;
|
||||||
|
try {
|
||||||
|
Long currentTime_start = System.currentTimeMillis();
|
||||||
|
Long currentTime_end = 0l;
|
||||||
|
response = httpClient.newCall(request).execute();
|
||||||
|
currentTime_end = System.currentTimeMillis();
|
||||||
|
if (currentTime_end - currentTime_start > timeOut) {
|
||||||
|
logger.error("地址:" + DHV_MPS_URL[i] + "请求超时!");
|
||||||
|
throw new BusinessException("地址:" + DHV_MPS_URL[i] + "请求超时!");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("被请求的接口:" + DHV_MPS_URL[i] + "请求超时," + e.getMessage());
|
||||||
|
throw new BusinessException("被请求的接口:" + DHV_MPS_URL[i] + "请求超时," + e.getMessage());
|
||||||
|
}
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
String jsonString = null;
|
||||||
|
try {
|
||||||
|
jsonString = new String(response.body().bytes(), StandardCharsets.UTF_8);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.error("MPS响应数据解析异常");
|
||||||
|
throw new BusinessException("MPS响应数据解析异常");
|
||||||
|
}
|
||||||
|
Object jsonArrayObject = ((JSONObject) JSONObject.parse(jsonString)).get("values");
|
||||||
|
JSONObject resJson = new JSONObject();
|
||||||
|
if (jsonArrayObject instanceof JSONArray) {
|
||||||
|
JSONArray jsonArray = (JSONArray) jsonArrayObject;
|
||||||
|
for (int j = 0; j < jsonArray.size(); j++) {
|
||||||
|
JSONObject jsonObject = (JSONObject) jsonArray.get(j);
|
||||||
|
MPSItem[] mpsItems = MPSItem.values();
|
||||||
|
MPSItem primary = MPSItem.getPrimary();
|
||||||
|
Object primaryValue = jsonObject.get(primary.toString());
|
||||||
|
|
||||||
|
String mp = jsonObject.getString(MPSItem.getPrimary().getMpsItem());
|
||||||
|
if (!AllowMeasuringPoint.allowMeasuringPoint(mp)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (MPSItem mpsItem : mpsItems) {
|
||||||
|
String key = dbNames.get(i) + YFDHV.YF_Separator + primaryValue + YFDHV.YF_Separator + mpsItem.getMpsItem();
|
||||||
|
Object value = jsonObject.get(mpsItem.toString());
|
||||||
|
resJson.fluentPut(key, value);
|
||||||
|
}
|
||||||
|
resJson.fluentPut(dbNames.get(i) + YFDHV.YF_Separator + primaryValue + YFDHV.YF_Separator + YFDHV.DateTime
|
||||||
|
, LocalDateTime.now());//注意测点状态时间是系统生成的,没有从接口中获取到
|
||||||
|
if (!metPara) {
|
||||||
|
String mpx = jsonObject.getString(MPSItem.getPrimary().getMpsItem());
|
||||||
|
if (!AllowMeasuringPoint.allowMeasuringPoint(mpx)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dbNameList.add(dbNames.get(i));
|
||||||
|
itemIdList.add(mpx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.warn("地址:" + DHV_MPS_URL[i] + " 未采集到数据!");
|
||||||
|
}
|
||||||
|
if (resJson.size() > 0) {
|
||||||
|
mpsJsonMap.put(dbNames.get(i), resJson.toJSONString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!metPara) {
|
||||||
|
StringBuilder stringBuffer = new StringBuilder("\n");
|
||||||
|
stringBuffer.append("测点状态采集点信息:\n");
|
||||||
|
stringBuffer.append("=======================================================================================\n");
|
||||||
|
for (int i = 0; i < dbNameList.size(); i++) {
|
||||||
|
stringBuffer.append("数据库:" + dbNameList.get(i) + " 测点状态id:" + itemIdList.get(i) + "\n");
|
||||||
|
}
|
||||||
|
stringBuffer.append("=======================================================================================\n");
|
||||||
|
logger.info(stringBuffer.toString());
|
||||||
|
metPara = true;
|
||||||
|
}
|
||||||
|
if (mpsJsonMap.size() > 0) {
|
||||||
|
return mpsJsonMap;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function: 构造DHV_MET_URL的请求地址
|
||||||
|
* @author jianghc
|
||||||
|
* @date 2022/5/24 16:12
|
||||||
|
*/
|
||||||
|
private void Construct_DHV_MET_URL() {
|
||||||
|
if (itemIdList == null || itemIdList.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int itemIdList_len = itemIdList.size();
|
||||||
|
DHV_MET_URL = new String[itemIdList_len];
|
||||||
|
for (int i = 0; i < itemIdList.size(); i++) {
|
||||||
|
String measuringPointNumberOrTechID = itemIdList.get(i);
|
||||||
|
if (measuringPointNumberOrTechID.contains("#")) {
|
||||||
|
measuringPointNumberOrTechID = measuringPointNumberOrTechID.replace("#", "%23");
|
||||||
|
}
|
||||||
|
DHV_MET_URL[i] = url + String.format(YFDHV.YF_DHV_METH, dbNameList.get(i), measuringPointNumberOrTechID);
|
||||||
|
}
|
||||||
|
StringBuilder stringBuffer = new StringBuilder("\n");
|
||||||
|
stringBuffer.append("获取测点总值需要的方法请求路径包含:\n");
|
||||||
|
stringBuffer.append("=======================================================================================\n");
|
||||||
|
for (int i = 0; i < DHV_MET_URL.length; i++) {
|
||||||
|
stringBuffer.append(DHV_MET_URL[i] + "\n");
|
||||||
|
}
|
||||||
|
stringBuffer.append("=======================================================================================\n");
|
||||||
|
logger.info(stringBuffer.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param httpClient
|
||||||
|
* @function: 主要要来获取dbNameList,itemIdList,methodNameList
|
||||||
|
* @author jianghc
|
||||||
|
* @date 2022/5/24 16:12
|
||||||
|
*/
|
||||||
|
private void METRequest(OkHttpClient httpClient) {
|
||||||
|
List<String> dbNameList_temp = new ArrayList<>();
|
||||||
|
List<String> itemIdList_temp = new ArrayList<>();
|
||||||
|
if (DHV_MET_URL == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
methodNameList = new ArrayList<>();
|
||||||
|
int DHV_MET_URL_len = DHV_MET_URL.length;
|
||||||
|
for (int i = 0; i < DHV_MET_URL_len; i++) {
|
||||||
|
okhttp3.Request request = new okhttp3.Request.Builder()
|
||||||
|
.header("Authorization", Authorization)
|
||||||
|
.header("emptyanddefault", emptyanddefault)
|
||||||
|
.url(DHV_MET_URL[i])
|
||||||
|
.get()
|
||||||
|
.build();
|
||||||
|
Response response = null;
|
||||||
|
try {
|
||||||
|
response = httpClient.newCall(request).execute();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new BusinessException("接口:" + DHV_MET_URL[i] + "请求失败!");
|
||||||
|
}
|
||||||
|
if (response != null && response.isSuccessful()) {
|
||||||
|
String jsonString = null;
|
||||||
|
try {
|
||||||
|
jsonString = new String(response.body().bytes(), StandardCharsets.UTF_8);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.error("MPS响应数据解析异常");
|
||||||
|
throw new BusinessException("MPS响应数据解析异常");
|
||||||
|
}
|
||||||
|
JSONObject jsonObject = (JSONObject) JSONObject.parse(jsonString);
|
||||||
|
JSONArray jsonArray = (JSONArray) jsonObject.get("values");
|
||||||
|
if (jsonArray != null && jsonArray.size() > 0) {
|
||||||
|
for (int j = 0; j < jsonArray.size(); j++) {
|
||||||
|
JSONObject jsonObject_val = (JSONObject) jsonArray.get(j);
|
||||||
|
String TechName = jsonObject_val.getString("TechName");
|
||||||
|
if (!AllowMethod.allowMethod(TechName)) {
|
||||||
|
logger.info(TechName + "方法不匹配");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dbNameList_temp.add(dbNameList.get(i));
|
||||||
|
itemIdList_temp.add(itemIdList.get(i));
|
||||||
|
methodNameList.add(TechName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbNameList = null;
|
||||||
|
dbNameList = dbNameList_temp;
|
||||||
|
itemIdList = null;
|
||||||
|
itemIdList = itemIdList_temp;
|
||||||
|
StringBuilder stringBuilder = new StringBuilder("\n");
|
||||||
|
measuringPointNumberOrTechIDs = new String[dbNameList.size()];
|
||||||
|
stringBuilder.append("测点总值需要的参数:\n");
|
||||||
|
stringBuilder.append("=======================================================================================\n");
|
||||||
|
for (int i = 0; i < dbNameList.size(); i++) {
|
||||||
|
measuringPointNumberOrTechIDs[i] = dbNameList.get(i) + YFDHV.YF_Separator + itemIdList.get(i) + YFDHV.YF_Separator + methodNameList.get(i);
|
||||||
|
stringBuilder.append("数据库:" + dbNameList.get(i)
|
||||||
|
+ " 测点总值id:" + itemIdList.get(i)
|
||||||
|
+ " 方法:" + methodNameList.get(i) + "\n");
|
||||||
|
}
|
||||||
|
stringBuilder.append("=======================================================================================\n");
|
||||||
|
logger.info(stringBuilder.toString());
|
||||||
|
Construct_DHV_MPV_URL();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @function: 构造DHV_MPV_URL的请求地址
|
||||||
|
* @author jianghc
|
||||||
|
* @date 2022/5/24 16:14
|
||||||
|
*/
|
||||||
|
private void Construct_DHV_MPV_URL() {
|
||||||
|
if (methodNameList == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int methodNameList_len = methodNameList.size();
|
||||||
|
DHV_MPV_URL = new String[methodNameList_len];
|
||||||
|
for (int i = 0; i < methodNameList_len; i++) {
|
||||||
|
String measuringPointNumberOrTechID = itemIdList.get(i);
|
||||||
|
if (measuringPointNumberOrTechID.contains("#")) {
|
||||||
|
measuringPointNumberOrTechID = measuringPointNumberOrTechID.replace("#", "%23");
|
||||||
|
}
|
||||||
|
DHV_MPV_URL[i] = url + String.format(YFDHV.YF_DHV_MPV, dbNameList.get(i), measuringPointNumberOrTechID, methodNameList.get(i));
|
||||||
|
DHV_MPV_URL[i] += "?ShortMem=true&LongMem=true&Expand=result";
|
||||||
|
}
|
||||||
|
StringBuilder stringBuilder = new StringBuilder("\n");
|
||||||
|
stringBuilder.append("测点总值请求路径(该请求路径不含时间参数 &StartDateTime &StopDateTime ):\n");
|
||||||
|
stringBuilder.append("=======================================================================================\n");
|
||||||
|
for (int i = 0; i < DHV_MPV_URL.length; i++) {
|
||||||
|
stringBuilder.append(DHV_MPV_URL[i] + "\n");
|
||||||
|
}
|
||||||
|
stringBuilder.append("=======================================================================================\n");
|
||||||
|
logger.info(stringBuilder.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param httpClient
|
||||||
|
* @param start
|
||||||
|
* @param end
|
||||||
|
* @return Map<String, JSONArray>
|
||||||
|
* @function: 终极奥义之通过DHV_MPV_URL信息获取测点总值信息
|
||||||
|
* @author jianghc
|
||||||
|
* @date 2022/5/24 16:14
|
||||||
|
*/
|
||||||
|
private Map<String, JSONObject> MPVRequest(OkHttpClient httpClient, LocalDateTime start, LocalDateTime end) {
|
||||||
|
String startTime = start.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
String endTime = end.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
if (DHV_MPV_URL == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int DHV_MPV_URL_Len = DHV_MPV_URL.length;
|
||||||
|
|
||||||
|
Map<String, JSONObject> jsonArrayResObj = new HashMap<>();
|
||||||
|
JSONObject resJson = null;
|
||||||
|
for (int i = 0; i < DHV_MPV_URL_Len; i++) {
|
||||||
|
String msgKey = dbNameList.get(i) + YFDHV.YF_Separator + itemIdList.get(i) + YFDHV.YF_Separator + YFDHV.YF_MPV;
|
||||||
|
resJson = jsonArrayResObj.get(msgKey);
|
||||||
|
if (resJson == null) {
|
||||||
|
resJson = new JSONObject();
|
||||||
|
}
|
||||||
|
okhttp3.Request request = new okhttp3.Request.Builder()
|
||||||
|
.header("Authorization", Authorization)
|
||||||
|
.header("emptyanddefault", emptyanddefault)
|
||||||
|
//.url(DHV_MPV_URL[i] + "&StartDateTime=2020-01-01 00:00:01" + "&StopDateTime=" + endTime)
|
||||||
|
.url(DHV_MPV_URL[i] + "&StartDateTime=" + startTime + "&StopDateTime=" + endTime)
|
||||||
|
.get()
|
||||||
|
.build();
|
||||||
|
Response response = null;
|
||||||
|
try {
|
||||||
|
Long currentTime_start = System.currentTimeMillis();
|
||||||
|
Long currentTime_end = 0l;
|
||||||
|
response = httpClient.newCall(request).execute();
|
||||||
|
currentTime_end = System.currentTimeMillis();
|
||||||
|
if (currentTime_end - currentTime_start > timeOut) {
|
||||||
|
logger.error("地址:" + DHV_MPV_URL[i] + "请求超时!");
|
||||||
|
throw new BusinessException("地址:" + DHV_MPV_URL[i] + "请求超时!");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("地址:" + DHV_MPV_URL[i] + "请求超时!" + e.getMessage());
|
||||||
|
throw new BusinessException("地址:" + DHV_MPV_URL[i] + "请求超时!");
|
||||||
|
}
|
||||||
|
MPVItem[] mpvItems = MPVItem.values();
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
MPVItem primary = MPVItem.getPrimary();
|
||||||
|
String primary_value = measuringPointNumberOrTechIDs[i];
|
||||||
|
String jsonString = null;
|
||||||
|
try {
|
||||||
|
jsonString = new String(response.body().bytes(), StandardCharsets.UTF_8);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.error("MPV响应数据解析异常");
|
||||||
|
throw new BusinessException("MPV响应数据解析异常");
|
||||||
|
}
|
||||||
|
Object jsonObject_temp = JSONObject.parse(jsonString);
|
||||||
|
if (jsonObject_temp instanceof JSONObject) {
|
||||||
|
JSONObject jsonObject = (JSONObject) jsonObject_temp;
|
||||||
|
Object jsonArrayObject = jsonObject.get("values");
|
||||||
|
if (jsonArrayObject != null && jsonArrayObject instanceof JSONArray) {
|
||||||
|
JSONArray jsonArray = (JSONArray) jsonArrayObject;
|
||||||
|
|
||||||
|
for (int j = 0; j < jsonArray.size(); j++) {
|
||||||
|
Object obj = jsonArray.get(j);
|
||||||
|
if (j >= 2) {
|
||||||
|
logger.error("拉取数据过多,请缩短采集时间间隔!");
|
||||||
|
logger.error("多余数据将不被采集:" + ((JSONObject) obj).toJSONString());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (obj != null && obj instanceof JSONObject) {
|
||||||
|
JSONObject jsonObject_value = (JSONObject) obj;
|
||||||
|
Object obj_Result = jsonObject_value.get("Result");
|
||||||
|
if (obj_Result != null && obj_Result instanceof JSONObject) {
|
||||||
|
JSONObject jsonObject_Result = (JSONObject) obj_Result;
|
||||||
|
|
||||||
|
//primary_value=数据库.测点.方法
|
||||||
|
//key-value
|
||||||
|
//key:数据库.测点.方法.属性
|
||||||
|
//value:测点
|
||||||
|
resJson.fluentPut(primary_value + YFDHV.YF_Separator + primary.getMpvItem(),
|
||||||
|
primary_value.split(YFDHV.YF_EscapeCharacter + YFDHV.YF_Separator)[1]);
|
||||||
|
|
||||||
|
|
||||||
|
Object RPM = jsonObject_Result.get("RPM");
|
||||||
|
if (RPM != null && RPM instanceof JSONObject) {
|
||||||
|
JSONObject rpmObj = (JSONObject) RPM;
|
||||||
|
MPVRPMItem[] mpvrpmItems = MPVRPMItem.values();
|
||||||
|
for (MPVRPMItem mpvrpmItem : mpvrpmItems) {
|
||||||
|
String key = primary_value + YFDHV.YF_Separator + mpvrpmItem.getMpvRPMItem();
|
||||||
|
String value = rpmObj.getString(mpvrpmItem.getMpvRPMItem());
|
||||||
|
//key-value
|
||||||
|
//key:数据库.测点.方法.属性
|
||||||
|
//value:属性值
|
||||||
|
resJson.fluentPut(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//String DateTime_key = primary_value + YFDHV.YF_Separator + MPVItem.DateTime.getMpvItem();
|
||||||
|
//String DateTime_value = jsonObject_Result.get(MPVItem.DateTime.toString()).toString();
|
||||||
|
//key-value
|
||||||
|
//key:数据库.测点.方法.属性
|
||||||
|
//value:属性值
|
||||||
|
//resJson.fluentPut(DateTime_key, DateTime_value);
|
||||||
|
|
||||||
|
Object obj_Conditions = jsonObject_Result.get("Conditions");
|
||||||
|
if (obj_Conditions != null && obj_Conditions instanceof JSONObject) {
|
||||||
|
JSONObject jsonObject_Conditions = (JSONObject) obj_Conditions;
|
||||||
|
|
||||||
|
for (MPVItem mpvItem : mpvItems) {
|
||||||
|
String key = primary_value + YFDHV.YF_Separator + mpvItem.getMpvItem();
|
||||||
|
Object value = null;
|
||||||
|
try {
|
||||||
|
value = jsonObject_Conditions.get(mpvItem.toString());
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.error("永峰设备健康振动数据Http网关response解析异常");
|
||||||
|
throw new BusinessException("永峰设备健康振动数据Http网关response解析异常");
|
||||||
|
}
|
||||||
|
if (value != null) {
|
||||||
|
//key-value
|
||||||
|
//key:数据库.测点.方法.属性
|
||||||
|
//value:属性值
|
||||||
|
resJson.fluentPut(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (resJson != null && resJson.size() > 0) {
|
||||||
|
jsonArrayResObj.put(msgKey, resJson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (jsonArrayResObj.size() > 0) {
|
||||||
|
return jsonArrayResObj;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param body
|
||||||
|
* @param msgKey
|
||||||
|
* @function: 将数据发送到平台
|
||||||
|
* @author jianghc
|
||||||
|
* @date 2022/5/24 16:15
|
||||||
|
*/
|
||||||
|
private void sendToNextMQ(Object body, String msgKey) {
|
||||||
|
ServiceProvider serviceProvider = startVo.getServiceProvider();
|
||||||
|
PulledHttpGatewayBase gatewayBase = startVo.getGatewayBase();
|
||||||
|
if (serviceProvider != null && gatewayBase != null && body instanceof String) {
|
||||||
|
SendService service = (SendService) serviceProvider.getByName(ServiceName.Send);
|
||||||
|
Message message = null;
|
||||||
|
HttpMessage httpMessage = gatewayBase.buildHttpMessage();
|
||||||
|
httpMessage.setDeviceId(startVo.getDeviceId());
|
||||||
|
httpMessage.setProviderCode(null);
|
||||||
|
httpMessage.setBody((String) body);
|
||||||
|
httpMessage.setMsgKey(msgKey);
|
||||||
|
message = httpMessage;
|
||||||
|
service.sendMessage(message);
|
||||||
|
} else if (serviceProvider != null && gatewayBase != null && body instanceof JSONArray) {
|
||||||
|
SendService service = (SendService) serviceProvider.getByName(ServiceName.Send);
|
||||||
|
Message message;
|
||||||
|
JSONArray sendBody = (JSONArray) body;
|
||||||
|
List<Message> httpMessages = new ArrayList(sendBody.size());
|
||||||
|
for (Object obj : sendBody) {
|
||||||
|
HttpMessage httpMessage = gatewayBase.buildHttpMessage();
|
||||||
|
httpMessage.setDeviceId(startVo.getDeviceId());
|
||||||
|
httpMessage.setProviderCode(null);
|
||||||
|
httpMessage.setBody(obj.toString());
|
||||||
|
httpMessage.setMsgKey(msgKey);
|
||||||
|
httpMessages.add(httpMessage);
|
||||||
|
}
|
||||||
|
MessageBatch<Message> batch = new MessageBatch<>(httpMessages);
|
||||||
|
message = batch;
|
||||||
|
service.sendMessage(message);
|
||||||
|
} else {
|
||||||
|
logger.info("连接id-{} 拉取采集到值-{}", gatewayBase.getInstanceVo().getRunId(), body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package com.cisdi.data.DHV.gateway.vo;
|
||||||
|
|
||||||
|
import com.cisdi.data.sdk.gateway.base.PulledHttpGatewayBase;
|
||||||
|
import com.cisdi.data.sdk.param.PullHttpParam;
|
||||||
|
import com.cisdi.data.sdk.service.ServiceProvider;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
public class PullHttpTaskStartVo {
|
||||||
|
private AtomicBoolean shouldRun;
|
||||||
|
private ServiceProvider serviceProvider;
|
||||||
|
private String deviceId;
|
||||||
|
private PulledHttpGatewayBase gatewayBase;
|
||||||
|
private PullHttpParam httpParam;
|
||||||
|
|
||||||
|
public AtomicBoolean getShouldRun() {
|
||||||
|
return shouldRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShouldRun(AtomicBoolean shouldRun) {
|
||||||
|
this.shouldRun = shouldRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServiceProvider getServiceProvider() {
|
||||||
|
return serviceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServiceProvider(ServiceProvider serviceProvider) {
|
||||||
|
this.serviceProvider = serviceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceId() {
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceId(String deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PulledHttpGatewayBase getGatewayBase() {
|
||||||
|
return gatewayBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGatewayBase(PulledHttpGatewayBase gatewayBase) {
|
||||||
|
this.gatewayBase = gatewayBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PullHttpParam getHttpParam() {
|
||||||
|
return httpParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHttpParam(PullHttpParam httpParam) {
|
||||||
|
this.httpParam = httpParam;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package com.cisdi.data.DHV.gateway.vo.dhv;
|
||||||
|
|
||||||
|
public enum AllowMeasuringPoint {
|
||||||
|
//1#XB-10V -02,符合规则的测点
|
||||||
|
RegularExpression1("^([\\s]*)([0-9]+)[#]([A-Z]+)([\\s]*)[-]([\\s]*)([0-9]+)([A-Z]+)([\\s]*)([\\s]*)[-]([\\s]*)([0-9]+)([\\s]*)$"),
|
||||||
|
//1#XB-ZG1 -05,符合规则的测点
|
||||||
|
RegularExpression2("^([\\s]*)([0-9]+)[#]([A-Z]+)([\\s]*)[-]([\\s]*)([A-Z]+)([0-9]+)([\\s]*)([\\s]*)[-]([\\s]*)([0-9]+)([\\s]*)$"),
|
||||||
|
//2#XB-1#GF-05,符合规则的测点
|
||||||
|
RegularExpression3("^([\\s]*)([0-9]+)[#]([A-Z]+)([\\s]*)[-]([\\s]*)([0-9]+)[#]([A-Z]+)([\\s]*)([\\s]*)[-]([\\s]*)([0-9]+)([\\s]*)$");
|
||||||
|
|
||||||
|
private String reg;
|
||||||
|
|
||||||
|
AllowMeasuringPoint(String reg) {
|
||||||
|
this.reg = reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getReg() {
|
||||||
|
return this.reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean allowMeasuringPoint(String mp) {
|
||||||
|
if (mp == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
AllowMeasuringPoint[] allowMeasuringPoints = AllowMeasuringPoint.values();
|
||||||
|
for (int i = 0; i < allowMeasuringPoints.length; i++) {
|
||||||
|
if (mp.matches(allowMeasuringPoints[i].getReg())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.cisdi.data.DHV.gateway.vo.dhv;
|
||||||
|
|
||||||
|
|
||||||
|
public enum AllowMethod {
|
||||||
|
// tam1("SPM HD"),
|
||||||
|
// tam2("HD ENV"),
|
||||||
|
// tam3("振动低频"),
|
||||||
|
// tam4("振动高频"),
|
||||||
|
|
||||||
|
am1("冲击脉冲频谱"),
|
||||||
|
am2("振动速度谱"),
|
||||||
|
am3("冲击脉冲"),
|
||||||
|
am4("振动速度"),
|
||||||
|
am5("冲击脉冲谱"),
|
||||||
|
am6("冲激脉冲频谱"),
|
||||||
|
am7("振动速度普");
|
||||||
|
|
||||||
|
private String method;
|
||||||
|
|
||||||
|
AllowMethod(String method) {
|
||||||
|
this.method = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getMethod(){
|
||||||
|
return this.method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean allowMethod(String am) {
|
||||||
|
if (am == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
AllowMethod[] allowMethods=AllowMethod.values();
|
||||||
|
for (int i=0;i<allowMethods.length;i++) {
|
||||||
|
if (am.contains(allowMethods[i].getMethod())){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
23
src/main/java/com/cisdi/data/DHV/gateway/vo/dhv/MPSItem.java
Normal file
23
src/main/java/com/cisdi/data/DHV/gateway/vo/dhv/MPSItem.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package com.cisdi.data.DHV.gateway.vo.dhv;
|
||||||
|
|
||||||
|
public enum MPSItem {
|
||||||
|
Number("Number"),
|
||||||
|
ColorEval("ColorEval");
|
||||||
|
//DateTime("DateTime");注意测点状态时间是系统生成的,没有从接口中获取到
|
||||||
|
|
||||||
|
private String mpsItem;
|
||||||
|
|
||||||
|
MPSItem(String mpsItem) {
|
||||||
|
this.mpsItem=mpsItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMpsItem(){
|
||||||
|
return mpsItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static MPSItem getPrimary() {
|
||||||
|
return Number;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
src/main/java/com/cisdi/data/DHV/gateway/vo/dhv/MPSVO.java
Normal file
26
src/main/java/com/cisdi/data/DHV/gateway/vo/dhv/MPSVO.java
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
package com.cisdi.data.DHV.gateway.vo.dhv;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author jianghc
|
||||||
|
* @function:
|
||||||
|
* @date 2022年05月06日 16:23
|
||||||
|
*/
|
||||||
|
public class MPSVO implements Serializable {
|
||||||
|
|
||||||
|
List<String> databaseName;
|
||||||
|
|
||||||
|
public MPSVO(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getDatabaseName() {
|
||||||
|
return databaseName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDatabaseName(List<String> databaseName) {
|
||||||
|
this.databaseName = databaseName;
|
||||||
|
}
|
||||||
|
}
|
27
src/main/java/com/cisdi/data/DHV/gateway/vo/dhv/MPVItem.java
Normal file
27
src/main/java/com/cisdi/data/DHV/gateway/vo/dhv/MPVItem.java
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package com.cisdi.data.DHV.gateway.vo.dhv;
|
||||||
|
|
||||||
|
public enum MPVItem {
|
||||||
|
measuringPointNumberOrTechID("measuringPointNumberOrTechID"),
|
||||||
|
// DateTime("DateTime"),
|
||||||
|
HDm("HDm"),
|
||||||
|
HDc("HDc");
|
||||||
|
// VEL("VEL"),
|
||||||
|
// DISP("DISP"),
|
||||||
|
// ACC("ACC"),
|
||||||
|
// Peak("Peak"),
|
||||||
|
// PkToPk("PkToPk");
|
||||||
|
|
||||||
|
private String mpvItem;
|
||||||
|
|
||||||
|
MPVItem(String mpvItem) {
|
||||||
|
this.mpvItem = mpvItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMpvItem() {
|
||||||
|
return this.mpvItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MPVItem getPrimary() {
|
||||||
|
return measuringPointNumberOrTechID;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.cisdi.data.DHV.gateway.vo.dhv;
|
||||||
|
|
||||||
|
public enum MPVRPMItem {
|
||||||
|
// RPM1("RPM1"),
|
||||||
|
// RPM2("RPM2"),
|
||||||
|
// Avg("Avg"),
|
||||||
|
// Min("Min"),
|
||||||
|
Max("Max");
|
||||||
|
// Delta("Delta");
|
||||||
|
|
||||||
|
MPVRPMItem(String mpvRPMItem) {
|
||||||
|
this.mpvRPMItem = mpvRPMItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String mpvRPMItem;
|
||||||
|
|
||||||
|
public String getMpvRPMItem() {
|
||||||
|
return this.mpvRPMItem;
|
||||||
|
}
|
||||||
|
}
|
147
src/main/java/com/cisdi/data/DHV/gateway/vo/dhv/MPVVO.java
Normal file
147
src/main/java/com/cisdi/data/DHV/gateway/vo/dhv/MPVVO.java
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
package com.cisdi.data.DHV.gateway.vo.dhv;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author jianghc
|
||||||
|
* @function:
|
||||||
|
* @date 2022年05月06日 16:25
|
||||||
|
*/
|
||||||
|
public class MPVVO implements Serializable {
|
||||||
|
|
||||||
|
private String databaseName;
|
||||||
|
|
||||||
|
private String measuringPointNumberOrTechID;
|
||||||
|
|
||||||
|
private String assignmentTechIDorName;
|
||||||
|
|
||||||
|
private Boolean shortMem;
|
||||||
|
|
||||||
|
private Boolean longMem;
|
||||||
|
|
||||||
|
private Integer maxCount;
|
||||||
|
|
||||||
|
private String startDateTime;
|
||||||
|
|
||||||
|
private String stopDateTime;
|
||||||
|
|
||||||
|
private Integer mpktTech;
|
||||||
|
|
||||||
|
private String expand;
|
||||||
|
|
||||||
|
public String getParameter() {
|
||||||
|
String para = "?placeholder=placeholder";//该参数无意义,用作占位符,方便后面拼接url,统一 &xxx=yyy
|
||||||
|
if (shortMem != null) {
|
||||||
|
para = para + ("&ShortMem=" + shortMem);
|
||||||
|
} else {
|
||||||
|
para = para + ("&ShortMem=" + true);
|
||||||
|
}
|
||||||
|
if (longMem != null) {
|
||||||
|
para = para + ("&LongMem=" + longMem);
|
||||||
|
} else {
|
||||||
|
para = para + ("&LongMem=" + true);
|
||||||
|
}
|
||||||
|
if (maxCount != null) {
|
||||||
|
para = para + ("&MaxCount=" + maxCount);
|
||||||
|
}
|
||||||
|
// if (startDateTime != null) {
|
||||||
|
// para = para + ("&StartDateTime=" + startDateTime);
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// if (stopDateTime != null) {
|
||||||
|
// para = para + ("&StartDateTime=" + startDateTime);
|
||||||
|
// }
|
||||||
|
if (mpktTech != null) {
|
||||||
|
para = para + ("&MpktTech=" + mpktTech);
|
||||||
|
}
|
||||||
|
if (expand != null) {
|
||||||
|
para = para + ("&Expand=" + expand);
|
||||||
|
}
|
||||||
|
return para;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MPVVO() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDatabaseName() {
|
||||||
|
return databaseName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDatabaseName(String databaseName) {
|
||||||
|
this.databaseName = databaseName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMeasuringPointNumberOrTechID() {
|
||||||
|
return measuringPointNumberOrTechID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMeasuringPointNumberOrTechID(String measuringPointNumberOrTechID) {
|
||||||
|
this.measuringPointNumberOrTechID = measuringPointNumberOrTechID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAssignmentTechIDorName() {
|
||||||
|
return assignmentTechIDorName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAssignmentTechIDorName(String assignmentTechIDorName) {
|
||||||
|
this.assignmentTechIDorName = assignmentTechIDorName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isShortMem() {
|
||||||
|
return shortMem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShortMem(Boolean shortMem) {
|
||||||
|
this.shortMem = shortMem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLongMem() {
|
||||||
|
return longMem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLongMem(Boolean longMem) {
|
||||||
|
this.longMem = longMem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxCount() {
|
||||||
|
return maxCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxCount(Integer maxCount) {
|
||||||
|
this.maxCount = maxCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStartDateTime() {
|
||||||
|
return startDateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStartDateTime(String startDateTime) {
|
||||||
|
this.startDateTime = startDateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStopDateTime() {
|
||||||
|
return stopDateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStopDateTime(String stopDateTime) {
|
||||||
|
this.stopDateTime = stopDateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMpktTech() {
|
||||||
|
return mpktTech;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMpktTech(Integer mpktTech) {
|
||||||
|
this.mpktTech = mpktTech;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExpand() {
|
||||||
|
return expand;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpand(String expand) {
|
||||||
|
this.expand = expand;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package com.cisdi.data.DHV.gateway.vo.dhv;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author jianghc
|
||||||
|
* @function: 连接管理中,自定义的其他参数
|
||||||
|
* @date 2022年05月05日 09:48
|
||||||
|
*/
|
||||||
|
public class OtherParamVO implements Serializable {
|
||||||
|
|
||||||
|
private MPSVO mpsvo;
|
||||||
|
|
||||||
|
private List<MPVVO> mpvvoList;
|
||||||
|
|
||||||
|
String Authorization;
|
||||||
|
|
||||||
|
String emptyanddefault;
|
||||||
|
|
||||||
|
public OtherParamVO(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public MPSVO getMpsvo() {
|
||||||
|
return mpsvo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMpsvo(MPSVO mpsvo) {
|
||||||
|
this.mpsvo = mpsvo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MPVVO> getMpvvoList() {
|
||||||
|
return mpvvoList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMpvvoList(List<MPVVO> mpvvoList) {
|
||||||
|
this.mpvvoList = mpvvoList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthorization() {
|
||||||
|
return Authorization;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthorization(String authorization) {
|
||||||
|
Authorization = authorization;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmptyanddefault() {
|
||||||
|
return emptyanddefault;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmptyanddefault(String emptyanddefault) {
|
||||||
|
this.emptyanddefault = emptyanddefault;
|
||||||
|
}
|
||||||
|
}
|
45
src/main/java/com/cisdi/data/DHV/gateway/vo/dhv/YFDHV.java
Normal file
45
src/main/java/com/cisdi/data/DHV/gateway/vo/dhv/YFDHV.java
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package com.cisdi.data.DHV.gateway.vo.dhv;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author jianghc
|
||||||
|
* @function: 设备健康振动数据接入请求接口路径
|
||||||
|
* @date 2022/5/6 15:46
|
||||||
|
*/
|
||||||
|
public interface YFDHV {
|
||||||
|
|
||||||
|
|
||||||
|
//测点状态接口
|
||||||
|
//{databaseName}
|
||||||
|
String YF_DHV_MPS = "/databases/%s/measuringpoints";
|
||||||
|
|
||||||
|
|
||||||
|
//测点方法接口
|
||||||
|
//{dataBaseNamePlaceholder}数据库
|
||||||
|
//{measuringPointNumberOrTechID}测点编码
|
||||||
|
String YF_DHV_METH = "/databases/%s/measuringpoints/%s/assignments";
|
||||||
|
|
||||||
|
|
||||||
|
//测点总值接口
|
||||||
|
//{databaseName}
|
||||||
|
//{measuringPointNumberOrTechID}
|
||||||
|
//{assignmentTechIDorName}
|
||||||
|
String YF_DHV_MPV = "/databases/%s/measuringpoints/%s/assignments/%s/results";
|
||||||
|
|
||||||
|
|
||||||
|
//测点状态电文号=数据库.MPS
|
||||||
|
String YF_MPS = "MPS";
|
||||||
|
|
||||||
|
|
||||||
|
//测点总值电文号=测点.MPV
|
||||||
|
String YF_MPV = "MPV";
|
||||||
|
|
||||||
|
//分隔符,用.作为分隔符
|
||||||
|
String YF_Separator = ".";
|
||||||
|
|
||||||
|
//转义字符,split("\\.")时使用
|
||||||
|
String YF_EscapeCharacter="\\";
|
||||||
|
|
||||||
|
//注意测点状态时间是系统生成的,没有从接口中获取到
|
||||||
|
String DateTime = "DateTime";
|
||||||
|
|
||||||
|
}
|
146
src/main/java/com/cisdi/data/DIClient/DIClientGateway.java
Normal file
146
src/main/java/com/cisdi/data/DIClient/DIClientGateway.java
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
package com.cisdi.data.DIClient;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.cisdi.data.DIClient.bean.DIClientCnfg;
|
||||||
|
import com.cisdi.data.DIClient.bean.PDIOVo;
|
||||||
|
import com.cisdi.data.DIClient.gateway.DBReader;
|
||||||
|
import com.cisdi.data.DIClient.gateway.DBTask;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import com.cisdi.data.sdk.consts.ServiceName;
|
||||||
|
import com.cisdi.data.sdk.enums.GatewayState;
|
||||||
|
import com.cisdi.data.sdk.gateway.base.SocketGatewayBase;
|
||||||
|
import com.cisdi.data.sdk.param.ListenSocketParam;
|
||||||
|
import com.cisdi.data.sdk.procotol.message.SocketReturnMessage;
|
||||||
|
import com.cisdi.data.sdk.service.RouteService;
|
||||||
|
import com.cisdi.data.sdk.vo.DeviceVo;
|
||||||
|
import com.cisdi.data.sdk.vo.ExeResultVo;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
public class DIClientGateway extends SocketGatewayBase {
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(DIClientGateway.class);
|
||||||
|
|
||||||
|
private String deviceId;
|
||||||
|
private DBTask dbTask = null;
|
||||||
|
|
||||||
|
private AtomicLong lastTime=new AtomicLong(0);
|
||||||
|
private AtomicInteger no=new AtomicInteger(0);
|
||||||
|
@Override
|
||||||
|
public ExeResultVo sendReturnMessage(SocketReturnMessage returnMsg) {
|
||||||
|
ExeResultVo rt = new ExeResultVo();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PDIOVo pdioVo = new PDIOVo();
|
||||||
|
pdioVo.setQueueId(returnMsg.getMsgKey());
|
||||||
|
pdioVo.setData(new String(returnMsg.getData()));
|
||||||
|
Long thisTime=System.currentTimeMillis();
|
||||||
|
if(thisTime>lastTime.get())
|
||||||
|
{
|
||||||
|
lastTime.set(thisTime);
|
||||||
|
no.set(0);
|
||||||
|
pdioVo.setSerialNo(0);
|
||||||
|
pdioVo.setTimeStamp(thisTime);
|
||||||
|
}
|
||||||
|
else if(thisTime==lastTime.get())
|
||||||
|
{
|
||||||
|
pdioVo.setSerialNo(no.incrementAndGet());
|
||||||
|
pdioVo.setTimeStamp(thisTime);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pdioVo.setTimeStamp(lastTime.get());
|
||||||
|
pdioVo.setSerialNo(no.incrementAndGet());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pdioVo.setHeader("cisdi");
|
||||||
|
pdioVo.setStatus("N");
|
||||||
|
dbTask.sendMessage(pdioVo);
|
||||||
|
|
||||||
|
rt.setSuccess(true);
|
||||||
|
rt.setMessage("DIClient下发数据成功,消息体为" + JSON.toJSONString(pdioVo));
|
||||||
|
logger.info("DIClient下发数据成功,消息体为" + JSON.toJSONString(pdioVo));
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
if (state == GatewayState.RUNNING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ListenSocketParam socketParam = JSON.parseObject(getInstanceVo().getParameter(), ListenSocketParam.class);
|
||||||
|
|
||||||
|
String otherParameter = socketParam.getOtherParameter();
|
||||||
|
DIClientCnfg diClientCnfg = null;
|
||||||
|
// 处理分组
|
||||||
|
if (StringUtils.isNotBlank(otherParameter)) {
|
||||||
|
diClientCnfg = JSON.parseObject(otherParameter, DIClientCnfg.class);
|
||||||
|
}
|
||||||
|
if (diClientCnfg == null) {
|
||||||
|
throw new BusinessException("网关Id:" + instanceVo.getRunId() + "为DIClient网关,请配置正确的DIClient配置");
|
||||||
|
}
|
||||||
|
|
||||||
|
RouteService routeService = (RouteService) serviceProvider.getByName(ServiceName.Route);
|
||||||
|
List<DeviceVo> deviceVos = routeService.findByRunId(instanceVo.getRunId());
|
||||||
|
|
||||||
|
if (deviceVos.size() > 1) {
|
||||||
|
throw new BusinessException("网关Id:" + instanceVo.getRunId() + "为DIClient网关,只允许关联一个设备Id");
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceId = deviceVos.size() > 0 ? deviceVos.get(0).getDeviceId() : null;
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(deviceId)) {
|
||||||
|
throw new BusinessException("runId=" + getInstanceVo().getRunId() + "未正确配置网关和设备关联");
|
||||||
|
}
|
||||||
|
logger.info("DIClient网关:{}读取启动配置参数:{}", instanceVo.getRunId(), getInstanceVo().getParameter());
|
||||||
|
|
||||||
|
|
||||||
|
boolean open = false;
|
||||||
|
DBReader dbReader = new DBReader(diClientCnfg.getDriverClassName(), diClientCnfg.getUrl(), diClientCnfg.getUser(), diClientCnfg.getPwd());
|
||||||
|
open = dbReader.connectionInternal(0);
|
||||||
|
if (open == true) {
|
||||||
|
dbTask = new DBTask(serviceProvider, this, dbReader, diClientCnfg.getCycleTime(), deviceId);
|
||||||
|
dbTask.start();
|
||||||
|
state = GatewayState.RUNNING;
|
||||||
|
logger.info("DIClient网关:{}启动成功 参数:{}", instanceVo.getRunId(), getInstanceVo().getParameter());
|
||||||
|
} else {
|
||||||
|
logger.info("DIClient网关:{}启动失败 参数:{}", instanceVo.getRunId(), getInstanceVo().getParameter());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
if (state == GatewayState.CLOSED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
dbTask.close();
|
||||||
|
state = GatewayState.CLOSED;
|
||||||
|
logger.info("网关:" + instanceVo.getRunId() + "关闭成功", instanceVo.getRunId());
|
||||||
|
} catch (SQLException e) {
|
||||||
|
logger.error("网关:" + instanceVo.getRunId() + "关闭失败" + e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getActiveDeviceIds() {
|
||||||
|
|
||||||
|
Set<String> set = Sets.newConcurrentHashSet();
|
||||||
|
|
||||||
|
if (StringUtils.isNotEmpty(deviceId)) {
|
||||||
|
set.add(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
}
|
52
src/main/java/com/cisdi/data/DIClient/DIClientTest.java
Normal file
52
src/main/java/com/cisdi/data/DIClient/DIClientTest.java
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package com.cisdi.data.DIClient;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.cisdi.data.DIClient.bean.DIClientCnfg;
|
||||||
|
import com.cisdi.data.DIClient.gateway.DBReader;
|
||||||
|
import com.cisdi.data.DIClient.gateway.DBTask;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import com.cisdi.data.sdk.enums.GatewayState;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
|
public class DIClientTest {
|
||||||
|
public static void main(String[] args) throws UnsupportedEncodingException {
|
||||||
|
char x=0x03;
|
||||||
|
String test="20210408195055077MR001 N11001001 yf R一级焦炭 Bt 7.000 2 Y99999.0000 0.0000 0.0000 0.0000 B020 ";
|
||||||
|
String value="7.000 ";
|
||||||
|
value=value.trim();
|
||||||
|
int splitIndex = value.length() - 3;
|
||||||
|
|
||||||
|
String t="{\"cycleTime\":3000,\"dbName\":\"test\",\"driverClassName\":\"com.mysql.jdbc.Driver\",\"pwd\":\"yLNklB0v6Hu&J2T!\",\"url\":\"jdbc:mysql://10.232.12.58:3306/zgerp?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false\",\"user\":\"root\"} ";
|
||||||
|
|
||||||
|
String prev = value.substring(0, splitIndex-1);
|
||||||
|
String end = value.substring(splitIndex);
|
||||||
|
|
||||||
|
DIClientCnfg diClientCnfg=new DIClientCnfg();
|
||||||
|
diClientCnfg.setCycleTime((long) 3000);
|
||||||
|
diClientCnfg.setDbName("test");
|
||||||
|
diClientCnfg.setDriverClassName("com.mysql.jdbc.Driver");
|
||||||
|
diClientCnfg.setUrl("jdbc:mysql://10.232.12.58:3306/zgerp?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false");
|
||||||
|
diClientCnfg.setUser("root");
|
||||||
|
diClientCnfg.setPwd("yLNklB0v6Hu&J2T!");
|
||||||
|
|
||||||
|
System.out.println(JSON.toJSONString(diClientCnfg));
|
||||||
|
boolean open = false;
|
||||||
|
DBReader dbReader=new DBReader(diClientCnfg.getDriverClassName(),diClientCnfg.getUrl(),diClientCnfg.getUser(),diClientCnfg.getPwd());
|
||||||
|
open=dbReader.connectionInternal(0);
|
||||||
|
if(open == true) {
|
||||||
|
DBTask dbTask=new DBTask(null,null,dbReader,diClientCnfg.getCycleTime(),"");
|
||||||
|
dbTask.start();
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(10000000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
System.out.println("DIClient网关:{}启动成功 参数:{}");
|
||||||
|
}else {
|
||||||
|
System.out.println("DIClient网关:{}启动失败 参数:{}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
src/main/java/com/cisdi/data/DIClient/bean/DBFieldVo.java
Normal file
31
src/main/java/com/cisdi/data/DIClient/bean/DBFieldVo.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package com.cisdi.data.DIClient.bean;
|
||||||
|
|
||||||
|
public class DBFieldVo {
|
||||||
|
private String filedName;
|
||||||
|
private String as;
|
||||||
|
private boolean orderBy;
|
||||||
|
|
||||||
|
public String getFiledName() {
|
||||||
|
return filedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFiledName(String filedName) {
|
||||||
|
this.filedName = filedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAs() {
|
||||||
|
return as;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAs(String as) {
|
||||||
|
this.as = as;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOrderBy() {
|
||||||
|
return orderBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrderBy(boolean orderBy) {
|
||||||
|
this.orderBy = orderBy;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
package com.cisdi.data.DIClient.bean;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class DBTableTaskCnfg {
|
||||||
|
private DBTableVo tableName;
|
||||||
|
private List<DBFieldVo> fieldNames;
|
||||||
|
private List<String> condition;
|
||||||
|
private Long cycleTime;
|
||||||
|
private String taskType;
|
||||||
|
private String sortType;
|
||||||
|
private String groupBy;
|
||||||
|
private String msgKey;
|
||||||
|
|
||||||
|
public String getMsgKey() {
|
||||||
|
return msgKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMsgKey(String msgKey) {
|
||||||
|
this.msgKey = msgKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DBTableVo getTableName() {
|
||||||
|
return tableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTableName(DBTableVo tableName) {
|
||||||
|
this.tableName = tableName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DBFieldVo> getFieldNames() {
|
||||||
|
return fieldNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFieldNames(List<DBFieldVo> fieldNames) {
|
||||||
|
this.fieldNames = fieldNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getCondition() {
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCondition(List<String> condition) {
|
||||||
|
this.condition = condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getCycleTime() {
|
||||||
|
return cycleTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCycleTime(Long cycleTime) {
|
||||||
|
this.cycleTime = cycleTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTaskType() {
|
||||||
|
return taskType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTaskType(String taskType) {
|
||||||
|
this.taskType = taskType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSortType() {
|
||||||
|
return sortType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSortType(String sortType) {
|
||||||
|
this.sortType = sortType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGroupBy() {
|
||||||
|
return groupBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGroupBy(String groupBy) {
|
||||||
|
this.groupBy = groupBy;
|
||||||
|
}
|
||||||
|
}
|
40
src/main/java/com/cisdi/data/DIClient/bean/DBTableVo.java
Normal file
40
src/main/java/com/cisdi/data/DIClient/bean/DBTableVo.java
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package com.cisdi.data.DIClient.bean;
|
||||||
|
|
||||||
|
public class DBTableVo {
|
||||||
|
private DBTableVo leftTable;
|
||||||
|
private String rightTable;
|
||||||
|
private String joinType;
|
||||||
|
private String on;
|
||||||
|
|
||||||
|
public DBTableVo getLeftTable() {
|
||||||
|
return leftTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLeftTable(DBTableVo leftTable) {
|
||||||
|
this.leftTable = leftTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRightTable() {
|
||||||
|
return rightTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRightTable(String rightTable) {
|
||||||
|
this.rightTable = rightTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJoinType() {
|
||||||
|
return joinType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJoinType(String joinType) {
|
||||||
|
this.joinType = joinType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOn() {
|
||||||
|
return on;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOn(String on) {
|
||||||
|
this.on = on;
|
||||||
|
}
|
||||||
|
}
|
72
src/main/java/com/cisdi/data/DIClient/bean/DIClientCnfg.java
Normal file
72
src/main/java/com/cisdi/data/DIClient/bean/DIClientCnfg.java
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
package com.cisdi.data.DIClient.bean;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class DIClientCnfg {
|
||||||
|
private String dbName;
|
||||||
|
private String url;
|
||||||
|
private String user;
|
||||||
|
private String pwd;
|
||||||
|
private String driverClassName;
|
||||||
|
private Long cycleTime;
|
||||||
|
//TASK名字,TASK筛选条件
|
||||||
|
// Map<String, DBTableTaskCnfg> taskMap;
|
||||||
|
|
||||||
|
|
||||||
|
public Long getCycleTime() {
|
||||||
|
return cycleTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCycleTime(Long cycleTime) {
|
||||||
|
this.cycleTime = cycleTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDbName() {
|
||||||
|
return dbName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDbName(String dbName) {
|
||||||
|
this.dbName = dbName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(String user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPwd() {
|
||||||
|
return pwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPwd(String pwd) {
|
||||||
|
this.pwd = pwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDriverClassName() {
|
||||||
|
return driverClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDriverClassName(String driverClassName) {
|
||||||
|
this.driverClassName = driverClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public Map<String, DBTableTaskCnfg> getTaskMap() {
|
||||||
|
// return taskMap;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public void setTaskMap(Map<String, DBTableTaskCnfg> taskMap) {
|
||||||
|
// this.taskMap = taskMap;
|
||||||
|
// }
|
||||||
|
}
|
76
src/main/java/com/cisdi/data/DIClient/bean/PDIOVo.java
Normal file
76
src/main/java/com/cisdi/data/DIClient/bean/PDIOVo.java
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package com.cisdi.data.DIClient.bean;
|
||||||
|
|
||||||
|
public class PDIOVo {
|
||||||
|
private Long timeStamp;
|
||||||
|
private Integer serialNo;
|
||||||
|
private String queueId;
|
||||||
|
private String header;
|
||||||
|
private String data;
|
||||||
|
private String status;
|
||||||
|
private String processTime;
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
public Long getTimeStamp() {
|
||||||
|
return timeStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTimeStamp(Long timeStamp) {
|
||||||
|
this.timeStamp = timeStamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getSerialNo() {
|
||||||
|
return serialNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSerialNo(Integer serialNo) {
|
||||||
|
this.serialNo = serialNo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getQueueId() {
|
||||||
|
return queueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setQueueId(String queueId) {
|
||||||
|
this.queueId = queueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHeader() {
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeader(String header) {
|
||||||
|
this.header = header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(String data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(String status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProcessTime() {
|
||||||
|
return processTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProcessTime(String processTime) {
|
||||||
|
this.processTime = processTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
}
|
215
src/main/java/com/cisdi/data/DIClient/gateway/DBReader.java
Normal file
215
src/main/java/com/cisdi/data/DIClient/gateway/DBReader.java
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
package com.cisdi.data.DIClient.gateway;
|
||||||
|
|
||||||
|
import com.cisdi.data.DIClient.bean.PDIOVo;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.sql.*;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class DBReader
|
||||||
|
{
|
||||||
|
Logger logger= LoggerFactory.getLogger(DBReader.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JDBC的连接对象实例
|
||||||
|
*/
|
||||||
|
private Connection conn = null;
|
||||||
|
private String driver;
|
||||||
|
private String url;
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
public DBReader(String driver, String url, String username, String password) {
|
||||||
|
this.driver = driver;
|
||||||
|
this.url = url;
|
||||||
|
this.username = username;
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reconnect()
|
||||||
|
{
|
||||||
|
logger.info("由于发生了异常,正在尝试重连");
|
||||||
|
try {
|
||||||
|
if(conn!=null&&!conn.isClosed())
|
||||||
|
{
|
||||||
|
conn.close();
|
||||||
|
}
|
||||||
|
connectionInternal(0);
|
||||||
|
} catch (SQLException e1) {
|
||||||
|
e1.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean connectionInternal(int reconnectNumber) {
|
||||||
|
try {
|
||||||
|
Class.forName(driver);
|
||||||
|
conn = DriverManager.getConnection(url, username, password);
|
||||||
|
logger.info("【DI Client】建立与mysql数据库(URL:" + url + ")的连接");
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn(e.getMessage(), e);
|
||||||
|
|
||||||
|
logger.error("【DI Client】SQL:连接失败,等待重连,剩余重连次数" + reconnectNumber + " 异常信息:" + e.getLocalizedMessage());
|
||||||
|
reconnectNumber=reconnectNumber-1;
|
||||||
|
if (reconnectNumber <= 0) {
|
||||||
|
logger.error("【DI Client】SQL:重连失败,DIClient连接启动失败");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Thread.sleep(10000);
|
||||||
|
} catch (Exception e1) {
|
||||||
|
logger.info("【DI Client】SQL:等待失败,进程退出");
|
||||||
|
}
|
||||||
|
return this.connectionInternal(reconnectNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void close() throws SQLException {
|
||||||
|
if(conn!=null&&!conn.isClosed())
|
||||||
|
{
|
||||||
|
conn.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTotal()
|
||||||
|
{
|
||||||
|
String sql = "select count(*) from TBDIPDI where status='N' ";
|
||||||
|
ResultSet myResult = null;
|
||||||
|
PreparedStatement pre = null;
|
||||||
|
try {
|
||||||
|
pre = conn.prepareStatement(sql);
|
||||||
|
myResult = pre.executeQuery();
|
||||||
|
while (myResult.next()) {
|
||||||
|
return myResult.getInt("count(*)");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("【DB】SQL语句" + sql + "执行失败,请检查配置文件是否正确,以及数据表是否更改:" + e.getLocalizedMessage(), e);
|
||||||
|
reconnect();
|
||||||
|
} finally {
|
||||||
|
closeObj(myResult);
|
||||||
|
closeObj(pre);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PDIOVo> getPDIOs(int limit)
|
||||||
|
{
|
||||||
|
List<PDIOVo> rt=new ArrayList<>();
|
||||||
|
String sql = "select timestamp,serialno,queueid,header,data,status,processtime,description from TBDIPDI where status='N' order by TIMESTAMP,SerialNo asc limit "+limit;
|
||||||
|
ResultSet myResult = null;
|
||||||
|
PreparedStatement pre = null;
|
||||||
|
try {
|
||||||
|
pre = conn.prepareStatement(sql);
|
||||||
|
myResult = pre.executeQuery();
|
||||||
|
while (myResult.next()) {
|
||||||
|
PDIOVo pdioVo=new PDIOVo();
|
||||||
|
pdioVo.setTimeStamp(myResult.getLong("timestamp"));
|
||||||
|
pdioVo.setSerialNo(myResult.getInt("serialno"));
|
||||||
|
pdioVo.setQueueId(myResult.getString("queueid"));
|
||||||
|
pdioVo.setHeader(myResult.getString("header"));
|
||||||
|
pdioVo.setData(myResult.getString("data"));
|
||||||
|
pdioVo.setStatus(myResult.getString("status"));
|
||||||
|
pdioVo.setProcessTime(myResult.getString("processtime"));
|
||||||
|
pdioVo.setDescription(myResult.getString("description"));
|
||||||
|
rt.add(pdioVo);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("【DB】SQL语句" + sql + "执行失败,请检查配置文件是否正确,以及数据表是否更改:" + e.getLocalizedMessage(), e);
|
||||||
|
reconnect();
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
closeObj(myResult);
|
||||||
|
closeObj(pre);
|
||||||
|
}
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void closeObj(Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (obj instanceof PreparedStatement) {
|
||||||
|
PreparedStatement prepare = (PreparedStatement) obj;
|
||||||
|
try {
|
||||||
|
prepare.close();
|
||||||
|
return;
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (obj instanceof ResultSet) {
|
||||||
|
ResultSet resultSet = (ResultSet) obj;
|
||||||
|
try {
|
||||||
|
resultSet.close();
|
||||||
|
return;
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new BusinessException("not support type" + obj.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateStatus(List<PDIOVo> pdioVos,char status,String desc)
|
||||||
|
{
|
||||||
|
if(pdioVos==null||pdioVos.size()==0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String inStr="(";
|
||||||
|
for(PDIOVo pdioVo:pdioVos)
|
||||||
|
{
|
||||||
|
inStr+="("+pdioVo.getTimeStamp()+","+pdioVo.getSerialNo()+"),";
|
||||||
|
}
|
||||||
|
if(inStr.contains("),"))
|
||||||
|
{
|
||||||
|
inStr=inStr.substring(0,inStr.length()-1);
|
||||||
|
}
|
||||||
|
inStr+=")";
|
||||||
|
List<PDIOVo> rt=new ArrayList<>();
|
||||||
|
|
||||||
|
Date date=new Date();
|
||||||
|
DateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||||
|
String sql = "update TBDIPDI set status='"+status+"', processtime='"+format.format(date)+"'"+ (StringUtils.isBlank(desc)?"":",description='"+desc+"'") +" where (timestamp,serialno) in "+ inStr;
|
||||||
|
int myResultCount = 0;
|
||||||
|
PreparedStatement pre = null;
|
||||||
|
try {
|
||||||
|
pre = conn.prepareStatement(sql);
|
||||||
|
myResultCount = pre.executeUpdate();
|
||||||
|
if(myResultCount!=pdioVos.size())
|
||||||
|
{
|
||||||
|
logger.error("【DB】部分数据更新失败,入参"+pdioVos.size()+"条,更新了"+myResultCount+"条");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("【DB】SQL语句" + sql + "执行失败,请检查配置文件是否正确,以及数据表是否更改:" + e.getLocalizedMessage(), e);
|
||||||
|
reconnect();
|
||||||
|
} finally {
|
||||||
|
closeObj(pre);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPDIOs(PDIOVo pdioVos)
|
||||||
|
{
|
||||||
|
String sql = "insert into TBDIPDO (TBDIPDO.`TimeStamp`,TBDIPDO.SerialNo,TBDIPDO.QueueId,TBDIPDO.Header,TBDIPDO.`Data`,TBDIPDO.`Status`) value ("+pdioVos.getTimeStamp()+","+pdioVos.getSerialNo()+",'"+pdioVos.getQueueId()+"','"+pdioVos.getHeader()+"','"+pdioVos.getData()+"','"+pdioVos.getStatus()+"')";
|
||||||
|
int myResultCount = 0;
|
||||||
|
PreparedStatement pre = null;
|
||||||
|
try {
|
||||||
|
pre = conn.prepareStatement(sql);
|
||||||
|
myResultCount = pre.executeUpdate();
|
||||||
|
if(myResultCount!=1)
|
||||||
|
{
|
||||||
|
logger.error("【DB】部分数据插入失败");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("【DB】SQL语句" + sql + "执行失败,请检查配置文件是否正确,以及数据表是否更改:" + e.getLocalizedMessage(), e);
|
||||||
|
reconnect();
|
||||||
|
} finally {
|
||||||
|
closeObj(pre);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
137
src/main/java/com/cisdi/data/DIClient/gateway/DBTask.java
Normal file
137
src/main/java/com/cisdi/data/DIClient/gateway/DBTask.java
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
package com.cisdi.data.DIClient.gateway;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.cisdi.data.DIClient.bean.DBFieldVo;
|
||||||
|
import com.cisdi.data.DIClient.bean.DBTableTaskCnfg;
|
||||||
|
import com.cisdi.data.DIClient.bean.PDIOVo;
|
||||||
|
import com.cisdi.data.sdk.consts.ServiceName;
|
||||||
|
import com.cisdi.data.sdk.gateway.base.SocketGatewayBase;
|
||||||
|
import com.cisdi.data.sdk.gateway.message.SocketMessage;
|
||||||
|
import com.cisdi.data.sdk.service.DynamicCodecService;
|
||||||
|
import com.cisdi.data.sdk.service.SendService;
|
||||||
|
import com.cisdi.data.sdk.service.ServiceProvider;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class DBTask extends Thread {
|
||||||
|
|
||||||
|
Logger logger= LoggerFactory.getLogger(DBTask.class);
|
||||||
|
private ServiceProvider serviceProvider;
|
||||||
|
private SocketGatewayBase socketGateway;
|
||||||
|
private DBReader dbReader;
|
||||||
|
private Long cycleTime;
|
||||||
|
private boolean shouldRun;
|
||||||
|
private String deviceId;
|
||||||
|
private long lastTime=0;
|
||||||
|
private int lastNo=0;
|
||||||
|
public DBTask(ServiceProvider serviceProvider, SocketGatewayBase socketGateway, DBReader dbReader,Long cycleTime,String deviceId) {
|
||||||
|
this.serviceProvider = serviceProvider;
|
||||||
|
this.socketGateway = socketGateway;
|
||||||
|
this.dbReader = dbReader;
|
||||||
|
this.cycleTime=cycleTime;
|
||||||
|
shouldRun=true;
|
||||||
|
this.deviceId=deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean close() throws SQLException {
|
||||||
|
dbReader.close();
|
||||||
|
shouldRun=false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendMessage(PDIOVo pdioVo)
|
||||||
|
{
|
||||||
|
dbReader.addPDIOs(pdioVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (shouldRun)
|
||||||
|
{
|
||||||
|
long startTime=System.currentTimeMillis();
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
int total=dbReader.getTotal();
|
||||||
|
List<PDIOVo> pdioVoList=dbReader.getPDIOs(2000);
|
||||||
|
if(pdioVoList!=null&&pdioVoList.size()>0)
|
||||||
|
{
|
||||||
|
List<PDIOVo> successList=new ArrayList<>();
|
||||||
|
List<PDIOVo> errorList=new ArrayList<>();
|
||||||
|
String error="";
|
||||||
|
if(serviceProvider==null||socketGateway==null)
|
||||||
|
{
|
||||||
|
for(PDIOVo pdioVo:pdioVoList)
|
||||||
|
{
|
||||||
|
sendMessage(pdioVo);
|
||||||
|
System.out.println(JSON.toJSONString(pdioVo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SendService service = (SendService)serviceProvider.getByName(ServiceName.Send);
|
||||||
|
DynamicCodecService dynamicCodecService=(DynamicCodecService)serviceProvider.getByName(ServiceName.DynamicCodec);
|
||||||
|
for(PDIOVo pdioVo:pdioVoList)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String paramObj = dynamicCodecService.findByRunIdAndMsgKey(socketGateway.getInstanceVo().getRunId(), pdioVo.getQueueId());
|
||||||
|
if(StringUtils.isBlank(paramObj))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
SocketMessage socketMessage = socketGateway.buildSocketMessage();
|
||||||
|
socketMessage.setDeviceId(this.deviceId);
|
||||||
|
socketMessage.setMsgKey(pdioVo.getQueueId());
|
||||||
|
socketMessage.setData(pdioVo.getData().getBytes("GBK"));
|
||||||
|
socketMessage.getPropsMap().put("charset", Charset.forName("GBK"));
|
||||||
|
service.sendMessage(socketMessage);
|
||||||
|
successList.add(pdioVo);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
pdioVo.setDescription(e.getLocalizedMessage());
|
||||||
|
errorList.add(pdioVo);
|
||||||
|
error=e.getLocalizedMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(errorList.size() > 0)
|
||||||
|
{
|
||||||
|
dbReader.updateStatus(errorList,'E',error);
|
||||||
|
}
|
||||||
|
if(successList.size() > 0)
|
||||||
|
{
|
||||||
|
dbReader.updateStatus(successList,'O',"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(pdioVoList.size()==0||pdioVoList.size()==total)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
long endTime=System.currentTimeMillis();
|
||||||
|
try {
|
||||||
|
if(endTime-startTime<=cycleTime)
|
||||||
|
{
|
||||||
|
Thread.sleep(cycleTime-(endTime-startTime));
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
64
src/main/java/com/cisdi/data/DIClient/gateway/MysqlPool.txt
Normal file
64
src/main/java/com/cisdi/data/DIClient/gateway/MysqlPool.txt
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
//package com.cisdi.data.DIClient.gateway;
|
||||||
|
//
|
||||||
|
//import org.apache.commons.dbcp2.BasicDataSourceFactory;
|
||||||
|
//
|
||||||
|
//import javax.security.auth.login.Configuration;
|
||||||
|
//import javax.sql.DataSource;
|
||||||
|
//import java.sql.Connection;
|
||||||
|
//import java.sql.SQLException;
|
||||||
|
//import java.util.Properties;
|
||||||
|
//
|
||||||
|
//public class MysqlPool {
|
||||||
|
// private String driver;
|
||||||
|
// private String url;
|
||||||
|
// private String username;
|
||||||
|
// private String password;
|
||||||
|
// private Long removeTimeOut;
|
||||||
|
// private int maxTotal;
|
||||||
|
//
|
||||||
|
// private DataSource dataSource=null;
|
||||||
|
//
|
||||||
|
// public MysqlPool(String driver, String url, String username, String password, Long removeTimeOut, int maxTotal) {
|
||||||
|
// this.driver = driver;
|
||||||
|
// this.url = url;
|
||||||
|
// this.username = username;
|
||||||
|
// this.password = password;
|
||||||
|
// this.removeTimeOut = removeTimeOut;
|
||||||
|
// this.maxTotal = maxTotal;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public boolean init()
|
||||||
|
// {
|
||||||
|
// Properties properties=new Properties();
|
||||||
|
// properties.setProperty("driverClassName",driver);
|
||||||
|
// properties.setProperty("url",url);
|
||||||
|
// properties.setProperty("username",username);
|
||||||
|
// properties.setProperty("password",password);
|
||||||
|
// properties.setProperty("initialSize",String.valueOf(maxTotal));
|
||||||
|
// properties.setProperty("maxTotal",String.valueOf(maxTotal));
|
||||||
|
// properties.setProperty("maxIdle",String.valueOf(maxTotal/2));
|
||||||
|
// properties.setProperty("minIdle",String.valueOf(maxTotal/4));
|
||||||
|
// properties.setProperty("maxWaitMillis",String.valueOf(1000));
|
||||||
|
// properties.setProperty("removeAbandonedTimeout",String.valueOf(removeTimeOut));
|
||||||
|
// properties.setProperty("removeAbandonedOnMaintenance",String.valueOf(true));
|
||||||
|
// properties.setProperty("removeAbandonedOnBorrow",String.valueOf(true));
|
||||||
|
// try {
|
||||||
|
// dataSource= BasicDataSourceFactory.createDataSource(properties);
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// public Connection getConnection()
|
||||||
|
// {
|
||||||
|
// Connection connection=null;
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// connection=dataSource.getConnection();
|
||||||
|
// connection.setAutoCommit(false);
|
||||||
|
// } catch (SQLException e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// return connection;
|
||||||
|
// }
|
||||||
|
//}
|
@ -0,0 +1,127 @@
|
|||||||
|
package com.cisdi.data.DIClient.protocol;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.cisdi.data.DIClient.protocol.utils.IXComActionParamDTO;
|
||||||
|
import com.cisdi.data.DIClient.protocol.utils.IXComCodecService;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import com.cisdi.data.sdk.consts.ServiceName;
|
||||||
|
import com.cisdi.data.sdk.gateway.message.SocketMessage;
|
||||||
|
import com.cisdi.data.sdk.procotol.SocketProtocol;
|
||||||
|
import com.cisdi.data.sdk.procotol.base.ProtocolBase;
|
||||||
|
import com.cisdi.data.sdk.procotol.message.SocketReturnMessage;
|
||||||
|
import com.cisdi.data.sdk.service.DynamicCodecService;
|
||||||
|
import com.cisdi.data.sdk.service.RouteService;
|
||||||
|
import com.cisdi.data.sdk.vo.DecodeVo;
|
||||||
|
import com.cisdi.data.sdk.vo.DeviceVo;
|
||||||
|
import com.cisdi.data.sdk.vo.ReturnVo;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: lhp
|
||||||
|
* @date: 2019/10/8
|
||||||
|
**/
|
||||||
|
public class IXCom29DStringSocketProtocol extends ProtocolBase implements SocketProtocol {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DecodeVo deCode(SocketMessage message) {
|
||||||
|
if (message == null || message.getRunId() == null || message.getPropsMap() == null || message.getDeviceId() == null) {
|
||||||
|
throw new BusinessException("解析入参错误1,msg为:" + message.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicCodecService service = (DynamicCodecService)serviceProvider.getByName(ServiceName.DynamicCodec);
|
||||||
|
if (service == null || !(service instanceof DynamicCodecService)) {
|
||||||
|
throw new BusinessException("获取DynamicCodecService失败");
|
||||||
|
}
|
||||||
|
String paramObj = service.findByRunIdAndMsgKey(message.getRunId(), message.getMsgKey());
|
||||||
|
Charset charset = Charset.forName(String.valueOf(message.getPropsMap().get("charset")));
|
||||||
|
|
||||||
|
byte[] data = message.getData();
|
||||||
|
|
||||||
|
if(data == null || paramObj == null) {
|
||||||
|
throw new BusinessException("解析入参错误2,msg为:" + message.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
IXComActionParamDTO dto = JSON.parseObject(paramObj, IXComActionParamDTO.class);
|
||||||
|
dto.setMsgKey(message.getMsgKey());
|
||||||
|
if(dto == null || dto.getPropertyList().size() == 0) {
|
||||||
|
throw new BusinessException("解析入参错误3,msg为:" + message.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
DecodeVo vo = new DecodeVo();
|
||||||
|
|
||||||
|
IXComCodecService defaultService = new IXComCodecService();
|
||||||
|
|
||||||
|
Map<String,Object> map = defaultService.decode(message.getRunId(), dto, data, charset);
|
||||||
|
vo.setData(map);
|
||||||
|
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SocketReturnMessage enCode(ReturnVo returnVo) {
|
||||||
|
|
||||||
|
if (returnVo == null || returnVo.getValue() == null || returnVo.getDeviceId() == null) {
|
||||||
|
throw new BusinessException("解析入参错误1,msg为:" + JSON.toJSONString(returnVo));
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicCodecService service = (DynamicCodecService)serviceProvider.getByName(ServiceName.DynamicCodec);
|
||||||
|
if (service == null || !(service instanceof DynamicCodecService)) {
|
||||||
|
throw new BusinessException("获取DynamicCodecService失败");
|
||||||
|
}
|
||||||
|
RouteService routeService = (RouteService)serviceProvider.getByName(ServiceName.Route);
|
||||||
|
if (service == null || !(routeService instanceof RouteService)) {
|
||||||
|
throw new BusinessException("获取RouteService失败");
|
||||||
|
}
|
||||||
|
DeviceVo deviceVo=routeService.findDeviceByDeviceId(returnVo.getDeviceId());
|
||||||
|
if(deviceVo==null|| StringUtils.isBlank(deviceVo.getRunId()))
|
||||||
|
{
|
||||||
|
throw new BusinessException("获取DeviceVo失败");
|
||||||
|
}
|
||||||
|
String paramObj = service.findByRunIdAndMsgKey(deviceVo.getRunId(), returnVo.getMsgKey());
|
||||||
|
Charset charset = Charset.forName(String.valueOf(Charset.forName("GBK")));
|
||||||
|
IXComActionParamDTO dto = JSON.parseObject(paramObj, IXComActionParamDTO.class);
|
||||||
|
if(dto == null || dto.getPropertyList().size() == 0) {
|
||||||
|
throw new BusinessException("解析入参错误3,msg为:" + JSON.toJSONString(returnVo));
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder data= new StringBuilder();
|
||||||
|
|
||||||
|
for(IXComActionParamDTO.PropertyConfig propertyConfig:dto.getPropertyList())
|
||||||
|
{
|
||||||
|
if(!returnVo.getValue().containsKey(propertyConfig.getPropertyId()))
|
||||||
|
{
|
||||||
|
throw new BusinessException("解析入参错误4,msg为:" + JSON.toJSONString(returnVo)+"在runId="+deviceVo.getRunId()+";msgKey="+returnVo.getMsgKey()+"的情况下,入参缺失"+propertyConfig.getPropertyId());
|
||||||
|
}
|
||||||
|
StringBuilder tmp= new StringBuilder(String.valueOf(returnVo.getValue().get(propertyConfig.getPropertyId())));
|
||||||
|
int tmpLength= 0;
|
||||||
|
try {
|
||||||
|
tmpLength = tmp.toString().getBytes("GBK").length;
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new BusinessException("解析入参错误5,msg为:" + JSON.toJSONString(returnVo)+"在runId="+deviceVo.getRunId()+";msgKey="+returnVo.getMsgKey()+"的情况下,入参"+propertyConfig.getPropertyId()+"转换GBK失败"+e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
if(propertyConfig.getFixedLength()!=0&&tmpLength<propertyConfig.getFixedLength())
|
||||||
|
{
|
||||||
|
for(int i=0;i<(propertyConfig.getFixedLength()-tmpLength);i++)
|
||||||
|
{
|
||||||
|
tmp.append(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(propertyConfig.getFixedLength()!=0&&tmp.length()>propertyConfig.getFixedLength())
|
||||||
|
{
|
||||||
|
throw new BusinessException("解析入参错误6,msg为:" + JSON.toJSONString(returnVo)+"在runId="+deviceVo.getRunId()+";msgKey="+returnVo.getMsgKey()+"的情况下,入参过长"+propertyConfig.getPropertyId());
|
||||||
|
}
|
||||||
|
data.append(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
SocketReturnMessage rt=new SocketReturnMessage();
|
||||||
|
rt.setDeviceId(returnVo.getDeviceId());
|
||||||
|
rt.setMsgId(returnVo.getMsgId());
|
||||||
|
rt.setMsgKey(returnVo.getMsgKey());
|
||||||
|
rt.setData(data.toString().getBytes());
|
||||||
|
return rt;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,133 @@
|
|||||||
|
package com.cisdi.data.DIClient.protocol.utils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: lhp
|
||||||
|
* @date: 2019/10/8
|
||||||
|
**/
|
||||||
|
|
||||||
|
public class IXComActionParamDTO {
|
||||||
|
|
||||||
|
public enum PropertyType {
|
||||||
|
BYTE,
|
||||||
|
BOOLEAN,
|
||||||
|
SHORT,
|
||||||
|
INT,
|
||||||
|
FLOAT,
|
||||||
|
DOUBLE,
|
||||||
|
STRING,
|
||||||
|
LONG,
|
||||||
|
PLACEHOLDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 属性列表
|
||||||
|
*/
|
||||||
|
private List<PropertyConfig> propertyList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 电文号
|
||||||
|
*/
|
||||||
|
private String msgKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否透传
|
||||||
|
*/
|
||||||
|
private Boolean isPassthrough;
|
||||||
|
|
||||||
|
public Boolean getIsPassthrough() {
|
||||||
|
return isPassthrough;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsPassthrough(Boolean isPassthrough) {
|
||||||
|
this.isPassthrough = isPassthrough;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMsgKey() {
|
||||||
|
return msgKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMsgKey(String msgKey) {
|
||||||
|
this.msgKey = msgKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void appendProperty(PropertyConfig propertyConfig) {
|
||||||
|
|
||||||
|
if (propertyConfig == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propertyList == null) {
|
||||||
|
propertyList = new ArrayList<>();
|
||||||
|
}
|
||||||
|
propertyList.add(propertyConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PropertyConfig{
|
||||||
|
|
||||||
|
/** 属性Id*/
|
||||||
|
private String propertyId;
|
||||||
|
|
||||||
|
/** 属性类型*/
|
||||||
|
private PropertyType propertyType;
|
||||||
|
|
||||||
|
/**固定长度*/
|
||||||
|
private Integer fixedLength;
|
||||||
|
|
||||||
|
/**精度*/
|
||||||
|
private Integer precision;
|
||||||
|
|
||||||
|
public String getPropertyId() {
|
||||||
|
return propertyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPropertyId(String propertyId) {
|
||||||
|
this.propertyId = propertyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PropertyType getPropertyType() {
|
||||||
|
return propertyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPropertyType(PropertyType propertyType) {
|
||||||
|
this.propertyType = propertyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getFixedLength() {
|
||||||
|
return fixedLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFixedLength(Integer fixedLength) {
|
||||||
|
this.fixedLength = fixedLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getPrecision() {
|
||||||
|
return precision;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrecision(Integer precision) {
|
||||||
|
this.precision = precision;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "PropertyConfig [propertyId=" + propertyId + ", propertyType=" + propertyType + ", fixedLength="
|
||||||
|
+ fixedLength + ", precision=" + precision + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PropertyConfig> getPropertyList() {
|
||||||
|
return propertyList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPropertyList(List<PropertyConfig> propertyList) {
|
||||||
|
this.propertyList = propertyList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "IXComActionParamDTO [propertyList=" + propertyList + ", isPassthrough=" + isPassthrough + "]";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,141 @@
|
|||||||
|
package com.cisdi.data.DIClient.protocol.utils;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import com.cisdi.data.sdk.service.DynamicCodecService;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: lhp
|
||||||
|
* @date: 2019/10/8
|
||||||
|
**/
|
||||||
|
public class IXComCodecService {
|
||||||
|
|
||||||
|
public Map<String, Object> decode(String runId, IXComActionParamDTO dto, byte[] data, Charset charset) {
|
||||||
|
int sumLen = 0;
|
||||||
|
|
||||||
|
try{
|
||||||
|
sumLen = dto.getPropertyList().stream().mapToInt(IXComActionParamDTO.PropertyConfig::getFixedLength).sum();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new BusinessException("连接id:" + String.valueOf(runId) + "电文号:" + String.valueOf(dto.getMsgKey()) +
|
||||||
|
" ixcom29d解析数据长度失败", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sumLen != data.length) {
|
||||||
|
if(dto.getPropertyList().get(dto.getPropertyList().size()-1).getFixedLength()!=0)
|
||||||
|
{
|
||||||
|
throw new BusinessException("连接id:" + String.valueOf(runId) + "电文号:" + String.valueOf(dto.getMsgKey()) +
|
||||||
|
" ixcom29d解析长度与数据长度不一致错误, 解析数据长度为: " + data.length + " 配置长度为: " + sumLen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
|
||||||
|
ByteBuffer byteBuffer = ByteBuffer.wrap(data);
|
||||||
|
|
||||||
|
for(int i=0;i<dto.getPropertyList().size();i++)
|
||||||
|
{
|
||||||
|
if (dto.getPropertyList().get(i) != null) {
|
||||||
|
IXComActionParamDTO.PropertyConfig property=dto.getPropertyList().get(i);
|
||||||
|
if(i==dto.getPropertyList().size()-1&&property.getFixedLength()==0)
|
||||||
|
{
|
||||||
|
property.setFixedLength(byteBuffer.array().length-sumLen);
|
||||||
|
}
|
||||||
|
Object object = IXComConverterUtils.convertProperty(property, byteBuffer, charset,runId,dto.getMsgKey());
|
||||||
|
if (object != null) {
|
||||||
|
map.put(property.getPropertyId(), object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试类*/
|
||||||
|
public static class TestDynamicCodecHelperImpl implements DynamicCodecService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String findByRunIdAndMsgKey(String runId, String msgKey) {
|
||||||
|
IXComActionParamDTO dto = new IXComActionParamDTO();
|
||||||
|
IXComActionParamDTO.PropertyConfig config = new IXComActionParamDTO.PropertyConfig();
|
||||||
|
config.setPropertyId("boolean");
|
||||||
|
config.setPropertyType(IXComActionParamDTO.PropertyType.BOOLEAN);
|
||||||
|
config.setFixedLength(1);
|
||||||
|
dto.appendProperty(config);
|
||||||
|
IXComActionParamDTO.PropertyConfig config1 = new IXComActionParamDTO.PropertyConfig();
|
||||||
|
config1.setPropertyId("short");
|
||||||
|
config1.setPropertyType(IXComActionParamDTO.PropertyType.SHORT);
|
||||||
|
config1.setFixedLength(1);
|
||||||
|
IXComActionParamDTO.PropertyConfig config2 = new IXComActionParamDTO.PropertyConfig();
|
||||||
|
config2.setPropertyId("int");
|
||||||
|
config2.setPropertyType(IXComActionParamDTO.PropertyType.INT);
|
||||||
|
config2.setFixedLength(4);
|
||||||
|
IXComActionParamDTO.PropertyConfig config3 = new IXComActionParamDTO.PropertyConfig();
|
||||||
|
config3.setPropertyId("long");
|
||||||
|
config3.setPropertyType(IXComActionParamDTO.PropertyType.LONG);
|
||||||
|
config3.setFixedLength(4);
|
||||||
|
IXComActionParamDTO.PropertyConfig config4 = new IXComActionParamDTO.PropertyConfig();
|
||||||
|
config4.setPropertyId("string");
|
||||||
|
config4.setPropertyType(IXComActionParamDTO.PropertyType.STRING);
|
||||||
|
config4.setFixedLength(10);
|
||||||
|
IXComActionParamDTO.PropertyConfig config5 = new IXComActionParamDTO.PropertyConfig();
|
||||||
|
config5.setPropertyId("double");
|
||||||
|
config5.setPropertyType(IXComActionParamDTO.PropertyType.DOUBLE);
|
||||||
|
config5.setFixedLength(8);
|
||||||
|
|
||||||
|
IXComActionParamDTO.PropertyConfig config6 = new IXComActionParamDTO.PropertyConfig();
|
||||||
|
config6.setPropertyId("");
|
||||||
|
config6.setPropertyType(IXComActionParamDTO.PropertyType.PLACEHOLDER);
|
||||||
|
config6.setFixedLength(6);
|
||||||
|
dto.appendProperty(config1);
|
||||||
|
dto.appendProperty(config2);
|
||||||
|
dto.appendProperty(config3);
|
||||||
|
dto.appendProperty(config4);
|
||||||
|
dto.appendProperty(config5);
|
||||||
|
dto.appendProperty(config6);
|
||||||
|
|
||||||
|
return JSON.toJSONString(dto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean judgeBigEndianByRunId(String runId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean judgeBigEndianByDeviceId(String deviceId) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String findByRunIdAndMsgKeyNoCache(String runId, String msgKey) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public static void main(String[] args) {
|
||||||
|
IXComCodecService service = new IXComCodecService();
|
||||||
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
map.put("boolean", true);
|
||||||
|
map.put("short", Short.valueOf((short) 0xf2));
|
||||||
|
map.put("int", Integer.valueOf(0x03));
|
||||||
|
map.put("long", Long.valueOf(0xf4L));
|
||||||
|
map.put("string",new String("1234567890"));
|
||||||
|
map.put("double", Double.valueOf(-123123213.3));
|
||||||
|
Map<String, Object> map1 = JSON.parseObject(JSON.toJSONString(map));
|
||||||
|
// System.out.println(Arrays.toString(service.encode(map, "1","2", "1")));
|
||||||
|
// System.out.println(service.encode(map, "1","2","1").length);
|
||||||
|
//System.out.println(service.decode(service.encode(map, "1","2","1"), "1", "2", "1"));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,127 @@
|
|||||||
|
package com.cisdi.data.DIClient.protocol.utils;
|
||||||
|
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author: lhp
|
||||||
|
* @date: 2019/10/8
|
||||||
|
**/
|
||||||
|
public class IXComConverterUtils {
|
||||||
|
private static final char blankspace = ' ';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数字数据:则在不满位数时左补0:
|
||||||
|
例如:421: “00421”在5位数字值的情况下
|
||||||
|
-421: “-0421”
|
||||||
|
字符串数据:则在不够长度时右补空格
|
||||||
|
例如:TSB: “TSBDDDD”在7位字符串值的情况
|
||||||
|
* @param config
|
||||||
|
* @param reader
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Object convertProperty(IXComActionParamDTO.PropertyConfig config, ByteBuffer reader, Charset charset,String runid,String msgKey) {
|
||||||
|
|
||||||
|
char[] buffer = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
byte[] subBody = new byte[config.getFixedLength()];
|
||||||
|
reader.get(subBody);
|
||||||
|
|
||||||
|
String subValue = new String(subBody, charset);
|
||||||
|
buffer = subValue.toCharArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new BusinessException("ixcom29d读取字符数组失败" + e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
String value = new String(buffer);
|
||||||
|
if(config.getPropertyType()!= IXComActionParamDTO.PropertyType.STRING&&StringUtils.isBlank(value))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (config.getPropertyType()) {
|
||||||
|
case BYTE:
|
||||||
|
return Byte.valueOf(value.trim());
|
||||||
|
case SHORT:
|
||||||
|
return Short.valueOf(value.trim());
|
||||||
|
case INT:
|
||||||
|
return Integer.valueOf(value.trim());
|
||||||
|
case LONG:
|
||||||
|
return Long.valueOf(value.trim());
|
||||||
|
case BOOLEAN:
|
||||||
|
value = value.trim().replaceFirst("0*", "");
|
||||||
|
|
||||||
|
if("true".equalsIgnoreCase(value) || "1".equals(value)) {
|
||||||
|
return true;
|
||||||
|
}else if("false".equalsIgnoreCase(value) || "0".equals(value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FLOAT:
|
||||||
|
case DOUBLE:
|
||||||
|
if(config.getPrecision() != null) {
|
||||||
|
value=value.trim();
|
||||||
|
BigDecimal decimal=null;
|
||||||
|
if(config.getPrecision()!=0)
|
||||||
|
{
|
||||||
|
int splitIndex = value.length() - config.getPrecision();
|
||||||
|
|
||||||
|
if(splitIndex < 0) {
|
||||||
|
throw new BusinessException("config:" + config + ",value:" + value + ",precision error");
|
||||||
|
}
|
||||||
|
|
||||||
|
String prev = value.substring(0, splitIndex-1);
|
||||||
|
String end = value.substring(splitIndex);
|
||||||
|
|
||||||
|
decimal= new BigDecimal(prev + "." + end);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
decimal=new BigDecimal(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return decimal;
|
||||||
|
}else {
|
||||||
|
return new BigDecimal(value);
|
||||||
|
}
|
||||||
|
case STRING:
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
int index = buffer.length;
|
||||||
|
for (int i = buffer.length -1 ; i >= 0; i--) {
|
||||||
|
|
||||||
|
if(buffer[i] == blankspace) {
|
||||||
|
index = i;
|
||||||
|
continue;
|
||||||
|
}else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < index; j++) {
|
||||||
|
builder.append(buffer[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.toString();
|
||||||
|
case PLACEHOLDER:
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new BusinessException("连接id:" + String.valueOf(runid) + "电文号:" + msgKey +
|
||||||
|
" 解析数据类型错误:属性ID=" + config.getPropertyId()+"属性类型="+config.getPropertyType()+"属性精度="+config.getPrecision()+"属性长度="+config.getFixedLength()+"对应的值="+value+"错误为:"+e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new BusinessException(config.toString() + "解析失败,ixcom29d");
|
||||||
|
}
|
||||||
|
}
|
138
src/main/java/com/cisdi/data/HJ212/YfHj212SocketGateway.java
Normal file
138
src/main/java/com/cisdi/data/HJ212/YfHj212SocketGateway.java
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
package com.cisdi.data.HJ212;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.cisdi.data.HJ212.gateway.AliveCheckTask;
|
||||||
|
import com.cisdi.data.HJ212.gateway.Hj212ChannelInitializer;
|
||||||
|
import com.cisdi.data.HJ212.gateway.Hj212FrameDecoder;
|
||||||
|
import com.cisdi.data.HJ212.gateway.Hj212IoSession;
|
||||||
|
import com.cisdi.data.HJ212.gateway.Hj212SessionFactory;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import com.cisdi.data.sdk.consts.ServiceName;
|
||||||
|
import com.cisdi.data.sdk.enums.GatewayState;
|
||||||
|
import com.cisdi.data.sdk.gateway.base.SocketGatewayBase;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.IoSession;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.SessionFactory;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.TcpIoService;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.DefaultTcpIoService;
|
||||||
|
import com.cisdi.data.sdk.param.ListenSocketParam;
|
||||||
|
import com.cisdi.data.sdk.procotol.message.SocketReturnMessage;
|
||||||
|
import com.cisdi.data.sdk.service.RouteService;
|
||||||
|
import com.cisdi.data.sdk.vo.DeviceVo;
|
||||||
|
import com.cisdi.data.sdk.vo.ExeResultVo;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扬尘监测网络设备 HJ212协议数据接入
|
||||||
|
* @author cup
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class YfHj212SocketGateway extends SocketGatewayBase {
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(YfHj212SocketGateway.class);
|
||||||
|
private TcpIoService ioService = null;
|
||||||
|
private SessionFactory sessionFactory = null;
|
||||||
|
private AtomicBoolean shouldRun = null;
|
||||||
|
private String deviceId;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExeResultVo sendReturnMessage(SocketReturnMessage returnMsg) {
|
||||||
|
throw new BusinessException("hj212网关不支持下发命令");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
if(state == GatewayState.RUNNING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("hj212网关:{}读取启动配置参数:{}",instanceVo.getRunId(), getInstanceVo().getParameter());
|
||||||
|
|
||||||
|
RouteService routeService = (RouteService)serviceProvider.getByName(ServiceName.Route);
|
||||||
|
List<DeviceVo> deviceVos = routeService.findByRunId(instanceVo.getRunId());
|
||||||
|
|
||||||
|
if(deviceVos.size() > 1) {
|
||||||
|
throw new BusinessException("网关Id:" +instanceVo.getRunId() + "为hj212网关,只允许关联一个设备Id");
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceId = deviceVos.size() > 0 ? deviceVos.get(0).getDeviceId() : null;
|
||||||
|
|
||||||
|
if(StringUtils.isEmpty(deviceId)) {
|
||||||
|
throw new BusinessException("runId=" + getInstanceVo().getRunId() + "未正确配置网关和设备关联");
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultTcpIoService defaultIoService = new DefaultTcpIoService();
|
||||||
|
SessionFactory factory = new Hj212SessionFactory(deviceId);
|
||||||
|
factory.init(serviceProvider, this);
|
||||||
|
|
||||||
|
ListenSocketParam socketParam = JSON.parseObject(getInstanceVo().getParameter(), ListenSocketParam.class);
|
||||||
|
|
||||||
|
Hj212ChannelInitializer<Hj212FrameDecoder> channelInitializer =
|
||||||
|
new Hj212ChannelInitializer<Hj212FrameDecoder>(factory);
|
||||||
|
|
||||||
|
defaultIoService.init(instanceVo, factory, channelInitializer);
|
||||||
|
|
||||||
|
ioService = defaultIoService;
|
||||||
|
sessionFactory = factory;
|
||||||
|
|
||||||
|
boolean open = ioService.open();
|
||||||
|
|
||||||
|
if(open == true) {
|
||||||
|
state = GatewayState.RUNNING;
|
||||||
|
logger.info("hj212网关:{}启动成功 参数:{}", instanceVo.getRunId(), getInstanceVo().getParameter());
|
||||||
|
|
||||||
|
shouldRun = new AtomicBoolean(true);
|
||||||
|
|
||||||
|
Integer keepAlive = socketParam.getKeepAlive();
|
||||||
|
|
||||||
|
if(keepAlive == null || keepAlive < 120) {
|
||||||
|
keepAlive = 120;
|
||||||
|
}else if (keepAlive > 3600) {
|
||||||
|
keepAlive = 3600;
|
||||||
|
}
|
||||||
|
|
||||||
|
AliveCheckTask task = new AliveCheckTask(keepAlive, shouldRun, factory);
|
||||||
|
|
||||||
|
Thread thread = new Thread(task, "hj212-alive-check-thread-" + getInstanceVo().getRunId());
|
||||||
|
thread.start();
|
||||||
|
}else {
|
||||||
|
logger.info("hj212网关:{}启动失败 参数:{}", instanceVo.getRunId(), getInstanceVo().getParameter());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
if(state == GatewayState.CLOSED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sessionFactory != null) {
|
||||||
|
for (IoSession ioSession : sessionFactory.getSessions()) {
|
||||||
|
Hj212IoSession imsIoSession = (Hj212IoSession)ioSession;
|
||||||
|
imsIoSession.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean close = ioService.close();
|
||||||
|
if(close == true) {
|
||||||
|
sessionFactory = null;
|
||||||
|
state = GatewayState.CLOSED;
|
||||||
|
logger.info("hj212网关:{}关闭成功", instanceVo.getRunId());
|
||||||
|
}else {
|
||||||
|
logger.info("hj212网关:{}关闭失败", instanceVo.getRunId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getActiveDeviceIds(){
|
||||||
|
Set<String> set = Sets.newHashSet();
|
||||||
|
set.add(deviceId);
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,68 @@
|
|||||||
|
package com.cisdi.data.HJ212.gateway;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.IoSession;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.SessionFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保活时间检测,如果超过指定时间,则关闭连接
|
||||||
|
* @author cup
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class AliveCheckTask implements Runnable {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(AliveCheckTask.class);
|
||||||
|
|
||||||
|
private SessionFactory sessionFactory;
|
||||||
|
private AtomicBoolean shouldRun = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 会话允许的保活时间,单位秒
|
||||||
|
*/
|
||||||
|
private int keepAlive;
|
||||||
|
|
||||||
|
private static final double multiply = 1.5;
|
||||||
|
|
||||||
|
private static final int sleepInternal = 1000; // 1秒
|
||||||
|
|
||||||
|
public AliveCheckTask(int keepAlive, AtomicBoolean shouldRun, SessionFactory sessionFactory) {
|
||||||
|
super();
|
||||||
|
this.keepAlive = keepAlive;
|
||||||
|
this.shouldRun = shouldRun;
|
||||||
|
this.sessionFactory = sessionFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
logger.info("启动hj212保活超时检测线程");
|
||||||
|
|
||||||
|
while (shouldRun != null && shouldRun.get() == true) {
|
||||||
|
try {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
|
||||||
|
List<IoSession> sessions = sessionFactory.getSessions();
|
||||||
|
|
||||||
|
for (IoSession ioSession : sessions) {
|
||||||
|
Hj212IoSession session = (Hj212IoSession)ioSession;
|
||||||
|
|
||||||
|
// 超出指定倍数保活时间,
|
||||||
|
if((now - session.getLastAliveTime()) > (multiply * keepAlive * 1000)) {
|
||||||
|
session.close();
|
||||||
|
logger.warn("{} 超出指定倍数{}保活时间{},单位秒,关闭通道",
|
||||||
|
session.gwPrefix(), multiply, keepAlive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.sleep(sleepInternal);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn(e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("结束hj212保活超时检测线程");
|
||||||
|
}
|
||||||
|
}
|
48
src/main/java/com/cisdi/data/HJ212/gateway/CRC16Util.java
Normal file
48
src/main/java/com/cisdi/data/HJ212/gateway/CRC16Util.java
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package com.cisdi.data.HJ212.gateway;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
public class CRC16Util {
|
||||||
|
public static final Charset UTF8 = Charset.forName("UTF-8");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HJ212污染监测 CRC16校验算法
|
||||||
|
*
|
||||||
|
* @param dataBody
|
||||||
|
* @return CRC16校验码
|
||||||
|
*/
|
||||||
|
public static String CRC16(String dataBody) {
|
||||||
|
Integer[] regs = new Integer[dataBody.length()];
|
||||||
|
for (int i = 0; i < dataBody.length(); i++) {
|
||||||
|
regs[i] = (int)dataBody.charAt(i);
|
||||||
|
}
|
||||||
|
int por = 0xFFFF;
|
||||||
|
for (int j = 0; j < regs.length; j++) {
|
||||||
|
por = por >> 8;
|
||||||
|
por ^= regs[j];
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
if ((por & 0x01) == 1) {
|
||||||
|
por = por >> 1;
|
||||||
|
por = por ^ 0xa001;
|
||||||
|
} else
|
||||||
|
por = por >> 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String result = Integer.toHexString(por).toUpperCase();
|
||||||
|
|
||||||
|
while (result.length() < 4) {
|
||||||
|
result = "0" + result;
|
||||||
|
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
String body1 =
|
||||||
|
"QN=20160801085857223;ST=32;CN=1062;PW=100000;MN=010000A8900016F000169DC0;Flag=5;CP=&&RtdInterval=30&&";
|
||||||
|
System.out.println(CRC16(body1)); // should be 1C80
|
||||||
|
|
||||||
|
String body2 = "QN=20120416225111069;ST=91;CN=9021;PW=122333;MN=88888880000006;Flag=1;CP=&&&&";
|
||||||
|
System.out.println(CRC16(body2)); // should be 4100
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package com.cisdi.data.HJ212.gateway;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.SessionFactory;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.AbstractChannelInitializer;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.AbstractIoChannelHandler;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.DefaultIoChannelHandler;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.ChannelHandler;
|
||||||
|
import io.netty.handler.timeout.IdleStateHandler;
|
||||||
|
|
||||||
|
public class Hj212ChannelInitializer<I> extends AbstractChannelInitializer<I> {
|
||||||
|
private SessionFactory factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造通道初始化器对象
|
||||||
|
* @param factory 会话工厂
|
||||||
|
*/
|
||||||
|
public Hj212ChannelInitializer(SessionFactory factory) {
|
||||||
|
this.factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
protected AbstractIoChannelHandler<I> getTailHandler() {
|
||||||
|
return new DefaultIoChannelHandler(factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<ChannelHandler> getHandlers() {
|
||||||
|
List<ChannelHandler> handlers = new ArrayList<ChannelHandler>();
|
||||||
|
handlers.add(new Hj212FrameDecoder());
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IdleStateHandler getIdleStateHandler() {
|
||||||
|
return new IdleStateHandler(15, 15, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ChannelHandler getSslChannelHandler(Channel socketChannel) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
package com.cisdi.data.HJ212.gateway;
|
||||||
|
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Title: 永峰HJ212协议解码</p>
|
||||||
|
* <p>Description: 得到一个完整报文长度</p>
|
||||||
|
*
|
||||||
|
* @author lhp
|
||||||
|
* @version 1.0
|
||||||
|
* @date 2021.05.13
|
||||||
|
*/
|
||||||
|
public class Hj212FrameDecoder extends ByteToMessageDecoder {
|
||||||
|
Logger logger = LoggerFactory.getLogger(Hj212FrameDecoder.class);
|
||||||
|
// 包头2+数据段长度4+数据段0+CRC校验4+包尾2
|
||||||
|
private static final short Min_Length = 12;
|
||||||
|
private static final short Max_Length = 8192;
|
||||||
|
private Charset charset = StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void decode(ChannelHandlerContext ctx, ByteBuf bufferIn, List<Object> out) throws Exception {
|
||||||
|
try {
|
||||||
|
if (bufferIn.readableBytes() < Min_Length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int beginIndex = bufferIn.readerIndex();
|
||||||
|
|
||||||
|
byte[] headerBytes = new byte[6];
|
||||||
|
bufferIn.readBytes(headerBytes);
|
||||||
|
|
||||||
|
String header = new String(headerBytes, charset);
|
||||||
|
|
||||||
|
// 解析headerString
|
||||||
|
String lendthString = getString(header, 2, 6);
|
||||||
|
|
||||||
|
// 数据段长度
|
||||||
|
int length = Integer.valueOf(lendthString);
|
||||||
|
|
||||||
|
// 数据段长度+其他长度才是总的长度
|
||||||
|
length += 12;
|
||||||
|
|
||||||
|
if (length > Max_Length) {
|
||||||
|
ctx.close();
|
||||||
|
throw new BusinessException("超过协议允许最大报文长度,默认为 " + Max_Length + " byte,当前为" + length + "byte");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length < Min_Length) {
|
||||||
|
ctx.close();
|
||||||
|
throw new BusinessException(ctx.channel().toString() + "传输数据体长度小于12, 此长度为:" + length);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bufferIn.readableBytes() < length - 6) { // 拆包
|
||||||
|
bufferIn.readerIndex(beginIndex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bufferIn.readerIndex(beginIndex);
|
||||||
|
|
||||||
|
ByteBuf otherByteBufRef = bufferIn.retainedSlice(beginIndex, length);
|
||||||
|
|
||||||
|
bufferIn.readerIndex(beginIndex + length);
|
||||||
|
|
||||||
|
out.add(otherByteBufRef);
|
||||||
|
|
||||||
|
// 处理可能的粘包
|
||||||
|
decode(ctx, bufferIn, out);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("拆包过程出现异常,原始消息为:{}", bufferIn.toString(charset));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getString(String header, int start, int end) {
|
||||||
|
char[] dst = new char[end - start];
|
||||||
|
header.getChars(start, end, dst, 0);
|
||||||
|
|
||||||
|
return new String(dst);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
package com.cisdi.data.HJ212.gateway;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class Hj212FrameInputVo {
|
||||||
|
/** 请求编码 精确到毫秒的时间戳:QN=YYYYMMDDhhmmsszzz,用来唯一标识一次命令交互 */
|
||||||
|
private String qn;
|
||||||
|
/** 系统编码 */
|
||||||
|
private String st;
|
||||||
|
/** 命令编码,可以作为电文号 */
|
||||||
|
private String cn;
|
||||||
|
/** 访问密码 */
|
||||||
|
private String pw;
|
||||||
|
/** 设备唯一标识MN */
|
||||||
|
private String mn;
|
||||||
|
/** 拆分包及应答标志 */
|
||||||
|
private Integer flag;
|
||||||
|
/** 指令参数CP */
|
||||||
|
private String cp;
|
||||||
|
/** cp 中包含的 DataTime字段 */
|
||||||
|
private Long dataTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过命令上传的数据
|
||||||
|
*/
|
||||||
|
private Map<String, String> dataMap;
|
||||||
|
|
||||||
|
public String getQn() {
|
||||||
|
return qn;
|
||||||
|
}
|
||||||
|
public void setQn(String qn) {
|
||||||
|
this.qn = qn;
|
||||||
|
}
|
||||||
|
public String getSt() {
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
public void setSt(String st) {
|
||||||
|
this.st = st;
|
||||||
|
}
|
||||||
|
public String getCn() {
|
||||||
|
return cn;
|
||||||
|
}
|
||||||
|
public void setCn(String cn) {
|
||||||
|
this.cn = cn;
|
||||||
|
}
|
||||||
|
public String getPw() {
|
||||||
|
return pw;
|
||||||
|
}
|
||||||
|
public void setPw(String pw) {
|
||||||
|
this.pw = pw;
|
||||||
|
}
|
||||||
|
public String getMn() {
|
||||||
|
return mn;
|
||||||
|
}
|
||||||
|
public void setMn(String mn) {
|
||||||
|
this.mn = mn;
|
||||||
|
}
|
||||||
|
public Integer getFlag() {
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
public void setFlag(Integer flag) {
|
||||||
|
this.flag = flag;
|
||||||
|
}
|
||||||
|
public String getCp() {
|
||||||
|
return cp;
|
||||||
|
}
|
||||||
|
public void setCp(String cp) {
|
||||||
|
this.cp = cp;
|
||||||
|
}
|
||||||
|
public Long getDataTime() {
|
||||||
|
return dataTime;
|
||||||
|
}
|
||||||
|
public void setDataTime(Long dataTime) {
|
||||||
|
this.dataTime = dataTime;
|
||||||
|
}
|
||||||
|
public Map<String, String> getDataMap() {
|
||||||
|
return dataMap;
|
||||||
|
}
|
||||||
|
public void setDataMap(Map<String, String> dataMap) {
|
||||||
|
this.dataMap = dataMap;
|
||||||
|
}
|
||||||
|
}
|
124
src/main/java/com/cisdi/data/HJ212/gateway/Hj212IoSession.java
Normal file
124
src/main/java/com/cisdi/data/HJ212/gateway/Hj212IoSession.java
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
package com.cisdi.data.HJ212.gateway;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.cisdi.data.sdk.consts.ServiceName;
|
||||||
|
import com.cisdi.data.sdk.gateway.message.SocketMessage;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.IoSession;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.AbstractIoSession;
|
||||||
|
import com.cisdi.data.sdk.service.SendService;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* <p>Title: Hj212IoSession.java</p>
|
||||||
|
* @author lhp
|
||||||
|
* @date 2021年05月13日
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
public class Hj212IoSession extends AbstractIoSession implements IoSession {
|
||||||
|
private long lastAliveTime = System.currentTimeMillis();
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(Hj212IoSession.class);
|
||||||
|
private String deviceId = null;
|
||||||
|
|
||||||
|
public Hj212IoSession(String deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRead(Object message) {
|
||||||
|
int length = ((ByteBuf)message).readableBytes();
|
||||||
|
ByteBuf inBuf = (ByteBuf)message;
|
||||||
|
|
||||||
|
Hj212FrameInputVo vo = Hj212VoDecode.Decode(inBuf);
|
||||||
|
|
||||||
|
if(socketGateway!= null && Boolean.TRUE.equals(socketGateway.getInstanceVo().getLogOpen())) {
|
||||||
|
logger.info("hj212 {} 报文长度:{} vo:{} ", getChannel(), length, JSON.toJSONString(vo));
|
||||||
|
}
|
||||||
|
//发送的真正电文数据
|
||||||
|
Map<String, Object> realDataMap = Maps.newHashMap(vo.getDataMap());
|
||||||
|
realDataMap.put("dataTime", vo.getDataTime());
|
||||||
|
realDataMap.put("mn", vo.getMn());
|
||||||
|
realDataMap.put("qn", vo.getQn());
|
||||||
|
realDataMap.put("cn", vo.getCn());
|
||||||
|
String msgKey = String.format("%s_%s", vo.getMn(), vo.getCn());
|
||||||
|
|
||||||
|
if(vo != null && serviceProvider != null && socketGateway != null) {
|
||||||
|
SendService service = (SendService)serviceProvider.getByName(ServiceName.Send);
|
||||||
|
|
||||||
|
SocketMessage socketMessage = socketGateway.buildSocketMessage();
|
||||||
|
socketMessage.setDeviceId(deviceId);
|
||||||
|
|
||||||
|
socketMessage.setData(JSON.toJSONString(realDataMap).getBytes(CRC16Util.UTF8));
|
||||||
|
socketMessage.setMsgKey(msgKey);
|
||||||
|
|
||||||
|
service.sendMessage(socketMessage);
|
||||||
|
}else {
|
||||||
|
logger.info("hj212收到 msgkey: {} 消息:{}",msgKey, JSON.toJSONString(realDataMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] backBodys = Hj212VoEncoder.encode(vo.getSt(), vo.getCn(), vo.getPw(), vo.getMn());
|
||||||
|
ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(backBodys);
|
||||||
|
|
||||||
|
getChannel().writeAndFlush(wrappedBuffer);
|
||||||
|
lastAliveTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOpen() {
|
||||||
|
super.onOpen();
|
||||||
|
logger.info("建立连接,channel:{}", getChannel());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClose() {
|
||||||
|
super.onClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
if(getChannel() != null) {
|
||||||
|
try {
|
||||||
|
getChannel().close().sync();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
logger.warn(e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String gwPrefixCache = null;
|
||||||
|
|
||||||
|
public String gwPrefix() {
|
||||||
|
if(gwPrefixCache != null) {
|
||||||
|
return gwPrefixCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
gwPrefixCache = "";
|
||||||
|
if(socketGateway != null && socketGateway.getInstanceVo() != null) {
|
||||||
|
gwPrefixCache = "网关Id:" + socketGateway.getInstanceVo().getRunId() + "连接:" + getChannel() + " ";
|
||||||
|
}else {
|
||||||
|
gwPrefixCache = "连接:" + getChannel() + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return gwPrefixCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLastAliveTime() {
|
||||||
|
return lastAliveTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getDeviceIds() {
|
||||||
|
String cpDeviceId = deviceId;
|
||||||
|
String[] result = new String[cpDeviceId == null ? 0 : 1];
|
||||||
|
if(cpDeviceId != null) {
|
||||||
|
result[0] = cpDeviceId;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.cisdi.data.HJ212.gateway;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.IoSession;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.AbstractSessionFactory;
|
||||||
|
|
||||||
|
public class Hj212SessionFactory extends AbstractSessionFactory {
|
||||||
|
private String deviceId;
|
||||||
|
|
||||||
|
public Hj212SessionFactory(String deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IoSession newSession() {
|
||||||
|
IoSession session = new Hj212IoSession(deviceId);
|
||||||
|
session.init(UUID.randomUUID().toString(), provider, socketGateway);
|
||||||
|
sessionSet.add(session);
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
}
|
117
src/main/java/com/cisdi/data/HJ212/gateway/Hj212VoDecode.java
Normal file
117
src/main/java/com/cisdi/data/HJ212/gateway/Hj212VoDecode.java
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
package com.cisdi.data.HJ212.gateway;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.tomcat.util.buf.HexUtils;
|
||||||
|
import org.apache.tomcat.util.buf.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import com.cisdi.data.common.utils.Strings;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
|
||||||
|
public class Hj212VoDecode {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(Hj212VoDecode.class);
|
||||||
|
|
||||||
|
public static Hj212FrameInputVo Decode(ByteBuf in) {
|
||||||
|
byte[] bytes = new byte[in.readableBytes()];
|
||||||
|
in.readBytes(bytes);
|
||||||
|
String message = new String(bytes, CRC16Util.UTF8);
|
||||||
|
|
||||||
|
String body = message.substring(6, message.length() - 6);
|
||||||
|
String end = message.substring(message.length() - 6, message.length());
|
||||||
|
|
||||||
|
String crcParameter = end.substring(0, 4);
|
||||||
|
String crcResult = CRC16Util.CRC16(body);
|
||||||
|
|
||||||
|
if(Strings.equalsIgnoreCase(crcParameter, crcResult) == false){
|
||||||
|
log.error("hj212 crc16 check fail, input:{}, input-crc:{},cal-crc:{}", body, crcParameter, crcResult);
|
||||||
|
throw new BusinessException("crc16 check fail input-crc=" + crcParameter);
|
||||||
|
}
|
||||||
|
// 解析body字段
|
||||||
|
// 字段与其值用‘=’连接;在数据区中,同一项目的不同分类值间用‘,’来分隔,不同项目之间用‘;’来分隔。
|
||||||
|
Map<String, String> map = new HashMap<String, String>();
|
||||||
|
|
||||||
|
String[] bodyItems = Strings.split(body.substring(0,body.length()-2), ';');
|
||||||
|
for (String item : bodyItems) {
|
||||||
|
if(item.contains(",")) {
|
||||||
|
String[] itemBodys = Strings.split(item, ',');
|
||||||
|
for (String subItem : itemBodys) {
|
||||||
|
if(subItem.contains("=")) {
|
||||||
|
int indexOp = subItem.indexOf('=');
|
||||||
|
map.put(subItem.substring(0, indexOp), subItem.substring(indexOp + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else if(item.contains("=")) {
|
||||||
|
int indexOp = item.indexOf('=');
|
||||||
|
map.put(item.substring(0, indexOp), item.substring(indexOp + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Hj212FrameInputVo value = new Hj212FrameInputVo();
|
||||||
|
|
||||||
|
value.setCn(map.get("CN"));
|
||||||
|
value.setQn(map.get("QN"));
|
||||||
|
value.setSt(map.get("ST"));
|
||||||
|
value.setPw(map.get("PW"));
|
||||||
|
value.setMn(map.get("MN"));
|
||||||
|
if(map.containsKey("Flag")){
|
||||||
|
value.setFlag(Integer.valueOf(map.get("Flag")));
|
||||||
|
}
|
||||||
|
value.setCp(map.get("CP").substring(2));
|
||||||
|
|
||||||
|
// &&DataTime=20190425110800
|
||||||
|
int indexDt = value.getCp().indexOf("DataTime");
|
||||||
|
if(indexDt >= 0) {
|
||||||
|
value.setDataTime(Long.valueOf(value.getCp().substring(indexDt + 9, indexDt + 9 + 14)));
|
||||||
|
}
|
||||||
|
|
||||||
|
map.remove("CN");
|
||||||
|
map.remove("QN");
|
||||||
|
map.remove("ST");
|
||||||
|
map.remove("PW");
|
||||||
|
map.remove("MN");
|
||||||
|
map.remove("Flag");
|
||||||
|
map.remove("CP");
|
||||||
|
|
||||||
|
value.setDataMap(map);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// 实时数据
|
||||||
|
// String input = "##0365QN=20190425110900000;ST=22;CN=2011;PW=123456;MN=01004190001003;Flag=5;CP=&&DataTime=20190425110800;a01001-Rtd=0.0,a01001-Flag=N;a01002-Rtd=0.0,a01002-Flag=N;a01006-Rtd=101.09,a01006-Flag=N;a01007-Rtd=0.0,a01007-Flag=N;a01008-Rtd=0,a01008-Flag=N;a34001-Rtd=0.0,a34001-Flag=N;a34002-Rtd=17.8,a34002-Flag=N;a34004-Rtd=7.7,a34004-Flag=N;a50001-Rtd=30.0,a50001-Flag=N;&&0880\r\n";
|
||||||
|
// String input="##0102QN=20211207181139971;ST=31;CN=1011;PW=123456;MN=YFLGZXJCLT0003;Flag=1;CP=&&SystemTime=20211207181139&&4980\r\n";
|
||||||
|
// String input="##0453QN=20211207181137957;ST=31;CN=2051;PW=123456;MN=YFLGZXJCLT0003;CP=&&DataTime=20211207180000;01-ZsAvg=1.38,01-ZsMin=1.25,01-ZsMax=1.54,01-Cou=0.18,01-Avg=1.38,01-Min=1.25,01-Max=1.54;B02-Cou=130926.47,B02-Avg=218.21,B02-Min=206.41,B02-Max=230.95;S03-Avg=16.38,S03-Min=16.30,S03-Max=16.44;S05-Avg=2.31,S05-Min=2.31,S05-Max=2.32;S08-Avg=-0.16,S08-Min=-0.17,S08-Max=-0.14;S02-Avg=12.08,S02-Min=11.42,S02-Max=12.79;S01-Avg=21.17,S01-Min=21.16,S01-Max=21.18&&5280\r\n";
|
||||||
|
// String input="##0279QN=20211207181240386;ST=31;CN=2011;PW=123456;MN=YFLGZXJCLT0003;CP=&&DataTime=20211207181148;01-ZsRtd=1.32,01-Rtd=1.32,01-Flag=N;B02-Rtd=225.99,B02-Flag=N;S03-Rtd=16.29,S03-Flag=N;S05-Rtd=2.31,S05-Flag=N;S08-Rtd=-0.16,S08-Flag=N;S02-Rtd=12.51,S02-Flag=N;S01-Rtd=21.16,S01-Flag=N&&7940\r\n";
|
||||||
|
// String input="##0275QN=20211208195054384;ST=31;CN=2011;PW=123456;MN=SD371300004744;CP=&&DataTime=20211208194952;01-ZsRtd=0.52,01-Rtd=0.52,01-Flag=N;B02-Rtd=38.10,B02-Flag=N;S03-Rtd=8.66,S03-Flag=N;S05-Rtd=1.23,S05-Flag=N;S08-Rtd=0.00,S08-Flag=N;S02-Rtd=1.20,S02-Flag=N;S01-Rtd=21.61,S01-Flag=N&&4040\r\n";
|
||||||
|
// String input="##0102QN=20211208194951184;ST=31;CN=1011;PW=123456;MN=SD371300004744;Flag=1;CP=&&SystemTime=20211208194951&&7F80\r\n";
|
||||||
|
// String input="##0275QN=20211208194952060;ST=31;CN=2011;PW=123456;MN=SD371300004744;CP=&&DataTime=20211208194853;01-ZsRtd=0.52,01-Rtd=0.52,01-Flag=N;B02-Rtd=38.09,B02-Flag=N;S03-Rtd=8.65,S03-Flag=N;S05-Rtd=1.26,S05-Flag=N;S08-Rtd=0.00,S08-Flag=N;S02-Rtd=1.20,S02-Flag=N;S01-Rtd=21.61,S01-Flag=N&&5000\r\n";
|
||||||
|
String input="##0441QN=20211208195157432;ST=31;CN=2051;PW=123456;MN=SD371300004744;CP=&&DataTime=20211208194000;01-ZsAvg=0.52,01-ZsMin=0.52,01-ZsMax=0.52,01-Cou=0.01,01-Avg=0.52,01-Min=0.52,01-Max=0.52;B02-Cou=22469.20,B02-Avg=37.45,B02-Min=34.90,B02-Max=38.10;S03-Avg=8.66,S03-Min=8.65,S03-Max=8.68;S05-Avg=1.27,S05-Min=1.23,S05-Max=1.29;S08-Avg=0.00,S08-Min=-0.01,S08-Max=0.00;S02-Avg=1.18,S02-Min=1.10,S02-Max=1.20;S01-Avg=21.61,S01-Min=21.60,S01-Max=21.62&&F9C1\r\n";
|
||||||
|
ByteBuf wrappedBuffer = Unpooled.wrappedBuffer(input.getBytes(CRC16Util.UTF8));
|
||||||
|
|
||||||
|
Hj212FrameInputVo decode = Hj212VoDecode.Decode(wrappedBuffer);
|
||||||
|
wrappedBuffer.release();
|
||||||
|
System.out.println(JSON.toJSONString(decode));
|
||||||
|
|
||||||
|
// String inputDay = "##0638QN=20190425104000000;ST=22;CN=2051;PW=123456;MN=0100410001003;Flag=5;CP=&&DataTime=20190425104000;a01001-Min=0.0,a01001-Avg=0.0,a01001-Max=0.0,a01001-Flag=N;a01002-Min=0.0,a01002-Avg=0.0,a01002-Max=0.0,a01002-Flag=N;a01006-Min=0.00,a01006-Avg=101.08,a01006-Max=101.08,a01006-Flag=N;a01007-Min=0.0,a01007-Avg=0.0,a01007-Max=0.0,a01007-Flag=N;a01008-Min=0,a01008-Avg=0,a01008-Max=0,a01008-Flag=N;a34001-Min=0.0,a34001-Avg=0.0,a34001-Max=0.0,a34001-Flag=N;a34002-Min=0.0,a34002-Avg=21.6,a34002-Max=35.2,a34002-Flag=N;a34004-Min=0.0,a34004-Avg=10.8,a34004-Max=22.7,a34004-Flag=N;a50001-Min=0.0,a50001-Avg=30.0,a50001-Max=30.0,a50001-Flag=N;&&5B40\r\n";
|
||||||
|
// wrappedBuffer = Unpooled.wrappedBuffer(inputDay.getBytes(CRC16Util.UTF8));
|
||||||
|
// decode = Hj212VoDecode.Decode(wrappedBuffer);
|
||||||
|
// wrappedBuffer.release();
|
||||||
|
// System.out.println(JSON.toJSONString(decode));
|
||||||
|
|
||||||
|
|
||||||
|
// // 实时数据
|
||||||
|
// String inputTest = "##0365QN=20190425110900000;ST=22;CN=2011;PW=123456;MN=01004190001003;Flag=5;CP=&&DataTime=20190425110800;a01001-Rtd=0.0,a01001-Flag=N;a01002-Rtd=0.0,a01002-Flag=N;a01006-Rtd=101.09,a01006-Flag=N;a01007-Rtd=0.0,a01007-Flag=N;a01008-Rtd=0,a01008-Flag=N;a34001-Rtd=0.0,a34001-Flag=N;a34002-Rtd=17.8,a34002-Flag=N;a34004-Rtd=7.7,a34004-Flag=N;a50001-Rtd=30.0,a50001-Flag=N;&&0880\r\n";
|
||||||
|
// byte[] inputTestBytes = inputTest.getBytes(CRC16Util.UTF8);
|
||||||
|
// String hexString = HexUtils.toHexString(inputTestBytes);
|
||||||
|
// System.out.print(hexString);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
package com.cisdi.data.HJ212.gateway;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class Hj212VoEncoder {
|
||||||
|
private static DateFormat qnFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
|
||||||
|
|
||||||
|
public static byte[] encode(String st, String cn, String pw, String mn) {
|
||||||
|
String flag = "4";
|
||||||
|
|
||||||
|
String asciiString = combineAsciiString(null, st, cn, pw, mn, flag);
|
||||||
|
|
||||||
|
return asciiString.getBytes(StandardCharsets.US_ASCII);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String combineAsciiString(String qn, String st, String cn, String pw, String mn, String flag) {
|
||||||
|
Date date = new Date();
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append(String.format("QN=%s;", qn == null ? qnFormat.format(date) : qn));
|
||||||
|
builder.append(String.format("ST=%s;", st));
|
||||||
|
builder.append(String.format("CN=%s;", cn));
|
||||||
|
builder.append(String.format("PW=%s;", pw));
|
||||||
|
builder.append(String.format("MN=%s;", mn));
|
||||||
|
builder.append(String.format("Flag=%s;", flag));
|
||||||
|
builder.append("CP=&&&&");
|
||||||
|
|
||||||
|
String dataBody = builder.toString();
|
||||||
|
int dataLength = builder.toString().length();
|
||||||
|
|
||||||
|
builder.insert(0, String.format("##%04d", dataLength));
|
||||||
|
String crc16 = CRC16Util.CRC16(dataBody);
|
||||||
|
builder.append(crc16 + "\r\n");
|
||||||
|
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
String combine1 = combineAsciiString("20190425110917290", "22", "9014", "123456", "01004190001003", "4");
|
||||||
|
System.out.println(combine1);
|
||||||
|
|
||||||
|
String combine2 = combineAsciiString("20190425110913469", "22", "9014", "123456", "0100410001003", "4");
|
||||||
|
System.out.println(combine2);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package com.cisdi.data.HJ212.gateway;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.cisdi.data.HJ212.YfHj212SocketGateway;
|
||||||
|
import com.cisdi.data.sdk.enums.ByteOrder;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.SessionFactory;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.TcpIoService;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.DefaultTcpIoService;
|
||||||
|
import com.cisdi.data.sdk.vo.GatewayVo;
|
||||||
|
|
||||||
|
public class StartHj212Test {
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(YfHj212SocketGateway.class);
|
||||||
|
|
||||||
|
private static TcpIoService ioService = null;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private static SessionFactory sessionFactory = null;
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
DefaultTcpIoService defaultIoService = new DefaultTcpIoService();
|
||||||
|
SessionFactory factory = new Hj212SessionFactory("10000022");
|
||||||
|
|
||||||
|
factory.init(null, null);
|
||||||
|
|
||||||
|
Hj212ChannelInitializer<Hj212FrameInputVo> channelInitializer =
|
||||||
|
new Hj212ChannelInitializer<Hj212FrameInputVo>(factory);
|
||||||
|
|
||||||
|
GatewayVo instanceVo = new GatewayVo();
|
||||||
|
instanceVo.setByteOrder(ByteOrder.BIGENDIAN);
|
||||||
|
instanceVo.setParameter("{\"listenIp\":\"0.0.0.0\",\"listenPort\":9010,\"threadSize\":50,\"timeout\":2000}");
|
||||||
|
|
||||||
|
defaultIoService.init(instanceVo, factory, channelInitializer);
|
||||||
|
|
||||||
|
ioService = defaultIoService;
|
||||||
|
sessionFactory = factory;
|
||||||
|
|
||||||
|
boolean open = ioService.open();
|
||||||
|
|
||||||
|
if(open == true) {
|
||||||
|
|
||||||
|
AtomicBoolean shouldRun = new AtomicBoolean(true);
|
||||||
|
AliveCheckTask task = new AliveCheckTask(120, shouldRun, factory);
|
||||||
|
|
||||||
|
Thread thread = new Thread(task, "Hj212-alive-check-thread");
|
||||||
|
thread.start();
|
||||||
|
|
||||||
|
logger.info("Hj212网关启动成功");
|
||||||
|
}else {
|
||||||
|
logger.info("Hj212网关启动失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(10000000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,100 @@
|
|||||||
|
package com.cisdi.data.IDCardReader;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.cisdi.data.IDCardReader.gateway.impl.ZKIDROnlineClient;
|
||||||
|
import com.cisdi.data.IDCardReader.gateway.impl.ZKIDROnlineListener;
|
||||||
|
import com.cisdi.data.IDCardReader.gateway.vo.ZKIDROnlineConfigVo;
|
||||||
|
import com.cisdi.data.IDCardReader.gateway.vo.ZKIDROnlineResponseVo;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import com.cisdi.data.emserver.EmiaProSocketGateway;
|
||||||
|
import com.cisdi.data.sdk.consts.ServiceName;
|
||||||
|
import com.cisdi.data.sdk.enums.GatewayState;
|
||||||
|
import com.cisdi.data.sdk.gateway.base.SocketGatewayBase;
|
||||||
|
import com.cisdi.data.sdk.param.ListenSocketParam;
|
||||||
|
import com.cisdi.data.sdk.procotol.message.SocketReturnMessage;
|
||||||
|
import com.cisdi.data.sdk.service.RouteService;
|
||||||
|
import com.cisdi.data.sdk.vo.DeviceVo;
|
||||||
|
import com.cisdi.data.sdk.vo.ExeResultVo;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class IDCardReaderGateway extends SocketGatewayBase {
|
||||||
|
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(IDCardReaderGateway.class);
|
||||||
|
private ZKIDROnlineClient zkidrOnlineClient=null;
|
||||||
|
private String deviceId;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExeResultVo sendReturnMessage(SocketReturnMessage returnMsg) {
|
||||||
|
ExeResultVo resultVo = new ExeResultVo();
|
||||||
|
resultVo.setMessage("该协议不允许下发数据");
|
||||||
|
resultVo.setSuccess(false);
|
||||||
|
logger.info("网关:{}->设备,消息:{},结果:{}",instanceVo.getRunId(), returnMsg, resultVo);
|
||||||
|
return resultVo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
if (state == GatewayState.RUNNING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ListenSocketParam socketParam = JSON.parseObject(getInstanceVo().getParameter(), ListenSocketParam.class);
|
||||||
|
|
||||||
|
String otherParameter = socketParam.getOtherParameter();
|
||||||
|
ZKIDROnlineConfigVo zkidrOnlineConfigVo = null;
|
||||||
|
// 处理分组
|
||||||
|
if (StringUtils.isNotBlank(otherParameter)) {
|
||||||
|
zkidrOnlineConfigVo = JSON.parseObject(otherParameter, ZKIDROnlineConfigVo.class);
|
||||||
|
}
|
||||||
|
if (zkidrOnlineConfigVo == null) {
|
||||||
|
throw new BusinessException("网关Id:" + instanceVo.getRunId() + "为ZKIDROnline网关,请配置正确的ZKIDROnline配置");
|
||||||
|
}
|
||||||
|
|
||||||
|
RouteService routeService = (RouteService) serviceProvider.getByName(ServiceName.Route);
|
||||||
|
List<DeviceVo> deviceVos = routeService.findByRunId(instanceVo.getRunId());
|
||||||
|
|
||||||
|
if (deviceVos.size() > 1) {
|
||||||
|
throw new BusinessException("网关Id:" + instanceVo.getRunId() + "为ZKIDROnline网关,只允许关联一个设备Id");
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceId = deviceVos.size() > 0 ? deviceVos.get(0).getDeviceId() : null;
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(deviceId)) {
|
||||||
|
throw new BusinessException("runId=" + getInstanceVo().getRunId() + "未正确配置网关和设备关联");
|
||||||
|
}
|
||||||
|
logger.info("ZKIDROnline网关:{}读取启动配置参数:{}", instanceVo.getRunId(), getInstanceVo().getParameter());
|
||||||
|
|
||||||
|
zkidrOnlineClient=new ZKIDROnlineClient(deviceId,serviceProvider,this,zkidrOnlineConfigVo);
|
||||||
|
Thread thread=new Thread(zkidrOnlineClient);
|
||||||
|
thread.start();
|
||||||
|
state = GatewayState.RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
if (state == GatewayState.CLOSED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(zkidrOnlineClient.close())
|
||||||
|
{
|
||||||
|
state=GatewayState.CLOSED;
|
||||||
|
logger.info("网关:" + instanceVo.getRunId() + "关闭成功", instanceVo.getRunId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getActiveDeviceIds() {
|
||||||
|
Set<String> set = Sets.newConcurrentHashSet();
|
||||||
|
|
||||||
|
if (StringUtils.isNotEmpty(deviceId)) {
|
||||||
|
set.add(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,80 @@
|
|||||||
|
package com.cisdi.data.IDCardReader.gateway.impl;
|
||||||
|
|
||||||
|
import com.cisdi.data.IDCardReader.gateway.vo.ZKIDROnlineConfigVo;
|
||||||
|
import com.cisdi.data.sdk.gateway.base.SocketGatewayBase;
|
||||||
|
import com.cisdi.data.sdk.service.ServiceProvider;
|
||||||
|
import org.java_websocket.client.WebSocketClient;
|
||||||
|
import org.java_websocket.drafts.Draft;
|
||||||
|
import org.java_websocket.handshake.ServerHandshake;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
public class ZKIDROnlineClient implements Runnable{
|
||||||
|
|
||||||
|
private String deviceId;
|
||||||
|
ServiceProvider serviceProvider;
|
||||||
|
SocketGatewayBase socketGateway;
|
||||||
|
private ZKIDROnlineConfigVo zkidrOnlineConfigVo;
|
||||||
|
private ZKIDROnlineListener zkidrOnlineListener=null;
|
||||||
|
private Logger logger= LoggerFactory.getLogger(ZKIDROnlineClient.class);
|
||||||
|
private AtomicBoolean shouldRun=new AtomicBoolean(true);
|
||||||
|
|
||||||
|
private Boolean isOpen=false;
|
||||||
|
|
||||||
|
public Boolean getOpen() {
|
||||||
|
return isOpen;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean close()
|
||||||
|
{
|
||||||
|
zkidrOnlineListener.setShouldRun(false);
|
||||||
|
shouldRun.set(false);
|
||||||
|
return zkidrOnlineListener.endListen();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZKIDROnlineClient(String deviceId, ServiceProvider serviceProvider, SocketGatewayBase socketGateway, ZKIDROnlineConfigVo zkidrOnlineConfigVo) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
this.serviceProvider = serviceProvider;
|
||||||
|
this.socketGateway = socketGateway;
|
||||||
|
this.zkidrOnlineConfigVo = zkidrOnlineConfigVo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (shouldRun.get())
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
zkidrOnlineListener=new ZKIDROnlineListener(new URI(zkidrOnlineConfigVo.getUri()),deviceId,socketGateway,serviceProvider,zkidrOnlineConfigVo);
|
||||||
|
logger.info("ZKIDROnline网关:{}启动成功 参数:{}", socketGateway.getInstanceVo().getRunId(), socketGateway.getInstanceVo().getParameter());
|
||||||
|
break;
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
logger.error("连接ID:"+socketGateway.getInstanceVo().getRunId()+",设备ID:"+deviceId+",自动重连设置:"+zkidrOnlineConfigVo.getAutoReconnect()+"启动失败,错误原因:"+e.getMessage());
|
||||||
|
try {
|
||||||
|
Thread.sleep(zkidrOnlineConfigVo.getReconnectDelay());
|
||||||
|
} catch (InterruptedException e1) {
|
||||||
|
e1.printStackTrace();
|
||||||
|
}
|
||||||
|
if(zkidrOnlineConfigVo.getAutoReconnect())
|
||||||
|
{
|
||||||
|
logger.info("连接ID:"+socketGateway.getInstanceVo().getRunId()+",设备ID:"+deviceId+",自动重连设置:"+zkidrOnlineConfigVo.getAutoReconnect()+"启动失败,正在重连");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.info("ZKIDROnline网关:{}启动失败 参数:{}", socketGateway.getInstanceVo().getRunId(), socketGateway.getInstanceVo().getParameter());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(zkidrOnlineListener!=null) {
|
||||||
|
zkidrOnlineListener.start(false);
|
||||||
|
isOpen=true;
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,224 @@
|
|||||||
|
package com.cisdi.data.IDCardReader.gateway.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.cisdi.data.IDCardReader.gateway.vo.IDCardVo;
|
||||||
|
import com.cisdi.data.IDCardReader.gateway.vo.ZKIDROnlineConfigVo;
|
||||||
|
import com.cisdi.data.IDCardReader.gateway.vo.ZKIDROnlineResponseVo;
|
||||||
|
import com.cisdi.data.sdk.consts.ServiceName;
|
||||||
|
import com.cisdi.data.sdk.gateway.Gateway;
|
||||||
|
import com.cisdi.data.sdk.gateway.base.GatewayBase;
|
||||||
|
import com.cisdi.data.sdk.gateway.base.SocketGatewayBase;
|
||||||
|
import com.cisdi.data.sdk.gateway.message.SocketMessage;
|
||||||
|
import com.cisdi.data.sdk.service.SendService;
|
||||||
|
import com.cisdi.data.sdk.service.ServiceProvider;
|
||||||
|
import org.java_websocket.WebSocket;
|
||||||
|
import org.java_websocket.client.WebSocketClient;
|
||||||
|
import org.java_websocket.handshake.ServerHandshake;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
public class ZKIDROnlineListener extends WebSocketClient {
|
||||||
|
|
||||||
|
private Integer reconnectCount=0;
|
||||||
|
|
||||||
|
private String runId;
|
||||||
|
private String deviceId;
|
||||||
|
private Boolean autoReconnect=false;
|
||||||
|
private Long reconnectDelay =1000L;
|
||||||
|
private ServiceProvider serviceProvider=null;
|
||||||
|
private SocketGatewayBase socketGatewayBase=null;
|
||||||
|
private Logger logger= LoggerFactory.getLogger(ZKIDROnlineListener.class);
|
||||||
|
private ZKIDROnlineConfigVo zkidrOnlineConfigVo=null;
|
||||||
|
private Boolean startFlag=false;
|
||||||
|
private static final String SUCCESS_STR="BeginReadCard Succsefull";
|
||||||
|
private AtomicBoolean shouldRun=new AtomicBoolean(true);
|
||||||
|
|
||||||
|
public void setShouldRun(boolean b)
|
||||||
|
{
|
||||||
|
shouldRun.set(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZKIDROnlineListener(URI serverUri,
|
||||||
|
String deviceId,
|
||||||
|
SocketGatewayBase socketGateway,
|
||||||
|
ServiceProvider serviceProvider,
|
||||||
|
ZKIDROnlineConfigVo zkidrOnlineConfigVo) {
|
||||||
|
super(serverUri);
|
||||||
|
if(socketGateway!=null)
|
||||||
|
{
|
||||||
|
this.runId=socketGateway.getInstanceVo().getRunId();
|
||||||
|
}
|
||||||
|
if(zkidrOnlineConfigVo!=null)
|
||||||
|
{
|
||||||
|
this.autoReconnect=zkidrOnlineConfigVo.getAutoReconnect();
|
||||||
|
this.reconnectDelay =zkidrOnlineConfigVo.getReconnectDelay();
|
||||||
|
}
|
||||||
|
this.deviceId=deviceId;
|
||||||
|
this.socketGatewayBase=socketGateway;
|
||||||
|
this.serviceProvider=serviceProvider;
|
||||||
|
this.zkidrOnlineConfigVo=zkidrOnlineConfigVo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean endListen()
|
||||||
|
{
|
||||||
|
startFlag=false;
|
||||||
|
autoReconnect=false;
|
||||||
|
this.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean start(boolean reconnect)
|
||||||
|
{
|
||||||
|
startFlag=false;
|
||||||
|
while (shouldRun.get())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(this.getReadyState().equals(READYSTATE.NOT_YET_CONNECTED))
|
||||||
|
{
|
||||||
|
logger.info("连接ID:"+runId+",设备ID:"+deviceId+",自动重连设置:"+autoReconnect+"状态为:"+this.getReadyState()+"准备尝试连接");
|
||||||
|
if(!this.connectBlocking())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
logger.info("连接ID:"+runId+",设备ID:"+deviceId+",自动重连设置:"+autoReconnect+"正在发送启动消息:"+zkidrOnlineConfigVo.getStartMsg());
|
||||||
|
this.send(zkidrOnlineConfigVo.getStartMsg());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if(this.getReadyState().equals(READYSTATE.CLOSED)||this.getReadyState().equals(READYSTATE.CLOSING))
|
||||||
|
{
|
||||||
|
logger.info("连接ID:"+runId+",设备ID:"+deviceId+",自动重连设置:"+autoReconnect+"状态为:"+this.getReadyState()+"准备尝试重连");
|
||||||
|
if(!this.reconnectBlocking())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
logger.info("连接ID:"+runId+",设备ID:"+deviceId+",自动重连设置:"+autoReconnect+"正在发送启动消息:"+zkidrOnlineConfigVo.getStartMsg());
|
||||||
|
this.send(zkidrOnlineConfigVo.getStartMsg());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.error("连接ID:"+socketGatewayBase.getInstanceVo().getRunId()+",设备ID:"+deviceId+",自动重连设置:"+zkidrOnlineConfigVo.getAutoReconnect()+"启动失败,错误原因:"+e.getLocalizedMessage());
|
||||||
|
try {
|
||||||
|
Thread.sleep(zkidrOnlineConfigVo.getReconnectDelay());
|
||||||
|
} catch (InterruptedException e1) {
|
||||||
|
e1.printStackTrace();
|
||||||
|
}
|
||||||
|
if(reconnect)
|
||||||
|
{
|
||||||
|
logger.info("连接ID:"+socketGatewayBase.getInstanceVo().getRunId()+",设备ID:"+deviceId+",自动重连设置:"+zkidrOnlineConfigVo.getAutoReconnect()+"启动失败,正在重连");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOpen(ServerHandshake handshakedata) {
|
||||||
|
logger.info("连接ID:"+runId+",设备ID:"+deviceId+",自动重连设置:"+autoReconnect+"已经打开连接");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMessage(String message) {
|
||||||
|
if(startFlag)
|
||||||
|
{
|
||||||
|
IDCardVo idCardVo=null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
idCardVo= JSON.parseObject(message,IDCardVo.class);
|
||||||
|
idCardVo.getCertificate().setReadID(deviceId);
|
||||||
|
idCardVo.getCertificate().setReadTime(System.currentTimeMillis()+"");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.error("连接ID:"+runId+",设备ID:"+deviceId+",自动重连设置:"+autoReconnect+"解析数据发生异常:"+e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(idCardVo!=null&&serviceProvider!=null&&socketGatewayBase!=null)
|
||||||
|
{
|
||||||
|
SendService service = (SendService)serviceProvider.getByName(ServiceName.Send);
|
||||||
|
SocketMessage socketMessage = socketGatewayBase.buildSocketMessage();
|
||||||
|
socketMessage.setDeviceId(this.deviceId);
|
||||||
|
socketMessage.setMsgKey("default");
|
||||||
|
socketMessage.setData(JSON.toJSONString(idCardVo.getCertificate()).getBytes());
|
||||||
|
socketMessage.getPropsMap().put("charset", Charset.forName("GBK"));
|
||||||
|
service.sendMessage(socketMessage);
|
||||||
|
if(socketGatewayBase.getInstanceVo().getLogOpen())
|
||||||
|
{
|
||||||
|
logger.error("连接ID:"+runId+",设备ID:"+deviceId+",自动重连设置:"+autoReconnect+"收到数据:"+idCardVo.getCertificate());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ZKIDROnlineResponseVo zkidrOnlineResponseVo=null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
zkidrOnlineResponseVo= JSON.parseObject(message,ZKIDROnlineResponseVo.class);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.error("连接ID:"+runId+",设备ID:"+deviceId+",自动重连设置:"+autoReconnect+"收到无法解析的数据:"+message);
|
||||||
|
}
|
||||||
|
if(zkidrOnlineResponseVo!=null&&SUCCESS_STR.equals(zkidrOnlineResponseVo.getData()))
|
||||||
|
{
|
||||||
|
logger.info("连接ID:"+runId+",设备ID:"+deviceId+",自动重连设置:"+autoReconnect+"请求自动获取身份证信息成功");
|
||||||
|
startFlag=true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//this.close();
|
||||||
|
this.start(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClose(int code, String reason, boolean remote) {
|
||||||
|
if(startFlag&&remote)
|
||||||
|
{
|
||||||
|
logger.info("连接ID:"+runId+",设备ID:"+deviceId+",自动重连设置:"+autoReconnect+"正在尝试重连");
|
||||||
|
//this.close();
|
||||||
|
this.start(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.info("连接ID:"+runId+",设备ID:"+deviceId+",自动重连设置:"+autoReconnect+"正在关闭连接");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Exception ex) {
|
||||||
|
logger.error("连接ID:"+runId+",设备ID:"+deviceId+",自动重连设置:"+autoReconnect+"发生异常:"+ex.getLocalizedMessage());
|
||||||
|
if(autoReconnect)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.sleep(reconnectDelay);
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
logger.info("连接ID:"+runId+",设备ID:"+deviceId+",自动重连设置:"+autoReconnect+"正在尝试重连");
|
||||||
|
//this.close();
|
||||||
|
this.start(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger.warn("连接ID:"+runId+",设备ID:"+deviceId+",自动重连设置:"+autoReconnect+"未配置重连,连接关闭");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
package com.cisdi.data.IDCardReader.gateway.vo;
|
||||||
|
|
||||||
|
public class IDCardVo {
|
||||||
|
public class IDCardDataVo{
|
||||||
|
private String IDNumber;
|
||||||
|
private String Name;
|
||||||
|
private String ReadID;
|
||||||
|
private String ReadTime;
|
||||||
|
|
||||||
|
public String getIDNumber() {
|
||||||
|
return IDNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIDNumber(String IDNumber) {
|
||||||
|
this.IDNumber = IDNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReadID() {
|
||||||
|
return ReadID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReadID(String readID) {
|
||||||
|
ReadID = readID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReadTime() {
|
||||||
|
return ReadTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReadTime(String readTime) {
|
||||||
|
ReadTime = readTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private Integer ret;
|
||||||
|
private IDCardDataVo Certificate;
|
||||||
|
|
||||||
|
public Integer getRet() {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRet(Integer ret) {
|
||||||
|
this.ret = ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDCardDataVo getCertificate() {
|
||||||
|
return Certificate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCertificate(IDCardDataVo certificate) {
|
||||||
|
Certificate = certificate;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package com.cisdi.data.IDCardReader.gateway.vo;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
|
||||||
|
public class ZKIDROnlineConfigVo {
|
||||||
|
private String uri;
|
||||||
|
private Boolean autoReconnect;
|
||||||
|
private String startMsg;
|
||||||
|
private Long reconnectDelay;
|
||||||
|
|
||||||
|
public String getStartMsg() {
|
||||||
|
return startMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStartMsg(String startMsg) {
|
||||||
|
this.startMsg = startMsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getReconnectDelay() {
|
||||||
|
return reconnectDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReconnectDelay(Long reconnectDelay) {
|
||||||
|
this.reconnectDelay = reconnectDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUri() {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUri(String uri) {
|
||||||
|
this.uri = uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getAutoReconnect() {
|
||||||
|
return autoReconnect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutoReconnect(Boolean autoReconnect) {
|
||||||
|
this.autoReconnect = autoReconnect;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package com.cisdi.data.IDCardReader.gateway.vo;
|
||||||
|
|
||||||
|
public class ZKIDROnlineResponseVo {
|
||||||
|
private String data;
|
||||||
|
private String dev;
|
||||||
|
private String ret;
|
||||||
|
|
||||||
|
public String getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setData(String data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDev() {
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDev(String dev) {
|
||||||
|
this.dev = dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRet() {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRet(String ret) {
|
||||||
|
this.ret = ret;
|
||||||
|
}
|
||||||
|
}
|
145
src/main/java/com/cisdi/data/OBLF/OBLFSocketGateway.java
Normal file
145
src/main/java/com/cisdi/data/OBLF/OBLFSocketGateway.java
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
package com.cisdi.data.OBLF;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.cisdi.data.OBLF.impl.OBLFChannelInitializer;
|
||||||
|
import com.cisdi.data.OBLF.impl.OBLFIoSession;
|
||||||
|
import com.cisdi.data.OBLF.impl.OBLFSessionFactory;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import com.cisdi.data.sdk.consts.ServiceName;
|
||||||
|
import com.cisdi.data.sdk.enums.GatewayState;
|
||||||
|
import com.cisdi.data.sdk.gateway.base.SocketGatewayBase;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.IoSession;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.SessionFactory;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.TcpIoService;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.DefaultTcpIoService;
|
||||||
|
import com.cisdi.data.sdk.param.ListenSocketParam;
|
||||||
|
import com.cisdi.data.sdk.procotol.message.SocketReturnMessage;
|
||||||
|
import com.cisdi.data.sdk.service.PlatformService;
|
||||||
|
import com.cisdi.data.sdk.service.RouteService;
|
||||||
|
import com.cisdi.data.sdk.vo.DeviceVo;
|
||||||
|
import com.cisdi.data.sdk.vo.ExeResultVo;
|
||||||
|
import com.cisdi.data.sdk.vo.SslConfigVo;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cuianbing
|
||||||
|
* @version 1.0
|
||||||
|
* @description: 炼钢OBLF750设备
|
||||||
|
* @date 2021/7/21 11:33
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class OBLFSocketGateway extends SocketGatewayBase {
|
||||||
|
|
||||||
|
|
||||||
|
TcpIoService ioService = null;
|
||||||
|
SessionFactory sessionFactory = null;
|
||||||
|
|
||||||
|
// 当配置为单个设备模式时,此为该设备id
|
||||||
|
String onlyOneDeviceId = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExeResultVo sendReturnMessage(SocketReturnMessage socketReturnMessage) {
|
||||||
|
throw new BusinessException("OBLF750不支持下发服务!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
if (state == GatewayState.RUNNING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log.info("网关:{}读取启动配置参数:{},是否支持支持多个设备:{}", instanceVo.getRunId(), instanceVo.getParameter(),
|
||||||
|
instanceVo.getSuportMultiDevice());
|
||||||
|
|
||||||
|
|
||||||
|
// 不支持多个设备,必须强制配置一个设备id
|
||||||
|
if (instanceVo.getSuportMultiDevice() != null && instanceVo.getSuportMultiDevice() == false) {
|
||||||
|
RouteService routeService = (RouteService) serviceProvider.getByName(ServiceName.Route);
|
||||||
|
List<DeviceVo> deviceVos = routeService.findByRunId(instanceVo.getRunId());
|
||||||
|
|
||||||
|
if (deviceVos.size() > 1) {
|
||||||
|
throw new BusinessException("网关Id:" + instanceVo.getRunId() + "为OBLF750网关,当前配置为只支持单个设备,但配置了多个设备。");
|
||||||
|
}
|
||||||
|
|
||||||
|
onlyOneDeviceId = deviceVos.size() > 0 ? deviceVos.get(0).getDeviceId() : null;
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(onlyOneDeviceId)) {
|
||||||
|
throw new BusinessException("runId=" + getInstanceVo().getRunId() + "未正确配置网关和设备关联");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DefaultTcpIoService defaultIoService = new DefaultTcpIoService();
|
||||||
|
SessionFactory factory = new OBLFSessionFactory(onlyOneDeviceId);
|
||||||
|
factory.init(serviceProvider, this);
|
||||||
|
|
||||||
|
SslConfigVo sslConfigVo = null;
|
||||||
|
|
||||||
|
ListenSocketParam socketParam = JSON.parseObject(getInstanceVo().getParameter(), ListenSocketParam.class);
|
||||||
|
|
||||||
|
if (socketParam != null && Boolean.TRUE.equals(socketParam.getEnableSsl())) {
|
||||||
|
|
||||||
|
PlatformService platformService = (PlatformService) serviceProvider.getByName(ServiceName.Platform);
|
||||||
|
|
||||||
|
sslConfigVo = platformService.getSslConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
OBLFChannelInitializer channelInitializer =
|
||||||
|
new OBLFChannelInitializer(factory, getInstanceVo().getByteOrder(), sslConfigVo);
|
||||||
|
|
||||||
|
defaultIoService.init(instanceVo, factory, channelInitializer);
|
||||||
|
|
||||||
|
ioService = defaultIoService;
|
||||||
|
sessionFactory = factory;
|
||||||
|
|
||||||
|
boolean open = ioService.open();
|
||||||
|
|
||||||
|
if (open == true) {
|
||||||
|
state = GatewayState.RUNNING;
|
||||||
|
log.info("OBLF750网关:{}启动成功 参数:{}", instanceVo.getRunId(), getInstanceVo().getParameter());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
log.info("OBLF750网关:{}启动失败 参数:{}", instanceVo.getRunId(), getInstanceVo().getParameter());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
if (state == GatewayState.CLOSED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sessionFactory != null) {
|
||||||
|
for (IoSession ioSession : sessionFactory.getSessions()) {
|
||||||
|
OBLFIoSession XrfIoSession = (OBLFIoSession) ioSession;
|
||||||
|
XrfIoSession.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean close = ioService.close();
|
||||||
|
if (close == true) {
|
||||||
|
sessionFactory = null;
|
||||||
|
state = GatewayState.CLOSED;
|
||||||
|
log.info("OBLF750网关:{}关闭成功", instanceVo.getRunId());
|
||||||
|
} else {
|
||||||
|
log.info("OBLF750网关:{}关闭失败", instanceVo.getRunId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getActiveDeviceIds() {
|
||||||
|
if (onlyOneDeviceId != null) {
|
||||||
|
Set<String> set = new HashSet<String>();
|
||||||
|
set.add(onlyOneDeviceId);
|
||||||
|
return set;
|
||||||
|
} else {
|
||||||
|
return sessionFactory.getActiveDeviceIds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
package com.cisdi.data.OBLF.impl;
|
||||||
|
|
||||||
|
import com.cisdi.data.sdk.enums.ByteOrder;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.SessionFactory;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.AbstractChannelInitializer;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.AbstractIoChannelHandler;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.DefaultIoChannelHandler;
|
||||||
|
import com.cisdi.data.sdk.utils.NettySslUtils;
|
||||||
|
import com.cisdi.data.sdk.vo.SslConfigVo;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.ChannelHandler;
|
||||||
|
import io.netty.channel.socket.SocketChannel;
|
||||||
|
import io.netty.handler.timeout.IdleStateHandler;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cuianbing
|
||||||
|
* @version 1.0
|
||||||
|
* @description: TODO
|
||||||
|
* @date 2021/7/20 21:27
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class OBLFChannelInitializer<I> extends AbstractChannelInitializer<I> {
|
||||||
|
private SessionFactory factory;
|
||||||
|
private ByteOrder byteOrder;
|
||||||
|
private SslConfigVo sslConfigVo;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造通道初始化器对象
|
||||||
|
*
|
||||||
|
* @param factory 会话工厂
|
||||||
|
* @param byteOrder 大小端
|
||||||
|
* @param sslConfig ssl证书配置,如果不启用tls,传null
|
||||||
|
*/
|
||||||
|
public OBLFChannelInitializer(SessionFactory factory,
|
||||||
|
ByteOrder byteOrder,
|
||||||
|
SslConfigVo sslConfig) {
|
||||||
|
this.factory = factory;
|
||||||
|
this.byteOrder = byteOrder;
|
||||||
|
this.sslConfigVo = sslConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AbstractIoChannelHandler<I> getTailHandler() {
|
||||||
|
return new DefaultIoChannelHandler(factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<ChannelHandler> getHandlers() {
|
||||||
|
List<ChannelHandler> handlers = new ArrayList<ChannelHandler>();
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IdleStateHandler getIdleStateHandler() {
|
||||||
|
return new IdleStateHandler(15, 15, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ChannelHandler getSslChannelHandler(Channel socketChannel) {
|
||||||
|
ChannelHandler sslHandler = null;
|
||||||
|
try {
|
||||||
|
if (sslConfigVo != null) {
|
||||||
|
sslHandler = NettySslUtils.getServerSslHandler((SocketChannel) socketChannel, sslConfigVo);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn(e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
return sslHandler;
|
||||||
|
}
|
||||||
|
}
|
169
src/main/java/com/cisdi/data/OBLF/impl/OBLFIoSession.java
Normal file
169
src/main/java/com/cisdi/data/OBLF/impl/OBLFIoSession.java
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
package com.cisdi.data.OBLF.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import com.cisdi.data.sdk.consts.ServiceName;
|
||||||
|
import com.cisdi.data.sdk.gateway.message.SocketMessage;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.IoSession;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.AbstractIoSession;
|
||||||
|
import com.cisdi.data.sdk.service.PassthroughService;
|
||||||
|
import com.cisdi.data.sdk.service.SendService;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.ByteBufAllocator;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cuianbing
|
||||||
|
* @version 1.0
|
||||||
|
* @description: TODO
|
||||||
|
* @date 2021/7/20 21:28
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class OBLFIoSession extends AbstractIoSession implements IoSession {
|
||||||
|
|
||||||
|
private OBLFSessionFactory factory = null;
|
||||||
|
|
||||||
|
private String deviceId = null;
|
||||||
|
/**
|
||||||
|
* 如果有值,代表所有会话都使用这一个设备id,且允许多会话共享此一个设备id,不除旧会话
|
||||||
|
*/
|
||||||
|
private final String onlyOneDeviceId;
|
||||||
|
|
||||||
|
private String gwPrefixCache = null;
|
||||||
|
|
||||||
|
private ByteBuf allBuf = ByteBufAllocator.DEFAULT.buffer();
|
||||||
|
|
||||||
|
|
||||||
|
public OBLFIoSession(OBLFSessionFactory factory, String onlyOneDeviceId) {
|
||||||
|
super();
|
||||||
|
this.factory = factory;
|
||||||
|
this.onlyOneDeviceId = onlyOneDeviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getDeviceIds() {
|
||||||
|
String cpDeviceId = deviceId;
|
||||||
|
String[] result = new String[cpDeviceId == null ? 0 : 1];
|
||||||
|
if (cpDeviceId != null) {
|
||||||
|
result[0] = cpDeviceId;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRead(Object message) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
ByteBuf inBuf = (ByteBuf) message;
|
||||||
|
if (inBuf != null) {
|
||||||
|
allBuf.writeBytes(inBuf);
|
||||||
|
} else {
|
||||||
|
log.info("电文格式为空");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("电文格式错误!");
|
||||||
|
throw new BusinessException("电文格式错误!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOpen() {
|
||||||
|
super.onOpen();
|
||||||
|
log.info("建立连接,channel:{}", getChannel());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClose() {
|
||||||
|
log.info("onClose");
|
||||||
|
Map<String, String> message = decode(allBuf);
|
||||||
|
|
||||||
|
if (serviceProvider != null && socketGateway != null) {
|
||||||
|
SendService service = (SendService) serviceProvider.getByName(ServiceName.Send);
|
||||||
|
SocketMessage socketMessage = socketGateway.buildSocketMessage();
|
||||||
|
socketMessage.setDeviceId(onlyOneDeviceId);
|
||||||
|
socketMessage.setData(JSON.toJSONString(message).getBytes(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
String analysisProgram = message.get("AnalysisProgram_");
|
||||||
|
|
||||||
|
if ("FE 4".equals(analysisProgram)) {
|
||||||
|
socketMessage.setMsgKey("iron");
|
||||||
|
} else {
|
||||||
|
socketMessage.setMsgKey("steel");
|
||||||
|
}
|
||||||
|
|
||||||
|
service.sendMessage(socketMessage);
|
||||||
|
if (socketGateway.getInstanceVo().getLogOpen()) {
|
||||||
|
log.info("类似为:{}:发送消息内容{}", message, message.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
super.onClose();
|
||||||
|
factory = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
if (getChannel() != null) {
|
||||||
|
try {
|
||||||
|
getChannel().close().sync();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.warn(e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Throwable t) {
|
||||||
|
// 这里会出现 java.io.IOException: 远程主机强迫关闭了一个现有的连接。
|
||||||
|
log.info("远程主机强迫关闭了一个现有的连接。");
|
||||||
|
// log.error("session exception:{}", t);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Map<String, String> decode(ByteBuf byteBuf) {
|
||||||
|
|
||||||
|
List<Map<String, String>> dataList = new ArrayList<>();
|
||||||
|
AtomicInteger dataFlag = new AtomicInteger();
|
||||||
|
|
||||||
|
String msg = byteBuf.toString(StandardCharsets.UTF_8);
|
||||||
|
Map<String, String> data = JSON.parseObject(msg, Map.class);
|
||||||
|
log.debug("收到数据{}", data);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void passThrough(ByteBuf passthroughBuf) {
|
||||||
|
try {
|
||||||
|
if (serviceProvider != null && socketGateway != null) {
|
||||||
|
PassthroughService service = (PassthroughService) serviceProvider.getByName(ServiceName.Passthrough);
|
||||||
|
service.transfer(passthroughBuf, socketGateway.getInstanceVo().getPassthroughAddress());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("协议透传失败:" + e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String gwPrefix() {
|
||||||
|
if (gwPrefixCache != null) {
|
||||||
|
return gwPrefixCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
gwPrefixCache = "";
|
||||||
|
if (socketGateway != null && socketGateway.getInstanceVo() != null) {
|
||||||
|
gwPrefixCache = "网关Id:" + socketGateway.getInstanceVo().getRunId() + "连接:" + getChannel() + " ";
|
||||||
|
} else {
|
||||||
|
gwPrefixCache = "连接:" + getChannel() + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return gwPrefixCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.cisdi.data.OBLF.impl;
|
||||||
|
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.IoSession;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.AbstractSessionFactory;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cuianbing
|
||||||
|
* @version 1.0
|
||||||
|
* @description: TODO
|
||||||
|
* @date 2021/7/20 21:29
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class OBLFSessionFactory extends AbstractSessionFactory {
|
||||||
|
|
||||||
|
private String onlyOneDeviceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @param: onlyOneDeviceId 设备唯一ID
|
||||||
|
* @return: void
|
||||||
|
* @author cuianbing
|
||||||
|
* @date: 2021/7/7 22:10
|
||||||
|
*/
|
||||||
|
public OBLFSessionFactory(String onlyOneDeviceId) {
|
||||||
|
this.onlyOneDeviceId = onlyOneDeviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IoSession newSession() {
|
||||||
|
IoSession session = new OBLFIoSession(this, onlyOneDeviceId);
|
||||||
|
session.init(UUID.randomUUID().toString(), provider, socketGateway);
|
||||||
|
sessionSet.add(session);
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.cisdi.data.OBLF.test;
|
||||||
|
|
||||||
|
import com.cisdi.data.sdk.service.Service;
|
||||||
|
import com.cisdi.data.sdk.service.ServiceProvider;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cuianbing
|
||||||
|
* @version 1.0
|
||||||
|
* @description: TODO
|
||||||
|
* @date 2021/7/7 19:17
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class ServiceProviderTest implements ServiceProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Service getByName(String name) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
65
src/main/java/com/cisdi/data/OBLF/test/StartTest.java
Normal file
65
src/main/java/com/cisdi/data/OBLF/test/StartTest.java
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package com.cisdi.data.OBLF.test;
|
||||||
|
|
||||||
|
import com.cisdi.data.OBLF.impl.OBLFChannelInitializer;
|
||||||
|
import com.cisdi.data.OBLF.impl.OBLFSessionFactory;
|
||||||
|
import com.cisdi.data.sdk.enums.ByteOrder;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.SessionFactory;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.TcpIoService;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.DefaultTcpIoService;
|
||||||
|
import com.cisdi.data.sdk.vo.GatewayVo;
|
||||||
|
import io.netty.handler.ssl.OpenSsl;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cuianbing
|
||||||
|
* @version 1.0
|
||||||
|
* @description: TODO
|
||||||
|
* @date 2021/7/7 19:28
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class StartTest {
|
||||||
|
|
||||||
|
private static TcpIoService ioService = null;
|
||||||
|
|
||||||
|
private static SessionFactory sessionFactory = null;
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
boolean available = OpenSsl.isAvailable();
|
||||||
|
log.info("openssl available={}", available);
|
||||||
|
|
||||||
|
DefaultTcpIoService defaultIoService = new DefaultTcpIoService();
|
||||||
|
|
||||||
|
SessionFactory factory = new OBLFSessionFactory(null);
|
||||||
|
|
||||||
|
ServiceProviderTest testServiceProvider = new ServiceProviderTest();
|
||||||
|
|
||||||
|
factory.init(testServiceProvider, null);
|
||||||
|
|
||||||
|
OBLFChannelInitializer channelInitializer =
|
||||||
|
new OBLFChannelInitializer(factory, ByteOrder.BIGENDIAN, null);
|
||||||
|
|
||||||
|
GatewayVo instanceVo = new GatewayVo();
|
||||||
|
instanceVo.setByteOrder(ByteOrder.BIGENDIAN);
|
||||||
|
instanceVo.setParameter("{\"listenIp\":\"0.0.0.0\",\"listenPort\":8888,\"threadSize\":50,\"timeout\":2000}");
|
||||||
|
|
||||||
|
defaultIoService.init(instanceVo, factory, channelInitializer);
|
||||||
|
|
||||||
|
ioService = defaultIoService;
|
||||||
|
sessionFactory = factory;
|
||||||
|
|
||||||
|
boolean open = ioService.open();
|
||||||
|
|
||||||
|
if (open == true) {
|
||||||
|
log.info("plc网关启动成功");
|
||||||
|
} else {
|
||||||
|
log.info("plc网关启动失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(10000000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
src/main/java/com/cisdi/data/OBLF/util/ByteBufUtil.java
Normal file
28
src/main/java/com/cisdi/data/OBLF/util/ByteBufUtil.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package com.cisdi.data.OBLF.util;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import static io.netty.buffer.ByteBufUtil.appendPrettyHexDump;
|
||||||
|
import static io.netty.util.internal.StringUtil.NEWLINE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cuianbing
|
||||||
|
* @version 1.0
|
||||||
|
* @description: TODO
|
||||||
|
* @date 2021/7/9 15:32
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class ByteBufUtil {
|
||||||
|
public static void log(ByteBuf byteBuf) {
|
||||||
|
int length = byteBuf.readableBytes();
|
||||||
|
int row = length / 16 + (length % 15 == 0 ? 0 : 1) + 4;
|
||||||
|
StringBuilder buf = new StringBuilder(row * 80 * 2)
|
||||||
|
.append("read index:").append(byteBuf.readerIndex())
|
||||||
|
.append(" write index:").append(byteBuf.writerIndex())
|
||||||
|
.append(" capacity:").append(byteBuf.capacity())
|
||||||
|
.append(NEWLINE);
|
||||||
|
appendPrettyHexDump(buf, byteBuf);
|
||||||
|
log.info(buf.toString());
|
||||||
|
}
|
||||||
|
}
|
27
src/main/java/com/cisdi/data/OBLF/util/HexTransform.java
Normal file
27
src/main/java/com/cisdi/data/OBLF/util/HexTransform.java
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package com.cisdi.data.OBLF.util;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cuianbing
|
||||||
|
* @version 1.0
|
||||||
|
* @description: 16进制转换工具类
|
||||||
|
* @date 2021/7/7 21:41
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class HexTransform {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @param: hex 16进制字符串
|
||||||
|
* @param: chartSet 字符集 UTF-8 GB2312 ASCII
|
||||||
|
* @return: java.lang.String
|
||||||
|
* @author cuianbing
|
||||||
|
* @date: 2021/7/7 21:43
|
||||||
|
*/
|
||||||
|
public static String HexToString(String hex, String chartSet) {
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
135
src/main/java/com/cisdi/data/RFID/gateway/RfidClient.java
Normal file
135
src/main/java/com/cisdi/data/RFID/gateway/RfidClient.java
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
package com.cisdi.data.RFID.gateway;
|
||||||
|
|
||||||
|
import io.netty.bootstrap.Bootstrap;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.ChannelOption;
|
||||||
|
import io.netty.channel.EventLoopGroup;
|
||||||
|
import io.netty.channel.epoll.*;
|
||||||
|
import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class RfidClient {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(RfidClient.class);
|
||||||
|
private volatile Channel channel = null;
|
||||||
|
private EventLoopGroup workerGroup = null;
|
||||||
|
private RfidTaskStartVo startVo;
|
||||||
|
private Long lastHeartbeatTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
public RfidClient(RfidTaskStartVo startVo) {
|
||||||
|
this.startVo = startVo;
|
||||||
|
|
||||||
|
if (Epoll.isAvailable()) {
|
||||||
|
logger.info("rfid enable epoll and have tcp SO_KEEPALIVE check");
|
||||||
|
} else {
|
||||||
|
logger.info("rfid disable epoll and not have custom SO_KEEPALIVE check");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean close() {
|
||||||
|
boolean result = false;
|
||||||
|
if (workerGroup == null && channel == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channel != null) {
|
||||||
|
try {
|
||||||
|
channel.close().sync();
|
||||||
|
channel = null;
|
||||||
|
result = true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error(e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (workerGroup != null) {
|
||||||
|
try {
|
||||||
|
workerGroup.shutdownGracefully().sync();
|
||||||
|
workerGroup = null;
|
||||||
|
result = true;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
logger.error("永锋物流rfid到 {}:{}的连接关闭失败,{}",
|
||||||
|
startVo.getSocketParam().getPeerIp(), startVo.getSocketParam().getPeerPort(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channel != null || workerGroup != null) {
|
||||||
|
logger.info("channel:{},workgoup:{}", channel, workerGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() throws IOException {
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void start() {
|
||||||
|
lastHeartbeatTime = System.currentTimeMillis();
|
||||||
|
if (channel != null) {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
//设置一个多线程循环器
|
||||||
|
//启动附注类
|
||||||
|
Bootstrap bootstrap = new Bootstrap();
|
||||||
|
bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
|
||||||
|
|
||||||
|
if (Epoll.isAvailable()) {
|
||||||
|
bootstrap.channel(EpollSocketChannel.class);
|
||||||
|
bootstrap.option(EpollChannelOption.EPOLL_MODE, EpollMode.LEVEL_TRIGGERED);
|
||||||
|
bootstrap.option(EpollChannelOption.TCP_KEEPIDLE, 10);
|
||||||
|
bootstrap.option(EpollChannelOption.TCP_KEEPINTVL, 5);
|
||||||
|
bootstrap.option(EpollChannelOption.TCP_KEEPCNT, 2);
|
||||||
|
workerGroup = new EpollEventLoopGroup(2);
|
||||||
|
} else {
|
||||||
|
workerGroup = new NioEventLoopGroup(2);
|
||||||
|
bootstrap.channel(NioSocketChannel.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
bootstrap.group(workerGroup);
|
||||||
|
//指定所使用的NIO传输channel
|
||||||
|
//指定客户端初始化处理
|
||||||
|
bootstrap.handler(new RfidClientInitializer(startVo, this));
|
||||||
|
try {
|
||||||
|
channel = bootstrap.connect(startVo.getSocketParam().getPeerIp(),
|
||||||
|
startVo.getSocketParam().getPeerPort()).sync().channel();
|
||||||
|
//channel.closeFuture().sync(); // 如果会话关闭,会退出当前线程
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
logger.warn(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reconnect() {
|
||||||
|
logger.info("永锋物流rfid重新连接中......{}:{}", getIp(), getPort());
|
||||||
|
close();
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Channel getChannel() {
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChannel(Channel channel) {
|
||||||
|
this.channel = channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIp() {
|
||||||
|
return startVo.getSocketParam().getPeerIp();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPort() {
|
||||||
|
return startVo.getSocketParam().getPeerPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getLastHeartbeatTime() {
|
||||||
|
return lastHeartbeatTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastHeartbeatTime(Long lastHeartbeatTime) {
|
||||||
|
this.lastHeartbeatTime = lastHeartbeatTime;
|
||||||
|
}
|
||||||
|
}
|
110
src/main/java/com/cisdi/data/RFID/gateway/RfidClientHandler.java
Normal file
110
src/main/java/com/cisdi/data/RFID/gateway/RfidClientHandler.java
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
package com.cisdi.data.RFID.gateway;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||||
|
import com.cisdi.data.sdk.consts.ServiceName;
|
||||||
|
import com.cisdi.data.sdk.gateway.message.SocketMessage;
|
||||||
|
import com.cisdi.data.sdk.service.SendService;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.SimpleChannelInboundHandler;
|
||||||
|
import io.netty.util.ReferenceCountUtil;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class RfidClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(RfidClientHandler.class);
|
||||||
|
private static final Charset Encode_Charset = Charset.forName("UTF-8");
|
||||||
|
private static final String HEARTBEAT_CODE = "HeartBea";
|
||||||
|
|
||||||
|
private RfidClient rfidClient;
|
||||||
|
|
||||||
|
private RfidTaskStartVo startVo;
|
||||||
|
|
||||||
|
public RfidClientHandler(RfidTaskStartVo startVo, RfidClient rfidClient) {
|
||||||
|
this.startVo = startVo;
|
||||||
|
this.rfidClient = rfidClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<RfidItemVo> decode = RfidVoDecoder.Decode(msg);
|
||||||
|
if(decode.size() == 1 && HEARTBEAT_CODE.equalsIgnoreCase(decode.get(0).getCode())) {
|
||||||
|
logger.info("永锋物流Rfid {},启用心跳:{} , 心跳 vo:{}", rfidClient.getChannel(),
|
||||||
|
startVo.getCustomParam() == null ? false : startVo.getCustomParam().getEnableHeartbeat(),
|
||||||
|
decode);
|
||||||
|
rfidClient.setLastHeartbeatTime(System.currentTimeMillis());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
decode.forEach((RfidItemVo i) -> {
|
||||||
|
i.setServerIp(startVo.getSocketParam().getPeerIp());
|
||||||
|
i.setServerPort(startVo.getSocketParam().getPeerPort());
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if (startVo.getGatewayBase() != null && Boolean.TRUE.equals(startVo.getGatewayBase().getInstanceVo().getLogOpen())) {
|
||||||
|
logger.info("永锋物流Rfid {} vo:{} ", rfidClient.getChannel(), decode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startVo.getGatewayBase() != null && startVo.getServiceProvider() != null) {
|
||||||
|
Map<String, Object> data = new HashMap<>();
|
||||||
|
SendService service = (SendService) startVo.getServiceProvider().getByName(ServiceName.Send);
|
||||||
|
SocketMessage socketMessage = startVo.getGatewayBase().buildSocketMessage();
|
||||||
|
socketMessage.setDeviceId(startVo.getDeviceId());
|
||||||
|
socketMessage.setProviderCode(null);
|
||||||
|
socketMessage.setMsgKey("666");
|
||||||
|
data.put("data", decode);
|
||||||
|
String jsonString = JSON.toJSONString(data, SerializerFeature.WriteMapNullValue);
|
||||||
|
byte[] body = jsonString.getBytes(Encode_Charset);
|
||||||
|
socketMessage.setData(body);
|
||||||
|
logger.info("socketMess" + socketMessage.toString());
|
||||||
|
service.sendMessage(socketMessage);
|
||||||
|
} else {
|
||||||
|
logger.info("永锋物流Rfid收到消息{}", decode);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error(e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||||
|
logger.info("{} channelActive active", ctx.channel());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||||
|
logger.info("{} channelInactive inactive", ctx.channel());
|
||||||
|
|
||||||
|
try {
|
||||||
|
rfidClient.setChannel(null);
|
||||||
|
logger.info("set channel to null raise reconnect");
|
||||||
|
} finally {
|
||||||
|
// 释放引用
|
||||||
|
rfidClient = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.channelInactive(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exceptionCaught(ChannelHandlerContext ctx, Throwable t) throws Exception {
|
||||||
|
logger.error("exceptionCaught:{}", t);
|
||||||
|
super.exceptionCaught(ctx, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
|
||||||
|
logger.error("userEventTriggered:{}", evt);
|
||||||
|
super.userEventTriggered(ctx, evt);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.cisdi.data.RFID.gateway;
|
||||||
|
|
||||||
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
import io.netty.channel.ChannelPipeline;
|
||||||
|
import io.netty.channel.socket.SocketChannel;
|
||||||
|
|
||||||
|
public class RfidClientInitializer extends ChannelInitializer<SocketChannel> {
|
||||||
|
|
||||||
|
private RfidClient rfidClient;
|
||||||
|
private RfidTaskStartVo startVo;
|
||||||
|
|
||||||
|
public RfidClientInitializer(RfidTaskStartVo startVo, RfidClient rfidClient) {
|
||||||
|
this.startVo = startVo;
|
||||||
|
this.rfidClient = rfidClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initChannel(SocketChannel socketChannel) throws Exception {
|
||||||
|
//注册管道
|
||||||
|
ChannelPipeline pipeline = socketChannel.pipeline();
|
||||||
|
pipeline.addLast(new RfidFrameDecoder(startVo));
|
||||||
|
pipeline.addLast("chat", new RfidClientHandler(startVo, rfidClient));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
package com.cisdi.data.RFID.gateway;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rfid server有多个,所以需要支持配置多个服务端地址的
|
||||||
|
* @author cup
|
||||||
|
* @date 2021/03/03
|
||||||
|
*/
|
||||||
|
public class RfidCustomParam implements Serializable {
|
||||||
|
private static final long serialVersionUID = -5017472517219960138L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每个String 如 192.168.1.5:8823 形式
|
||||||
|
*/
|
||||||
|
private List<String> serverList = new ArrayList<String>();
|
||||||
|
|
||||||
|
private Boolean enableHeartbeat = Boolean.FALSE;
|
||||||
|
|
||||||
|
private Integer heartbeatTimeInMs = 5000;
|
||||||
|
private Integer heartbeatMaxLostCount = 3;
|
||||||
|
|
||||||
|
public List<String> getServerList() {
|
||||||
|
return serverList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServerList(List<String> serverList) {
|
||||||
|
this.serverList = serverList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getEnableHeartbeat() {
|
||||||
|
return enableHeartbeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnableHeartbeat(Boolean enableHeartbeat) {
|
||||||
|
this.enableHeartbeat = enableHeartbeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getHeartbeatTimeInMs() {
|
||||||
|
return heartbeatTimeInMs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeartbeatTimeInMs(Integer heartbeatTimeInMs) {
|
||||||
|
this.heartbeatTimeInMs = heartbeatTimeInMs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getHeartbeatMaxLostCount() {
|
||||||
|
return heartbeatMaxLostCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeartbeatMaxLostCount(Integer heartbeatMaxLostCount) {
|
||||||
|
this.heartbeatMaxLostCount = heartbeatMaxLostCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return JSON.toJSONString(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args){
|
||||||
|
RfidCustomParam dto = new RfidCustomParam();
|
||||||
|
dto.getServerList().add("192.168.6.55:10000");
|
||||||
|
dto.getServerList().add("192.168.6.56:10000");
|
||||||
|
dto.getServerList().add("192.165.20.111:10000");
|
||||||
|
dto.getServerList().add("192.165.20.112:10000");
|
||||||
|
dto.getServerList().add("192.165.20.113:10000");
|
||||||
|
dto.getServerList().add("192.165.20.119:10000");
|
||||||
|
dto.getServerList().add("192.165.20.118:10000");
|
||||||
|
dto.getServerList().add("192.165.20.120:10000");
|
||||||
|
dto.getServerList().add("192.165.20.121:10000");
|
||||||
|
dto.getServerList().add("192.165.20.121:10000");
|
||||||
|
List<String> customParams=dto.getServerList().stream().distinct().collect(Collectors.toList());
|
||||||
|
System.out.println(customParams);
|
||||||
|
System.out.println(dto);
|
||||||
|
}
|
||||||
|
}
|
150
src/main/java/com/cisdi/data/RFID/gateway/RfidDaemonTask.java
Normal file
150
src/main/java/com/cisdi/data/RFID/gateway/RfidDaemonTask.java
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
package com.cisdi.data.RFID.gateway;
|
||||||
|
|
||||||
|
import com.cisdi.data.common.dto.AlarmDto;
|
||||||
|
import com.cisdi.data.sdk.consts.ServiceName;
|
||||||
|
import com.cisdi.data.sdk.service.AlarmService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class RfidDaemonTask implements Runnable {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(RfidDaemonTask.class);
|
||||||
|
|
||||||
|
private RfidClient rfidClient;
|
||||||
|
private RfidTaskStartVo startVo;
|
||||||
|
|
||||||
|
public RfidDaemonTask(RfidClient rfidClient, RfidTaskStartVo startVo) {
|
||||||
|
this.rfidClient = rfidClient;
|
||||||
|
this.startVo = startVo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
String channelInfo = null;
|
||||||
|
while (startVo.getShouldRun().get() == true) {
|
||||||
|
channelInfo = String.format("channel:%s, active:%s,open:%s,writable:%s", rfidClient.getChannel(),
|
||||||
|
rfidClient.getChannel() == null ? "" : rfidClient.getChannel().isActive(),
|
||||||
|
rfidClient.getChannel() == null ? "" : rfidClient.getChannel().isOpen(),
|
||||||
|
rfidClient.getChannel() == null ? "" : rfidClient.getChannel().isWritable());
|
||||||
|
try {
|
||||||
|
if (rfidClient != null && rfidClient.getChannel() != null
|
||||||
|
&& rfidClient.getChannel().isActive() == true) {
|
||||||
|
if (startVo.getGatewayBase() != null
|
||||||
|
&& Boolean.TRUE.equals(startVo.getGatewayBase().getInstanceVo().getLogOpen())) {
|
||||||
|
logger.info("当前永锋物流Rfid拉取连接通道处于连接状态,连接id:{},连接信息:{}",
|
||||||
|
startVo.getGatewayBase().getInstanceVo().getRunId(), channelInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(startVo.getCustomParam() != null
|
||||||
|
&& Boolean.TRUE.equals(startVo.getCustomParam().getEnableHeartbeat())
|
||||||
|
&& Math.abs(System.currentTimeMillis() - rfidClient.getLastHeartbeatTime()) >
|
||||||
|
startVo.getCustomParam().getHeartbeatMaxLostCount() * startVo.getCustomParam().getHeartbeatTimeInMs()){
|
||||||
|
logger.warn("当前永锋物流Rfid拉取连接通道心跳启用,且心跳超时,触发重连,连接id:{},连接信息:{}",
|
||||||
|
startVo.getGatewayBase().getInstanceVo().getRunId(), channelInfo);
|
||||||
|
//启用了心跳,且心跳时间超时
|
||||||
|
reconnectToRfid(channelInfo, true);
|
||||||
|
}
|
||||||
|
} else if (rfidClient.getChannel() == null) {
|
||||||
|
String errorMsg = String.format("永锋物流Rfid到%s:%s的连接未建立或已关闭, %s", rfidClient.getIp(),
|
||||||
|
rfidClient.getPort(), channelInfo);
|
||||||
|
logger.warn(errorMsg);
|
||||||
|
sendAlarmToPlatform(errorMsg);
|
||||||
|
reconnectToRfid(channelInfo, false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
String errorMsg = String.format("永锋物流Rfid到%s:%s的连接未建立或已关闭, %s", rfidClient.getIp(),
|
||||||
|
rfidClient.getPort(), channelInfo);
|
||||||
|
logger.warn(errorMsg);
|
||||||
|
|
||||||
|
sendAlarmToPlatform(errorMsg);
|
||||||
|
|
||||||
|
if(startVo.getCustomParam() != null
|
||||||
|
&& Boolean.TRUE.equals(startVo.getCustomParam().getEnableHeartbeat())
|
||||||
|
&& Math.abs(System.currentTimeMillis() - rfidClient.getLastHeartbeatTime()) >
|
||||||
|
startVo.getCustomParam().getHeartbeatMaxLostCount() * startVo.getCustomParam().getHeartbeatTimeInMs()){
|
||||||
|
logger.warn("当前永锋物流Rfid拉取连接通道心跳启用,且心跳超时,触发重连,连接id:{},连接信息:{}",
|
||||||
|
startVo.getGatewayBase().getInstanceVo().getRunId(), channelInfo);
|
||||||
|
//启用了心跳,且心跳时间超时
|
||||||
|
reconnectToRfid(channelInfo, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.sleep(startVo.getSocketParam().getPullInternal());
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rfidClient != null) {
|
||||||
|
rfidClient.close();
|
||||||
|
rfidClient = null;
|
||||||
|
}
|
||||||
|
logger.info("退出永锋物流Rfid拉取连接线程 {}", channelInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reconnectToRfid(final String copyChannelInfo, boolean forceConnect) throws InterruptedException {
|
||||||
|
Thread.sleep(5000);
|
||||||
|
Thread thread = new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
logger.info("永锋物流Rfid触发重连强制:{}....{}:{} {}", forceConnect, rfidClient.getIp(), rfidClient.getPort(),
|
||||||
|
copyChannelInfo);
|
||||||
|
if (rfidClient.getChannel() == null || forceConnect) {
|
||||||
|
rfidClient.reconnect();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.info(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void forceReconnectToRfid() {
|
||||||
|
String channelInfo = String.format("channel:%s, active:%s,open:%s,writable:%s", rfidClient.getChannel(),
|
||||||
|
rfidClient.getChannel() == null ? "" : rfidClient.getChannel().isActive(),
|
||||||
|
rfidClient.getChannel() == null ? "" : rfidClient.getChannel().isOpen(),
|
||||||
|
rfidClient.getChannel() == null ? "" : rfidClient.getChannel().isWritable());
|
||||||
|
try {
|
||||||
|
Thread.sleep(500);
|
||||||
|
Thread thread = new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
logger.info("永锋物流Rfid触发重连强制:{}....{}:{} {}", true, rfidClient.getIp(), rfidClient.getPort(),
|
||||||
|
channelInfo);
|
||||||
|
rfidClient.reconnect();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.info(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
thread.start();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendAlarmToPlatform(String detail) {
|
||||||
|
if (startVo.getServiceProvider() != null && startVo.getGatewayBase() != null) {
|
||||||
|
AlarmService alarmService = (AlarmService)startVo.getServiceProvider().getByName(ServiceName.Alarm);
|
||||||
|
if (alarmService != null) {
|
||||||
|
AlarmDto alarmDto = new AlarmDto();
|
||||||
|
|
||||||
|
alarmDto.setAlarmType(AlarmDto.Connect_Fail_Alarm);
|
||||||
|
alarmDto.setDetail(detail);
|
||||||
|
alarmDto.setDeviceId(startVo.getDeviceId());
|
||||||
|
alarmDto.setGatewayId(startVo.getGatewayBase().getInstanceVo().getRunId());
|
||||||
|
alarmDto.setGatewayName(startVo.getGatewayBase().getInstanceVo().getName());
|
||||||
|
alarmDto.setMsgKey(null);
|
||||||
|
alarmDto.setUpper(Boolean.TRUE);
|
||||||
|
alarmDto.setTime(new Date());
|
||||||
|
|
||||||
|
alarmService.raiseAlarm(Arrays.asList(alarmDto));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package com.cisdi.data.RFID.gateway;
|
||||||
|
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description: 获取完整的报文
|
||||||
|
* @Creator: Mo
|
||||||
|
* @Date: 2021/6/2 23:37
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class RfidFrameDecoder extends ByteToMessageDecoder {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(RfidFrameDecoder.class);
|
||||||
|
|
||||||
|
private RfidTaskStartVo startVo;
|
||||||
|
|
||||||
|
private final static Integer MIN_LENGTH = 10;
|
||||||
|
private final byte START_SPLIT = 0x02;
|
||||||
|
private final byte END_SPLIT = 0x03;
|
||||||
|
private final Set<Integer> validDataSizeInByte = new HashSet<Integer>(Arrays.asList(10));
|
||||||
|
|
||||||
|
public RfidFrameDecoder(RfidTaskStartVo startVo) {
|
||||||
|
this.startVo = startVo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void decode(ChannelHandlerContext ctx, ByteBuf bufferIn, List<Object> out) throws Exception {
|
||||||
|
if (bufferIn.readableBytes() < MIN_LENGTH) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String channelInfo = ctx.toString();
|
||||||
|
|
||||||
|
// 心跳报文为 02 48 65 61 72 74 42 65 61 03 长度10个字节,拥有独立的起始符和结束符,不会和数据报文共享起始符和结束符
|
||||||
|
// 数据体长度固定为 8,心跳报文数据内容为 HeartBea
|
||||||
|
int beginIndex = bufferIn.readerIndex();
|
||||||
|
|
||||||
|
for (int i = 0; i + 9 < bufferIn.readableBytes(); i += 10) {
|
||||||
|
byte curByte = bufferIn.getByte(beginIndex + i);
|
||||||
|
if(curByte != START_SPLIT){
|
||||||
|
ctx.close();
|
||||||
|
throw new BusinessException(channelInfo + "完整报文第一个字节内容不正确,期望: 0x02,实际:" + curByte);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte endByte = bufferIn.getByte(beginIndex + i + 9);
|
||||||
|
if(endByte != END_SPLIT){
|
||||||
|
ctx.close();
|
||||||
|
throw new BusinessException(channelInfo + "完整报文最后一个字节内容不正确,期望: 0x03,实际:" + endByte);
|
||||||
|
}
|
||||||
|
|
||||||
|
out.add(bufferIn.retainedSlice(beginIndex + i, 10));
|
||||||
|
bufferIn.readerIndex(beginIndex + i + 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
58
src/main/java/com/cisdi/data/RFID/gateway/RfidItemVo.java
Normal file
58
src/main/java/com/cisdi/data/RFID/gateway/RfidItemVo.java
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package com.cisdi.data.RFID.gateway;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取到标签或标签离开,解析后的内容都一致
|
||||||
|
*
|
||||||
|
* @author cup
|
||||||
|
* @date 2021/03/03
|
||||||
|
*/
|
||||||
|
public class RfidItemVo implements Serializable {
|
||||||
|
private static final long serialVersionUID = -4290553035349526464L;
|
||||||
|
/**
|
||||||
|
* rfid 服务器Ip
|
||||||
|
*/
|
||||||
|
private String serverIp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rfid 服务器端口
|
||||||
|
*/
|
||||||
|
private Integer serverPort;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编号
|
||||||
|
*/
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
public String getServerIp() {
|
||||||
|
return serverIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServerIp(String serverIp) {
|
||||||
|
this.serverIp = serverIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getServerPort() {
|
||||||
|
return serverPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServerPort(Integer serverPort) {
|
||||||
|
this.serverPort = serverPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCode(String code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return JSON.toJSONString(this);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,172 @@
|
|||||||
|
package com.cisdi.data.RFID.gateway;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import com.cisdi.data.common.utils.Strings;
|
||||||
|
import com.cisdi.data.sdk.consts.ServiceName;
|
||||||
|
import com.cisdi.data.sdk.enums.GatewayState;
|
||||||
|
import com.cisdi.data.sdk.gateway.base.PulledSocketGatewayBase;
|
||||||
|
import com.cisdi.data.sdk.param.PullSocketParam;
|
||||||
|
import com.cisdi.data.sdk.procotol.message.SocketReturnMessage;
|
||||||
|
import com.cisdi.data.sdk.service.RouteService;
|
||||||
|
import com.cisdi.data.sdk.vo.DeviceVo;
|
||||||
|
import com.cisdi.data.sdk.vo.ExeResultVo;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 物流 rfid 驱动,平台:客户端 rfid:server,多个server,使用tcp协议
|
||||||
|
*
|
||||||
|
* @author cup
|
||||||
|
* @date 2021/03/04
|
||||||
|
*/
|
||||||
|
public class RfidPullSocketGateway extends PulledSocketGatewayBase {
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(RfidPullSocketGateway.class);
|
||||||
|
|
||||||
|
private String deviceId;
|
||||||
|
private AtomicBoolean shouldRun = null;
|
||||||
|
private static final int Min_Pull_Internal = 1; // 允许最小的拉取间隔为1毫秒
|
||||||
|
private static final int Min_Timeout = 1000; // 允许最小的超时时间间隔,为1000毫秒
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExeResultVo sendReturnMessage(SocketReturnMessage returnMsg) {
|
||||||
|
throw new BusinessException("永锋物流Rfid协议不支持下发命令。");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
if (state == GatewayState.RUNNING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
startInternal();
|
||||||
|
state = GatewayState.RUNNING;
|
||||||
|
logger.info("永锋物流Rfid报警socket拉取网关:{}启动成功", instanceVo.getRunId());
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("永锋物流Rfid报警socket拉取网关:{}启动失败", instanceVo.getRunId());
|
||||||
|
logger.error(e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startInternal() {
|
||||||
|
socketParam = JSON.parseObject(getInstanceVo().getParameter(), PullSocketParam.class);
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(socketParam.getPeerIp()) || socketParam.getPeerPort() == null) {
|
||||||
|
throw new BusinessException("未正确配置拉取对端ip地址和对端端口。");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (socketParam.getPullInternal() == null) {
|
||||||
|
throw new BusinessException("未正确配置拉取间隔");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (socketParam.getTimeout() == null) {
|
||||||
|
throw new BusinessException("未正确配置拉取超时时间");
|
||||||
|
}
|
||||||
|
|
||||||
|
socketParam.setPullInternal(socketParam.getPullInternal() < Min_Pull_Internal ?
|
||||||
|
Min_Pull_Internal : socketParam.getPullInternal());
|
||||||
|
|
||||||
|
socketParam.setTimeout(socketParam.getTimeout() < Min_Timeout ? Min_Timeout : socketParam.getTimeout());
|
||||||
|
|
||||||
|
RouteService routeService = (RouteService) serviceProvider.getByName(ServiceName.Route);
|
||||||
|
List<DeviceVo> deviceVos = routeService.findByRunId(instanceVo.getRunId());
|
||||||
|
|
||||||
|
if (deviceVos.size() > 1) {
|
||||||
|
throw new BusinessException("网关Id:" + instanceVo.getRunId() + "为永锋物流Rfid报警socket拉取网关,只允许关联一个设备Id");
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceId = deviceVos.size() > 0 ? deviceVos.get(0).getDeviceId() : null;
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(deviceId)) {
|
||||||
|
throw new BusinessException("runId=" + getInstanceVo().getRunId() + "未正确配置网关和设备关联");
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("永锋物流Rfid报警socket拉取网关:{}读取启动配置参数:{}", getInstanceVo().getRunId(), socketParam);
|
||||||
|
|
||||||
|
closePrevState();
|
||||||
|
shouldRun = new AtomicBoolean(true);
|
||||||
|
|
||||||
|
String parameter = socketParam.getOtherParameter();
|
||||||
|
Set<String> targetServerSet = new HashSet<String>();
|
||||||
|
targetServerSet.add(String.format("%s:%s", socketParam.getPeerIp(), socketParam.getPeerPort()));
|
||||||
|
RfidCustomParam customParam = null;
|
||||||
|
if (parameter != null) {
|
||||||
|
customParam = JSON.parseObject(parameter, RfidCustomParam.class);
|
||||||
|
if (customParam != null) {
|
||||||
|
/**
|
||||||
|
* RFID服务端参数去重
|
||||||
|
*/
|
||||||
|
customParam.setServerList(customParam.getServerList().stream().distinct().collect(Collectors.toList()));
|
||||||
|
for (String server : customParam.getServerList()) {
|
||||||
|
targetServerSet.add(server.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = 1;
|
||||||
|
for (String server : targetServerSet) {
|
||||||
|
// 复制已有参数
|
||||||
|
PullSocketParam serverParam = JSON.parseObject(JSON.toJSONString(socketParam), PullSocketParam.class);
|
||||||
|
|
||||||
|
serverParam.setPeerIp(Strings.split(server, ":")[0]);
|
||||||
|
serverParam.setPeerPort(Integer.valueOf(Strings.split(server, ":")[1]));
|
||||||
|
|
||||||
|
// 启动线程
|
||||||
|
RfidTaskStartVo startVo = new RfidTaskStartVo();
|
||||||
|
startVo.setDeviceId(deviceId);
|
||||||
|
startVo.setGatewayBase(this);
|
||||||
|
startVo.setServiceProvider(serviceProvider);
|
||||||
|
startVo.setSocketParam(serverParam);
|
||||||
|
startVo.setShouldRun(shouldRun);
|
||||||
|
startVo.setCustomParam(customParam);
|
||||||
|
|
||||||
|
RfidClient fireClient = new RfidClient(startVo);
|
||||||
|
RfidDaemonTask daemonTask = new RfidDaemonTask(fireClient, startVo);
|
||||||
|
startVo.setRfidDaemonTask(daemonTask);
|
||||||
|
Thread thread = new Thread(daemonTask, "Fire-Daemon-Task-runid-" + instanceVo.getRunId() + "-s" + index++);
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
state = GatewayState.RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
if (state == GatewayState.CLOSED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
closePrevState();
|
||||||
|
|
||||||
|
logger.info("永锋物流Rfid报警socket拉取网关:{}关闭中", getInstanceVo().getRunId());
|
||||||
|
|
||||||
|
state = GatewayState.CLOSED;
|
||||||
|
|
||||||
|
logger.info("永锋物流Rfid报警socket拉取网关:{}关闭成功", getInstanceVo().getRunId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void closePrevState() {
|
||||||
|
if (shouldRun != null) {
|
||||||
|
shouldRun.set(false);
|
||||||
|
shouldRun = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getActiveDeviceIds() {
|
||||||
|
Set<String> set = new HashSet<String>();
|
||||||
|
if (deviceId != null) {
|
||||||
|
set.add(deviceId);
|
||||||
|
}
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package com.cisdi.data.RFID.gateway;
|
||||||
|
|
||||||
|
import com.cisdi.data.sdk.gateway.base.PulledSocketGatewayBase;
|
||||||
|
import com.cisdi.data.sdk.param.PullSocketParam;
|
||||||
|
import com.cisdi.data.sdk.service.ServiceProvider;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
public class RfidTaskStartVo {
|
||||||
|
private AtomicBoolean shouldRun;
|
||||||
|
private ServiceProvider serviceProvider;
|
||||||
|
private String deviceId;
|
||||||
|
private PulledSocketGatewayBase gatewayBase;
|
||||||
|
private PullSocketParam socketParam;
|
||||||
|
private RfidCustomParam customParam;
|
||||||
|
private RfidDaemonTask rfidDaemonTask;
|
||||||
|
|
||||||
|
public AtomicBoolean getShouldRun() {
|
||||||
|
return shouldRun;
|
||||||
|
}
|
||||||
|
public void setShouldRun(AtomicBoolean shouldRun) {
|
||||||
|
this.shouldRun = shouldRun;
|
||||||
|
}
|
||||||
|
public ServiceProvider getServiceProvider() {
|
||||||
|
return serviceProvider;
|
||||||
|
}
|
||||||
|
public void setServiceProvider(ServiceProvider serviceProvider) {
|
||||||
|
this.serviceProvider = serviceProvider;
|
||||||
|
}
|
||||||
|
public String getDeviceId() {
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
public void setDeviceId(String deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
public PulledSocketGatewayBase getGatewayBase() {
|
||||||
|
return gatewayBase;
|
||||||
|
}
|
||||||
|
public void setGatewayBase(PulledSocketGatewayBase gatewayBase) {
|
||||||
|
this.gatewayBase = gatewayBase;
|
||||||
|
}
|
||||||
|
public PullSocketParam getSocketParam() {
|
||||||
|
return socketParam;
|
||||||
|
}
|
||||||
|
public void setSocketParam(PullSocketParam socketParam) {
|
||||||
|
this.socketParam = socketParam;
|
||||||
|
}
|
||||||
|
public RfidCustomParam getCustomParam() {
|
||||||
|
return customParam;
|
||||||
|
}
|
||||||
|
public void setCustomParam(RfidCustomParam customParam) {
|
||||||
|
this.customParam = customParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RfidDaemonTask getRfidDaemonTask() {
|
||||||
|
return rfidDaemonTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRfidDaemonTask(RfidDaemonTask rfidDaemonTask) {
|
||||||
|
this.rfidDaemonTask = rfidDaemonTask;
|
||||||
|
}
|
||||||
|
}
|
87
src/main/java/com/cisdi/data/RFID/gateway/RfidVoDecoder.java
Normal file
87
src/main/java/com/cisdi/data/RFID/gateway/RfidVoDecoder.java
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
package com.cisdi.data.RFID.gateway;
|
||||||
|
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import com.cisdi.data.util.HexUtil;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import io.netty.util.CharsetUtil;
|
||||||
|
import io.netty.util.ReferenceCountUtil;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class RfidVoDecoder {
|
||||||
|
|
||||||
|
public static List<RfidItemVo> Decode(ByteBuf in) {
|
||||||
|
RfidItemVo vo = new RfidItemVo();
|
||||||
|
List<RfidItemVo> result = new ArrayList<>();
|
||||||
|
//消息体部分
|
||||||
|
int length;
|
||||||
|
if (in == null) {
|
||||||
|
throw new BusinessException("ByteBuf 入参为null");
|
||||||
|
} else if (in.readableBytes() == 10) {
|
||||||
|
length = 8;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new BusinessException("报文长度不匹配 ,期望:10,实际:" + in.readableBytes());
|
||||||
|
}
|
||||||
|
//去掉报文头 和 结束符
|
||||||
|
ByteBuf proceedIn = in.retainedSlice(1, length);
|
||||||
|
result.add(split(proceedIn));
|
||||||
|
ReferenceCountUtil.release(proceedIn);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param in 去掉头尾的报文
|
||||||
|
* @Description: 拆分报文
|
||||||
|
* @author: Mo
|
||||||
|
* @Date: 2021/6/2 10:51
|
||||||
|
* @return: com.cisdi.data.RFID.gateway.RfidItemVo
|
||||||
|
*/
|
||||||
|
public static RfidItemVo split(ByteBuf in) {
|
||||||
|
RfidItemVo rfidItemVo = new RfidItemVo();
|
||||||
|
ByteBuf buf = in.readBytes(8);
|
||||||
|
// 编号
|
||||||
|
String code = buf.toString(CharsetUtil.UTF_8);
|
||||||
|
rfidItemVo.setCode(code);
|
||||||
|
ReferenceCountUtil.release(buf);
|
||||||
|
return rfidItemVo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
// 标签读取
|
||||||
|
// byte[] readBytes1 = HexUtil.hexStringToBytes("001c1952000b000e3000eabcdef01234567890003001000400000501");
|
||||||
|
// ByteBuf copiedBuffer = Unpooled.copiedBuffer(readBytes1);
|
||||||
|
// RfidItemVo decoderVo = RfidVoDecoder.Decode(copiedBuffer);
|
||||||
|
// logger.info("vo1={}", decoderVo);
|
||||||
|
//
|
||||||
|
// // 标签离开
|
||||||
|
// readBytes1 = HexUtil.hexStringToBytes("00161942050c000e3000eabcdef01234567890003001");
|
||||||
|
// copiedBuffer = Unpooled.copiedBuffer(readBytes1);
|
||||||
|
// decoderVo = RfidVoDecoder.Decode(copiedBuffer);
|
||||||
|
// logger.info("vo1={}", decoderVo);
|
||||||
|
|
||||||
|
//标签读取
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
byte[] readBytes1 = HexUtil.hexStringToBytes("02524630313030303103");
|
||||||
|
ByteBuf copiedBuff = Unpooled.copiedBuffer(readBytes1);
|
||||||
|
List<RfidItemVo> rfidItemVoList = RfidVoDecoder.Decode(copiedBuff);
|
||||||
|
rfidItemVoList.forEach(System.out::println);
|
||||||
|
|
||||||
|
|
||||||
|
readBytes1 = HexUtil.hexStringToBytes("0248656172744265617403");
|
||||||
|
copiedBuff = Unpooled.copiedBuffer(readBytes1);
|
||||||
|
rfidItemVoList = RfidVoDecoder.Decode(copiedBuff);
|
||||||
|
rfidItemVoList.forEach(System.out::println);
|
||||||
|
|
||||||
|
RfidFrameDecoder decoder = new RfidFrameDecoder(null);
|
||||||
|
readBytes1 = HexUtil.hexStringToBytes("0248656172744265617403");
|
||||||
|
copiedBuff = Unpooled.copiedBuffer(readBytes1);
|
||||||
|
decoder.decode(null, copiedBuff, new ArrayList<Object>());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,143 @@
|
|||||||
|
package com.cisdi.data.Spectrograph8860;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.cisdi.data.Spectrograph8860.impl.SGSessionFactory;
|
||||||
|
import com.cisdi.data.Spectrograph8860.impl.SGChannelInitializer;
|
||||||
|
import com.cisdi.data.Spectrograph8860.impl.SGIoSession;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import com.cisdi.data.sdk.consts.ServiceName;
|
||||||
|
import com.cisdi.data.sdk.enums.GatewayState;
|
||||||
|
import com.cisdi.data.sdk.gateway.base.SocketGatewayBase;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.IoSession;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.SessionFactory;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.TcpIoService;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.DefaultTcpIoService;
|
||||||
|
import com.cisdi.data.sdk.param.ListenSocketParam;
|
||||||
|
import com.cisdi.data.sdk.procotol.message.SocketReturnMessage;
|
||||||
|
import com.cisdi.data.sdk.service.PlatformService;
|
||||||
|
import com.cisdi.data.sdk.service.RouteService;
|
||||||
|
import com.cisdi.data.sdk.vo.DeviceVo;
|
||||||
|
import com.cisdi.data.sdk.vo.ExeResultVo;
|
||||||
|
import com.cisdi.data.sdk.vo.SslConfigVo;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
||||||
|
public class SGSocketGateway extends SocketGatewayBase {
|
||||||
|
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(SGSocketGateway.class);
|
||||||
|
|
||||||
|
TcpIoService ioService = null;
|
||||||
|
SessionFactory sessionFactory = null;
|
||||||
|
|
||||||
|
// 当配置为单个设备模式时,此为该设备id
|
||||||
|
String onlyOneDeviceId = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下发的时候,查配置路由,如果配置路由里面有匹配的,则走配置路由;如果没有匹配的,则原路返回
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ExeResultVo sendReturnMessage(SocketReturnMessage returnMsg) {
|
||||||
|
throw new BusinessException("光谱仪8860不支持下发服务!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
if (state == GatewayState.RUNNING) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("plc网关:{}读取启动配置参数:{},支持多个设备:{}", instanceVo.getRunId(), instanceVo.getParameter(),
|
||||||
|
instanceVo.getSuportMultiDevice());
|
||||||
|
|
||||||
|
// 不支持多个设备,必须强制配置一个设备id
|
||||||
|
if (instanceVo.getSuportMultiDevice() != null && instanceVo.getSuportMultiDevice() == false) {
|
||||||
|
RouteService routeService = (RouteService) serviceProvider.getByName(ServiceName.Route);
|
||||||
|
List<DeviceVo> deviceVos = routeService.findByRunId(instanceVo.getRunId());
|
||||||
|
|
||||||
|
if (deviceVos.size() > 1) {
|
||||||
|
throw new BusinessException("网关Id:" + instanceVo.getRunId() + "为光谱仪8860网关,当前配置为只支持单个设备,但配置了多个设备。");
|
||||||
|
}
|
||||||
|
|
||||||
|
onlyOneDeviceId = deviceVos.size() > 0 ? deviceVos.get(0).getDeviceId() : null;
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(onlyOneDeviceId)) {
|
||||||
|
throw new BusinessException("runId=" + getInstanceVo().getRunId() + "未正确配置网关和设备关联");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DefaultTcpIoService defaultIoService = new DefaultTcpIoService();
|
||||||
|
SessionFactory factory = new SGSessionFactory(onlyOneDeviceId);
|
||||||
|
factory.init(serviceProvider, this);
|
||||||
|
|
||||||
|
SslConfigVo sslConfigVo = null;
|
||||||
|
|
||||||
|
ListenSocketParam socketParam = JSON.parseObject(getInstanceVo().getParameter(), ListenSocketParam.class);
|
||||||
|
|
||||||
|
if (socketParam != null && Boolean.TRUE.equals(socketParam.getEnableSsl())) {
|
||||||
|
|
||||||
|
PlatformService platformService = (PlatformService) serviceProvider.getByName(ServiceName.Platform);
|
||||||
|
|
||||||
|
sslConfigVo = platformService.getSslConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SGChannelInitializer channelInitializer =
|
||||||
|
new SGChannelInitializer(factory, getInstanceVo().getByteOrder(), sslConfigVo);
|
||||||
|
|
||||||
|
defaultIoService.init(instanceVo, factory, channelInitializer);
|
||||||
|
|
||||||
|
ioService = defaultIoService;
|
||||||
|
sessionFactory = factory;
|
||||||
|
|
||||||
|
boolean open = ioService.open();
|
||||||
|
|
||||||
|
if (open == true) {
|
||||||
|
state = GatewayState.RUNNING;
|
||||||
|
logger.info("光谱仪8860网关:{}启动成功 参数:{}", instanceVo.getRunId(), getInstanceVo().getParameter());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
logger.info("光谱仪8860网关:{}启动失败 参数:{}", instanceVo.getRunId(), getInstanceVo().getParameter());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
if (state == GatewayState.CLOSED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sessionFactory != null) {
|
||||||
|
for (IoSession ioSession : sessionFactory.getSessions()) {
|
||||||
|
SGIoSession SGIoSession = (SGIoSession) ioSession;
|
||||||
|
SGIoSession.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean close = ioService.close();
|
||||||
|
if (close == true) {
|
||||||
|
sessionFactory = null;
|
||||||
|
state = GatewayState.CLOSED;
|
||||||
|
logger.info("光谱仪8860网关:{}关闭成功", instanceVo.getRunId());
|
||||||
|
} else {
|
||||||
|
logger.info("光谱仪8860网关:{}关闭失败", instanceVo.getRunId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getActiveDeviceIds() {
|
||||||
|
if (onlyOneDeviceId != null) {
|
||||||
|
Set<String> set = new HashSet<String>();
|
||||||
|
set.add(onlyOneDeviceId);
|
||||||
|
return set;
|
||||||
|
} else {
|
||||||
|
return sessionFactory.getActiveDeviceIds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package com.cisdi.data.Spectrograph8860.impl;
|
||||||
|
|
||||||
|
import com.cisdi.data.sdk.enums.ByteOrder;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.SessionFactory;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.AbstractChannelInitializer;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.AbstractIoChannelHandler;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.DefaultIoChannelHandler;
|
||||||
|
import com.cisdi.data.sdk.utils.NettySslUtils;
|
||||||
|
import com.cisdi.data.sdk.vo.SslConfigVo;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.ChannelHandler;
|
||||||
|
import io.netty.channel.socket.SocketChannel;
|
||||||
|
import io.netty.handler.timeout.IdleStateHandler;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SGChannelInitializer<I> extends AbstractChannelInitializer<I> {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(SGChannelInitializer.class);
|
||||||
|
|
||||||
|
private SessionFactory factory;
|
||||||
|
private ByteOrder byteOrder;
|
||||||
|
private SslConfigVo sslConfigVo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造通道初始化器对象
|
||||||
|
*
|
||||||
|
* @param factory 会话工厂
|
||||||
|
* @param byteOrder 大小端
|
||||||
|
* @param sslConfig ssl证书配置,如果不启用tls,传null
|
||||||
|
*/
|
||||||
|
public SGChannelInitializer(SessionFactory factory,
|
||||||
|
ByteOrder byteOrder,
|
||||||
|
SslConfigVo sslConfig) {
|
||||||
|
this.factory = factory;
|
||||||
|
this.byteOrder = byteOrder;
|
||||||
|
this.sslConfigVo = sslConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
protected AbstractIoChannelHandler<I> getTailHandler() {
|
||||||
|
return new DefaultIoChannelHandler(factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<ChannelHandler> getHandlers() {
|
||||||
|
List<ChannelHandler> handlers = new ArrayList<ChannelHandler>();
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IdleStateHandler getIdleStateHandler() {
|
||||||
|
return new IdleStateHandler(15, 15, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ChannelHandler getSslChannelHandler(Channel socketChannel) {
|
||||||
|
ChannelHandler sslHandler = null;
|
||||||
|
try {
|
||||||
|
if (sslConfigVo != null) {
|
||||||
|
sslHandler = NettySslUtils.getServerSslHandler((SocketChannel) socketChannel, sslConfigVo);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.warn(e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
return sslHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Binary file not shown.
@ -0,0 +1,23 @@
|
|||||||
|
package com.cisdi.data.Spectrograph8860.impl;
|
||||||
|
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.IoSession;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.AbstractSessionFactory;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class SGSessionFactory extends AbstractSessionFactory {
|
||||||
|
|
||||||
|
private String onlyOneDeviceId;
|
||||||
|
|
||||||
|
public SGSessionFactory(String onlyoneDeviceId) {
|
||||||
|
this.onlyOneDeviceId = onlyoneDeviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IoSession newSession() {
|
||||||
|
IoSession session = new SGIoSession(this, onlyOneDeviceId);
|
||||||
|
session.init(UUID.randomUUID().toString(), provider, socketGateway);
|
||||||
|
sessionSet.add(session);
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.cisdi.data.Spectrograph8860.test;
|
||||||
|
|
||||||
|
import com.cisdi.data.sdk.service.Service;
|
||||||
|
import com.cisdi.data.sdk.service.ServiceProvider;
|
||||||
|
|
||||||
|
public class ServiceProviderTest implements ServiceProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Service getByName(String name) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package com.cisdi.data.Spectrograph8860.test;
|
||||||
|
|
||||||
|
import com.cisdi.data.Spectrograph8860.SGSocketGateway;
|
||||||
|
import com.cisdi.data.Spectrograph8860.impl.SGSessionFactory;
|
||||||
|
import com.cisdi.data.Spectrograph8860.impl.SGChannelInitializer;
|
||||||
|
import com.cisdi.data.sdk.enums.ByteOrder;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.SessionFactory;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.TcpIoService;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.DefaultTcpIoService;
|
||||||
|
import com.cisdi.data.sdk.vo.GatewayVo;
|
||||||
|
import io.netty.handler.ssl.OpenSsl;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class StartPlcTest {
|
||||||
|
private static Logger logger = LoggerFactory.getLogger(SGSocketGateway.class);
|
||||||
|
|
||||||
|
private static TcpIoService ioService = null;
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private static SessionFactory sessionFactory = null;
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
boolean available = OpenSsl.isAvailable();
|
||||||
|
logger.info("openssl available={}", available);
|
||||||
|
|
||||||
|
DefaultTcpIoService defaultIoService = new DefaultTcpIoService();
|
||||||
|
SessionFactory factory = new SGSessionFactory(null);
|
||||||
|
|
||||||
|
ServiceProviderTest testServiceProvider = new ServiceProviderTest();
|
||||||
|
//String passthroughAddress = "192.168.235.1:9098";
|
||||||
|
|
||||||
|
factory.init(testServiceProvider, null);
|
||||||
|
|
||||||
|
SGChannelInitializer channelInitializer =
|
||||||
|
new SGChannelInitializer(factory, ByteOrder.BIGENDIAN, null);
|
||||||
|
|
||||||
|
GatewayVo instanceVo = new GatewayVo();
|
||||||
|
instanceVo.setByteOrder(ByteOrder.BIGENDIAN);
|
||||||
|
instanceVo.setParameter("{\"listenIp\":\"10.76.49.121\",\"listenPort\":5002,\"threadSize\":50,\"timeout\":2000}");
|
||||||
|
|
||||||
|
defaultIoService.init(instanceVo, factory, channelInitializer);
|
||||||
|
|
||||||
|
ioService = defaultIoService;
|
||||||
|
sessionFactory = factory;
|
||||||
|
|
||||||
|
boolean open = ioService.open();
|
||||||
|
|
||||||
|
if (open == true) {
|
||||||
|
logger.info("plc网关启动成功");
|
||||||
|
} else {
|
||||||
|
logger.info("plc网关启动失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(10000000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
145
src/main/java/com/cisdi/data/XRFLEFT/XRFLEFTSocketGateway.java
Normal file
145
src/main/java/com/cisdi/data/XRFLEFT/XRFLEFTSocketGateway.java
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
package com.cisdi.data.XRFLEFT;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.cisdi.data.XRFLEFT.impl.XRFLeftChannelInitializer;
|
||||||
|
import com.cisdi.data.XRFLEFT.impl.XRFLeftIoSession;
|
||||||
|
import com.cisdi.data.XRFLEFT.impl.XRFLeftSessionFactory;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import com.cisdi.data.sdk.consts.ServiceName;
|
||||||
|
import com.cisdi.data.sdk.enums.GatewayState;
|
||||||
|
import com.cisdi.data.sdk.gateway.base.SocketGatewayBase;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.IoSession;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.SessionFactory;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.TcpIoService;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.DefaultTcpIoService;
|
||||||
|
import com.cisdi.data.sdk.param.ListenSocketParam;
|
||||||
|
import com.cisdi.data.sdk.procotol.message.SocketReturnMessage;
|
||||||
|
import com.cisdi.data.sdk.service.PlatformService;
|
||||||
|
import com.cisdi.data.sdk.service.RouteService;
|
||||||
|
import com.cisdi.data.sdk.vo.DeviceVo;
|
||||||
|
import com.cisdi.data.sdk.vo.ExeResultVo;
|
||||||
|
import com.cisdi.data.sdk.vo.SslConfigVo;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 左侧荧光仪 10.233.2.132
|
||||||
|
* @author cuianbing
|
||||||
|
* @date 2021/7/15 9:27
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class XRFLEFTSocketGateway extends SocketGatewayBase {
|
||||||
|
|
||||||
|
|
||||||
|
TcpIoService ioService = null;
|
||||||
|
SessionFactory sessionFactory = null;
|
||||||
|
|
||||||
|
// 当配置为单个设备模式时,此为该设备id
|
||||||
|
String onlyOneDeviceId = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExeResultVo sendReturnMessage(SocketReturnMessage socketReturnMessage) {
|
||||||
|
throw new BusinessException("X射线荧光光谱仪不支持下发服务!");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
if (state == GatewayState.RUNNING){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log.info("网关:{}读取启动配置参数:{},是否支持支持多个设备:{}", instanceVo.getRunId(), instanceVo.getParameter(),
|
||||||
|
instanceVo.getSuportMultiDevice());
|
||||||
|
|
||||||
|
|
||||||
|
// 不支持多个设备,必须强制配置一个设备id
|
||||||
|
if (instanceVo.getSuportMultiDevice() != null && instanceVo.getSuportMultiDevice() == false) {
|
||||||
|
RouteService routeService = (RouteService) serviceProvider.getByName(ServiceName.Route);
|
||||||
|
List<DeviceVo> deviceVos = routeService.findByRunId(instanceVo.getRunId());
|
||||||
|
|
||||||
|
if (deviceVos.size() > 1) {
|
||||||
|
throw new BusinessException("网关Id:" + instanceVo.getRunId() + "为X射线荧光光谱仪网关,当前配置为只支持单个设备,但配置了多个设备。");
|
||||||
|
}
|
||||||
|
|
||||||
|
onlyOneDeviceId = deviceVos.size() > 0 ? deviceVos.get(0).getDeviceId() : null;
|
||||||
|
|
||||||
|
if (StringUtils.isEmpty(onlyOneDeviceId)) {
|
||||||
|
throw new BusinessException("runId=" + getInstanceVo().getRunId() + "未正确配置网关和设备关联");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DefaultTcpIoService defaultIoService = new DefaultTcpIoService();
|
||||||
|
SessionFactory factory = new XRFLeftSessionFactory(onlyOneDeviceId);
|
||||||
|
factory.init(serviceProvider, this);
|
||||||
|
|
||||||
|
SslConfigVo sslConfigVo = null;
|
||||||
|
|
||||||
|
ListenSocketParam socketParam = JSON.parseObject(getInstanceVo().getParameter(), ListenSocketParam.class);
|
||||||
|
|
||||||
|
if (socketParam != null && Boolean.TRUE.equals(socketParam.getEnableSsl())) {
|
||||||
|
|
||||||
|
PlatformService platformService = (PlatformService) serviceProvider.getByName(ServiceName.Platform);
|
||||||
|
|
||||||
|
sslConfigVo = platformService.getSslConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
XRFLeftChannelInitializer channelInitializer =
|
||||||
|
new XRFLeftChannelInitializer(factory, getInstanceVo().getByteOrder(), sslConfigVo);
|
||||||
|
|
||||||
|
defaultIoService.init(instanceVo, factory, channelInitializer);
|
||||||
|
|
||||||
|
ioService = defaultIoService;
|
||||||
|
sessionFactory = factory;
|
||||||
|
|
||||||
|
boolean open = ioService.open();
|
||||||
|
|
||||||
|
if (open == true) {
|
||||||
|
state = GatewayState.RUNNING;
|
||||||
|
log.info("X射线荧光光谱仪网关:{}启动成功 参数:{}", instanceVo.getRunId(), getInstanceVo().getParameter());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
log.info("X射线荧光光谱仪网关:{}启动失败 参数:{}", instanceVo.getRunId(), getInstanceVo().getParameter());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
if (state == GatewayState.CLOSED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sessionFactory != null) {
|
||||||
|
for (IoSession ioSession : sessionFactory.getSessions()) {
|
||||||
|
XRFLeftIoSession XrfIoSession = (XRFLeftIoSession) ioSession;
|
||||||
|
XrfIoSession.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean close = ioService.close();
|
||||||
|
if (close == true) {
|
||||||
|
sessionFactory = null;
|
||||||
|
state = GatewayState.CLOSED;
|
||||||
|
log.info("X射线荧光光谱仪网关:{}关闭成功", instanceVo.getRunId());
|
||||||
|
} else {
|
||||||
|
log.info("X射线荧光光谱仪网关:{}关闭失败", instanceVo.getRunId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getActiveDeviceIds() {
|
||||||
|
if (onlyOneDeviceId != null) {
|
||||||
|
Set<String> set = new HashSet<String>();
|
||||||
|
set.add(onlyOneDeviceId);
|
||||||
|
return set;
|
||||||
|
} else {
|
||||||
|
return sessionFactory.getActiveDeviceIds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
package com.cisdi.data.XRFLEFT.impl;
|
||||||
|
|
||||||
|
import com.cisdi.data.sdk.enums.ByteOrder;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.SessionFactory;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.AbstractChannelInitializer;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.AbstractIoChannelHandler;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.DefaultIoChannelHandler;
|
||||||
|
import com.cisdi.data.sdk.utils.NettySslUtils;
|
||||||
|
import com.cisdi.data.sdk.vo.SslConfigVo;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.ChannelHandler;
|
||||||
|
import io.netty.channel.socket.SocketChannel;
|
||||||
|
import io.netty.handler.timeout.IdleStateHandler;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cuianbing
|
||||||
|
* @version 1.0
|
||||||
|
* @description: TODO
|
||||||
|
* @date 2021/7/7 18:57
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class XRFLeftChannelInitializer<I> extends AbstractChannelInitializer<I> {
|
||||||
|
|
||||||
|
private SessionFactory factory;
|
||||||
|
private ByteOrder byteOrder;
|
||||||
|
private SslConfigVo sslConfigVo;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造通道初始化器对象
|
||||||
|
* @param factory 会话工厂
|
||||||
|
* @param byteOrder 大小端
|
||||||
|
* @param sslConfig ssl证书配置,如果不启用tls,传null
|
||||||
|
*/
|
||||||
|
public XRFLeftChannelInitializer(SessionFactory factory,
|
||||||
|
ByteOrder byteOrder,
|
||||||
|
SslConfigVo sslConfig) {
|
||||||
|
this.factory = factory;
|
||||||
|
this.byteOrder = byteOrder;
|
||||||
|
this.sslConfigVo = sslConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AbstractIoChannelHandler<I> getTailHandler() {
|
||||||
|
return new DefaultIoChannelHandler(factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<ChannelHandler> getHandlers() {
|
||||||
|
List<ChannelHandler> handlers = new ArrayList<ChannelHandler>();
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IdleStateHandler getIdleStateHandler() {
|
||||||
|
return new IdleStateHandler(15, 15, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ChannelHandler getSslChannelHandler(Channel socketChannel) {
|
||||||
|
ChannelHandler sslHandler = null;
|
||||||
|
try {
|
||||||
|
if(sslConfigVo != null) {
|
||||||
|
sslHandler = NettySslUtils.getServerSslHandler((SocketChannel)socketChannel, sslConfigVo);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn(e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
return sslHandler;
|
||||||
|
}
|
||||||
|
}
|
198
src/main/java/com/cisdi/data/XRFLEFT/impl/XRFLeftIoSession.java
Normal file
198
src/main/java/com/cisdi/data/XRFLEFT/impl/XRFLeftIoSession.java
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
package com.cisdi.data.XRFLEFT.impl;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.cisdi.data.common.exception.BusinessException;
|
||||||
|
import com.cisdi.data.sdk.consts.ServiceName;
|
||||||
|
import com.cisdi.data.sdk.gateway.message.SocketMessage;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.IoSession;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.AbstractIoSession;
|
||||||
|
import com.cisdi.data.sdk.service.PassthroughService;
|
||||||
|
import com.cisdi.data.sdk.service.SendService;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.ByteBufAllocator;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 荧光光谱仪左侧解码
|
||||||
|
* @author cuianbing
|
||||||
|
* @date 2021/7/15 9:19
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class XRFLeftIoSession extends AbstractIoSession implements IoSession {
|
||||||
|
|
||||||
|
private XRFLeftSessionFactory factory = null;
|
||||||
|
|
||||||
|
private String deviceId = null;
|
||||||
|
/**
|
||||||
|
* 如果有值,代表所有会话都使用这一个设备id,且允许多会话共享此一个设备id,不除旧会话
|
||||||
|
*/
|
||||||
|
private final String onlyOneDeviceId;
|
||||||
|
|
||||||
|
private String gwPrefixCache = null;
|
||||||
|
|
||||||
|
private ByteBuf allBuf = ByteBufAllocator.DEFAULT.buffer();
|
||||||
|
|
||||||
|
|
||||||
|
public XRFLeftIoSession(XRFLeftSessionFactory factory, String onlyOneDeviceId) {
|
||||||
|
super();
|
||||||
|
this.factory = factory;
|
||||||
|
this.onlyOneDeviceId = onlyOneDeviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getDeviceIds() {
|
||||||
|
String cpDeviceId = deviceId;
|
||||||
|
String[] result = new String[cpDeviceId == null ? 0 : 1];
|
||||||
|
if (cpDeviceId != null) {
|
||||||
|
result[0] = cpDeviceId;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRead(Object message) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
ByteBuf inBuf = (ByteBuf) message;
|
||||||
|
if (inBuf != null) {
|
||||||
|
allBuf.writeBytes(inBuf);
|
||||||
|
}else {
|
||||||
|
log.info("电文格式为空");
|
||||||
|
}
|
||||||
|
}catch (Exception e){
|
||||||
|
log.error("电文格式错误!");
|
||||||
|
throw new BusinessException("电文格式错误!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onOpen() {
|
||||||
|
super.onOpen();
|
||||||
|
log.info("建立连接,channel:{}", getChannel());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClose() {
|
||||||
|
log.info("onClose");
|
||||||
|
List<Map<String,String>> messages = decode(allBuf);
|
||||||
|
Map<String, Object> sendMessage =new HashMap<>();
|
||||||
|
|
||||||
|
if (serviceProvider != null && socketGateway != null) {
|
||||||
|
for (Map<String,String> message : messages){
|
||||||
|
sendMessage.put("data",message);
|
||||||
|
SendService service = (SendService) serviceProvider.getByName(ServiceName.Send);
|
||||||
|
SocketMessage socketMessage = socketGateway.buildSocketMessage();
|
||||||
|
socketMessage.setDeviceId(onlyOneDeviceId);
|
||||||
|
socketMessage.setData(JSON.toJSONString(sendMessage).getBytes(StandardCharsets.UTF_8));
|
||||||
|
socketMessage.setMsgKey("default");
|
||||||
|
service.sendMessage(socketMessage);
|
||||||
|
if (socketGateway.getInstanceVo().getLogOpen()) {
|
||||||
|
log.info("类似为:{}:发送消息内容{}", sendMessage.get("data"), sendMessage.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.onClose();
|
||||||
|
factory = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
if (getChannel() != null) {
|
||||||
|
try {
|
||||||
|
getChannel().close().sync();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.warn(e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onError(Throwable t) {
|
||||||
|
// 这里会出现 java.io.IOException: 远程主机强迫关闭了一个现有的连接。
|
||||||
|
log.info("远程主机强迫关闭了一个现有的连接。");
|
||||||
|
// log.error("session exception:{}", t);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<Map<String,String>> decode(ByteBuf byteBuf){
|
||||||
|
|
||||||
|
List<Map<String,String>> dataList= new ArrayList<>();
|
||||||
|
AtomicInteger dataFlag = new AtomicInteger();
|
||||||
|
Map<String,String> data = null;
|
||||||
|
|
||||||
|
String msg = byteBuf.toString(Charset.forName("GB2312"));
|
||||||
|
|
||||||
|
log.debug("{}",msg);
|
||||||
|
String[] split = msg.split("\n\r");
|
||||||
|
for (String s: split){
|
||||||
|
char tag = s.charAt(0);
|
||||||
|
if (tag == '3'){
|
||||||
|
String[] dataArray = s.split("\\s+");
|
||||||
|
if (dataArray.length > 1){ // 分析错误会出现 `3 (Error) `的数据
|
||||||
|
assert data != null;
|
||||||
|
data.put(dataArray[1],dataArray[2]);
|
||||||
|
}
|
||||||
|
}else if (tag == '2'){
|
||||||
|
if (dataFlag.getAndIncrement() > 0){
|
||||||
|
log.debug("解析的数据为:{}",data);
|
||||||
|
dataList.add(data);
|
||||||
|
}
|
||||||
|
data = new HashMap<>();
|
||||||
|
//2 高炉渣 323 2021- 7-14 15:41 101
|
||||||
|
String[] dateArray = s.split("\\s+");
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
// 时间会出现多余空格的问题 2021- 7-14 15:41 ,但是10月之后就可以
|
||||||
|
for (int i = 3 , j = dateArray.length - 1 ; i < j ; i++){
|
||||||
|
builder.append(dateArray[i]);
|
||||||
|
}
|
||||||
|
data.put("分析方法",dateArray[1]);
|
||||||
|
data.put("样品名称",dateArray[2]);
|
||||||
|
data.put("分析时间",builder.toString());
|
||||||
|
}else if(tag == '5'){
|
||||||
|
dataList.add(data);
|
||||||
|
log.debug("解析的数据为:{}",data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
allBuf.clear();
|
||||||
|
log.info("所有的的数据为:{}",dataList);
|
||||||
|
return dataList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void passThrough(ByteBuf passthroughBuf) {
|
||||||
|
try {
|
||||||
|
if (serviceProvider != null && socketGateway != null) {
|
||||||
|
PassthroughService service = (PassthroughService) serviceProvider.getByName(ServiceName.Passthrough);
|
||||||
|
service.transfer(passthroughBuf, socketGateway.getInstanceVo().getPassthroughAddress());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("荧光光谱仪协议透传失败:" + e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String gwPrefix() {
|
||||||
|
if (gwPrefixCache != null) {
|
||||||
|
return gwPrefixCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
gwPrefixCache = "";
|
||||||
|
if (socketGateway != null && socketGateway.getInstanceVo() != null) {
|
||||||
|
gwPrefixCache = "网关Id:" + socketGateway.getInstanceVo().getRunId() + "连接:" + getChannel() + " ";
|
||||||
|
} else {
|
||||||
|
gwPrefixCache = "连接:" + getChannel() + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return gwPrefixCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
package com.cisdi.data.XRFLEFT.impl;
|
||||||
|
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.IoSession;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.AbstractSessionFactory;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cuianbing
|
||||||
|
* @version 1.0
|
||||||
|
* @description: TODO
|
||||||
|
* @date 2021/7/7 18:52
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class XRFLeftSessionFactory extends AbstractSessionFactory {
|
||||||
|
|
||||||
|
private String onlyOneDeviceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description:
|
||||||
|
* @param: onlyOneDeviceId 设备唯一ID
|
||||||
|
* @return: void
|
||||||
|
* @author cuianbing
|
||||||
|
* @date: 2021/7/7 22:10
|
||||||
|
*/
|
||||||
|
public XRFLeftSessionFactory(String onlyOneDeviceId) {
|
||||||
|
this.onlyOneDeviceId = onlyOneDeviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IoSession newSession() {
|
||||||
|
IoSession session = new XRFLeftIoSession(this, onlyOneDeviceId);
|
||||||
|
session.init(UUID.randomUUID().toString(), provider, socketGateway);
|
||||||
|
sessionSet.add(session);
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.cisdi.data.XRFLEFT.test;
|
||||||
|
|
||||||
|
import com.cisdi.data.sdk.service.Service;
|
||||||
|
import com.cisdi.data.sdk.service.ServiceProvider;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cuianbing
|
||||||
|
* @version 1.0
|
||||||
|
* @description: TODO
|
||||||
|
* @date 2021/7/7 19:17
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class ServiceProviderTest implements ServiceProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Service getByName(String name) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
65
src/main/java/com/cisdi/data/XRFLEFT/test/StartTest.java
Normal file
65
src/main/java/com/cisdi/data/XRFLEFT/test/StartTest.java
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package com.cisdi.data.XRFLEFT.test;
|
||||||
|
|
||||||
|
import com.cisdi.data.XRFRIGHT.impl.XRFRightChannelInitializer;
|
||||||
|
import com.cisdi.data.XRFRIGHT.impl.XRFRightSessionFactory;
|
||||||
|
import com.cisdi.data.sdk.enums.ByteOrder;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.SessionFactory;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.TcpIoService;
|
||||||
|
import com.cisdi.data.sdk.gateway.netty.impl.DefaultTcpIoService;
|
||||||
|
import com.cisdi.data.sdk.vo.GatewayVo;
|
||||||
|
import io.netty.handler.ssl.OpenSsl;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author cuianbing
|
||||||
|
* @version 1.0
|
||||||
|
* @description: TODO
|
||||||
|
* @date 2021/7/7 19:28
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class StartTest {
|
||||||
|
|
||||||
|
private static TcpIoService ioService = null;
|
||||||
|
|
||||||
|
private static SessionFactory sessionFactory = null;
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
boolean available = OpenSsl.isAvailable();
|
||||||
|
log.info("openssl available={}", available);
|
||||||
|
|
||||||
|
DefaultTcpIoService defaultIoService = new DefaultTcpIoService();
|
||||||
|
|
||||||
|
SessionFactory factory = new XRFRightSessionFactory(null);
|
||||||
|
|
||||||
|
ServiceProviderTest testServiceProvider = new ServiceProviderTest();
|
||||||
|
|
||||||
|
factory.init(testServiceProvider, null);
|
||||||
|
|
||||||
|
XRFRightChannelInitializer channelInitializer =
|
||||||
|
new XRFRightChannelInitializer(factory, ByteOrder.BIGENDIAN, null);
|
||||||
|
|
||||||
|
GatewayVo instanceVo = new GatewayVo();
|
||||||
|
instanceVo.setByteOrder(ByteOrder.BIGENDIAN);
|
||||||
|
instanceVo.setParameter("{\"listenIp\":\"0.0.0.0\",\"listenPort\":8888,\"threadSize\":50,\"timeout\":2000}");
|
||||||
|
|
||||||
|
defaultIoService.init(instanceVo, factory, channelInitializer);
|
||||||
|
|
||||||
|
ioService = defaultIoService;
|
||||||
|
sessionFactory = factory;
|
||||||
|
|
||||||
|
boolean open = ioService.open();
|
||||||
|
|
||||||
|
if (open == true) {
|
||||||
|
log.info("plc网关启动成功");
|
||||||
|
} else {
|
||||||
|
log.info("plc网关启动失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(10000000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user