[v0.0.0] 原始哈勃服务器代码
commit
f016e02e75
@ -0,0 +1,2 @@
|
||||
/target/
|
||||
/.idea/
|
@ -0,0 +1,132 @@
|
||||
<?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.1.5.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.platform</groupId>
|
||||
<artifactId>pass-through</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<name>pass-through</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.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>4.1.32.Final</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.76</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- log4j2 日志记录-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-log4j2</artifactId>
|
||||
</dependency>
|
||||
<!-- 加上这个才能辨认到log4j2.yml文件 -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.dataformat</groupId>
|
||||
<artifactId>jackson-dataformat-yaml</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
<version>2.7.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger-ui</artifactId>
|
||||
<version>2.7.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<!--<plugin>
|
||||
<groupId>org.mybatis.generator</groupId>
|
||||
<artifactId>mybatis-generator-maven-plugin</artifactId>
|
||||
<version>1.3.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>Generate MyBatis Artifacts</id>
|
||||
<goals>
|
||||
<goal>generate</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<!– generator 工具配置文件的位置 –>
|
||||
<configurationFile>src/main/resources/mybatis-generator/generatorConfig.xml</configurationFile>
|
||||
<verbose>true</verbose>
|
||||
<overwrite>true</overwrite>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>5.1.34</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis.generator</groupId>
|
||||
<artifactId>mybatis-generator-core</artifactId>
|
||||
<version>1.3.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>-->
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
</project>
|
@ -0,0 +1,14 @@
|
||||
package com.platform;
|
||||
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class BootApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(BootApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.platform.config;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
public class ClientHttpFilter implements Filter {
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
|
||||
HttpServletResponse response = (HttpServletResponse) res;
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
|
||||
response.setHeader("Access-Control-Max-Age", "3600");
|
||||
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
|
||||
chain.doFilter(req, res);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.platform.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@Data
|
||||
public class ServiceConfig {
|
||||
@Value("${log.debug}")
|
||||
private boolean debug;
|
||||
@Value("${service.port}")
|
||||
private Integer port;
|
||||
}
|
@ -0,0 +1,219 @@
|
||||
package com.platform.controller;
|
||||
|
||||
import com.platform.model.ManyToMany;
|
||||
import com.platform.model.OneToMany;
|
||||
import com.platform.util.SessionCache;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@RestController
|
||||
@Slf4j
|
||||
public class ClientController {
|
||||
@Autowired
|
||||
private SessionCache sessionCache;
|
||||
|
||||
/**
|
||||
* 获取已经连接上的session ip
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/session/ips")
|
||||
public List<String> getSessions() {
|
||||
List<String> ips = new ArrayList<>();
|
||||
Set set= sessionCache.tcpSession.keySet();
|
||||
Iterator iterator = set.iterator();
|
||||
while (iterator.hasNext()){
|
||||
ips.add(iterator.next().toString());
|
||||
}
|
||||
return ips;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一对一连接
|
||||
*
|
||||
* @param source
|
||||
* @param target
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/mapping/oneToOne")
|
||||
public Boolean addSnMap(@RequestParam("source") String source, @RequestParam("target") String target) {
|
||||
sessionCache.snToSnMap.put(source, target);
|
||||
sessionCache.snToSnMap.put(target, source);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一对多连接
|
||||
* @param param
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/mapping/oneToMany")
|
||||
public Boolean addSnsMap(@RequestBody OneToMany param) {
|
||||
List<String> list = param.getTarget();
|
||||
List<String> target = list.stream().map(String::toUpperCase).collect(Collectors.toList());
|
||||
String source = param.getSource().toUpperCase();
|
||||
target.forEach(sn -> sessionCache.snToSnMap.put(sn, source));
|
||||
if(!sessionCache.snList.contains(source)) {
|
||||
sessionCache.snList.add(source);
|
||||
}
|
||||
List<String> oldTarget = sessionCache.snToListMap.get(source);
|
||||
if (!ObjectUtils.isEmpty(oldTarget)) {
|
||||
oldTarget.forEach(sn ->{
|
||||
if (!target.contains(sn)) {
|
||||
target.add(sn);
|
||||
}
|
||||
});
|
||||
}
|
||||
sessionCache.snToListMap.put(source, target);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一对一、一对多、多对多映射
|
||||
* @param param
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/mapping/all")
|
||||
public Boolean addSourcesAndTargetsMap(@RequestBody ManyToMany param) {
|
||||
List<String> targetList = param.getTarget().stream().map(String::toUpperCase).collect(Collectors.toList());
|
||||
List<String> sourceList = param.getSource().stream().map(String::toUpperCase).collect(Collectors.toList());
|
||||
List<String> sourceTmp = new ArrayList<>();
|
||||
targetList.forEach(target->{
|
||||
List<String> oldSource = sessionCache.mappingListMap.get(target);
|
||||
if (!ObjectUtils.isEmpty(oldSource)) {
|
||||
oldSource.forEach(sn ->{
|
||||
if (!sourceList.contains(sn)) {
|
||||
sourceList.add(sn);
|
||||
}
|
||||
});
|
||||
}
|
||||
List<String> newSource= new ArrayList<>();
|
||||
newSource.addAll(sourceList);
|
||||
if (!sourceTmp.isEmpty()){
|
||||
newSource.addAll(sourceTmp);
|
||||
sourceTmp.clear();
|
||||
}
|
||||
sessionCache.mappingListMap.put(target, newSource);
|
||||
});
|
||||
List<String> targetTmp = new ArrayList<>();
|
||||
sourceList.forEach(source ->{
|
||||
List<String> oldTarget = sessionCache.mappingListMap.get(source);
|
||||
if (!ObjectUtils.isEmpty(oldTarget)) {
|
||||
oldTarget.forEach(sn ->{
|
||||
if (!targetList.contains(sn)) {
|
||||
targetTmp.add(sn);
|
||||
}
|
||||
});
|
||||
}
|
||||
List<String> newTarget = new ArrayList<>();
|
||||
newTarget.addAll(targetList);
|
||||
if (!targetTmp.isEmpty()){
|
||||
newTarget.addAll(targetTmp);
|
||||
targetTmp.clear();
|
||||
}
|
||||
sessionCache.mappingListMap.put(source, newTarget);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除映射关系
|
||||
* @param param
|
||||
* @return
|
||||
*/
|
||||
@PostMapping("/mapping/delete")
|
||||
public Boolean deleteSourcesAndTargetsMap(@RequestBody ManyToMany param) {
|
||||
List<String> sourceList = param.getSource().stream().map(String::toUpperCase).collect(Collectors.toList());
|
||||
List<String> targetList = param.getTarget().stream().map(String::toUpperCase).collect(Collectors.toList());
|
||||
List<String> all = new ArrayList<>();
|
||||
all.addAll(sourceList);
|
||||
all.addAll(targetList);
|
||||
all.forEach(code ->{
|
||||
List<String> valueList = sessionCache.mappingListMap.get(code);
|
||||
List<String> deletedList = new ArrayList<>();
|
||||
if (!ObjectUtils.isEmpty(valueList)) {
|
||||
valueList.forEach(value ->{
|
||||
if (all.contains(value)){
|
||||
deletedList.add(value);
|
||||
}
|
||||
});
|
||||
deletedList.forEach(deleted -> valueList.remove(deleted));
|
||||
if (valueList.size() > 0) {
|
||||
sessionCache.mappingListMap.put(code, valueList);
|
||||
} else{
|
||||
sessionCache.mappingListMap.remove(code);
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一对一映射关系
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/mapping/oneToOne")
|
||||
public Map<String, String> getSnMap() {
|
||||
return sessionCache.snToSnMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一对多映射关系
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/mapping/oneToMany")
|
||||
public Map<String, List<String>> getSnListMap() {
|
||||
return sessionCache.snToListMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有映射关系
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/mapping/get")
|
||||
public Map<String, List<String>> getTargetListMap() {
|
||||
return sessionCache.mappingListMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置监控接口
|
||||
*
|
||||
* @param supervisor
|
||||
* @param monitored
|
||||
* @return
|
||||
*/
|
||||
@ApiImplicitParams({
|
||||
@ApiImplicitParam(name = "supervisor", value = "监控者", required = true),
|
||||
@ApiImplicitParam(name = "monitored", value = "被监控者", required = true),
|
||||
})
|
||||
@GetMapping("/sn/mapping/monitor/add")
|
||||
@ApiModelProperty(value = "配置监控接口")
|
||||
public Boolean addMonitorMap(String supervisor, String monitored) {
|
||||
if(StringUtils.isEmpty(supervisor) || StringUtils.isEmpty(monitored)){
|
||||
return false;
|
||||
}
|
||||
sessionCache.snToMonitorMap.clear();
|
||||
sessionCache.snToMonitorMap.put(monitored,supervisor);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询监控关系
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sn/mapping/monitor/get")
|
||||
@ApiModelProperty(value = "查询监控关系接口")
|
||||
public Map<String,String> getMonitorMap() {
|
||||
return sessionCache.snToMonitorMap;
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.platform.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class ManyToMany implements Serializable {
|
||||
private List<String> source;
|
||||
private List<String> target;
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package com.platform.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class OneToMany implements Serializable {
|
||||
private String source;
|
||||
private List<String> target;
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package com.platform.service;
|
||||
|
||||
import com.platform.config.ServiceConfig;
|
||||
import com.platform.util.SessionCache;
|
||||
import com.platform.util.StringUtil;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.handler.codec.bytes.ByteArrayDecoder;
|
||||
import io.netty.handler.codec.bytes.ByteArrayEncoder;
|
||||
import io.netty.handler.timeout.IdleStateHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ServerService {
|
||||
|
||||
public ChannelFuture mChannelFuture;
|
||||
|
||||
@Autowired
|
||||
private ServiceConfig config;
|
||||
@Autowired
|
||||
private StringUtil stringUtil;
|
||||
@Autowired
|
||||
private SessionCache sessionCache;
|
||||
|
||||
private void startServer() {
|
||||
//服务端需要2个线程组 boss处理客户端连接 work进行客服端连接之后的处理
|
||||
log.warn("【读取配置端口】 端口 = " + config.getPort());
|
||||
EventLoopGroup boss = new NioEventLoopGroup();
|
||||
EventLoopGroup work = new NioEventLoopGroup(10);
|
||||
try {
|
||||
ServerBootstrap bootstrap = new ServerBootstrap();
|
||||
//服务器 配置
|
||||
bootstrap.group(boss, work);
|
||||
bootstrap.channel(NioServerSocketChannel.class);
|
||||
bootstrap.childHandler(new ChannelInitializer<Channel>() {
|
||||
@Override
|
||||
protected void initChannel(Channel channel) throws Exception {
|
||||
channel.pipeline().addLast(new ByteArrayDecoder());
|
||||
channel.pipeline().addLast(new ByteArrayEncoder());
|
||||
channel.pipeline().addLast(new IdleStateHandler(0, 0,
|
||||
60 * 24, TimeUnit.MINUTES));
|
||||
channel.pipeline().addLast(new InMessageHandler(sessionCache, stringUtil, config));
|
||||
}
|
||||
});
|
||||
|
||||
bootstrap.option(ChannelOption.SO_BACKLOG, 2048);
|
||||
bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
|
||||
bootstrap.childOption(ChannelOption.TCP_NODELAY, true);
|
||||
mChannelFuture = bootstrap.bind(config.getPort()).sync();
|
||||
mChannelFuture.channel().closeFuture().sync();
|
||||
log.warn("【服务器启动成功========端口:" + config.getPort() + "】");
|
||||
} catch (Exception e) {
|
||||
log.error("【服务器启动失败】", e);
|
||||
} finally {
|
||||
//关闭资源
|
||||
boss.shutdownGracefully();
|
||||
work.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
@PostConstruct()
|
||||
public void init() {
|
||||
log.warn("【初始化......】");
|
||||
//需要开启一个新的线程来执行netty server 服务器
|
||||
new Thread(() -> startServer()).start();
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package com.platform.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class ControlDevice {
|
||||
|
||||
private static final HashMap<Byte, String> deviceSnToFkID = new HashMap<Byte, String>(){{
|
||||
put((byte) 0x11,"D80A72");
|
||||
put((byte) 0x13,"D80B00");
|
||||
put((byte) 0x23,"D80AD8");
|
||||
put((byte) 0x24,"D80A83");
|
||||
put((byte) 0x25,"D80A87");
|
||||
put((byte) 0x30,"D80A88");
|
||||
put((byte) 0x31,"D80B0A");
|
||||
put((byte) 0x32,"D80AB6");
|
||||
|
||||
put((byte) 0x01,"F492C1");
|
||||
put((byte) 0x02,"F492C2");
|
||||
put((byte) 0x03,"F492C3");
|
||||
put((byte) 0xff,"all");
|
||||
|
||||
}};
|
||||
|
||||
public static String getSn(Byte fkID){return deviceSnToFkID.get(fkID);}
|
||||
|
||||
public static boolean isTure(Byte fkID){return deviceSnToFkID.containsKey(fkID);}
|
||||
|
||||
|
||||
public static int getFk(String uavId){
|
||||
int fk = 0;
|
||||
for(Byte key: deviceSnToFkID.keySet()){
|
||||
if(deviceSnToFkID.get(key).equals(uavId)){
|
||||
fk = key;
|
||||
}
|
||||
}
|
||||
return fk;
|
||||
}
|
||||
|
||||
|
||||
public static Map<String, String> currenCtrDevice = new ConcurrentHashMap<>(16); // 设备编号对应的mac地址
|
||||
|
||||
|
||||
public static void clearCurrenCtrDeviceByMac(String mac){
|
||||
|
||||
for(String key: currenCtrDevice.keySet()){
|
||||
if(currenCtrDevice.get(key).equals(mac)){
|
||||
currenCtrDevice.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<String> getCurrenCtrDevicesByMac(String mac){
|
||||
|
||||
List<String> ctrDevices = new ArrayList<>();
|
||||
for(String key: currenCtrDevice.keySet()){
|
||||
if(currenCtrDevice.get(key).equals(mac)){
|
||||
ctrDevices.add(key);
|
||||
}
|
||||
}
|
||||
return ctrDevices;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
package com.platform.util;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import io.netty.channel.Channel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class SessionCache {
|
||||
|
||||
public Map<String, Channel> tcpSession = new ConcurrentHashMap<>(16);
|
||||
|
||||
public Map<String, String> addToSnMap = new ConcurrentHashMap<>(16); // ip地址对应的设备编号
|
||||
public Map<String, String> snToAddMap = new ConcurrentHashMap<>(16); // 设备编号对应的ip地址
|
||||
public Map<String, String> snToSnMap = new ConcurrentHashMap<>(16); //一对一映射关系
|
||||
public Map<String, String> snToMonitorMap = new ConcurrentHashMap<>(16); //监控映射
|
||||
public Map<String, List<String>> mappingListMap = new ConcurrentHashMap<>(16); //所有映射关系
|
||||
public Map<String, List<String>> snToListMap = new ConcurrentHashMap<>(16); //一对多映射关系
|
||||
public List<String> snList = new ArrayList<>();
|
||||
|
||||
public Optional<Channel> findTargetChannel(String sourceAddr) {
|
||||
String sSn = addToSnMap.get(sourceAddr);
|
||||
String tSn = snToSnMap.get(sSn);
|
||||
if (tSn == null) {
|
||||
log.warn("找不到" + sourceAddr + "的目标映射;" +
|
||||
"addToSnMap = " + JSON.toJSONString(addToSnMap) + "; " +
|
||||
"snToSnMap = " + JSON.toJSONString(snToSnMap));
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
String targetAddr = snToAddMap.get(tSn);
|
||||
if (targetAddr == null) {
|
||||
log.warn("目标映射" + tSn + "的地址找不到; " +
|
||||
"snToAddMap = " + JSON.toJSONString(snToAddMap));
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Channel c = tcpSession.get(targetAddr);
|
||||
if (c == null) {
|
||||
log.warn("目标地址" + targetAddr + "的session channel找不到; " +
|
||||
"tcpSession = " + JSON.toJSONString(tcpSession));
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.of(c);
|
||||
}
|
||||
|
||||
public Optional<Channel> findMonitorChannel(String sourceAddr) {
|
||||
String sSn = addToSnMap.get(sourceAddr);
|
||||
String tSn = snToMonitorMap.get(sSn);
|
||||
if (tSn == null) {
|
||||
log.warn("找不到" + sourceAddr + "的目标映射;" +
|
||||
"addToSnMap = " + JSON.toJSONString(addToSnMap) + "; " +
|
||||
"snToMonitorMap = " + JSON.toJSONString(snToMonitorMap));
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
String targetAddr = snToAddMap.get(tSn);
|
||||
if (targetAddr == null) {
|
||||
log.warn("目标映射" + tSn + "的地址找不到; " +
|
||||
"snToAddMap = " + JSON.toJSONString(snToAddMap));
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
Channel c = tcpSession.get(targetAddr);
|
||||
if (c == null) {
|
||||
log.warn("目标地址" + targetAddr + "的session channel找不到; " +
|
||||
"tcpSession = " + JSON.toJSONString(tcpSession));
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.of(c);
|
||||
}
|
||||
|
||||
public List<Channel> findManyTargetChannel(String sSn) {
|
||||
List<Channel> channel = new ArrayList<>();
|
||||
List<String> tSn = snToListMap.get(sSn);
|
||||
|
||||
if (!ObjectUtils.isEmpty(tSn)) {
|
||||
tSn.forEach(s -> {
|
||||
String targetAddr = snToAddMap.get(s);
|
||||
if (targetAddr != null) {
|
||||
Channel c = tcpSession.get(targetAddr);
|
||||
if (c == null) {
|
||||
log.warn("targetAddr " + targetAddr + " channel is null" + ", tcpSession = " + JSON.toJSONString(tcpSession));
|
||||
} else {
|
||||
channel.add(c);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
public List<Channel> findMappingTargetChannel(String sSn) {
|
||||
List<Channel> channel = new ArrayList<>();
|
||||
List<String> tSn = mappingListMap.get(sSn); // 设备的映射关系
|
||||
|
||||
if (!ObjectUtils.isEmpty(tSn)) {
|
||||
tSn.forEach(s -> { //
|
||||
String targetAddr = snToAddMap.get(s); // 根据设备编号找到ip地址
|
||||
if (targetAddr != null) {
|
||||
Channel c = tcpSession.get(targetAddr); // 根据ip找到通道
|
||||
if (c == null) {
|
||||
log.warn("targetAddr " + targetAddr + " channel is null" + ", tcpSession = " + JSON.toJSONString(tcpSession));
|
||||
} else {
|
||||
channel.add(c);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return channel;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* channel找ip地址
|
||||
*/
|
||||
|
||||
public String findSnByChannel(Channel channel){
|
||||
String fk = null;
|
||||
for(String key: tcpSession.keySet()){
|
||||
if(tcpSession.get(key).equals(channel)){
|
||||
fk = key;
|
||||
}
|
||||
}
|
||||
return fk;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,390 @@
|
||||
package com.platform.util;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Component
|
||||
public class StringUtil {
|
||||
|
||||
private static Pattern pattern = Pattern.compile("\\b\\w+:\\w+:\\w+:\\w+:\\w+:\\w+\\b");
|
||||
|
||||
/**
|
||||
* Convert the hex string to byte array;
|
||||
*
|
||||
* @param strHexValue the hex string value.
|
||||
* @return byte[] the resolved value.
|
||||
*/
|
||||
public byte[] stringToByteArray(String strHexValue) {
|
||||
String[] strAryHex = strHexValue.split(" ");
|
||||
byte[] btAryHex = new byte[strAryHex.length];
|
||||
|
||||
try {
|
||||
int nIndex = 0;
|
||||
for (String strTemp : strAryHex) {
|
||||
btAryHex[nIndex] = (byte) Integer.parseInt(strTemp, 16);
|
||||
nIndex++;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
|
||||
}
|
||||
|
||||
return btAryHex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the Hex string array to byte array
|
||||
*
|
||||
* @param strAryHex the hex string value.
|
||||
* @param nLen the needed parse length.
|
||||
* @return byte[] the resolved value.
|
||||
*/
|
||||
public byte[] stringArrayToByteArray(String[] strAryHex, int nLen) {
|
||||
if (strAryHex == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (strAryHex.length < nLen) {
|
||||
nLen = strAryHex.length;
|
||||
}
|
||||
|
||||
byte[] btAryHex = new byte[nLen];
|
||||
|
||||
try {
|
||||
for (int i = 0; i < nLen; i++) {
|
||||
btAryHex[i] = (byte) Integer.parseInt(strAryHex[i], 16);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
|
||||
}
|
||||
|
||||
return btAryHex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the Hex string array to byte array
|
||||
*
|
||||
* @param btAryHex the hex string value.
|
||||
* @param nIndex the starting parse position.
|
||||
* @param nLen the needed parse length.
|
||||
* @return byte[] the resolved value.
|
||||
*/
|
||||
public String byteArrayToString(byte[] btAryHex, int nIndex, int nLen) {
|
||||
if (nIndex + nLen > btAryHex.length) {
|
||||
nLen = btAryHex.length - nIndex;
|
||||
}
|
||||
|
||||
String strResult = String.format("%02X", btAryHex[nIndex]);
|
||||
for (int nloop = nIndex + 1; nloop < nIndex + nLen; nloop++) {
|
||||
String strTemp = String.format(" %02X", btAryHex[nloop]);
|
||||
|
||||
strResult += strTemp;
|
||||
}
|
||||
|
||||
return strResult;
|
||||
}
|
||||
|
||||
public String bytesToHexString(byte[] bArray) {
|
||||
StringBuffer sb = new StringBuffer(bArray.length);
|
||||
String sTemp;
|
||||
for (int i = 0; i < bArray.length; i++) {
|
||||
sTemp = Integer.toHexString(0xFF & bArray[i]);
|
||||
if (sTemp.length() < 2) {
|
||||
sb.append(0);
|
||||
}
|
||||
sb.append(sTemp.toUpperCase());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the String to StringArray
|
||||
*
|
||||
* @param strValue the src string
|
||||
* @param nLen needed convert length
|
||||
* @return String[] the parsed value.
|
||||
*/
|
||||
public String[] stringToStringArray(String strValue, int nLen) {
|
||||
String[] strAryResult = null;
|
||||
|
||||
if (strValue != null && !"".equals(strValue)) {
|
||||
ArrayList<String> strListResult = new ArrayList<String>();
|
||||
String strTemp = "";
|
||||
int nTemp = 0;
|
||||
|
||||
for (int nloop = 0; nloop < strValue.length(); nloop++) {
|
||||
if (strValue.charAt(nloop) == ' ') {
|
||||
continue;
|
||||
} else {
|
||||
nTemp++;
|
||||
|
||||
if (!pattern.matcher(strValue.substring(nloop, nloop + 1)).matches()) {
|
||||
return strAryResult;
|
||||
}
|
||||
|
||||
strTemp += strValue.substring(nloop, nloop + 1);
|
||||
|
||||
if ((nTemp == nLen) || (nloop == strValue.length() - 1
|
||||
&& (strTemp != null && !"".equals(strTemp)))) {
|
||||
strListResult.add(strTemp);
|
||||
nTemp = 0;
|
||||
strTemp = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strListResult.size() > 0) {
|
||||
strAryResult = new String[strListResult.size()];
|
||||
for (int i = 0; i < strAryResult.length; i++) {
|
||||
strAryResult[i] = strListResult.get(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return strAryResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the byte array to special encode char array.
|
||||
*
|
||||
* @param bytes the needed byte array.
|
||||
* @param encoding the encoding format.
|
||||
* @return char[] the converted char array.
|
||||
*/
|
||||
@Deprecated
|
||||
public char[] getChars(byte[] bytes, String encoding) {
|
||||
Charset cs = Charset.forName(encoding);
|
||||
ByteBuffer bb = ByteBuffer.allocate(bytes.length);
|
||||
bb.put(bytes);
|
||||
bb.flip();
|
||||
CharBuffer cb = cs.decode(bb);
|
||||
return cb.array();
|
||||
}
|
||||
|
||||
/**
|
||||
* resolve the bytes String data to ASCII.String like this "2f3Eab"
|
||||
*
|
||||
* @param hexString the needed parse data.
|
||||
* @return String the return value.
|
||||
*/
|
||||
@Deprecated
|
||||
public String toASCIIString(String hexString) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
int i = 0;
|
||||
while (i < hexString.length()) {
|
||||
stringBuilder.append((char) Integer.parseInt(hexString.substring(i, i + 2), 16));
|
||||
i = i + 2;
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the bytes String data to ASCII.String like this "2f3Eab"
|
||||
*
|
||||
* @param hexString the needed parse data.
|
||||
* @return String the return value.
|
||||
*/
|
||||
public String hexStringToASCIIString(String hexString) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
if (hexString == null || "".equals(hexString)) {
|
||||
return null;
|
||||
}
|
||||
for (int i = 0; i < hexString.length(); i = i + 2) {
|
||||
char high = hexString.charAt(i);
|
||||
char low = hexString.charAt(i + 1);
|
||||
|
||||
char no = (char) (charToInt(high) * 16 + charToInt(low));
|
||||
stringBuilder.append(no);
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the char 1-f to int value;
|
||||
*
|
||||
* @param c the needed converter character.
|
||||
* @return int the converted value.
|
||||
*/
|
||||
|
||||
private int charToInt(char c) {
|
||||
int num = -1;
|
||||
num = "0123456789ABCDEF".indexOf(String.valueOf(c));
|
||||
if (num < 0) {
|
||||
num = "0123456789abcdef".indexOf(String.valueOf(c));
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sub bytes of the parent bytes;
|
||||
*
|
||||
* @param bytes parent bytes;
|
||||
* @param start start position;
|
||||
* @param end end position;
|
||||
* @return the child bytes;
|
||||
*/
|
||||
public byte[] subBytes(byte[] bytes, int start, int end) {
|
||||
byte[] subBytes = new byte[end - start];
|
||||
System.arraycopy(bytes, start, subBytes, 0, end - start);
|
||||
return subBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the child position in their parents string
|
||||
*
|
||||
* @param parentBytes parent bytes;
|
||||
* @param childBytes child bytes;
|
||||
* @param startPosition start scan position;
|
||||
* @return if -1 child not in parent string,or the child first position found in parent;
|
||||
*/
|
||||
public int subBytesContains(byte[] parentBytes, byte[] childBytes, int startPosition) {
|
||||
if (parentBytes.length < childBytes.length) {
|
||||
return -1;
|
||||
}
|
||||
for (int i = startPosition; i < parentBytes.length; i++) {
|
||||
for (int j = 0; j < childBytes.length; j++) {
|
||||
if (parentBytes[i + j] == childBytes[j]) {
|
||||
if (j == childBytes.length - 1) {
|
||||
return i;
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert hexString to byte array.
|
||||
*
|
||||
* @param hexString to bytes
|
||||
* @return The converted byte array.
|
||||
*/
|
||||
public byte[] hexStringToBytes(String hexString) {
|
||||
byte[] bytes = new byte[hexString.length() / 2];
|
||||
if (hexString == null || "".equals(hexString)) {
|
||||
return null;
|
||||
}
|
||||
for (int i = 0; i < hexString.length(); i = i + 2) {
|
||||
char high = hexString.charAt(i);
|
||||
char low = hexString.charAt(i + 1);
|
||||
|
||||
bytes[i / 2] = (byte) (charToInt(high) * 16 + charToInt(low));
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
/**
|
||||
* 将十六进制的字符串转换成字节数组
|
||||
*
|
||||
* @param hexString
|
||||
* @return
|
||||
*/
|
||||
public byte[] hexStrToBinaryStr(String hexString) {
|
||||
if (hexString=="") {
|
||||
return null;
|
||||
}
|
||||
hexString = hexString.replaceAll(" ", "");
|
||||
int len = hexString.length();
|
||||
int index = 0;
|
||||
byte[] bytes = new byte[len / 2];
|
||||
while (index < len) {
|
||||
String sub = hexString.substring(index, index + 2);
|
||||
bytes[index/2] = (byte)Integer.parseInt(sub,16);
|
||||
index += 2;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
/**
|
||||
* Compare the both byte array
|
||||
*
|
||||
* @param first the first byte array
|
||||
* @param second the second byte array
|
||||
* @return if true first equals second ,otherwise unequal
|
||||
*/
|
||||
public boolean compareBytes(byte[] first, byte[] second) {
|
||||
if (first.length != second.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < first.length; i++) {
|
||||
if (first[i] != second[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert Ascii string to byte array.
|
||||
*
|
||||
* @param string the needed converter data.
|
||||
* @return byte[] the converted value.
|
||||
*/
|
||||
public byte[] asciiStringToBytes(String string) {
|
||||
byte[] result = new byte[string.length()];
|
||||
for (int i = 0; i < string.length(); i++) {
|
||||
result[i] = (byte) string.charAt(i);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public String computeCRC(String data) {
|
||||
data = data.replace(" ", "");
|
||||
int len = data.length();
|
||||
if (!(len % 2 == 0)) {
|
||||
return "0000";
|
||||
}
|
||||
int num = len / 2;
|
||||
byte[] para = new byte[num];
|
||||
for (int i = 0; i < num; i++) {
|
||||
int value = Integer.valueOf(data.substring(i * 2, 2 * (i + 1)), 16);
|
||||
para[i] = (byte) value;
|
||||
}
|
||||
return getCRC(para);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算CRC16校验码
|
||||
*
|
||||
* @param bytes
|
||||
* 字节数组
|
||||
* @return {@link String} 校验码
|
||||
* @since 1.0
|
||||
*/
|
||||
public String getCRC(byte[] bytes) {
|
||||
// CRC寄存器全为1
|
||||
int CRC = 0x0000ffff;
|
||||
// 多项式校验值
|
||||
int POLYNOMIAL = 0x0000a001;
|
||||
int i, j;
|
||||
for (i = 0; i < bytes.length; i++) {
|
||||
CRC ^= ((int) bytes[i] & 0x000000ff);
|
||||
for (j = 0; j < 8; j++) {
|
||||
if ((CRC & 0x00000001) != 0) {
|
||||
CRC >>= 1;
|
||||
CRC ^= POLYNOMIAL;
|
||||
} else {
|
||||
CRC >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 结果转换为16进制
|
||||
String result = Integer.toHexString(CRC).toUpperCase();
|
||||
if (result.length() != 4) {
|
||||
StringBuffer sb = new StringBuffer("0000");
|
||||
result = sb.replace(4 - result.length(), 4, result).toString();
|
||||
}
|
||||
//高位在前地位在后
|
||||
//return result.substring(2, 4) + " " + result.substring(0, 2);
|
||||
// 交换高低位,低位在前高位在后
|
||||
return result.substring(2, 4) + " " + result.substring(0, 2);
|
||||
}
|
||||
|
||||
public static int byteToInt(byte b) {
|
||||
return (b) & 0xff;
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
server:
|
||||
port: 11727
|
||||
service:
|
||||
port: 11728
|
||||
log:
|
||||
debug: false
|
@ -0,0 +1,3 @@
|
||||
spring:
|
||||
profiles:
|
||||
active: dev
|
Loading…
Reference in New Issue