Commit 677459c9 authored by zengtianlai3's avatar zengtianlai3

自诊断

parent 4103d792
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ]; then
if [ -f /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
export JAVA_HOME="$(/usr/libexec/java_home)"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ]; then
if [ -r /etc/gentoo-release ]; then
JAVA_HOME=$(java-config --jre-home)
fi
fi
if [ -z "$M2_HOME" ]; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ]; do
ls=$(ls -ld "$PRG")
link=$(expr "$ls" : '.*-> \(.*\)$')
if expr "$link" : '/.*' >/dev/null; then
PRG="$link"
else
PRG="$(dirname "$PRG")/$link"
fi
done
saveddir=$(pwd)
M2_HOME=$(dirname "$PRG")/..
# make it fully qualified
M2_HOME=$(cd "$M2_HOME" && pwd)
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=$(cygpath --unix "$M2_HOME")
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw; then
[ -n "$M2_HOME" ] &&
M2_HOME="$( (
cd "$M2_HOME"
pwd
))"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="$( (
cd "$JAVA_HOME"
pwd
))"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="$(which javac)"
if [ -n "$javaExecutable" ] && ! [ "$(expr \"$javaExecutable\" : '\([^ ]*\)')" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=$(which readlink)
if [ ! $(expr "$readLink" : '\([^ ]*\)') = "no" ]; then
if $darwin; then
javaHome="$(dirname \"$javaExecutable\")"
javaExecutable="$(cd \"$javaHome\" && pwd -P)/javac"
else
javaExecutable="$(readlink -f \"$javaExecutable\")"
fi
javaHome="$(dirname \"$javaExecutable\")"
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ]; then
if [ -n "$JAVA_HOME" ]; then
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="$(
\unset -f command
\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
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]; then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ]; do
if [ -d "$wdir"/.mvn ]; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=$(
cd "$wdir/.."
pwd
)
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' <"$1")"
fi
}
BASE_DIR=$(find_maven_basedir "$(pwd)")
if [ -z "$BASE_DIR" ]; then
exit 1
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
fi
while IFS="=" read key value; do
case "$key" in wrapperUrl)
jarUrl="$value"
break
;;
esac
done <"$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
fi
if command -v wget >/dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
fi
elif command -v curl >/dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=$(cygpath --path --windows "$javaClass")
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=$(cygpath --path --windows "$M2_HOME")
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
$MAVEN_DEBUG_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" \
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%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 DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
%JVM_CONFIG_MAVEN_PROPS% ^
%MAVEN_OPTS% ^
%MAVEN_DEBUG_OPTS% ^
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%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%
<?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.2.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>iot.sixiang</groupId>
<artifactId>iot_diagnose</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>iot_diagnose</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--xss-->
<dependency>
<groupId>org.owasp.esapi</groupId>
<artifactId>esapi</artifactId>
<version>2.2.0.0</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.13.1</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.33.Final</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.8.2</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
<!-- velocity 模板引擎, Mybatis Plus 代码生成器需要 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<!--Knife4j API文档生产工具-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.9</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package iot.sixiang.iot_diagnose;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@ServletComponentScan(basePackages = "iot.sixiang.iot_diagnose")
@SpringBootApplication
@EnableScheduling
@MapperScan(basePackages = "iot.sixiang.iot_diagnose.mapper")
public class IotDiagnoseApplication implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
public static void main(String[] args) {
SpringApplication.run(IotDiagnoseApplication.class, args);
}
}
package iot.sixiang.iot_diagnose.auth;
import iot.sixiang.iot_diagnose.device.DeviceManager;
import iot.sixiang.iot_diagnose.entity.Apply;
import iot.sixiang.iot_diagnose.entity.DeviceBlack;
import iot.sixiang.iot_diagnose.model.PageInfoModel;
import iot.sixiang.iot_diagnose.model.vo.AppVo;
import iot.sixiang.iot_diagnose.model.vo.DeviceVo;
import iot.sixiang.iot_diagnose.service.ApplyService;
import iot.sixiang.iot_diagnose.service.DeviceBlackService;
import iot.sixiang.iot_diagnose.util.CommonUtil;
import iot.sixiang.iot_diagnose.util.HmacUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
@Slf4j
public class AuthManager {
@Autowired
private ApplyService applyService;
@Autowired
private DeviceManager deviceManager;
@Autowired
private DeviceBlackService deviceBlackService;
private Map<String, Apply> allApply = null;
private Map<Integer, DeviceBlack> deviceBlackMap = null;
public AuthManager() {
allApply = new HashMap<>();
deviceBlackMap = new HashMap<>();
}
@PostConstruct
public void init() {
initApps();
initDeviceBlacks();
}
public void initApps() {
allApply = new HashMap<>();
PageInfoModel<AppVo> records = applyService.getAppList(1, 10000, "");
List<AppVo> appList = records.getResult();
for (Apply apply : appList) {
String appId = apply.getAppId();
allApply.put(appId, apply);
}
}
public void initDeviceBlacks() {
deviceBlackMap = new HashMap<>();
PageInfoModel<DeviceBlack> records = deviceBlackService.getDeviceBlackList(1, 10000);
List<DeviceBlack> deviceBlackList = records.getResult();
for (DeviceBlack deviceBlack : deviceBlackList) {
int deviceId = deviceBlack.getDeviceId();
deviceBlackMap.put(deviceId, deviceBlack);
}
}
public boolean auth(String appId, String sn, String sign) {
if (!allApply.containsKey(appId)) {
return false;
}
if (!deviceManager.getContainSn(sn)) {
return false;
}
DeviceVo device = deviceManager.getDevice(sn);
int deviceId = device.getDeviceId();
if(deviceBlackMap.containsKey(deviceId)){
return false;
}
Apply apply = allApply.get(appId);
String appKey = apply.getAppKey();
String input = "app_id=" + appId + "&sn=" + sn;
String valSHA1 = HmacUtil.encrypt(input, appKey, HmacUtil.HMAC_SHA1).toUpperCase();
if (CommonUtil.toUpperCaseByEnglish(sign).equals(CommonUtil.toUpperCaseByEnglish(valSHA1))) {
return true;
} else {
return false;
}
}
public synchronized Map<Integer, DeviceBlack> getDeviceBlack() {
return deviceBlackMap;
}
}
package iot.sixiang.iot_diagnose.balance;
import iot.sixiang.iot_diagnose.entity.Server;
import iot.sixiang.iot_diagnose.service.ServerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Component
@Slf4j
public class BalanceManager {
@Autowired
private ServerService serverService;
private Map<String, Server> allServers = null;
public BalanceManager() {
allServers = new HashMap<String, Server>();
}
@PostConstruct
public void init() {
List<Server> servers = serverService.getServerList(0, 20);
for (Server server : servers) {
String serverIp = server.getServerIp();
allServers.put(serverIp, server);
}
}
public Server getBalanceServer() {
int count = allServers.size();
if (count == 0) {
return null;
} else {
SecureRandom secureRandom = null;
try {
secureRandom = SecureRandom.getInstance("SHA1PRNG");
} catch (NoSuchAlgorithmException e) {
log.error("SecureRandom 不可用");
}
int index = 0;
if (secureRandom != null) {
index = secureRandom.nextInt(count);
}
List<Server> servers = new ArrayList<>(allServers.values());
return servers.get(index);
}
}
}
package iot.sixiang.iot_diagnose.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Created by m33 on 2022/6/7 15:08
*/
@Configuration
public class MyBatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
package iot.sixiang.iot_diagnose.config.swagger;
import org.springframework.context.annotation.Bean;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.ArrayList;
import java.util.List;
public abstract class BaseSwaggerConfig {
@Bean
public Docket createRestApi() {
SwaggerProperties swaggerProperties = swaggerProperties();
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo(swaggerProperties))
.select()
//.apis(RequestHandlerSelectors.basePackage(swaggerProperties.getApiBasePackage()))
.paths(PathSelectors.any())
//这里指定Controller扫描包路径
.apis(RequestHandlerSelectors.basePackage("iot.sixiang.iot_diagnose.controller"))
.build();
if (swaggerProperties.isEnableSecurity()) {
docket.securitySchemes(securitySchemes()).securityContexts(securityContexts());
}
return docket;
}
private ApiInfo apiInfo(SwaggerProperties swaggerProperties) {
return new ApiInfoBuilder()
.title(swaggerProperties.getTitle())
.description(swaggerProperties.getDescription())
.contact(new Contact(swaggerProperties.getContactName(), swaggerProperties.getContactUrl(), swaggerProperties.getContactEmail()))
.version(swaggerProperties.getVersion())
.build();
}
private List<ApiKey> securitySchemes() {
//设置请求头信息
List<ApiKey> result = new ArrayList<>();
ApiKey apiKey = new ApiKey("Authorization", "Authorization", "header");
result.add(apiKey);
return result;
}
private List<SecurityContext> securityContexts() {
//设置需要登录认证的路径
List<SecurityContext> result = new ArrayList<>();
result.add(getContextByPath("/*/.*"));
return result;
}
private SecurityContext getContextByPath(String pathRegex) {
return SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex(pathRegex))
.build();
}
private List<SecurityReference> defaultAuth() {
List<SecurityReference> result = new ArrayList<>();
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
result.add(new SecurityReference("Authorization", authorizationScopes));
return result;
}
/**
* 自定义Swagger配置
*/
public abstract SwaggerProperties swaggerProperties();
}
package iot.sixiang.iot_diagnose.config.swagger;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
/**
* Created by M=54G
* Date 4/27/21 9:37 AM
* Description API文档相关配置
*/
@Configuration
@EnableSwagger2WebMvc
@EnableKnife4j
public class SwaggerConfig extends BaseSwaggerConfig {
@Override
public SwaggerProperties swaggerProperties() {
return SwaggerProperties.builder()
.apiBasePackage("iot.sixiang.iot_diagnose.controller")
.title("实名制接口")
.description("实名制接口文档")
.contactName("ACC")
.version("1.0")
.enableSecurity(true)
.build();
}
}
package iot.sixiang.iot_diagnose.config.swagger;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = false)
@Builder
public class SwaggerProperties {
/**
* API文档生成基础路径
*/
private String apiBasePackage;
/**
* 是否要启用登录认证
*/
private boolean enableSecurity;
/**
* 文档标题
*/
private String title;
/**
* 文档描述
*/
private String description;
/**
* 文档版本
*/
private String version;
/**
* 文档联系人姓名
*/
private String contactName;
/**
* 文档联系人网址
*/
private String contactUrl;
/**
* 文档联系人邮箱
*/
private String contactEmail;
}
package iot.sixiang.iot_diagnose.consts;
public class Consts {
public static final int CMD_LICENSE = 1;//授权消息的cmd,十进制
public static final int EXECUTOR_THREAD_NUM = 30;
public static final int FORWARD_THREAD_NUM = 30;
public static final int OPERATE_THREAD_NUM = 5;
public static final int DEVICE_STATE_ONLINE = 1;// 设备在线
public static final int DEVICE_STATE_OFFLINE = 0;// 设备离线
public static final int SERVICE_DX_THRESHOLD_NORMAL = 100;
public static final int SERVICE_DX_THRESHOLD_BUSY = 500;
public static final int SERVICE_DX_STATUS_FLUENT = 0;//流畅
public static final int SERVICE_DX_STATUS_NORMAL = 1;//正常
public static final int SERVICE_DX_STATUS_BUSY = 2;//繁忙
}
package iot.sixiang.iot_diagnose.consts;
/**
* Created by m33 on 2022/6/15 9:43
*/
public enum ResultCode {
SUCCESS(200, "操作成功"),
SERVER_EXCEPTION(400, "服务异常"),
UNAUTHORIZED(401, "暂未登录或token已经过期"),
VALIDATE_FAILED(402, "参数检验失败"),
FAILED(403, "操作失败");
private long code;
private String msg;
private ResultCode(long code, String msg) {
this.code = code;
this.msg = msg;
}
public long getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
package iot.sixiang.iot_diagnose.controller;
import com.alibaba.fastjson.JSONObject;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.DynamicParameter;
import com.github.xiaoymin.knife4j.annotations.DynamicParameters;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import iot.sixiang.iot_diagnose.entity.Server;
import iot.sixiang.iot_diagnose.forward.ForwardManager;
import iot.sixiang.iot_diagnose.model.BaseResult;
import iot.sixiang.iot_diagnose.model.ResResult;
import iot.sixiang.iot_diagnose.model.SamMonitor;
import iot.sixiang.iot_diagnose.model.vo.QpsVo;
import iot.sixiang.iot_diagnose.model.vo.SamVo;
import iot.sixiang.iot_diagnose.model.vo.ServerStatusVo;
import iot.sixiang.iot_diagnose.operate.OperateManager;
import iot.sixiang.iot_diagnose.service.MonitorService;
import iot.sixiang.iot_diagnose.service.ServerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@RestController
@RequestMapping("/iot_license/operate")
@Api(value = "运维模块", tags = {"运维模块"})
public class OperateController {
@Autowired
private ServerService serverService;
@Autowired
private OperateManager operateManager;
@Autowired
private MonitorService monitorService;
@Autowired
private ForwardManager forwardManager;
@ApiOperation(value = "服务接口", notes = "用于获取服务列表")
@GetMapping("monitor/server")
public ResResult<SamMonitor> getDeviceTypes() {
List<SamMonitor> records = operateManager.getSamMonitorList();
return ResResult.success().goRecord(records);
}
@ApiOperation(value = "在线数量添加接口", notes = "用于添加当前在线数量")
@PostMapping("monitor/add")
public boolean addMonitor() {
return monitorService.addMonitor(20);
}
@ApiOperation(value = "获取并发量接口", notes = "用于获取并发量")
@GetMapping("monitor/qps")
@ApiImplicitParam(name = "type", value = "类型:0:今天 1:昨天 2:七天前 3:三十天前", required = true, dataType = "int")
public ResResult<QpsVo> getQps(@RequestParam("type") int type) {
HashMap<String, List<Integer>> monitorList = monitorService.getMonitorList(type);
return ResResult.success().goRecord(monitorList);
}
@ApiOperation(value = "获取服务自诊断信息接口", notes = "用于获取服务诊断信息")
@GetMapping("diagnosis/server")
@ApiImplicitParam()
public ResResult<ServerStatusVo> getDiagnosisInfo() {
ServerStatusVo serverStatus = forwardManager.getServerStatus();
return ResResult.success().goRecord(serverStatus);
}
@ApiOperation(value = "统计sam总数接口", notes = "用于统计sam的总数和总在线数量")
@GetMapping("sam/count")
public ResResult<SamVo> getSamTotalCount() {
Map<String, SamMonitor> samMonitorMap = operateManager.getSamMonitorMap();
Map<String, Integer> map = new HashMap<>();
int totalSamCount = 0;
int totalOnlineCount = 0;
for (SamMonitor samMonitor : samMonitorMap.values()) {
totalSamCount += samMonitor.getSamCount();
totalOnlineCount += samMonitor.getOnlineCount();
}
SamVo samVo = new SamVo();
samVo.setTotalOnlineCount(totalOnlineCount);
samVo.setTotalSamCount(totalSamCount);
return ResResult.success().goRecord(samVo);
}
/**
* 添加server
*
* @param jsonObject
* @return
*/
@ApiOperation(value = "添加服务接口", notes = "用于添加服务")
@PostMapping("server/add")
@ApiOperationSupport(params = @DynamicParameters(name = "jsonObject", properties = {
@DynamicParameter(name = "serverIp", value = "服务Ip", required = true, dataTypeClass = String.class),
@DynamicParameter(name = "port", value = "端口", required = true, dataTypeClass = Integer.class)
}))
public BaseResult addServer(@RequestBody JSONObject jsonObject) {
String serverIp = jsonObject.getString("serverIp");
int port = jsonObject.getIntValue("port");
boolean res = serverService.addServer(serverIp, port);
if (res) {
return BaseResult.success();
} else {
return BaseResult.failed();
}
}
/**
* 删除server
*
* @param serverIp
* @return
*/
@ApiOperation(value = "删除服务接口", notes = "删除服务")
@PostMapping("server/delete")
public BaseResult deleteServer(@RequestParam("serverIp") String serverIp) {
boolean res = serverService.deleteServer(serverIp);
if (res) {
return BaseResult.success();
} else {
return BaseResult.failed();
}
}
/**
* 修改server
*
* @param jsonObject
* @return
*/
@ApiOperation(value = "修改服务接口", notes = "修改服务")
@PostMapping("server/update")
@ApiOperationSupport(params = @DynamicParameters(name = "jsonObject", properties = {
@DynamicParameter(name = "serverIp", value = "服务Ip", required = true, dataTypeClass = String.class),
@DynamicParameter(name = "port", value = "端口", required = true, dataTypeClass = Integer.class)
}))
public BaseResult updateServer(@RequestBody JSONObject jsonObject) {
String serverIp = jsonObject.getString("serverIp");
int port = jsonObject.getInteger("port");
boolean res = serverService.updateServer(serverIp, port);
if (res) {
return BaseResult.success();
} else {
return BaseResult.failed();
}
}
/**
* 分页查询所有的server
*
* @param pageNo
* @param pageSize
* @return
*/
@ApiOperation(value = "获取服务列表接口", notes = "用于获取服务列表")
@GetMapping("server/list")
@ApiImplicitParams({
@ApiImplicitParam(name = "pageNo", value = "当前在第几页", required = true, dataType = "int"),
@ApiImplicitParam(name = "pageSize", value = "每页显示多少条", required = true, dataType = "int")
})
public ResResult<List<Server>> getServerList(@RequestParam("pageNo") int pageNo,
@RequestParam("pageSize") int pageSize) {
List<Server> records = serverService.getServerList(pageNo, pageSize);
return ResResult.success().goRecord(records);
}
}
package iot.sixiang.iot_diagnose.device;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import io.netty.util.concurrent.EventExecutorGroup;
import iot.sixiang.iot_diagnose.consts.Consts;
import iot.sixiang.iot_diagnose.net.BaseChannelInitializer;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.TimeUnit;
@Slf4j
public class DeviceChannelInitializer extends BaseChannelInitializer {
private DeviceServerHandler handler;
static final EventExecutorGroup workGroup = new DefaultEventExecutorGroup(Consts.EXECUTOR_THREAD_NUM);
public DeviceChannelInitializer(DeviceServerHandler handler) {
this.handler = handler;
}
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// 服务端心跳检测
ch.pipeline().addLast(new IdleStateHandler(3, 0, 0, TimeUnit.SECONDS));
ch.pipeline().addLast("decoder", new DeviceDecoder());
ch.pipeline().addLast("encoder", new DeviceEncoder());
ch.pipeline().addLast(workGroup, "handler", handler);
}
}
package iot.sixiang.iot_diagnose.device;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import iot.sixiang.iot_diagnose.util.Util;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
/**
* 数据包格式
* STX |LEN |CMD |ACK |DATA |END
*/
@Slf4j
public class DeviceDecoder extends ByteToMessageDecoder {
public final int BASE_LENGTH = 2 + 2 + 1 + 1 + 1;
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) {
byte[] packet = new byte[buffer.readableBytes()];
buffer.readBytes(packet);
buffer.resetReaderIndex();
Util.DEBUG_HEX("SERVER -> IN", packet, packet.length);
if (buffer.readableBytes() < BASE_LENGTH) {
return;
}
buffer.markReaderIndex();
short stx = buffer.readShort();
short len = buffer.readShortLE();
byte cmd = buffer.readByte();
byte ack = buffer.readByte();
int real_len = len;
int cmd_ack_len = 2;
if (buffer.readableBytes() < real_len - cmd_ack_len + 1) {
buffer.resetReaderIndex();
return;
}
// buffer.resetReaderIndex();
byte[] content = new byte[real_len - cmd_ack_len];
buffer.readBytes(content);
byte end = buffer.readByte();
DeviceProtocol protocol = new DeviceProtocol(stx, len, cmd, ack, content, end);
out.add(protocol);
}
}
\ No newline at end of file
package iot.sixiang.iot_diagnose.device;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import lombok.extern.slf4j.Slf4j;
/**
* 数据包格式
* STX |LEN |CMD |ACK |DATA |END
*/
@Slf4j
public class DeviceEncoder extends MessageToByteEncoder<DeviceProtocol> {
@Override
protected void encode(ChannelHandlerContext tcx, DeviceProtocol msg, ByteBuf out) {
out.writeShort(msg.getStx());
out.writeShortLE(msg.getLen());
out.writeByte(msg.getCmd());
out.writeByte(msg.getAck());
if (msg.getContent() != null) {
out.writeBytes(msg.getContent());
}
out.writeByte(msg.getEnd());
}
}
package iot.sixiang.iot_diagnose.device;
import iot.sixiang.iot_diagnose.consts.Consts;
import iot.sixiang.iot_diagnose.model.PageInfoModel;
import iot.sixiang.iot_diagnose.model.SessionContext;
import iot.sixiang.iot_diagnose.model.vo.DeviceDetailVo;
import iot.sixiang.iot_diagnose.model.vo.DeviceVo;
import iot.sixiang.iot_diagnose.net.TcpServer;
import iot.sixiang.iot_diagnose.service.DeviceService;
import iot.sixiang.iot_diagnose.util.CommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.*;
@Component
@Slf4j
public class DeviceManager {
private Map<String, SessionContext> sessionContexts = null;
private DeviceChannelInitializer channelInitializer;
private TcpServer server = null;
private int port = 18889;
private Map<String, DeviceVo> allDevice = null;
@Autowired
private DeviceService deviceService;
@Autowired
private DeviceServerHandler handler;
public DeviceManager() {
sessionContexts = new HashMap<String, SessionContext>();
allDevice = new HashMap<String, DeviceVo>();
}
@PostConstruct
public void init() {
startTcpService();
initDevices();
}
private void startTcpService() {
sessionContexts = new HashMap<String, SessionContext>();
channelInitializer = new DeviceChannelInitializer(handler);
server = new TcpServer(port, channelInitializer);
server.start();
}
public void initDevices() {
allDevice = new HashMap<>();
PageInfoModel<DeviceVo> records = deviceService.getDeviceList(1, 10000, "", "");
List<DeviceVo> deviceList = records.getResult();
for (DeviceVo deviceVo : deviceList) {
String sn = deviceVo.getSn();
allDevice.put(sn, deviceVo);
}
}
public boolean getContainSn(String sn) {
if (!allDevice.containsKey(sn)) {
return false;
}
return true;
}
public synchronized Map<String, DeviceVo> getAllDevice() {
return allDevice;
}
public synchronized void putSession(String appId, SessionContext session) {
sessionContexts.put(appId, session);
}
public SessionContext getSessionContextByAppId(String appId) {
return sessionContexts.get(appId);
}
public SessionContext getSessionByChannelId(String channelId) {
SessionContext session = null;
Iterator<Map.Entry<String, SessionContext>> it = sessionContexts.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, SessionContext> entry = it.next();
SessionContext targetSession = entry.getValue();
if (targetSession.getChannelId().equals(channelId)) {
return targetSession;
}
}
return session;
}
public boolean getAuthStatusByChannelId(String channelId) {
Iterator<Map.Entry<String, SessionContext>> it = sessionContexts.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, SessionContext> entry = it.next();
SessionContext targetSession = entry.getValue();
if (targetSession.getChannelId().equals(channelId)) {
return targetSession.isAuthStatus();
}
}
return false;
}
public SessionContext getSessionBySn(String sn) {
Iterator<Map.Entry<String, SessionContext>> it = sessionContexts.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, SessionContext> entry = it.next();
SessionContext targetSession = entry.getValue();
if (targetSession.getSn().equals(sn)) {
return targetSession;
}
}
return null;
}
public synchronized boolean removeSessionByChannelId(String channelId) {
Iterator<Map.Entry<String, SessionContext>> it = sessionContexts.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, SessionContext> entry = it.next();
SessionContext targetSession = entry.getValue();
if (targetSession.getChannelId().equals(channelId)) {
it.remove();
return true;
}
}
return false;
}
public boolean changeSessionOffline(String channelId) {
Iterator<Map.Entry<String, SessionContext>> it = sessionContexts.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, SessionContext> entry = it.next();
SessionContext targetSession = entry.getValue();
if (targetSession.getChannelId().equals(channelId)) {
targetSession.setAuthStatus(false);
targetSession.setStatus(Consts.DEVICE_STATE_OFFLINE);
targetSession.setOffline(CommonUtil.getSystemTime());
return true;
}
}
return false;
}
public PageInfoModel<DeviceDetailVo> getDeviceDetailList(int pageNo, int pageSize, String appName, String userName) {
PageInfoModel<DeviceVo> records = deviceService.getDeviceList(pageNo, pageSize, appName, userName);
List<DeviceVo> deviceVos = records.getResult();
PageInfoModel<DeviceDetailVo> detailVoPageInfoModel = new PageInfoModel<>();
List<DeviceDetailVo> detailVos = new ArrayList<>();
for (DeviceVo vo : deviceVos) {
DeviceDetailVo detailVo = new DeviceDetailVo();
detailVo.setDeviceId(vo.getDeviceId());
detailVo.setAppName(vo.getAppName());
detailVo.setUserName(vo.getUserName());
detailVo.setSn(vo.getSn());
detailVo.setOnline("");
detailVo.setOffline("");
String sn = vo.getSn();
SessionContext session = this.getSessionBySn(sn);
if (session != null) {
int status = session.getStatus();
String online = session.getOnline();
String offline = session.getOffline();
detailVo.setStatus(status);
detailVo.setOnline(online);
detailVo.setOffline(offline);
}
detailVos.add(detailVo);
}
detailVoPageInfoModel.setTotal(detailVos.size());
detailVoPageInfoModel.setResult(detailVos);
return detailVoPageInfoModel;
}
public DeviceVo getDevice(String sn) {
DeviceVo deviceVo = allDevice.get(sn);
return deviceVo;
}
}
package iot.sixiang.iot_diagnose.device;
import lombok.Data;
@Data
public class DeviceProtocol {
// |STX |LEN |CMD |ACK |DATA |END
private short stx;//
private int len;//
private byte cmd;
private byte ack;
private byte[] content;// 数据
private byte end;
public DeviceProtocol(short stx, int len, byte cmd, byte ack, byte[] content,byte end) {
super();
this.stx = stx;
this.len = len;
this.cmd = cmd;
this.ack = ack;
this.content = content;
this.end = end;
}
}
\ No newline at end of file
package iot.sixiang.iot_diagnose.device;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.SocketChannel;
import iot.sixiang.iot_diagnose.auth.AuthManager;
import iot.sixiang.iot_diagnose.consts.Consts;
import iot.sixiang.iot_diagnose.event.CreateForwarClientEvent;
import iot.sixiang.iot_diagnose.event.DeviceClientInactiveEvent;
import iot.sixiang.iot_diagnose.event.EventPublisher;
import iot.sixiang.iot_diagnose.event.ForwardClientRequestEvent;
import iot.sixiang.iot_diagnose.idreader.Safety;
import iot.sixiang.iot_diagnose.model.SessionContext;
import iot.sixiang.iot_diagnose.util.CommonUtil;
import iot.sixiang.iot_diagnose.util.HexUtil;
import iot.sixiang.iot_diagnose.util.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.net.InetSocketAddress;
@Component
@ChannelHandler.Sharable
@Slf4j
public class DeviceServerHandler extends SimpleChannelInboundHandler<Object> {
@Autowired
EventPublisher eventPublisher;
@Autowired
Safety safety;
public DeviceServerHandler() {
super();
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) {
// TODO Auto-generated method stub
SocketChannel channel = (SocketChannel) ctx.channel();
InetSocketAddress socketAddr = (InetSocketAddress) ctx.channel().remoteAddress();
String remoteIp = socketAddr.getHostString();
int remotePort = socketAddr.getPort();
DeviceProtocol protocol = (DeviceProtocol) msg;
String channelId = channel.id().asLongText();
log.debug("设备服务器,channelRead0:{},{}", channelId, HexUtil.bytes2hex(protocol.getContent()));
/*
TODO:
1.透传前先进行鉴权
2.鉴权通过后,创建桥接客户端,非鉴权消息全部放行
3.未鉴权的不能进行透传,强制下线
*/
byte cmd = protocol.getCmd();
int cmdInt = cmd & 0xFF;
boolean auth = false;
if (cmdInt == Consts.CMD_LICENSE) {
auth = handlerCheckAuth(channel, remoteIp, remotePort, protocol);
} else {
auth = handlerCheckAuthStatus(channel);
if (auth) {
handlerForward(channel, protocol);
}
}
//TODO 以下为正式代码
if (auth == false) {
channel.close();
}
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelRegistered(ctx);
log.debug("设备服务器,channelRegistered:{}", ctx.channel().id().asLongText());
}
@Override
public synchronized void channelActive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelActive(ctx);
log.debug("设备服务器,channelActive:{}", ctx.channel().id().asLongText());
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelInactive(ctx);
SocketChannel channel = (SocketChannel) ctx.channel();
String channelId = channel.id().asLongText();
log.debug("设备服务器,channelInactive:{}", channelId);
DeviceClientInactiveEvent deviceClientInactiveEvent = new DeviceClientInactiveEvent();
deviceClientInactiveEvent.setChannelId(channelId);
eventPublisher.publishEvent(deviceClientInactiveEvent);
ctx.close();
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelReadComplete(ctx);
log.debug("设备服务器,channelReadComplete:{}", ctx.channel().id().asLongText());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception{
// TODO Auto-generated method stub
super.exceptionCaught(ctx, cause);
log.debug("设备服务器,exceptionCaught:{}", ctx.channel().id().asLongText());
ctx.close();
}
private boolean handlerCheckAuth(SocketChannel channel, String remoteIp, int remotePort, DeviceProtocol protocol) {
//TODO 正式代码要放开
byte[] bytes = safety.decodeExtendedPayload(protocol.getContent(), 0, protocol.getContent().length);
if (bytes == null) {
return false;
}
String decodeInfo = CommonUtil.bytesToStr(bytes);
if (decodeInfo == null) {
return false;
}
JSONObject jsonObject = JSON.parseObject(decodeInfo);
String appId = jsonObject.getString("app_id");
String sn = jsonObject.getString("sn");
String sign = jsonObject.getString("sign");
AuthManager authManager = SpringUtil.getBean(AuthManager.class);
boolean license = authManager.auth(appId, sn, sign);
log.info("设备鉴权信息和结果,{},{},{},{} ", appId, sn, sign, license);
String channelId = channel.id().asLongText();
if (license) {
SessionContext session = new SessionContext();
session.setRemoteIp(remoteIp);
session.setRemotePort(remotePort);
session.setAppId(appId);
session.setSn(sn);
session.setChannelId(channelId);
session.setClientChannel(channel);
session.setAuthStatus(true);
session.setStatus(Consts.DEVICE_STATE_ONLINE);
session.setOnline(CommonUtil.getSystemTime());
DeviceManager deviceManager = SpringUtil.getBean(DeviceManager.class);
deviceManager.putSession(appId, session);
//TODO 创建透传的客户端
CreateForwarClientEvent event = new CreateForwarClientEvent();
event.setAppId(appId);
eventPublisher.publishEvent(event);
}
return license;
}
private boolean handlerCheckAuthStatus(SocketChannel channel) {
String channelId = channel.id().asLongText();
DeviceManager deviceManager = SpringUtil.getBean(DeviceManager.class);
return deviceManager.getAuthStatusByChannelId(channelId);
}
private void handlerForward(SocketChannel channel, DeviceProtocol protocol) {
String channelId = channel.id().asLongText();
ForwardClientRequestEvent forwardClientRequestEvent = new ForwardClientRequestEvent();
forwardClientRequestEvent.setDeviceChannelId(channelId);
forwardClientRequestEvent.setProtocol(protocol);
eventPublisher.publishEvent(forwardClientRequestEvent);
}
}
package iot.sixiang.iot_diagnose.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel("告警实体类")
public class Alarm {
private static final long serialVersionUID = 1L;
@TableId(type = IdType.AUTO)
@ApiModelProperty("主键Id")
private Integer id;
@ApiModelProperty("告警类型Id")
private int typeId;
@ApiModelProperty("告警标题")
private String title;
@ApiModelProperty("告警内容")
private String content;
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
@ApiModelProperty("告警创建时间")
private Date createTime;
}
package iot.sixiang.iot_diagnose.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
*
* </p>
*
* @author m33
* @since 2022-06-10
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel("告警已读实体类")
public class AlarmRead implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 告警已读唯一id
*/
@TableId(type = IdType.AUTO)
@ApiModelProperty("主键Id")
private Integer id;
/**
* 告警id
*/
@ApiModelProperty("告警Id")
private int alarmId;
/**
* 告警类型id
*/
@ApiModelProperty("告警类型Id")
private int typeId;
/**
* 告警标题
*/
@ApiModelProperty("告警标题")
private String title;
/**
* 告警内容
*/
@ApiModelProperty("告警内容")
private String content;
/**
* 创建时间
*/
@ApiModelProperty("创建时间")
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 阅读用户id
*/
@ApiModelProperty("阅读用户Id")
private Integer userId;
}
package iot.sixiang.iot_diagnose.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* <p>
*
* </p>
*
* @author m33
* @since 2022-06-10
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel("告警类型实体类")
public class AlarmType implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 告警类型id
*/
@ApiModelProperty("主键Id")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 等级
*/
@ApiModelProperty("告警等级")
private Integer level;
/**
* 等级描述
*/
@ApiModelProperty("等级描述")
private String levelDescribe;
}
package iot.sixiang.iot_diagnose.entity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
*
* </p>
*
* @author m33
* @since 2022-06-09
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel("应用实体类")
public class Apply implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("应用Id")
private String appId;
@ApiModelProperty("应用名")
private String appName;
@ApiModelProperty("应用key")
private String appKey;
@ApiModelProperty("用户Id")
private Integer userId;
@ApiModelProperty("创建时间")
private Date createTime;
@ApiModelProperty("更新时间")
private Date updateTime;
}
package iot.sixiang.iot_diagnose.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
*
* </p>
*
* @author m33
* @since 2022-06-08
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel("设备实体类")
public class Device implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("主键Id")
@TableId(type = IdType.AUTO)
private Integer deviceId;
@ApiModelProperty("设备编号")
private String sn;
@ApiModelProperty("应用Id")
private String appId;
@ApiModelProperty("创建时间")
private Date createTime;
@ApiModelProperty("更新时间")
private Date updateTime;
}
package iot.sixiang.iot_diagnose.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
*
* </p>
*
* @author m33
* @since 2022-06-15
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class DeviceBlack implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
@ApiModelProperty("主键Id")
private Integer id;
@ApiModelProperty("设备Id")
private Integer deviceId;
@ApiModelProperty("创建时间")
private Date createTime;
}
package iot.sixiang.iot_diagnose.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.time.LocalDate;
/**
* <p>
*
* </p>
*
* @author m33
* @since 2022-06-10
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel("运维实体类")
public class Monitor implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键id
*/
@ApiModelProperty("主键Id")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 年月日
*/
@ApiModelProperty("日期")
private LocalDate date;
/**
* 时
*/
@ApiModelProperty("小时")
private Integer hour;
/**
* 在线数量
*/
@ApiModelProperty("在线数量")
private Integer count;
}
package iot.sixiang.iot_diagnose.entity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* <p>
*
* </p>
*
* @author m33
* @since 2022-06-06
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel("服务实体类")
public class Server implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("服务Ip")
private String serverIp;
@ApiModelProperty("端口")
private Integer port;
}
package iot.sixiang.iot_diagnose.event;
import lombok.Data;
@Data
public abstract class BaseEvent {
}
package iot.sixiang.iot_diagnose.event;
import lombok.Data;
@Data
public class CreateForwarClientEvent extends BaseEvent {
private String appId;
}
package iot.sixiang.iot_diagnose.event;
import iot.sixiang.iot_diagnose.balance.BalanceManager;
import iot.sixiang.iot_diagnose.entity.Server;
import iot.sixiang.iot_diagnose.forward.ForwardManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class CreateForwarClientEventHandler {
@Autowired
ForwardManager forwardManager;
@Autowired
EventPublisher eventPublisher;
@Autowired
BalanceManager balanceManager;
public CreateForwarClientEventHandler() {
}
@EventListener
public void handlerEvent(CreateForwarClientEvent event) {
String appId = event.getAppId();
Server balanceServer = balanceManager.getBalanceServer();
if (balanceServer != null) {
String serverIp = balanceServer.getServerIp();
Integer port = balanceServer.getPort();
forwardManager.startTcpClient(serverIp, port, appId);
} else {
log.error("balanceServer is null");
}
}
}
package iot.sixiang.iot_diagnose.event;
import lombok.Data;
@Data
public class DeviceClientBeForcedOfflineEvent extends BaseEvent {
private String appId;
}
package iot.sixiang.iot_diagnose.event;
import io.netty.channel.socket.SocketChannel;
import iot.sixiang.iot_diagnose.device.DeviceManager;
import iot.sixiang.iot_diagnose.model.SessionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class DeviceClientBeForcedOfflineEventHandler {
@Autowired
DeviceManager deviceManager;
public DeviceClientBeForcedOfflineEventHandler() {
}
@EventListener
public void handlerEvent(DeviceClientBeForcedOfflineEvent event) {
String appId = event.getAppId();
SessionContext deviceSessionContext = deviceManager.getSessionContextByAppId(appId);
if (deviceSessionContext != null) {
SocketChannel deviceClientChannel = deviceSessionContext.getClientChannel();
if (deviceClientChannel != null) {
deviceClientChannel.close();
log.debug("device client be forced offline success ..." + appId);
}
} else {
log.debug("device client be forced offline undo ..." + appId);
}
}
}
package iot.sixiang.iot_diagnose.event;
import lombok.Data;
@Data
public class DeviceClientInactiveEvent extends BaseEvent {
String channelId;
}
package iot.sixiang.iot_diagnose.event;
import iot.sixiang.iot_diagnose.device.DeviceManager;
import iot.sixiang.iot_diagnose.model.SessionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class DeviceClientInactiveEventHandler {
@Autowired
DeviceManager deviceManager;
@Autowired
EventPublisher eventPublisher;
public DeviceClientInactiveEventHandler() {
}
@EventListener
public void handlerEvent(DeviceClientInactiveEvent event) {
String channelId = event.getChannelId();
SessionContext session = deviceManager.getSessionByChannelId(channelId);
if (session == null) {
log.debug("device client inactive undo ...");
return;
} else {
String appId = session.getAppId();
// boolean result = deviceManager.removeSessionByChannelId(channelId);
boolean result = deviceManager.changeSessionOffline(channelId);
if (result) {
// TODO device client 离线需要强制中断该设备对应的forward client
ForwardClientBeForcedOfflineEvent forwardClientBeForcedOfflineEvent = new ForwardClientBeForcedOfflineEvent();
forwardClientBeForcedOfflineEvent.setAppId(appId);
eventPublisher.publishEvent(forwardClientBeForcedOfflineEvent);
log.debug("device client inactive success ...");
}
}
}
}
package iot.sixiang.iot_diagnose.event;
import iot.sixiang.iot_diagnose.device.DeviceProtocol;
import lombok.Data;
@Data
public class DeviceClientLicenseEvent extends BaseEvent {
private String appId;
private DeviceProtocol protocol;
}
package iot.sixiang.iot_diagnose.event;
import iot.sixiang.iot_diagnose.device.DeviceManager;
import iot.sixiang.iot_diagnose.device.DeviceProtocol;
import iot.sixiang.iot_diagnose.model.SessionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class DeviceClientLicenseEventHandler {
@Autowired
DeviceManager deviceManager;
@Autowired
EventPublisher eventPublisher;
public DeviceClientLicenseEventHandler() {
}
@EventListener
public void handlerEvent(DeviceClientLicenseEvent event) {
String appId = event.getAppId();
DeviceProtocol protocol = event.getProtocol();
SessionContext session = deviceManager.getSessionContextByAppId(appId);
if (session == null) {
log.debug("device client license undo ...");
return;
} else {
session.getClientChannel().writeAndFlush(protocol);
log.debug("device client license success ...");
}
}
}
package iot.sixiang.iot_diagnose.event;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class EventPublisher {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
public EventPublisher() {
log.debug("EventPublisher init");
}
public void publishEvent(BaseEvent event) {
applicationEventPublisher.publishEvent(event);
}
}
package iot.sixiang.iot_diagnose.event;
import lombok.Data;
@Data
public class ForwardClientBeForcedOfflineEvent extends BaseEvent {
private String appId;
}
package iot.sixiang.iot_diagnose.event;
import io.netty.channel.socket.SocketChannel;
import iot.sixiang.iot_diagnose.forward.ForwardManager;
import iot.sixiang.iot_diagnose.model.SessionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class ForwardClientBeForcedOfflineEventHandler {
@Autowired
ForwardManager forwardManager;
public ForwardClientBeForcedOfflineEventHandler() {
}
@EventListener
public void handlerEvent(ForwardClientBeForcedOfflineEvent event) {
String appId = event.getAppId();
SessionContext forwardSessionContext = forwardManager.getSessionContextByAppId(appId);
if (forwardSessionContext != null) {
SocketChannel forwardClientChannel = forwardSessionContext.getClientChannel();
if (forwardClientChannel != null) {
forwardClientChannel.close();
log.debug("forward client be forced offline success ..." + appId);
}
} else {
log.debug("forward client be forced offline undo ..." + appId);
}
}
}
package iot.sixiang.iot_diagnose.event;
import io.netty.channel.socket.SocketChannel;
import lombok.Data;
@Data
public class ForwardClientConnectEvent extends BaseEvent {
private String appId;
private String channelId;
private SocketChannel channel;
}
package iot.sixiang.iot_diagnose.event;
import io.netty.channel.socket.SocketChannel;
import iot.sixiang.iot_diagnose.forward.ForwardManager;
import iot.sixiang.iot_diagnose.model.SessionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class ForwardClientConnectEventHandler {
@Autowired
ForwardManager forwardManager;
@Autowired
EventPublisher eventPublisher;
public ForwardClientConnectEventHandler() {
}
@EventListener
public void handlerEvent(ForwardClientConnectEvent event) {
String appId = event.getAppId();
String channelId = event.getChannelId();
SocketChannel channel = event.getChannel();
SessionContext session = new SessionContext();
// session.setRemoteIp(remoteIp);
// session.setRemotePort(remotePort);
session.setAppId(appId);
// session.setAppKey(appKey);
// session.setToken(token);
session.setChannelId(channelId);
session.setClientChannel(channel);
forwardManager.putSession(appId, session);
log.debug("forward client connect:" + event);
}
}
package iot.sixiang.iot_diagnose.event;
import lombok.Data;
@Data
public class ForwardClientInactiveEvent extends BaseEvent {
String channelId;
}
package iot.sixiang.iot_diagnose.event;
import iot.sixiang.iot_diagnose.device.DeviceManager;
import iot.sixiang.iot_diagnose.forward.ForwardManager;
import iot.sixiang.iot_diagnose.model.SessionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class ForwardClientInactiveEventHandler {
@Autowired
DeviceManager deviceManager;
@Autowired
ForwardManager forwardManager;
@Autowired
EventPublisher eventPublisher;
public ForwardClientInactiveEventHandler() {
}
@EventListener
public void handlerEvent(ForwardClientInactiveEvent event) {
String channelId = event.getChannelId();
SessionContext session = forwardManager.getSessionByChannelId(channelId);
if (session == null) {
log.debug("forward client inactive undo ...");
return;
} else {
String appId = session.getAppId();
boolean result = forwardManager.removeSessionByChannelId(channelId);
if (result) {
// TODO forward client 离线需要强制中断该设备对应的 device client
DeviceClientBeForcedOfflineEvent deviceClientBeForcedOfflineEvent = new DeviceClientBeForcedOfflineEvent();
deviceClientBeForcedOfflineEvent.setAppId(appId);
eventPublisher.publishEvent(deviceClientBeForcedOfflineEvent);
log.debug("forward client inactive success ...");
}
}
}
}
package iot.sixiang.iot_diagnose.event;
import iot.sixiang.iot_diagnose.device.DeviceProtocol;
import lombok.Data;
@Data
public class ForwardClientRequestEvent extends BaseEvent {
private String appId;
private String deviceChannelId;
private DeviceProtocol protocol;
}
\ No newline at end of file
package iot.sixiang.iot_diagnose.event;
import io.netty.channel.socket.SocketChannel;
import iot.sixiang.iot_diagnose.device.DeviceManager;
import iot.sixiang.iot_diagnose.device.DeviceProtocol;
import iot.sixiang.iot_diagnose.forward.ForwardManager;
import iot.sixiang.iot_diagnose.model.SessionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class ForwardClientRequestEventHandler {
@Autowired
DeviceManager deviceManager;
@Autowired
ForwardManager forwardManager;
@Autowired
EventPublisher eventPublisher;
public ForwardClientRequestEventHandler() {
}
@EventListener
public void handlerEvent(ForwardClientRequestEvent event) {
String deviceChannelId = event.getDeviceChannelId();
DeviceProtocol protocol = event.getProtocol();
SessionContext deviceSessionContext = deviceManager.getSessionByChannelId(deviceChannelId);
String appId = deviceSessionContext.getAppId();
SessionContext forwardSessionContext = forwardManager.getSessionContextByAppId(appId);
log.debug("forward client request:" + appId + "," + forwardSessionContext);
SocketChannel clientChannel = forwardSessionContext.getClientChannel();
clientChannel.writeAndFlush(protocol);
}
}
package iot.sixiang.iot_diagnose.event;
import io.netty.channel.socket.SocketChannel;
import iot.sixiang.iot_diagnose.device.DeviceProtocol;
import lombok.Data;
@Data
public class ForwardMessageResponseEvent extends BaseEvent {
// private String appId;
private String channelId;
private SocketChannel channel;
private DeviceProtocol protocol;
}
package iot.sixiang.iot_diagnose.event;
import io.netty.channel.socket.SocketChannel;
import iot.sixiang.iot_diagnose.device.DeviceManager;
import iot.sixiang.iot_diagnose.device.DeviceProtocol;
import iot.sixiang.iot_diagnose.forward.ForwardManager;
import iot.sixiang.iot_diagnose.model.SessionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class ForwardMessageResponseEventHandler {
@Autowired
DeviceManager deviceManager;
@Autowired
ForwardManager forwardManager;
@Autowired
EventPublisher eventPublisher;
public ForwardMessageResponseEventHandler() {
}
@EventListener
public void handlerEvent(ForwardMessageResponseEvent event) {
String channelId = event.getChannelId();
SocketChannel channel = event.getChannel();
DeviceProtocol protocol = event.getProtocol();
SessionContext forwardSessionContext = forwardManager.getSessionByChannelId(channelId);
String appId = forwardSessionContext.getAppId();
SessionContext deviceSessionContext = deviceManager.getSessionContextByAppId(appId);
if (deviceSessionContext != null) {
SocketChannel deviceClientChannel = deviceSessionContext.getClientChannel();
log.debug("forward client response..." + appId + ",forward session:" + deviceSessionContext);
deviceClientChannel.writeAndFlush(protocol);
} else {
log.debug("forward client response undo ..." + appId);
}
}
}
package iot.sixiang.iot_diagnose.event;
import io.netty.channel.socket.SocketChannel;
import iot.sixiang.iot_diagnose.device.DeviceProtocol;
import lombok.Data;
@Data
public class OperateSAMStatusRequestEvent extends BaseEvent {
private SocketChannel channel;
private DeviceProtocol protocol;
}
package iot.sixiang.iot_diagnose.event;
import io.netty.channel.socket.SocketChannel;
import iot.sixiang.iot_diagnose.device.DeviceProtocol;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class OperateSAMStatusRequestEventHandler {
public OperateSAMStatusRequestEventHandler() {
}
@EventListener
public void handlerEvent(OperateSAMStatusRequestEvent event) {
SocketChannel channel = event.getChannel();
DeviceProtocol protocol = event.getProtocol();
channel.writeAndFlush(protocol);
}
}
package iot.sixiang.iot_diagnose.event;
import iot.sixiang.iot_diagnose.device.DeviceProtocol;
import lombok.Data;
/**
* Created by m33 on 2022/6/9 21:38
*/
@Data
public class OperateSAMStatusResponseEvent extends BaseEvent {
private String ip;
private DeviceProtocol protocol;
}
package iot.sixiang.iot_diagnose.event;
import com.alibaba.fastjson.JSONObject;
import iot.sixiang.iot_diagnose.device.DeviceProtocol;
import iot.sixiang.iot_diagnose.model.SamInfo;
import iot.sixiang.iot_diagnose.model.SamMonitor;
import iot.sixiang.iot_diagnose.operate.OperateManager;
import iot.sixiang.iot_diagnose.service.AlarmService;
import iot.sixiang.iot_diagnose.util.CommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* Created by m33 on 2022/6/9 21:39
*/
@Component
@Slf4j
public class OperateSAMStatusResponseEventHandler {
@Autowired
public OperateManager operateManager;
@Autowired
private AlarmService alarmService;
public OperateSAMStatusResponseEventHandler() {
}
@EventListener
public void handlerEvent(OperateSAMStatusResponseEvent event) {
DeviceProtocol protocol = event.getProtocol();
String serverIp = event.getIp();
String jsonOperateStatus = CommonUtil.bytesToStr(protocol.getContent());
if (jsonOperateStatus == null) {
log.warn("SAM的参数为空或出现异常");
return;
}
List<SamInfo> samInfoList = JSONObject.parseArray(jsonOperateStatus, SamInfo.class);
int samCount = samInfoList.size();
int onlineCount = 0;
for (SamInfo samInfo : samInfoList) {
if (samInfo.getStatus() == 2 || samInfo.getStatus() == 4) {
onlineCount++;
} else {
int index = samInfo.getIndex();
int typeId = 2;
String title = "SAM故障";
String content = "index为" + index + "的SAM发生故障";
alarmService.addAlarm(typeId,title,content);
}
}
SamMonitor samMonitor = new SamMonitor();
samMonitor.setServerIp(serverIp);
samMonitor.setOnlineCount(onlineCount);
samMonitor.setSamCount(samCount);
operateManager.putSamMonitorMap(serverIp, samMonitor);
if (onlineCount / samCount > 0.7) {
int typeId = 3;
String title = "SAM不足";
String content = "当前在线客户端已超过70%";
alarmService.addAlarm(typeId,title,content);
}
}
}
package iot.sixiang.iot_diagnose.forward;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import io.netty.util.concurrent.EventExecutorGroup;
import iot.sixiang.iot_diagnose.consts.Consts;
import iot.sixiang.iot_diagnose.net.BaseChannelInitializer;
public class ForwardChannelInitializer extends BaseChannelInitializer {
private ForwardClientHandler handler;
static final EventExecutorGroup workGroup = new DefaultEventExecutorGroup(Consts.FORWARD_THREAD_NUM);
public ForwardChannelInitializer(ForwardClientHandler handler) {
this.handler = handler;
}
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast("decoder", new ForwardDecoder());
ch.pipeline().addLast("encoder", new ForwardEncoder());
ch.pipeline().addLast(workGroup, "handler", handler);
}
}
package iot.sixiang.iot_diagnose.forward;
import iot.sixiang.iot_diagnose.net.TcpClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class ForwardClient {
private TcpClient client = null;
private ForwardChannelInitializer channelInitializer;
@Autowired
ForwardClientHandler handler;
public ForwardClient() {
}
public void startTcp(String host, int port, String appId) {
log.debug("桥接客户端,开始连接桥接服务:{},{},{}", host, port, appId);
ForwardConnectionListener listener = new ForwardConnectionListener();
listener.setAppId(appId);
listener.setHost(host);
listener.setPort(port);
channelInitializer = new ForwardChannelInitializer(handler);
client = new TcpClient(host, port, channelInitializer, listener);
client.start();
}
}
package iot.sixiang.iot_diagnose.forward;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.SocketChannel;
import iot.sixiang.iot_diagnose.device.DeviceProtocol;
import iot.sixiang.iot_diagnose.event.EventPublisher;
import iot.sixiang.iot_diagnose.event.ForwardClientInactiveEvent;
import iot.sixiang.iot_diagnose.event.ForwardMessageResponseEvent;
import iot.sixiang.iot_diagnose.util.HexUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@ChannelHandler.Sharable
@Slf4j
public class ForwardClientHandler extends SimpleChannelInboundHandler<Object> {
@Autowired
EventPublisher eventPublisher;
public ForwardClientHandler() {
super();
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg){
// TODO Auto-generated method stub
// TODO 中转客户端收到消息后,将消息原封不动的发送给设备客户端
SocketChannel channel = (SocketChannel) ctx.channel();
DeviceProtocol protocol = (DeviceProtocol) msg;
String channelId = channel.id().asLongText();
log.debug("桥接客户端,channelRead0:{},{}", channelId, HexUtil.bytes2hex(protocol.getContent()));
ForwardMessageResponseEvent forwardMessageResponseEvent = new ForwardMessageResponseEvent();
forwardMessageResponseEvent.setChannelId(channelId);
forwardMessageResponseEvent.setChannel(channel);
forwardMessageResponseEvent.setProtocol(protocol);
eventPublisher.publishEvent(forwardMessageResponseEvent);
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelRegistered(ctx);
log.debug("桥接客户端,channelRegistered:{}", ctx.channel().id().asLongText());
}
@Override
public synchronized void channelActive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelActive(ctx);
log.debug("桥接客户端,channelActive:{}", ctx.channel().id().asLongText());
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelInactive(ctx);
SocketChannel channel = (SocketChannel) ctx.channel();
String channelId = channel.id().asLongText();
log.debug("桥接客户端,channelInactive:{}", channelId);
ForwardClientInactiveEvent forwardClientInactiveEvent = new ForwardClientInactiveEvent();
forwardClientInactiveEvent.setChannelId(channelId);
eventPublisher.publishEvent(forwardClientInactiveEvent);
ctx.close();
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelReadComplete(ctx);
log.debug("桥接客户端,channelReadComplete:{}", ctx.channel().id().asLongText());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// TODO Auto-generated method stub
super.exceptionCaught(ctx, cause);
log.debug("桥接客户端,exceptionCaught:{}", ctx.channel().id().asLongText());
ctx.close();
}
@Override
public synchronized void userEventTriggered(ChannelHandlerContext ctx, Object obj) {
log.debug("桥接客户端,userEventTriggered:{}", ctx.channel().id().asLongText());
}
}
package iot.sixiang.iot_diagnose.forward;
import io.netty.channel.ChannelFuture;
import io.netty.channel.socket.SocketChannel;
import iot.sixiang.iot_diagnose.device.DeviceProtocol;
import iot.sixiang.iot_diagnose.event.DeviceClientBeForcedOfflineEvent;
import iot.sixiang.iot_diagnose.event.DeviceClientLicenseEvent;
import iot.sixiang.iot_diagnose.event.EventPublisher;
import iot.sixiang.iot_diagnose.event.ForwardClientConnectEvent;
import iot.sixiang.iot_diagnose.net.BaseConnectionListener;
import iot.sixiang.iot_diagnose.operate.OperateManager;
import iot.sixiang.iot_diagnose.service.AlarmService;
import iot.sixiang.iot_diagnose.util.SpringUtil;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ForwardConnectionListener extends BaseConnectionListener {
@Override
public void operationComplete(ChannelFuture channelFuture) {
AlarmService alarmService = SpringUtil.getBean(AlarmService.class);
if (!channelFuture.isSuccess()) {
//TODO 失败进行告警
log.debug("桥接客户端,连接服务器失败:{},{},{}", this.host, this.port, this.appId);
int typeId = 1;
String title = "连接服器失败";
String content = "连接服务器:" + this.host + ":" + this.port + "失败";
alarmService.addAlarm(typeId, title, content);
//TODO forward client连接失败,则强制踢掉设备客户端
DeviceClientBeForcedOfflineEvent deviceClientBeForcedOfflineEvent = new DeviceClientBeForcedOfflineEvent();
deviceClientBeForcedOfflineEvent.setAppId(this.appId);
EventPublisher eventPublisher = SpringUtil.getBean(EventPublisher.class);
eventPublisher.publishEvent(deviceClientBeForcedOfflineEvent);
} else {
log.debug("桥接客户端,连接服务器成功:{},{},{}", this.host, this.port, this.appId);
OperateManager operateManager = SpringUtil.getBean(OperateManager.class);
operateManager.autoIncrement();
SocketChannel channel = (SocketChannel) channelFuture.channel();
String channelId = channel.id().asLongText();
ForwardClientConnectEvent forwardClientConnectEvent = new ForwardClientConnectEvent();
forwardClientConnectEvent.setAppId(this.appId);
forwardClientConnectEvent.setChannelId(channelId);
forwardClientConnectEvent.setChannel(channel);
EventPublisher eventPublisher = SpringUtil.getBean(EventPublisher.class);
eventPublisher.publishEvent(forwardClientConnectEvent);
short stx = 21930;
byte ack = 0x0;
int len = 3;
byte cmd = 0x1;
byte[] content = new byte[1];
content[0] = 0x7e;
byte end = 0x1;
DeviceProtocol protocol = new DeviceProtocol(stx, len, cmd, ack, content, end);
DeviceClientLicenseEvent deviceClientLicenseEvent = new DeviceClientLicenseEvent();
deviceClientLicenseEvent.setAppId(appId);
deviceClientLicenseEvent.setProtocol(protocol);
eventPublisher.publishEvent(deviceClientLicenseEvent);
}
}
}
package iot.sixiang.iot_diagnose.forward;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import iot.sixiang.iot_diagnose.device.DeviceProtocol;
import iot.sixiang.iot_diagnose.util.Util;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
@Slf4j
public class ForwardDecoder extends ByteToMessageDecoder {
public final int BASE_LENGTH = 2 + 2 + 1 + 1;
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) {
// 可读长度必须大于等于基本长度
byte[] packet = new byte[buffer.readableBytes()];
buffer.readBytes(packet);
buffer.resetReaderIndex();
Util.DEBUG_HEX("SERVER -> IN", packet, packet.length);
if (buffer.readableBytes() < BASE_LENGTH) {
return;
}
buffer.markReaderIndex();
short stx = buffer.readShort();//55AA->21930
short len = buffer.readShortLE();
byte cmd = buffer.readByte();
byte ack = buffer.readByte();////stx:21930,len:52,cmd:-112,ack:0
int real_len = len;//注意,透传前已经去掉了END一个字符
int cmd_ack_len = 2;
if (buffer.readableBytes() < real_len - cmd_ack_len + 1) {
buffer.resetReaderIndex();
return;
}
// buffer.resetReaderIndex();//复位
// 读取data数据
byte[] content = new byte[real_len - cmd_ack_len];
buffer.readBytes(content);
byte end = buffer.readByte();
DeviceProtocol protocol = new DeviceProtocol(stx, real_len, cmd, ack, content, end);
out.add(protocol);
}
}
\ No newline at end of file
package iot.sixiang.iot_diagnose.forward;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import iot.sixiang.iot_diagnose.device.DeviceProtocol;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ForwardEncoder extends MessageToByteEncoder<DeviceProtocol> {
@Override
protected void encode(ChannelHandlerContext tcx, DeviceProtocol msg, ByteBuf out) {
out.writeShort(msg.getStx());
out.writeShortLE(msg.getLen());
out.writeByte(msg.getCmd());
out.writeByte(msg.getAck());
if (msg.getContent() != null) {
out.writeBytes(msg.getContent());
}
out.writeByte(msg.getEnd());
}
}
package iot.sixiang.iot_diagnose.forward;
import iot.sixiang.iot_diagnose.consts.Consts;
import iot.sixiang.iot_diagnose.model.SessionContext;
import iot.sixiang.iot_diagnose.model.vo.ServerStatusVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@Component(value = "forwardManager")
@Slf4j
public class ForwardManager {
@Autowired
public ForwardClient client;
private Map<String, SessionContext> sessionContexts = null;
public ForwardManager() {
sessionContexts = new HashMap<String, SessionContext>();
}
public void startTcpClient(String serviceIP,int port,String appId) {
client.startTcp(serviceIP, port,appId);
}
public synchronized void putSession(String appId, SessionContext session) {
sessionContexts.put(appId, session);
}
public SessionContext getSessionContextByAppId(String appId) {
return sessionContexts.get(appId);
}
public SessionContext getSessionByChannelId(String channelId) {
SessionContext session = null;
Iterator<Map.Entry<String, SessionContext>> it = sessionContexts.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, SessionContext> entry = it.next();
SessionContext targetSession = entry.getValue();
if (targetSession.getChannelId().equals(channelId)) {
return targetSession;
}
}
return session;
}
public synchronized boolean removeSessionByChannelId(String channelId) {
Iterator<Map.Entry<String, SessionContext>> it = sessionContexts.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, SessionContext> entry = it.next();
SessionContext targetSession = entry.getValue();
if (targetSession.getChannelId().equals(channelId)) {
it.remove();
return true;
}
}
return false;
}
public ServerStatusVo getServerStatus() {
ServerStatusVo vo = new ServerStatusVo();
int size = sessionContexts.size();
int statue = Consts.SERVICE_DX_STATUS_FLUENT;
if (size >= Consts.SERVICE_DX_THRESHOLD_NORMAL) {
statue = Consts.SERVICE_DX_STATUS_NORMAL;
} else if (size > Consts.SERVICE_DX_THRESHOLD_BUSY) {
statue = Consts.SERVICE_DX_STATUS_BUSY;
}
vo.setCount(size);
vo.setStatus(statue);
return vo;
}
}
\ No newline at end of file
package iot.sixiang.iot_diagnose.handler;
import iot.sixiang.iot_diagnose.model.BaseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* Created by m33 on 2022/6/9 11:01
*/
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
//指定出现什么异常执行这个方法
@ExceptionHandler(Exception.class)
@ResponseBody //为了返回数据
public BaseResult error(Exception e){
log.error("出现自定义异常,{}" + e.getMessage());
return BaseResult.serverException();
}
//自定义异常
@ExceptionHandler(IotLicenseException.class)
@ResponseBody//为了返回数据
public BaseResult error(IotLicenseException e){
log.error("出现自定义异常,{}" + e.getMsg());
return BaseResult.failed().setMsgValue(e.getMsg()).setCodeValue(e.getCode());
}
}
package iot.sixiang.iot_diagnose.handler;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Created by m33 on 2022/6/9 11:13
*/
@Data
@AllArgsConstructor //生成有参构造
@NoArgsConstructor //生成无参构造
public class IotLicenseException extends RuntimeException {
private long code;
private String msg;//异常信息
}
package iot.sixiang.iot_diagnose.idreader;
import iot.sixiang.iot_diagnose.util.CommonUtil;
import org.springframework.stereotype.Component;
@Component
public class Safety {
static {
System.load(CommonUtil.getLibFilePathByFileName("IdReaderSafetyLib"));
}
public native byte[] decodeExtendedPayload(byte[] data, int offset, int length);
}
\ No newline at end of file
package iot.sixiang.iot_diagnose.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import iot.sixiang.iot_diagnose.entity.Alarm;
import iot.sixiang.iot_diagnose.model.vo.AlarmVo;
import java.util.List;
public interface AlarmMapper extends BaseMapper<Alarm> {
boolean addAlarm(int typeId, String title, String content);
List<AlarmVo> getAlarmList(int userId);
}
package iot.sixiang.iot_diagnose.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import iot.sixiang.iot_diagnose.entity.AlarmRead;
/**
* <p>
* Mapper 接口
* </p>
*
* @author m33
* @since 2022-06-10
*/
public interface AlarmReadMapper extends BaseMapper<AlarmRead> {
boolean readAlarm(int alarmId, int typeId, String title, String content, int userId);
}
package iot.sixiang.iot_diagnose.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import iot.sixiang.iot_diagnose.entity.AlarmType;
/**
* <p>
* Mapper 接口
* </p>
*
* @author m33
* @since 2022-06-10
*/
public interface AlarmTypeMapper extends BaseMapper<AlarmType> {
}
package iot.sixiang.iot_diagnose.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import iot.sixiang.iot_diagnose.entity.Apply;
import iot.sixiang.iot_diagnose.model.vo.AppVo;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author m33
* @since 2022-06-09
*/
public interface ApplyMapper extends BaseMapper<Apply> {
boolean addApply(String appId, String appName, String appKey, int userId);
List<AppVo> getAppList(String appName);
Apply getApplyByAppName(String appName);
}
package iot.sixiang.iot_diagnose.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import iot.sixiang.iot_diagnose.entity.DeviceBlack;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author m33
* @since 2022-06-15
*/
public interface DeviceBlackMapper extends BaseMapper<DeviceBlack> {
boolean addDeviceBlack(int deviceId);
boolean deleteDeviceBlack(int deviceId);
List<DeviceBlack> getDeviceBlackList();
}
package iot.sixiang.iot_diagnose.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import iot.sixiang.iot_diagnose.entity.Device;
import iot.sixiang.iot_diagnose.model.vo.DeviceVo;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author m33
* @since 2022-06-08
*/
public interface DeviceMapper extends BaseMapper<Device> {
List<DeviceVo> getDeviceList(String appName, String userName);
boolean addDevice(String sn, String appId);
}
package iot.sixiang.iot_diagnose.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import iot.sixiang.iot_diagnose.entity.Monitor;
import java.time.LocalDate;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author m33
* @since 2022-06-10
*/
public interface MonitorMapper extends BaseMapper<Monitor> {
boolean addMonitor(LocalDate date, int hour, int count);
List<Monitor> getMonitorList(LocalDate localDate, LocalDate endDate);
}
package iot.sixiang.iot_diagnose.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import iot.sixiang.iot_diagnose.entity.Server;
/**
* <p>
* Mapper 接口
* </p>
*
* @author m33
* @since 2022-06-06
*/
public interface ServerMapper extends BaseMapper<Server> {
boolean deleteServer(String serverIp);
boolean addServer(String serverIp, int port);
boolean updateServer(String serverIp, int port);
}
package iot.sixiang.iot_diagnose.model;
import io.swagger.annotations.ApiModelProperty;
import iot.sixiang.iot_diagnose.consts.ResultCode;
//@Data
public class BaseResult {
@ApiModelProperty("状态码")
private long code;
@ApiModelProperty("信息")
private String msg;
public BaseResult(long code, String msg) {
super();
this.code = code;
this.msg = msg;
}
public BaseResult() {
super();
// TODO Auto-generated constructor stub
}
/**
* code = 200
* msg = 操作成功
* @return
*/
public static BaseResult success() {
return new BaseResult(ResultCode.SUCCESS.getCode(),ResultCode.SUCCESS.getMsg());
}
/**
* code = 400
* msg = 服务异常
* @return
*/
public static BaseResult serverException() {
return new BaseResult(ResultCode.SERVER_EXCEPTION.getCode(),ResultCode.SERVER_EXCEPTION.getMsg());
}
/**
* code = 401
* msg = 暂未登录或token已经过期
* @return
*/
public static BaseResult unauthorized() {
return new BaseResult(ResultCode.UNAUTHORIZED.getCode(),ResultCode.UNAUTHORIZED.getMsg());
}
/**
* code = 402
* msg = 参数校验失败
* @return
*/
public static BaseResult validate_failed() {
return new BaseResult(ResultCode.VALIDATE_FAILED.getCode(),ResultCode.VALIDATE_FAILED.getMsg());
}
/**
* code = 403
* msg = 操作失败(数据库增删改查等失败)
* @return
*/
public static BaseResult failed() {
return new BaseResult(ResultCode.FAILED.getCode(),ResultCode.FAILED.getMsg());
}
public BaseResult setCodeValue(long code) {
this.code = code;
return this;
}
public BaseResult setMsgValue(String message) {
this.msg = message;
return this;
}
public long getCode() {
return code;
}
public void setCode(long code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
package iot.sixiang.iot_diagnose.model;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
@Data
public class Device implements Serializable{
@ApiModelProperty("设备状态码")
private String device_code;
@ApiModelProperty("设备名")
private String device_name;
@ApiModelProperty("密码状态码")
private String pass_code;
@ApiModelProperty("设备状态 0:offline,1:online")
private int device_status;//0 offline,1 online
}
package iot.sixiang.iot_diagnose.model;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
public class PageInfoModel<T> {
@ApiModelProperty("总数")
private int total;
@ApiModelProperty("结果")
private List<T> result = new ArrayList<T>();
}
package iot.sixiang.iot_diagnose.model;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class PageResult<T> {
@ApiModelProperty("状态码")
private int code;
@ApiModelProperty("信息")
private String msg;
@ApiModelProperty("当前在第几页")
private int pageNo;
@ApiModelProperty("总页数")
private int pages;
@ApiModelProperty("总条数")
private int total;
@ApiModelProperty("返回结果")
private T record;
public PageResult(int code, String msg, int pageNo,int pages, int total, T record) {
super();
this.code = code;
this.msg = msg;
this.pageNo = pageNo;
this.pages = pages;
this.total = total;
this.record = record;
}
public PageResult() {
super();
// TODO Auto-generated constructor stub
}
}
package iot.sixiang.iot_diagnose.model;
import io.swagger.annotations.ApiModelProperty;
import iot.sixiang.iot_diagnose.consts.ResultCode;
import lombok.Data;
/**
* Title: ResResult
* Description: TODO
*
* @author m33
* @version V1.0
* @date 2022-06-08
*/
@Data
public class ResResult<T> {
@ApiModelProperty("状态码")
private long code;
@ApiModelProperty("信息")
private String msg;
@ApiModelProperty("返回结果")
private T record;
public ResResult(long code, String msg) {
super();
this.code = code;
this.msg = msg;
}
/**
* code = 200
* msg = 操作成功
*
* @return
*/
public static ResResult success() {
return new ResResult(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg());
}
/**
* code = 400
* msg = 服务异常
*
* @return
*/
public static ResResult serverException() {
return new ResResult(ResultCode.SERVER_EXCEPTION.getCode(), ResultCode.SERVER_EXCEPTION.getMsg());
}
/**
* code = 401
* msg = 暂未登录或token已经过期
*
* @return
*/
public static ResResult unauthorized() {
return new ResResult(ResultCode.UNAUTHORIZED.getCode(), ResultCode.UNAUTHORIZED.getMsg());
}
/**
* code = 402
* msg = 参数校验失败
*
* @return
*/
public static ResResult validate_failed() {
return new ResResult(ResultCode.VALIDATE_FAILED.getCode(), ResultCode.VALIDATE_FAILED.getMsg());
}
/**
* code = 403
* msg = 操作失败(数据库增删改查等失败)
*
* @return
*/
public static ResResult failed() {
return new ResResult(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg());
}
public ResResult setCodeValue(long code) {
this.code = code;
return this;
}
public ResResult setMsgValue(String message) {
this.msg = message;
return this;
}
public ResResult goRecord(T data) {
this.record = data;
return this;
}
}
package iot.sixiang.iot_diagnose.model;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* Created by m33 on 2022/6/9 20:34
*/
@Data
public class SamInfo {
@ApiModelProperty("SAM通道序号")
private int index;
@ApiModelProperty("SAM模组唯一识别码")
private String samid;
@ApiModelProperty("SAM模组状态")
private int status;
}
package iot.sixiang.iot_diagnose.model;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* Created by m33 on 2022/6/9 22:07
*/
@Data
public class SamMonitor {
@ApiModelProperty("服务Ip")
private String serverIp;
@ApiModelProperty("sam总数")
private int samCount;
@ApiModelProperty("在线数量")
private int onlineCount;
}
package iot.sixiang.iot_diagnose.model;
import io.netty.channel.socket.SocketChannel;
import lombok.Data;
@Data
public class SessionContext {
private String remoteIp;
private int remotePort;
private String appId;
private String appKey;
private String sn;
private boolean authStatus;//授权验证状态
private int status;//当前状态,0 offline,1 online
private String online;//上线时间
private String offline;//下线时间
private String channelId;
private SocketChannel clientChannel;
}
package iot.sixiang.iot_diagnose.model.vo;
import io.swagger.annotations.ApiModelProperty;
import iot.sixiang.iot_diagnose.entity.Alarm;
import lombok.Data;
/**
* Created by m33 on 2022/6/10 11:58
*/
@Data
public class AlarmVo extends Alarm {
@ApiModelProperty("警告等级")
private int level;
@ApiModelProperty("警告描述")
private String levelDescribe;
@ApiModelProperty("已读标记")
private int readFlag;
}
package iot.sixiang.iot_diagnose.model.vo;
import io.swagger.annotations.ApiModelProperty;
import iot.sixiang.iot_diagnose.entity.Apply;
import lombok.Data;
/**
* Created by m33 on 2022/6/9 16:50
*/
@Data
public class AppVo extends Apply {
@ApiModelProperty("设备数量")
public int deviceCount;
@ApiModelProperty("用户名")
public String userName;
@ApiModelProperty("公司名")
public String company;
@ApiModelProperty("设备编号")
public String sn;
@ApiModelProperty("设备Id")
public int deviceId;
}
package iot.sixiang.iot_diagnose.model.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class DeviceDetailVo extends DeviceVo {
@ApiModelProperty("当前状态,0 offline,1 online")
private int status;
@ApiModelProperty("上线时间")
private String online;
@ApiModelProperty("下线时间")
private String offline;
}
package iot.sixiang.iot_diagnose.model.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* Created by m33 on 2022/6/8 13:35
*/
@Data
public class DeviceVo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("设备Id")
private int deviceId;
@ApiModelProperty("应用名")
private String appName;
@ApiModelProperty("用户名")
private String userName;
@ApiModelProperty("设备编号")
private String sn;
@ApiModelProperty("设备状态 0:正常 1:禁用")
private int blackFlag;
@ApiModelProperty("创建时间")
private Date createTime;
@ApiModelProperty("更新时间")
private Date updateTime;
}
package iot.sixiang.iot_diagnose.model.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* Created by m33 on 2022/6/14 19:02
*/
@Data
public class QpsVo {
@ApiModelProperty("x轴")
private List<Integer> x;
@ApiModelProperty("y轴")
private List<Integer> y;
}
package iot.sixiang.iot_diagnose.model.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* Created by m33 on 2022/6/10 16:17
*/
@Data
public class ResourceVo {
@ApiModelProperty("用户名")
private String userName;
@ApiModelProperty("密码")
private String password;
@ApiModelProperty("公司名")
private String company;
@ApiModelProperty("应用名")
private String appName;
@ApiModelProperty("应用key")
private String appKey;
@ApiModelProperty("设备编号")
private String sn;
@ApiModelProperty("应用id")
private String appId;
}
\ No newline at end of file
package iot.sixiang.iot_diagnose.model.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* Created by m33 on 2022/6/14 18:56
*/
@Data
public class SamVo {
@ApiModelProperty("总Sam数量")
private int totalSamCount;
@ApiModelProperty("总在线数量")
private int totalOnlineCount;
}
package iot.sixiang.iot_diagnose.model.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
public class ServerStatusVo {
@ApiModelProperty("服务实时工作通道数量")
private int count;
@ApiModelProperty("诊断状态,通道数量小于100流畅,100-500正常,500以上拥挤")
private int status;
}
package iot.sixiang.iot_diagnose.net;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class BaseChannelInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// TODO Auto-generated method stub
log.info("重写了initChannel方法");
}
}
package iot.sixiang.iot_diagnose.net;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@Data
@Slf4j
public class BaseConnectionListener implements ChannelFutureListener {
public String appId;
public String host;
public int port;
@Override
public void operationComplete(ChannelFuture future) {
// TODO Auto-generated method stub
log.info("重写了operationComplete方法");
}
}
package iot.sixiang.iot_diagnose.net;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class TcpClient {
private int port;
private String host;
private BaseChannelInitializer channelInitializer;
private BaseConnectionListener connectionListener;
public TcpClient(String host, int port,BaseChannelInitializer channelInitializer,BaseConnectionListener connectionListener) {
this.host = host;
this.port = port;
this.channelInitializer = channelInitializer;
this.connectionListener = connectionListener;
}
public void start() {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
try {
bootstrap
.channel(NioSocketChannel.class)
.option(ChannelOption.SO_KEEPALIVE, true)
.group(eventLoopGroup)
.remoteAddress(host, port)
.handler(channelInitializer);
} catch (NullPointerException e) {
log.error(e.getMessage());
}catch (IllegalStateException ex) {
log.error(ex.getMessage());
}
ChannelFuture future = bootstrap.connect(host, port);
future.addListener(connectionListener);
}
});
thread.start();
}
}
package iot.sixiang.iot_diagnose.net;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class TcpServer {
private int port;
private BaseChannelInitializer channelInitializer;
public TcpServer(int port, BaseChannelInitializer channelInitializer) {
this.port = port;
this.channelInitializer = channelInitializer;
}
public void start() {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
//创建两个线程组 bossGroup、workerGroup
EventLoopGroup bossGroup = new NioEventLoopGroup(4);
EventLoopGroup workerGroup = new NioEventLoopGroup(4);
log.debug("Tcp服务,开始监听端口:{}",port);
//创建服务端的启动对象,设置参数
ServerBootstrap b = new ServerBootstrap();
//设置两个线程组boosGroup和workerGroup
b.group(bossGroup, workerGroup)
//设置服务端通道实现类型
.channel(NioServerSocketChannel.class)
// .handler(new LoggingHandler(LogLevel.INFO))
.childHandler(channelInitializer)
// 设置tcp缓冲区
.option(ChannelOption.SO_BACKLOG, 1024)
//设置保持活动连接状态
.childOption(ChannelOption.SO_KEEPALIVE, true);
ChannelFuture f;
try {
f = b.bind(port).sync();
f.channel().closeFuture().sync();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
log.error("Tcp服务异常,端口:{}", port);
} finally {
log.debug("Tcp服务,停止退出");
if (workerGroup != null) {
workerGroup.shutdownGracefully();
}
if (bossGroup != null) {
bossGroup.shutdownGracefully();
}
}
}
});
thread.start();
}
}
package iot.sixiang.iot_diagnose.operate;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import io.netty.util.concurrent.EventExecutorGroup;
import iot.sixiang.iot_diagnose.consts.Consts;
import iot.sixiang.iot_diagnose.net.BaseChannelInitializer;
public class OperateChannelInitializer extends BaseChannelInitializer {
private OperateClientHandler handler;
static final EventExecutorGroup workGroup = new DefaultEventExecutorGroup(Consts.OPERATE_THREAD_NUM);
public OperateChannelInitializer(OperateClientHandler handler) {
this.handler = handler;
}
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast("decoder", new OperateDecoder());
ch.pipeline().addLast("encoder", new OperateEncoder());
ch.pipeline().addLast(workGroup, "handler", handler);
}
}
package iot.sixiang.iot_diagnose.operate;
import iot.sixiang.iot_diagnose.net.TcpClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class OperateClient {
private TcpClient client = null;
private OperateChannelInitializer channelInitializer;
@Autowired
OperateClientHandler handler;
public OperateClient() {
}
public void startTcp(String host, int port) {
OperateConnectionListener listener = new OperateConnectionListener();
listener.setHost(host);
listener.setPort(port);
channelInitializer = new OperateChannelInitializer(handler);
client = new TcpClient(host, port, channelInitializer, listener);
client.start();
}
}
package iot.sixiang.iot_diagnose.operate;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import iot.sixiang.iot_diagnose.device.DeviceProtocol;
import iot.sixiang.iot_diagnose.event.EventPublisher;
import iot.sixiang.iot_diagnose.event.OperateSAMStatusResponseEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.net.InetSocketAddress;
@Component
@ChannelHandler.Sharable
@Slf4j
public class OperateClientHandler extends SimpleChannelInboundHandler<Object> {
@Autowired
EventPublisher eventPublisher;
public OperateClientHandler() {
super();
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
InetSocketAddress socketAddr = (InetSocketAddress) ctx.channel().remoteAddress();
String remoteIp = socketAddr.getHostString();
DeviceProtocol protocol = (DeviceProtocol) msg;
OperateSAMStatusResponseEvent event = new OperateSAMStatusResponseEvent();
event.setProtocol(protocol);
event.setIp(remoteIp);
eventPublisher.publishEvent(event);
}
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelRegistered(ctx);
log.debug("运维客户端,channelRegistered:{}", ctx.channel().id().asLongText());
}
@Override
public synchronized void channelActive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelActive(ctx);
log.debug("运维客户端,channelActive:{}", ctx.channel().id().asLongText());
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelInactive(ctx);
log.debug("运维客户端,channelInactive:{}", ctx.channel().id().asLongText());
ctx.close();
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// TODO Auto-generated method stub
super.channelReadComplete(ctx);
log.debug("运维客户端,channelReadComplete:{}", ctx.channel().id().asLongText());
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// TODO Auto-generated method stub
super.exceptionCaught(ctx, cause);
log.debug("运维客户端,exceptionCaught:{}", ctx.channel().id().asLongText());
ctx.close();
}
@Override
public synchronized void userEventTriggered(ChannelHandlerContext ctx, Object obj) {
log.debug("运维客户端,userEventTriggered:{}", ctx.channel().id().asLongText());
}
}
package iot.sixiang.iot_diagnose.operate;
import io.netty.channel.ChannelFuture;
import io.netty.channel.socket.SocketChannel;
import iot.sixiang.iot_diagnose.device.DeviceProtocol;
import iot.sixiang.iot_diagnose.event.EventPublisher;
import iot.sixiang.iot_diagnose.event.OperateSAMStatusRequestEvent;
import iot.sixiang.iot_diagnose.net.BaseConnectionListener;
import iot.sixiang.iot_diagnose.service.AlarmService;
import iot.sixiang.iot_diagnose.util.SpringUtil;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class OperateConnectionListener extends BaseConnectionListener {
@Override
public void operationComplete(ChannelFuture channelFuture) {
if (!channelFuture.isSuccess()) {
//TODO 失败进行告警
log.info("运维客户端,连接服务器失败:{},{}", this.host, this.port);
AlarmService alarmService = SpringUtil.getBean(AlarmService.class);
int typeId = 1;
String title = "连接服器失败";
String content = "连接服务器:" + this.host + ":" + this.port + "失败";
alarmService.addAlarm(typeId, title, content);
} else {
log.info("运维客户端,连接服务器成功:{},{}", this.host, this.port);
//TODO 查询SAM状态
OperateSAMStatusRequestEvent operateSAMStatusQueryEvent = new OperateSAMStatusRequestEvent();
short stx = 21930;
int len = 2;
byte cmd = 0x5f;
byte ack = 0x00;
byte end = 0x5f;
SocketChannel channel = (SocketChannel) channelFuture.channel();
DeviceProtocol protocol = new DeviceProtocol(stx, len, cmd, ack, null, end);
operateSAMStatusQueryEvent.setChannel(channel);
operateSAMStatusQueryEvent.setProtocol(protocol);
EventPublisher eventPublisher = SpringUtil.getBean(EventPublisher.class);
eventPublisher.publishEvent(operateSAMStatusQueryEvent);
}
}
}
package iot.sixiang.iot_diagnose.operate;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import iot.sixiang.iot_diagnose.device.DeviceProtocol;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
@Slf4j
public class OperateDecoder extends ByteToMessageDecoder {
public final int BASE_LENGTH = 2 + 2 + 1 + 1;
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) {
// 可读长度必须大于等于基本长度
if (buffer.readableBytes() < BASE_LENGTH) {
return;
}
buffer.markReaderIndex();
short stx = buffer.readShort();
short len = buffer.readShortLE();
byte cmd = buffer.readByte();
byte ack = buffer.readByte();
int real_len = len;
int cmd_ack_len = 2;
if (buffer.readableBytes() < real_len - cmd_ack_len + 1) {
buffer.resetReaderIndex();
return;
}
// 读取data数据
byte[] content = new byte[real_len - cmd_ack_len];
buffer.readBytes(content);
byte end = buffer.readByte();
DeviceProtocol protocol = new DeviceProtocol(stx, real_len, cmd, ack, content, end);
out.add(protocol);
}
}
\ No newline at end of file
package iot.sixiang.iot_diagnose.operate;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import iot.sixiang.iot_diagnose.device.DeviceProtocol;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class OperateEncoder extends MessageToByteEncoder<DeviceProtocol> {
@Override
protected void encode(ChannelHandlerContext tcx, DeviceProtocol msg, ByteBuf out) {
out.writeShort(msg.getStx());
out.writeShortLE(msg.getLen());
out.writeByte(msg.getCmd());
out.writeByte(msg.getAck());
if (msg.getContent() != null) {
out.writeBytes(msg.getContent());
}
out.writeByte(msg.getEnd());
}
}
package iot.sixiang.iot_diagnose.operate;
import iot.sixiang.iot_diagnose.entity.Server;
import iot.sixiang.iot_diagnose.model.SamMonitor;
import iot.sixiang.iot_diagnose.service.ServerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.*;
@Component
@Slf4j
public class OperateManager {
@Autowired
private ServerService serverService;
@Autowired
public OperateClient client;
private Map<String, Server> allServers = null;
private Map<String, SamMonitor> samMonitorMap = null;
private int count = 0;
public OperateManager() {
allServers = new HashMap<String, Server>();
samMonitorMap = new HashMap<>();
}
public synchronized Map<String, SamMonitor> getSamMonitorMap() {
return samMonitorMap;
}
public synchronized void putSamMonitorMap(String serverIp, SamMonitor samMonitor) {
samMonitorMap.put(serverIp, samMonitor);
}
public List<SamMonitor> getSamMonitorList() {
List<SamMonitor> result = new ArrayList<>();
if (samMonitorMap.size() > 0) {
samMonitorMap.entrySet().stream().sorted(Map.Entry.<String, SamMonitor>comparingByKey()).forEachOrdered(x -> result.add(x.getValue()));
}
return result;
}
public int getCount(){
return this.count;
}
public synchronized void clearCount() {
this.count = 0;
}
public synchronized void autoIncrement() {
this.count++;
}
@PostConstruct
public void init() {
List<Server> servers = serverService.getServerList(0, 20);
for (Server server : servers) {
String serverIp = server.getServerIp();
allServers.put(serverIp, server);
SamMonitor samMonitor = new SamMonitor();
samMonitor.setServerIp(serverIp);
samMonitor.setOnlineCount(0);
samMonitor.setSamCount(0);
this.putSamMonitorMap(serverIp, samMonitor);
}
// createProxyClient();
// test();
}
public void createProxyClient() {
Iterator<Map.Entry<String, Server>> iterator = allServers.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, Server> next = iterator.next();
Server server = next.getValue();
//TODO 创建运维客户端去查询相关的运维消息
String serverIp = server.getServerIp();
Integer port = server.getPort();
this.startTcpClient(serverIp, port);
}
}
private void test() {
String serverIp = "192.168.1.56";
int port = 18889;
// serverIp = "172.17.115.81";
// port = 777;
this.startTcpClient(serverIp, port);
}
public void startTcpClient(String serviceIP, int port) {
client.startTcp(serviceIP, port);
}
}
package iot.sixiang.iot_diagnose.service;
import com.baomidou.mybatisplus.extension.service.IService;
import iot.sixiang.iot_diagnose.entity.Alarm;
import iot.sixiang.iot_diagnose.model.vo.AlarmVo;
import java.util.List;
public interface AlarmService extends IService<Alarm> {
boolean addAlarm(int typeId, String title, String content);
List<AlarmVo> getAlarmList(int userId);
}
package iot.sixiang.iot_diagnose.service;
import com.baomidou.mybatisplus.extension.service.IService;
import iot.sixiang.iot_diagnose.entity.AlarmType;
/**
* <p>
* 服务类
* </p>
*
* @author m33
* @since 2022-06-10
*/
public interface AlarmTypeService extends IService<AlarmType> {
}
package iot.sixiang.iot_diagnose.service;
import com.baomidou.mybatisplus.extension.service.IService;
import iot.sixiang.iot_diagnose.entity.Apply;
import iot.sixiang.iot_diagnose.model.PageInfoModel;
import iot.sixiang.iot_diagnose.model.vo.AppVo;
/**
* <p>
* 服务类
* </p>
*
* @author m33
* @since 2022-06-09
*/
public interface ApplyService extends IService<Apply> {
boolean addApply(String appName, String appKey, int userId);
PageInfoModel<AppVo> getAppList(int pageNo, int pageSize, String appName);
}
package iot.sixiang.iot_diagnose.service;
import com.baomidou.mybatisplus.extension.service.IService;
import iot.sixiang.iot_diagnose.entity.DeviceBlack;
import iot.sixiang.iot_diagnose.model.PageInfoModel;
/**
* <p>
* 服务类
* </p>
*
* @author m33
* @since 2022-06-15
*/
public interface DeviceBlackService extends IService<DeviceBlack> {
boolean addDeviceBlack(int deviceId);
boolean deleteDeviceBlack(int deviceId);
PageInfoModel<DeviceBlack> getDeviceBlackList(int pageNo, int pageSize);
}
package iot.sixiang.iot_diagnose.service;
import com.baomidou.mybatisplus.extension.service.IService;
import iot.sixiang.iot_diagnose.entity.Device;
import iot.sixiang.iot_diagnose.model.PageInfoModel;
import iot.sixiang.iot_diagnose.model.vo.DeviceVo;
/**
* <p>
* 服务类
* </p>
*
* @author m33
* @since 2022-06-08
*/
public interface DeviceService extends IService<Device> {
PageInfoModel<DeviceVo> getDeviceList(int pageNo, int pageSize, String appName, String userName);
boolean addDevice(String appId, int count);
}
package iot.sixiang.iot_diagnose.service;
import com.baomidou.mybatisplus.extension.service.IService;
import iot.sixiang.iot_diagnose.entity.Monitor;
import java.util.HashMap;
import java.util.List;
/**
* <p>
* 服务类
* </p>
*
* @author m33
* @since 2022-06-10
*/
public interface MonitorService extends IService<Monitor> {
boolean addMonitor(int count);
HashMap<String,List<Integer>> getMonitorList(int type);
}
package iot.sixiang.iot_diagnose.service;
import com.baomidou.mybatisplus.extension.service.IService;
import iot.sixiang.iot_diagnose.entity.Server;
import java.util.List;
/**
* <p>
* 服务类
* </p>
*
* @author m33
* @since 2022-06-06
*/
public interface ServerService extends IService<Server> {
List<Server> getServerList(int pageNo, int pageSize);
boolean deleteServer(String serverIp);
boolean addServer(String serverIp, int port);
boolean updateServer(String serverIp, int port);
}
package iot.sixiang.iot_diagnose.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import iot.sixiang.iot_diagnose.consts.ResultCode;
import iot.sixiang.iot_diagnose.entity.Alarm;
import iot.sixiang.iot_diagnose.handler.IotLicenseException;
import iot.sixiang.iot_diagnose.mapper.AlarmMapper;
import iot.sixiang.iot_diagnose.model.vo.AlarmVo;
import iot.sixiang.iot_diagnose.service.AlarmService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements AlarmService {
@Resource
AlarmMapper alarmMapper;
@Override
public boolean addAlarm(int typeId, String title, String content) {
return alarmMapper.addAlarm(typeId, title, content);
}
@Override
public List<AlarmVo> getAlarmList(int userId) {
if (userId == 0) {
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(), ResultCode.VALIDATE_FAILED.getMsg());
}
List<AlarmVo> alarmVos = alarmMapper.getAlarmList(userId);
alarmVos = alarmVos.stream().sorted(Comparator.comparing(AlarmVo::getCreateTime, Comparator.reverseOrder())).collect(Collectors.toList());
return alarmVos;
}
}
package iot.sixiang.iot_diagnose.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import iot.sixiang.iot_diagnose.entity.AlarmType;
import iot.sixiang.iot_diagnose.mapper.AlarmTypeMapper;
import iot.sixiang.iot_diagnose.service.AlarmTypeService;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author m33
* @since 2022-06-10
*/
@Service
public class AlarmTypeServiceImpl extends ServiceImpl<AlarmTypeMapper, AlarmType> implements AlarmTypeService {
}
package iot.sixiang.iot_diagnose.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import iot.sixiang.iot_diagnose.auth.AuthManager;
import iot.sixiang.iot_diagnose.consts.ResultCode;
import iot.sixiang.iot_diagnose.entity.Apply;
import iot.sixiang.iot_diagnose.handler.IotLicenseException;
import iot.sixiang.iot_diagnose.mapper.ApplyMapper;
import iot.sixiang.iot_diagnose.model.PageInfoModel;
import iot.sixiang.iot_diagnose.model.vo.AppVo;
import iot.sixiang.iot_diagnose.service.ApplyService;
import iot.sixiang.iot_diagnose.util.CommonUtil;
import iot.sixiang.iot_diagnose.util.SpringUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 服务实现类
* </p>
*
* @author m33
* @since 2022-06-09
*/
@Service
public class ApplyServiceImpl extends ServiceImpl<ApplyMapper, Apply> implements ApplyService {
@Resource
ApplyMapper applyMapper;
@Override
public boolean addApply(String appName, String appKey, int userId) {
if(StringUtils.isEmpty(appName) || StringUtils.isEmpty(appKey)
|| userId == 0) {
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(),ResultCode.VALIDATE_FAILED.getMsg());
}
Apply res = applyMapper.getApplyByAppName(appName);
if (res != null) {
throw new IotLicenseException(403, "应用名已存在");
}
String appId = CommonUtil.genRandomNum(18).toLowerCase();
boolean re = applyMapper.addApply(appId, appName, appKey, userId);
if (!re) {
return false;
}
AuthManager authManager = SpringUtil.getBean(AuthManager.class);
authManager.initApps();
return true;
}
@Override
public PageInfoModel<AppVo> getAppList(int pageNo, int pageSize, String appName) {
if(pageNo == 0 || pageSize == 0) {
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(),ResultCode.VALIDATE_FAILED.getMsg());
}
List<AppVo> records = applyMapper.getAppList(appName);
records = records.stream().sorted(Comparator.comparing(AppVo::getCreateTime, Comparator.reverseOrder())).collect(Collectors.toList());
List<AppVo> result = new ArrayList<>();
int begin = (pageNo - 1) * pageSize;
if (begin >= 0 && records.size() > 0) {
result = records.stream().skip(begin).limit(pageSize).collect(Collectors.toList());
}
PageInfoModel<AppVo> objectPageInfoModel = new PageInfoModel<>();
objectPageInfoModel.setTotal(records.size());
objectPageInfoModel.setResult(result);
return objectPageInfoModel;
}
}
package iot.sixiang.iot_diagnose.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import iot.sixiang.iot_diagnose.auth.AuthManager;
import iot.sixiang.iot_diagnose.consts.ResultCode;
import iot.sixiang.iot_diagnose.device.DeviceManager;
import iot.sixiang.iot_diagnose.entity.DeviceBlack;
import iot.sixiang.iot_diagnose.handler.IotLicenseException;
import iot.sixiang.iot_diagnose.mapper.DeviceBlackMapper;
import iot.sixiang.iot_diagnose.mapper.DeviceMapper;
import iot.sixiang.iot_diagnose.model.PageInfoModel;
import iot.sixiang.iot_diagnose.model.vo.DeviceVo;
import iot.sixiang.iot_diagnose.service.DeviceBlackService;
import iot.sixiang.iot_diagnose.util.SpringUtil;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* <p>
* 服务实现类
* </p>
*
* @author m33
* @since 2022-06-15
*/
@Service
public class DeviceBlackServiceImpl extends ServiceImpl<DeviceBlackMapper, DeviceBlack> implements DeviceBlackService {
@Resource
private DeviceBlackMapper deviceBlackMapper;
@Resource
private DeviceMapper deviceMapper;
@Override
public boolean addDeviceBlack(int deviceId) {
if (deviceId == 0) {
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(),ResultCode.VALIDATE_FAILED.getMsg());
}
AuthManager authManager = SpringUtil.getBean(AuthManager.class);
DeviceManager deviceManager = SpringUtil.getBean(DeviceManager.class);
if (authManager.getDeviceBlack().containsKey(deviceId)) {
throw new IotLicenseException(ResultCode.FAILED.getCode(),ResultCode.FAILED.getMsg());
}
Map<String, DeviceVo> allDevice = deviceManager.getAllDevice();
boolean flag = false;
for (DeviceVo deviceVo : allDevice.values()) {
if (deviceVo.getDeviceId() == deviceId){
flag = true;
break;
}
}
if (!flag) {
throw new IotLicenseException(403, "设备不存在");
}
boolean res = deviceBlackMapper.addDeviceBlack(deviceId);
if (res) {
authManager.initDeviceBlacks();
return true;
}
return false;
}
@Override
public boolean deleteDeviceBlack(int deviceId) {
boolean res = deviceBlackMapper.deleteDeviceBlack(deviceId);
if (res) {
AuthManager authManager = SpringUtil.getBean(AuthManager.class);
authManager.initDeviceBlacks();
return true;
}
return false;
}
@Override
public PageInfoModel<DeviceBlack> getDeviceBlackList(int pageNo, int pageSize) {
if(pageNo == 0 || pageSize == 0) {
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(),ResultCode.VALIDATE_FAILED.getMsg());
}
List<DeviceBlack> records = deviceBlackMapper.getDeviceBlackList();
records = records.stream().sorted(Comparator.comparing(DeviceBlack::getCreateTime)).collect(Collectors.toList());
List<DeviceBlack> result = new ArrayList<>();
int begin = (pageNo - 1) * pageSize;
if (begin >= 0 && records.size() > 0) {
result = records.stream().skip(begin).limit(pageSize).collect(Collectors.toList());
}
PageInfoModel<DeviceBlack> objectPageInfoModel = new PageInfoModel<>();
objectPageInfoModel.setTotal(records.size());
objectPageInfoModel.setResult(result);
return objectPageInfoModel;
}
}
package iot.sixiang.iot_diagnose.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import iot.sixiang.iot_diagnose.consts.ResultCode;
import iot.sixiang.iot_diagnose.device.DeviceManager;
import iot.sixiang.iot_diagnose.entity.Device;
import iot.sixiang.iot_diagnose.handler.IotLicenseException;
import iot.sixiang.iot_diagnose.mapper.DeviceMapper;
import iot.sixiang.iot_diagnose.model.PageInfoModel;
import iot.sixiang.iot_diagnose.model.vo.DeviceVo;
import iot.sixiang.iot_diagnose.service.DeviceService;
import iot.sixiang.iot_diagnose.util.CommonUtil;
import iot.sixiang.iot_diagnose.util.SpringUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 服务实现类
* </p>
*
* @author m33
* @since 2022-06-08
*/
@Service
public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements DeviceService {
@Resource
private DeviceMapper deviceMapper;
@Override
public PageInfoModel<DeviceVo> getDeviceList(int pageNo, int pageSize, String appName, String userName) {
if(pageNo == 0 || pageSize == 0) {
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(),ResultCode.VALIDATE_FAILED.getMsg());
}
List<DeviceVo> deviceTypes = deviceMapper.getDeviceList(appName,userName);
deviceTypes = deviceTypes.stream().sorted(Comparator.comparing(DeviceVo::getCreateTime, Comparator.reverseOrder())).collect(Collectors.toList());
List<DeviceVo> result = new ArrayList<>();
int begin = (pageNo - 1) * pageSize;
if (begin >= 0 && deviceTypes.size() > 0) {
result = deviceTypes.stream().skip(begin).limit(pageSize).collect(Collectors.toList());
}
PageInfoModel<DeviceVo> objectPageInfoModel = new PageInfoModel<>();
objectPageInfoModel.setTotal(deviceTypes.size());
objectPageInfoModel.setResult(result);
return objectPageInfoModel;
}
@Override
public boolean addDevice(String appId, int count) {
if(StringUtils.isEmpty(appId) || count == 0) {
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(),ResultCode.VALIDATE_FAILED.getMsg());
}
for (int i = 0; i < count; i++) {
String sn = CommonUtil.genRandomNum(18);
boolean res = deviceMapper.addDevice(sn, appId);
if (!res) {
return false;
}
}
DeviceManager deviceManager = SpringUtil.getBean(DeviceManager.class);
deviceManager.initDevices();
return true;
}
}
package iot.sixiang.iot_diagnose.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import iot.sixiang.iot_diagnose.entity.Monitor;
import iot.sixiang.iot_diagnose.mapper.MonitorMapper;
import iot.sixiang.iot_diagnose.service.MonitorService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* <p>
* 服务实现类
* </p>
*
* @author m33
* @since 2022-06-10
*/
@Service
public class MonitorServiceImpl extends ServiceImpl<MonitorMapper, Monitor> implements MonitorService {
@Resource
MonitorMapper monitorMapper;
@Override
public boolean addMonitor(int count) {
LocalDate date = LocalDate.now();
LocalTime localTime = LocalTime.now();
int hour = localTime.getHour();
return monitorMapper.addMonitor(date, hour, count);
}
@Override
public HashMap<String,List<Integer>> getMonitorList(int type) {
LocalDate localDate = LocalDate.now();
LocalDate endDate = LocalDate.now();
switch (type) {
case 0:
localDate = LocalDate.now();
break;
case 1:
localDate = localDate.plusDays(-1);
break;
case 2:
localDate = localDate.plusDays(-6);
break;
case 3:
localDate = localDate.plusDays(-29);
break;
default:
break;
}
List<Monitor> monitorList = monitorMapper.getMonitorList(localDate, endDate);
HashMap<Integer, List<Integer>> map = new HashMap<>();
List<Integer> listX = new ArrayList<>();
List<Integer> listY = new ArrayList<>();
if (type == 0 || type == 1) {
for (int i = 0; i < 24; i++) {
int count = 0;
for (Monitor monitor : monitorList) {
Integer hour = monitor.getHour();
if (i == hour) {
count += monitor.getCount();
}
}
listX.add(i);
listY.add(count);
}
} else {
LocalDate now = LocalDate.now();
int end = 0;
if (type == 2) {
end = 7;
} else {
end = 30;
}
for (int i = 0; i < end; i++) {
LocalDate target = now.plusDays(-i);
int count = 0;
for (Monitor monitor : monitorList) {
LocalDate tempDate = monitor.getDate();
if (target.isEqual(tempDate)) {
count += monitor.getCount();
}
}
listX.add(i);
listY.add(count);
}
}
HashMap<String,List<Integer>> maps = new HashMap<>();
maps.put("x",listX);
maps.put("y",listY);
return maps;
}
}
package iot.sixiang.iot_diagnose.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import iot.sixiang.iot_diagnose.consts.ResultCode;
import iot.sixiang.iot_diagnose.entity.Server;
import iot.sixiang.iot_diagnose.handler.IotLicenseException;
import iot.sixiang.iot_diagnose.mapper.ServerMapper;
import iot.sixiang.iot_diagnose.service.ServerService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* <p>
* 服务实现类
* </p>
*
* @author m33
* @since 2022-06-06
*/
@Service
public class ServerServiceImpl extends ServiceImpl<ServerMapper, Server> implements ServerService {
@Resource
ServerMapper serverMapper;
@Override
public List<Server> getServerList(int pageNo, int pageSize) {
Page<Server> page = new Page<>(pageNo, pageSize);
baseMapper.selectPage(page, null);
List<Server> records = page.getRecords();
return records;
}
@Override
public boolean deleteServer(String serverIp) {
if (StringUtils.isEmpty(serverIp)) {
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(), ResultCode.VALIDATE_FAILED.getMsg());
}
return serverMapper.deleteServer(serverIp);
}
@Override
public boolean addServer(String serverIp, int port) {
if (StringUtils.isEmpty(serverIp) || port == 0) {
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(), ResultCode.VALIDATE_FAILED.getMsg());
}
return serverMapper.addServer(serverIp, port);
}
@Override
public boolean updateServer(String serverIp, int port) {
if (StringUtils.isEmpty(serverIp) || port == 0) {
throw new IotLicenseException(ResultCode.VALIDATE_FAILED.getCode(), ResultCode.VALIDATE_FAILED.getMsg());
}
return serverMapper.updateServer(serverIp, port);
}
}
package iot.sixiang.iot_diagnose.util;
import iot.sixiang.iot_diagnose.consts.Consts;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.system.ApplicationHome;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
@Slf4j
public class CommonUtil {
/**
* 随机生成指定长度的字符串
*
* @param length
* @return
*/
public static String genRandomNum(int length) {
int maxNum = 36;
int i = -1;
int count = 0;
char[] str = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
StringBuilder pwd = new StringBuilder("");
SecureRandom secureRandom = null;
try {
secureRandom = SecureRandom.getInstance("SHA1PRNG");
} catch (NoSuchAlgorithmException e) {
log.error("随机生成字符串失败");
}
while (count < length) {
if (secureRandom != null) {
i = Math.abs(secureRandom.nextInt(maxNum));
}
if (i >= 0 && i < str.length) {
pwd.append(str[i]);
count++;
}
}
return pwd.toString();
}
public static String getSystemTime() {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 设置日期格式
String time = df.format(new Date());
return time;
}
public static boolean regularMessage(String message) {
String regex = "^[0-9a-zA-Z_]{1,}$";
return message.matches(regex);
}
public static String toUpperCaseByEnglish(String message) {
return message.toUpperCase(Locale.ENGLISH);
}
public static String bytesToStr(byte[] bytes) {
String str = null;
if (bytes == null) {
return str;
} else {
try {
str = new String(bytes, 0, bytes.length, "utf-8");
} catch (UnsupportedEncodingException e) {
log.error("数组转换成字符串异常,{}", e.getMessage());
}
return str;
}
}
public static String getServerParentDirectory() {
return new File(new ApplicationHome(Consts.class).getSource().getParentFile().getPath()).getParent();
}
public static String getLibFilePathByFileName(String fileName) {
String os = System.getProperty("os.name");
String serverParentDirectory = getServerParentDirectory();
if (os != null) {
if (os.toLowerCase(Locale.ENGLISH).startsWith("win")) {
return serverParentDirectory + File.separator + "lib" + File.separator + fileName + ".dll";
} else {
return serverParentDirectory + File.separator + "lib" + File.separator + fileName + ".so";
}
}
return "";
}
}
package iot.sixiang.iot_diagnose.util;
public class HexUtil {
public static String bytes2hex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
StringBuilder tmp;
sb.append("[");
for (byte b : bytes) {
// 将每个字节与0xFF进行与运算,然后转化为10进制,然后借助于Integer再转化为16进制
tmp = new StringBuilder(Integer.toHexString(0xFF & b));
if (tmp.length() == 1) {
tmp = tmp.insert(0, '0');//只有一位的前面补个0
}
sb.append(tmp).append(" ");//每个字节用空格断开
}
sb.delete(sb.length() - 1, sb.length());//删除最后一个字节后面对于的空格
sb.append("]");
return sb.toString();
}
}
\ No newline at end of file
package iot.sixiang.iot_diagnose.util;
import lombok.extern.slf4j.Slf4j;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
@Slf4j
public class HmacUtil {
//加密算法
public static final String HMAC_SHA1 = "HmacSHA1";
public static final String HMAC_MD5 = "HmacMD5";
public static final String HMAC_SHA256 = "HmacSHA256";
public static final String HMAC_SHA512 = "HmacSHA512";
/**
* 实现Hmac系列的加密算法HmacSHA1、HmacMD5等
*
* @param input 需要加密的输入参数
* @param key 密钥
* @param algorithm 选择加密算法
* @return 加密后的值
**/
public static String encrypt(String input, String key, String algorithm) {
String cipher = "";
try {
byte[] data = key.getBytes(StandardCharsets.UTF_8);
//根据给定的字节数组构造一个密钥,第二个参数指定一个密钥的算法名称,生成HmacSHA1专属密钥
SecretKey secretKey = new SecretKeySpec(data, algorithm);
//生成一个指定Mac算法的Mac对象
Mac mac = Mac.getInstance(algorithm);
//用给定密钥初始化Mac对象
mac.init(secretKey);
byte[] text = input.getBytes(StandardCharsets.UTF_8);
byte[] encryptByte = mac.doFinal(text);
cipher = bytesToHexStr(encryptByte);
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
log.error("加密算法出现异常,{}", e.getMessage());
}
return cipher;
}
/**
* byte数组转16进制字符串
*
* @param bytes byte数组
* @return hex字符串
*/
public static String bytesToHexStr(byte[] bytes) {
StringBuilder hexStr = new StringBuilder();
for (byte b : bytes) {
String hex = Integer.toHexString(b & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
hexStr.append(hex);
}
return hexStr.toString();
}
}
\ No newline at end of file
package iot.sixiang.iot_diagnose.util;
import iot.sixiang.iot_diagnose.operate.OperateManager;
import iot.sixiang.iot_diagnose.service.MonitorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* Created by m33 on 2022/6/10 10:30
*/
@Component
public class OperateSchedu {
@Autowired
private OperateManager operateManager;
@Autowired
private MonitorService monitorService;
@Scheduled(cron = "0 0 0/1 * * ?")
public void scheduled() {
operateManager.createProxyClient();
int count = operateManager.getCount();
monitorService.addMonitor(count);
operateManager.clearCount();
}
}
package iot.sixiang.iot_diagnose.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringUtil.applicationContext == null) {
SpringUtil.applicationContext = applicationContext;
}
}
// 获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
// 通过class获取Bean.
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
}
\ No newline at end of file
package iot.sixiang.iot_diagnose.util;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Util {
public static void DEBUG_HEX(String tag, byte[] data, int datalen) {
StringBuilder hexStr = new StringBuilder();
int i = 0;
for (i = 0; i < datalen; i++) {
if ((i % 16) == 0) {
hexStr.append("");
}
if (Integer.toHexString(data[i] & 0xff).length() == 1) {
hexStr.append("0");
}
hexStr.append(Integer.toHexString(data[i] & 0xff).toUpperCase() + " ");
if ((i % 16) == 15) {
for (int j = (i - 15); j <= i; j++) {
if (data[j] > 0x20 && data[j] <= 0x7e) {
hexStr.append(String.valueOf((char) (data[j] & 0xff)));
} else {
hexStr.append('.');
}
}
}
}
if ((i % 16) != 0) {
for (int j = 0; j < 16; j++) {
if (j < (16 - (i % 16))) {
hexStr.append("-- ");
}
}
for (int j = (i - (i % 16)); j < i; j++) {
if (data[j] > 0x20 && data[j] <= 0x7e) {
hexStr.append(String.valueOf((char) (data[j] & 0xff)));
} else {
hexStr.append('.');
}
}
}
log.debug(hexStr.toString());
}
}
#
# OWASP Enterprise Security API (ESAPI) Properties file -- PRODUCTION Version
#
# This file is part of the Open Web Application Security Project (OWASP)
# Enterprise Security API (ESAPI) project. For details, please see
# https://owasp.org/www-project-enterprise-security-api/
#
# Copyright (c) 2008,2009 - The OWASP Foundation
#
# DISCUSS: This may cause a major backwards compatibility issue, etc. but
# from a name space perspective, we probably should have prefaced
# all the property names with ESAPI or at least OWASP. Otherwise
# there could be problems is someone loads this properties file into
# the System properties. We could also put this file into the
# esapi.jar file (perhaps as a ResourceBundle) and then allow an external
# ESAPI properties be defined that would overwrite these defaults.
# That keeps the application's properties relatively simple as usually
# they will only want to override a few properties. If looks like we
# already support multiple override levels of this in the
# DefaultSecurityConfiguration class, but I'm suggesting placing the
# defaults in the esapi.jar itself. That way, if the jar is signed,
# we could detect if those properties had been tampered with. (The
# code to check the jar signatures is pretty simple... maybe 70-90 LOC,
# but off course there is an execution penalty (similar to the way
# that the separate sunjce.jar used to be when a class from it was
# first loaded). Thoughts?
###############################################################################
#
# WARNING: Operating system protection should be used to lock down the .esapi
# resources directory and all the files inside and all the directories all the
# way up to the root directory of the file system. Note that if you are using
# file-based implementations, that some files may need to be read-write as they
# get updated dynamically.
#
#===========================================================================
# ESAPI Configuration
#
# If true, then print all the ESAPI properties set here when they are loaded.
# If false, they are not printed. Useful to reduce output when running JUnit tests.
# If you need to troubleshoot a properties related problem, turning this on may help.
# This is 'false' in the src/test/resources/.esapi version. It is 'true' by
# default for reasons of backward compatibility with earlier ESAPI versions.
ESAPI.printProperties=true
# ESAPI is designed to be easily extensible. You can use the reference implementation
# or implement your own providers to take advantage of your enterprise's security
# infrastructure. The functions in ESAPI are referenced using the ESAPI locator, like:
#
# String ciphertext =
# ESAPI.encryptor().encrypt("Secret message"); // Deprecated in 2.0
# CipherText cipherText =
# ESAPI.encryptor().encrypt(new PlainText("Secret message")); // Preferred
#
# Below you can specify the classname for the provider that you wish to use in your
# application. The only requirement is that it implement the appropriate ESAPI interface.
# This allows you to switch security implementations in the future without rewriting the
# entire application.
#
# ExperimentalAccessController requires ESAPI-AccessControlPolicy.xml in .esapi directory
ESAPI.AccessControl=org.owasp.esapi.reference.DefaultAccessController
# FileBasedAuthenticator requires users.txt file in .esapi directory
ESAPI.Authenticator=org.owasp.esapi.reference.FileBasedAuthenticator
ESAPI.Encoder=org.owasp.esapi.reference.DefaultEncoder
ESAPI.Encryptor=org.owasp.esapi.reference.crypto.JavaEncryptor
ESAPI.Executor=org.owasp.esapi.reference.DefaultExecutor
ESAPI.HTTPUtilities=org.owasp.esapi.reference.DefaultHTTPUtilities
ESAPI.IntrusionDetector=org.owasp.esapi.reference.DefaultIntrusionDetector
ESAPI.Logger=org.owasp.esapi.logging.slf4j.Slf4JLogFactory
# To use the new SLF4J logger in ESAPI (see GitHub issue #129), set
# ESAPI.Logger=org.owasp.esapi.logging.slf4j.Slf4JLogFactory
# and do whatever other normal SLF4J configuration that you normally would do for your application.
ESAPI.Randomizer=org.owasp.esapi.reference.DefaultRandomizer
ESAPI.Validator=org.owasp.esapi.reference.DefaultValidator
#===========================================================================
# ESAPI Authenticator
#
Authenticator.AllowedLoginAttempts=3
Authenticator.MaxOldPasswordHashes=ENC(F0TJ9iT6D4VW8xVjZf9Nqw==)
Authenticator.UsernameParameterName=username
Authenticator.PasswordParameterName=ENC(F0TJ9iT6D4VW8xVjZf9Nqw==)
# RememberTokenDuration (in days)
Authenticator.RememberTokenDuration=14
# Session Timeouts (in minutes)
Authenticator.IdleTimeoutDuration=20
Authenticator.AbsoluteTimeoutDuration=120
#===========================================================================
# ESAPI Encoder
#
# ESAPI canonicalizes input before validation to prevent bypassing filters with encoded attacks.
# Failure to canonicalize input is a very common mistake when implementing validation schemes.
# Canonicalization is automatic when using the ESAPI Validator, but you can also use the
# following code to canonicalize data.
#
# ESAPI.Encoder().canonicalize( "%22hello world&#x22;" );
#
# Multiple encoding is when a single encoding format is applied multiple times. Allowing
# multiple encoding is strongly discouraged.
Encoder.AllowMultipleEncoding=false
# Mixed encoding is when multiple different encoding formats are applied, or when
# multiple formats are nested. Allowing multiple encoding is strongly discouraged.
Encoder.AllowMixedEncoding=false
# The default list of codecs to apply when canonicalizing untrusted data. The list should include the codecs
# for all downstream interpreters or decoders. For example, if the data is likely to end up in a URL, HTML, or
# inside JavaScript, then the list of codecs below is appropriate. The order of the list is not terribly important.
Encoder.DefaultCodecList=HTMLEntityCodec,PercentCodec,JavaScriptCodec
#===========================================================================
# ESAPI Encryption
#
# The ESAPI Encryptor provides basic cryptographic functions with a simplified API.
# To get started, generate a new key using java -classpath esapi.jar org.owasp.esapi.reference.crypto.JavaEncryptor
# There is not currently any support for key rotation, so be careful when changing your key and salt as it
# will invalidate all signed, encrypted, and hashed data.
#
# WARNING: Not all combinations of algorithms and key lengths are supported.
# If you choose to use a key length greater than 128, you MUST download the
# unlimited strength policy files and install in the lib directory of your JRE/JDK.
# See http://java.sun.com/javase/downloads/index.jsp for more information.
#
# ***** IMPORTANT: Do NOT forget to replace these with your own values! *****
# To calculate these values, you can run:
# java -classpath esapi.jar org.owasp.esapi.reference.crypto.JavaEncryptor
#
#Encryptor.MasterKey=
#Encryptor.MasterSalt=
# Provides the default JCE provider that ESAPI will "prefer" for its symmetric
# encryption and hashing. (That is it will look to this provider first, but it
# will defer to other providers if the requested algorithm is not implemented
# by this provider.) If left unset, ESAPI will just use your Java VM's current
# preferred JCE provider, which is generally set in the file
# "$JAVA_HOME/jre/lib/security/java.security".
#
# The main intent of this is to allow ESAPI symmetric encryption to be
# used with a FIPS 140-2 compliant crypto-module. For details, see the section
# "Using ESAPI Symmetric Encryption with FIPS 140-2 Cryptographic Modules" in
# the ESAPI 2.0 Symmetric Encryption User Guide, at:
# http://owasp-esapi-java.googlecode.com/svn/trunk/documentation/esapi4java-core-2.0-symmetric-crypto-user-guide.html
# However, this property also allows you to easily use an alternate JCE provider
# such as "Bouncy Castle" without having to make changes to "java.security".
# See Javadoc for SecurityProviderLoader for further details. If you wish to use
# a provider that is not known to SecurityProviderLoader, you may specify the
# fully-qualified class name of the JCE provider class that implements
# java.security.Provider. If the name contains a '.', this is interpreted as
# a fully-qualified class name that implements java.security.Provider.
#
# NOTE: Setting this property has the side-effect of changing it in your application
# as well, so if you are using JCE in your application directly rather than
# through ESAPI (you wouldn't do that, would you? ;-), it will change the
# preferred JCE provider there as well.
#
# Default: Keeps the JCE provider set to whatever JVM sets it to.
Encryptor.PreferredJCEProvider=
# AES is the most widely used and strongest encryption algorithm. This
# should agree with your Encryptor.CipherTransformation property.
# Warning: This property does not control the default reference implementation for
# ESAPI 2.0 using JavaEncryptor. Also, this property will be dropped
# in the future.
# @deprecated
Encryptor.EncryptionAlgorithm=AES
# For ESAPI Java 2.0 - New encrypt / decrypt methods use this.
Encryptor.CipherTransformation=AES/CBC/PKCS5Padding
# Applies to ESAPI 2.0 and later only!
# Comma-separated list of cipher modes that provide *BOTH*
# confidentiality *AND* message authenticity. (NIST refers to such cipher
# modes as "combined modes" so that's what we shall call them.) If any of these
# cipher modes are used then no MAC is calculated and stored
# in the CipherText upon encryption. Likewise, if one of these
# cipher modes is used with decryption, no attempt will be made
# to validate the MAC contained in the CipherText object regardless
# of whether it contains one or not. Since the expectation is that
# these cipher modes support support message authenticity already,
# injecting a MAC in the CipherText object would be at best redundant.
#
# Note that as of JDK 1.5, the SunJCE provider does not support *any*
# of these cipher modes. Of these listed, only GCM and CCM are currently
# NIST approved. YMMV for other JCE providers. E.g., Bouncy Castle supports
# GCM and CCM with "NoPadding" mode, but not with "PKCS5Padding" or other
# padding modes.
Encryptor.cipher_modes.combined_modes=GCM,CCM,IAPM,EAX,OCB,CWC
# Applies to ESAPI 2.0 and later only!
# Additional cipher modes allowed for ESAPI 2.0 encryption. These
# cipher modes are in _addition_ to those specified by the property
# 'Encryptor.cipher_modes.combined_modes'.
# DISCUSS: Better name?
Encryptor.cipher_modes.additional_allowed=CBC
# Default key size to use for cipher specified by Encryptor.EncryptionAlgorithm.
# Note that this MUST be a valid key size for the algorithm being used
# (as specified by Encryptor.EncryptionAlgorithm). So for example, if AES is used,
# it must be 128, 192, or 256. If DESede is chosen, then it must be either 112 or 168.
#
# Note that 128-bits is almost always sufficient and for AES it appears to be more
# somewhat more resistant to related key attacks than is 256-bit AES.)
#
# Defaults to 128-bits if left blank.
#
# NOTE: If you use a key size > 128-bits, then you MUST have the JCE Unlimited
# Strength Jurisdiction Policy files installed!!!
#
Encryptor.EncryptionKeyLength=128
# This is the _minimum_ key size (in bits) that we allow with ANY symmetric
# cipher for doing encryption. (There is no minimum for decryption.)
#
# Generally, if you only use one algorithm, this should be set the same as
# the Encryptor.EncryptionKeyLength property.
Encryptor.MinEncryptionKeyLength=128
# Because 2.x uses CBC mode by default, it requires an initialization vector (IV).
# (All cipher modes except ECB require an IV.) Previously there were two choices: we can either
# use a fixed IV known to both parties or allow ESAPI to choose a random IV. The
# former was deprecated in ESAPI 2.2 and removed in ESAPI 2.3. It was not secure
# because the Encryptor (as are all the other major ESAPI components) is a
# singleton and thus the same IV would get reused each time. It was not a
# well-thought out plan. (To do it correctly means we need to add a setIV() method
# and get rid of the Encryptor singleton, thus it will not happen until 3.0.)
# However, while the IV does not need to be hidden from adversaries, it is important that the
# adversary not be allowed to choose it. Thus for now, ESAPI just chooses a random IV.
# Originally there was plans to allow a developer to provide a class and method
# name to define a custom static method to generate an IV, but that is just
# trouble waiting to happen. Thus in effect, the ONLY acceptable property value
# for this property is "random". In the not too distant future (possibly the
# next release), I will be removing it, but for now I am leaving this and
# checking for it so a ConfigurationException can be thrown if anyone using
# ESAPI ignored the deprecation warning message and still has it set to "fixed".
#
# Valid values: random
Encryptor.ChooseIVMethod=random
# Whether or not CipherText should use a message authentication code (MAC) with it.
# This prevents an adversary from altering the IV as well as allowing a more
# fool-proof way of determining the decryption failed because of an incorrect
# key being supplied. This refers to the "separate" MAC calculated and stored
# in CipherText, not part of any MAC that is calculated as a result of a
# "combined mode" cipher mode.
#
# If you are using ESAPI with a FIPS 140-2 cryptographic module, you *must* also
# set this property to false. That is because ESAPI takes the master key and
# derives 2 keys from it--a key for the MAC and a key for encryption--and
# because ESAPI is not itself FIPS 140-2 verified such intermediary aterations
# to keys from FIPS approved sources would have the effect of making your FIPS
# approved key generation and thus your FIPS approved JCE provider unapproved!
# More details in
# documentation/esapi4java-core-2.0-readme-crypto-changes.html
# documentation/esapi4java-core-2.0-symmetric-crypto-user-guide.html
# You have been warned.
Encryptor.CipherText.useMAC=true
# Whether or not the PlainText object may be overwritten and then marked
# eligible for garbage collection. If not set, this is still treated as 'true'.
Encryptor.PlainText.overwrite=true
# Do not use DES except in a legacy situations. 56-bit is way too small key size.
#Encryptor.EncryptionKeyLength=56
#Encryptor.MinEncryptionKeyLength=56
#Encryptor.EncryptionAlgorithm=DES
# TripleDES is considered strong enough for most purposes.
# Note: There is also a 112-bit version of DESede. Using the 168-bit version
# requires downloading the special jurisdiction policy from Sun.
#Encryptor.EncryptionKeyLength=168
#Encryptor.MinEncryptionKeyLength=112
#Encryptor.EncryptionAlgorithm=DESede
Encryptor.HashAlgorithm=SHA-512
Encryptor.HashIterations=1024
Encryptor.DigitalSignatureAlgorithm=SHA1withDSA
Encryptor.DigitalSignatureKeyLength=1024
Encryptor.RandomAlgorithm=SHA1PRNG
Encryptor.CharacterEncoding=UTF-8
# This is the Pseudo Random Function (PRF) that ESAPI's Key Derivation Function
# (KDF) normally uses. Note this is *only* the PRF used for ESAPI's KDF and
# *not* what is used for ESAPI's MAC. (Currently, HmacSHA1 is always used for
# the MAC, mostly to keep the overall size at a minimum.)
#
# Currently supported choices for JDK 1.5 and 1.6 are:
# HmacSHA1 (160 bits), HmacSHA256 (256 bits), HmacSHA384 (384 bits), and
# HmacSHA512 (512 bits).
# Note that HmacMD5 is *not* supported for the PRF used by the KDF even though
# the JDKs support it. See the ESAPI 2.0 Symmetric Encryption User Guide
# further details.
Encryptor.KDF.PRF=HmacSHA256
#===========================================================================
# ESAPI HttpUtilties
#
# The HttpUtilities provide basic protections to HTTP requests and responses. Primarily these methods
# protect against malicious data from attackers, such as unprintable characters, escaped characters,
# and other simple attacks. The HttpUtilities also provides utility methods for dealing with cookies,
# headers, and CSRF tokens.
#
# Default file upload location (remember to escape backslashes with \\)
HttpUtilities.UploadDir=C:\\ESAPI\\testUpload
HttpUtilities.UploadTempDir=C:\\temp
# Force flags on cookies, if you use HttpUtilities to set cookies
#HttpUtilities.ForceHttpOnlySession=false
HttpUtilities.ForceSecureSession=false
#HttpUtilities.ForceHttpOnlyCookies=true
HttpUtilities.ForceSecureCookies=true
# Maximum size of HTTP header key--the validator regex may have additional values.
HttpUtilities.MaxHeaderNameSize=256
# Maximum size of HTTP header value--the validator regex may have additional values.
HttpUtilities.MaxHeaderValueSize=4096
# Maximum size of JSESSIONID for the application--the validator regex may have additional values.
HttpUtilities.HTTPJSESSIONIDLENGTH=50
# Maximum length of a URL (see https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers)
HttpUtilities.URILENGTH=2000
# Maximum length of a redirect
HttpUtilities.maxRedirectLength=512
# Maximum length for an http scheme
HttpUtilities.HTTPSCHEMELENGTH=10
# Maximum length for an http host
HttpUtilities.HTTPHOSTLENGTH=100
# Maximum length for an http path
HttpUtilities.HTTPPATHLENGTH=150
#Maximum length for a context path
HttpUtilities.contextPathLength=150
#Maximum length for an httpServletPath
HttpUtilities.HTTPSERVLETPATHLENGTH=100
#Maximum length for an http query parameter name
HttpUtilities.httpQueryParamNameLength=100
#Maximum length for an http query parameter -- old default was 2000, but that's the max length for a URL...
HttpUtilities.httpQueryParamValueLength=500
# File upload configuration
HttpUtilities.ApprovedUploadExtensions=.pdf,.doc,.docx,.ppt,.pptx,.xls,.xlsx,.rtf,.txt,.jpg,.png
HttpUtilities.MaxUploadFileBytes=500000000
# Using UTF-8 throughout your stack is highly recommended. That includes your database driver,
# container, and any other technologies you may be using. Failure to do this may expose you
# to Unicode transcoding injection attacks. Use of UTF-8 does not hinder internationalization.
HttpUtilities.ResponseContentType=text/html; charset=UTF-8
# This is the name of the cookie used to represent the HTTP session
# Typically this will be the default "JSESSIONID"
HttpUtilities.HttpSessionIdName=JSESSIONID
#Sets whether or not we will overwrite http status codes to 200.
HttpUtilities.OverwriteStatusCodes=true
#Sets the application's base character encoding. This is forked from the Java Encryptor property.
HttpUtilities.CharacterEncoding=UTF-8
#===========================================================================
# ESAPI Executor
# CHECKME - This should be made OS independent. Don't use unsafe defaults.
# # Examples only -- do NOT blindly copy!
# For Windows:
# Executor.WorkingDirectory=C:\\Windows\\Temp
# Executor.ApprovedExecutables=C:\\Windows\\System32\\cmd.exe,C:\\Windows\\System32\\runas.exe
# For *nux, MacOS:
# Executor.WorkingDirectory=/tmp
# Executor.ApprovedExecutables=/bin/bash
Executor.WorkingDirectory=
Executor.ApprovedExecutables=
#===========================================================================
# ESAPI Logging
# Set the application name if these logs are combined with other applications
Logger.ApplicationName=ExampleApplication
# If you use an HTML log viewer that does not properly HTML escape log data, you can set LogEncodingRequired to true
Logger.LogEncodingRequired=false
# Determines whether ESAPI should log the application name. This might be clutter in some single-server/single-app environments.
Logger.LogApplicationName=true
# Determines whether ESAPI should log the server IP and port. This might be clutter in some single-server environments.
Logger.LogServerIP=true
# Determines whether ESAPI should log the user info.
Logger.UserInfo=true
# Determines whether ESAPI should log the session id and client IP.
Logger.ClientInfo=true
#===========================================================================
# ESAPI Intrusion Detection
#
# Each event has a base to which .count, .interval, and .action are added
# The IntrusionException will fire if we receive "count" events within "interval" seconds
# The IntrusionDetector is configurable to take the following actions: log, logout, and disable
# (multiple actions separated by commas are allowed e.g. event.test.actions=log,disable
#
# Custom Events
# Names must start with "event." as the base
# Use IntrusionDetector.addEvent( "test" ) in your code to trigger "event.test" here
# You can also disable intrusion detection completely by changing
# the following parameter to true
#
IntrusionDetector.Disable=false
#
IntrusionDetector.event.test.count=2
IntrusionDetector.event.test.interval=10
IntrusionDetector.event.test.actions=disable,log
# Exception Events
# All EnterpriseSecurityExceptions are registered automatically
# Call IntrusionDetector.getInstance().addException(e) for Exceptions that do not extend EnterpriseSecurityException
# Use the fully qualified classname of the exception as the base
# any intrusion is an attack
IntrusionDetector.org.owasp.esapi.errors.IntrusionException.count=1
IntrusionDetector.org.owasp.esapi.errors.IntrusionException.interval=1
IntrusionDetector.org.owasp.esapi.errors.IntrusionException.actions=log,disable,logout
# for test purposes
# CHECKME: Shouldn't there be something in the property name itself that designates
# that these are for testing???
IntrusionDetector.org.owasp.esapi.errors.IntegrityException.count=10
IntrusionDetector.org.owasp.esapi.errors.IntegrityException.interval=5
IntrusionDetector.org.owasp.esapi.errors.IntegrityException.actions=log,disable,logout
# rapid validation errors indicate scans or attacks in progress
# org.owasp.esapi.errors.ValidationException.count=10
# org.owasp.esapi.errors.ValidationException.interval=10
# org.owasp.esapi.errors.ValidationException.actions=log,logout
# sessions jumping between hosts indicates session hijacking
IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.count=2
IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.interval=10
IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.actions=log,logout
#===========================================================================
# ESAPI Validation
#
# The ESAPI Validator works on regular expressions with defined names. You can define names
# either here, or you may define application specific patterns in a separate file defined below.
# This allows enterprises to specify both organizational standards as well as application specific
# validation rules.
#
# Use '\p{L}' (without the quotes) within the character class to match
# any Unicode LETTER. You can also use a range, like: \u00C0-\u017F
# You can also use any of the regex flags as documented at
# https://docs.oracle.com/javase/tutorial/essential/regex/pattern.html, e.g. (?u)
#
Validator.ConfigurationFile=validation.properties
# Validators used by ESAPI
Validator.AccountName=^[a-zA-Z0-9]{3,20}$
Validator.SystemCommand=^[a-zA-Z\\-\\/]{1,64}$
Validator.RoleName=^[a-z]{1,20}$
#the word TEST below should be changed to your application
#name - only relative URL's are supported
Validator.Redirect=^\\/test.*$
# Global HTTP Validation Rules
# Values with Base64 encoded data (e.g. encrypted state) will need at least [a-zA-Z0-9\/+=]
Validator.HTTPScheme=^(http|https)$
Validator.HTTPServerName=^[a-zA-Z0-9_.\\-]*$
Validator.HTTPCookieName=^[a-zA-Z0-9\\-_]{1,32}$
Validator.HTTPCookieValue=^[a-zA-Z0-9\\-\\/+=_ ]{0,1024}$
# Note that headerName and Value length is also configured in the HTTPUtilities section
Validator.HTTPHeaderName=^[a-zA-Z0-9\\-_]{1,256}$
Validator.HTTPHeaderValue=^[a-zA-Z0-9()\\-=\\*\\.\\?;,+\\/:&_ ]*$
Validator.HTTPServletPath=^[a-zA-Z0-9.\\-\\/_]*$
Validator.HTTPPath=^[a-zA-Z0-9.\\-_]*$
Validator.HTTPURL=^.*$
Validator.HTTPJSESSIONID=^[A-Z0-9]{10,32}$
# Contributed by Fraenku@gmx.ch
# Github Issue 126 https://github.com/ESAPI/esapi-java-legacy/issues/126
Validator.HTTPParameterName=^[a-zA-Z0-9_\\-]{1,32}$
Validator.HTTPParameterValue=^[-\\p{L}\\p{N}./+=_ !$*?@]{0,1000}$
Validator.HTTPContextPath=^/[a-zA-Z0-9.\\-_]*$
Validator.HTTPQueryString=^([a-zA-Z0-9_\\-]{1,32}=[\\p{L}\\p{N}.\\-/+=_ !$*?@%]*&?)*$
Validator.HTTPURI=^/([a-zA-Z0-9.\\-_]*/?)*$
# Validation of file related input
Validator.FileName=^[a-zA-Z0-9!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1,255}$
Validator.DirectoryName=^[a-zA-Z0-9:/\\\\!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1,255}$
# Validation of dates. Controls whether or not 'lenient' dates are accepted.
# See DataFormat.setLenient(boolean flag) for further details.
Validator.AcceptLenientDates=false
# ~~~~~ Important Note ~~~~~
# This is a workaround to make sure that a commit to address GitHub issue #509
# doesn't accidentally break someone's production code. So essentially what we
# are doing is to reverting back to the previous possibly buggy (by
# documentation intent at least), but, by now, expected legacy behavior.
# Prior to the code changes for issue #509, if invalid / malicious HTML input was
# observed, AntiSamy would simply attempt to sanitize (cleanse) it and it would
# only be logged. However, the code change made ESAPI comply with its
# documentation, which stated that a ValidationException should be thrown in
# such cases. Unfortunately, changing this behavior--especially when no one is
# 100% certain that the documentation was correct--could break existing code
# using ESAPI so after a lot of debate, issue #521 was created to restore the
# previous behavior, but still allow the documented behavior. (We did this
# because it wasn't really causing an security issues since AntiSamy would clean
# it up anyway and we value backward compatibility as long as it doesn't clearly
# present security vulnerabilities.)
# More defaults about this are written up under GitHub issue #521 and
# the pull request it references. Future major releases of ESAPI (e.g., ESAPI 3.x)
# will not support this previous behavior, but it will remain for ESAPI 2.x.
# Set this to 'throw' if you want the originally intended behavior of throwing
# that was fixed via issue #509. Set to 'clean' if you want want the HTML input
# sanitized instead.
#
# Possible values:
# clean -- Use the legacy behavior where unsafe HTML input is logged and the
# sanitized (i.e., clean) input as determined by AntiSamy and your
# AntiSamy rules is returned. This is the default behavior if this
# new property is not found.
# throw -- The new, presumably correct and originally intended behavior where
# a ValidationException is thrown when unsafe HTML input is
# encountered.
#
#Validator.HtmlValidationAction=clean
Validator.HtmlValidationAction=throw
# With the fix for #310 to enable loading antisamy-esapi.xml from the classpath
# also an enhancement was made to be able to use a different filename for the configuration.
# You don't have to configure the filename here, but in that case the code will keep looking for antisamy-esapi.xml.
# This is the default behaviour of ESAPI.
#
#Validator.HtmlValidationConfigurationFile=antisamy-esapi.xml
\ No newline at end of file
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
W3C rules retrieved from:
http://www.w3.org/TR/html401/struct/global.html
-->
<!--
Slashdot allowed tags taken from "Reply" page:
<b> <i> <p> <br> <a> <ol> <ul> <li> <dl> <dt> <dd> <em> <strong> <tt> <blockquote> <div> <ecode> <quote>
-->
<anti-samy-rules xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="antisamy.xsd">
<directives>
<directive name="omitXmlDeclaration" value="true"/>
<directive name="omitDoctypeDeclaration" value="true"/>
<directive name="maxInputSize" value="500000"/>
<directive name="embedStyleSheets" value="false"/>
</directives>
<common-regexps>
<!--
From W3C:
This attribute assigns a class name or set of class names to an
element. Any number of elements may be assigned the same class
name or names. Multiple class names must be separated by white
space characters.
-->
<regexp name="htmlTitle" value="[\p{L}\p{N}\s\-_',:\[\]!\./\\\(\)&amp;]*"/>
<regexp name="onsiteURL" value="^(?!//)(?![\p{L}\p{N}\\\.\#@\$%\+&amp;;\-_~,\?=/!]*(&amp;colon))[\p{L}\p{N}\\\.\#@\$%\+&amp;;\-_~,\?=/!]*"/>
<regexp name="offsiteURL" value="(\s)*((ht|f)tp(s?)://|mailto:)[\p{L}\p{N}]+[\p{L}\p{N}\p{Zs}\.\#@\$%\+&amp;;:\-_~,\?=/!\(\)]*(\s)*"/>
</common-regexps>
<!--
Tag.name = a, b, div, body, etc.
Tag.action = filter: remove tags, but keep content, validate: keep content as long as it passes rules, remove: remove tag and contents
Attribute.name = id, class, href, align, width, etc.
Attribute.onInvalid = what to do when the attribute is invalid, e.g., remove the tag (removeTag), remove the attribute (removeAttribute), filter the tag (filterTag)
Attribute.description = What rules in English you want to tell the users they can have for this attribute. Include helpful things so they'll be able to tune their HTML
-->
<!--
Some attributes are common to all (or most) HTML tags. There aren't many that qualify for this. You have to make sure there's no
collisions between any of these attribute names with attribute names of other tags that are for different purposes.
-->
<common-attributes>
<attribute name="lang" description="The 'lang' attribute tells the browser what language the element's attribute values and content are written in">
<regexp-list>
<regexp value="[a-zA-Z]{2,20}"/>
</regexp-list>
</attribute>
<attribute name="title" description="The 'title' attribute provides text that shows up in a 'tooltip' when a user hovers their mouse over the element">
<regexp-list>
<regexp name="htmlTitle"/>
</regexp-list>
</attribute>
<attribute name="href" onInvalid="filterTag">
<regexp-list>
<regexp name="onsiteURL"/>
</regexp-list>
</attribute>
<attribute name="align" description="The 'align' attribute of an HTML element is a direction word, like 'left', 'right' or 'center'">
<literal-list>
<literal value="center"/>
<literal value="left"/>
<literal value="right"/>
<literal value="justify"/>
<literal value="char"/>
</literal-list>
</attribute>
</common-attributes>
<!--
This requires normal updates as browsers continue to diverge from the W3C and each other. As long as the browser wars continue
this is going to continue. I'm not sure war is the right word for what's going on. Doesn't somebody have to win a war after
a while?
-->
<global-tag-attributes>
<attribute name="title"/>
<attribute name="lang"/>
</global-tag-attributes>
<tag-rules>
<!-- Tags related to JavaScript -->
<tag name="script" action="remove"/>
<tag name="noscript" action="remove"/>
<!-- Frame & related tags -->
<tag name="iframe" action="remove"/>
<tag name="frameset" action="remove"/>
<tag name="frame" action="remove"/>
<tag name="noframes" action="remove"/>
<!-- All reasonable formatting tags -->
<tag name="p" action="validate">
<attribute name="align"/>
</tag>
<tag name="div" action="validate"/>
<tag name="i" action="validate"/>
<tag name="b" action="validate"/>
<tag name="em" action="validate"/>
<tag name="blockquote" action="validate"/>
<tag name="tt" action="validate"/>
<tag name="br" action="truncate"/>
<!-- Custom Slashdot tags, though we're trimming the idea of having a possible mismatching end tag with the endtag="" attribute -->
<tag name="quote" action="validate"/>
<tag name="ecode" action="validate"/>
<!-- Anchor and anchor related tags -->
<tag name="a" action="validate">
<attribute name="href" onInvalid="filterTag"/>
<attribute name="nohref">
<literal-list>
<literal value="nohref"/>
<literal value=""/>
</literal-list>
</attribute>
<attribute name="rel">
<literal-list>
<literal value="nofollow"/>
</literal-list>
</attribute>
</tag>
<!-- List tags -->
<tag name="ul" action="validate"/>
<tag name="ol" action="validate"/>
<tag name="li" action="validate"/>
</tag-rules>
<!-- No CSS on Slashdot posts -->
<css-rules>
</css-rules>
</anti-samy-rules>
\ No newline at end of file
server:
port: 8873
logging:
level:
root: debug
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/iot_license?serverTimezone=GMT%2B8
username: root
password: 123456
mybatis-plus:
mapper-locations: classpath:/mapper/**.xml
type-aliases-package: iot.sixiang.iot_diagnose.entity
knife4j:
enable: true
\ No newline at end of file
spring:
profiles:
active: dev
application:
name: iot_license #当前服务的名称
main:
allow-bean-definition-overriding: true
## 配置输出日志
logging:
config: classpath:logback-spring.xml
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="false" scanPeriod="10 seconds">
<!-- <logger>用来设置某一个包或者具体的某一个类的日志打印级别、 -->
<!-- <logger name="iot.sixiang.iot_diagnose" level="debug" />-->
<!--控制台输出的格式设置 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- 控制台输出的日志 的格式 -->
<encoder>
<pattern>
%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %5level %logger{96}:%line - %msg%n
</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 只是DEBUG级别以上的日志才显示 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
</appender>
<!--文件输出的格式设置 -->
<appender name="ALL_FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 日志日常打印文件 -->
<file>logs/license.log</file>
<!-- 配置日志所生成的目录以及生成文件名的规则 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/license.log-%d{yyyy-MM-dd}.%i</fileNamePattern>
<!-- 如果按天来回滚,则最大保存时间为365天,365天之前的都将被清理掉 -->
<maxHistory>365</maxHistory>
<!-- 日志总保存量为10GB -->
<totalSizeCap>100GB</totalSizeCap>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!--文件达到 最大128MB时会被压缩和切割 -->
<maxFileSize>40 MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>DEBUG</level>
</filter>
<!-- 文件输出的日志 的格式 -->
<encoder>
<pattern>
%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %5level %logger{96}:%line - %msg%n
</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- Safely log to the same file from multiple JVMs. Degrades performance! -->
<prudent>false</prudent>
</appender>
<!--文件输出的格式设置 -->
<appender name="MSG_FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 日志日常打印文件 -->
<file>logs/message.log</file>
<!-- 配置日志所生成的目录以及生成文件名的规则 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/message.log-%d{yyyy-MM-dd}.%i</fileNamePattern>
<!-- 如果按天来回滚,则最大保存时间为365天,365天之前的都将被清理掉 -->
<maxHistory>365</maxHistory>
<!-- 日志总保存量为10GB -->
<totalSizeCap>100GB</totalSizeCap>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!--文件达到 最大128MB时会被压缩和切割 -->
<maxFileSize>40 MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<!-- 此日志文档只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<!-- 文件输出的日志 的格式 -->
<encoder>
<pattern>
%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %5level %logger{96}:%line - %msg%n
</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- Safely log to the same file from multiple JVMs. Degrades performance! -->
<prudent>false</prudent>
</appender>
<!-- Enable FILE and STDOUT appenders for all log messages. By default,
only log at level INFO and above. -->
<!--这里选择INFO就代表,进行INFO级别输出记录,那么在控制台也好,log文件也好只记录INFO及以上级别的日志,这里相当于第一道设置-->
<root level="info">
<appender-ref ref="STDOUT" />
<appender-ref ref="ALL_FILE" />
<appender-ref ref="MSG_FILE" />
</root>
</configuration>
\ No newline at end of file
<?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="iot.sixiang.iot_diagnose.mapper.AlarmMapper">
<insert id="addAlarm" parameterType="iot.sixiang.iot_diagnose.entity.Alarm">
insert into alarm (type_id, title, content, create_time) values (#{typeId},#{title},#{content},now());
</insert>
<select id="getAlarmList" resultType="iot.sixiang.iot_diagnose.model.vo.AlarmVo">
SELECT al.id,al.type_id,al.title,al.content,al.create_time,alt.level,
alt.level_describe,al.id IN(SELECT alarm_id FROM alarm_read WHERE user_id = #{userId}) read_flag
FROM alarm AS al JOIN alarm_type AS alt ON al.type_id = alt.id
</select>
</mapper>
<?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="iot.sixiang.iot_diagnose.mapper.AlarmReadMapper">
<insert id="readAlarm" parameterType="iot.sixiang.iot_diagnose.entity.AlarmRead">
insert into alarm_read (alarm_id, type_id, title, content, create_time, user_id) values (#{alarmId},#{typeId},#{title},#{content},now(),#{userId});
</insert>
</mapper>
<?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="iot.sixiang.iot_diagnose.mapper.AlarmTypeMapper">
</mapper>
<?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="iot.sixiang.iot_diagnose.mapper.ApplyMapper">
<sql id="AppVoColumn">
app.app_id, app.app_name, app.app_key, app.create_time, app.update_time, us.user_id,
COUNT(sn) AS deviceCount, us.user_name, us.company
</sql>
<insert id="addApply" parameterType="iot.sixiang.iot_diagnose.entity.Apply">
insert into apply(app_id,app_name, app_key, user_id, create_time, update_time) values (#{appId}, #{appName}, #{appKey}, #{userId}, now(), now())
</insert>
<select id="getAppList" resultType="iot.sixiang.iot_diagnose.model.vo.AppVo">
SELECT <include refid="AppVoColumn"/>
FROM apply AS app LEFT JOIN device AS de ON app.app_id = de.app_id
LEFT JOIN user AS us ON us.user_id = app.user_id
where 1=1
<if test="null != _parameter and '' != _parameter">
and app_name like concat('%',#{_parameter},'%')
</if>
GROUP BY app.app_id
</select>
<select id="getApplyByAppName" resultType="iot.sixiang.iot_diagnose.entity.Apply">
select app_id from apply where app_name = #{appName}
</select>
</mapper>
<?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="iot.sixiang.iot_diagnose.mapper.DeviceBlackMapper">
<insert id="addDeviceBlack" parameterType="iot.sixiang.iot_diagnose.entity.DeviceBlack">
insert into device_black(device_id, create_time) values (#{deviceId}, now())
</insert>
<delete id="deleteDeviceBlack" parameterType="iot.sixiang.iot_diagnose.entity.DeviceBlack">
delete from device_black where device_id = #{deviceId}
</delete>
<select id="getDeviceBlackList" resultType="iot.sixiang.iot_diagnose.entity.DeviceBlack">
select id, device_id, create_time from device_black
</select>
</mapper>
<?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="iot.sixiang.iot_diagnose.mapper.DeviceMapper">
<select id="getDeviceList" resultType="iot.sixiang.iot_diagnose.model.vo.DeviceVo">
SELECT de.device_id,app_name,user_name,sn,de.create_time,de.update_time,de.device_id IN (select device_id from device_black) AS blackFlag FROM device AS de
JOIN apply AS app ON de.app_id = app.app_id
JOIN USER AS us ON us.user_id = app.user_id
where 1=1
<if test="null != appName and '' != appName">
and app_name like concat('%',#{appName},'%')
</if>
<if test="null != userName and '' != userName">
and user_name like concat('%',#{userName},'%')
</if>
</select>
<insert id="addDevice" parameterType="iot.sixiang.iot_diagnose.entity.Device">
insert into device(sn, app_id, create_time, update_time) values (#{sn},#{appId}, now(), now())
</insert>
</mapper>
<?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="iot.sixiang.iot_diagnose.mapper.MonitorMapper">
<insert id="addMonitor" parameterType="iot.sixiang.iot_diagnose.entity.Monitor">
insert into monitor (date, hour, count) values (#{date},#{hour},#{count});
</insert>
<select id="getMonitorList" resultType="iot.sixiang.iot_diagnose.entity.Monitor">
select id, date, hour, count from monitor where date between #{localDate} and #{endDate}
</select>
</mapper>
<?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="iot.sixiang.iot_diagnose.mapper.ServerMapper">
<insert id="addServer" parameterType="iot.sixiang.iot_diagnose.entity.Server">
insert into server(server_ip, port) values (#{serverIp},#{port})
</insert>
<delete id="deleteServer" parameterType="iot.sixiang.iot_diagnose.entity.Server">
delete from server where server_ip = #{serverIp}
</delete>
<update id="updateServer" parameterType="iot.sixiang.iot_diagnose.entity.Server">
update server set port = #{port} where server_ip = #{serverIp}
</update>
</mapper>
# The ESAPI validator does many security checks on input, such as canonicalization
# and whitelist validation. Note that all of these validation rules are applied *after*
# canonicalization. Double-encoded characters (even with different encodings involved,
# are never allowed.
#
# To use:
#
# First set up a pattern below. You can choose any name you want, prefixed by the word
# "Validation." For example:
# Validation.Email=^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+\\.[a-zA-Z]{2,4}$
#
# Then you can validate in your code against the pattern like this:
# ESAPI.validator().isValidInput("User Email", input, "Email", maxLength, allowNull);
# Where maxLength and allowNull are set for you needs, respectively.
#
# But note, when you use boolean variants of validation functions, you lose critical
# canonicalization. It is preferable to use the "get" methods (which throw exceptions) and
# and use the returned user input which is in canonical form. Consider the following:
#
# try {
# someObject.setEmail(ESAPI.validator().getValidInput("User Email", input, "Email", maxLength, allowNull));
#
Validator.SafeString=^[.\\p{Alnum}\\p{Space}]{0,1024}$
Validator.Email=^[A-Za-z0-9._%'-]+@[A-Za-z0-9.-]+\\.[a-zA-Z]{2,4}$
Validator.IPAddress=^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
Validator.URL=^(ht|f)tp(s?)\\:\\/\\/[0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*(:(0-9)*)*(\\/?)([a-zA-Z0-9\\-\\.\\?\\,\\:\\'\\/\\\\\\+=&;%\\$#_]*)?$
Validator.CreditCard=^(\\d{4}[- ]?){3}\\d{4}$
Validator.SSN=^(?!000)([0-6]\\d{2}|7([0-6]\\d|7[012]))([ -]?)(?!00)\\d\\d\\3(?!0000)\\d{4}$
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment