Browse Source

first commit

main
GG 5 months ago
commit
05ba53f444
  1. 14
      .gitignore
  2. 30
      HELP.md
  3. 0
      README.md
  4. 1
      compose.yaml
  5. 308
      mvnw
  6. 205
      mvnw.cmd
  7. 224
      pom.xml
  8. 60
      src/main/java/com/zgx/iot/MilitaryMqttApplication.java
  9. 58
      src/main/java/com/zgx/iot/MilitaryNettyApplication.java
  10. 171
      src/main/java/com/zgx/iot/MilitarySocketApplication.java
  11. 684
      src/main/java/com/zgx/iot/MilitaryZMQApplication.java
  12. 54
      src/main/java/com/zgx/iot/SystemApplication.java
  13. 43
      src/main/java/com/zgx/iot/api/DeviceInfoAPI.java
  14. 4
      src/main/java/com/zgx/iot/api/ServiceAPI.java
  15. 4
      src/main/java/com/zgx/iot/api/mq/MQManager.java
  16. 4
      src/main/java/com/zgx/iot/api/mq/MQService.java
  17. 4
      src/main/java/com/zgx/iot/api/mq/MQTTServiceimpl.java
  18. 140
      src/main/java/com/zgx/iot/base/BaseMap.java
  19. 48
      src/main/java/com/zgx/iot/client/ClientProtocalFactory.java
  20. 34
      src/main/java/com/zgx/iot/client/ClientProtocalManager.java
  21. 30
      src/main/java/com/zgx/iot/client/IClientProtocal.java
  22. 61
      src/main/java/com/zgx/iot/client/impl/ProtocalLadarYS.java
  23. 36
      src/main/java/com/zgx/iot/common/Cache.java
  24. 36
      src/main/java/com/zgx/iot/common/Code.java
  25. 8
      src/main/java/com/zgx/iot/common/Config.java
  26. 105
      src/main/java/com/zgx/iot/common/Constants.java
  27. 73
      src/main/java/com/zgx/iot/config/mqtt/MQTTProps.java
  28. 80
      src/main/java/com/zgx/iot/config/socket/ssl/NettyProps.java
  29. 4
      src/main/java/com/zgx/iot/config/socket/ssl/SslConfig.java
  30. 94
      src/main/java/com/zgx/iot/constant/CacheConstant.java
  31. 14
      src/main/java/com/zgx/iot/constant/GlobalConstants.java
  32. 30
      src/main/java/com/zgx/iot/constant/SocketConstant.java
  33. 64
      src/main/java/com/zgx/iot/constant/WebsocketConst.java
  34. 33
      src/main/java/com/zgx/iot/constant/enums/AlarmType.java
  35. 27
      src/main/java/com/zgx/iot/constant/enums/AlarmType2.java
  36. 27
      src/main/java/com/zgx/iot/constant/enums/CameraType.java
  37. 25
      src/main/java/com/zgx/iot/constant/enums/DateType.java
  38. 28
      src/main/java/com/zgx/iot/constant/enums/DeviceComp.java
  39. 29
      src/main/java/com/zgx/iot/constant/enums/DeviceType.java
  40. 54
      src/main/java/com/zgx/iot/constant/enums/FaultItem.java
  41. 37
      src/main/java/com/zgx/iot/constant/enums/FaultResult.java
  42. 38
      src/main/java/com/zgx/iot/constant/enums/FenceType.java
  43. 30
      src/main/java/com/zgx/iot/constant/enums/Invade.java
  44. 27
      src/main/java/com/zgx/iot/constant/enums/StateType.java
  45. 27
      src/main/java/com/zgx/iot/constant/enums/TargetType.java
  46. 18
      src/main/java/com/zgx/iot/constant/enums/WarnLevel.java
  47. 18
      src/main/java/com/zgx/iot/constant/enums/WarnType.java
  48. 248
      src/main/java/com/zgx/iot/controller/TrackingTargetController.java
  49. 22
      src/main/java/com/zgx/iot/dto/Brower2LpmDto.java
  50. 52
      src/main/java/com/zgx/iot/dto/radar/NyGuideCamPosModel.java
  51. 87
      src/main/java/com/zgx/iot/dto/radar/RadarRESPackageModel.java
  52. 101
      src/main/java/com/zgx/iot/dto/radar/RadarStateModel.java
  53. 91
      src/main/java/com/zgx/iot/dto/radar/RadarTargetModel.java
  54. 225
      src/main/java/com/zgx/iot/dto/radar/RadarTrackModel.java
  55. 29
      src/main/java/com/zgx/iot/dto/radar/TrackingTargetDTO.java
  56. 120
      src/main/java/com/zgx/iot/dto/site/AisInfo.java
  57. 101
      src/main/java/com/zgx/iot/dto/site/AlarmInfo.java
  58. 325
      src/main/java/com/zgx/iot/dto/site/CommonConstant.java
  59. 66
      src/main/java/com/zgx/iot/dto/site/DeveiceType.java
  60. 133
      src/main/java/com/zgx/iot/dto/site/DeviceInfo.java
  61. 44
      src/main/java/com/zgx/iot/dto/site/DeviceStatus.java
  62. 159
      src/main/java/com/zgx/iot/dto/site/Result.java
  63. 75
      src/main/java/com/zgx/iot/dto/site/SysDictItem.java
  64. 195
      src/main/java/com/zgx/iot/entity/DtDeviceInfo.java
  65. 67
      src/main/java/com/zgx/iot/entity/MsAlarmSettings.java
  66. 112
      src/main/java/com/zgx/iot/entity/MsCameraSetting.java
  67. 50
      src/main/java/com/zgx/iot/entity/MsModelPosition.java
  68. 55
      src/main/java/com/zgx/iot/entity/MsModelTrajectory.java
  69. 16
      src/main/java/com/zgx/iot/mapper/DtDeviceInfoMapper.java
  70. 18
      src/main/java/com/zgx/iot/mapper/MsAlarmSettingsMapper.java
  71. 29
      src/main/java/com/zgx/iot/mapper/MsCameraSettingMapper.java
  72. 17
      src/main/java/com/zgx/iot/mapper/MsModelPositionMapper.java
  73. 22
      src/main/java/com/zgx/iot/mapper/MsModelTrajectoryMapper.java
  74. 6
      src/main/java/com/zgx/iot/mapper/xml/DtDeviceInfoMapper.xml
  75. 6
      src/main/java/com/zgx/iot/mapper/xml/MsAlarmSettingsMapper.xml
  76. 38
      src/main/java/com/zgx/iot/mapper/xml/MsCameraSettingMapper.xml
  77. 5
      src/main/java/com/zgx/iot/mapper/xml/MsModelPositionMapper.xml
  78. 16
      src/main/java/com/zgx/iot/mapper/xml/MsModelTrajectoryMapper.xml
  79. 165
      src/main/java/com/zgx/iot/message/websocket/WebSocket.java
  80. 102
      src/main/java/com/zgx/iot/mq/mqtt/MessageCallback.java
  81. 50
      src/main/java/com/zgx/iot/mq/mqtt/MessageHandler.java
  82. 166
      src/main/java/com/zgx/iot/mq/mqtt/MqttService.java
  83. 821
      src/main/java/com/zgx/iot/mq/mqtt/handle/RadarHandler.java
  84. 20
      src/main/java/com/zgx/iot/mq/mqtt/model/radar/TargetMessage.java
  85. 203
      src/main/java/com/zgx/iot/netty/NettyServiceManage.java
  86. 42
      src/main/java/com/zgx/iot/netty/config/AppServiceConfig.java
  87. 20
      src/main/java/com/zgx/iot/netty/constant/AttributeMapConstant.java
  88. 21
      src/main/java/com/zgx/iot/netty/constant/CustomLogLevel.java
  89. 150
      src/main/java/com/zgx/iot/netty/constant/DeviceRelations.java
  90. 36
      src/main/java/com/zgx/iot/netty/constant/HandlerDataType.java
  91. 74
      src/main/java/com/zgx/iot/netty/constant/SocketType.java
  92. 239
      src/main/java/com/zgx/iot/netty/constant/device/MicrowaveDetectorConstant.java
  93. 12
      src/main/java/com/zgx/iot/netty/exception/CompletableFutureException.java
  94. 12
      src/main/java/com/zgx/iot/netty/exception/DeviceInfoException.java
  95. 12
      src/main/java/com/zgx/iot/netty/exception/NettyServiceControllerException.java
  96. 57
      src/main/java/com/zgx/iot/netty/handler/ConnectHandler.java
  97. 168
      src/main/java/com/zgx/iot/netty/handler/ExceptionHandler.java
  98. 87
      src/main/java/com/zgx/iot/netty/handler/codec/MicrowaveDetectorMessageClientDecoder.java
  99. 81
      src/main/java/com/zgx/iot/netty/handler/codec/MicrowaveDetectorMessageServiceDecoder.java
  100. 105
      src/main/java/com/zgx/iot/netty/handler/codec/RadarDetectorMessageServiceDecoder.java

14
.gitignore

@ -0,0 +1,14 @@
### Example user template template
### Example user template
# IntelliJ project files
.idea
*.iml
out
gen
/target/
/mqttlogs/debug/debug-Arvin.log
/mqttlogs/error/error-Arvin.log
/mqttlogs/info/info-Arvin.log
mqttlogs
db

30
HELP.md

@ -0,0 +1,30 @@
# Read Me First
The following was discovered as part of building this project:
* No Docker Compose services found. As of now, the application won't start! Please add at least one service to
the `compose.yaml` file.
* The JVM level was changed from '1.8' to '17', review
the [JDK Version Range](https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-Versions#jdk-version-range)
on the wiki for more details.
# Getting Started
### Reference Documentation
For further reference, please consider the following sections:
* [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/3.1.3/maven-plugin/reference/html/)
* [Create an OCI image](https://docs.spring.io/spring-boot/docs/3.1.3/maven-plugin/reference/html/#build-image)
* [Spring Boot DevTools](https://docs.spring.io/spring-boot/docs/3.1.3/reference/htmlsingle/index.html#using.devtools)
* [Docker Compose Support](https://docs.spring.io/spring-boot/docs/3.1.3/reference/htmlsingle/index.html#features.docker-compose)
### Docker Compose support
This project contains a Docker Compose file named `compose.yaml`.
However, no services were found. As of now, the application won't start!
Please make sure to add at least one service in the `compose.yaml` file.

0
README.md

1
compose.yaml

@ -0,0 +1 @@
services:

308
mvnw

@ -0,0 +1,308 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.2.0
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /usr/local/etc/mavenrc ] ; then
. /usr/local/etc/mavenrc
fi
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "$(uname)" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
else
JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=$(java-config --jre-home)
fi
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="$(which javac)"
if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=$(which readlink)
if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
if $darwin ; then
javaHome="$(dirname "\"$javaExecutable\"")"
javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
else
javaExecutable="$(readlink -f "\"$javaExecutable\"")"
fi
javaHome="$(dirname "\"$javaExecutable\"")"
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=$(cd "$wdir/.." || exit 1; pwd)
fi
# end of workaround
done
printf '%s' "$(cd "$basedir" || exit 1; pwd)"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
# Remove \r in case we run on Windows within Git Bash
# and check out the repository with auto CRLF management
# enabled. Otherwise, we may read lines that are delimited with
# \r\n and produce $'-Xarg\r' rather than -Xarg due to word
# splitting rules.
tr -s '\r\n' ' ' < "$1"
fi
}
log() {
if [ "$MVNW_VERBOSE" = true ]; then
printf '%s\n' "$1"
fi
}
BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
log "$MAVEN_PROJECTBASEDIR"
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
if [ -r "$wrapperJarPath" ]; then
log "Found $wrapperJarPath"
else
log "Couldn't find $wrapperJarPath, downloading it ..."
if [ -n "$MVNW_REPOURL" ]; then
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
else
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
fi
while IFS="=" read -r key value; do
# Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
safeValue=$(echo "$value" | tr -d '\r')
case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
log "Downloading from: $wrapperUrl"
if $cygwin; then
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
fi
if command -v wget > /dev/null; then
log "Found wget ... using wget"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
else
wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
log "Found curl ... using curl"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
else
curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
fi
else
log "Falling back to using Java to download"
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaSource=$(cygpath --path --windows "$javaSource")
javaClass=$(cygpath --path --windows "$javaClass")
fi
if [ -e "$javaSource" ]; then
if [ ! -e "$javaClass" ]; then
log " - Compiling MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/javac" "$javaSource")
fi
if [ -e "$javaClass" ]; then
log " - Running MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
# If specified, validate the SHA-256 sum of the Maven wrapper jar file
wrapperSha256Sum=""
while IFS="=" read -r key value; do
case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
if [ -n "$wrapperSha256Sum" ]; then
wrapperSha256Result=false
if command -v sha256sum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
elif command -v shasum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
exit 1
fi
if [ $wrapperSha256Result = false ]; then
echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
exit 1
fi
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
# shellcheck disable=SC2086 # safe args
exec "$JAVACMD" \
$MAVEN_OPTS \
$MAVEN_DEBUG_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

205
mvnw.cmd

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

224
pom.xml

@ -0,0 +1,224 @@
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.10</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>military-hq</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>military-hq</name>
<description>military-hq</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<xxl-job-core.version>2.2.0</xxl-job-core.version>
<fastjson.version>1.2.83</fastjson.version>
<dom4j.version>1.2.83</dom4j.version>
<java.version>1.8</java.version>
<dom4j.version>1.6.1</dom4j.version>
<qiniu-java-sdk.version>7.4.0</qiniu-java-sdk.version>
<!-- Log4j2爆雷漏洞 -->
<log4j2.version>2.17.0</log4j2.version>
<logback.version>1.2.9</logback.version>
<skipTests>true</skipTests>
<mysql-connector-java.version>8.0.21</mysql-connector-java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-docker-compose</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- json -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- dom4j -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>${dom4j.version}</version>
</dependency>
<dependency>
<groupId>org.zeromq</groupId>
<artifactId>jeromq</artifactId>
<version>0.5.2</version>
</dependency>
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.13.5</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.16.1</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.22</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.2-android</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.gavaghan</groupId>
<artifactId>geodesy</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<!-- Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<!--<version>2.3.5.RELEASE</version>-->
</dependency>
<!-- onvif -->
<dependency>
<groupId>com.github.03</groupId>
<artifactId>onvif</artifactId>
<version>1.0.7</version>
</dependency>
<dependency>
<groupId>org.gavaghan</groupId>
<artifactId>geodesy</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>com.dbb</groupId>
<artifactId>onvif</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector-java.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
<mainClass>com.zgx.iot.SystemApplication</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>

60
src/main/java/com/zgx/iot/MilitaryMqttApplication.java

@ -0,0 +1,60 @@
package com.zgx.iot;
import com.zgx.iot.config.mqtt.MQTTProps;
import com.zgx.iot.config.socket.ssl.NettyProps;
import com.zgx.iot.mq.mqtt.MqttService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Arrays;
/**
* 启动 MQTT 服务
* 注解 @Order 执行顺序
*
* @author AaGMixW
*/
@Slf4j
@Component
@Order(value = 1)
@EnableAsync
public class MilitaryMqttApplication implements ApplicationRunner {
@Resource
private MQTTProps mqttProps;
@Resource
private NettyProps nettyProps;
//@Resource
private static MqttService mqttService ;
// public MilitaryMqttApplication() {
// // this.mqttService = mqttService;
// }
@Override
@Async
public void run(ApplicationArguments args) throws Exception {
try {
mqttService = new MqttService(mqttProps);
mqttService.connect();
mqttService.subscribe();
} catch (Exception e) {
// 尝试重新连接
mqttService.reconnect();
}
}
public static void pubMessage(String message,String topic){
log.info("msg:"+message+"--------topic:"+topic);
mqttService.pubMessage(message, topic);
}
}

58
src/main/java/com/zgx/iot/MilitaryNettyApplication.java

@ -0,0 +1,58 @@
/*
package com.zgx.iot;
import com.zgx.iot.api.DeviceInfoAPI;
import com.zgx.iot.entity.DtDeviceInfo;
import com.zgx.iot.utils.DeviceServiceUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
*/
/**
* 启动 Netty 服务
*
* @author AaGMixW
*//*
@Slf4j
@Order(value = 3) //执行顺序
@Component
public class MilitaryNettyApplication implements ApplicationRunner {
@Resource
private final DeviceServiceUtil deviceServiceUtil;
public MilitaryNettyApplication(DeviceServiceUtil deviceServiceUtil) {
this.deviceServiceUtil = deviceServiceUtil;
}
@Override
public void run(ApplicationArguments args) throws Exception {
//List<MsDeviceInfo> deviceInfos = DeviceInfoAPI.GetALLDeviceLit("1446644493355888641");
DtDeviceInfo msDeviceInfo = new DtDeviceInfo();
msDeviceInfo.setNetProtocol("1");
msDeviceInfo.setServerType(1);
//msDeviceInfo.setIp("172.20.0.77");
msDeviceInfo.setDeviceIp("127.0.0.1");
msDeviceInfo.setIpPort(8899);
List<DtDeviceInfo> deviceInfoList =new ArrayList<>();
deviceInfoList.add(msDeviceInfo);
//deviceServiceUtil.startServerByDeviceInfo(deviceInfos);
deviceServiceUtil.startServerByDeviceInfo(deviceInfoList);
}
}
*/

171
src/main/java/com/zgx/iot/MilitarySocketApplication.java

@ -0,0 +1,171 @@
package com.zgx.iot;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zgx.iot.constant.enums.DeviceType;
import com.zgx.iot.entity.DtDeviceInfo;
import com.zgx.iot.entity.MsCameraSetting;
import com.zgx.iot.service.IDtDeviceInfoService;
import com.zgx.iot.service.IMsCameraSettingService;
import com.zgx.iot.utils.RedisUtil;
import com.zgx.iot.utils.hp.HPDataParser;
import com.zgx.iot.utils.hp.HPReqParamEnc;
import com.zgx.iot.utils.hp.HPTcpKeepAlive;
import com.zgx.iot.utils.hp.ThreadManager;
import com.zgx.iot.utils.socket.TcpClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 启动Socket服务
*/
@Slf4j
@Component
@Order(value = 1) //执行顺序
@EnableAsync
public class MilitarySocketApplication implements ApplicationRunner {
@Autowired
private RedisUtil redisUtil;
@Autowired
private IDtDeviceInfoService msDeviceInfoService;
@Autowired
private IMsCameraSettingService msCameraSettingService;
@PostConstruct //通过@PostConstruct实现初始化bean之前进行的操作
public void init() {
MilitarySocketApplication socketApplication = this;
// 初使化时将已静态化的Service实例化
socketApplication.msDeviceInfoService = this.msDeviceInfoService;
socketApplication.msCameraSettingService = this.msCameraSettingService;
}
/* @Override
public void run(ApplicationArguments args) throws Exception {
//1.查询所有光电设备
//2.循环建立TCP连接
//3.设备登录(userSaltGet,userLogin)
//4.定时发送心跳保持连接(userOnlineHeart)
//key为设备IP
Map<String, TcpClient> tcpClientMap = new HashMap<>();
redisUtil.del("cameraList");
redisUtil.del("dataRecordServer");
QueryWrapper<DtDeviceInfo> queryWrapper = new QueryWrapper<>();
//queryWrapper.eq("state", 1);//1-启用
//todo 查询光电
queryWrapper.and(wrapper -> wrapper.eq("device_type", DeviceType.PHOTOELECTRIC.getValue()));
List<DtDeviceInfo> deviceList = msDeviceInfoService.list(queryWrapper);
for (DtDeviceInfo ms : deviceList) {
//todo 建立TCP连接并接收数据
log.info("建立连接的设备 : "+ms.toString());//测试数据
TcpClient tcpClient = new TcpClient(ms.getDeviceIp(), ms.getIpPort()) {
@Override
public void dealWithRecvData(byte[] data) throws ParseException {
if (ms.getDeviceType() == DeviceType.PHOTOELECTRIC.getValue()) {
HPDataParser.recv(data, this);//接收数据
}
}
};
tcpClient.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info(tcpClient.getIp() +"状态:" + String.valueOf(tcpClient.flag)+"类型"+String.valueOf(ms.getDeviceType()));
if (tcpClient.flag) {
if (ms.getDeviceType() == DeviceType.PHOTOELECTRIC.getValue()) {
redisUtil.lSet("cameraList", ms);
//获取salt
tcpClient.send(HPDataParser.send(HPReqParamEnc.userSaltGet(ms.getUsername())));
} else if (ms.getDeviceType() == DeviceType.DATARECORD.getValue()) {
redisUtil.hset("dataRecordServer", "deviceCode", ms.getDeviceCode());
redisUtil.hset("dataRecordServer", "ip", ms.getDeviceIp());
redisUtil.hset("dataRecordServer", "port", ms.getIpPort());
}
//将线程放入map
tcpClientMap.put(ms.getDeviceIp(), tcpClient);
}
}
//将tcp线程放入管理类
ThreadManager.setTcpClientMap(tcpClientMap);
//发送心跳保持连接
HPTcpKeepAlive keepAlive = new HPTcpKeepAlive(redisUtil);
keepAlive.start();
log.info("Socket服务启动成功!");
}*/
public void run(ApplicationArguments args) throws Exception {
//1.查询所有光电设备
//2.循环建立TCP连接
//3.设备登录(userSaltGet,userLogin)
//4.定时发送心跳保持连接(userOnlineHeart)
//key为设备IP
Map<String, TcpClient> tcpClientMap = new HashMap<>();
redisUtil.del("cameraList");
redisUtil.del("dataRecordServer");
LambdaQueryWrapper<MsCameraSetting> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//lambdaQueryWrapper.eq(MsCameraSetting::getType,3).eq(MsCameraSetting::getStatus,1);
lambdaQueryWrapper.eq(MsCameraSetting::getType,3);
List<MsCameraSetting> deviceList = msCameraSettingService.list(lambdaQueryWrapper);
for (MsCameraSetting ms : deviceList) {
//todo 建立TCP连接并接收数据
log.info("建立连接的设备 : "+ms.toString());//测试数据
TcpClient tcpClient = new TcpClient(ms.getIp(), ms.getPort()) {
@Override
public void dealWithRecvData(byte[] data) throws ParseException {
if (ms.getType() == 3) {
HPDataParser.recv(data, this);//接收数据
}
}
};
tcpClient.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info(tcpClient.getIp() +"状态:" + String.valueOf(tcpClient.flag)+"类型"+String.valueOf(ms.getType()));
if (tcpClient.flag) {
if (ms.getType() == 3) {
redisUtil.lSet("cameraList", ms);
//获取salt
tcpClient.send(HPDataParser.send(HPReqParamEnc.userSaltGet(ms.getUser())));
}
//将线程放入map
tcpClientMap.put(ms.getIp(), tcpClient);
}
}
//将tcp线程放入管理类
ThreadManager.setTcpClientMap(tcpClientMap);
//发送心跳保持连接
HPTcpKeepAlive keepAlive = new HPTcpKeepAlive(redisUtil);
keepAlive.start();
log.info("Socket服务启动成功!");
}
}

684
src/main/java/com/zgx/iot/MilitaryZMQApplication.java

@ -0,0 +1,684 @@
package com.zgx.iot;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zgx.iot.constant.enums.CameraType;
import com.zgx.iot.constant.enums.DeviceType;
import com.zgx.iot.dto.radar.RadarTrackModel;
import com.zgx.iot.entity.MsAlarmSettings;
import com.zgx.iot.entity.MsCameraSetting;
import com.zgx.iot.entity.DtDeviceInfo;
import com.zgx.iot.service.IMsAlarmSettingsService;
import com.zgx.iot.service.IMsCameraSettingService;
import com.zgx.iot.service.IDtDeviceInfoService;
import com.zgx.iot.service.impl.MsCameraSettingServiceImpl;
import com.zgx.iot.mq.mqtt.handle.RadarHandler;
import com.zgx.iot.thread.ZmqSubThread;
import com.zgx.iot.utils.*;
import com.zgx.iot.utils.hp.HPDataParser;
import com.zgx.iot.utils.hp.HPReqParamEnc;
import com.zgx.iot.utils.hp.ThreadManager;
import com.zgx.iot.utils.socket.TcpClient;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
/**
* 启动ZMQ服务
*/
@Slf4j
@Component
@Order(value = 3) //执行顺序
@EnableAsync
public class MilitaryZMQApplication implements ApplicationRunner {
@Autowired
RedisUtil redisUtil;
@Autowired
IDtDeviceInfoService msDeviceInfoService;
@Autowired
IMsCameraSettingService msCameraSettingService;
@Autowired
IMsAlarmSettingsService msAlarmSettingsService;
@Autowired
RadarHandler radarHandler;
/**
* 服务发布地址
*/
@Value(value = "${zmq.ip}")
private String address;
/**
* 服务接收端口
*/
@Value(value = "${zmq.recv-port}")
private int recvPort;
/**
* 雷达图上目标主题
*/
@Value(value = "${zmq.topic.radar_target}")
private String radarTarget;
/**
* 雷达目标轨迹主题
*/
@Value(value = "${zmq.topic.target_trajectory}")
private String targetTrajectory;
/**
* 发送前端轨迹数据主题
*/
private final String trajectoryTopic = "/server/radar";
private final String trackDeviceInfo = "/track/deviceInfo";
/**
* 发送球机数据主题
*/
private final String trackCameraInfo = "/track/cameraInfo";
@PostConstruct //通过@PostConstruct实现初始化bean之前进行的操作
public void init() {
MilitaryZMQApplication zmqApplication = this;
// 初使化时将已静态化的Service实例化
zmqApplication.msDeviceInfoService = this.msDeviceInfoService;
zmqApplication.msAlarmSettingsService = this.msAlarmSettingsService;
zmqApplication.msCameraSettingService = this.msCameraSettingService;
}
@Override
public void run(ApplicationArguments args) throws Exception {
//判断缓存是否存在报警参数,无则从数据库查询并放入缓存
if (!redisUtil.hasKey("alarm_settings")) {
MsAlarmSettings alarmSettings = msAlarmSettingsService.list().get(0);
redisUtil.hset("alarm_settings", "lineEffectTime", alarmSettings.getLineEffectTime());
redisUtil.hset("alarm_settings", "alarmEffectTime", alarmSettings.getAlarmEffectTime());
redisUtil.hset("alarm_settings", "trackEffectTime", alarmSettings.getTrackEffectTime());
redisUtil.hset("alarm_settings", "fenceEffectTime", alarmSettings.getFenceEffectTime());
redisUtil.hset("alarm_settings", "inOutEffectDistance", alarmSettings.getInOutEffectDistance());
redisUtil.hset("alarm_settings", "targetHeight", alarmSettings.getTargetHeight());
//测试数据
/* RadarTrackModel radarTrackModel = new RadarTrackModel();
radarTrackModel.setLongitude(113.485085f);
radarTrackModel.setLatitude(22.050129f);
radarTrackModel.setDis(8560);
radarTrackModel.setAzimuth(158.7832f);
radarTrackModel.setCourse(169.96576f);
radarTrackModel.setSpeed(3.2160966f);
radarTrackModel.setTrackId(1);
radarTrackModel.setAltitude(5.770267f);
String trackIdKey = "trackIds:" + radarTrackModel.getTrackId();
redisUtil.hset(trackIdKey, "targetLon", radarTrackModel.getLongitude());
redisUtil.hset(trackIdKey, "targetLat", radarTrackModel.getLatitude());
redisUtil.hset(trackIdKey, "targetDis", radarTrackModel.getDis());
redisUtil.hset(trackIdKey, "targetAzimuth", radarTrackModel.getAzimuth());
redisUtil.hset(trackIdKey, "targetCourse", radarTrackModel.getCourse());
redisUtil.hset(trackIdKey, "targetSpeed", radarTrackModel.getSpeed());
redisUtil.hset(trackIdKey, "trackId", radarTrackModel.getTrackId());
redisUtil.hset(trackIdKey, "trackAltitude", radarTrackModel.getAltitude());
redisUtil.hset("PTZStatus", "pan", 331.0400085449219);
redisUtil.hset("PTZStatus", "tilt", 24.100000381469727);
redisUtil.hset("PTZStatus", "ptRunState", 4104);*/
}
//todo 新增代码 目标位置信息
/**
* case4 : 点击的目标数据 (只有点击雷达图上的目标时才发送)
* address : 172.20.0.77 (ZMQ发布地址)
* port : 5151
* topic : NyGuideCamPos
*/
ZmqSubThread nyGuideCamPosThread = new ZmqSubThread(address, recvPort, radarTarget) { //todo ip为radar-gui服务运行的机器
@Override
public void dealWithData(byte[] data) {
log.info(Thread.currentThread().getName() + "接收到数据:" + new String(data));
JSONObject jsonObject = JSON.parseObject(new String(data));
log.info("case4 : jsonObject:" + jsonObject.toString());
//查询雷达信息 雷达经纬度(113.455074,22.122197)
QueryWrapper<DtDeviceInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("device_type", DeviceType.RADAR.getValue())
.eq("device_status", 1);//1-启用状态
DtDeviceInfo deviceInfo = msDeviceInfoService.getOne(queryWrapper);
log.info("雷达信息:" + deviceInfo);
if (deviceInfo == null) {
log.info("查询不到相关设备");
return;
}
//目标相对方位角
double azimuth = jsonObject.getDoubleValue("azimuth");
//目标距离
double distance = jsonObject.getDoubleValue("dis");
//计算目标经纬度
GEOIntersectPointUtils.LatLon targetLonLat = GEOUtils.getLocationByLocationAndAngleAndDistance(deviceInfo.getDeviceLon(), deviceInfo.getDeviceLat(), azimuth, distance);//计算目标点经纬度
log.info("目标经纬度targetLonLat:" + targetLonLat);
//查询光电信息
DtDeviceInfo cameraInfo = null;
LambdaQueryWrapper<DtDeviceInfo> photoelectricLambdaQueryWrapper = new LambdaQueryWrapper<>();
photoelectricLambdaQueryWrapper.eq(DtDeviceInfo::getDeviceType, DeviceType.PHOTOELECTRIC.getValue()).eq(DtDeviceInfo::getDeviceStatus, 1);
List<DtDeviceInfo> photoelectricDevices = null;
photoelectricDevices = msDeviceInfoService.list(photoelectricLambdaQueryWrapper);//查出所有光电
cameraInfo = photoelectricDevices.get(0);
log.info("光电信息:" + cameraInfo);
//1、若设备关联光电,则进行联动定位
if (cameraInfo != null) {
try {
double cameraAzimuth = cameraInfo.getInitAzimuth() + Double.parseDouble(redisUtil.hget("PTZStatus", "pan").toString());
//计算目标相对于光电的方位角
double targetAzimuth = GEOUtils.getAzimuth(deviceInfo.getDeviceLon(),
deviceInfo.getDeviceLat(),
targetLonLat.getLon(),
targetLonLat.getLat()
);
//计算光电水平所需方位角
double differAzimuth = targetAzimuth - cameraAzimuth;
//计算方位角
double horAngle = Double.parseDouble(redisUtil.hget("PTZStatus", "pan").toString()) + differAzimuth;
horAngle = horAngle >= 0 ? horAngle : (360 + horAngle);
//计算俯仰角(上27000-36000中间0-9000下)
double verAngle = Math.toDegrees(Math.asin(cameraInfo.getDeviceHeight() / distance));
verAngle = verAngle + cameraInfo.getInitPitch();
//根据IP获取对应光电线程
TcpClient tcpClient = ThreadManager.getTcpClientMap().get(cameraInfo.getDeviceIp());
//停止跟踪
tcpClient.send(
HPDataParser.send(
HPReqParamEnc.ivpTrackingCtrl(String.valueOf(redisUtil.get(tcpClient.getIp())), 0, false, null)
)
);
//转动光电到指定位置
//当光电已经处于跟踪状态时,以下操作不会生效
//根据目标位置进行定位(角度实际上送值 : 100倍整数值)
tcpClient.send(
HPDataParser.send(
HPReqParamEnc.ptzControl(String.valueOf(redisUtil.get(tcpClient.getIp())),
0, 51, null,
null, null, 45,
(int) (horAngle * 100), (int) (verAngle * 100), null)
)
);
//目标高度 平均高度 在ms_alarm_settings表中设置 船的平均高度 高度越高视场角越大
double h = Double.parseDouble(redisUtil.hget("alarm_settings", "targetHeight").toString());
//计算目标距离光点的距离
double d = GEOUtils.GetDistance(targetLonLat.getLon(), targetLonLat.getLat(), cameraInfo.getDeviceLon(), cameraInfo.getDeviceLat());
//计算视场角,100为分辨率/像素
double fov = Math.toDegrees(Math.atan(h / d)) * 2 * 100;
log.info("目标平均高度:" + h + " 目标距离光电:" + d);
log.info("水平方位角:" + horAngle + " 俯仰角:" + verAngle + " 视场角:" + fov);
tcpClient.send(
HPDataParser.send(
HPReqParamEnc.ptzControl(String.valueOf(redisUtil.get(tcpClient.getIp())),
0, 42, null,
null, null, null,
null, null, (int) (fov * 100))
)
);
log.info("联动控制球机:");
List<MsCameraSetting> cameraSettings = null;
LambdaQueryWrapper<MsCameraSetting> cameraSettingLambdaQueryWrapper = new LambdaQueryWrapper<>();
cameraSettingLambdaQueryWrapper.eq(MsCameraSetting::getType, 2).eq(MsCameraSetting::getStatus, 1);//只查询球机的信息 type:2 球机 type:1 枪击
cameraSettings = msCameraSettingService.list(cameraSettingLambdaQueryWrapper);
if (cameraSettings == null || cameraSettings.isEmpty()) {
return;
}
log.info("case4 : 遍历相机列表 寻找最近的点的球机去跟踪");
// 计算距离最近的球机
MsCameraSetting msCameraSetting = null;//最近球机信息
double nearestDistance = 0;//最近距离
double heightDiff = 0;//最近球机的高度差
for (MsCameraSetting cameraSetting : cameraSettings) {
// todo : 判断该球机是否满足照射范围 不满足的话还可以找第二近的球机 如果放到后面才判断高度差 就无法找第二近的去跟踪了
BigDecimal cameraHeight = cameraSetting.getHeight();//球机高度
BigDecimal labelHeight = new BigDecimal(h);//目标高度
double tempHeightDiff = cameraHeight.subtract(labelHeight).doubleValue();//球机与目标高度差
if (tempHeightDiff < 0) {
log.info("case4 :" + "ip=" + cameraSetting.getIp() + " tempHeightDiff < 0 超过球机照射范围");
} else {
double temp = GEOUtils.GetDistance(cameraSetting.getLongitude().doubleValue(), cameraSetting.getLatitude().doubleValue(), targetLonLat.getLon(), targetLonLat.getLat());
log.info("当前的球机" + cameraSetting.getIp() + "与目标的距离:" + temp);
// 第一次 先将第一个球机的距离作为最近距离 和 最近球机信息
if (msCameraSetting == null) {
msCameraSetting = cameraSetting;
nearestDistance = temp;
continue;
}
// 第二次以后 如果距离更近则更新最近距离 以及 最近球机信息
if (nearestDistance > temp) {
msCameraSetting = cameraSetting;
nearestDistance = temp;
heightDiff = tempHeightDiff;
}
}
}
if (msCameraSetting == null) {
log.info("没有可跟踪的球机");
return;
}
//判断两点的距离是否超过有效距离,超过则丢掉
if (nearestDistance > Integer.parseInt(redisUtil.hget("alarm_settings", "inOutEffectDistance").toString())) {
log.info("case4 :" + "超过跟踪的最大距离" + redisUtil.hget("alarm_settings", "inOutEffectDistance").toString());
return;
}
log.info("case4 :" + " 相机IP:" + msCameraSetting.getIp() + " 最短距离nearestDistance:" + nearestDistance);
log.info("case4 :" + "距离最近的相机:" + JSON.toJSONString(msCameraSetting));
//控制球机照射目标
log.info("case4【尝试使用ptzControllerByLatLonAndDistance】将球机转到目标位置");
msCameraSettingService.ptzControllerByLatLon(msCameraSetting.getIp(),
msCameraSetting.getUser(),
msCameraSetting.getPassword(),
msCameraSetting.getMaxElevation(),
msCameraSetting.getZeroAzimuth(),
heightDiff,
msCameraSetting.getZoomFactor(),
msCameraSetting.getLongitude().doubleValue(),
msCameraSetting.getLatitude().doubleValue(),
targetLonLat.getLon(),
targetLonLat.getLat(),
msCameraSetting.getFactory());//factory用于区分品牌类型 1:海康 2:宇视
log.info("跟踪球机的主要参数信息:");
log.info("1.IP: " + msCameraSetting.getIp());
log.info("2.用户名: " + msCameraSetting.getUser());
log.info("3.密码: " + msCameraSetting.getPassword());
log.info("4.最大俯仰角: " + msCameraSetting.getMaxElevation());
log.info("5.初始方位角: " + msCameraSetting.getZeroAzimuth());
log.info("6.品牌: " + (msCameraSetting.getFactory() == 1 ? "海康" : "宇视"));
//由于只能接收到方位角和距离 并且轨迹不断更新 所以只能将方位角和距离进行
//由于经纬度不断变化 暂时不使用经纬度进行定位
DecimalFormat decimalFormat = new DecimalFormat("#.00");//保留两位小数
String longitude = decimalFormat.format(targetLonLat.getLon());
String latitude = decimalFormat.format(targetLonLat.getLat());
//获取轨迹信息
//String redisKey = "tracks"+"_"+longitude+"_"+latitude;
int redisAzimuth = (int) azimuth;
int redisDis = (((int) distance + 999) / 1000) * 1000;
String redisKey = "tracks:" + redisAzimuth + "_" + redisDis;
log.info("case4 :" + "redisLongitude:" + longitude + " " + "redisLatitude:" + latitude + "redisAzimuth:" + redisAzimuth + " redisDis:" + redisDis);
log.info("case4 :" + "redisKey = " + redisKey);
//通过不断更新的船经纬度信息控制球机转动
int trackId = Integer.parseInt(redisUtil.hget(redisKey, "trackId").toString());//根据方位角 找到 轨迹Id
redisUtil.hset("trackingTargetId", String.valueOf(trackId), msCameraSetting.getIp());//将该轨迹 和 定位该轨迹的球机 保存到跟踪队列中
log.info("正在跟踪的trackId:" + trackId + "跟踪的球机" + msCameraSetting.getIp());
//将光电信息封装成rtspUrl返回前端
String rtspUrl = getRtspUrl(deviceInfo.getDeviceIp(), deviceInfo.getIpPort(), deviceInfo.getUsername(), deviceInfo.getPassword());
//轨迹数据发送mqtt给前端使用
JSONObject jsonObject1 = new JSONObject();
jsonObject1.put("rtspUrl", rtspUrl);
MilitaryMqttApplication.pubMessage(jsonObject1.toJSONString(), trackDeviceInfo);
log.info("发送轨迹数据给前端----------" + "消息:" + jsonObject1.toJSONString() + " 主题:" + trackDeviceInfo);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
};
new Thread(nyGuideCamPosThread).start();
//todo : 新增代码 球机联动
/**
* case3 : 船轨迹数据 (开启目标跟踪使能后 持续发送)
* address : 172.20.0.77 (ZMQ发布地址)
* port : 5151
* topic : RadarTrack
*/
/* ZmqSubThread radarTrackThread = new ZmqSubThread(address, recvPort, targetTrajectory) {
@Override
public void dealWithData(byte[] data) {
log.info(Thread.currentThread().getName() + "接收到数据:" + new String(data));
JSONObject jsonObject = JSON.parseObject(new String(data));
log.info("case3 :" + "RadarTrack航迹数据:" + jsonObject.toString());
String radarTarcksJsonString = (String) jsonObject.get("radarTracks");
List<RadarTrackModel> radarTrackModels = JSONObject.parseArray(radarTarcksJsonString, RadarTrackModel.class);
//RadarTrackModel radarTrackModel = radarTrackModels.get(0);
for (RadarTrackModel radarTrackModel : radarTrackModels) {
log.info("case3 :" + "航迹数据:" + JSON.toJSONString(radarTrackModel));
log.error("时间:" + new Date(System.currentTimeMillis()) + "轨迹" + radarTrackModel.getTrackId() + "的数据 经纬度:" + radarTrackModel.getLongitude() + "_" + radarTrackModel.getLatitude());
//保存有轨迹的Id
redisUtil.zAdd("updatedIds", String.valueOf(radarTrackModel.getTrackId()), (double) System.currentTimeMillis());
//缓存 TrackId =》 船具体信息
String trackIdKey = "trackIds:" + radarTrackModel.getTrackId();
redisUtil.hset(trackIdKey, "targetLon", radarTrackModel.getLongitude());
redisUtil.hset(trackIdKey, "targetLat", radarTrackModel.getLatitude());
redisUtil.hset(trackIdKey, "targetDis", radarTrackModel.getDis());
redisUtil.hset(trackIdKey, "targetAzimuth", radarTrackModel.getAzimuth());
redisUtil.hset(trackIdKey, "targetCourse", radarTrackModel.getCourse());
redisUtil.hset(trackIdKey, "targetSpeed", radarTrackModel.getSpeed());
redisUtil.hset(trackIdKey, "trackAltitude", radarTrackModel.getAltitude());
//redis中存在正在跟踪的轨迹目标信息
String trackingTarget = (String) redisUtil.hget("trackingTargetId", String.valueOf(radarTrackModel.getTrackId()));//获取并判断雷达传过来的轨迹数据 看是否该轨迹在跟踪目标队列中
if (trackingTarget != null) {// 该轨迹处于跟踪状态
log.info("当前轨迹处于跟踪列表中" + trackingTarget);
//计算最近球机
List<MsCameraSetting> cameraSettings = null;
LambdaQueryWrapper<MsCameraSetting> cameraSettingLambdaQueryWrapper = new LambdaQueryWrapper<>();
cameraSettingLambdaQueryWrapper.eq(MsCameraSetting::getType, 1).eq(MsCameraSetting::getStatus, 1);//只查询球机的信息 type:1 球机 type:2 枪击 type:10 故障
cameraSettings = msCameraSettingService.list(cameraSettingLambdaQueryWrapper);
if (cameraSettings == null || cameraSettings.isEmpty()) {
return;
}
log.info("遍历相机列表 寻找最近的点的球机去跟踪" + JSON.toJSONString(cameraSettings));
//最近球机信息
MsCameraSetting msCameraSetting = null;
//最近距离
double nearestDistance = 0;
//最近球机的高度差
double heightDiff = 0;
//轨迹数据中有海拔(就暂时不使用目标平均高度了)
double trackAltitude = Double.parseDouble(redisUtil.hget(trackIdKey, "trackAltitude").toString());
if (trackAltitude == 0) {
trackAltitude = Double.parseDouble(redisUtil.hget("alarm_settings", "targetHeight").toString());//没有就取平均值
log.info("该轨迹没有传船的高度 赋予平均值");
}
//查找最近的相机
for (MsCameraSetting cameraSetting : cameraSettings) {
BigDecimal cameraHeight = cameraSetting.getHeight();//球机高度
BigDecimal labelHeight = new BigDecimal(trackAltitude);//目标高度
double tempHeightDiff = cameraHeight.subtract(labelHeight).doubleValue();//球机与目标高度差
if (tempHeightDiff < 0) {
log.info("case3 :" + "ip=" + cameraSetting.getIp() + " tempHeightDiff < 0 超过球机照射范围");
} else {
double temp = GEOUtils.GetDistance(cameraSetting.getLongitude().doubleValue(), cameraSetting.getLatitude().doubleValue(), (double) redisUtil.hget("trackIds:" + radarTrackModel.getTrackId(), "targetLon"), (double) redisUtil.hget("trackIds:" + radarTrackModel.getTrackId(), "targetLat"));
// 第一次 先将第一个球机的距离作为最近距离 和 最近球机信息
if (msCameraSetting == null) {
msCameraSetting = cameraSetting;
nearestDistance = temp;
continue;
}
// 第二次以后 如果距离更近则更新最近距离 以及 最近球机信息
if (nearestDistance > temp) {
msCameraSetting = cameraSetting;
nearestDistance = temp;
heightDiff = tempHeightDiff;
}
}
}
if (msCameraSetting == null) {
log.info("没有可跟踪的球机");
return;
}
//判断两点的距离是否超过有效距离,超过则丢掉
if (nearestDistance > Integer.parseInt(redisUtil.hget("alarm_settings", "inOutEffectDistance").toString())) {
log.info("case3 :" + "超过跟踪的最大距离" + redisUtil.hget("alarm_settings", "inOutEffectDistance").toString());
return;
}
//获取跟踪目标的最新经纬度
String trackIdKey2 = "trackIds:" + radarTrackModel.getTrackId();//获取该轨迹对应的最新数据
double targetLon = (double) redisUtil.hget(trackIdKey2, "targetLon");
double targetLat = (double) redisUtil.hget(trackIdKey2, "targetLat");
//将球机信息返回前端
if (!trackingTarget.equals(msCameraSetting.getIp())){
//跟踪的球机改变发送给前端
JSONObject jsonObject2 = new JSONObject();
jsonObject2.put("deviceId", msCameraSetting.getId());
jsonObject2.put("rtspUrl", msCameraSetting.getPreRtsp());
jsonObject2.put("rtcUrl", msCameraSetting.getWebcastAddress());
MilitaryMqttApplication.pubMessage(jsonObject2.toJSONString(), trackCameraInfo);
}
redisUtil.hset("trackingTargetId", String.valueOf(radarTrackModel.getTrackId()), msCameraSetting.getIp(), 60 * 5);//更新时间
//控制球机照射目标
log.info("case3 :" + "【尝试使用ptzControllerByLatLonAndDistance】");
msCameraSettingService.ptzControllerByLatLon(msCameraSetting.getIp(),
msCameraSetting.getUser(),
msCameraSetting.getPassword(),
msCameraSetting.getMaxElevation(),
msCameraSetting.getZeroAzimuth(),
heightDiff,
msCameraSetting.getZoomFactor(),
msCameraSetting.getLongitude().doubleValue(),
msCameraSetting.getLatitude().doubleValue(),
targetLon,
targetLat,
msCameraSetting.getFactory());//style用于区分品牌类型 1:海康 3:宇视
redisUtil.hset("trackingTargetId", String.valueOf(radarTrackModel.getTrackId()), msCameraSetting.getIp());//更新时间
}
//发送雷达轨迹数据
JSONObject jsonObject1 = new JSONObject();
jsonObject1.put("sourceId", "AgilTrack_cat010bsz");
jsonObject1.put("flag", 1);
//jsonObject1.put("radarTrack", radarTrackModel);
jsonObject1.put("radarTrack", JSON.toJSONString(radarTrackModel));
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String dataString = simpleDateFormat.format(new Date(System.currentTimeMillis()));
jsonObject1.put("utc", dataString);
jsonObject1.put("length", 3);
MilitaryMqttApplication.pubMessage(jsonObject1.toJSONString(), trajectoryTopic);
log.info("发送轨迹数据给前端----------" + "消息:" + JSON.toJSONString(radarTrackModel) + " 主题:" + trajectoryTopic);
}
}
};
new Thread(radarTrackThread).start();*/
ZmqSubThread radarTrackThread = new ZmqSubThread(address, recvPort, targetTrajectory) {
@Override
public void dealWithData(byte[] data) {
log.info(Thread.currentThread().getName() + "接收到数据:" + new String(data));
JSONObject jsonObject = JSON.parseObject(new String(data));
log.info("case3 :" + "RadarTrack航迹数据:" + jsonObject.toString());
String radarTarcksJsonString = (String) jsonObject.get("radarTracks");
List<RadarTrackModel> radarTrackModels = JSONObject.parseArray(radarTarcksJsonString, RadarTrackModel.class);
//RadarTrackModel radarTrackModel = radarTrackModels.get(0);
for (RadarTrackModel radarTrackModel : radarTrackModels) {
log.info("case3 :" + "航迹数据:" + JSON.toJSONString(radarTrackModel));
log.error("时间:" + new Date(System.currentTimeMillis()) + "轨迹" + radarTrackModel.getTrackId() + "的数据 经纬度:" + radarTrackModel.getLongitude() + "_" + radarTrackModel.getLatitude());
//保存有轨迹的Id
redisUtil.zAdd("updatedIds", String.valueOf(radarTrackModel.getTrackId()), (double) System.currentTimeMillis());
//缓存 TrackId =》 船具体信息
String trackIdKey = "trackIds:" + radarTrackModel.getTrackId();
redisUtil.hset(trackIdKey, "targetLon", radarTrackModel.getLongitude());
redisUtil.hset(trackIdKey, "targetLat", radarTrackModel.getLatitude());
redisUtil.hset(trackIdKey, "targetDis", radarTrackModel.getDis());
redisUtil.hset(trackIdKey, "targetAzimuth", radarTrackModel.getAzimuth());
redisUtil.hset(trackIdKey, "targetCourse", radarTrackModel.getCourse());
redisUtil.hset(trackIdKey, "targetSpeed", radarTrackModel.getSpeed());
redisUtil.hset(trackIdKey, "trackAltitude", radarTrackModel.getAltitude());
//redis中存在正在跟踪的轨迹目标信息
//String trackingCamera = (String) redisUtil.hget("trackingTargetId", String.valueOf(radarTrackModel.getTrackId()));//获取并判断雷达传过来的轨迹数据 看是否该轨迹在跟踪目标队列中
String trackingId = (String) redisUtil.get("trackingId");//获取跟踪目标Id
String cameraIp = (String) redisUtil.get("trackingCameraIp");//获取跟踪球机的Ip
if (trackingId != null && trackingId.equals(String.valueOf(radarTrackModel.getTrackId()))) {// 该轨迹处于跟踪状态
//log.info("当前轨迹处于跟踪列表中" + cameraIp);
List<MsCameraSetting> cameraSettings = null;
LambdaQueryWrapper<MsCameraSetting> cameraSettingLambdaQueryWrapper = new LambdaQueryWrapper<>();
cameraSettingLambdaQueryWrapper.eq(MsCameraSetting::getType,CameraType.QIUJI.getValue()).eq(MsCameraSetting::getStatus, 0);//只查询球机的信息 type:2 球机 type:1 枪击 type:10 故障
cameraSettings = msCameraSettingService.list(cameraSettingLambdaQueryWrapper);
if (cameraSettings != null) {
//获取跟踪目标的最新经纬度
String trackIdKey2 = "trackIds:" + radarTrackModel.getTrackId();//获取该轨迹对应的最新数据
double targetLon = radarTrackModel.getLongitude();
double targetLat = radarTrackModel.getLatitude();
//计算最近球机
MsCameraSetting msCameraSetting = radarHandler.getNearestCamera(cameraSettings, targetLon, targetLat);
//控制球机照射目标
//radarHandler.cameraToTarget((float) targetLon, (float) targetLat, msCameraSetting);
//控制球机照射目标2
JSONObject jsonObject1 = new JSONObject();
jsonObject1.put("targetLon", radarTrackModel.getLongitude());
jsonObject1.put("targetLat", radarTrackModel.getLatitude());
jsonObject1.put("camera", JSON.toJSONString(msCameraSetting));
MilitaryMqttApplication.pubMessage(JSON.toJSONString(jsonObject1), "/cameraToTarget");
//当前跟踪的球机与之前跟踪的球机是否一样
if (!cameraIp.equals(msCameraSetting.getIp())) {
//跟踪的球机改变发送给前端
JSONObject jsonObject2 = new JSONObject();
jsonObject2.put("deviceId", msCameraSetting.getId());
jsonObject2.put("rtspUrl", msCameraSetting.getPreRtsp());
jsonObject2.put("rtcUrl", msCameraSetting.getWebcastAddress());
MilitaryMqttApplication.pubMessage(jsonObject2.toJSONString(), trackCameraInfo);
redisUtil.set("trackingCameraIp", msCameraSetting.getIp(),5*60);//更新正在跟踪的球机Ip
}
//redisUtil.hset("trackingTargetId", String.valueOf(radarTrackModel.getTrackId()), msCameraSetting.getIp(), 60 * 5);//更新时间
log.info("轨迹-----------【参数信息】");
log.info("相机IP:" + msCameraSetting.getIp());
log.info("用户名:" + msCameraSetting.getUser());
log.info("密码:" + msCameraSetting.getPassword());
log.info("最大俯仰角:" + msCameraSetting.getMaxElevation());
log.info("初始方位角:" + msCameraSetting.getZeroAzimuth());
log.info("变焦倍数:" + msCameraSetting.getZoomFactor());
log.info("相机经度:" + msCameraSetting.getLongitude().doubleValue());
log.info("相机纬度:" + msCameraSetting.getLatitude().doubleValue());
log.info("目标经度: " + targetLon);
log.info("目标纬度: " + targetLat);
log.info("品牌: " + (msCameraSetting.getFactory() == 1 ? "海康" : "宇视"));
log.info("轨迹-----------【已控制球机照过去 等待下一次更新的轨迹信息 在进行下次定位】");
}
}
//todo : 真实发送雷达轨迹数据
JSONObject jsonObject1 = new JSONObject();
jsonObject1.put("sourceId", "AgilTrack_cat010bsz");
jsonObject1.put("flag", 1);
jsonObject1.put("radarTrack", JSON.toJSONString(radarTrackModel));
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String dataString = simpleDateFormat.format(new Date(System.currentTimeMillis()));
jsonObject1.put("utc", dataString);
jsonObject1.put("length", 3);
MilitaryMqttApplication.pubMessage(jsonObject1.toJSONString(), trajectoryTopic);
log.info("发送轨迹数据给前端----------" + "消息:" + JSON.toJSONString(radarTrackModel) + " 主题:" + trajectoryTopic);
}
}
};
new Thread(radarTrackThread).start();
}
private static String getRtspUrl(String ip, int port, String user, String password) {
String rtspUrl = String.format("rtsp://%s:%s@%s:%d/", user, password, ip, port);
return rtspUrl;
}
//测试
public static void main(String[] args) {
/* double distance = GEOUtils.getDistance(113.5130050, 22.161666, 113.448686, 22.118584);
System.out.println(distance);
BigDecimal cameraHeight = new BigDecimal(6);//球机高度
BigDecimal labelHeight = new BigDecimal(0.28445536);//目标高度
double tempHeightDiff = cameraHeight.subtract(labelHeight).doubleValue();//球机与目标高度差
System.out.println(tempHeightDiff);
double azimuth = GEOUtils.getAzimuth(113.4578, 22.8021, 113.6782, 22.6602);
System.out.println("方位角:" + azimuth);
System.out.println(new Date(System.currentTimeMillis()));
System.out.println(getRtspUrl("192.168.1.200", 8081, "admin", "admin123!#"));//测试rtsp生成
for (int i = 0; i < 10; i++) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("radarId", "1");
jsonObject.put("radarId2", "2");
jsonObject.put("radarId3", "3");
jsonObject.put("radarId4", "4");
jsonObject.put("radarId5", "5");
//测试数据
String filepath = "C:\\Users\\15819\\Desktop\\radarData.txt";
try {
bufferedWriterTest(filepath, jsonObject.toString());
} catch (IOException e) {
throw new RuntimeException(e);
}
}*/
}
private static void bufferedWriterTest(String filepath, String content) throws IOException {
try (BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filepath, true))) {
bufferedWriter.write(content);
bufferedWriter.newLine();
}
}
}

54
src/main/java/com/zgx/iot/SystemApplication.java

@ -0,0 +1,54 @@
package com.zgx.iot;
import com.zgx.iot.config.mqtt.MQTTProps;
import com.zgx.iot.config.socket.ssl.NettyProps;
import com.zgx.iot.mq.mqtt.MqttService;
import com.zgx.iot.utils.oConvertUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.EnableScheduling;
import javax.annotation.Resource;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@EnableScheduling
@SpringBootApplication
@Slf4j
public class SystemApplication implements ApplicationRunner{
@Resource
private NettyProps nettyProps;
public static ExecutorService threadPool = Executors.newFixedThreadPool(15);
public static void main(String[] args) throws UnknownHostException {
ConfigurableApplicationContext application = SpringApplication.run(SystemApplication.class, args);
Environment env = application.getEnvironment();
String ip = InetAddress.getLocalHost().getHostAddress();
String port = env.getProperty("server.port");
String path = oConvertUtils.getString(env.getProperty("server.servlet.context-path"));
log.info("\n----------------------------------------------------------\n\t" +
"周界入侵告警管控平台服务启动成功! Access URLs:\n\t" +
"Local: \t\thttp://localhost:" + port + path + "/\n\t" +
"External: \thttp://" + ip + ":" + port + path + "/\n\t" +
// "Swagger文档: \thttp://" + ip + ":" + port + path + "/doc.html\n" +
"----------------------------------------------------------");
}
@Override
public void run(ApplicationArguments args) throws Exception {
// MilitaryMqttApplication.pubMessage("aaa","military");
// System.out.println("111");
}
}

43
src/main/java/com/zgx/iot/api/DeviceInfoAPI.java

@ -0,0 +1,43 @@
package com.zgx.iot.api;
import com.alibaba.fastjson.JSON;
import com.zgx.iot.common.Constants;
import com.zgx.iot.entity.DtDeviceInfo;
import com.zgx.iot.utils.https.ResultData;
import com.zgx.iot.utils.https.HttpAPIHelper;
import java.util.HashMap;
import java.util.List;
public class DeviceInfoAPI {
public static List<DtDeviceInfo> GetALLDeviceLit(String siteid){
String url = Constants.APIURL.DEVICE_LIST;
HashMap<String, Object> valueMap = new HashMap<>();
valueMap.put("device_owner_id",siteid);
valueMap.put("device_status",0);
ResultData resultData = HttpAPIHelper.doGet(url, valueMap);
List<DtDeviceInfo> jsonArray = JSON.parseArray(resultData.getResult(), DtDeviceInfo.class);
// 将JSONArray数组转为List类型
//List<DeviceInfo> list = (List)jsonArray;
// return JSON.parseObject(resultData.getData(), List<DeviceInfo>.class);
for (DtDeviceInfo deviceInfo : jsonArray) {
System.out.println(deviceInfo.getDeviceName());
}
return jsonArray;
}
/* public static DeviceInfo GetDeviceInfo(String deviceCode){
String url = Constants.APIURL.DEVICE_LIST +"?deviceOwnerId=" +"";
ResultData resultData = HttpAPIHelper.doGet(url, null);
DeviceInfo deviceInfo = JSON.parseObject(resultData.getData(),DeviceInfo.class);
// return JSON.parseObject(resultData.getData(), List<DeviceInfo>.class);
return deviceInfo;
}*/
}

4
src/main/java/com/zgx/iot/api/ServiceAPI.java

@ -0,0 +1,4 @@
package com.zgx.iot.api;
public class ServiceAPI {
}

4
src/main/java/com/zgx/iot/api/mq/MQManager.java

@ -0,0 +1,4 @@
package com.zgx.iot.api.mq;
public class MQManager {
}

4
src/main/java/com/zgx/iot/api/mq/MQService.java

@ -0,0 +1,4 @@
package com.zgx.iot.api.mq;
public interface MQService {
}

4
src/main/java/com/zgx/iot/api/mq/MQTTServiceimpl.java

@ -0,0 +1,4 @@
package com.zgx.iot.api.mq;
public class MQTTServiceimpl implements MQService {
}

140
src/main/java/com/zgx/iot/base/BaseMap.java

@ -0,0 +1,140 @@
package com.zgx.iot.base;
import cn.hutool.core.util.ObjectUtil;
import org.apache.commons.beanutils.ConvertUtils;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* 自定义Map
*/
public class BaseMap extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
public BaseMap() {
}
public BaseMap(Map<String, Object> map) {
this.putAll(map);
}
@Override
public BaseMap put(String key, Object value) {
super.put(key, Optional.ofNullable(value).orElse(""));
return this;
}
public BaseMap add(String key, Object value) {
super.put(key, Optional.ofNullable(value).orElse(""));
return this;
}
@SuppressWarnings("unchecked")
public <T> T get(String key) {
Object obj = super.get(key);
if (ObjectUtil.isNotEmpty(obj)) {
return (T) obj;
} else {
return null;
}
}
@SuppressWarnings("unchecked")
public Boolean getBoolean(String key) {
Object obj = super.get(key);
if (ObjectUtil.isNotEmpty(obj)) {
return Boolean.valueOf(obj.toString());
} else {
return false;
}
}
public Long getLong(String key) {
Object v = get(key);
if (ObjectUtil.isNotEmpty(v)) {
return new Long(v.toString());
}
return null;
}
public Long[] getLongs(String key) {
Object v = get(key);
if (ObjectUtil.isNotEmpty(v)) {
return (Long[]) v;
}
return null;
}
public List<Long> getListLong(String key) {
List<String> list = get(key);
if (ObjectUtil.isNotEmpty(list)) {
return list.stream().map(e -> new Long(e)).collect(Collectors.toList());
} else {
return null;
}
}
public Long[] getLongIds(String key) {
Object ids = get(key);
if (ObjectUtil.isNotEmpty(ids)) {
return (Long[]) ConvertUtils.convert(ids.toString().split(","), Long.class);
} else {
return null;
}
}
public Integer getInt(String key, Integer def) {
Object v = get(key);
if (ObjectUtil.isNotEmpty(v)) {
return Integer.parseInt(v.toString());
} else {
return def;
}
}
public Integer getInt(String key) {
Object v = get(key);
if (ObjectUtil.isNotEmpty(v)) {
return Integer.parseInt(v.toString());
} else {
return 0;
}
}
public BigDecimal getBigDecimal(String key) {
Object v = get(key);
if (ObjectUtil.isNotEmpty(v)) {
return new BigDecimal(v.toString());
}
return new BigDecimal("0");
}
@SuppressWarnings("unchecked")
public <T> T get(String key, T def) {
Object obj = super.get(key);
if (ObjectUtil.isEmpty(obj)) {
return def;
}
return (T) obj;
}
public static BaseMap toBaseMap(Map<String, Object> obj) {
BaseMap map = new BaseMap();
map.putAll(obj);
return map;
}
}

48
src/main/java/com/zgx/iot/client/ClientProtocalFactory.java

@ -0,0 +1,48 @@
package com.zgx.iot.client;
import com.zgx.iot.client.impl.ProtocalLadarYS;
import com.zgx.iot.dto.site.DeviceInfo;
import java.util.HashMap;
import java.util.Map;
public class ClientProtocalFactory {
// 对象列表
private static Map<String, IClientProtocal> objectList = new HashMap<String, IClientProtocal>();
/**
* 根据路径新建对象
* @param path
* @return
*/
public static IClientProtocal getInstance(String path) {
if( objectList.containsKey(path) ){
return objectList.get(path);
}else{
try {
Class<IClientProtocal> classObject = (Class<IClientProtocal>) Class.forName("com.zgx.iot.protocal.impl." + path);
IClientProtocal iprotocal = classObject.newInstance() ;
objectList.put(path,iprotocal) ;
return iprotocal ;
} catch (Exception e) {
}
}
return null;
}
public static IClientProtocal CreateClient(DeviceInfo deviceInfo) {
IClientProtocal clientProtocal=null;
switch (deviceInfo.getProtocol()) {
case 1:
clientProtocal = new ProtocalLadarYS(deviceInfo);
default:
clientProtocal = new ProtocalLadarYS(deviceInfo);
}
if(clientProtocal!=null){
clientProtocal.login();
}
return clientProtocal;
}
}

34
src/main/java/com/zgx/iot/client/ClientProtocalManager.java

@ -0,0 +1,34 @@
package com.zgx.iot.client;
import java.util.HashMap;
import java.util.Map;
/**
* 协议解析入口
* @author chenrj
*
*/
public class ClientProtocalManager {
// 对象列表
private static Map<String, IClientProtocal> DeviceList = new HashMap<>();
private String site_id="";
/**
* 登录判断并匹配协议
*/
public void loginClientDevices(){
/* List<MsDeviceInfo> deviceInfoList= DeviceInfoAPI.GetALLDeviceLit(site_id);
for ( MsDeviceInfo deviceInfo :deviceInfoList) {
IClientProtocal clientProtocal = ClientProtocalFactory.CreateClient(deviceInfo);
}*/
}
}

30
src/main/java/com/zgx/iot/client/IClientProtocal.java

@ -0,0 +1,30 @@
package com.zgx.iot.client;
/**
* 策略抽象接口类,提供客户端需要的一些公共方法
*/
public interface IClientProtocal {
/**
* 登录
*/
void login();
/**
* 数据解析
* @param data
*/
void analysisData( byte[] data);
/**
* 心跳包
*/
void handbert();
void logout();
}

61
src/main/java/com/zgx/iot/client/impl/ProtocalLadarYS.java

@ -0,0 +1,61 @@
package com.zgx.iot.client.impl;
import com.zgx.iot.SystemApplication;
import com.zgx.iot.client.IClientProtocal;
import com.zgx.iot.common.Code.IOT_NODE_STATUS;
import com.zgx.iot.common.Config;
import com.zgx.iot.common.Constants;
import com.zgx.iot.dto.site.DeviceInfo;
import com.zgx.iot.radar.RadarServer;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
/**
*
* @author M
* HJ212
*
*/
public class ProtocalLadarYS implements IClientProtocal {
private DeviceInfo _deviceInfo;
public ProtocalLadarYS(DeviceInfo deviceInfo){
}
@Override
public void login() {
}
@Override
public void analysisData( byte[] data ) {
try{
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void handbert( ) {
}
@Override
public void logout() {
}
}

36
src/main/java/com/zgx/iot/common/Cache.java

@ -0,0 +1,36 @@
package com.zgx.iot.common;
import java.util.Map;
import java.util.Timer;
import java.util.concurrent.ConcurrentHashMap;
/**
* 缓存
*
*/
public class Cache {
/**
* nodeId session 缓存
*/
//public static Map<String, IoSession> nodeIdsessionMap = new ConcurrentHashMap<>();
/**
* 定时任务轮训主要主动请求数据
*/
public static Map<String, Timer > timerTaskMap = new ConcurrentHashMap<>();
/**
* 设备数据透传
*/
public static Map<String, Long > deviceMap = new ConcurrentHashMap<>();
//public static Map<String, IotNodeInfoBOSocket> nodeIdsessionMapEx = new ConcurrentHashMap<>();
}

36
src/main/java/com/zgx/iot/common/Code.java

@ -0,0 +1,36 @@
package com.zgx.iot.common;
public class Code {
public static class IOT_NODE_STATUS {
public static final Integer online = 16 ;
public static final Integer offline = 17;
}
public static class ResponseCode{
public static final Integer OK = 2 ;
public static final Integer NO_DATA = 4 ;
}
/**
* 设备状态
* @author chenrj
*
*/
public static class DEVICE_STATUS{
public static final Integer ONLINE = 16 ;
public static final Integer OFFLINE = 17 ;
public static final Integer UNCONTECT = 18;
public static final Integer FAILURE = 19 ;
}
}

8
src/main/java/com/zgx/iot/common/Config.java

@ -0,0 +1,8 @@
package com.zgx.iot.common;
public class Config {
public static String SITE_ID = "";
public static String IOT_USER_KEY ;
public static String IOT_URL="localhost:8088";
}

105
src/main/java/com/zgx/iot/common/Constants.java

@ -0,0 +1,105 @@
package com.zgx.iot.common;
public class Constants {
public final static String IOT_LPM_TYPE = "IOT_SERVER_LPM";
public final static String DEVICE_CODE = "deviceId";
public final static String DEVICE_LOGIN = "login";
//协议类型
public final static String PROTOCOL_CATEGORY = "protocolCategory";
public final static String DEVICE_PARAM = "deviceParam" ;
public final static String DEVICE_TRANSFER = "deviceTransfer" ;
public final static String DEVICE_FLAG = "deviceFlag" ;
public final static String DEVICE_SESSION = "deviceSession" ;
public final static String NODE_INFO = "nodeInfo" ;
public final static String THREAD_HASH_CODE = "threadHashCode" ;
public final static String DATA_CACHE = "dataCache";
public static class CODE_TYPE{
public final static String HEX = "hex";
public final static String STR = "STR";
}
public String API_URL="";
public static class APIURL {
/**
* 所属站点设备列表
*/
public static String DEVICE_LIST = Config.IOT_URL + "/dt/military/dtDeviceInfo/queryByIsland";
}
public static class URL{
/**
* 同步lpro和lpm数据
*/
public static String SYNC_NODE = Config.IOT_URL + "/service/node/data/sync.json" ;
/**
* 修改传感器的请求值,实时值
*/
public static String SENSORS_DATA = Config.IOT_URL + "/service/sensors/realtime/update.json";
/**
* 修改设备的状态
*/
public static String NODE_INFO = Config.IOT_URL +"/service/node/status.json";
/**
* 批量保存储存传感器数据
*/
public static String SAVE_NODE_DATA = Config.IOT_URL + "/service/save/node/data.json" ;
}
public static class MQTT_TOPIC{
/**
*雷达目标信息
*/
public static String RadarTargetTopic = "RadarTargetTopic" ;
/**
*AIS目标原始信息
*/
public static String AisRawTargetTopic = "AisRawTargetTopic" ;
/**
*AIS目标信息
*/
public static String AisTargetTopic = "AisTargetTopic" ;
/**
*其他目标信息
*/
public static String ExtTargetTopic = "ExtTargetTopic" ;
/**
*融合目标信息
*/
public static String UnionTargetTopic = "UnionTargetTopic" ;
/**
*报警信息
*/
public static String AlarmInfoTopic = "AlarmInfoTopic" ;
/**
*站点信息
*/
public static String SiteTopic = "SiteTopic" ;
/**
*设备信息
*/
public static String DeviceInfoTopic = "DeviceInfoTopic" ;
/**
*设备状态信息
*/
public static String DeviceStatusTopic = "DeviceStatusTopic" ;
}
}

73
src/main/java/com/zgx/iot/config/mqtt/MQTTProps.java

@ -0,0 +1,73 @@
package com.zgx.iot.config.mqtt;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 配置文件的前缀
*/
@Data
@Component
@ConfigurationProperties(prefix = "mqtt")
public class MQTTProps {
@Data
public static class Service {
/**
* MQTT 服务器地址
*/
private String address;
/**
* 服务端 账号
*/
private String username;
/**
* 认证方式
*/
private String authentication;
/**
* 服务端 密码
*/
private String password;
}
@Data
public static class Retry {
/**
* 重试次数 ()
*/
private int count;
/**
* 重试间隔
*/
private int interval;
}
@Data
public static class Client {
/**
* mqtt 客户端 ID
*/
private String id;
/**
* 定阅的主题
*/
private String topics;
}
/**
* 服务端
*/
private Service service;
/**
* 客户端
*/
private Client client;
/**
* 重试选项
*/
private Retry retry;
}

80
src/main/java/com/zgx/iot/config/socket/ssl/NettyProps.java

@ -0,0 +1,80 @@
package com.zgx.iot.config.socket.ssl;
import com.zgx.iot.config.mqtt.MQTTProps;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "netty")
public class NettyProps {
@Data
public static class tcpClient {
/**
* netty tcp客户端地址
*/
private String address;
/**
* netty tcp客户端端口
*/
private String port;
}
@Data
public static class tcpService {
/**
* netty tcp服务端地址
*/
private String address;
/**
* netty tcp服务端端口
*/
private String port;
}
/**
* udp
*/
@Data
public static class udpService {
/**
* udp服务端地址
*/
private String address;
/**
* udp服务端端口
*/
private String port;
}
@Data
public static class udpClient {
/**
* netty udp客户端地址
*/
private String address;
/**
* netty udp客户端端口
*/
private String port;
}
/**
* tcp服务端
*/
private tcpService tcpService;
/**
* tcp客户端
*/
private tcpClient tcpClient;
/**
* udp服务端
*/
private tcpService udpService;
/**
* udp客户端
*/
private tcpClient udpClient;
}

4
src/main/java/com/zgx/iot/config/socket/ssl/SslConfig.java

@ -0,0 +1,4 @@
package com.zgx.iot.config.socket.ssl;
public class SslConfig {
}

94
src/main/java/com/zgx/iot/constant/CacheConstant.java

@ -0,0 +1,94 @@
package com.zgx.iot.constant;
/**
* @author: huangxutao
* @date: 2019-06-14
* @description: 缓存常量
*/
public interface CacheConstant {
/**
* 字典信息缓存
*/
public static final String SYS_DICT_CACHE = "sys:cache:dict";
/**
* 表字典信息缓存
*/
public static final String SYS_DICT_TABLE_CACHE = "sys:cache:dictTable";
public static final String SYS_DICT_TABLE_BY_KEYS_CACHE = SYS_DICT_TABLE_CACHE + "ByKeys";
/**
* 数据权限配置缓存
*/
public static final String SYS_DATA_PERMISSIONS_CACHE = "sys:cache:permission:datarules";
/**
* 缓存用户信息
*/
public static final String SYS_USERS_CACHE = "sys:cache:user";
/**
* 全部部门信息缓存
*/
public static final String SYS_DEPARTS_CACHE = "sys:cache:depart:alldata";
/**
* 全部部门ids缓存
*/
public static final String SYS_DEPART_IDS_CACHE = "sys:cache:depart:allids";
/**
* 测试缓存key
*/
public static final String TEST_DEMO_CACHE = "test:demo";
/**
* 字典信息缓存
*/
public static final String SYS_DYNAMICDB_CACHE = "sys:cache:dbconnect:dynamic:";
/**
* gateway路由缓存
*/
public static final String GATEWAY_ROUTES = "sys:cache:cloud:gateway_routes";
/**
* gateway路由 reload key
*/
public static final String ROUTE_JVM_RELOAD_TOPIC = "gateway_jvm_route_reload_topic";
/**
* TODO 冗余代码 待删除
*插件商城排行榜
*/
public static final String PLUGIN_MALL_RANKING = "pluginMall::rankingList";
/**
* TODO 冗余代码 待删除
*插件商城排行榜
*/
public static final String PLUGIN_MALL_PAGE_LIST = "pluginMall::queryPageList";
/**
* online列表页配置信息缓存key
*/
public static final String ONLINE_LIST = "sys:cache:online:list";
/**
* online表单页配置信息缓存key
*/
public static final String ONLINE_FORM = "sys:cache:online:form";
/**
* online报表
*/
public static final String ONLINE_RP = "sys:cache:online:rp";
/**
* online图表
*/
public static final String ONLINE_GRAPH = "sys:cache:online:graph";
}

14
src/main/java/com/zgx/iot/constant/GlobalConstants.java

@ -0,0 +1,14 @@
package com.zgx.iot.constant;
public class GlobalConstants {
/**
* 业务处理器beanName传递参数
*/
public static final String HANDLER_NAME = "handlerName";
/**
* redis消息通道名称
*/
public static final String REDIS_TOPIC_NAME="jeecg_redis_topic";
}

30
src/main/java/com/zgx/iot/constant/SocketConstant.java

@ -0,0 +1,30 @@
package com.zgx.iot.constant;
/**
* @Description: Socket常量类
* @author: bb
* @date: 2022-07-31
*/
public class SocketConstant {
/**
* 连接超时时间毫秒
*/
public static final int TIME_OUT = 3 * 1000;
/**
* 若指定时间内无数据交互则进行心跳探测
*/
public static final int IDLE_TIME = 15 * 1000;
/**
* 重试次数
*/
public static final int RETRY_COUNT = 5;
/**
* 重试间隔
*/
public static final int RETRY_INTERVAL = 3;
}

64
src/main/java/com/zgx/iot/constant/WebsocketConst.java

@ -0,0 +1,64 @@
package com.zgx.iot.constant;
/**
* @Description: Websocket常量类
* @author: taoyan
* @date: 2020年03月23日
*/
public class WebsocketConst {
/**
* 消息json key:cmd
*/
public static final String MSG_CMD = "cmd";
/**
* 消息json key:msgId
*/
public static final String MSG_ID = "msgId";
/**
* 消息json key:msgTxt
*/
public static final String MSG_TXT = "msgTxt";
/**
* 消息json key:userId
*/
public static final String MSG_USER_ID = "userId";
/**
* 消息类型 heartcheck
*/
public static final String CMD_CHECK = "heartcheck";
/**
* 消息类型 user 用户消息
*/
public static final String CMD_USER = "user";
/**
* 消息类型 topic 系统通知
*/
public static final String CMD_TOPIC = "topic";
/**
* 消息类型 email
*/
public static final String CMD_EMAIL = "email";
/**
* 消息类型 meetingsign 会议签到
*/
public static final String CMD_SIGN = "sign";
/**
* 消息类型 新闻发布/取消
*/
public static final String NEWS_PUBLISH = "publish";
/**
* 消息类型 事件通报
*/
public static final String event_PUBLISH = "eventPublish";
}

33
src/main/java/com/zgx/iot/constant/enums/AlarmType.java

@ -0,0 +1,33 @@
package com.zgx.iot.constant.enums;
/**
* 报警类型
*/
public enum AlarmType {
VIDEO("视频报警", 1),
RADAR("雷达报警", 2),
FENCE("电子围网报警", 3),
PATROL("巡逻人员警报", 4),
OTHERS("其他报警", 9);
private String desc;
private int code;
AlarmType(String desc, int code) {
this.desc = desc;
this.code = code;
}
public int getCode() {
return this.code;
}
public static String getDesc(int code) {
for (AlarmType alarmType : AlarmType.values()) {
if (code == alarmType.code) {
return alarmType.desc;
}
}
return null;
}
}

27
src/main/java/com/zgx/iot/constant/enums/AlarmType2.java

@ -0,0 +1,27 @@
package com.zgx.iot.constant.enums;
/**
* 报警类型
*/
public enum AlarmType2 {
INVADE("入侵", 1),
BREAK("破坏", 2),
OTHER("其他", 3);
private String desc;
private Integer code;
AlarmType2(String desc, Integer value) {
this.desc = desc;
this.code = value;
}
public String getDesc() {
return desc;
}
public Integer getCode() {
return code;
}
}

27
src/main/java/com/zgx/iot/constant/enums/CameraType.java

@ -0,0 +1,27 @@
package com.zgx.iot.constant.enums;
/**
* 设备类型
*/
public enum CameraType {
QIUJI("球机", 1),
QIANGJI("枪击", 2),
GUANGDIAN("光电跟踪仪", 3),
YUNTAI("高清云台", 4);
private final String desc;
private final Integer value;
CameraType(String desc, Integer value) {
this.desc = desc;
this.value = value;
}
public String getDesc() {
return desc;
}
public Integer getValue() {
return value;
}
}

25
src/main/java/com/zgx/iot/constant/enums/DateType.java

@ -0,0 +1,25 @@
package com.zgx.iot.constant.enums;
/**
* 信息类型
*/
public enum DateType {
ALARM_INFO("报警信息", 0),
STATE_INFO("状态信息", 1);
private String desc;
private Integer value;
DateType(String desc, Integer value) {
this.desc = desc;
this.value = value;
}
public String getDesc() {
return desc;
}
public Integer getValue() {
return value;
}
}

28
src/main/java/com/zgx/iot/constant/enums/DeviceComp.java

@ -0,0 +1,28 @@
package com.zgx.iot.constant.enums;
/**
* 相机设备厂商
*/
public enum DeviceComp {
HAIKAN("海康", 1),
DAHUA("大华", 2),
YUSHI("宇视", 3),
HEPU("和普", 4);
private String desc;
private Integer value;
DeviceComp(String desc, Integer value) {
this.desc = desc;
this.value = value;
}
public Integer getValue() {
return value;
}
public String getDesc(){
return desc;
}
}

29
src/main/java/com/zgx/iot/constant/enums/DeviceType.java

@ -0,0 +1,29 @@
package com.zgx.iot.constant.enums;
/**
* 设备类型
*/
public enum DeviceType {
RADAR("雷达", 1),
PHOTOELECTRIC("光电", 2),
PERIMETERALARM("电子围网", 3),
PHOTOVOLTAIC("光伏", 4),
DATARECORD("数据记录设备", 5),
VIBRATECABLE("振动电缆", 6);
private final String desc;
private final Integer value;
DeviceType(String desc, Integer value) {
this.desc = desc;
this.value = value;
}
public String getDesc() {
return desc;
}
public Integer getValue() {
return value;
}
}

54
src/main/java/com/zgx/iot/constant/enums/FaultItem.java

@ -0,0 +1,54 @@
package com.zgx.iot.constant.enums;
/**
* 故障诊断项
*/
public enum FaultItem {
N(1, "系统"),
N2(2, "网络连接"),
N3(3, "串口通信"),
N4(4, "视频接口通信"),
N5(5, "视频输入"),
N6(6, "视频处理子系统"),
N7(7, "视频编码"),
N8(8, "视频解码"),
N9(9, "智能分析"),
N10(10, "云台角度定位准确性"),
N11(11, "云台速度平稳性"),
N12(12, "可见光zoom定位准确性"),
N13(13, "可见光focus定位准确性"),
N14(14, "热像zoom定位准确性"),
N15(15, "热像focus定位准确性"),
N16(16, "热像自检"),
N17(17, "云台自检"),
N18(18, "激光自检"),
N19(19, "激光测距"),
N20(20, "GPS"),
N21(21, "电子罗盘"),
N22(22, "雨刷");
private int code;
private String desc;
FaultItem(int code, String desc) {
this.code = code;
this.desc = desc;
}
public static String getDesc(int code) {
for (FaultItem fenceType : FaultItem.values()) {
if (code == fenceType.code) {
return fenceType.desc;
}
}
return null;
}
public int getCode() {
return code;
}
public String getDesc() {
return desc;
}
}

37
src/main/java/com/zgx/iot/constant/enums/FaultResult.java

@ -0,0 +1,37 @@
package com.zgx.iot.constant.enums;
/**
* 故障诊断结果
*/
public enum FaultResult {
NORMAL(0, "正常"),
FAULT(1, "故障"),
UNSUPPORT(2, "不支持"),
POWEROFF(3, "电源关"),
UNDIAGNOSED(4, "未诊断");
private int code;
private String desc;
FaultResult(int code, String desc) {
this.code = code;
this.desc = desc;
}
public static String getDesc(int code) {
for (FaultResult fenceType : FaultResult.values()) {
if (code == fenceType.code) {
return fenceType.desc;
}
}
return null;
}
public int getCode() {
return code;
}
public String getDesc() {
return desc;
}
}

38
src/main/java/com/zgx/iot/constant/enums/FenceType.java

@ -0,0 +1,38 @@
package com.zgx.iot.constant.enums;
/**
* 电子围栏信息类型
*/
public enum FenceType {
BROKEN(2, "断线报警"),
INVADE(6, "入侵报警"),
OFFLINE(8, "离线报警"),
ONLINE(9, "离线报警恢复"),
TAMPER(10, "防拆报警"),
FAULT(12, "故障报警");
private int code;
private String desc;
FenceType(int code, String desc) {
this.code = code;
this.desc = desc;
}
public static String getDesc(int code) {
for (FenceType fenceType : FenceType.values()) {
if (code == fenceType.code) {
return fenceType.desc;
}
}
return null;
}
public int getCode() {
return code;
}
public String getDesc() {
return desc;
}
}

30
src/main/java/com/zgx/iot/constant/enums/Invade.java

@ -0,0 +1,30 @@
package com.zgx.iot.constant.enums;
/**
* 入侵行为
*/
public enum Invade {
CLIMB(1, "攀爬"), JUMP(2, "翻越");
private int code;
private String value;
Invade(int code, String value) {
this.code = code;
this.value = value;
}
public String getValue() {
return this.value;
}
public static String getVal(int code) {
for (Invade invade : Invade.values()) {
if (code == invade.code) {
return invade.value;
}
}
return null;
}
}

27
src/main/java/com/zgx/iot/constant/enums/StateType.java

@ -0,0 +1,27 @@
package com.zgx.iot.constant.enums;
/**
* 状态类型
*/
public enum StateType {
HEARTBEAT("心跳",1),
BREAK_LINE("断纤",2),
OTHER_FAULT("其他故障",3);
private String desc;
private Integer code;
StateType(String desc, Integer value) {
this.desc = desc;
this.code = value;
}
public String getDesc() {
return desc;
}
public Integer getCode() {
return code;
}
}

27
src/main/java/com/zgx/iot/constant/enums/TargetType.java

@ -0,0 +1,27 @@
package com.zgx.iot.constant.enums;
/**
* 目标类型
*/
public enum TargetType {
PEOPLE("人", 1),
CAR("车", 2),
OTHER("其他", 3);
private String desc;
private Integer code;
TargetType(String desc, Integer value) {
this.desc = desc;
this.code = value;
}
public String getDesc() {
return desc;
}
public Integer getCode() {
return code;
}
}

18
src/main/java/com/zgx/iot/constant/enums/WarnLevel.java

@ -0,0 +1,18 @@
package com.zgx.iot.constant.enums;
/**
* 报警等级
*/
public enum WarnLevel {
ONE(1), TWO(2), THREE(3), FOUR(4);
private int value;
WarnLevel(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
}

18
src/main/java/com/zgx/iot/constant/enums/WarnType.java

@ -0,0 +1,18 @@
package com.zgx.iot.constant.enums;
/**
* 警示类型
*/
public enum WarnType {
PRE_WARN(1), WARN(2);
private int value;
WarnType(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
}

248
src/main/java/com/zgx/iot/controller/TrackingTargetController.java

@ -0,0 +1,248 @@
package com.zgx.iot.controller;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zgx.iot.constant.enums.DeviceType;
import com.zgx.iot.dto.radar.TrackingTargetDTO;
import com.zgx.iot.dto.site.Result;
import com.zgx.iot.entity.DtDeviceInfo;
import com.zgx.iot.entity.MsCameraSetting;
import com.zgx.iot.service.IDtDeviceInfoService;
import com.zgx.iot.service.IMsAlarmSettingsService;
import com.zgx.iot.service.IMsCameraSettingService;
import com.zgx.iot.utils.GEOUtils;
import com.zgx.iot.utils.RedisUtil;
import com.zgx.iot.utils.hp.HPDataParser;
import com.zgx.iot.utils.hp.HPReqParamEnc;
import com.zgx.iot.utils.hp.ThreadManager;
import com.zgx.iot.utils.socket.TcpClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.List;
/**
* 光电跟踪接口
*/
@RestController
@RequestMapping("/tracking")
@Slf4j
public class TrackingTargetController {
@Autowired
RedisUtil redisUtil;
@Autowired
IDtDeviceInfoService msDeviceInfoService;
@Autowired
IMsCameraSettingService msCameraSettingService;
@Autowired
IMsAlarmSettingsService msAlarmSettingsService;
@PostMapping(value = "/target")
public Result<?> trackingTarget(@RequestBody TrackingTargetDTO trackingTarget) throws UnsupportedEncodingException {
//获取目标id 和 雷达id 和是否跟踪
String trackTargetId = String.valueOf(trackingTarget.getTrackId());
int radarId = trackingTarget.getRadarId();
boolean isTracking = trackingTarget.isTrackStatus();//todo : 是否跟踪
String trackIdKey = "trackIds:" + trackTargetId;
//目标经纬度
float targetLon = Float.parseFloat(redisUtil.hget(trackIdKey, "targetLon").toString());
float targetLat = Float.parseFloat(redisUtil.hget(trackIdKey, "targetLat").toString());
//目标距离(基于雷达)
int distance = Integer.parseInt(redisUtil.hget(trackIdKey, "targetDis").toString());
//目标方位角(基于雷达)
float azimuth = Float.parseFloat(redisUtil.hget(trackIdKey, "targetAzimuth").toString());
log.info("目标经纬度:" + targetLon + "," + targetLat);
//查询雷达信息 雷达经纬度(113.455074,22.122197)
QueryWrapper<DtDeviceInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("device_type", DeviceType.RADAR.getValue()) //雷达类型
.eq("device_status", 1) //1-启用状态
.eq("id", radarId); //雷达Id
DtDeviceInfo deviceInfo = msDeviceInfoService.getOne(queryWrapper);
if (deviceInfo == null) {
log.info("查询不到雷达设备");
return Result.error("查询不到雷达设备");
}
log.info("雷达设备信息:" + deviceInfo);
//查询光电信息
DtDeviceInfo cameraInfo = null;
LambdaQueryWrapper<DtDeviceInfo> photoelectricLambdaQueryWrapper = new LambdaQueryWrapper<>();
photoelectricLambdaQueryWrapper.eq(DtDeviceInfo::getDeviceType, DeviceType.PHOTOELECTRIC.getValue()) //光电类型
.eq(DtDeviceInfo::getDeviceStatus, 1);//1-启用状态
List<DtDeviceInfo> photoelectricDevices = msDeviceInfoService.list(photoelectricLambdaQueryWrapper);//查出所有光电
if (CollectionUtils.isEmpty(photoelectricDevices)) {
log.info("查询不到光电设备");
return Result.error("查询不到光电设备");
}
cameraInfo = photoelectricDevices.get(0);//todo : 是否需要计算最近的光电
log.info("光电设备信息:" + cameraInfo);
//1、若设备关联光电,则进行联动定位
if (cameraInfo != null) {
double cameraAzimuth = cameraInfo.getInitAzimuth() + Double.parseDouble(redisUtil.hget("PTZStatus", "pan").toString());
//计算目标基于光电的方位角
double targetAzimuth = GEOUtils.getAzimuth(cameraInfo.getDeviceLon(),
deviceInfo.getDeviceLat(),
targetLon,
targetLat
);
//计算光电水平所需方位角
double differAzimuth = targetAzimuth - cameraAzimuth;
//计算方位角
double horAngle = Double.parseDouble(redisUtil.hget("PTZStatus", "pan").toString()) + differAzimuth;
horAngle = horAngle >= 0 ? horAngle : (360 + horAngle);
//计算俯仰角(上27000-36000中间0-9000下)
double verAngle = Math.toDegrees(Math.asin((double) cameraInfo.getDeviceHeight() / distance));
verAngle = verAngle + cameraInfo.getInitPitch();
//根据IP获取对应光电线程
TcpClient tcpClient = ThreadManager.getTcpClientMap().get(cameraInfo.getDeviceIp());
//停止跟踪
tcpClient.send(
HPDataParser.send(
HPReqParamEnc.ivpTrackingCtrl(String.valueOf(redisUtil.get(tcpClient.getIp())), 0, false, null)
)
);
//转动光电到指定位置
//当光电已经处于跟踪状态时,以下操作不会生效
//根据目标位置进行定位(角度实际上送值 : 100倍整数值)
tcpClient.send(
HPDataParser.send(
HPReqParamEnc.ptzControl(String.valueOf(redisUtil.get(tcpClient.getIp())),
0, 51, null,
null, null, 45,
(int) (horAngle * 100), (int) (verAngle * 100), null)
)
);
//目标高度 平均高度 在ms_alarm_settings表中设置 船的平均高度 高度越高视场角越大
double h = Double.parseDouble(redisUtil.hget("alarm_settings", "targetHeight").toString());
//计算目标距离光点的距离
double d = GEOUtils.GetDistance(targetLon, targetLat, cameraInfo.getDeviceLon(), cameraInfo.getDeviceLat());
//计算视场角,100为分辨率/像素
double fov = Math.toDegrees(Math.atan(h / d)) * 2 * 100;
log.info("目标平均高度:" + h + " 目标距离光电:" + d);
log.info("水平方位角:" + horAngle + " 俯仰角:" + verAngle + " 视场角:" + fov);
tcpClient.send(
HPDataParser.send(
HPReqParamEnc.ptzControl(String.valueOf(redisUtil.get(tcpClient.getIp())),
0, 42, null,
null, null, null,
null, null, (int) (fov * 100))
)
);
//球机联动
log.info("联动控制球机:");
LambdaQueryWrapper<MsCameraSetting> cameraSettingLambdaQueryWrapper = new LambdaQueryWrapper<>();
cameraSettingLambdaQueryWrapper.eq(MsCameraSetting::getType, 2)//2-球机类型
.eq(MsCameraSetting::getStatus, 1);//1-启用状态
List<MsCameraSetting> cameraSettings = msCameraSettingService.list(cameraSettingLambdaQueryWrapper);
if (CollectionUtils.isEmpty(cameraSettings)) {
log.info("没有可联动的球机");
return Result.error("没有可联动的球机");
}
log.info("case4 : 遍历相机列表 寻找最近的点的球机去跟踪");
// 计算距离最近的球机
MsCameraSetting msCameraSetting = null;//最近球机信息
double nearestDistance = 0;//最近距离
double heightDiff = 0;//最近球机的高度差
for (MsCameraSetting cameraSetting : cameraSettings) {
// 判断该球机是否满足照射范围 不满足的话还可以找第二近的球机 如果放到后面才判断高度差 就无法找第二近的去跟踪了
BigDecimal cameraHeight = cameraSetting.getHeight();//球机高度
BigDecimal labelHeight = new BigDecimal(h);//目标高度
double tempHeightDiff = cameraHeight.subtract(labelHeight).doubleValue();//球机与目标高度差
if (tempHeightDiff < 0) {
log.info("case4 :" + "ip=" + cameraSetting.getIp() + " tempHeightDiff < 0 超过球机照射范围");
} else {
double temp = GEOUtils.GetDistance(cameraSetting.getLongitude().doubleValue(), cameraSetting.getLatitude().doubleValue(), targetLon, targetLat);
log.info("当前的球机" + cameraSetting.getIp() + "与目标的距离:" + temp);
// 第一次 先将第一个球机的距离作为最近距离 和 最近球机信息
if (msCameraSetting == null) {
msCameraSetting = cameraSetting;
nearestDistance = temp;
continue;
}
// 第二次以后 如果距离更近则更新最近距离 以及 最近球机信息
if (nearestDistance > temp) {
msCameraSetting = cameraSetting;
nearestDistance = temp;
heightDiff = tempHeightDiff;
}
}
}
//没有找到跟踪的球机
if (msCameraSetting == null) {
log.info("没有可跟踪的球机");
return Result.ERROR("没有可跟踪的球机");
}
//判断两点的距离是否超过有效距离,超过则丢掉
if (nearestDistance > Integer.parseInt(redisUtil.hget("alarm_settings", "inOutEffectDistance").toString())) {
log.info("case4 :" + "目标超过跟踪的最大距离" + redisUtil.hget("alarm_settings", "inOutEffectDistance").toString());
return Result.ERROR("目标超过跟踪的最大距离");
}
log.info("case4 :" + " 相机IP:" + msCameraSetting.getIp() + " 最短距离nearestDistance:" + nearestDistance);
log.info("case4 :" + "距离最近的相机:" + JSON.toJSONString(msCameraSetting));
//控制球机照射目标
log.info("case4【尝试使用ptzControllerByLatLonAndDistance】将球机转到目标位置");
msCameraSettingService.ptzControllerByLatLon(msCameraSetting.getIp(),
msCameraSetting.getUser(),
msCameraSetting.getPassword(),
msCameraSetting.getMaxElevation(),
msCameraSetting.getZeroAzimuth(),
heightDiff,
msCameraSetting.getZoomFactor(),
msCameraSetting.getLongitude().doubleValue(),
msCameraSetting.getLatitude().doubleValue(),
targetLon,
targetLat,
msCameraSetting.getFactory());//factory用于区分品牌类型 1:海康 2:宇视
log.info("跟踪球机的主要参数信息:");
log.info("1.IP: " + msCameraSetting.getIp());
log.info("2.用户名: " + msCameraSetting.getUser());
log.info("3.密码: " + msCameraSetting.getPassword());
log.info("4.最大俯仰角: " + msCameraSetting.getMaxElevation());
log.info("5.初始方位角: " + msCameraSetting.getZeroAzimuth());
log.info("6.品牌: " + (msCameraSetting.getFactory() == 1 ? "海康" : "宇视"));
//将需要跟踪的目标进行保存 并且保存跟踪该目标的球机IP
redisUtil.hset("trackingTargetId", trackTargetId, msCameraSetting.getIp());
log.info("正在跟踪的trackId:" + trackTargetId + "跟踪的球机" + msCameraSetting.getIp());
//返回当前联动跟踪的球机信息
return Result.OK(msCameraSetting);
}
return Result.ERROR("没有可跟踪的光电");
}
}

22
src/main/java/com/zgx/iot/dto/Brower2LpmDto.java

@ -0,0 +1,22 @@
package com.zgx.iot.dto;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class Brower2LpmDto {
private Integer messageType ; // 1 连接 ,2 数据
private String deviceCode ; // 设备号
private Integer dataType ; // 数据类型 1 16进制,2 ascii
private String data ; // 数据
}

52
src/main/java/com/zgx/iot/dto/radar/NyGuideCamPosModel.java

@ -0,0 +1,52 @@
//
// Decompiled by Procyon v0.5.36
//
package com.zgx.iot.dto.radar;
import java.beans.ConstructorProperties;
/**
* 引导光电位置
*/
public class NyGuideCamPosModel
{
/**
* 距离单位
*/
private int dis;
/**
* 方位相对于大地北单位
*/
private float azimuth;
public int getDis() {
return dis;
}
public void setDis(int dis) {
this.dis = dis;
}
public float getAzimuth() {
return azimuth;
}
public void setAzimuth(float azimuth) {
this.azimuth = azimuth;
}
public NyGuideCamPosModel() {
}
@ConstructorProperties({ "dis","azimuth" })
public NyGuideCamPosModel(final int dis, final float azimuth) {
this.dis=dis;
this.azimuth=azimuth;
}
}

87
src/main/java/com/zgx/iot/dto/radar/RadarRESPackageModel.java

@ -0,0 +1,87 @@
//
// Decompiled by Procyon v0.5.36
//
package com.zgx.iot.dto.radar;
import com.zgx.iot.utils.radarUtils.BitConverter;
import java.beans.ConstructorProperties;
/**
* todo 雷达总体数据
* 1.包头标识 mark
* 2.数据类型 dataType
* 3.整包数据的长度 dataLength
* 4.数据数量 dataNum
* 5.雷达数据 allBytes
*/
public class RadarRESPackageModel
{
private byte[] allBytes;
public int getMark() {
final int mark = BitConverter.bytes2IntSmallEndian(this.allBytes, 0);
return mark;
}
public int getDataType() {
final int dataType = BitConverter.bytes2IntSmallEndian(this.allBytes, 4);
return dataType;
}
public int getDataLength() {
final int dataLength = BitConverter.bytes2IntSmallEndian(this.allBytes, 8);
return dataLength;
}
public int getDataNum() {
final int dataNum = BitConverter.bytes2IntSmallEndian(this.allBytes, 12);
return dataNum;
}
public boolean isIntegrated() {
boolean flag = false;
if (this.getDataLength() <= this.allBytes.length) {
flag = true;
}
return flag;
}
public byte[] getData() {
final int len = this.getDataLength() - 16;
final byte[] bs = new byte[len];
System.arraycopy(this.allBytes, 16, bs, 0, len);
return bs;
}
public byte[] getRemain() {
final int len = this.getDataLength();
byte[] bs = null;
if (len < this.allBytes.length) {
bs = new byte[this.allBytes.length - len];
System.arraycopy(this.allBytes, len, bs, 0, this.allBytes.length - len);
}
return bs;
}
public RadarRESPackageModel() {
this.allBytes = null;
}
@ConstructorProperties({ "allBytes" })
public RadarRESPackageModel(final byte[] allBytes) {
this.allBytes = null;
this.allBytes = allBytes;
}
public void setAllBytes(final byte[] allBytes) {
this.allBytes = allBytes;
}
public byte[] getAllBytes() {
return this.allBytes;
}
}

101
src/main/java/com/zgx/iot/dto/radar/RadarStateModel.java

@ -0,0 +1,101 @@
//
// Decompiled by Procyon v0.5.36
//
package com.zgx.iot.dto.radar;
import java.beans.ConstructorProperties;
/**
* 雷达状态数据
*/
public class RadarStateModel
{
private int radarId;
private long timestamp;
private char workState;
private char sendState;
private float temperature;
private float longitude;
private float latitude;
private float altitude;
public void setRadarId(final int radarId) {
this.radarId = radarId;
}
public void setTimestamp(final long timestamp) {
this.timestamp = timestamp;
}
public void setWorkState(final char workState) {
this.workState = workState;
}
public void setSendState(final char sendState) {
this.sendState = sendState;
}
public void setTemperature(final float temperature) {
this.temperature = temperature;
}
public void setLongitude(final float longitude) {
this.longitude = longitude;
}
public void setLatitude(final float latitude) {
this.latitude = latitude;
}
public void setAltitude(final float altitude) {
this.altitude = altitude;
}
public int getRadarId() {
return this.radarId;
}
public long getTimestamp() {
return this.timestamp;
}
public char getWorkState() {
return this.workState;
}
public char getSendState() {
return this.sendState;
}
public float getTemperature() {
return this.temperature;
}
public float getLongitude() {
return this.longitude;
}
public float getLatitude() {
return this.latitude;
}
public float getAltitude() {
return this.altitude;
}
public RadarStateModel() {
}
@ConstructorProperties({ "radarId", "timestamp", "workState", "sendState", "temperature", "longitude", "latitude", "altitude" })
public RadarStateModel(final int radarId, final long timestamp, final char workState, final char sendState, final float temperature, final float longitude, final float latitude, final float altitude) {
this.radarId = radarId;
this.timestamp = timestamp;
this.workState = workState;
this.sendState = sendState;
this.temperature = temperature;
this.longitude = longitude;
this.latitude = latitude;
this.altitude = altitude;
}
}

91
src/main/java/com/zgx/iot/dto/radar/RadarTargetModel.java

@ -0,0 +1,91 @@
//
// Decompiled by Procyon v0.5.36
//
package com.zgx.iot.dto.radar;
import java.beans.ConstructorProperties;
/**
* 雷达点迹数据
*/
public class RadarTargetModel
{
private int radarId;
private long timestamp;
private int dis;
private float azimuth;
private float longitude;
private float latitude;
private float altitude;
public void setRadarId(final int radarId) {
this.radarId = radarId;
}
public void setTimestamp(final long timestamp) {
this.timestamp = timestamp;
}
public void setDis(final int dis) {
this.dis = dis;
}
public void setAzimuth(final float azimuth) {
this.azimuth = azimuth;
}
public void setLongitude(final float longitude) {
this.longitude = longitude;
}
public void setLatitude(final float latitude) {
this.latitude = latitude;
}
public void setAltitude(final float altitude) {
this.altitude = altitude;
}
public int getRadarId() {
return this.radarId;
}
public long getTimestamp() {
return this.timestamp;
}
public int getDis() {
return this.dis;
}
public float getAzimuth() {
return this.azimuth;
}
public float getLongitude() {
return this.longitude;
}
public float getLatitude() {
return this.latitude;
}
public float getAltitude() {
return this.altitude;
}
public RadarTargetModel() {
}
@ConstructorProperties({ "radarId", "timestamp", "dis", "azimuth", "longitude", "latitude", "altitude" })
public RadarTargetModel(final int radarId, final long timestamp, final int dis, final float azimuth, final float longitude, final float latitude, final float altitude) {
this.radarId = radarId;
this.timestamp = timestamp;
this.dis = dis;
this.azimuth = azimuth;
this.longitude = longitude;
this.latitude = latitude;
this.altitude = altitude;
}
}

225
src/main/java/com/zgx/iot/dto/radar/RadarTrackModel.java

@ -0,0 +1,225 @@
//
// Decompiled by Procyon v0.5.36
//
package com.zgx.iot.dto.radar;
import java.beans.ConstructorProperties;
/**
* 雷达航迹数据
*/
public class RadarTrackModel
{
private int radarId;//设备ID
private long timestamp;//时间戳
private int trackId;//航迹ID(目标批号)
private char trackState;//目标状态
private int dis;//距离
private float azimuth;//方位角
private float speed;//速度
private float course;//航向
private float longitude;//经度
private float latitude;//纬度
private float altitude;//海拔(估算目标高度)
private char type;//目标类型
//todo 增加字段
private int deviceOwnerId;//设备所属站点ID
private int counter;//目标消息
private int timeoutToNext;
public int getdeviceOwnerId() {
return deviceOwnerId;
}
public void setdeviceOwnerId(int deviceOwnerId) {
this.deviceOwnerId = deviceOwnerId;
}
public int getCounter() {
return counter;
}
public void setCounter(int counter) {
this.counter = counter;
}
public int getDeviceOwnerId() {
return deviceOwnerId;
}
public void setDeviceOwnerId(int deviceOwnerId) {
this.deviceOwnerId = deviceOwnerId;
}
public int getTimeoutToNext() {
return timeoutToNext;
}
public void setTimeoutToNext(int timeoutToNext) {
this.timeoutToNext = timeoutToNext;
}
public void setRadarId(final int radarId) {
this.radarId = radarId;
}
public void setTimestamp(final long timestamp) {
this.timestamp = timestamp;
}
public void setTrackId(final int trackId) {
this.trackId = trackId;
}
public void setTrackState(final char trackState) {
this.trackState = trackState;
}
public void setDis(final int dis) {
this.dis = dis;
}
public void setAzimuth(final float azimuth) {
this.azimuth = azimuth;
}
public void setSpeed(final float speed) {
this.speed = speed;
}
public void setCourse(final float course) {
this.course = course;
}
public void setLongitude(final float longitude) {
this.longitude = longitude;
}
public void setLatitude(final float latitude) {
this.latitude = latitude;
}
public void setAltitude(final float altitude) {
this.altitude = altitude;
}
public void setType(final char type) {
this.type = type;
}
public int getRadarId() {
return this.radarId;
}
public long getTimestamp() {
return this.timestamp;
}
public int getTrackId() {
return this.trackId;
}
public char getTrackState() {
return this.trackState;
}
public int getDis() {
return this.dis;
}
public float getAzimuth() {
return this.azimuth;
}
public float getSpeed() {
return this.speed;
}
public float getCourse() {
return this.course;
}
public float getLongitude() {
return this.longitude;
}
public float getLatitude() {
return this.latitude;
}
public float getAltitude() {
return this.altitude;
}
public char getType() {
return this.type;
}
public RadarTrackModel() {
}
@ConstructorProperties({ "radarId", "timestamp", "trackId", "trackState", "dis", "azimuth", "speed", "course", "longitude", "latitude", "altitude", "type" })
public RadarTrackModel(final int radarId,
final long timestamp,
final int trackId,
final char trackState,
final int dis,
final float azimuth,
final float speed,
final float course,
final float longitude,
final float latitude,
final float altitude,
final char type) {
this.radarId = radarId;
this.timestamp = timestamp;
this.trackId = trackId;
this.trackState = trackState;
this.dis = dis;
this.azimuth = azimuth;
this.speed = speed;
this.course = course;
this.longitude = longitude;
this.latitude = latitude;
this.altitude = altitude;
this.type = type;
}
//todo : 把新增字段的加入构造函数
@ConstructorProperties({ "radarId", "timestamp", "trackId", "trackState", "dis", "azimuth", "speed", "course", "longitude", "latitude", "altitude", "type" ,"deviceOwnerId","counter","timeoutToNext"})
public RadarTrackModel(final int radarId,
final long timestamp,
final int trackId,
final char trackState,
final int dis,
final float azimuth,
final float speed,
final float course,
final float longitude,
final float latitude,
final float altitude,
final char type,
final int deviceOwnerId,
final int counter,
final int timeoutToNext) {
this.radarId = radarId;
this.timestamp = timestamp;
this.trackId = trackId;
this.trackState = trackState;
this.dis = dis;
this.azimuth = azimuth;
this.speed = speed;
this.course = course;
this.longitude = longitude;
this.latitude = latitude;
this.altitude = altitude;
this.type = type;
this.deviceOwnerId=deviceOwnerId;
this.counter=counter;
this.timeoutToNext=timeoutToNext;
}
}

29
src/main/java/com/zgx/iot/dto/radar/TrackingTargetDTO.java

@ -0,0 +1,29 @@
package com.zgx.iot.dto.radar;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TrackingTargetDTO {
/**
* 雷达Id
*/
private int radarId;
/**
* 轨迹Id
*/
private int trackId;
/**
* 是否跟踪
*/
private boolean trackStatus;
}

120
src/main/java/com/zgx/iot/dto/site/AisInfo.java

@ -0,0 +1,120 @@
package com.zgx.iot.dto.site;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
/**
* @Description: 船泊AIS信息表
* @Author: jeecg-boot
* @Date: 2021-11-01
* @Version: V1.0
*/
@Data
public class AisInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**主键*/
//(value = "主键")
private String id;
/**创建人*/
//(value = "创建人")
private String createBy;
/**创建日期*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
//(value = "创建日期")
private java.util.Date createTime;
/**更新人*/
//(value = "更新人")
private String updateBy;
/**更新日期*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
//(value = "更新日期")
private java.util.Date updateTime;
/**事件编号*/
//(value = "事件编号")
private String eventSerialNum;
/**船名*/
//(value = "船名")
private String shipName;
/**MMSI*/
//(value = "MMSI")
private String mmsi;
/**呼号*/
//(value = "呼号")
private String callSign;
/**IMO*/
//(value = "IMO")
private String imo;
/**船首向*/
//(value = "船首向")
private java.math.BigDecimal bowDirection;
/**航迹向*/
//(value = "航迹向")
private java.math.BigDecimal trackDirection;
/**状态*/
//(value = "状态")
private Integer shipStatus;
/**船长*/
//(value = "船长")
private Double shipLength;
/**船宽*/
//(value = "船宽")
private Double shipWidth;
/**吃水*/
//(value = "吃水")
private Double draft;
/**类型*/
//(value = "类型")
private Integer shipType;
/**航速*/
//(value = "航速")
private Double shipSpeed;
/**目的地*/
//(value = "目的地")
private String destination;
/**经度*/
//(value = "经度")
private java.math.BigDecimal longitude;
/**纬度*/
//(value = "纬度")
private java.math.BigDecimal latitude;
/**国籍*/
//(value = "国籍")
private String nationality;
/**预到时间*/
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
//(value = "预到时间")
private java.util.Date preArrivalTime;
//(value = "创建时间")
private Long realTime;
//(value = "操作类型:设备增加,1;设备删减,2;设备信息变更,3;")
private int operaType;
}

101
src/main/java/com/zgx/iot/dto/site/AlarmInfo.java

@ -0,0 +1,101 @@
package com.zgx.iot.dto.site;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* @Description: 告警信息格式
* @Author: lxc
* @Date: 2023-08-01
* @Version: V1.0
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
public class AlarmInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**报警信息唯一标识*/
/*@TableId(type = IdType.ASSIGN_ID)*/
//(value = "报警信息唯一标识")
private String _id;
/**报警所属站点ID*/
//(value = "报警所属站点ID")
private String alarmOwnerId;
/**报警类型*/
//(value = "报警类型")
private Integer alarmType;
/**报警类型名称*/
//(value = "报警类型名称")
private String alarmTypeName;
/**报警等级*/
//(value = "报警等级")
private Integer alarmLevel;
/**报警信息描述*/
//(value = "报警信息描述")
private String alarmContent;
/**报警处置状态*/
//(value = "报警处置状态")
private String alarmDisposal;
/**报警开始时间*/
//(value = "报警开始时间")
private Date alarmTimeStart;
/**报警关闭时间*/
//(value = "报警关闭时间")
private Date alarmTimeEnd;
/**报警点经度*/
//(value = "报警点经度")
private Double alarmPointLon;
/**报警点纬度*/
//(value = "报警点纬度")
private Double alarmPointLat;
/**报警点海拔*/
//(value = "报警点海拔")
private Double alarmPointAlt;
/**关联报警目标唯一标识*/
//(value = "关联报警目标唯一标识")
private String alarmTargetId;
/**记录目标到目前位置航迹点位*/
//(value = "记录目标到目前位置航迹点位")
private String targetPoint;
/**关联摄像机唯一标识*/
//(value = "关联摄像机唯一标识")
private String alarmCameraId;
/**创建人*/
//(value = "创建人")
private String createBy;
/**创建时间*/
//(value = "创建时间")
private Long realTime;
//(value = "操作类型:设备增加,1;设备删减,2;设备信息变更,3;")
private int operaType;
}

325
src/main/java/com/zgx/iot/dto/site/CommonConstant.java

@ -0,0 +1,325 @@
package com.zgx.iot.dto.site;
public interface CommonConstant {
/**
* 正常状态
*/
public static final Integer STATUS_NORMAL = 0;
/**
* 禁用状态
*/
public static final Integer STATUS_DISABLE = -1;
/**
* 删除标志
*/
public static final Integer DEL_FLAG_1 = 1;
/**
* 未删除
*/
public static final Integer DEL_FLAG_0 = 0;
/**
* 系统日志类型 登录
*/
public static final int LOG_TYPE_1 = 1;
/**
* 系统日志类型 操作
*/
public static final int LOG_TYPE_2 = 2;
/**
* 操作日志类型 查询
*/
public static final int OPERATE_TYPE_1 = 1;
/**
* 操作日志类型 添加
*/
public static final int OPERATE_TYPE_2 = 2;
/**
* 操作日志类型 更新
*/
public static final int OPERATE_TYPE_3 = 3;
/**
* 操作日志类型 删除
*/
public static final int OPERATE_TYPE_4 = 4;
/**
* 操作日志类型 倒入
*/
public static final int OPERATE_TYPE_5 = 5;
/**
* 操作日志类型 导出
*/
public static final int OPERATE_TYPE_6 = 6;
/** {@code 500 Server Error} (HTTP/1.0 - RFC 1945) */
public static final Integer SC_INTERNAL_SERVER_ERROR_500 = 500;
/** {@code 200 OK} (HTTP/1.0 - RFC 1945) */
public static final Integer SC_OK_200 = 200;
/**访问权限认证未通过 510*/
public static final Integer SC_JEECG_NO_AUTHZ=510;
/** 登录用户Shiro权限缓存KEY前缀 */
public static String PREFIX_USER_SHIRO_CACHE = "shiro:cache:org.jeecg.config.shiro.ShiroRealm.authorizationCache:";
/** 登录用户Token令牌缓存KEY前缀 */
public static final String PREFIX_USER_TOKEN = "prefix_user_token_";
/** Token缓存时间:3600秒即一小时 */
public static final int TOKEN_EXPIRE_TIME = 3600;
/**
* 0一级菜单
*/
public static final Integer MENU_TYPE_0 = 0;
/**
* 1子菜单
*/
public static final Integer MENU_TYPE_1 = 1;
/**
* 2按钮权限
*/
public static final Integer MENU_TYPE_2 = 2;
/**通告对象类型(USER:指定用户,ALL:全体用户)*/
public static final String MSG_TYPE_UESR = "USER";
public static final String MSG_TYPE_ALL = "ALL";
/**发布状态(0未发布,1已发布,2已撤销)*/
public static final String NO_SEND = "0";
public static final String HAS_SEND = "1";
public static final String HAS_CANCLE = "2";
/**阅读状态(0未读,1已读)*/
public static final String HAS_READ_FLAG = "1";
public static final String NO_READ_FLAG = "0";
/**优先级(L低,M中,H高)*/
public static final String PRIORITY_L = "L";
public static final String PRIORITY_M = "M";
public static final String PRIORITY_H = "H";
/**
* 短信模板方式 0 .登录模板1.注册模板2.忘记密码模板
*/
public static final String SMS_TPL_TYPE_0 = "0";
public static final String SMS_TPL_TYPE_1 = "1";
public static final String SMS_TPL_TYPE_2 = "2";
/**
* 状态(0无效1有效)
*/
public static final String STATUS_0 = "0";
public static final String STATUS_1 = "1";
/**
* 同步工作流引擎1同步0不同步
*/
public static final Integer ACT_SYNC_1 = 1;
public static final Integer ACT_SYNC_0 = 0;
/**
* 消息类型1:通知公告2:系统消息
*/
public static final String MSG_CATEGORY_1 = "1";
public static final String MSG_CATEGORY_2 = "2";
/**
* 是否配置菜单的数据权限 1是0否
*/
public static final Integer RULE_FLAG_0 = 0;
public static final Integer RULE_FLAG_1 = 1;
/**
* 是否用户已被冻结 1正常(解冻) 2冻结
*/
public static final Integer USER_UNFREEZE = 1;
public static final Integer USER_FREEZE = 2;
/**字典翻译文本后缀*/
public static final String DICT_TEXT_SUFFIX = "_dictText";
/**
* 表单设计器主表类型
*/
public static final Integer DESIGN_FORM_TYPE_MAIN = 1;
/**
* 表单设计器子表表类型
*/
public static final Integer DESIGN_FORM_TYPE_SUB = 2;
/**
* 表单设计器URL授权通过
*/
public static final Integer DESIGN_FORM_URL_STATUS_PASSED = 1;
/**
* 表单设计器URL授权未通过
*/
public static final Integer DESIGN_FORM_URL_STATUS_NOT_PASSED = 2;
/**
* 表单设计器新增 Flag
*/
public static final String DESIGN_FORM_URL_TYPE_ADD = "add";
/**
* 表单设计器修改 Flag
*/
public static final String DESIGN_FORM_URL_TYPE_EDIT = "edit";
/**
* 表单设计器详情 Flag
*/
public static final String DESIGN_FORM_URL_TYPE_DETAIL = "detail";
/**
* 表单设计器复用数据 Flag
*/
public static final String DESIGN_FORM_URL_TYPE_REUSE = "reuse";
/**
* 表单设计器编辑 Flag 已弃用
*/
public static final String DESIGN_FORM_URL_TYPE_VIEW = "view";
/**
* online参数值设置Y, N
*/
public static final String ONLINE_PARAM_VAL_IS_TURE = "Y";
public static final String ONLINE_PARAM_VAL_IS_FALSE = "N";
/**
* 文件上传类型本地localMiniominio阿里云alioss
*/
public static final String UPLOAD_TYPE_LOCAL = "local";
public static final String UPLOAD_TYPE_MINIO = "minio";
public static final String UPLOAD_TYPE_OSS = "alioss";
/**
* 文档上传自定义桶名称
*/
public static final String UPLOAD_CUSTOM_BUCKET = "eoafile";
/**
* 文档上传自定义路径
*/
public static final String UPLOAD_CUSTOM_PATH = "eoafile";
/**
* 文件外链接有效天数
*/
public static final Integer UPLOAD_EFFECTIVE_DAYS = 1;
/**
* 员工身份 1:普通员工 2:上级
*/
public static final Integer USER_IDENTITY_1 = 1;
public static final Integer USER_IDENTITY_2 = 2;
/** sys_user 表 username 唯一键索引 */
public static final String SQL_INDEX_UNIQ_SYS_USER_USERNAME = "uniq_sys_user_username";
/** sys_user 表 work_no 唯一键索引 */
public static final String SQL_INDEX_UNIQ_SYS_USER_WORK_NO = "uniq_sys_user_work_no";
/** sys_user 表 phone 唯一键索引 */
public static final String SQL_INDEX_UNIQ_SYS_USER_PHONE = "uniq_sys_user_phone";
/** sys_user 表 email 唯一键索引 */
public static final String SQL_INDEX_UNIQ_SYS_USER_EMAIL = "uniq_sys_user_email";
/** sys_quartz_job 表 job_class_name 唯一键索引 */
public static final String SQL_INDEX_UNIQ_JOB_CLASS_NAME = "uniq_job_class_name";
/** sys_position 表 code 唯一键索引 */
public static final String SQL_INDEX_UNIQ_CODE = "uniq_code";
/** sys_role 表 code 唯一键索引 */
public static final String SQL_INDEX_UNIQ_SYS_ROLE_CODE = "uniq_sys_role_role_code";
/** sys_depart 表 code 唯一键索引 */
public static final String SQL_INDEX_UNIQ_DEPART_ORG_CODE = "uniq_depart_org_code";
/**
* 在线聊天 是否为默认分组
*/
public static final String IM_DEFAULT_GROUP = "1";
/**
* 在线聊天 图片文件保存路径
*/
public static final String IM_UPLOAD_CUSTOM_PATH = "imfile";
/**
* 在线聊天 用户状态
*/
public static final String IM_STATUS_ONLINE = "online";
/**
* 在线聊天 SOCKET消息类型
*/
public static final String IM_SOCKET_TYPE = "chatMessage";
/**
* 在线聊天 是否开启默认添加好友 1是 0否
*/
public static final String IM_DEFAULT_ADD_FRIEND = "1";
/**
* 在线聊天 用户好友缓存前缀
*/
public static final String IM_PREFIX_USER_FRIEND_CACHE = "sys:cache:im:im_prefix_user_friend_";
/**
* 考勤补卡业务状态 1同意 2不同意
*/
public static final String SIGN_PATCH_BIZ_STATUS_1 = "1";
public static final String SIGN_PATCH_BIZ_STATUS_2 = "2";
/**
* 公文文档上传自定义路径
*/
public static final String UPLOAD_CUSTOM_PATH_OFFICIAL = "officialdoc";
/**
* 公文文档下载自定义路径
*/
public static final String DOWNLOAD_CUSTOM_PATH_OFFICIAL = "officaldown";
/**
* WPS存储值类别(1 code文号 2 textWPS模板还是公文发文模板)
*/
public static final String WPS_TYPE_1="1";
public static final String WPS_TYPE_2="2";
public final static String X_ACCESS_TOKEN = "X-Access-Token";
/**
* 多租户 请求头
*/
public final static String TENANT_ID = "tenant-id";
/**
* 微服务读取配置文件属性 服务地址
*/
public final static String CLOUD_SERVER_KEY = "spring.cloud.nacos.discovery.server-addr";
/**
* 第三方登录 验证密码/创建用户 都需要设置一个操作码 防止被恶意调用
*/
public final static String THIRD_LOGIN_CODE = "third_login_code";
/**
* 第三方APP同步方向本地 --> 第三方APP
*/
String THIRD_SYNC_TO_APP = "SYNC_TO_APP";
/**
* 第三方APP同步方向第三方APP --> 本地
*/
String THIRD_SYNC_TO_LOCAL = "SYNC_TO_LOCAL";
/** 系统通告消息状态:0=未发布 */
String ANNOUNCEMENT_SEND_STATUS_0 = "0";
/** 系统通告消息状态:1=已发布 */
String ANNOUNCEMENT_SEND_STATUS_1 = "1";
/** 系统通告消息状态:2=已撤销 */
String ANNOUNCEMENT_SEND_STATUS_2 = "2";
}

66
src/main/java/com/zgx/iot/dto/site/DeveiceType.java

@ -0,0 +1,66 @@
package com.zgx.iot.dto.site;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* @Description: 设备类型表
* @Author: lxc
* @Date: 2023-08-17
* @Version: V1.0
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
public class DeveiceType implements Serializable {
private static final long serialVersionUID = 1L;
/**id*/
//(value = "id")
private String id;
/**类型编号*/
//(value = "类型编号")
private Integer typeNo;
/**类型名称*/
//(value = "类型名称")
private String typeName;
/**是否有传感器*/
//(value = "是否有传感器")
private Integer havesensor;
/**地图显示图片模型*/
//(value = "地图显示图片模型")
private String mapIco;
/**是否3D*/
//(value = "是否3D")
private Integer is3d;
/**默认宽度*/
//(value = "默认宽度")
private BigDecimal width;
/**默认长度*/
//(value = "默认长度")
private BigDecimal length;
/**默认高度*/
//(value = "默认高度")
private BigDecimal height;
//(value = "创建时间")
private Long realTime;
//(value = "操作类型:设备增加,1;设备删减,2;设备信息变更,3;")
private int operaType;
}

133
src/main/java/com/zgx/iot/dto/site/DeviceInfo.java

@ -0,0 +1,133 @@
package com.zgx.iot.dto.site;
import lombok.Data;
import java.io.Serializable;
/**
* @Description: 设备信息表
* @Author: jeecg-boot
* @Date: 2023-08-18
* @Version: V1.0
*/
@Data
@Deprecated
public class DeviceInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**设备唯一标识*/
//(value = "设备唯一标识")
private String id;
/**设备所属站点ID*/
private String deviceOwnerId;
/**设备类型*/
//(value = "设备类型")
private Integer deviceType;
/**设备编码*/
//(value = "设备编码")
private String deviceCode;
/**设备名称*/
//(value = "设备名称")
private String deviceName;
/**位置描述置*/
//(value = "位置描述置")
private String devicePosition;
/**设备经度*/
//(value = "设备经度")
private Double deviceLon;
/**设备纬度*/
//(value = "设备纬度")
private Double deviceLat;
/**设备海拔*/
//(value = "设备海拔")
private Double deviceAlt;
/**设备状态*/
//(value = "设备状态")
private Integer deviceStatus;
/**入网许可证*/
//(value = "入网许可证")
private Integer isAudit;
/**设备访问路径*/
//(value = "设备访问路径")
private String deviceUrl;
/**设备ip地址*/
//(value = "设备ip地址")
private String deviceIp;
/**端口*/
//(value = "端口")
private Integer ipPort;
/**端口2*/
//(value = "端口2")
private Integer ipPort2;
/**用户名*/
//(value = "用户名")
private String username;
/**密码*/
//(value = "密码")
private String password;
/**设备子类型*/
//(value = "设备子类型")
private Integer subtype;
/**安装高度*/
//(value = "安装高度")
private Integer deviceHeight;
/**初始方位角*/
//(value = "初始方位角")
private Integer initAzimuth;
/**初始俯仰角*/
//(value = "初始俯仰角")
private Integer initPitch;
/**工作半径*/
//(value = "工作半径")
private Integer workingRadius;
/**水平市场角度*/
//(value = "水平市场角度")
private Integer horizontalAngle;
/**锤子市场角度*/
//(value = "锤子市场角度")
private Integer verticalAngle;
/**识别刻度*/
//(value = "识别刻度")
private Integer identificationScale;
/**备注*/
//(value = "备注")
private String remark;
/**协议类型*/
//(value = "协议类型")
private Integer protocol;
//(value = "创建时间")
private Long realTime;
//(value = "操作类型:设备增加,1;设备删减,2;设备信息变更,3;")
private int operaType;
}

44
src/main/java/com/zgx/iot/dto/site/DeviceStatus.java

@ -0,0 +1,44 @@
package com.zgx.iot.dto.site;
import lombok.Data;
import java.io.Serializable;
/**
* @Description: 设备状态信息
* @Author: jeecg-boot
* @Date: 2023-08-18
* @Version: V1.0
*/
@Data
public class DeviceStatus implements Serializable {
private static final long serialVersionUID = 1L;
/**id*/
private String id;
/**设备唯一标识*/
//(value = "设备唯一标识")
private String deviceId;
/**设备所属站点ID*/
//(value = "设备所属站点ID")
private Integer deviceOwnerId;
/**设备初始状态*/
//(value = "设备初始状态")
private Integer status;
/**状态补充说明*/
//(value = "状态补充说明")
private String remark;
//(value = "创建时间")
private Long realTime;
//(value = "操作类型:设备增加,1;设备删减,2;设备信息变更,3;")
private int operaType;
}

159
src/main/java/com/zgx/iot/dto/site/Result.java

@ -0,0 +1,159 @@
package com.zgx.iot.dto.site;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import java.io.Serializable;
/**
* 接口返回数据格式
* @author scott
* @email jeecgos@163.com
* @date 2019年1月19日
*/
@Data
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 成功标志
*/
private boolean success = true;
/**
* 返回处理消息
*/
private String message = "操作成功!";
/**
* 返回代码
*/
private Integer code = 0;
/**
* 返回数据对象 data
*/
private T result;
/**
* 时间戳
*/
private long timestamp = System.currentTimeMillis();
public Result() {
}
public Result<T> success(String message) {
this.message = message;
this.code = CommonConstant.SC_OK_200;
this.success = true;
return this;
}
@Deprecated
public static Result<Object> ok() {
Result<Object> r = new Result<Object>();
r.setSuccess(true);
r.setCode(CommonConstant.SC_OK_200);
r.setMessage("成功");
return r;
}
@Deprecated
public static Result<Object> ok(String msg) {
Result<Object> r = new Result<>();
r.setSuccess(true);
r.setCode(CommonConstant.SC_OK_200);
r.setMessage(msg);
return r;
}
@Deprecated
public static Result<Object> ok(Object data) {
Result<Object> r = new Result<Object>();
r.setSuccess(true);
r.setCode(CommonConstant.SC_OK_200);
r.setResult(data);
return r;
}
public static<T> Result<T> OK() {
Result<T> r = new Result<T>();
r.setSuccess(true);
r.setCode(CommonConstant.SC_OK_200);
r.setMessage("成功");
return r;
}
public static<T> Result<T> OK(T data) {
Result<T> r = new Result<T>();
r.setSuccess(true);
r.setCode(CommonConstant.SC_OK_200);
r.setResult(data);
return r;
}
public static<T> Result<T> OK(String msg, T data) {
Result<T> r = new Result<T>();
r.setSuccess(true);
r.setCode(CommonConstant.SC_OK_200);
r.setMessage(msg);
r.setResult(data);
return r;
}
public static<T> Result<T> error(String msg, T data) {
Result<T> r = new Result<T>();
r.setSuccess(false);
r.setCode(CommonConstant.SC_INTERNAL_SERVER_ERROR_500);
r.setMessage(msg);
r.setResult(data);
return r;
}
public static<T> Result<T> ERROR(String msg) {
return ERROR(CommonConstant.SC_INTERNAL_SERVER_ERROR_500, msg);
}
public static<T> Result<T> ERROR(int code, String msg) {
Result<T> r = new Result<>();
r.setCode(code);
r.setMessage(msg);
r.setSuccess(false);
return r;
}
public static Result<Object> error(String msg) {
return error(CommonConstant.SC_INTERNAL_SERVER_ERROR_500, msg);
}
public static Result<Object> error(int code, String msg) {
Result<Object> r = new Result<>();
r.setCode(code);
r.setMessage(msg);
r.setSuccess(false);
return r;
}
public Result<T> error500(String message) {
this.message = message;
this.code = CommonConstant.SC_INTERNAL_SERVER_ERROR_500;
this.success = false;
return this;
}
/**
* 无权限访问返回结果
*/
public static Result<Object> noauth(String msg) {
return error(CommonConstant.SC_JEECG_NO_AUTHZ, msg);
}
@JsonIgnore
private String onlTable;
}

75
src/main/java/com/zgx/iot/dto/site/SysDictItem.java

@ -0,0 +1,75 @@
package com.zgx.iot.dto.site;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
*
* </p>
*
* @Author zhangweijian
* @since 2018-12-28
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class SysDictItem implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
private String id;
/**
* 字典id
*/
private String dictId;
/**
* 字典项文本
*/
private String itemText;
/**
* 字典项值
*/
private String itemValue;
/**
* 描述
*/
private String description;
/**
* 排序
*/
private Integer sortOrder;
/**
* 状态1启用 0不启用
*/
private Integer status;
private String createBy;
private Date createTime;
private String updateBy;
private Date updateTime;
}

195
src/main/java/com/zgx/iot/entity/DtDeviceInfo.java

@ -0,0 +1,195 @@
package com.zgx.iot.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* @Description: 设备信息表
* @Author: jeecg-boot
* @Date: 2022-08-12
* @Version: V1.0
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
public class DtDeviceInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 设备唯一标识
*/
private String id;
/**
* 设备所属站点ID
*/
private String deviceOwnerId;
/**
* 设备类型
*/
private Integer deviceType;
/**
* 设备编码
*/
private String deviceCode;
/**
* 设备名称
*/
private String deviceName;
/**
* 位置描述置
*/
private String devicePosition;
/**
* 设备经度
*/
private Double deviceLon;
/**
* 设备纬度
*/
private Double deviceLat;
/**
* 设备海拔
*/
private Double deviceAlt;
/**
* 设备状态
*/
private Integer deviceStatus;
/**
* 设备访问路径
*/
private String deviceUrl;
/**
* 设备ip地址
*/
private String deviceIp;
/**
* 端口
*/
private Integer ipPort;
/**
* 端口2
*/
private Integer ipPort2;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 设备子类型
*/
private Integer subtype;
/**
* 安装高度
*/
private Integer deviceHeight;
/**
* 初始方位角
*/
private Integer initAzimuth;
/**
* 初始俯仰角
*/
private Integer initPitch;
/**
* 工作半径
*/
private Integer workingRadius;
/**
* 水平市场角度
*/
private Integer horizontalAngle;
/**
* 锤子市场角度
*/
private Integer verticalAngle;
/**
* 识别刻度
*/
private Integer identificationScale;
/**
* 网络协议类型
*/
private String netProtocol;
/**
* 数据协议类型
*/
private String dataProtocol;
/**
* 备注
*/
private String remark;
/**
* 创建人
*/
private String createBy;
/**
* 创建时间
*/
private Date createTime;
/**
* 修改人
*/
private String updateBy;
/**
* 修改时间
*/
private Date updateTime;
/**
* 所属区域
*/
private String sysAreaCode;
/**
* 所属部门
*/
private String sysOrgCode;
/**
* 入网许可证
*/
private Integer isAudit;
/**
* 设备服务器类型
*/
private Integer serverType;
}

67
src/main/java/com/zgx/iot/entity/MsAlarmSettings.java

@ -0,0 +1,67 @@
package com.zgx.iot.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* @Description: 报警参数配置表
* @Author: jeecg-boot
* @Date: 2022-09-02
* @Version: V1.0
*/
@Data
public class MsAlarmSettings implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
private String id;
/**
* 创建人
*/
private String createBy;
/**
* 创建日期
*/
private Date createTime;
/**
* 更新人
*/
private String updateBy;
/**
* 更新日期
*/
private Date updateTime;
/**
* 所属部门
*/
private String sysOrgCode;
/**
* 航迹点有效时间
*/
private Integer lineEffectTime;
/**
* 报警区域有效时间
*/
private Integer alarmEffectTime;
/**
* 跟踪目标有效时间
*/
private Integer trackEffectTime;
/**
* 报警防区有效时间
*/
private Integer fenceEffectTime;
/**
* 围网外侧航迹点与内测点迹距离有效距离
*/
private Integer inOutEffectDistance;
/**
* 目标平均身高
*/
private Double targetHeight;
}

112
src/main/java/com/zgx/iot/entity/MsCameraSetting.java

@ -0,0 +1,112 @@
package com.zgx.iot.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* @Description: 相机设置
* @Author: jeecg-boot
* @Date: 2021-07-01
* @Version: V1.0
*/
//todo : 少了字段 1.厂家
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
public class MsCameraSetting implements Serializable {
private static final long serialVersionUID = 1L;
/**主键*/
private String id;
/**创建人*/
private String createBy;
/**创建日期*/
private Date createTime;
/**更新人*/
private String updateBy;
/**更新日期*/
private Date updateTime;
/**站点id*/
private String siteId;
/**相机ip*/
private String ip;
/**相机备用ip*/
private String ip2;
/**端口*/
private Integer port;
/**相机类型(厂家)*/
private Integer factory;
/**认证用户名*/
private String user;
/**认证密码*/
private String password;
/**相机预览通道*/
private Integer channel;
/**rtsp地址*/
private String preRtsp;
/**分析rtsp*/
private String analysisRtsp;
/**录像rtsp*/
private String recordRtsp;
//todo:补充字段 1.站点名称(siteName) 2.web播放地址(webcast_address) 3.相机编号(camera_code)
/**站点名称*/
private String siteName;
/**web播放地址*/
private String webcastAddress;
/**相机编号*/
private String cameraCode;
/**云台控制ip*/
private String cloudCtrlIp;
/**云台控制端口*/
private Integer cloudCtrlPort;
/**相机名称*/
private String cameraName;
/**纬度*/
private BigDecimal latitude;
/**经度*/
private BigDecimal longitude;
/**高度*/
private BigDecimal height;
/**类型*/
private Integer type;
/**样式*/
private Integer style;
/**左夹角*/
private Double leftAngle;
/**右夹角*/
private Double rightAngle;
/**视野中央有效距离*/
private Double viewDistance;
/**采样帧率*/
private Integer frameRate;
/**最大跟踪范围*/
private Integer maxRange;
/**状态*/
private Integer status;
/**零方位角(正北夹角)*/
private Double zeroAzimuth;
/**安装垂直角(上下-90°~90°)*/
private Double fixedAngle;
/**最大仰角*/
private Double maxElevation;
/**最大可视距离*/
private Double maxVisibleDistance;
/**变倍因子*/
private Double zoomFactor;
/**流媒体服务器id*/
private String streamingMediaId;
/**录像机id*/
private String videoRecorderId;
/**白光开始时间*/
private String dayBeginTime;
/**白光结束时间*/
private String dayEndTime;
/**报警次数*/
private Integer alarmNum;
}

50
src/main/java/com/zgx/iot/entity/MsModelPosition.java

@ -0,0 +1,50 @@
package com.zgx.iot.entity;
import lombok.Data;
import java.io.Serializable;
@Data
public class MsModelPosition implements Serializable {
private static final long serialVersionUID = 1L;
/**主键*/
private String id;
/**创建人*/
private String createBy;
/**创建日期*/
private java.util.Date createTime;
/**更新人*/
private String updateBy;
/**更新日期*/
private java.util.Date updateTime;
/**所属部门*/
private String sysOrgCode;
/**事件编号*/
private String eventSerialNum;
/**事件类型*/
private Integer eventType;
/**模型id*/
private String modelId;
/**模型类别*/
private Integer modelType;
/**经度*/
private java.math.BigDecimal lon;
/**纬度*/
private java.math.BigDecimal lat;
/**高度*/
private java.math.BigDecimal height;
/**偏航角*/
private java.math.BigDecimal yaw;
/**俯仰角*/
private java.math.BigDecimal pitch;
/**翻转角*/
private java.math.BigDecimal roll;
/**开始时间*/
private java.util.Date startTimestamp;
/**结束时间*/
private java.util.Date endTimestamp;
/**是否展示*/
private Integer isShow;
}

55
src/main/java/com/zgx/iot/entity/MsModelTrajectory.java

@ -0,0 +1,55 @@
package com.zgx.iot.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* @Description: 模型历史轨迹
* @Author: jeecg-boot
* @Date: 2021-07-09
* @Version: V1.0
*/
@Data
public class MsModelTrajectory implements Serializable {
private static final long serialVersionUID = 1L;
/**主键*/
private String id;
/**创建人*/
private String createBy;
/**创建日期*/
private Date createTime;
/**更新人*/
private String updateBy;
/**更新日期*/
private Date updateTime;
/**所属部门*/
private String sysOrgCode;
/**模型位置表id*/
private String modelPositionId;
/**经度*/
private java.math.BigDecimal lon;
/**纬度*/
private java.math.BigDecimal lat;
/**高度*/
private java.math.BigDecimal height;
/**偏航角*/
private java.math.BigDecimal yaw;
/**俯仰角*/
private java.math.BigDecimal pitch;
/**翻转角*/
private java.math.BigDecimal roll;
/**当前位置时间*/
private Date currPosTime;
}

16
src/main/java/com/zgx/iot/mapper/DtDeviceInfoMapper.java

@ -0,0 +1,16 @@
package com.zgx.iot.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zgx.iot.entity.DtDeviceInfo;
import org.apache.ibatis.annotations.Mapper;
/**
* @Description: 设备信息表
* @Author: jeecg-boot
* @Date: 2022-08-12
* @Version: V1.0
*/
@Mapper
public interface DtDeviceInfoMapper extends BaseMapper<DtDeviceInfo> {
}

18
src/main/java/com/zgx/iot/mapper/MsAlarmSettingsMapper.java

@ -0,0 +1,18 @@
package com.zgx.iot.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zgx.iot.entity.MsAlarmSettings;
import org.apache.ibatis.annotations.Mapper;
/**
* @Description: 报警参数配置表
* @Author: jeecg-boot
* @Date: 2022-09-02
* @Version: V1.0
*/
@Mapper
public interface MsAlarmSettingsMapper extends BaseMapper<MsAlarmSettings> {
}

29
src/main/java/com/zgx/iot/mapper/MsCameraSettingMapper.java

@ -0,0 +1,29 @@
package com.zgx.iot.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zgx.iot.entity.MsCameraSetting;
import io.lettuce.core.dynamic.annotation.Param;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @Description: 相机设置
* @Author: jeecg-boot
* @Date: 2021-07-01
* @Version: V1.0
*/
@Mapper
public interface MsCameraSettingMapper extends BaseMapper<MsCameraSetting> {
public boolean deleteByMainId(@Param("mainId") String mainId);
public List<MsCameraSetting> selectByMainId(@Param("mainId") String mainId);
public List<MsCameraSetting> selectAllSetting();
//public List<MsCameraSettingVo> selectSettingVoList();
//public void updateLatAndLonBySiteId(MsCameraSite msCameraSite);
}

17
src/main/java/com/zgx/iot/mapper/MsModelPositionMapper.java

@ -0,0 +1,17 @@
package com.zgx.iot.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zgx.iot.entity.MsModelPosition;
import org.apache.ibatis.annotations.Mapper;
/**
* @Description: 模型位置信息
* @Author: jeecg-boot
* @Date: 2021-07-09
* @Version: V1.0
*/
@Mapper
public interface MsModelPositionMapper extends BaseMapper<MsModelPosition> {
}

22
src/main/java/com/zgx/iot/mapper/MsModelTrajectoryMapper.java

@ -0,0 +1,22 @@
package com.zgx.iot.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zgx.iot.entity.MsModelTrajectory;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @Description: 模型历史轨迹
* @Author: jeecg-boot
* @Date: 2021-07-09
* @Version: V1.0
*/
@Mapper
public interface MsModelTrajectoryMapper extends BaseMapper<MsModelTrajectory> {
public boolean deleteByMainId(@Param("mainId") String mainId);
public List<MsModelTrajectory> selectByMainId(@Param("mainId") String mainId);
}

6
src/main/java/com/zgx/iot/mapper/xml/DtDeviceInfoMapper.xml

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zgx.iot.mapper.DtDeviceInfoMapper">
</mapper>

6
src/main/java/com/zgx/iot/mapper/xml/MsAlarmSettingsMapper.xml

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zgx.iot.mapper.MsAlarmSettingsMapper">
</mapper>

38
src/main/java/com/zgx/iot/mapper/xml/MsCameraSettingMapper.xml

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zgx.iot.mapper.MsCameraSettingMapper">
<delete id="deleteByMainId" parameterType="java.lang.String">
DELETE
FROM ms_camera_setting
WHERE
site_id = #{mainId}
</delete>
<select id="selectByMainId" parameterType="java.lang.String"
resultType="com.zgx.iot.entity.MsCameraSetting">
SELECT *
FROM ms_camera_setting
WHERE
site_id = #{mainId}
</select>
<select id="selectAllSetting" resultType="com.zgx.iot.entity.MsCameraSetting">
select id, site_id, camera_name
from ms_camera_setting
</select>
<!-- <select id="selectSettingVoList" resultType="com.zgx.modules.military.vo.MsCameraSettingVo">
select b.sitename,a.* from ms_camera_setting a LEFT JOIN ms_camera_site b ON a.site_id = b.id
</select>
<update id="updateLatAndLonBySiteId" parameterType="com.zgx.modules.military.entity.MsCameraSite">
update ms_camera_setting
<set>
&#45;&#45; noop
id = #{id},
<if test="latitude!= null">latitude=#{latitude},</if>
<if test="longitude!= null">longitude=#{longitude},</if>
</set>
where site_id=#{id}
</update>-->
</mapper>

5
src/main/java/com/zgx/iot/mapper/xml/MsModelPositionMapper.xml

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zgx.iot.mapper.MsModelPositionMapper">
</mapper>

16
src/main/java/com/zgx/iot/mapper/xml/MsModelTrajectoryMapper.xml

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zgx.iot.mapper.MsModelTrajectoryMapper">
<delete id="deleteByMainId" parameterType="java.lang.String">
DELETE
FROM ms_model_trajectory
WHERE
model_position_id = #{mainId} </delete>
<select id="selectByMainId" parameterType="java.lang.String" resultType="com.zgx.iot.entity.MsModelTrajectory">
SELECT *
FROM ms_model_trajectory
WHERE
model_position_id = #{mainId} </select>
</mapper>

165
src/main/java/com/zgx/iot/message/websocket/WebSocket.java

@ -0,0 +1,165 @@
package com.zgx.iot.message.websocket;
import com.alibaba.fastjson.JSONObject;
import com.zgx.iot.base.BaseMap;
import com.zgx.iot.constant.WebsocketConst;
import com.zgx.iot.redis.client.JeecgRedisClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* @Author scott
* @Date 2019/11/29 9:41
* @Description: 此注解相当于设置访问URL
*/
@Component
@Slf4j
@ServerEndpoint("/websocket/{userId}") //此注解相当于设置访问URL
public class WebSocket {
private Session session;
private String userId;
private static final String REDIS_TOPIC_NAME = "socketHandler";
@Resource
private JeecgRedisClient jeecgRedisClient;
@Value("${mqtt.orgCode}")
private String myOrgCode;
/**
* 缓存 webSocket连接到单机服务class中整体方案支持集群
*/
private static CopyOnWriteArraySet<WebSocket> webSockets = new CopyOnWriteArraySet<>();
private static Map<String, Session> sessionPool = new HashMap<String, Session>();
@OnOpen
public void onOpen(Session session, @PathParam(value = "userId") String userId) {
try {
this.session = session;
this.userId = userId;
webSockets.add(this);
sessionPool.put(userId, session);
log.info("【websocket消息】有新的连接,总数为:" + webSockets.size());
} catch (Exception e) {
}
}
@OnClose
public void onClose() {
try {
webSockets.remove(this);
sessionPool.remove(this.userId);
log.info("【websocket消息】连接断开,总数为:" + webSockets.size());
} catch (Exception e) {
}
}
/**
* 服务端推送消息
*
* @param userId
* @param message
*/
public void pushMessage(String userId, String message) {
Session session = sessionPool.get(userId);
if (session != null && session.isOpen()) {
try {
log.info("【websocket消息】 单点消息:" + message);
session.getAsyncRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 服务器端推送消息
*/
public void pushMessage(String message) {
webSockets.forEach(ws -> {
Session curSession = ws.session;
synchronized (curSession) {
if (curSession.isOpen()) {
try {
log.info("【websocket消息】广播消息:" + message);
curSession.getAsyncRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
}
@OnMessage
public void onMessage(String message) {
//todo 现在有个定时任务刷,应该去掉
log.debug("【websocket消息】收到客户端消息:" + message);
JSONObject obj = new JSONObject();
//业务类型
obj.put(WebsocketConst.MSG_CMD, WebsocketConst.CMD_CHECK);
//消息内容
obj.put(WebsocketConst.MSG_TXT, "心跳响应");
// 当前登录用户所属机构
obj.put("source", myOrgCode); // 信息来源
for (WebSocket webSocket : webSockets) {
webSocket.pushMessage(message);
}
}
/**
* 后台发送消息到redis
*
* @param message
*/
public void sendMessage(String message) {
log.info("【websocket消息】广播消息:" + message);
BaseMap baseMap = new BaseMap();
baseMap.put("userId", "");
baseMap.put("message", message);
jeecgRedisClient.sendMessage(REDIS_TOPIC_NAME, baseMap);
}
/**
* 此为单点消息
*
* @param userId
* @param message
*/
public void sendMessage(String userId, String message) {
BaseMap baseMap = new BaseMap();
baseMap.put("userId", userId);
baseMap.put("message", message);
jeecgRedisClient.sendMessage(REDIS_TOPIC_NAME, baseMap);
}
/**
* 此为单点消息(多人)
*
* @param userIds
* @param message
*/
public void sendMessage(String[] userIds, String message) {
for (String userId : userIds) {
sendMessage(userId, message);
}
}
}

102
src/main/java/com/zgx/iot/mq/mqtt/MessageCallback.java

@ -0,0 +1,102 @@
package com.zgx.iot.mq.mqtt;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zgx.iot.SystemApplication;
import com.zgx.iot.dto.radar.RadarTrackModel;
import com.zgx.iot.dto.radar.TrackingTargetDTO;
import com.zgx.iot.entity.MsCameraSetting;
import com.zgx.iot.mq.mqtt.handle.RadarHandler;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.regex.Pattern;
@Component
@Slf4j
public class MessageCallback implements MqttCallbackExtended {
/*
@Resource
RadarHandler radarHandler;
@Resource
MqttService mqttService;*/
// 定义正则表达式模式
/**
* 雷达跟踪目标信息
*/
private static final Pattern TRACK_TARGET_PATTERN = Pattern.compile("^/trackTarget$", Pattern.MULTILINE);
/**
* 球机雷达跟踪目标信息
*/
private static final Pattern CAMERA_TRACK_TARGET_PATTERN = Pattern.compile("^/cameraToTarget$", Pattern.MULTILINE);
/**
* 正北俯仰角校正
*/
private static final Pattern MODIFY_ANGLE = Pattern.compile("^/modifyAngle$", Pattern.MULTILINE);
@Override
public void connectionLost(Throwable arg0) {
// TODO 连接断开,可以做重连,目前重连失败,还没有设置
}
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
// TODO delivery 传送OK
}
@Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
log.info("【MQTT-客户端】接收消息主题 : " + topic);
log.info("【MQTT-客户端】接收消息Qos : " + message.getQos());
log.info("【MQTT-客户端】接收消息内容 : " + new String(message.getPayload(),"UTF-8"));
String messageStr = new String(message.getPayload(),"UTF-8");
// 通过正则表达式匹配主题
boolean matches = TRACK_TARGET_PATTERN.matcher(topic).matches();
boolean matches2= CAMERA_TRACK_TARGET_PATTERN.matcher(topic).matches();
boolean matches3= MODIFY_ANGLE.matcher(topic).matches();
RadarHandler radarHandler = SpringUtil.getBean(RadarHandler.class);
if (matches){
TrackingTargetDTO trackingTarget = JSON.parseObject(messageStr, TrackingTargetDTO.class);
radarHandler.targetHandler(trackingTarget);
}else if (matches2){
JSONObject jsonObject = JSON.parseObject(messageStr);
Float targetLon = jsonObject.getFloatValue("targetLon");
Float targetLat = jsonObject.getFloatValue("targetLat");
String cameraJsonString = (String) jsonObject.get("camera");
MsCameraSetting nearestCamera = JSON.parseObject(cameraJsonString, MsCameraSetting.class);
radarHandler.cameraToTarget(targetLon,targetLat,nearestCamera);
}else if (matches3){
JSONObject jsonObject = JSON.parseObject(messageStr);
Float targetLon = jsonObject.getFloatValue("longitude");
Float targetLat = jsonObject.getFloatValue("latitude");
String ip = (String) jsonObject.get("ip");
radarHandler.cameraToTarget2(targetLon,targetLat,ip);
}
}
@Override
public void connectComplete(boolean arg0, String arg1) {
// 连接成功后,重新订阅自己的主题
//MqttService.subscribe();
/* MqttService mqttService1 = SpringUtil.getBean(MqttService.class);
mqttService1.subscribe();*/
}
}

50
src/main/java/com/zgx/iot/mq/mqtt/MessageHandler.java

@ -0,0 +1,50 @@
package com.zgx.iot.mq.mqtt;
import com.alibaba.fastjson.JSON;
import com.zgx.iot.common.Cache;
import com.zgx.iot.dto.Brower2LpmDto;
import lombok.extern.slf4j.Slf4j;
import java.util.Date;
@Slf4j
public class MessageHandler implements Runnable {
private String message ;
private String topic ;
private byte[] msg ;
public MessageHandler(byte[] msg , String message,String topic){
this.message = message ;
this.topic = topic;
this.msg= msg;
log.debug("topic="+topic);
log.debug("message="+message);
}
@Override
public void run() {
try{
if(topic.contains("RadarData-3") ){
// 服务器发送命令
//Protocal.execServer(null,msg,message);
log.info("接收到雷达类型3数据,准备处理RadarData-3:"+message);
}else if(topic.contains("RadarData-1")){
log.info("接收到雷达类型1数据,准备处理RadarData-1:"+message);
/* // 透传命令 - 入库和更新时间
Brower2LpmDto browerDto = JSON.parseObject(message, Brower2LpmDto.class) ;
Integer messageType = browerDto.getMessageType() ;
String deviceCode = browerDto.getDeviceCode() ;
if( messageType == 1 ){
Cache.deviceMap.put( deviceCode , new Date().getTime()) ;
}else{
// 数据发送
}*/
}
}catch(Exception e){
log.error(e.getMessage());
}
}
}

166
src/main/java/com/zgx/iot/mq/mqtt/MqttService.java

@ -0,0 +1,166 @@
package com.zgx.iot.mq.mqtt;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.zgx.iot.common.Config;
import com.zgx.iot.config.mqtt.MQTTProps;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Data
@Component
@Slf4j
public class MqttService {
public MqttClient _client;
private MQTTProps _mqttProps;
/**
* 构造函数
* @throws MqttException
*/
public MqttService(MQTTProps mqttProps) throws MqttException {
// MemoryPersistence设置
_mqttProps=mqttProps;
System.out.println("siteid="+_mqttProps.getClient().getId());
System.out.println("HOST="+_mqttProps.getService().getAddress());
log.debug(JSON.toJSONString(mqttProps) );
_client = new MqttClient(_mqttProps.getService().getAddress(), _mqttProps.getClient().getId(), new MemoryPersistence());
}
/**
* 用来连接服务器
*/
public void connect() throws MqttException {
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(false);
options.setUserName(_mqttProps.getService().getUsername());
options.setPassword(_mqttProps.getService().getPassword().toCharArray());
// 设置超时时间
options.setConnectionTimeout(10000);
// 设置会话心跳时间
options.setKeepAliveInterval(2000);
// 重连
options.setAutomaticReconnect(true);
//options.setCleanSession(true);
try {
_client.setCallback(new MessageCallback());
_client.connect(options);
if (_client.isConnected()){
log.info("mqtt server connect success ;"+_client);
}
log.info("mqtt server connect fail");
} catch (Exception e) {
log.error("Error:" + e.getLocalizedMessage() +",请检查MQTT 代理是否正常启动!");
}
}
/**
* 重新连接
*/
public void reconnect() {
log.info("正在重新连接 MQTT 服务");
boolean isSuccess = false;
int retryCount = _mqttProps.getRetry().getCount();
long retryInterval = _mqttProps.getRetry().getInterval();
while (!isSuccess && retryCount > 0) {
try {
connect();
isSuccess = true;
} catch (Exception e) {
log.error("MQTT 服务 连接失败: {}", e.getMessage());
if (retryCount == 1) {
log.error("MQTT 服务 连接失败,停止重试");
// 跳过延迟
return;
}
try {
TimeUnit.SECONDS.sleep(retryInterval);
} catch (InterruptedException ex) {
log.error("MQTT 服务 尝试时连接时异常: {}", ex.getMessage());
Thread.currentThread().interrupt();
}
}
retryCount--;
}
}
public void subscribe(String[] topic1){
try{
// 订阅消息
int[] Qos = new int[topic1.length];
for(int i = 0; i< Qos.length ;i++ ){
Qos[i] =1 ;
}
_client.subscribe(topic1, Qos);
}catch (Exception e) {
log.error(e.getLocalizedMessage());
}
}
public void subscribe(){
try{
// 订阅消息
String[] topic1 =_mqttProps.getClient().getTopics().split(",");
int[] Qos = new int[topic1.length];
for(int i = 0; i< Qos.length ;i++ ){
Qos[i] =1 ;
}
_client.subscribe(topic1, Qos);
}catch (Exception e) {
log.error(e.getLocalizedMessage());
}
}
/**
* 消息发送
* @param message byte
* @param topic
*/
public void pubMessage(byte[] message,String topic){
MqttMessage mess = new MqttMessage();
mess.setQos(1);
mess.setRetained(false);
mess.setPayload(message);
try {
System.out.println("是否连接:"+_client.isConnected());
_client.publish(topic, mess);
} catch (Exception e) {
log.error(e.getLocalizedMessage());
}
}
/**
* 消息发送
* @param message
* @param topic
*/
public void pubMessage(String message,String topic){
MqttMessage mess = new MqttMessage();
mess.setQos(1);
mess.setRetained(false);
mess.setPayload(message.getBytes());
try {
_client.publish(topic, mess);
} catch (Exception e) {
log.error(e.getLocalizedMessage());
}
}
}

821
src/main/java/com/zgx/iot/mq/mqtt/handle/RadarHandler.java

@ -0,0 +1,821 @@
package com.zgx.iot.mq.mqtt.handle;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zgx.iot.MilitaryMqttApplication;
import com.zgx.iot.constant.enums.CameraType;
import com.zgx.iot.constant.enums.DeviceType;
import com.zgx.iot.dto.radar.RadarTrackModel;
import com.zgx.iot.dto.radar.TrackingTargetDTO;
import com.zgx.iot.entity.DtDeviceInfo;
import com.zgx.iot.entity.MsCameraSetting;
import com.zgx.iot.service.IDtDeviceInfoService;
import com.zgx.iot.service.IMsAlarmSettingsService;
import com.zgx.iot.service.IMsCameraSettingService;
import com.zgx.iot.service.impl.MsCameraSettingServiceImpl;
import com.zgx.iot.utils.GEOUtils;
import com.zgx.iot.utils.RedisUtil;
import com.zgx.iot.utils.hp.HPDataParser;
import com.zgx.iot.utils.hp.HPReqParamEnc;
import com.zgx.iot.utils.hp.ThreadManager;
import com.zgx.iot.utils.socket.TcpClient;
import com.zgx.iot.vo.PTZVo;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.fasterxml.jackson.databind.type.LogicalType.Map;
@Slf4j
@Component
public class RadarHandler {
@Autowired
RedisUtil redisUtil;
@Autowired
IDtDeviceInfoService msDeviceInfoService;
@Autowired
IMsCameraSettingService msCameraSettingService;
@Autowired
IMsAlarmSettingsService msAlarmSettingsService;
//发送轨迹数据主题
private final String trackDeviceInfoTopic = "/track/deviceInfo";
//发送球机数据主题
private final String trackCameraInfoTopic = "/track/cameraInfo";
//发送待删除的轨迹数据主题
private final String removeTrackIdsTopic = "/remove/trackIds";
public RadarHandler(IDtDeviceInfoService msDeviceInfoService, IMsCameraSettingService msCameraSettingService, IMsAlarmSettingsService msAlarmSettingsService, RedisUtil redisUtil) {
// 初使化时将已静态化的Service实例化
this.msDeviceInfoService = msDeviceInfoService;
this.msCameraSettingService = msCameraSettingService;
this.msAlarmSettingsService = msAlarmSettingsService;
this.redisUtil = redisUtil;
}
/* public void targetHandler(TrackingTargetDTO trackingTarget) throws UnsupportedEncodingException {
//获取目标id 和是否跟踪
String trackTargetId = String.valueOf(trackingTarget.getTrackId());
boolean trackStatus = trackingTarget.isTrackStatus();
String trackIdKey = "trackIds:" + trackTargetId;
//目标经纬度
float targetLon = Float.parseFloat(redisUtil.hget(trackIdKey, "targetLon").toString());
float targetLat = Float.parseFloat(redisUtil.hget(trackIdKey, "targetLat").toString());
//目标距离(基于雷达)
int distance = Integer.parseInt(redisUtil.hget(trackIdKey, "targetDis").toString());
log.info("目标经纬度:" + targetLon + "," + targetLat);
//查询光电信息
DtDeviceInfo cameraInfo = null;
LambdaQueryWrapper<DtDeviceInfo> photoelectricLambdaQueryWrapper = new LambdaQueryWrapper<>();
photoelectricLambdaQueryWrapper.eq(DtDeviceInfo::getDeviceType, DeviceType.PHOTOELECTRIC.getValue()) //光电类型
.eq(DtDeviceInfo::getDeviceStatus, 1);//1-启用状态
List<DtDeviceInfo> photoelectricDevices = msDeviceInfoService.list(photoelectricLambdaQueryWrapper);//查出所有光电
if (CollectionUtils.isEmpty(photoelectricDevices)) {
log.info("查询不到光电设备");
}
cameraInfo = photoelectricDevices.get(0);//todo : 是否需要计算最近的光电
log.info("光电设备信息:" + cameraInfo);
//1、若设备关联光电,则进行联动定位
if (cameraInfo != null) {
//根据IP获取对应光电线程
TcpClient tcpClient = ThreadManager.getTcpClientMap().get(cameraInfo.getDeviceIp());
//停止跟踪
if (!trackStatus) {
tcpClient.send(
HPDataParser.send(
HPReqParamEnc.ivpTrackingCtrl(String.valueOf(redisUtil.get(tcpClient.getIp())), 0, false, null)
)
);
return;
}
double cameraAzimuth = cameraInfo.getInitAzimuth() + Double.parseDouble(redisUtil.hget("PTZStatus", "pan").toString());
//计算目标基于光电的方位角
double targetAzimuth = GEOUtils.getAzimuth(cameraInfo.getDeviceLon(),
cameraInfo.getDeviceLat(),
targetLon,
targetLat
);
//计算光电水平所需方位角
double differAzimuth = targetAzimuth - cameraAzimuth;
//计算方位角
double horAngle = Double.parseDouble(redisUtil.hget("PTZStatus", "pan").toString()) + differAzimuth;
horAngle = horAngle >= 0 ? horAngle : (360 + horAngle);
//计算俯仰角(上27000-36000中间0-9000下)
double verAngle = Math.toDegrees(Math.asin((double) cameraInfo.getDeviceHeight() / distance));
verAngle = verAngle + cameraInfo.getInitPitch();
//停止跟踪
tcpClient.send(
HPDataParser.send(
HPReqParamEnc.ivpTrackingCtrl(String.valueOf(redisUtil.get(tcpClient.getIp())), 0, false, null)
)
);
//转动光电到指定位置
//当光电已经处于跟踪状态时,以下操作不会生效
//根据目标位置进行定位(角度实际上送值 : 100倍整数值)
tcpClient.send(
HPDataParser.send(
HPReqParamEnc.ptzControl(String.valueOf(redisUtil.get(tcpClient.getIp())),
0, 51, null,
null, null, 45,
(int) (horAngle * 100), (int) (verAngle * 100), null)
)
);
//目标高度 平均高度 在ms_alarm_settings表中设置 船的平均高度 高度越高视场角越大
double h = Double.parseDouble(redisUtil.hget("alarm_settings", "targetHeight").toString());
//计算目标距离光点的距离
double d = GEOUtils.GetDistance(targetLon, targetLat, cameraInfo.getDeviceLon(), cameraInfo.getDeviceLat());
//计算视场角,100为分辨率/像素
double fov = Math.toDegrees(Math.atan(h / d)) * 2 * 100;
log.info("目标平均高度:" + h + " 目标距离光电:" + d);
log.info("水平方位角:" + horAngle + " 俯仰角:" + verAngle + " 视场角:" + fov);
tcpClient.send(
HPDataParser.send(
HPReqParamEnc.ptzControl(String.valueOf(redisUtil.get(tcpClient.getIp())),
0, 42, null,
null, null, null,
null, null, (int) (fov * 100))
)
);
//球机联动
log.info("联动控制球机:");
LambdaQueryWrapper<MsCameraSetting> cameraSettingLambdaQueryWrapper = new LambdaQueryWrapper<>();
cameraSettingLambdaQueryWrapper.eq(MsCameraSetting::getType, 1)//1-球机类型
.eq(MsCameraSetting::getStatus, 0);//0-启用状态
List<MsCameraSetting> cameraSettings = msCameraSettingService.list(cameraSettingLambdaQueryWrapper);
if (CollectionUtils.isEmpty(cameraSettings)) {
log.info("没有可联动的球机");
}
MsCameraSetting msCameraSetting = getNearestCamera(cameraSettings, (double) targetLon, (double) targetLat);
//将光电信息封装成rtspUrl返回前端
String rtspUrl = getRtspUrl(cameraInfo.getDeviceIp(), cameraInfo.getUsername(), cameraInfo.getPassword(), 3);//光电
//String rtspUrlTest = "rtsp://admin:hk123456@192.168.1.71:554/";//光电
//String rtspUrl=getRtspUrl(msCameraSetting.getIp(), msCameraSetting.getUser(),msCameraSetting.getPassword(),msCameraSetting.getFactory());//球机
//相机数据发送mqtt给前端展示
JSONObject jsonObject1 = new JSONObject();
jsonObject1.put("longitude", cameraInfo.getDeviceLon());
jsonObject1.put("latitude", cameraInfo.getDeviceLat());
jsonObject1.put("deviceName", cameraInfo.getDeviceName());
jsonObject1.put("deviceStatus", cameraInfo.getDeviceStatus());
jsonObject1.put("deviceType", cameraInfo.getDeviceType());
jsonObject1.put("rtspUrl", rtspUrl);
//jsonObject1.put("rtspUrl", msCameraSetting.getPreRtsp());
//jsonObject1.put("rtspUrl", msCameraSetting.getAnalysisRtsp());
MilitaryMqttApplication.pubMessage(jsonObject1.toJSONString(), trackDeviceInfoTopic);
log.info("发送rtsp地址给前端----------" + "消息:" + jsonObject1.toJSONString() + " 主题:" + trackDeviceInfoTopic);
//控制球机照射目标
cameraToTarget(targetLon,targetLat,msCameraSetting);
log.info("跟踪球机的主要参数信息:");
log.info("1.IP: " + msCameraSetting.getIp());
log.info("2.用户名: " + msCameraSetting.getUser());
log.info("3.密码: " + msCameraSetting.getPassword());
log.info("4.最大俯仰角: " + msCameraSetting.getMaxElevation());
log.info("5.初始方位角: " + msCameraSetting.getZeroAzimuth());
log.info("6.品牌: " + (msCameraSetting.getFactory() == 1 ? "海康" : "宇视"));
//将需要跟踪的目标进行保存 并且保存跟踪该目标的球机IP
redisUtil.hset("trackingTargetId", trackTargetId, msCameraSetting.getIp());
log.info("正在跟踪的trackId:" + trackTargetId + "跟踪的球机" + msCameraSetting.getIp());
}
}*/
/* public void targetHandler(TrackingTargetDTO trackingTarget) throws UnsupportedEncodingException {
//获取目标id 和是否跟踪
String trackTargetId = String.valueOf(trackingTarget.getTrackId());
boolean trackStatus = trackingTarget.isTrackStatus();
String trackIdKey = "trackIds:" + trackTargetId;
//目标经纬度
float targetLon = Float.parseFloat(redisUtil.hget(trackIdKey, "targetLon").toString());
float targetLat = Float.parseFloat(redisUtil.hget(trackIdKey, "targetLat").toString());
//目标距离(基于雷达)
int distance = Integer.parseInt(redisUtil.hget(trackIdKey, "targetDis").toString());
log.info("目标经纬度:" + targetLon + "," + targetLat);
//查询光电信息
MsCameraSetting cameraInfo = null;
LambdaQueryWrapper<MsCameraSetting> photoelectricLambdaQueryWrapper = new LambdaQueryWrapper<>();
photoelectricLambdaQueryWrapper.eq(MsCameraSetting::getType, 3) //3-光电类型
.eq(MsCameraSetting::getStatus, 1);//1-启用状态
List<MsCameraSetting> photoelectricDevices = msCameraSettingService.list(photoelectricLambdaQueryWrapper);//查出所有光电
if (CollectionUtils.isEmpty(photoelectricDevices)) {
log.info("查询不到光电设备");
}
cameraInfo = photoelectricDevices.get(0);//todo : 是否需要计算最近的光电
log.info("光电设备信息:" + cameraInfo);
//1、若设备关联光电,则进行联动定位
if (cameraInfo != null) {
//根据IP获取对应光电线程
TcpClient tcpClient = ThreadManager.getTcpClientMap().get(cameraInfo.getIp());
//停止跟踪
if (!trackStatus) {
tcpClient.send(
HPDataParser.send(
HPReqParamEnc.ivpTrackingCtrl(String.valueOf(redisUtil.get(tcpClient.getIp())), 0, false, null)
)
);
return;
}
double cameraAzimuth = cameraInfo.getZeroAzimuth() + Double.parseDouble(redisUtil.hget("PTZStatus", "pan").toString());
//计算目标基于光电的方位角
double targetAzimuth = GEOUtils.getAzimuth(cameraInfo.getLongitude().doubleValue(),
cameraInfo.getLatitude().doubleValue(),
targetLon,
targetLat
);
//计算光电水平所需方位角
double differAzimuth = targetAzimuth - cameraAzimuth;
//计算方位角
double horAngle = Double.parseDouble(redisUtil.hget("PTZStatus", "pan").toString()) + differAzimuth;
horAngle = horAngle >= 0 ? horAngle : (360 + horAngle);
//计算俯仰角(上27000-36000中间0-9000下)
//double verAngle = Math.toDegrees(Math.asin((double) cameraInfo.getHeight() / distance));
double verAngle = Math.toDegrees(Math.asin((cameraInfo.getHeight().doubleValue() / distance)));
verAngle = verAngle + cameraInfo.getFixedAngle();
log.info("【停止跟踪】");
//停止跟踪
tcpClient.send(
HPDataParser.send(
HPReqParamEnc.ivpTrackingCtrl(String.valueOf(redisUtil.get(tcpClient.getIp())), 0, false, null)
)
);
//转动光电到指定位置
//当光电已经处于跟踪状态时,以下操作不会生效
//根据目标位置进行定位(角度实际上送值 : 100倍整数值)
log.info("【转动光电到指定位置】");
tcpClient.send(
HPDataParser.send(
HPReqParamEnc.ptzControl(String.valueOf(redisUtil.get(tcpClient.getIp())),
0, 51, null,
null, null, 45,
(int) (horAngle * 100), (int) (verAngle * 100), null)
)
);
//目标高度 平均高度 在ms_alarm_settings表中设置 船的平均高度 高度越高视场角越大
double h = Double.parseDouble(redisUtil.hget("alarm_settings", "targetHeight").toString());
//计算目标距离光点的距离
double d = GEOUtils.GetDistance(targetLon, targetLat, cameraInfo.getLongitude().doubleValue(), cameraInfo.getLatitude().doubleValue());
//计算视场角,100为分辨率/像素
double fov = Math.toDegrees(Math.atan(h / d)) * 2 * 100;
log.info("目标平均高度:" + h + " 目标距离光电:" + d);
log.info("水平方位角:" + horAngle + " 俯仰角:" + verAngle + " 视场角:" + fov);
log.info("【调整光电视场角】");
tcpClient.send(
HPDataParser.send(
HPReqParamEnc.ptzControl(String.valueOf(redisUtil.get(tcpClient.getIp())),
0, 42, null,
null, null, null,
null, null, (int) (fov * 100))
)
);
//球机联动
log.info("联动控制球机:");
LambdaQueryWrapper<MsCameraSetting> cameraSettingLambdaQueryWrapper = new LambdaQueryWrapper<>();
cameraSettingLambdaQueryWrapper.eq(MsCameraSetting::getType, 1)//1-球机类型
.eq(MsCameraSetting::getStatus, 1);//1-启用状态
List<MsCameraSetting> cameraSettings = msCameraSettingService.list(cameraSettingLambdaQueryWrapper);
if (CollectionUtils.isEmpty(cameraSettings)) {
log.info("没有可联动的球机");
}
log.info("case4 : 遍历相机列表 寻找最近的点的球机去跟踪");
// 计算距离最近的球机
MsCameraSetting msCameraSetting = null;//最近球机信息
double nearestDistance = 0;//最近距离
double heightDiff = 0;//最近球机的高度差
for (MsCameraSetting cameraSetting : cameraSettings) {
// 判断该球机是否满足照射范围 不满足的话还可以找第二近的球机 如果放到后面才判断高度差 就无法找第二近的去跟踪了
BigDecimal cameraHeight = cameraSetting.getHeight();//球机高度
BigDecimal labelHeight = new BigDecimal(h);//目标高度
double tempHeightDiff = cameraHeight.subtract(labelHeight).doubleValue();//球机与目标高度差
if (tempHeightDiff < 0) {
log.info("case4 :" + "ip=" + cameraSetting.getIp() + " tempHeightDiff < 0 超过球机照射范围");
} else {
double temp = GEOUtils.GetDistance(cameraSetting.getLongitude().doubleValue(), cameraSetting.getLatitude().doubleValue(), targetLon, targetLat);
log.info("当前的球机" + cameraSetting.getIp() + "与目标的距离:" + temp);
// 第一次 先将第一个球机的距离作为最近距离 和 最近球机信息
if (msCameraSetting == null) {
msCameraSetting = cameraSetting;
nearestDistance = temp;
continue;
}
// 第二次以后 如果距离更近则更新最近距离 以及 最近球机信息
if (nearestDistance > temp) {
msCameraSetting = cameraSetting;
nearestDistance = temp;
heightDiff = tempHeightDiff;
}
}
}
//没有找到跟踪的球机
if (msCameraSetting == null) {
log.info("没有可跟踪的球机");
}
//判断两点的距离是否超过有效距离,超过则丢掉
if (nearestDistance > Integer.parseInt(redisUtil.hget("alarm_settings", "inOutEffectDistance").toString())) {
log.info("case4 :" + "目标超过跟踪的最大距离" + redisUtil.hget("alarm_settings", "inOutEffectDistance").toString());
}
log.info("case4 :" + " 相机IP:" + msCameraSetting.getIp() + " 最短距离nearestDistance:" + nearestDistance);
log.info("case4 :" + "距离最近的相机:" + JSON.toJSONString(msCameraSetting));
//控制球机照射目标
log.info("case4【尝试使用ptzControllerByLatLonAndDistance】将球机转到目标位置");
//将光电信息封装成rtspUrl返回前端
String rtspUrl = getRtspUrl(cameraInfo.getIp(), cameraInfo.getUser(), cameraInfo.getPassword(), 3);//光电
//String rtspUrlTest = "rtsp://admin:hk123456@192.168.1.71:554/";//光电
//String rtspUrl=getRtspUrl(msCameraSetting.getIp(), msCameraSetting.getPort(), msCameraSetting.getUser(),msCameraSetting.getPassword(),msCameraSetting.getFactory());//球机
//轨迹数据发送mqtt给前端使用
JSONObject jsonObject1 = new JSONObject();
jsonObject1.put("longitude", cameraInfo.getLongitude());
jsonObject1.put("latitude", cameraInfo.getLatitude());
jsonObject1.put("deviceName", cameraInfo.getCameraName());
jsonObject1.put("deviceStatus", cameraInfo.getStatus());
jsonObject1.put("deviceType", cameraInfo.getType());
jsonObject1.put("rtspUrl", cameraInfo.getPreRtsp());
jsonObject1.put("videoUrl", cameraInfo.getVideoUrl());
//jsonObject1.put("rtspUrl", rtspUrlTest);
MilitaryMqttApplication.pubMessage(jsonObject1.toJSONString(), trackDeviceInfoTopic);
log.info("发送rtsp地址给前端----------" + "消息:" + jsonObject1.toJSONString() + " 主题:" + trackDeviceInfoTopic);
msCameraSettingService.ptzControllerByLatLon(msCameraSetting.getIp(),
msCameraSetting.getUser(),
msCameraSetting.getPassword(),
msCameraSetting.getMaxElevation(),
msCameraSetting.getZeroAzimuth(),
heightDiff,
msCameraSetting.getZoomFactor(),
msCameraSetting.getLongitude().doubleValue(),
msCameraSetting.getLatitude().doubleValue(),
targetLon,
targetLat,
msCameraSetting.getFactory());//factory用于区分品牌类型 1:海康 2:宇视
log.info("跟踪球机的主要参数信息:");
log.info("1.IP: " + msCameraSetting.getIp());
log.info("2.用户名: " + msCameraSetting.getUser());
log.info("3.密码: " + msCameraSetting.getPassword());
log.info("4.最大俯仰角: " + msCameraSetting.getMaxElevation());
log.info("5.初始方位角: " + msCameraSetting.getZeroAzimuth());
log.info("6.品牌: " + (msCameraSetting.getFactory() == 1 ? "海康" : "宇视"));
//将需要跟踪的目标进行保存 并且保存跟踪该目标的球机IP 跟踪有效时间设置为1h
redisUtil.hset("trackingTargetId", trackTargetId, msCameraSetting.getIp(), 60 * 5);
log.info("正在跟踪的trackId:" + trackTargetId + "跟踪的球机" + msCameraSetting.getIp());
}
}*/
/* public void targetHandler(TrackingTargetDTO trackingTarget) throws UnsupportedEncodingException{
angleTest();
}*/
public void targetHandler(TrackingTargetDTO trackingTarget) throws UnsupportedEncodingException {
//获取目标id 和是否跟踪
String trackTargetId = String.valueOf(trackingTarget.getTrackId());
boolean trackStatus = trackingTarget.isTrackStatus();
String trackIdKey = "trackIds:" + trackTargetId;
//目标经纬度
float targetLon = Float.parseFloat(redisUtil.hget(trackIdKey, "targetLon").toString());
float targetLat = Float.parseFloat(redisUtil.hget(trackIdKey, "targetLat").toString());
//目标距离(基于雷达)
int distance = Integer.parseInt(redisUtil.hget(trackIdKey, "targetDis").toString());
log.info("目标经纬度:" + targetLon + "," + targetLat);
//查询光电信息
MsCameraSetting cameraInfo = null;
LambdaQueryWrapper<MsCameraSetting> photoelectricLambdaQueryWrapper = new LambdaQueryWrapper<>();
photoelectricLambdaQueryWrapper.eq(MsCameraSetting::getType, CameraType.GUANGDIAN.getValue()); //3-光电类型
// .eq(MsCameraSetting::getStatus, 0);//0-启用状态
List<MsCameraSetting> photoelectricDevices = msCameraSettingService.list(photoelectricLambdaQueryWrapper);//查出所有光电
if (CollectionUtils.isEmpty(photoelectricDevices)) {
log.info("查询不到光电设备");
}
//获取目标最近的光电
cameraInfo = getNearestCamera(photoelectricDevices, (double) targetLon, (double) targetLat);
//cameraInfo = photoelectricDevices.get(0);//todo : 是否需要计算最近的光电
log.info("光电设备信息:" + cameraInfo);
//1、若设备关联光电,则进行联动定位
if (cameraInfo != null) {
//根据IP获取对应光电线程
TcpClient tcpClient = ThreadManager.getTcpClientMap().get(cameraInfo.getIp());
//停止跟踪
if (!trackStatus) {
tcpClient.send(
HPDataParser.send(
HPReqParamEnc.ivpTrackingCtrl(String.valueOf(redisUtil.get(tcpClient.getIp())), 0, false, null)
)
);
return;
}
double cameraAzimuth = cameraInfo.getZeroAzimuth() + Double.parseDouble(redisUtil.hget("PTZStatus", "pan").toString());
//计算目标基于光电的方位角
double targetAzimuth = GEOUtils.getAzimuth(cameraInfo.getLongitude().doubleValue(),
cameraInfo.getLatitude().doubleValue(),
targetLon,
targetLat
);
//计算光电水平所需方位角
double differAzimuth = targetAzimuth - cameraAzimuth;
//计算方位角
double horAngle = Double.parseDouble(redisUtil.hget("PTZStatus", "pan").toString()) + differAzimuth;
horAngle = horAngle >= 0 ? horAngle : (360 + horAngle);
//计算俯仰角(上27000-36000中间0-9000下)
//double verAngle = Math.toDegrees(Math.asin((double) cameraInfo.getHeight() / distance));
double verAngle = Math.toDegrees(Math.asin((cameraInfo.getHeight().doubleValue() / distance)));
verAngle = verAngle + cameraInfo.getFixedAngle();
log.info("【停止跟踪】");
//停止跟踪
tcpClient.send(
HPDataParser.send(
HPReqParamEnc.ivpTrackingCtrl(String.valueOf(redisUtil.get(tcpClient.getIp())), 0, false, null)
)
);
//转动光电到指定位置
//当光电已经处于跟踪状态时,以下操作不会生效
//根据目标位置进行定位(角度实际上送值 : 100倍整数值)
log.info("【转动光电到指定位置】");
tcpClient.send(
HPDataParser.send(
HPReqParamEnc.ptzControl(String.valueOf(redisUtil.get(tcpClient.getIp())),
0, 51, null,
null, null, 45,
(int) (horAngle * 100), (int) (verAngle * 100), null)
)
);
//目标高度 平均高度 在ms_alarm_settings表中设置 船的平均高度 高度越高视场角越大
double h = Double.parseDouble(redisUtil.hget("alarm_settings", "targetHeight").toString());
//计算目标距离光点的距离
double d = GEOUtils.GetDistance(targetLon, targetLat, cameraInfo.getLongitude().doubleValue(), cameraInfo.getLatitude().doubleValue());
//计算视场角,100为分辨率/像素
double fov = Math.toDegrees(Math.atan(h / d)) * 2 * 100;
log.info("目标平均高度:" + h + " 目标距离光电:" + d);
log.info("水平方位角:" + horAngle + " 俯仰角:" + verAngle + " 视场角:" + fov);
log.info("【调整光电视场角】");
tcpClient.send(
HPDataParser.send(
HPReqParamEnc.ptzControl(String.valueOf(redisUtil.get(tcpClient.getIp())),
0, 42, null,
null, null, null,
null, null, (int) (fov * 100))
)
);
//将光电信息返回前端
JSONObject jsonObject1 = new JSONObject();
jsonObject1.put("longitude", cameraInfo.getLongitude());
jsonObject1.put("latitude", cameraInfo.getLatitude());
jsonObject1.put("deviceName", cameraInfo.getCameraName());
jsonObject1.put("deviceStatus", cameraInfo.getStatus());
jsonObject1.put("deviceType", cameraInfo.getType());
jsonObject1.put("deviceId", cameraInfo.getId());
jsonObject1.put("rtspUrl", cameraInfo.getPreRtsp());
jsonObject1.put("rtcUrl", cameraInfo.getWebcastAddress());
MilitaryMqttApplication.pubMessage(jsonObject1.toJSONString(), trackDeviceInfoTopic);
log.info("发送rtsp地址给前端----------" + "消息:" + jsonObject1.toJSONString() + " 主题:" + trackDeviceInfoTopic);
//球机联动
log.info("联动控制球机:");
LambdaQueryWrapper<MsCameraSetting> cameraSettingLambdaQueryWrapper = new LambdaQueryWrapper<>();
cameraSettingLambdaQueryWrapper.eq(MsCameraSetting::getType, CameraType.QIUJI.getValue())//1-球机类型
.eq(MsCameraSetting::getStatus, 0);//启用状态
List<MsCameraSetting> cameraSettings = msCameraSettingService.list(cameraSettingLambdaQueryWrapper);
if (CollectionUtils.isEmpty(cameraSettings)) {
log.info("没有可联动的球机");
return;
}
// 计算距离最近的球机
MsCameraSetting msCameraSetting = null;//最近球机信息
double nearestDistance = 0;//最近距离
double heightDiff = 0;//最近球机的高度差
for (MsCameraSetting cameraSetting : cameraSettings) {
// 判断该球机是否满足照射范围 不满足的话还可以找第二近的球机 如果放到后面才判断高度差 就无法找第二近的去跟踪了
BigDecimal cameraHeight = cameraSetting.getHeight();//球机高度
BigDecimal labelHeight = new BigDecimal(h);//目标高度
double tempHeightDiff = cameraHeight.subtract(labelHeight).doubleValue();//球机与目标高度差
if (tempHeightDiff < 0) {
log.info("case4 :" + "ip=" + cameraSetting.getIp() + " tempHeightDiff < 0 超过球机照射范围");
} else {
double temp = GEOUtils.GetDistance(cameraSetting.getLongitude().doubleValue(), cameraSetting.getLatitude().doubleValue(), targetLon, targetLat);
log.info("当前的球机" + cameraSetting.getIp() + "与目标的距离:" + temp);
// 第一次 先将第一个球机的距离作为最近距离 和 最近球机信息
if (msCameraSetting == null) {
msCameraSetting = cameraSetting;
nearestDistance = temp;
continue;
}
// 第二次以后 如果距离更近则更新最近距离 以及 最近球机信息
if (nearestDistance > temp) {
msCameraSetting = cameraSetting;
nearestDistance = temp;
heightDiff = tempHeightDiff;
}
}
}
//没有找到跟踪的球机
if (msCameraSetting == null) {
log.info("没有可跟踪的球机");
return;
}
//判断两点的距离是否超过有效距离,超过则丢掉
if (nearestDistance > Integer.parseInt(redisUtil.hget("alarm_settings", "inOutEffectDistance").toString())) {
log.info("case4 :" + "目标超过跟踪的最大距离" + redisUtil.hget("alarm_settings", "inOutEffectDistance").toString());
}
//将球机信息返回前端
JSONObject jsonObject2 = new JSONObject();
jsonObject2.put("deviceId", msCameraSetting.getId());
jsonObject2.put("rtspUrl", msCameraSetting.getPreRtsp());
jsonObject2.put("rtcUrl", msCameraSetting.getWebcastAddress());
MilitaryMqttApplication.pubMessage(jsonObject2.toJSONString(), trackCameraInfoTopic);
log.info("发送联动跟踪的球机rtsp地址给前端----------" + "消息:" + jsonObject2.toJSONString() + " 主题:/track/cameraInfo");
msCameraSettingService.ptzControllerByLatLon(msCameraSetting.getIp(),
msCameraSetting.getUser(),
msCameraSetting.getPassword(),
msCameraSetting.getMaxElevation(),
msCameraSetting.getZeroAzimuth(),
heightDiff,
msCameraSetting.getZoomFactor(),
msCameraSetting.getLongitude().doubleValue(),
msCameraSetting.getLatitude().doubleValue(),
targetLon,
targetLat,
msCameraSetting.getFactory());//factory用于区分品牌类型 1:海康 3:宇视
//将需要跟踪的目标进行保存 并且保存跟踪该目标的球机IP 跟踪有效时间设置为1h
//redisUtil.hset("trackingTargetId", trackTargetId, msCameraSetting.getIp(), 60 * 5);
redisUtil.set("trackingCameraIp",msCameraSetting.getIp(),60 * 5);
redisUtil.set("trackingId",trackTargetId,60 * 5);
log.info("正在跟踪的trackId:" + trackTargetId + "跟踪的球机" + msCameraSetting.getIp());
}
}
/**
* 相机转动到指定位置
* @param targetLon
* @param targetLat
* @param msCameraSetting
*/
public void cameraToTarget(Float targetLon,Float targetLat,MsCameraSetting msCameraSetting){
BigDecimal cameraHeight = msCameraSetting.getHeight();//球机高度
double h = Double.parseDouble(redisUtil.hget("alarm_settings", "targetHeight").toString());
BigDecimal labelHeight = new BigDecimal(h);//目标高度
double heightDiff = cameraHeight.subtract(labelHeight).doubleValue();//球机与目标高度差
msCameraSettingService.ptzControllerByLatLon(msCameraSetting.getIp(),
msCameraSetting.getUser(),
msCameraSetting.getPassword(),
msCameraSetting.getMaxElevation(),
msCameraSetting.getZeroAzimuth(),
heightDiff,
msCameraSetting.getZoomFactor(),
msCameraSetting.getLongitude().doubleValue(),
msCameraSetting.getLatitude().doubleValue(),
targetLon,
targetLat,
msCameraSetting.getFactory());//factory用于区分品牌类型 1:海康 2:宇视
}
/**
* 相机转动到指定位置
* @param targetLon
* @param targetLat
* @param ip
*/
public void cameraToTarget2(Float targetLon,Float targetLat,String ip){
LambdaQueryWrapper<MsCameraSetting> queryWrapper = new LambdaQueryWrapper<MsCameraSetting>().eq(MsCameraSetting::getIp, ip);
MsCameraSetting msCameraSetting = msCameraSettingService.getOne(queryWrapper);
BigDecimal cameraHeight = msCameraSetting.getHeight();//球机高度
double h = Double.parseDouble(redisUtil.hget("alarm_settings", "targetHeight").toString());
BigDecimal labelHeight = new BigDecimal(h);//目标高度
double heightDiff = cameraHeight.subtract(labelHeight).doubleValue();//球机与目标高度差
msCameraSettingService.ptzControllerByLatLon(msCameraSetting.getIp(),
msCameraSetting.getUser(),
msCameraSetting.getPassword(),
msCameraSetting.getMaxElevation(),
msCameraSetting.getZeroAzimuth(),
heightDiff,
msCameraSetting.getZoomFactor(),
msCameraSetting.getLongitude().doubleValue(),
msCameraSetting.getLatitude().doubleValue(),
targetLon,
targetLat,
msCameraSetting.getFactory());//factory用于区分品牌类型 1:海康 2:宇视
}
/**
* 生成rtsp
* @param ip
* @param user
* @param password
* @param factory 品牌产商
* @return
*/
private static String getRtspUrl(String ip, String user, String password, Integer factory) {
String rtspUrl = null;
switch (factory) {
//海康
case 1: {
rtspUrl = String.format("rtsp://%s:%s@%s/Streaming/Channels/1?transportmode=unicast&profile=Profile_1", user, password, ip);
break;
}
//宇视
case 2: {
rtspUrl = String.format("rtsp://%s:%s@%s/media/video1", user, password, ip);
break;
}
//光电
case 3: {
rtspUrl = String.format("rtsp://%s:%s@%s/h264/ch1/main/av_stream", user, password, ip);
break;
}
}
return rtspUrl;
}
/**
* 定时清除多次未更新的轨迹数据 任务
*/
@Scheduled(cron="0 0/1 * * * ?")
public void scheduledCleanTask(){
System.out.println("定时清除旧轨迹任务执行...");
long now = System.currentTimeMillis() - 60000;//定义多久以前的数据是需要清除的轨迹
System.out.println(now);
//得到待删除轨迹的Id
Set<ZSetOperations.TypedTuple<Object>> removeIds = redisUtil.zRangeByScoreWithScores("updatedIds", 0, now);
List<Integer> removeIdList = removeIds.stream().map(key -> Integer.valueOf(key.getValue().toString())).collect(Collectors.toList());
JSONObject jsonObject = new JSONObject();
jsonObject.put("removeIds",removeIdList);
MilitaryMqttApplication.pubMessage(jsonObject.toJSONString(),removeTrackIdsTopic);
//删除过期的轨迹Id
redisUtil.zRemoveRangeByScore("updatedIds",0,now);
}
public MsCameraSetting getNearestCamera(List<MsCameraSetting> cameraSettings,Double targetLon,Double targetLat) {
// 计算距离最近的球机
MsCameraSetting msCameraSetting = null;//最近球机信息
double nearestDistance = 0;//最近距离
for (MsCameraSetting cameraSetting : cameraSettings) {
double temp = GEOUtils.GetDistance(cameraSetting.getLongitude().doubleValue(), cameraSetting.getLatitude().doubleValue(), targetLon, targetLat);
// 第一次 先将第一个球机的距离作为最近距离 和 最近球机信息
if (msCameraSetting == null) {
msCameraSetting = cameraSetting;
nearestDistance = temp;
continue;
}
// 第二次以后 如果距离更近则更新最近距离 以及 最近球机信息
if (nearestDistance > temp) {
msCameraSetting = cameraSetting;
nearestDistance = temp;
}
}
return msCameraSetting;
}
public static void main(String[] args) {
RedisUtil redisUtil1 = SpringUtil.getBean(RedisUtil.class);
Object o = redisUtil1.get("allIds:");
}
//用于本地测试 模拟光电
public void test(){
MsCameraSettingServiceImpl mscameraSettingService = new MsCameraSettingServiceImpl();
mscameraSettingService.ptzControl(
"192.168.1.71",
"admin",
"hk123456",
new PTZVo(0.5,-0.5,0.5)
);
}
//todo : 正北调整(2024-4-10)
public void angleTest() {
LambdaQueryWrapper<MsCameraSetting> msCameraSettingLambdaQueryWrapper = new LambdaQueryWrapper<>();
msCameraSettingLambdaQueryWrapper.eq(MsCameraSetting::getType, CameraType.QIUJI.getValue())//1-球机类型
.eq(MsCameraSetting::getStatus, 0);//启用状态
List<MsCameraSetting> msCameraSettingList = msCameraSettingService.list(msCameraSettingLambdaQueryWrapper);
/* double targetLon=113.45166600000000;
double targetLat=22.12888800000000; */
double targetLon=113.43722200000000;
double targetLat=22.15888800000000;
for (MsCameraSetting msCameraSetting : msCameraSettingList) {
try {
msCameraSettingService.ptzControllerByLatLon(msCameraSetting.getIp(),
msCameraSetting.getUser(),
msCameraSetting.getPassword(),
msCameraSetting.getMaxElevation(),
msCameraSetting.getZeroAzimuth(),
msCameraSetting.getHeight().doubleValue(),
msCameraSetting.getZoomFactor(),
msCameraSetting.getLongitude().doubleValue(),
msCameraSetting.getLatitude().doubleValue(),
targetLon,
targetLat,
msCameraSetting.getFactory());//factory用于区分品牌类型 1:海康 2:宇视
}catch (Exception e){
System.out.println("异常相机:"+msCameraSetting.getIp());
log.info("异常相机");
log.info(msCameraSetting.getIp());
}
}
}
}

20
src/main/java/com/zgx/iot/mq/mqtt/model/radar/TargetMessage.java

@ -0,0 +1,20 @@
package com.zgx.iot.mq.mqtt.model.radar;
import com.zgx.iot.dto.radar.TrackingTargetDTO;
import lombok.Data;
/**
* @author AaGMixW
*/
@Data
public class TargetMessage {
/**
* mqtt 消息体
*/
private TrackingTargetDTO messageBody;
/**
* mqtt 主题
*/
private String topic;
}

203
src/main/java/com/zgx/iot/netty/NettyServiceManage.java

@ -0,0 +1,203 @@
package com.zgx.iot.netty;
import com.zgx.iot.dto.site.Result;
import com.zgx.iot.netty.exception.NettyServiceControllerException;
import com.zgx.iot.netty.model.NettyDeviceInfo;
import com.zgx.iot.netty.model.NettyService;
import com.zgx.iot.netty.pipeline.TcpPipelineFactory;
import com.zgx.iot.netty.pipeline.UdpPipelineFactory;
import com.zgx.iot.netty.socket.base.NettyBaseServiceImpl;
import com.zgx.iot.netty.socket.base.NettyBaseSocket;
import com.zgx.iot.netty.socket.tcp.TcpClientByNetty;
import com.zgx.iot.netty.socket.tcp.TcpServiceByNetty;
import com.zgx.iot.netty.socket.udp.UdpClientByNetty;
import com.zgx.iot.netty.socket.udp.UdpServiceByNetty;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;
import java.net.InetSocketAddress;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author AaGMixW
*/
@Component
public class NettyServiceManage {
private static final Logger logger = LogManager.getLogger(NettyServiceManage.class);
private final ConcurrentHashMap<String, NettyService<? extends NettyBaseSocket>> nettyServiceMap = new ConcurrentHashMap<>(16);
// 启动服务
/**
* 启动 tcp 服务端
*
* @param deviceInfo 设备信息 {@link NettyDeviceInfo}
* @param pipelineFactoryType tcp 管道, 对传输的数据进行相关处理
* @return udp service
*/
public NettyService<? extends NettyBaseSocket> startupTcpService(
NettyDeviceInfo deviceInfo,
Class<? extends TcpPipelineFactory<TcpServiceByNetty>> pipelineFactoryType
) {
String key = deviceInfo.getId();
// 判断 已经启动服务中是否已经存在
if (nettyServiceMap.containsKey(key)) {
// 存在
// 直接返回获取到的服务
return nettyServiceMap.get(key);
}
// 不存在
TcpServiceByNetty service = new TcpServiceByNetty(deviceInfo, pipelineFactoryType);
try {
service.startup();
// 存储到 nettyServiceMap 里
NettyService<TcpServiceByNetty> nettyService = new NettyService<>(service);
nettyServiceMap.put(key, nettyService);
return nettyService;
} catch (InstantiationException | IllegalAccessException e) {
logger.error("启动 {} 服务失败,{}", deviceInfo.getDeviceName(), e.getMessage());
service.shutdown();
return null;
}
}
/**
* 启动 tcp 客户端
*
* @param deviceInfo 设备信息 {@link NettyDeviceInfo}
* @param pipelineFactoryType tcp 管道, 对传输的数据进行相关处理
* @return udp service
*/
public <T> TcpClientByNetty startupTcpClient(
NettyDeviceInfo deviceInfo,
Class<? extends TcpPipelineFactory<TcpClientByNetty>> pipelineFactoryType
) {
String key = deviceInfo.getId();
// 判断 已经启动服务中是否已经存在
if (nettyServiceMap.containsKey(key)) {
// 存在
// 直接返回获取到的服务
return (TcpClientByNetty) nettyServiceMap.get(key).getService();
}
// 不存在
TcpClientByNetty client = new TcpClientByNetty(deviceInfo, pipelineFactoryType);
try {
client.startup();
// 存储到 nettyServiceMap 里
NettyService<TcpClientByNetty> nettyService = new NettyService<>(client);
nettyServiceMap.put(key, nettyService);
return client;
} catch (InstantiationException | IllegalAccessException e) {
client.shutdown();
logger.error("启动 {} 服务失败,{}", deviceInfo.getDeviceName(), e.getMessage());
return null;
}
}
/**
* 启动 udp 客户端
*
* @param deviceInfo 设备信息 {@link NettyDeviceInfo}
* @param pipelineFactoryType udp 管道, 对传输的数据进行相关处理
* @return udp client
*/
public synchronized NettyService<? extends NettyBaseSocket> startupUdpClient(NettyDeviceInfo deviceInfo, Class<? extends UdpPipelineFactory<UdpClientByNetty>> pipelineFactoryType) {
String key = deviceInfo.getId();
// 判断 已经启动服务中是否已经存在
if (nettyServiceMap.containsKey(key)) {
// 存在
// 直接返回获取到的服务
return nettyServiceMap.get(key);
}
// 不存在
UdpClientByNetty client = new UdpClientByNetty(deviceInfo, pipelineFactoryType);
try {
// 启动服务
client.startup();
// 存储到 nettyServiceMap 里
NettyService<UdpClientByNetty> nettyService = new NettyService<>(client);
nettyServiceMap.put(key, nettyService);
return nettyService;
} catch (InstantiationException | IllegalAccessException e) {
logger.error("启动 {} 服务失败,{}", deviceInfo.getDeviceName(), e.getMessage());
client.shutdown();
return null;
}
}
/**
* 启动 udp 服务端
*
* @param deviceInfo 设备信息 {@link NettyDeviceInfo}
* @param pipelineFactoryType udp 管道, 对传输的数据进行相关处理
* @return udp service
*/
public NettyService<? extends NettyBaseSocket> startupUdpService(
NettyDeviceInfo deviceInfo,
Class<? extends UdpPipelineFactory<UdpServiceByNetty>> pipelineFactoryType
) {
String key = deviceInfo.getId();
// 判断 已经启动服务中是否已经存在
if (nettyServiceMap.containsKey(key)) {
// 存在
// 直接返回获取到的服务
return nettyServiceMap.get(key);
}
// 不存在
UdpServiceByNetty service = new UdpServiceByNetty(pipelineFactoryType, deviceInfo);
try {
// 启动服务
service.startup();
// 存储到 nettyServiceMap 里
NettyService<UdpServiceByNetty> nettyService = new NettyService<>(service);
nettyServiceMap.put(key, nettyService);
return nettyService;
} catch (InstantiationException | IllegalAccessException e) {
service.shutdown();
logger.error("启动 {} 服务失败,{}", deviceInfo.getDeviceName(), e.getMessage());
throw new NettyServiceControllerException("启动服务失败:" + e.getMessage());
}
}
/**
* 停止服务
*
* @param deviceInfo 设备信息 {@link NettyDeviceInfo}
* @return 是否成功
*/
public boolean stopService(NettyDeviceInfo deviceInfo) {
String key = deviceInfo.getId();
if (nettyServiceMap.containsKey(key)) {
NettyService<? extends NettyBaseSocket> nettyService = nettyServiceMap.get(key);
nettyService.shutdown();
}
// 服务不存在 失败
return false;
}
public boolean stopChannel(String key, InetSocketAddress address) {
if (nettyServiceMap.containsKey(key)) {
NettyService<? extends NettyBaseSocket> nettyService = nettyServiceMap.get(key);
return nettyService.stopChannel(address);
} else {
logger.error("找不到 netty service!");
return false;
}
}
public Result<NettyService<? extends NettyBaseSocket>> getNettyService(NettyDeviceInfo deviceInfo) {
String key = deviceInfo.getId();
if (nettyServiceMap.containsKey(key)) {
return Result.OK(nettyServiceMap.get(key));
} else {
logger.error("找不到 netty service!");
return Result.ERROR("找不到 netty service!");
}
}
}

42
src/main/java/com/zgx/iot/netty/config/AppServiceConfig.java

@ -0,0 +1,42 @@
package com.zgx.iot.netty.config;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @author AaGMixW
*/
@Component
@Getter
@Setter
public class AppServiceConfig {
/**
* 服务重试设置
*/
@Value("${netty.retry.interval}")
private Integer retryInterval;
@Value("${netty.retry.count}")
private Integer retryCount;
/**
* 请求设备重试设置
*/
@Value("${netty.device.retry.interval}")
private Integer deviceRetryInterval;
@Value("${netty.device.retry.count}")
private Integer deviceRetryCount;
/**
* 心跳包 间隔
*/
@Value("${netty.heartbeat.interval}")
private Integer heartbeatInterval;
/**
* 心跳包 重试次数()
*/
@Value("${netty.heartbeat.count}")
private Integer heartbeatCount;
}

20
src/main/java/com/zgx/iot/netty/constant/AttributeMapConstant.java

@ -0,0 +1,20 @@
package com.zgx.iot.netty.constant;
import com.zgx.iot.netty.socket.base.NettyBaseSocket;
import io.netty.util.AttributeKey;
import java.net.InetSocketAddress;
/**
* @author AaGMixW
*/
public class AttributeMapConstant {
private AttributeMapConstant() {
throw new IllegalStateException("Constant class");
}
public static final AttributeKey<NettyBaseSocket> NETTY_CHANNEL_SOCKET_KEY =
AttributeKey.valueOf("netty.channel.socket");
public static final AttributeKey<InetSocketAddress> NETTY_SERVICE_REMOTE_ADDR_KEY =
AttributeKey.valueOf("netty.service.remote.addr");
}

21
src/main/java/com/zgx/iot/netty/constant/CustomLogLevel.java

@ -0,0 +1,21 @@
package com.zgx.iot.netty.constant;
import org.apache.logging.log4j.Level;
/**
* @author AaGMixW
*/
public class CustomLogLevel {
private CustomLogLevel() {
throw new IllegalStateException("Constant class");
}
//定义业务操作日志级别(级别越高,数字越小)
// off 0, fatal 100, error 200, warn 300, info 400, debug 500
/**
* 设备数据 日志
*/
public static final Level DEVICE_DATA_LEVEL = Level.forName("DEVICE_DATA", 350);
}

150
src/main/java/com/zgx/iot/netty/constant/DeviceRelations.java

@ -0,0 +1,150 @@
package com.zgx.iot.netty.constant;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import java.util.*;
/**
* @author AaGMixW
*/
public enum DeviceRelations {
;
private static final Map<Integer, String> ALARM_TYPE = new HashMap<>();
static {
ALARM_TYPE.put(2, "断线报警");
ALARM_TYPE.put(3, "触网报警");
ALARM_TYPE.put(4, "短路报警");
ALARM_TYPE.put(5, "接近预警");
ALARM_TYPE.put(6, "入侵报警");
ALARM_TYPE.put(7, "感应报警");
ALARM_TYPE.put(8, "离线报警");
ALARM_TYPE.put(9, "离线报警恢复");
}
private static final BiMap<Integer, String> DEVICE_TYPE = HashBiMap.create();
static {
DEVICE_TYPE.put(1, "radar");
DEVICE_TYPE.put(2, "camera");
DEVICE_TYPE.put(3, "fence");
DEVICE_TYPE.put(4, "photovoltaics");
DEVICE_TYPE.put(98, "relay");
DEVICE_TYPE.put(99, "other");
}
private static final BiMap<Integer, String> DEVICE_TYPE_CHINESE = HashBiMap.create();
static {
DEVICE_TYPE_CHINESE.put(1, "雷达");
DEVICE_TYPE_CHINESE.put(2, "光电");
DEVICE_TYPE_CHINESE.put(3, "电子围网");
DEVICE_TYPE_CHINESE.put(4, "光伏");
DEVICE_TYPE_CHINESE.put(98, "网络继电器");
DEVICE_TYPE_CHINESE.put(99, "其他");
}
private static final BiMap<Integer, String> DEVICE_COMP = HashBiMap.create();
static {
DEVICE_COMP.put(1, "lei_yuan");
DEVICE_COMP.put(2, "sine");
DEVICE_COMP.put(3, "zhi_an");
DEVICE_COMP.put(4, "he_pu");
DEVICE_COMP.put(5, "shang_shang");
DEVICE_COMP.put(98, "corx");
DEVICE_COMP.put(99, "other");
}
private static final BiMap<Integer, String> DEVICE_COMP_CHINESE = HashBiMap.create();
static {
DEVICE_COMP_CHINESE.put(1, "雷远");
DEVICE_COMP_CHINESE.put(2, "赛英");
DEVICE_COMP_CHINESE.put(3, "智安");
DEVICE_COMP_CHINESE.put(4, "和普");
DEVICE_COMP_CHINESE.put(5, "尚上");
DEVICE_COMP_CHINESE.put(98, "科星");
DEVICE_COMP_CHINESE.put(99, "其他");
}
private static final Map<Integer, List<String>> DEVICE_SERVICE_TYPE = new HashMap<>(16);
static {
// 雷远雷达
DEVICE_SERVICE_TYPE.put(Objects.hash(1, 1), SocketType.UDP.SERVICE.getNameAsList());
// 赛英雷达
DEVICE_SERVICE_TYPE.put(Objects.hash(1, 2), SocketType.UDP.SERVICE.getNameAsList());
// 电子围网
DEVICE_SERVICE_TYPE.put(Objects.hash(3, 3), SocketType.TCP.CLIENT.getNameAsList());
// 科兴网络继电器
DEVICE_SERVICE_TYPE.put(Objects.hash(98, 98), SocketType.TCP.CLIENT.getNameAsList());
// 振动电缆
DEVICE_SERVICE_TYPE.put(Objects.hash(6, 3), SocketType.TCP.CLIENT.getNameAsList());
DEVICE_SERVICE_TYPE.put(-1, new ArrayList<>());
}
public static String getDeviceTypeName(int deviceType) {
return DEVICE_TYPE.get(deviceType);
}
public static String getDeviceCompName(int deviceComp) {
return DEVICE_COMP.get(deviceComp);
}
public static String getDeviceTypeNameChinese(int deviceType) {
return DEVICE_TYPE_CHINESE.get(deviceType);
}
public static String getDeviceCompNameChinese(int deviceComp) {
return DEVICE_COMP_CHINESE.get(deviceComp);
}
public static int getDeviceTypeValue(String deviceType) {
return DEVICE_TYPE.inverse().get(deviceType);
}
public static int getDeviceCompValue(String deviceComp) {
return DEVICE_COMP.inverse().get(deviceComp);
}
public static int getDeviceTypeValueChinese(String deviceType) {
return DEVICE_TYPE_CHINESE.inverse().get(deviceType);
}
public static int getDeviceCompValueChinese(String deviceComp) {
return DEVICE_COMP_CHINESE.inverse().get(deviceComp);
}
public static String getDeviceMark(int deviceType, int deviceComp, String delimiter) {
return DEVICE_TYPE.get(deviceType) + delimiter + DEVICE_COMP.get(deviceComp);
}
public static String getDeviceNameChinese(int deviceType, int deviceComp) {
return DEVICE_COMP_CHINESE.get(deviceComp) + DEVICE_TYPE_CHINESE.get(deviceType);
}
public static String getAlarmType(int alarmType) {
return ALARM_TYPE.get(alarmType);
}
public static String getServiceId(int deviceType, int deviceComp, String delimiter) {
int hash = Objects.hash(deviceType, deviceComp);
List<String> list = DEVICE_SERVICE_TYPE.getOrDefault(hash, new ArrayList<>());
// 没有值时
if (list.isEmpty()) {
return "";
}
StringBuilder value = new StringBuilder();
for (int i = 0; i < list.size(); i++) {
if (i != 0) {
value.append(delimiter);
}
value.append(list.get(i));
}
return value.toString();
}
}

36
src/main/java/com/zgx/iot/netty/constant/HandlerDataType.java

@ -0,0 +1,36 @@
package com.zgx.iot.netty.constant;
/**
* @author AaGMixW
*/
public enum HandlerDataType {
;
public enum PerimeterDataType {
/**
* 报警数据
*/
ALARM(0),
/**
* 操作结果数据
*/
OPERATE_RESULT(1),
/**
* 设防/旁路 数据
*/
DEFENCE_AREA_DATA(2),
;
private final int value;
PerimeterDataType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
}

74
src/main/java/com/zgx/iot/netty/constant/SocketType.java

@ -0,0 +1,74 @@
package com.zgx.iot.netty.constant;
import java.util.ArrayList;
import java.util.List;
public enum SocketType {
;
public enum TCP {
/**
* 服务端
*/
SERVICE("service", 1),
/**
* 客户端
*/
CLIENT("client", 0);
private final String name;
private final Integer value;
private static final String PREFIX = "TCP";
TCP(String name, Integer value) {
this.name = name;
this.value = value;
}
public String getName(String delimiter) {
return PREFIX + delimiter + name;
}
public Integer getValue() {
return value;
}
public List<String> getNameAsList() {
List<String> list = new ArrayList<>(16);
list.add(PREFIX);
list.add(name);
return list;
}
}
public enum UDP {
/**
* 服务端
*/
SERVICE("service", 1),
/**
* 客户端
*/
CLIENT("client", 0);
private final String name;
private final Integer value;
private static final String PREFIX = "UDP";
UDP(String name, Integer value) {
this.name = name;
this.value = value;
}
public String getName(String delimiter) {
return PREFIX + delimiter + name;
}
public Integer getValue() {
return value;
}
public List<String> getNameAsList() {
List<String> list = new ArrayList<>(16);
list.add(PREFIX);
list.add(name);
return list;
}
}
}

239
src/main/java/com/zgx/iot/netty/constant/device/MicrowaveDetectorConstant.java

@ -0,0 +1,239 @@
package com.zgx.iot.netty.constant.device;
import java.util.HashMap;
import java.util.Map;
/**
* @author AaGMixW
*/
public enum MicrowaveDetectorConstant {
;
public enum deviceType {
/**
* 探测器
*/
DETECTOR(1, "探测器"),
/**
* 探测主机
*/
DETECTOR_HOST(2, "探测主机"),
/**
* 串口设备
*/
SERIAL_DEVICE(3, "串口设备"),
/**
* 预留
*/
RESERVED(4, "预留");
private int value;
private String name;
deviceType(int value, String name) {
this.value = value;
this.name = name;
}
public int getValue() {
return value;
}
public String getName() {
return name;
}
private static final Map<Integer, deviceType> map = new HashMap<>();
static {
for (MicrowaveDetectorConstant.deviceType deviceType : deviceType.values()) {
map.put(deviceType.getValue(), deviceType);
}
}
public static deviceType valueOf(int value) {
return map.get(value);
}
}
public enum faultType {
/**
* 无特定类型
*/
NONE(0, "无特定类型"),
/**
* 离线丢失
*/
OFFLINE(1, "离线丢失"),
/**
* 硬件故障
*/
HARDWARE_FAULT(2, "硬件故障"),
/**
* 传感器噪声高
*/
SENSOR_NOISE_HIGH(3, "传感器噪声高"),
/**
* 内部软件故障
*/
INTERNAL_SOFTWARE_FAULT(4, "内部软件故障"),
/**
* 防拆报警
*/
ANTI_DEMOLITION_ALARM(5, "防拆报警"),
/**
* 状态不明
*/
STATUS_UNKNOWN(6, "状态不明"),
/**
* 错误消息或通信异常
*/
ERROR_MESSAGE_OR_COMMUNICATION_EXCEPTION(7, "错误消息或通信异常"),
/**
* 剪线断线
*/
CUT_LINE_DISCONNECT(8, "剪线断线"),
/**
* 其他预留
*/
OTHER_RESERVED(9, "其他预留");
private int value;
private String name;
faultType(int value, String name) {
this.value = value;
this.name = name;
}
public int getValue() {
return value;
}
public String getName() {
return name;
}
private static final Map<Integer, faultType> map = new HashMap<>();
static {
for (faultType faultType : faultType.values()) {
map.put(faultType.getValue(), faultType);
}
}
public static faultType valueOf(int value) {
return map.get(value);
}
}
public enum alarmType {
/**
* MEMS入侵报警
*/
MEMS_INVASION_ALARM(1, "MEMS入侵报警"),
/**
* 预留
*/
RESERVED(2, "预留");
private int value;
private String name;
alarmType(int value, String name) {
this.value = value;
this.name = name;
}
public int getValue() {
return value;
}
public String getName() {
return name;
}
private static final Map<Integer, alarmType> map = new HashMap<>();
static {
for (alarmType alarmType : alarmType.values()) {
map.put(alarmType.getValue(), alarmType);
}
}
public static alarmType valueOf(int value) {
return map.get(value);
}
}
public enum alarmReason {
// pc:0-其它(无特定原因);1-敲击;2-摇晃;3-攀爬(振动);4-倾斜;5~7:预留;8-剪切线缆;
//9-MEMS雷达报警
/**
* 其它无特定原因
*/
OTHER(0, "其它(无特定原因)"),
/**
* 敲击
*/
KNOCK(1, "敲击"),
/**
* 摇晃
*/
SHAKE(2, "摇晃"),
/**
* 攀爬振动
*/
CLIMB(3, "攀爬(振动)"),
/**
* 倾斜
*/
TILT(4, "倾斜"),
/**
* 预留
*/
RESERVED(5, "预留"),
RESERVED_2(6, "预留"),
RESERVED_3(7, "预留"),
/**
* 剪切线缆
*/
CUT_WIRE(8, "剪切线缆"),
/**
* MEMS雷达报警
*/
MEMS_RADAR_ALARM(9, "MEMS雷达报警");
private int value;
private String name;
alarmReason(int value, String name) {
this.value = value;
this.name = name;
}
public int getValue() {
return value;
}
public String getName() {
return name;
}
private static final Map<Integer, alarmReason> map = new HashMap<>();
static {
for (alarmReason alarmReason : alarmReason.values()) {
map.put(alarmReason.getValue(), alarmReason);
}
}
public static alarmReason valueOf(int value) {
return map.get(value);
}
}
}

12
src/main/java/com/zgx/iot/netty/exception/CompletableFutureException.java

@ -0,0 +1,12 @@
package com.zgx.iot.netty.exception;
/**
* @author AaGMixW
*/
public class CompletableFutureException extends RuntimeException {
private static final long serialVersionUID = 6898660892382632176L;
public CompletableFutureException(String s) {
super(s);
}
}

12
src/main/java/com/zgx/iot/netty/exception/DeviceInfoException.java

@ -0,0 +1,12 @@
package com.zgx.iot.netty.exception;
/**
* @author AaGMixW
*/
public class DeviceInfoException extends RuntimeException {
private static final long serialVersionUID = 5004118888832463932L;
public DeviceInfoException(String s) {
super(s);
}
}

12
src/main/java/com/zgx/iot/netty/exception/NettyServiceControllerException.java

@ -0,0 +1,12 @@
package com.zgx.iot.netty.exception;
/**
* @author AaGMixW
*/
public class NettyServiceControllerException extends RuntimeException {
private static final long serialVersionUID = -8621535055348629709L;
public NettyServiceControllerException(String s) {
super(s);
}
}

57
src/main/java/com/zgx/iot/netty/handler/ConnectHandler.java

@ -0,0 +1,57 @@
package com.zgx.iot.netty.handler;
import com.zgx.iot.netty.constant.AttributeMapConstant;
import com.zgx.iot.netty.socket.base.NettyBaseClientImpl;
import com.zgx.iot.netty.socket.base.NettyBaseServiceImpl;
import com.zgx.iot.netty.socket.base.NettyBaseSocket;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.NetUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.net.InetSocketAddress;
/**
* @author AaGMixW
*/
public class ConnectHandler extends ChannelInboundHandlerAdapter {
private static final Logger logger = LogManager.getLogger(ConnectHandler.class);
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
NettyBaseSocket socket = ctx.channel().attr(AttributeMapConstant.NETTY_CHANNEL_SOCKET_KEY).get();
InetSocketAddress address = new InetSocketAddress(0);
String msg = "";
if (socket instanceof NettyBaseClientImpl) {
address = (InetSocketAddress) ctx.channel().remoteAddress();
msg = "建立连接";
} else if (socket instanceof NettyBaseServiceImpl) {
address = (InetSocketAddress) ctx.channel().localAddress();
msg = "监听端口";
}
String name = socket.getDeviceInfo().getDeviceName() + "(" + NetUtil.toSocketAddressString(address) + ")";
logger.info("{} {}", name, msg);
super.channelActive(ctx);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) {
NettyBaseSocket socket = ctx.channel().attr(AttributeMapConstant.NETTY_CHANNEL_SOCKET_KEY).get();
InetSocketAddress address = new InetSocketAddress(0);
String msg = "";
if (socket instanceof NettyBaseClientImpl) {
// client
address = (InetSocketAddress) ctx.channel().remoteAddress();
msg = "断开连接";
} else if (socket instanceof NettyBaseServiceImpl) {
// service
address = (InetSocketAddress) ctx.channel().localAddress();
msg = "停止监听";
}
String name = socket.getDeviceInfo().getDeviceName() + "(" + NetUtil.toSocketAddressString(address) + ")";
logger.info("{} {}", name, msg);
}
}

168
src/main/java/com/zgx/iot/netty/handler/ExceptionHandler.java

@ -0,0 +1,168 @@
package com.zgx.iot.netty.handler;
import com.zgx.iot.netty.config.AppServiceConfig;
import com.zgx.iot.netty.constant.AttributeMapConstant;
import com.zgx.iot.netty.socket.base.NettyBaseClientImpl;
import com.zgx.iot.netty.socket.base.NettyBaseServiceImpl;
import com.zgx.iot.netty.socket.base.NettyBaseSocket;
import com.zgx.iot.utils.NettyConfigUtil;
import io.netty.channel.*;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.util.NetUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.PortUnreachableException;
import java.net.SocketAddress;
import java.nio.channels.ClosedChannelException;
import java.util.concurrent.TimeUnit;
/**
* @author AaGMixW
*/
@Sharable
public class ExceptionHandler extends ChannelDuplexHandler {
private static final Logger logger = LogManager.getLogger(ExceptionHandler.class);
private final AppServiceConfig appServiceConfig = NettyConfigUtil.getAppServiceConfig();
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// Uncaught exceptions from inbound handlers will propagate up to this handler
InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress();
String addressStr = NetUtil.toSocketAddressString(address);
try {
if (cause instanceof IOException) {
if (cause instanceof PortUnreachableException) {
logger.error("无法发送到指定端口 {} => {}", addressStr,
cause.getMessage() != null ? cause.getMessage() : cause.getClass().getSimpleName());
logger.error("关闭该连接");
ctx.channel().close().sync();
} else {
logger.error("连接 {} 异常=> {}", addressStr,
cause.getMessage() != null ? cause.getMessage() : cause.getClass().getSimpleName());
}
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
/**
* client
*
* @param ctx the {@link ChannelHandlerContext} for which the connect operation is made
* @param remoteAddress the {@link SocketAddress} to which it should connect
* @param localAddress the {@link SocketAddress} which is used as source on connect
* @param promise the {@link ChannelPromise} to notify once the operation completes
*/
@Override
public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
NettyBaseSocket socket = ctx.channel().attr(AttributeMapConstant.NETTY_CHANNEL_SOCKET_KEY).get();
ctx.connect(remoteAddress, localAddress, promise.addListener((ChannelFutureListener) future -> {
if (!future.isSuccess()) {
// Handle connect exception here...
Throwable failureCause = future.cause();
InetSocketAddress address = (InetSocketAddress) remoteAddress;
String addressStr = NetUtil.toSocketAddressString(address);
String name = socket.getDeviceInfo().getDeviceName() + "(" + addressStr + ")";
if (failureCause instanceof ClosedChannelException) {
logger.info("{} 连接已关闭", name);
return;
}
logger.error("{} 建立连接异常: {}", name, failureCause.getMessage());
// reconnect
doConnect(ctx, address);
}
}));
}
/**
* service
*
* @param ctx the {@link ChannelHandlerContext} for which the bind operation is made
* @param localAddress the {@link SocketAddress} to which it should bound
* @param promise the {@link ChannelPromise} to notify once the operation completes
* @throws Exception 异常
*/
@Override
public void bind(ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) throws Exception {
NettyBaseSocket socket = ctx.channel().attr(AttributeMapConstant.NETTY_CHANNEL_SOCKET_KEY).get();
ctx.bind(localAddress, promise.addListener((ChannelFutureListener) future -> {
if (!future.isSuccess()) {
// Handle connect exception here...
Throwable failureCause = future.cause();
InetSocketAddress address = (InetSocketAddress) localAddress;
String addressStr = NetUtil.toSocketAddressString(address);
String name = socket.getDeviceInfo().getDeviceName() + "(" + addressStr + ")";
logger.error("{} 监听端口异常: {}", name, failureCause.getMessage());
// reconnect
doConnect(ctx, address);
}
}));
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
ctx.write(msg, promise.addListener((ChannelFutureListener) future -> {
if (!future.isSuccess()) {
// Handle write exception here...
Throwable failureCause = future.cause();
logger.info("write exception: {}", failureCause.getMessage());
}
}));
}
/**
* Calls {@link ChannelHandlerContext#fireChannelUnregistered()} to forward
* to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}.
* <p>
* Subclasses may override this method to change behavior.
*
* @param ctx ctx
*/
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
NettyBaseSocket socket = ctx.channel().attr(AttributeMapConstant.NETTY_CHANNEL_SOCKET_KEY).get();
//客户端使用过程中断线重连
if (socket instanceof NettyBaseClientImpl) {
InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress();
if (address != null) {
doConnect(ctx, address);
} else {
logger.error("重连时获取连接地址出错,取消连接");
ctx.channel().close().sync();
}
}
super.channelUnregistered(ctx);
}
/**
* 重试方法
*
* @param ctx ctx
* @param address 连接地址
*/
private void doConnect(ChannelHandlerContext ctx, InetSocketAddress address) {
NettyBaseSocket socket = ctx.channel().attr(AttributeMapConstant.NETTY_CHANNEL_SOCKET_KEY).get();
String addressStr = NetUtil.toSocketAddressString(address);
String name = socket.getDeviceInfo().getDeviceName() + "(" + addressStr + ")";
long nextRetryDelay = appServiceConfig.getRetryInterval();
String msg = "";
if (socket instanceof NettyBaseClientImpl) {
// client
msg = "连接";
} else if (socket instanceof NettyBaseServiceImpl) {
// service
msg = "监听";
}
logger.info("{} 正在尝试重新{}", name, msg);
ctx.channel().eventLoop().schedule(() -> socket.retry(address), nextRetryDelay, TimeUnit.MILLISECONDS);
}
// ... override more outbound methods to handle their exceptions as well
}

87
src/main/java/com/zgx/iot/netty/handler/codec/MicrowaveDetectorMessageClientDecoder.java

@ -0,0 +1,87 @@
package com.zgx.iot.netty.handler.codec;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.zgx.iot.netty.constant.AttributeMapConstant;
import com.zgx.iot.netty.model.device.microwave.command.rep.MicrowaveDeviceRep;
import com.zgx.iot.netty.model.device.microwave.command.rep.MicrowaveIORep;
import com.zgx.iot.netty.model.device.microwave.command.rep.MicrowaveOpcRep;
import com.zgx.iot.netty.model.device.microwave.command.rep.MicrowaveQueryRep;
import com.zgx.iot.utils.JacksonUtil;
import com.zgx.iot.utils.NettyDeviceUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.socket.DatagramPacket;
import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.util.Attribute;
import lombok.extern.slf4j.Slf4j;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author AaGMixW
*/
@Slf4j
public class MicrowaveDetectorMessageClientDecoder extends MessageToMessageDecoder<DatagramPacket> {
private static final String LOCAL_HOST_ADDR = "127.0.0.1";
@Override
protected void decode(ChannelHandlerContext ctx, DatagramPacket packet, List<Object> list) {
ByteBuf byteBuf = packet.content();
int readableBytes = byteBuf.readableBytes();
if (readableBytes <= 0) {
return;
}
Attribute<InetSocketAddress> addrAttr = ctx.channel().attr(AttributeMapConstant.NETTY_SERVICE_REMOTE_ADDR_KEY);
InetSocketAddress address = packet.sender();
addrAttr.set(address);
String dataStr = byteBuf.toString(Charset.forName("GB18030"));
InetSocketAddress localAddress = (InetSocketAddress) ctx.channel().localAddress();
String deviceName = NettyDeviceUtil.getDeviceNameAndIp(ctx, localAddress, address);
log.debug("{} 字符数据: {}", deviceName, dataStr);
/* try {
// 判断数据类型
String regex = "^\\s*<(\\w+:)?(\\w+)";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(dataStr);
if (matcher.find()) {
String root = matcher.group(2);
switch (root) {
case "opcRep":
// 防区及探测器操作维护响应
MicrowaveOpcRep opcRep = JacksonUtil.xml2Obj(dataStr, MicrowaveOpcRep.class);
list.add(opcRep);
break;
case "ioRep":
// IO操作维护响应
MicrowaveIORep ioRep = JacksonUtil.xml2Obj(dataStr, MicrowaveIORep.class);
list.add(ioRep);
break;
case "deviceRep":
// 设备操作维护响应
MicrowaveDeviceRep deviceRep = JacksonUtil.xml2Obj(dataStr, MicrowaveDeviceRep.class);
list.add(deviceRep);
break;
case "queryRep":
// 查询响应
MicrowaveQueryRep queryRep = JacksonUtil.xml2Obj(dataStr, MicrowaveQueryRep.class);
list.add(queryRep);
break;
default:
log.error("{} 服务, 数据 => {}; 未匹配到数据类型, 丢弃数据", deviceName, dataStr);
}
} else {
log.error("{} 服务, 数据 => {}; 未匹配到数据类型, 丢弃数据", deviceName, dataStr);
}
} catch (JsonProcessingException e) {
log.error("{} 服务, 数据 => {}; 转换失败: {}, 丢弃数据", deviceName, dataStr, e.getMessage());
}*/
}
}

81
src/main/java/com/zgx/iot/netty/handler/codec/MicrowaveDetectorMessageServiceDecoder.java

@ -0,0 +1,81 @@
package com.zgx.iot.netty.handler.codec;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.zgx.iot.netty.constant.AttributeMapConstant;
import com.zgx.iot.netty.model.device.microwave.MicrowaveDetectorAlarm;
import com.zgx.iot.netty.model.device.microwave.MicrowaveDetectorFault;
import com.zgx.iot.netty.model.device.microwave.MicrowaveDetectorHeartbeat;
import com.zgx.iot.utils.JacksonUtil;
import com.zgx.iot.utils.NettyDeviceUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.socket.DatagramPacket;
import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.util.Attribute;
import lombok.extern.slf4j.Slf4j;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author AaGMixW
*/
@Slf4j
public class MicrowaveDetectorMessageServiceDecoder extends MessageToMessageDecoder<DatagramPacket> {
private static final String LOCAL_HOST_ADDR = "127.0.0.1";
@Override
protected void decode(ChannelHandlerContext ctx, DatagramPacket packet, List<Object> list) {
/* ByteBuf byteBuf = packet.content();
int readableBytes = byteBuf.readableBytes();
if (readableBytes <= 0) {
return;
}
Attribute<InetSocketAddress> addrAttr = ctx.channel().attr(AttributeMapConstant.NETTY_SERVICE_REMOTE_ADDR_KEY);
InetSocketAddress address = packet.sender();
addrAttr.set(address);
String dataStr = byteBuf.toString(Charset.forName("GB18030"));
InetSocketAddress localAddress = (InetSocketAddress) ctx.channel().localAddress();
String deviceName = NettyDeviceUtil.getDeviceNameAndIp(ctx, localAddress, address);
log.debug("{} 字符数据: {}", deviceName, dataStr);
try {
// 判断数据类型
String regex = "^\\s*<(\\w+:)?(\\w+)";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(dataStr);
if (matcher.find()) {
String root = matcher.group(2);
switch (root) {
case "heartbeat":
// 心跳数据
MicrowaveDetectorHeartbeat heartbeat = JacksonUtil.xml2Obj(dataStr, MicrowaveDetectorHeartbeat.class);
list.add(heartbeat);
break;
case "fault":
// 故障数据
MicrowaveDetectorFault fault = JacksonUtil.xml2Obj(dataStr, MicrowaveDetectorFault.class);
list.add(fault);
break;
case "alarm":
// 报警数据
MicrowaveDetectorAlarm alarm = JacksonUtil.xml2Obj(dataStr, MicrowaveDetectorAlarm.class);
list.add(alarm);
break;
default:
log.error("{} 服务, 数据 => {}; 未匹配到数据类型, 丢弃数据", deviceName, dataStr);
}
} else {
log.error("{} 服务, 数据 => {}; 未匹配到数据类型, 丢弃数据", deviceName, dataStr);
}
} catch (JsonProcessingException e) {
log.error("{} 服务, 数据 => {}; 转换失败: {}, 丢弃数据", deviceName, dataStr, e.getMessage());
}*/
}
}

105
src/main/java/com/zgx/iot/netty/handler/codec/RadarDetectorMessageServiceDecoder.java

@ -0,0 +1,105 @@
package com.zgx.iot.netty.handler.codec;
import com.zgx.iot.dto.radar.RadarRESPackageModel;
import com.zgx.iot.netty.NettyServiceManage;
import com.zgx.iot.radar.RadarAcceptSocket;
import com.zgx.iot.utils.radarUtils.ByteIntUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandler;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.FixedLengthFrameDecoder;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.ReplayingDecoder;
import org.apache.commons.logging.Log;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.DataInputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
public class RadarDetectorMessageServiceDecoder extends ByteToMessageDecoder {
private static final Logger log = LogManager.getLogger(RadarDetectorMessageServiceDecoder.class);
private int radar_data_package_head_len=16;
public static final int PACKAGE_MAX_LENGTH = 4096;
private volatile boolean flag = true;
private volatile byte[] data;
private int len;
private byte[] byte_buffer;
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf,List<Object> list) throws Exception {
int size = byteBuf.readableBytes();
while (flag) {
if (byteBuf.readableBytes()<size){
byteBuf.resetReaderIndex();
return;
}
System.out.println(size);
byte[] data = new byte[size];
byteBuf.readBytes(data);
this.len = data.length;
this.data = new byte[this.len];
System.arraycopy(data, 0, this.data, 0, this.len);
RadarRESPackageModel radarRESPackageModel = this.dealProcess(this.data);
log.info("处理好的数据:"+radarRESPackageModel);
if (radarRESPackageModel!=null){
list.add(radarRESPackageModel);
log.info("list添加了");
}
byteBuf.skipBytes(byteBuf.readableBytes());
byteBuf.markReaderIndex();
this.data = null;
}
}
private RadarRESPackageModel dealProcess(final byte[] bytes) {
log.info(Arrays.toString(bytes));
if (this.byte_buffer == null) {
this.byte_buffer = bytes;
} else if (this.byte_buffer.length > 1024000) {
this.byte_buffer = bytes;
} else {
this.byte_buffer = ByteIntUtil.byteMerger(this.byte_buffer, bytes);
}
final int byte_buffer_len = this.byte_buffer.length;
if (byte_buffer_len < this.radar_data_package_head_len) {
// 数据包头不完整,没有达到16字节长度
log.debug("\u6570\u636e\u5305\u5934\u4e0d\u5b8c\u6574\uff0c\u6ca1\u6709\u8fbe\u523016\u5b57\u8282\u957f\u5ea6");
return null;
}
final RadarRESPackageModel radarPackage = new RadarRESPackageModel(this.byte_buffer);
final int mark = radarPackage.getMark();
final int dataType = radarPackage.getDataType();
final int dataLength = radarPackage.getDataLength();
final int dataNum = radarPackage.getDataNum();
// 包头标识
log.info("\u5305\u5934\u6807\u8bc6\uff1a " + mark);
// 数据类型
log.info("\u6570\u636e\u7c7b\u578b\uff1a " + dataType);
// 整包数据的长度
log.info("\u6574\u5305\u6570\u636e\u7684\u957f\u5ea6\uff1a " + dataLength);
// 数据数量
log.info("\u6570\u636e\u6570\u91cf\uff1a " + dataNum);
if (!radarPackage.isIntegrated()) {
// 数据包没有发送完整,等待继续接收
log.info("\u6570\u636e\u5305\u6ca1\u6709\u53d1\u9001\u5b8c\u6574\uff0c\u7b49\u5f85\u7ee7\u7eed\u63a5\u6536\r\n");
return null;
}
final byte[] radardata = radarPackage.getData();
//this.handleRadarData(mark, dataType, dataLength, dataNum, radardata);
final byte[] remainbytes = radarPackage.getRemain();
if (remainbytes != null) {
this.byte_buffer = remainbytes;
} else {
this.byte_buffer = null;
}
return radarPackage;
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save