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
This diff is collapsed.
@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());
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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