Преглед на файлове

非nacos北斗辅助定位项目代码提交

develop
林万龙 преди 3 години
родител
ревизия
824e3d57b0
променени са 44 файла, в които са добавени 3527 реда и са изтрити 0 реда
  1. +2
    -0
      .idea/.gitignore
  2. +9
    -0
      .idea/BeidouAstPos.iml
  3. +6
    -0
      .idea/google-java-format.xml
  4. +36
    -0
      .idea/inspectionProfiles/Project_Default.xml
  5. +6
    -0
      .idea/misc.xml
  6. +8
    -0
      .idea/modules.xml
  7. +6
    -0
      .idea/vcs.xml
  8. +148
    -0
      pom.xml
  9. +64
    -0
      setup_dev.sh
  10. +53
    -0
      src/main/java/com/telpo/beidouast/BaidouAstApplication.java
  11. +22
    -0
      src/main/java/com/telpo/beidouast/annotation/MongoSwitch.java
  12. +35
    -0
      src/main/java/com/telpo/beidouast/co/PositionConfigInfo.java
  13. +87
    -0
      src/main/java/com/telpo/beidouast/common/CSVUtil.java
  14. +140
    -0
      src/main/java/com/telpo/beidouast/common/HexConvert.java
  15. +154
    -0
      src/main/java/com/telpo/beidouast/common/OkHttpUtil.java
  16. +665
    -0
      src/main/java/com/telpo/beidouast/common/RedisUtil.java
  17. +98
    -0
      src/main/java/com/telpo/beidouast/common/SocketClient.java
  18. +69
    -0
      src/main/java/com/telpo/beidouast/config/AsyncExecutorConfig.java
  19. +99
    -0
      src/main/java/com/telpo/beidouast/config/OkHttpConfig.java
  20. +61
    -0
      src/main/java/com/telpo/beidouast/config/PositionConfig.java
  21. +53
    -0
      src/main/java/com/telpo/beidouast/config/SchedulingExecutorConfig.java
  22. +65
    -0
      src/main/java/com/telpo/beidouast/config/db/MongoDbContext.java
  23. +30
    -0
      src/main/java/com/telpo/beidouast/config/db/MongoListProperties.java
  24. +26
    -0
      src/main/java/com/telpo/beidouast/config/db/MultiMongoTemplate.java
  25. +26
    -0
      src/main/java/com/telpo/beidouast/controller/DipperPositionController.java
  26. +24
    -0
      src/main/java/com/telpo/beidouast/entity/mongo/IPProvinceEntity.java
  27. +53
    -0
      src/main/java/com/telpo/beidouast/enums/DipperReturnValue.java
  28. +181
    -0
      src/main/java/com/telpo/beidouast/handler/NettyServerHandler.java
  29. +24
    -0
      src/main/java/com/telpo/beidouast/handler/ServerChannelInitializer.java
  30. +58
    -0
      src/main/java/com/telpo/beidouast/mapper/IPProvinceMapper.java
  31. +257
    -0
      src/main/java/com/telpo/beidouast/server/DipperPositionServer.java
  32. +27
    -0
      src/main/java/com/telpo/beidouast/service/IDipperAstPosAsyncTaskService.java
  33. +17
    -0
      src/main/java/com/telpo/beidouast/service/IDipperAstTimeAsyncTaskService.java
  34. +28
    -0
      src/main/java/com/telpo/beidouast/service/IDipperDataAsyncTaskService.java
  35. +45
    -0
      src/main/java/com/telpo/beidouast/service/IPProvinceService.java
  36. +247
    -0
      src/main/java/com/telpo/beidouast/service/impl/DipperAstPosAsyncTaskServiceImpl.java
  37. +106
    -0
      src/main/java/com/telpo/beidouast/service/impl/DipperAstTimeAsyncTaskServiceImpl.java
  38. +68
    -0
      src/main/java/com/telpo/beidouast/service/impl/DipperDataAsyncTaskServiceImpl.java
  39. +62
    -0
      src/main/java/com/telpo/beidouast/service/impl/IPProvinceServiceImpl.java
  40. +40
    -0
      src/main/java/com/telpo/beidouast/task/ScheduleService.java
  41. +20
    -0
      src/main/java/com/telpo/beidouast/vo/IPProvinceVo.java
  42. +69
    -0
      src/main/resources/bootstrap.yaml
  43. +35
    -0
      src/main/resources/csv/provinceLonAlt.csv
  44. +198
    -0
      src/main/resources/log/logback-spring.xml

+ 2
- 0
.idea/.gitignore Целия файл

@@ -0,0 +1,2 @@
# Default ignored files
/workspace.xml

+ 9
- 0
.idea/BeidouAstPos.iml Целия файл

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

+ 6
- 0
.idea/google-java-format.xml Целия файл

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GoogleJavaFormatSettings">
<option name="enabled" value="false" />
</component>
</project>

+ 36
- 0
.idea/inspectionProfiles/Project_Default.xml Целия файл

@@ -0,0 +1,36 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true">
<option name="TOP_LEVEL_CLASS_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="INNER_CLASS_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="METHOD_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="@return@param@throws or @exception" />
</value>
</option>
<option name="FIELD_OPTIONS">
<value>
<option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
<option name="REQUIRED_TAGS" value="" />
</value>
</option>
<option name="IGNORE_DEPRECATED" value="false" />
<option name="IGNORE_JAVADOC_PERIOD" value="true" />
<option name="IGNORE_DUPLICATED_THROWS" value="false" />
<option name="IGNORE_POINT_TO_ITSELF" value="false" />
<option name="myAdditionalJavadocTags" value="date" />
</inspection_tool>
</profile>
</component>

+ 6
- 0
.idea/misc.xml Целия файл

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
</project>

+ 8
- 0
.idea/modules.xml Целия файл

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/BeidouAstPos.iml" filepath="$PROJECT_DIR$/.idea/BeidouAstPos.iml" />
</modules>
</component>
</project>

+ 6
- 0
.idea/vcs.xml Целия файл

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

+ 148
- 0
pom.xml Целия файл

@@ -0,0 +1,148 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.telpo</groupId>
<artifactId>beidouast</artifactId>
<version>1.0-SNAPSHOT</version>
<name>beidouast</name>
<description>北斗定位服务</description>
<packaging>jar</packaging>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<spring-cloud-alibaba.version>2.2.0.RELEASE</spring-cloud-alibaba.version>
<spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
<skipTests>true</skipTests>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

<!--天波通用包-->
<dependency>
<groupId>com.telpo</groupId>
<artifactId>common</artifactId>
<version>1.1.19</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>

<!-- Yaml -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.25</version>
</dependency>

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.28</version>
</dependency>

<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.13.Final</version>
</dependency>

<!-- 开启redis缓存 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- redis依赖commons-pool 这个依赖一定要添加 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>

<!-- https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.8.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/de.codecentric/spring-boot-admin-starter-client -->
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.2.4</version>
</dependency>

<!-- https://mvnrepository.com/artifact/net.sourceforge.javacsv/javacsv -->
<dependency>
<groupId>net.sourceforge.javacsv</groupId>
<artifactId>javacsv</artifactId>
<version>2.0</version>
</dependency>

<dependency>
<groupId>com.mongodb</groupId>
<artifactId>mongo</artifactId>
<version>1.0</version>
</dependency>

</dependencies>

<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!--fork : 使用 devtools生效-->
<fork>true</fork>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal><!--可以把依赖的包都打包到生成的Jar包中-->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

+ 64
- 0
setup_dev.sh Целия файл

@@ -0,0 +1,64 @@
#!/bin/bash
mvn clean
mvn package -Dmaven.test.skip=true
#image_version=$(date +%Y%m%d%H%M)
image_version=$version

docker cp docker_jenkins:/var/jenkins_home/workspace/beidou_ast/target/beidouast.jar /usr/local/beidou_ast/beidou_ast.jar
#docker stop dipperposition_service || true
#docker rm dipperposition_service || true

# 删除镜像
#docker rmi -f $(docker images | grep telpo/dipperposition_service | awk '{print $3}')

#docker build . -t telpo/dipperposition_service:$image_version

#TODO:推送镜像到私有仓库
#echo '=================开始推送镜像======================='
#docker tag telpo/dipperposition_service:$image_version 139.224.254.18:5000/dipperposition_service:$image_version
#docker push 139.224.254.18:5000/dipperposition_service:$image_version
#echo '=================推送镜像完成======================='

#删除产生的None镜像
#docker rmi -f $(docker images | grep none | awk '{print $3}')
# 查看镜像列表
#docker images
# 启动容器
#docker run -v /home/data/dipperposition/log:/var/log/dipperposition -d -e active=dev --network host --restart=always
# -p 9011:9011 -p 9012:9012 -p 9013:9013 --name dipperposition_service 139.224.254.18:5000/dipperposition_service:$image_version

#echo "scp ${WORKSPACE} files......begin"
#set passwd "telpo#1234"
#scp /var/jenkins_home/workspace/dipperpos_service/target/dipperposition.jar root@47.116.142.20:/home/data/dipperposition/dipperposition.jar
#expect {
# "密码:"
# {
# send "$passwd\n"
# }
# "pass"
# {
# send "$passwd\n"
# }
#
# "yes/no"
# {
# sleep 5
# send_user "send yes"
# send "yes\n"
# }
# eof
# {
# sleep 5
# send_user "eof\n"
# }
#}
#send "exit\r"
#expect eof
#echo "scp ${WORKSPACE} files......end"
# 查看日志
# docker logs dipperposition_service

echo '=================启动NettyAPP======================='
ps -ef |grep beidou |awk '{print $2}'|xargs kill -9
java -jar -Xms256m -Xmx256m -Xss256k -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m /usr/local/beidou_ast/beidouast.jar
echo '=================完成NettyAPP启动======================='

+ 53
- 0
src/main/java/com/telpo/beidouast/BaidouAstApplication.java Целия файл

@@ -0,0 +1,53 @@
package com.telpo.dipperposition;

import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.exception.NacosException;
import com.telpo.dipperposition.co.PositionConfigInfo;
import com.telpo.dipperposition.server.DipperPositionServer;
import com.telpo.dipperposition.server.EphAsyncServer;
import com.telpo.dipperposition.server.TimeAsyncServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

import java.util.Properties;
import java.util.concurrent.Executor;

/**
* @program: gateway
* @description: 网关启动类
* @author: linwl
* @create: 2020-06-18 16:39
*/
@SpringBootApplication
@EnableDiscoveryClient
@ConfigurationPropertiesScan
@EnableAsync
@EnableScheduling
@Slf4j
public class BaidouAstApplication {

public static void main(String[] args) {
try {
log.info("北斗定位服务开始!");
ConfigurableApplicationContext applicationContext = SpringApplication.run(BaidouAstApplication.class, args);
log.info("北斗定位服务启动!");
//启动服务端
ConfigurableEnvironment environment = applicationContext.getEnvironment();
DipperPositionServer nettyServer = new DipperPositionServer(environment);
nettyServer.start2();
} catch (Exception e) {
log.error(e.getMessage());
}
}
}

+ 22
- 0
src/main/java/com/telpo/beidouast/annotation/MongoSwitch.java Целия файл

@@ -0,0 +1,22 @@
package com.telpo.dipperposition.annotation;

import java.lang.annotation.*;

/**
* @program: DataPushServer
* @description: mongo数据源切换注解
* @author: linwl
* @create: 2020-07-11 15:06
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MongoSwitch {

/**
* mongo数据库名称
*
* @return
*/
String value() default "";
}

+ 35
- 0
src/main/java/com/telpo/beidouast/co/PositionConfigInfo.java Целия файл

@@ -0,0 +1,35 @@
package com.telpo.dipperposition.co;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import okhttp3.*;
import okhttp3.internal.ws.RealWebSocket;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.net.SocketFactory;

/**
* @program: RzlAccount
* @description: 融智联账号配置
* @author: king
* @create: 2021-01-12 14:02
**/
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "position-server")
public class PositionConfigInfo {

private String serverAddr;

private String timeAsycPort;

private String posAsycPort;

private String starsAsycPort;

}

+ 87
- 0
src/main/java/com/telpo/beidouast/common/CSVUtil.java Целия файл

@@ -0,0 +1,87 @@
package com.telpo.dipperposition.common;

import com.csvreader.CsvReader;
import com.csvreader.CsvWriter;

import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
/**
* @program: dipperposition
* @description: CSV文件读取单元
* @author: linwl
* @create: 2021-01-14 11:19
**/
public class CSVUtil {
/**
* 读取每行的数据
*
* @param readPath
* @return
*/
public static List<String> readCSV(String readPath) {
String filePath = readPath;
List<String> listData = new ArrayList<>();
try {
filePath = readPath;
CsvReader csvReader = new CsvReader(filePath);
// 读表头
boolean re = csvReader.readHeaders();
while (csvReader.readRecord()) {
String rawRecord = csvReader.getRawRecord();
listData.add(rawRecord);
}
return listData;
} catch (FileNotFoundException e) {
throw new RuntimeException("文件未找到");
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}

}

/**
* 写入文件头
* @param writePath
* @param header
*/
public static void writeCSV(String writePath, String[] header) {
String filePath = writePath;
try {
CsvWriter csvWriter = new CsvWriter(writePath, ',', Charset.forName("UTF-8"));
//String [] header = {"SkuId","SsuId","图片地址","大小(bit)","高度","宽度"};
csvWriter.writeRecord(header);
csvWriter.close();
} catch (Exception e) {
e.printStackTrace();
}

}

/**
* 利用输入输出流持续写
* @param fileName
* @param content
*/
public static void writeContent(String fileName, String content) {
FileWriter writer = null;
try {
// 打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
writer = new FileWriter(fileName, true);
writer.write(content + "\r\n");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (writer != null) {
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

+ 140
- 0
src/main/java/com/telpo/beidouast/common/HexConvert.java Целия файл

@@ -0,0 +1,140 @@
package com.telpo.dipperposition.common;

/**
* @program: dipperposition
* @description: 16进制处理
* @author: linwl
* @create: 2021-01-14 22:05
**/
public class HexConvert {
public static String convertStringToHex(String str){

char[] chars = str.toCharArray();

StringBuffer hex = new StringBuffer();
for(int i = 0; i < chars.length; i++){
hex.append(Integer.toHexString((int)chars[i]));
}

return hex.toString();
}

public static String convertHexToString(String hex){

StringBuilder sb = new StringBuilder();
StringBuilder sb2 = new StringBuilder();

for( int i=0; i<hex.length()-1; i+=2 ){

String s = hex.substring(i, (i + 2));
int decimal = Integer.parseInt(s, 16);
sb.append((char)decimal);
sb2.append(decimal);
}

return sb.toString();
}
public static byte[] hexStringToBytes(String hexString) {
if (hexString == null || hexString.equals("")) {
return null;
}
// toUpperCase将字符串中的所有字符转换为大写
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
// toCharArray将此字符串转换为一个新的字符数组。
char[] hexChars = hexString.toCharArray();
byte[] d = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return d;
}
//返回匹配字符
private static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}

//将字节数组转换为short类型,即统计字符串长度
public static short bytes2Short2(byte[] b) {
short i = (short) (((b[1] & 0xff) << 8) | b[0] & 0xff);
return i;
}

//将字节数组转换为16进制字符串
public static String BinaryToHexString(byte[] bytes) {
String hexStr = "0123456789ABCDEF";
String result = "";
String hex = "";
for (byte b : bytes) {
hex = String.valueOf(hexStr.charAt((b & 0xF0) >> 4));
hex += String.valueOf(hexStr.charAt(b & 0x0F));
result += hex + " ";
}
return result;
}

//將10進制轉換為16進制
public static String encodeHEX(long numb){

String hex= Long.toHexString(numb);
return hex;

}


//將16進制字符串轉換為10進制數字
public static long decodeHEX(String hexs){
long longValue= Long.parseLong("123ABC", 16);
return longValue;
}


/**
* 生成校验码的int值
* */
public static String makeChecksum(String data) {
if (data == null || data.equals("")) {
return "";
}
int total = 0;
int len = data.length();
int num = 0;
while (num < len) {
String s = data.substring(num, num + 2);
//System.out.println(s);
total += Integer.parseInt(s, 16);
num = num + 2;
}
/**
* 用256求余最大是255,即16进制的FF
*/
int mod = total % 256;
String hex = Integer.toHexString(mod);
len = hex.length();
// 如果不够校验位的长度,补0,这里用的是两位校验
if (len < 2) {
hex = "0" + hex;
}
return hex;
}
//
// public static void main(String[] args) {
//
//
// System.out.println("======ASCII码转换为16进制======");
// String str = "*00007VERSION\\n1$";
// System.out.println("字符串: " + str);
// String hex = HexConvert.convertStringToHex(str);
// System.out.println("====转换为16进制=====" + hex);
//
// System.out.println("======16进制转换为ASCII======");
// System.out.println("Hex : " + hex);
// System.out.println("ASCII : " + HexConvert.convertHexToString(hex));
//
// byte[] bytes = HexConvert.hexStringToBytes( hex );
//
// System.out.println(HexConvert.BinaryToHexString( bytes ));
// }

}

+ 154
- 0
src/main/java/com/telpo/beidouast/common/OkHttpUtil.java Целия файл

@@ -0,0 +1,154 @@
package com.telpo.dipperposition.common;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.text.MessageFormat;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;

/**
* @program: DataPushServer
* @description: okhttp工具类
* @author: linwl
* @create: 2020-07-17 15:43
*/
@Slf4j
@Component
public class OkHttpUtil {

@Autowired private OkHttpClient okHttpClient;

/**
* 根据map获取get请求参数
*
* @param queries
* @return
*/
public StringBuffer getQueryString(String url, Map<String, String> queries) {
StringBuffer sb = new StringBuffer(url);
if (queries != null && queries.keySet().size() > 0) {
boolean firstFlag = true;
Iterator iterator = queries.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry<String, String>) iterator.next();
if (firstFlag) {
sb.append("?" + entry.getKey() + "=" + entry.getValue());
firstFlag = false;
} else {
sb.append("&" + entry.getKey() + "=" + entry.getValue());
}
}
}
return sb;
}

/**
* get
*
* @param url 请求的url
* @param queries 请求的参数,在浏览器?后面的数据,没有可以传null
* @return
*/
public String get(String url, Map<String, String> queries) {
StringBuffer sb = getQueryString(url, queries);
Request request = new Request.Builder().url(sb.toString()).build();
log.debug(MessageFormat.format("发送Get to url<{0}>,参数为:{1}", url, queries));
return execNewCall(request);
}

/**
* post
*
* @param url 请求的url
* @param params post form 提交的参数
* @return
*/
public String postFormParams(String url, Map<String, String> params) {
FormBody.Builder builder = new FormBody.Builder();
// 添加参数
if (params != null && params.keySet().size() > 0) {
for (String key : params.keySet()) {
builder.add(key, params.get(key));
}
}
log.debug(MessageFormat.format("发送post from to url<{0}>,参数为:{1}", url, params));
Request request = new Request.Builder().url(url).post(builder.build()).build();
return execNewCall(request);
}

/** Post请求发送JSON数据....{"name":"zhangsan","pwd":"123456"} 参数一:请求Url 参数二:请求的JSON 参数三:请求回调 */
public String postJsonParams(String url, String jsonParams) {
RequestBody requestBody = RequestBody.create(jsonParams, MediaType.parse("application/json; charset=utf-8"));
Request request = new Request.Builder().url(url).post(requestBody).build();
log.debug(MessageFormat.format("发送post json to url<{0}>,参数为:{1}", url, jsonParams));
return execNewCall(request);
}

/** Post请求发送xml数据.... 参数一:请求Url 参数二:请求的xmlString 参数三:请求回调 */
public String postXmlParams(String url, String xml) {
RequestBody requestBody =
RequestBody.create(xml, MediaType.parse("application/xml; charset=utf-8"));
Request request = new Request.Builder().url(url).post(requestBody).build();
log.debug(MessageFormat.format("发送post xml to url<{0}>,参数为:{1}", url, xml));
return execNewCall(request);
}

/**
* 调用okhttp的newCall方法
*
* @param request
* @return
*/
private String execNewCall(Request request) {
try (Response response = okHttpClient.newCall(request).execute()) {
if (response.isSuccessful()) {
return Objects.requireNonNull(response.body()).string();
}
} catch (Exception e) {
log.error("okhttp3 put error >> ex = {}", ExceptionUtils.getStackTrace(e));
}
return "FAIL";
}

/**
* Post请求发送JSON数据....{"name":"zhangsan","pwd":"123456"} 参数一:请求Url 参数二:请求的JSON 参数三:请求回调
*/
public String postJsonParamsWithToken(String url, String token, String jsonParams) {
RequestBody requestBody =
RequestBody.create(jsonParams, MediaType.parse("application/json; charset=utf-8"));
Request request = new Request.Builder().url(url).
addHeader("Authorization", token).post(requestBody).build();
log.debug(MessageFormat.format("发送post json to url<{0}>,参数为:{1}", url, jsonParams));
return execNewCall(request);
}

public JSONObject postRequestWithJson(String url, String accessToken, JSONObject postData) {
String postResult;
if (ObjectUtils.isNotEmpty(accessToken)) {
postResult = postJsonParamsWithToken(url, accessToken, JSONObject.toJSONString(postData));
} else {
postResult = postJsonParams(url, JSONObject.toJSONString(postData));
}

if (postResult == null) {
log.error("访问错误");
return null;
} else {
log.debug(postResult);
if(("FAIL").equals(postResult.toString())) {
JSONObject object = new JSONObject();
object.put("result", "FAIL");
return object;
} else {
return JSONObject.parseObject(postResult);
}
}
}
}

+ 665
- 0
src/main/java/com/telpo/beidouast/common/RedisUtil.java Целия файл

@@ -0,0 +1,665 @@
package com.telpo.dipperposition.common;

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
* @program: DataPushServer
* @description: redis工具类
* @author: linwl
* @create: 2020-07-11 10:26
*/
@Component
@Slf4j
public class RedisUtil {

@Resource private RedisTemplate<String, Object> redisTemplate;

// =============================common============================
/**
* 指定缓存失效时间
*
* @param key 键
* @param time 时间(秒)
* @return
*/
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
log.error(key, e);
return false;
}
}

/**
* 根据key 获取过期时间
*
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}

/**
* 判断key是否存在
*
* @param key 键
* @return true 存在 false不存在
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
log.error(key, e);
return false;
}
}

/**
* 删除缓存
*
* @param key 可以传一个值 或多个
*/
@SuppressWarnings("unchecked")
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}

// ============================String=============================
/**
* 普通缓存获取
*
* @param key 键
* @return 值
*/
public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}

/**
* 普通缓存放入
*
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
log.error(key, e);
return false;
}
}

/**
* 普通缓存放入并设置时间
*
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public boolean set(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
log.error(key, e);
return false;
}
}

/**
* 递增 适用场景: https://blog.csdn.net/y_y_y_k_k_k_k/article/details/79218254 高并发生成订单号,秒杀类的业务逻辑等。。
*
* @param key 键
* @param delta 要增加几(大于0)
* @return
*/
public long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, delta);
}

/**
* 递减
*
* @param key 键
* @param delta 要减少几(小于0)
* @return
*/
public long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, -delta);
}

// ================================Map=================================
/**
* HashGet
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return 值
*/
public Object hget(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}

/**
* 获取hashKey对应的所有键值
*
* @param key 键
* @return 对应的多个键值
*/
public Map<Object, Object> hmget(String key) {
return redisTemplate.opsForHash().entries(key);
}

/**
* HashSet
*
* @param key 键
* @param map 对应多个键值
* @return true 成功 false 失败
*/
public boolean hmset(String key, Map<String, Object> map) {
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
log.error(key, e);
return false;
}
}

/**
* HashSet 并设置时间
*
* @param key 键
* @param map 对应多个键值
* @param time 时间(秒)
* @return true成功 false失败
*/
public boolean hmset(String key, Map<String, Object> map, long time) {
try {
redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
log.error(key, e);
return false;
}
}

/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {
log.error(key, e);
return false;
}
}

/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key 键
* @param item 项
* @param value 值
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value, long time) {
try {
redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
log.error(key, e);
return false;
}
}

/**
* 删除hash表中的值
*
* @param key 键 不能为null
* @param item 项 可以使多个 不能为null
*/
public void hdel(String key, Object... item) {
redisTemplate.opsForHash().delete(key, item);
}

/**
* 判断hash表中是否有该项的值
*
* @param key 键 不能为null
* @param item 项 不能为null
* @return true 存在 false不存在
*/
public boolean hHasKey(String key, String item) {
return redisTemplate.opsForHash().hasKey(key, item);
}

/**
* hash递增 如果不存在,就会创建一个 并把新增后的值返回
*
* @param key 键
* @param item 项
* @param by 要增加几(大于0)
* @return
*/
public double hincr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, by);
}

/**
* hash递减
*
* @param key 键
* @param item 项
* @param by 要减少记(小于0)
* @return
*/
public double hdecr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, -by);
}

// ============================set=============================
/**
* 根据key获取Set中的所有值
*
* @param key 键
* @return
*/
public Set<Object> sGet(String key) {
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
log.error(key, e);
return null;
}
}

/**
* 根据value从一个set中查询,是否存在
*
* @param key 键
* @param value 值
* @return true 存在 false不存在
*/
public boolean sHasKey(String key, Object value) {
try {
return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) {
log.error(key, e);
return false;
}
}

/**
* 将数据放入set缓存
*
* @param key 键
* @param values 值 可以是多个
* @return 成功个数
*/
public long sSet(String key, Object... values) {
try {
return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) {
log.error(key, e);
return 0;
}
}

/**
* 将set数据放入缓存
*
* @param key 键
* @param time 时间(秒)
* @param values 值 可以是多个
* @return 成功个数
*/
public long sSetAndTime(String key, long time, Object... values) {
try {
Long count = redisTemplate.opsForSet().add(key, values);
if (time > 0) {
expire(key, time);
}
return count;
} catch (Exception e) {
log.error(key, e);
return 0;
}
}

/**
* 获取set缓存的长度
*
* @param key 键
* @return
*/
public long sGetSetSize(String key) {
try {
return redisTemplate.opsForSet().size(key);
} catch (Exception e) {
log.error(key, e);
return 0;
}
}

/**
* 移除值为value的
*
* @param key 键
* @param values 值 可以是多个
* @return 移除的个数
*/
public long setRemove(String key, Object... values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values);
return count;
} catch (Exception e) {
log.error(key, e);
return 0;
}
}

// ============================zset=============================
/**
* 根据key获取Set中的所有值
*
* @param key 键
* @return
*/
public Set<Object> zSGet(String key) {
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
log.error(key, e);
return null;
}
}

/**
* 根据value从一个set中查询,是否存在
*
* @param key 键
* @param value 值
* @return true 存在 false不存在
*/
public boolean zSHasKey(String key, Object value) {
try {
return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) {
log.error(key, e);
return false;
}
}

public Boolean zSSet(String key, Object value, double score) {
try {
return redisTemplate.opsForZSet().add(key, value, 2);
} catch (Exception e) {
log.error(key, e);
return false;
}
}

/**
* 将set数据放入缓存
*
* @param key 键
* @param time 时间(秒)
* @param values 值 可以是多个
* @return 成功个数
*/
public long zSSetAndTime(String key, long time, Object... values) {
try {
Long count = redisTemplate.opsForSet().add(key, values);
if (time > 0) {
expire(key, time);
}
return count;
} catch (Exception e) {
log.error(key, e);
return 0;
}
}

/**
* 获取set缓存的长度
*
* @param key 键
* @return
*/
public long zSGetSetSize(String key) {
try {
return redisTemplate.opsForSet().size(key);
} catch (Exception e) {
log.error(key, e);
return 0;
}
}

/**
* 移除值为value的
*
* @param key 键
* @param values 值 可以是多个
* @return 移除的个数
*/
public long zSetRemove(String key, Object... values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values);
return count;
} catch (Exception e) {
log.error(key, e);
return 0;
}
}
// ===============================list=================================

/**
* 获取list缓存的内容 取出来的元素 总数 end-start+1
*
* @param key 键
* @param start 开始 0 是第一个元素
* @param end 结束 -1代表所有值
* @return
*/
public List<Object> lGet(String key, long start, long end) {
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
log.error(key, e);
return null;
}
}

/**
* 获取list缓存的长度
*
* @param key 键
* @return
*/
public long lGetListSize(String key) {
try {
return redisTemplate.opsForList().size(key);
} catch (Exception e) {
log.error(key, e);
return 0;
}
}

/**
* 通过索引 获取list中的值
*
* @param key 键
* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
* @return
*/
public Object lGetIndex(String key, long index) {
try {
return redisTemplate.opsForList().index(key, index);
} catch (Exception e) {
log.error(key, e);
return null;
}
}

/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return
*/
public boolean lSet(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(key, value);
return true;
} catch (Exception e) {
log.error(key, e);
return false;
}
}

/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, Object value, long time) {
try {
redisTemplate.opsForList().rightPush(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
log.error(key, e);
return false;
}
}

/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @return
*/
public boolean lSet(String key, List<Object> value) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
return true;
} catch (Exception e) {
log.error(key, e);
return false;
}
}

/**
* 将list放入缓存
*
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, List<Object> value, long time) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
log.error(key, e);
return false;
}
}

/**
* 根据索引修改list中的某条数据
*
* @param key 键
* @param index 索引
* @param value 值
* @return
*/
public boolean lUpdateIndex(String key, long index, Object value) {
try {
redisTemplate.opsForList().set(key, index, value);
return true;
} catch (Exception e) {
log.error(key, e);
return false;
}
}

/**
* 移除N个值为value
*
* @param key 键
* @param count 移除多少个
* @param value 值
* @return 移除的个数
*/
public long lRemove(String key, long count, Object value) {
try {
Long remove = redisTemplate.opsForList().remove(key, count, value);
return remove;
} catch (Exception e) {
log.error(key, e);
return 0;
}
}
}

+ 98
- 0
src/main/java/com/telpo/beidouast/common/SocketClient.java Целия файл

@@ -0,0 +1,98 @@
package com.telpo.dipperposition.common;

import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

/**
* @program: dipperposition
* @description: socket连接单元
* @author: king
* @create: 2021-01-14 13:52
**/
@Slf4j
public class SocketClient {
//定义一个Socket对象
Socket socket = null;

public SocketClient(String host, int port, int timeout) {
try {
//需要服务器的IP地址和端口号,才能获得正确的Socket对象
socket = new Socket(host, port);
socket.setSoTimeout(timeout);
} catch (IOException e) {
log.error("Socket Connect Error:" + e.getMessage());
}
}

public String getOutput() {
try {
OutputStream os = socket.getOutputStream();
return os.toString();
} catch (IOException e) {
log.error("Socket getOutputStream Error:" + e.getMessage());
return null;
}
}


public String sendCmd(String astCmd, String ackAckCheckRef) {
try {
OutputStream os=socket.getOutputStream();
PrintWriter pw=new PrintWriter(os);
// TODO 发生命令
//String info="用户名:Tom,用户密码:123456";
pw.write(astCmd);
pw.flush();
socket.shutdownOutput();

//接收服务器的相应
String reply=null;
//输入流
InputStream is=socket.getInputStream();
//BufferedReader br=new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
byte[] buff = new byte[100];

//StringBuffer ackResultBuf= new StringBuffer();
//String ackHexOut = HexConvert.convertStringToHex(ackAckCheckRef);
// reply=br.readLine();
// while(reply!=null){
// //log.debug("接收服务器的信息:"+reply);
// //if (ackHexOut.equals(reply)) {
// ackResultBuf.append(reply);
// reply=br.readLine();
// // break;
// //}
// }
int rc = 0;
while ((rc = is.read(buff, 0, 100)) > 0) {
swapStream.write(buff, 0, rc);
}
byte[] in2b = swapStream.toByteArray();
//String ackResult = HexConvert.convertHexToString(ackResultBuf.toString());
//4.关闭资源
swapStream.close();
is.close();
pw.close();
os.close();
//log.debug(ackResult);
log.debug("接收服务器的信息:"+HexConvert.BinaryToHexString(in2b));
return HexConvert.BinaryToHexString(in2b);
} catch (IOException e) {
log.error("Socket sendCmd Error:" + e.getMessage());
return null;
}
}

public void closeConnection() {
try {
socket.close();
//socket.shutdownOutput();
} catch (IOException e) {
log.error("Socket getOutputStream Error:" + e.getMessage());
}
}
}

+ 69
- 0
src/main/java/com/telpo/beidouast/config/AsyncExecutorConfig.java Целия файл

@@ -0,0 +1,69 @@
package com.telpo.dipperposition.config;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
* @program: DataPushServer
* @description:
* @author: linwl
* @create: 2020-07-11 09:17
*/
@Configuration
@Slf4j
public class AsyncExecutorConfig implements AsyncConfigurer {

@Value("${async.pool.corePoolSize}")
private int corePoolSize;

@Value("${async.pool.maxPoolSize}")
private int maxPoolSize;

@Value("${async.pool.queueCapacity}")
private int queueCapacity;

@Bean(name = "asyncServiceExecutor")
public Executor asyncServiceExecutor() {
log.info("start asyncServiceExecutor");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 配置核心线程数
executor.setCorePoolSize(corePoolSize);
// 配置最大线程数
executor.setMaxPoolSize(maxPoolSize);
// 配置队列大小
executor.setQueueCapacity(queueCapacity);
// 配置线程池中的线程的名称前缀
String threadNamePrefix = "async-pool-";
executor.setThreadNamePrefix(threadNamePrefix);

// 设置拒绝策略:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 执行初始化
executor.initialize();
return executor;
}

/**
* 异步任务中异常处理
*
* @return
*/
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return (arg0, arg1, arg2) -> {
log.error("==========================" + arg0.getMessage() + "=======================", arg0);
log.error("com.telpo.auth.exception method:" + arg1.getName());
};
}
}

+ 99
- 0
src/main/java/com/telpo/beidouast/config/OkHttpConfig.java Целия файл

@@ -0,0 +1,99 @@
package com.telpo.dipperposition.config;

import lombok.extern.slf4j.Slf4j;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit;

/**
* @program: DataPushServer
* @description: http设置
* @author: linwl
* @create: 2020-07-17 15:29
*/
@Configuration
@Slf4j
public class OkHttpConfig {

@Value("${OkHttp-config.pool.max-conn}")
private Integer maxConn;

@Value("${OkHttp-config.pool.keep-alive}")
private Integer keepAlive;

@Value("${OkHttp-config.read-timeout}")
private long readTimeout;

@Value("${OkHttp-config.conn-timeout}")
private long connTimeout;

@Value("${OkHttp-config.write-timeout}")
private long writeTimeout;

@Bean
public X509TrustManager x509TrustManager() {
return new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s)
throws CertificateException {}

@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s)
throws CertificateException {}

@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
}

@Bean
public SSLSocketFactory sslSocketFactory() {
try {
// 信任任何链接
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] {x509TrustManager()}, new SecureRandom());
return sslContext.getSocketFactory();
} catch (NoSuchAlgorithmException | KeyManagementException e) {
log.error("okhttp3 send https error:", e);
}
return null;
}

/**
* Create a new connection pool with tuning parameters appropriate for a single-user application.
* The tuning parameters in this pool are subject to change in future OkHttp releases. Currently
*/
@Bean
public ConnectionPool pool() {
return new ConnectionPool(maxConn, keepAlive, TimeUnit.MINUTES);
}

@Bean
public OkHttpClient okHttpClient() {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder
.connectTimeout(connTimeout, TimeUnit.SECONDS)
.readTimeout(readTimeout, TimeUnit.SECONDS)
.writeTimeout(writeTimeout, TimeUnit.SECONDS)
.connectionPool(pool()) // 连接池
.retryOnConnectionFailure(true)
.hostnameVerifier((s, sslSession) -> true)
.sslSocketFactory(sslSocketFactory(), x509TrustManager());
return builder.build();
}
}

+ 61
- 0
src/main/java/com/telpo/beidouast/config/PositionConfig.java Целия файл

@@ -0,0 +1,61 @@
package com.telpo.dipperposition.config;

import com.telpo.dipperposition.co.PositionConfigInfo;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import okhttp3.OkHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* @program: gateway
* @description: jwt设置
* @author: linwl
* @create: 2020-06-18 17:45
*/
@Getter
@Setter
@Configuration
public class PositionConfig {

//@Autowired
//private ConfigurableApplicationContext configurableApplicationContext;
//@Value(value = "${position.hello}")
//private String hello;

//@Value(value = "${spring.application.name}")
//private String name;

// @Value(value = "${position.server.serverAddr}")
// private String serverAddr;
//
// @Value(value = "${position.server.timeAsycPort}")
// private String timeAsycServerPort;
//
// @Value(value = "${position.server.posAsycPort}")
// private String posAsycServerPort;
//
// @Value(value = "${position.server.starsAsycPort}")
// private String starsAsycServerPort;

PositionConfig()
{
//hello = configurableApplicationContext.getEnvironment().getProperty("position.hello");
//name = configurableApplicationContext.getEnvironment().getProperty("spring.application.name");
}
//
// @Bean (name = "positionConfigInfo")
// public PositionConfigInfo positionConfigInfo(){
// PositionConfigInfo configInfo = new PositionConfigInfo();
// configInfo.setServerAddr(this.serverAddr);
// configInfo.setTimeAsycServerPort(this.timeAsycServerPort);
// configInfo.setPosAsycServerPort(this.posAsycServerPort);
// configInfo.setStarsAsycServerPort(this.starsAsycServerPort);
// System.out.print(configInfo.toString());
// return configInfo;
// }
}

+ 53
- 0
src/main/java/com/telpo/beidouast/config/SchedulingExecutorConfig.java Целия файл

@@ -0,0 +1,53 @@
package com.telpo.dipperposition.config;

import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

/**
* @program: DataPushServer
* @description: 定时任务线程配置
* @author: linwl
* @create: 2020-07-24 10:53
*/
@Getter
@Setter
@Configuration
public class SchedulingExecutorConfig implements SchedulingConfigurer {

@Value("${scheduler.pool.size}")
private int pollSize;

@Value("${scheduler.pool.await-seconds}")
private int awaitSeconds;

@Value("${pos.ast.server}")
private String astServer;
@Value("${pos.ast.ephAstPort}")
private int ephAstPort;
@Value("${pos.ast.ephAstHexPort}")
private int ephAstHexPort;
@Value("${pos.ast.timeout}")
private int astTimeout;

@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
ThreadPoolTaskScheduler taskScheduler = taskScheduler();
taskRegistrar.setTaskScheduler(taskScheduler);
}

@Bean(destroyMethod = "shutdown", name = "taskScheduler")
public ThreadPoolTaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(pollSize);
scheduler.setThreadNamePrefix("task-");
scheduler.setAwaitTerminationSeconds(awaitSeconds);
scheduler.setWaitForTasksToCompleteOnShutdown(true);
return scheduler;
}
}

+ 65
- 0
src/main/java/com/telpo/beidouast/config/db/MongoDbContext.java Целия файл

@@ -0,0 +1,65 @@
package com.telpo.dipperposition.config.db;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.SimpleMongoClientDbFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
* @program: DataPushServer
* @description: mongdb数据库连接上下文
* @author: linwl
* @create: 2020-07-11 14:31
*/
@Component
public class MongoDbContext {

private static final Map<String, MongoDbFactory> MONGO_CLIENT_DB_FACTORY_MAP = new HashMap<>();
private static final ThreadLocal<MongoDbFactory> MONGO_DB_FACTORY_THREAD_LOCAL = new ThreadLocal<>();
@Autowired
MongoListProperties mongoListProperties;

public static MongoDbFactory getMongoDbFactory() {
return MONGO_DB_FACTORY_THREAD_LOCAL.get();
}

public static void setMongoDbFactory(String name) {
MONGO_DB_FACTORY_THREAD_LOCAL.set(MONGO_CLIENT_DB_FACTORY_MAP.get(name));
}

public static void removeMongoDbFactory() {
MONGO_DB_FACTORY_THREAD_LOCAL.remove();
}

@PostConstruct
public void afterPropertiesSet() {
if (!CollectionUtils.isEmpty(mongoListProperties.getDblist())) {
mongoListProperties
.getDblist()
.forEach(
info -> {
MONGO_CLIENT_DB_FACTORY_MAP.put(
info.getDatabase(), new SimpleMongoClientDbFactory(info.getUri()));
});
}
}

@Bean(name = "mongoTemplate")
public MultiMongoTemplate dynamicMongoTemplate() {
Iterator<MongoDbFactory> iterator = MONGO_CLIENT_DB_FACTORY_MAP.values().iterator();
return new MultiMongoTemplate(iterator.next());
}

@Bean(name = "mongoDbFactory")
public MongoDbFactory mongoDbFactory() {
Iterator<MongoDbFactory> iterator = MONGO_CLIENT_DB_FACTORY_MAP.values().iterator();
return iterator.next();
}
}

+ 30
- 0
src/main/java/com/telpo/beidouast/config/db/MongoListProperties.java Целия файл

@@ -0,0 +1,30 @@
package com.telpo.dipperposition.config.db;

import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.List;

/**
* @program: DataPushServer
* @description: mongo连接配置类
* @author: linwl
* @create: 2020-07-11 14:41
*/
@Getter
@Setter
@ToString
@ConfigurationProperties(prefix = "mongo.datasource")
public class MongoListProperties {

private List<MongoList> dblist;

@Data
public static class MongoList {
private String uri;
private String database;
}
}

+ 26
- 0
src/main/java/com/telpo/beidouast/config/db/MultiMongoTemplate.java Целия файл

@@ -0,0 +1,26 @@
package com.telpo.dipperposition.config.db;

import com.mongodb.client.MongoDatabase;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;

/**
* @program: DataPushServer
* @description: 多mongo数据源配置
* @author: linwl
* @create: 2020-07-11 14:21
*/
@Slf4j
public class MultiMongoTemplate extends MongoTemplate {

public MultiMongoTemplate(MongoDbFactory mongoDbFactory) {
super(mongoDbFactory);
}

@Override
protected MongoDatabase doGetDatabase() {
MongoDbFactory mongoDbFactory = MongoDbContext.getMongoDbFactory();
return mongoDbFactory == null ? super.doGetDatabase() : mongoDbFactory.getDb();
}
}

+ 26
- 0
src/main/java/com/telpo/beidouast/controller/DipperPositionController.java Целия файл

@@ -0,0 +1,26 @@
package com.telpo.dipperposition.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


/**
* @program: DipperPositionController
* @description: 北斗定位
* @author: linwl
* @create: 2020-07-10 14:01
*/
@RestController
@Slf4j
public class DipperPositionController {
@Value(value = "${position-server.serverAddr}")
private String hello;
//RzlAccount rzlAccount;

@RequestMapping("/getPos")
public String getPos() {
return "return serverAddr = " + hello;
}
}

+ 24
- 0
src/main/java/com/telpo/beidouast/entity/mongo/IPProvinceEntity.java Целия файл

@@ -0,0 +1,24 @@
package com.telpo.dipperposition.entity.mongo;

import com.telpo.dipperposition.vo.IPProvinceVo;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import models.BaseMongoDbEntity;

/**
* @program: IPProvinceEntity
* @description: 位置实体类
* @author: linwl
* @create: 2020-07-11 15:33
*/
@ToString
@Getter
@Setter
public class IPProvinceEntity extends BaseMongoDbEntity {

/** Ip */
private String ip;
/** Ip所在省份 */
private String province;
}

+ 53
- 0
src/main/java/com/telpo/beidouast/enums/DipperReturnValue.java Целия файл

@@ -0,0 +1,53 @@
package com.telpo.dipperposition.enums;

/**
* @program: DipperReturnValue
* @description: 推送类型枚举
* @author: king
* @create: 2021-01-24 11:44
*/
public enum DipperReturnValue {
ACK(0, "SDBP-PUB–ACK"),
NACK(1, "SDBP-PUB–NACK");

/** 状态值 */
private int value;
/** 描述 */
private String describe;

private DipperReturnValue(int value, String describe) {
this.value = value;
this.describe = describe;
}

/**
* 获取推送类型
*
* @param value
* @return
*/
public static DipperReturnValue getByValue(int value) {
for (DipperReturnValue enums : DipperReturnValue.values()) {
if (enums.getValue() == value) {
return enums;
}
}
return null;
}

public int getValue() {
return value;
}

public void setValue(int value) {
this.value = value;
}

public String getDescribe() {
return describe;
}

public void setDescribe(String describe) {
this.describe = describe;
}
}

+ 181
- 0
src/main/java/com/telpo/beidouast/handler/NettyServerHandler.java Целия файл

@@ -0,0 +1,181 @@
package com.telpo.dipperposition.handler;

import com.telpo.dipperposition.enums.DipperReturnValue;
import com.telpo.dipperposition.service.IDipperAstPosAsyncTaskService;
import com.telpo.dipperposition.service.IDipperAstTimeAsyncTaskService;
import com.telpo.dipperposition.service.IDipperDataAsyncTaskService;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.io.InputStream;
import java.time.LocalDateTime;

/**
* @program: dipperposition
* @description: Netty服务器处理句柄
* @author: linwl
* @create: 2021-01-13 13:56
**/
@Slf4j
public class NettyServerHandler extends ChannelInboundHandlerAdapter {

private static String AST_TIME_CMD = "54494d45";
private static String AST_POS_CMD = "504f53";
private static String AST_EPH_CMD = "455048";

@Autowired
private IDipperAstTimeAsyncTaskService dipperTimeAsyncTaskService;
@Autowired
private IDipperAstPosAsyncTaskService dipperAstPosAsyncTaskService;
@Autowired
private IDipperDataAsyncTaskService dipperDataAsyncTaskService;

@Value(value = "${position-server.timeAsycPort}")
private String timeAsycServerPort;

@Value(value = "${position-server.posAsycPort}")
private String posAsycServerPort;

@Value(value = "${position-server.starsAsycPort}")
private String starsAsycServerPort;


@Value("${pos.centerProvinceFilePath}")
String centerProvinceFilePath;

@Value("${pos.ipPositionRequestPath}")
String ipPositionRequestPath;
@Value("${pos.ipPositionRequestKey}")
String ipPositionRequestKey;
@Value("${pos.centerProvince}")
String centerProvince;


@Value("${pos.ast.server}")
String astServer;
@Value("${pos.ast.posAstPort}")
int posAstPort;
@Value("${pos.ast.timeout}")
int astTimeout;
/**
* 客户端连接会触发
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
log.info("Channel active......");

SocketChannel channel = (SocketChannel) ctx.channel();
log.info("链接报告开始");
log.info("链接报告信息:有一客户端链接到本服务端");
log.info("链接报告IP:" + channel.localAddress().getHostString());
log.info("链接报告Port:" + channel.localAddress().getPort());
log.info("链接报告完毕");
//通知客户端链接建立成功
// 默认返回取得时间成功
String ackAckCheckRef = "233E0101020004020A1D";
if (Integer.parseInt(posAsycServerPort) == channel.localAddress().getPort()) {
ackAckCheckRef = "233E010102000401091C";
}
if (Integer.parseInt(starsAsycServerPort) == channel.localAddress().getPort()) {
ackAckCheckRef = "233E010102000421293C";
}
//String str = "通知客户端链接建立成功" + " " + LocalDateTime.now() + " " + channel.localAddress().getHostString() +
// "\r\n";
ByteBuf buf = Unpooled.buffer(ackAckCheckRef.getBytes().length);
buf.writeBytes(ackAckCheckRef.getBytes("GBK"));
ctx.writeAndFlush(buf);
}


/**
* 当客户端主动断开服务端的链接后,这个通道就是不活跃的。也就是说客户端与服务端的关闭了通信通道并且不可以传输数据
*/
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
log.info("客户端断开链接,IP:{}", ctx.channel().localAddress().toString());
}

/**
* 客户端发消息会触发
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//接收msg消息{与上一章节相比,此处已经不需要自己进行解码}
SocketChannel channel = (SocketChannel) ctx.channel();
String ipAddress = channel.remoteAddress().toString();
String message = " 接收到消息:{0}, 客户端IP:{1}";
log.info(message ,msg, ipAddress);

String channelAns = "";
// 返回时间指令
//if (Integer.parseInt(timeAsycServerPort) == channel.localAddress().getPort()) {
ByteBuf recvmg = (ByteBuf) msg;
ByteBuf buf = null;
String recvmgStr = recvmg.toString();
if (AST_TIME_CMD.equals(recvmg)) {
// 初始时间辅助输入;
channelAns = dipperTimeAsyncTaskService.pushAstTime();
buf = Unpooled.buffer(channelAns.getBytes().length);
}

// 发送SDBP-AST-POS获取辅助位置信息
// if (Integer.parseInt(posAsycServerPort) == channel.localAddress().getPort()) {

if (AST_POS_CMD.equals(recvmg)) {
channelAns = dipperAstPosAsyncTaskService.pushAstPos(ipAddress,
centerProvinceFilePath,
centerProvince,
ipPositionRequestPath,
ipPositionRequestKey);
buf = Unpooled.buffer(channelAns.getBytes().length);
}

// 从缓存获取SDBP-AST-EPH星历数
//if (Integer.parseInt(starsAsycServerPort) == channel.localAddress().getPort()) {
if (AST_POS_CMD.equals(recvmg)) {
String astEPHBytes = dipperDataAsyncTaskService.getAstEPH();
buf = Unpooled.buffer(astEPHBytes.getBytes().length);
}


// 最后把SDBP-AST-TIME、SDBP-AST-POS、SDBP-AST-EPH并包一起发给设备。
// 设备采用16进制获取数据,则代理服务器也是采用16进制返回数据。
// 通知客户端链消息发送成功
// String str = "服务端收到:" + LocalDateTime.now() + " " + msg + "\r\n";
buf.writeBytes(channelAns.getBytes("GBK"));
ctx.writeAndFlush(buf);
//ctx.write("你也好哦");
//ctx.flush();
}

// @Override
// public void channelRead0(ChannelHandlerContext ctx, HttpObject msg)
// throws Exception {
// if (msg instanceof HttpRequest) {
// HttpRequest mReq = (HttpRequest) msg;
// String clientIP = mReq.headers().get("X-Forwarded-For");
// if (clientIP == null) {
// InetSocketAddress insocket = (InetSocketAddress) ctx.channel()
// .remoteAddress();
// clientIP = insocket.getAddress().getHostAddress();
// }
// }
// }

/**
* 发生异常触发
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}


}

+ 24
- 0
src/main/java/com/telpo/beidouast/handler/ServerChannelInitializer.java Целия файл

@@ -0,0 +1,24 @@
package com.telpo.dipperposition.handler;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;
/**
* @program: dipperposition
* @description: 服务器通道初始化
* @author: king
* @create: 2021-01-13 13:54
**/
public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
//添加编解码
socketChannel.pipeline().addLast("decoder", new StringDecoder(CharsetUtil.UTF_8));
socketChannel.pipeline().addLast("encoder", new StringEncoder(CharsetUtil.UTF_8));
socketChannel.pipeline().addLast(new NettyServerHandler());
}

}

+ 58
- 0
src/main/java/com/telpo/beidouast/mapper/IPProvinceMapper.java Целия файл

@@ -0,0 +1,58 @@
package com.telpo.dipperposition.mapper;

import com.telpo.dipperposition.annotation.MongoSwitch;
import com.telpo.dipperposition.entity.mongo.IPProvinceEntity;
import db.BaseMongoDbDao;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
* @program: DataPushServer
* @description: 推送记录mapper
* @author: linwl
* @create: 2020-07-20 11:12
*/
@Repository
public class IPProvinceMapper extends BaseMongoDbDao<IPProvinceEntity> {

@Override
protected Class<IPProvinceEntity> getEntityClass() {
return IPProvinceEntity.class;
}

@Override
@MongoSwitch("common")
public void save(IPProvinceEntity entity, String collectionName) {
super.save(entity, collectionName);
}

@Override
@MongoSwitch("common")
public void updateFirst(IPProvinceEntity srcObj, IPProvinceEntity targetObj) {
super.updateFirst(srcObj, targetObj);
}

@Override
public List<IPProvinceEntity> getPage(IPProvinceEntity object, int start, int size) {
return super.getPage(object, start, size);
}

@Override
@MongoSwitch("common")
public List<IPProvinceEntity> queryList(IPProvinceEntity object) {
return super.queryList(object);
}

@Override
@MongoSwitch("common")
public List<IPProvinceEntity> queryList(IPProvinceEntity object, String collectionName) {
return super.queryList(object, collectionName);
}

@Override
@MongoSwitch("common")
public void deleteById(String id) {
super.deleteById(id);
}
}

+ 257
- 0
src/main/java/com/telpo/beidouast/server/DipperPositionServer.java Целия файл

@@ -0,0 +1,257 @@
package com.telpo.dipperposition.server;

import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import com.telpo.dipperposition.co.PositionConfigInfo;
import com.telpo.dipperposition.handler.ServerChannelInitializer;
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;
import org.springframework.core.env.ConfigurableEnvironment;

import java.net.InetSocketAddress;

/**
* @program: DipperPositionServer
* @description: 北斗定位
* @author: king
* @create: 2021-01-13 14:01
*/
@Slf4j
public class DipperPositionServer {

// @Autowired PositionConfigInfo positionConfigInfo;
private String serverAddr;
private Integer serverPort;
private Integer timeAsycPort;
private Integer posAsycPort;
private Integer starsAsycPort;

public DipperPositionServer(ConfigurableEnvironment environment) throws NacosException {

this.serverAddr = environment.getProperty("position-server.serverAddr");
this.serverPort = Integer.parseInt(environment.getProperty("server.port"));
this.timeAsycPort = Integer.parseInt(environment.getProperty("position-server.timeAsycPort"));
this.posAsycPort = Integer.parseInt(environment.getProperty("position-server.posAsycPort"));
this.starsAsycPort = Integer.parseInt(environment.getProperty("position-server.starsAsycPort"));
//String serverAddr = positionConfigInfo.getServerAddr();
// try {
// try {
// InetAddress ip4 = Inet4Address.getLocalHost();
// serverAddr = ip4.getHostAddress();
// } catch (Exception ex) {
// serverAddr = "172.16.192.26";
// ex.printStackTrace();
// }
// String dataId = "dipperposition-service";
// String group = "DEFAULT_GROUP";
// Properties properties = new Properties();
// properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);
// ConfigService configService = NacosFactory.createConfigService(properties);
// String content = configService.getConfig(dataId, group, 5000);
//
// ByteArrayInputStream tInputStringStream = new ByteArrayInputStream(content.getBytes());
// Yaml yaml = new Yaml();
// Map m1 = yaml.load(tInputStringStream);
// Map m2 = (Map) m1.get("position-server");
// this.serverAddr = (String)m2.get("serverAddr");
// this.timeAsycPort = (Integer)m2.get("timeAsycPort");
// this.posAsycPort = (Integer)m2.get("posAsycPort");
// this.starsAsycPort = (Integer)m2.get("starsAsycPort");
// log.info("Map server is:" + m2.get("serverAddr"));
// } catch (Exception ex) {
// ex.printStackTrace();
// }
}
// /*
// * 时间同步进程线程
// */
// public void startTimeAsnc() {
//
// //new 一个主线程组
// EventLoopGroup mainThreadGroup = new NioEventLoopGroup(1);
// //new 一个工作线程组
// EventLoopGroup workThreadGroup = new NioEventLoopGroup(200);
// InetSocketAddress socketAddress = new InetSocketAddress(serverAddr,
// timeAsycPort);
// ServerBootstrap bootstrap = new ServerBootstrap()
// .group(mainThreadGroup, workThreadGroup)
// .channel(NioServerSocketChannel.class)
// .childHandler(new ServerChannelInitializer())
// .localAddress(socketAddress)
// //设置队列大小
// .option(ChannelOption.SO_BACKLOG, 1024)
// // 两小时内没有数据的通信时,TCP会自动发送一个活动探测数据报文
// .childOption(ChannelOption.SO_KEEPALIVE, true);
//
//
// //绑定端口,开始接收进来的连接
// try {
// ChannelFuture future = bootstrap.bind(socketAddress).sync();
// log.info("服务器启动开始监听端口: {}", socketAddress.getPort());
//
//
// future.channel().closeFuture().sync();
// } catch (InterruptedException e) {
// e.printStackTrace();
// } finally {
// //关闭主线程组
// mainThreadGroup.shutdownGracefully();
// //关闭工作线程组
// workThreadGroup.shutdownGracefully();
// }
// }

// /*
// * 时间同步进程线程
// */
// public void startPosAsnc() {
//
// //new 一个主线程组
// EventLoopGroup mainThreadGroup = new NioEventLoopGroup(1);
// //new 一个工作线程组
// EventLoopGroup workThreadGroup = new NioEventLoopGroup(200);
// InetSocketAddress socketAddress = new InetSocketAddress(serverAddr,
// posAsycPort);
// ServerBootstrap bootstrap = new ServerBootstrap()
// .group(mainThreadGroup, workThreadGroup)
// .channel(NioServerSocketChannel.class)
// .childHandler(new ServerChannelInitializer())
// .localAddress(socketAddress)
// //设置队列大小
// .option(ChannelOption.SO_BACKLOG, 1024)
// // 两小时内没有数据的通信时,TCP会自动发送一个活动探测数据报文
// .childOption(ChannelOption.SO_KEEPALIVE, true);
//
//
// //绑定端口,开始接收进来的连接
// try {
// ChannelFuture future = bootstrap.bind(socketAddress).sync();
// log.info("服务器启动开始监听端口: {}", socketAddress.getPort());
//
//
// future.channel().closeFuture().sync();
// } catch (InterruptedException e) {
// e.printStackTrace();
// } finally {
// //关闭主线程组
// mainThreadGroup.shutdownGracefully();
// //关闭工作线程组
// workThreadGroup.shutdownGracefully();
// }
// }


/*
* 星历同步进程线程
*/
//public void startStarsAsnc() {
public void start() {

//new 一个主线程组
EventLoopGroup mainThreadGroup = new NioEventLoopGroup(1);
//new 一个工作线程组
EventLoopGroup workThreadGroup = new NioEventLoopGroup(200);
//InetSocketAddress socketAddress = new InetSocketAddress(serverAddr,null);
ServerBootstrap bootstrap = new ServerBootstrap()
.group(mainThreadGroup, workThreadGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ServerChannelInitializer())
//.localAddress(socketAddress)
//设置队列大小
.option(ChannelOption.SO_BACKLOG, 1024)
// 两小时内没有数据的通信时,TCP会自动发送一个活动探测数据报文
.childOption(ChannelOption.SO_KEEPALIVE, true);


//绑定端口,开始接收进来的连接
try {
ChannelFuture channelFuture = bootstrap.bind(timeAsycPort).sync();
log.info("时间辅助服务器启动开始监听端口: {}", timeAsycPort);
channelFuture.addListener(future -> {
if (future.isSuccess()){
System.out.println("start success");
}else{
System.out.println("start failed");
}
});

ChannelFuture channelFuture2 = bootstrap.bind(posAsycPort).sync();
log.info("位置服务器启动开始监听端口: {}", posAsycPort);
channelFuture2.addListener(future -> {
if (future.isSuccess()){
System.out.println("start success");
}else{
System.out.println("start failed");
}
});


ChannelFuture channelFuture3 = bootstrap.bind(starsAsycPort).sync();
log.info("星历服务器启动开始监听端口: {}", starsAsycPort);
channelFuture3.addListener(future -> {
if (future.isSuccess()){
System.out.println("start success");
}else{
System.out.println("start failed");
}
});

//channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//关闭主线程组
mainThreadGroup.shutdownGracefully();
//关闭工作线程组
workThreadGroup.shutdownGracefully();
}
}

public void start2() {

//new 一个主线程组
EventLoopGroup mainThreadGroup = new NioEventLoopGroup(1);
//new 一个工作线程组
EventLoopGroup workThreadGroup = new NioEventLoopGroup(200);
//InetSocketAddress socketAddress = new InetSocketAddress(serverAddr,null);
ServerBootstrap bootstrap = new ServerBootstrap()
.group(mainThreadGroup, workThreadGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ServerChannelInitializer())
//.localAddress(socketAddress)
//设置队列大小
.option(ChannelOption.SO_BACKLOG, 1024)
// 两小时内没有数据的通信时,TCP会自动发送一个活动探测数据报文
.childOption(ChannelOption.SO_KEEPALIVE, true);


//绑定端口,开始接收进来的连接
try {
ChannelFuture channelFuture = bootstrap.bind(timeAsycPort).sync();
log.info("时间辅助服务器启动开始监听端口: {}", timeAsycPort);
channelFuture.addListener(future -> {
if (future.isSuccess()){
System.out.println("start success");
}else{
System.out.println("start failed");
}
});

//channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
//关闭主线程组
mainThreadGroup.shutdownGracefully();
//关闭工作线程组
workThreadGroup.shutdownGracefully();
}
}
}

+ 27
- 0
src/main/java/com/telpo/beidouast/service/IDipperAstPosAsyncTaskService.java Целия файл

@@ -0,0 +1,27 @@
package com.telpo.dipperposition.service;

import java.io.UnsupportedEncodingException;

/**
* @program: IDipperAstPosAsyncTaskService
* @description: 系统预先基于省份的省会城市的经纬度作为辅助信息,
* 根据设备请求的IP地址,从高德IP定位服务获取相关的省份,再匹配相应的位置信息作为辅助位置信息。
* 如果匹配不到省份,则以武汉中心作为辅助为位置信息。
* 关于IP与省份的关系保存到缓存中,用于下次使用时,先在缓存中获取匹配信息,匹配不到,再请求高德IP定位服务。
* 高德IP定位服务:https://lbs.amap.com/api/webservice/guide/api/ipconfig。
* @author: king
* @create: 2021-01-17 16:24
*/
public interface IDipperAstPosAsyncTaskService {

/**
* 同步任务
*
*/
String pushAstPos(String ipAddress,
String centerProvinceFilePath,
String centerProvince,
String ipPositionRequestPath,
String ipPositionRequestKey) throws UnsupportedEncodingException;

}

+ 17
- 0
src/main/java/com/telpo/beidouast/service/IDipperAstTimeAsyncTaskService.java Целия файл

@@ -0,0 +1,17 @@
package com.telpo.dipperposition.service;

/**
* @program: IDipperDataAsyncTaskService
* @description: 发送SDBP-AST-TIME获取时间信息
* @author: king
* @create: 2021-01-17 16:24
*/
public interface IDipperAstTimeAsyncTaskService {

/**
* 同步任务
*
*/
String pushAstTime();

}

+ 28
- 0
src/main/java/com/telpo/beidouast/service/IDipperDataAsyncTaskService.java Целия файл

@@ -0,0 +1,28 @@
package com.telpo.dipperposition.service;

import org.springframework.beans.factory.annotation.Value;

/**
* @program: IDipperDataAsyncTaskService
* @description: 发送bds获取星历数据。
* * 每30分钟获取1次,30秒超时,
* * 如果失败,则可以等待10秒再获取1次
* @author: king
* @create: 2021-01-17 16:24
*/
public interface IDipperDataAsyncTaskService {

/**
* 同步任务
*
*/
void pullAstEPH();


/**
* 根据IP获取EPH
*
*/
String getAstEPH();

}

+ 45
- 0
src/main/java/com/telpo/beidouast/service/IPProvinceService.java Целия файл

@@ -0,0 +1,45 @@
package com.telpo.dipperposition.service;

import com.telpo.dipperposition.entity.mongo.IPProvinceEntity;
import com.telpo.dipperposition.vo.IPProvinceVo;

/**
* @program: IPProvinceService
* @description: IP省份服务接口
* @author: king
* @create: 2020-07-20 11:09
*/
public interface IPProvinceService {

/**
* 保存IP省份
*
* @param entity
* @return
*/
boolean saveIPProvince(IPProvinceEntity entity);

/**
* 更新IP省份
*
* @param query
* @param update
* @return
*/
boolean updateIPProvince(
IPProvinceEntity query, IPProvinceEntity update);

/**
* 根据ID移除IP省份记录
*
* @param id
* @return
*/
boolean romveById(String id);

/*
* @param ipAddress
* 获取IP省份
*/
IPProvinceEntity getIPProvince(String ipAddress);
}

+ 247
- 0
src/main/java/com/telpo/beidouast/service/impl/DipperAstPosAsyncTaskServiceImpl.java Целия файл

@@ -0,0 +1,247 @@
package com.telpo.dipperposition.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Joiner;
import com.telpo.dipperposition.common.*;
import com.telpo.dipperposition.entity.mongo.IPProvinceEntity;
import com.telpo.dipperposition.mapper.IPProvinceMapper;
import com.telpo.dipperposition.service.IDipperAstPosAsyncTaskService;
import com.telpo.dipperposition.service.IPProvinceService;
import com.telpo.dipperposition.vo.IPProvinceVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
* @program: DipperAstPosAsyncTaskServiceImpl
* @description: 系统预先基于省份的省会城市的经纬度作为辅助信息,
* * 根据设备请求的IP地址,从高德IP定位服务获取相关的省份,再匹配相应的位置信息作为辅助位置信息。
* * 如果匹配不到省份,则以武汉中心作为辅助为位置信息。
* * 关于IP与省份的关系保存到缓存中,用于下次使用时,先在缓存中获取匹配信息,匹配不到,再请求高德IP定位服务。
* * 高德IP定位服务:https://lbs.amap.com/api/webservice/guide/api/ipconfig。
* @author: king
* @create: 2021-01-10 14:01
*/
@Service
@Slf4j
public class DipperAstPosAsyncTaskServiceImpl implements IDipperAstPosAsyncTaskService {

@Autowired
private RedisUtil redisUtil;
@Autowired
private OkHttpUtil okHttpUtil;
@Autowired
private IPProvinceService iPProvinceService;

private String centerProvince;
private String centerProvinceFilePath;
private String ipPositionRequestPath;
private String ipPositionRequestKey;
// private String getAstPos(String ipAddress) throws UnsupportedEncodingException {
//
// String centerAddress = getIpPositionProvince(ipAddress);
// if (ObjectUtils.isEmpty(centerAddress) || centerAddress.equals("0")) {
// log.warn("IP地址非法,无法获取辅助位置信息!");
// // 返回武汉的定位数据
// centerAddress = centerProvince;
// } else {
// // 保存到mongoDB
// createIPProvince(ipAddress, centerAddress);
// }
//
// String lonAndAlt;
// if (redisUtil.hasKey(centerAddress)) {
// // 获取省会城市定位信息
// lonAndAlt= (String) redisUtil.get(centerAddress);
// } else {
// // 请求高德IP定位服务
// this.getPosFromFile(centerAddress);
// lonAndAlt = (String) redisUtil.get(centerAddress);
// }
//
// return lonAndAlt;
// }

// 从CSV文件读取省会城市中心点位置信息
private void getPosFromFile(String centerAddress) {
// 不存在说明token是已过期了
String centerProvinceName = "";
String centerProvinceLonAndAlt = "";
List<String> centerAddressSets = CSVUtil.readCSV(this.centerProvinceFilePath);
for (String centerAddressSet:centerAddressSets) {
String[] centerAddressSetArray = centerAddressSet.split(",");
if (centerAddressSetArray.length < 3) {
log.warn("CSV数据格式错误");
} else {
centerProvinceName = centerAddressSetArray[3];
centerProvinceLonAndAlt = centerAddressSetArray[1]+","+centerAddressSetArray[2];
redisUtil.set(centerProvinceName, centerProvinceLonAndAlt, 0);
}
}
}

// 根据IP获取省会信息
private String getIpPositionProvince(String ipAddress) {

// 关于IP与省份的关系保存到缓存中
// 使用时,先在缓存中获取匹配信息
// 用mongodb实现
IPProvinceEntity ipProvinceEntity = iPProvinceService.getIPProvince(ipAddress);
if (ipProvinceEntity == null) {
// 匹配不到,再请求高德IP定位服务。
JSONObject userObj = new JSONObject();
userObj.put("ip", ipAddress);
userObj.put("key", ipPositionRequestKey);

JSONObject json = okHttpUtil.postRequestWithJson(ipPositionRequestPath, null, userObj);
if (ObjectUtils.isNotEmpty(json)) {
String province = (String) json.get("province");
if (ObjectUtils.isEmpty(province)) {
log.debug("json is :" + json.toString());
return null;
}
return province;
} else {
// 意外错误
log.debug("ip address is null");
return null;
}
} else {
return ipProvinceEntity.getProvince();
}
}

// 将IP对应的省会保存到mongoDB
@Async("asyncServiceExecutor")
public void createIPProvince(String ipAddress, String province) {
log.debug("异步创建推送失败任务记录!");
try {
IPProvinceEntity ipProvinceEntity = iPProvinceService.getIPProvince(ipAddress);
if (ipProvinceEntity == null) {
//DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
ipProvinceEntity.setIp(ipAddress);
ipProvinceEntity.setProvince(province);
iPProvinceService.saveIPProvince(ipProvinceEntity);
// } else {
//
// ipProvinceEntity.setProvince(province);
// iPProvinceService.updateIPProvince(ipProvinceEntity, ipProvinceEntity);
}
} catch (Exception e) {
log.error("创建推送失败记录异常:", e);
}
}

/*
* 获取定位辅助信息
* @param ipAddress
*/
@Override
@Async("asyncServiceExecutor")
public String pushAstPos(String ipAddress,
String centerProvinceFilePath,
String centerProvince,
String ipPositionRequestPath,
String ipPositionRequestKey) throws UnsupportedEncodingException {
this.ipPositionRequestKey = ipPositionRequestKey;
this.ipPositionRequestPath = ipPositionRequestPath;
this.centerProvince = centerProvince;
this.centerProvinceFilePath = centerProvinceFilePath;
// (1) 获取省会城市信息
String centerAddress = getIpPositionProvince(ipAddress);
if (ObjectUtils.isEmpty(centerAddress) || centerAddress.equals("0")) {
log.warn("IP地址非法,无法获取辅助位置信息!");
// 返回武汉的定位数据
centerAddress = this.centerProvince;
} else {
// 保存到mongoDB
createIPProvince(ipAddress, centerAddress);
}

String lonAndAlt;
if (redisUtil.hasKey(centerAddress)) {
// 获取省会城市定位信息
lonAndAlt= (String) redisUtil.get(centerAddress);
} else {
// 请求高德IP定位服务
this.getPosFromFile(centerAddress);
lonAndAlt = (String) redisUtil.get(centerAddress);
}

// (2) 处理返回结果
if (lonAndAlt == null) {
// null处理
log.error("系统错误,请联系系统管理员。");
return null;
//return;
}

// push to GNNS Server
String pushResult = getCmdOfPos(lonAndAlt);
return pushResult;
}

// 组装命令发送给设备
private String getCmdOfPos(String astPos) {

// 创建Socket客户端实例;
// SocketClient client = new SocketClient(astServer, posAstPort, astTimeout);

// 时间和位置不是从服务器获取,而是本地生成
String[] astPosArray = astPos.split(",");
String lan = astPosArray[0].trim();
String alt = astPosArray[1].trim();
double lanValue = Double.parseDouble(lan) * 10000000;
long lanLongValue = Double.doubleToLongBits(lanValue);
if (lanLongValue < 0) {
lanLongValue = lanLongValue + 4294967295L + 1;
}
double altValue = Double.parseDouble(alt) * 10000000;
long altLongValue = Double.doubleToLongBits(altValue);
if (altLongValue < 0) {
altLongValue = altLongValue + 4294967295L + 1;
}
// 数值换算举例(以经度举例。纬度、高度、位置精度换算方法一致):
// (1)经度数值为 113.431,则换算方法如下:
// 113.431/比例因子 = 1134310000(十进制)
//  439C3270(十六进制)
//  经度数据填入 70 32 9C 43(小端模式)
// (2)经度数值为-113.431,则换算方法如下:
// 113.431/比例因子 = 1134310000(十进制)
//  439C3270(十六进制)
//  FFFFFFFF - 439C3270 + 1= BC63CD90(补码)
// 经度数据填入 90 CD 63 BC(小端模式)
// 指令(十六进制)
// 举例: 23 3E 04 01 10 00 70 32 9C 43 D0 B2 CE 0D 70 17 00 00 40 0D 03 00 CA 95
// 其中
// 23 3E 为同步头
// 04 01 为识别码
// 10 00 表示长度为 16
// 70 32 9C 43 表示注入的辅助经度为 113.431 度
// D0 B2 CE 0D 表示注入的辅助纬度为 23.165 度
// 00 2F 为校验和

// astTimeCmd 组装
String astTimeCmd = "233E0401";
astTimeCmd += "1000";
astTimeCmd += HexConvert.encodeHEX(lanLongValue);
astTimeCmd += HexConvert.encodeHEX(altLongValue);

String hexIn = HexConvert.convertStringToHex(astTimeCmd) + HexConvert.makeChecksum(astTimeCmd);

//String sendResult = client.sendCmd(hexIn, ackAckCheckRef);
//client.closeConnection();

//return sendResult;
return hexIn;
}
}

+ 106
- 0
src/main/java/com/telpo/beidouast/service/impl/DipperAstTimeAsyncTaskServiceImpl.java Целия файл

@@ -0,0 +1,106 @@
package com.telpo.dipperposition.service.impl;

import com.telpo.dipperposition.common.HexConvert;
import com.telpo.dipperposition.common.SocketClient;
import com.telpo.dipperposition.service.IDipperAstTimeAsyncTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

/**
* @program: DipperDataAsyncTaskServiceImpl
* @description: 发送SDBP-AST-TIME获取时间信息
* @author: king
* @create: 2021-01-10 14:01
*/
@Service
@Slf4j
public class DipperAstTimeAsyncTaskServiceImpl implements IDipperAstTimeAsyncTaskService {

@Override
@Async("asyncServiceExecutor")
public String pushAstTime() {

// (1) 发送SDBP-AST-TIME
// String sendResult = pushTimeToDipper();
//if (sendResult == null) {
// log.error("取不到时间。");
// return null;
//}

// (2) 获取时间信息
return pushTimeToDipper();
//return sendResult;
}

private String pushTimeToDipper() {

// 创建Socket客户端实例;
// SocketClient client = new SocketClient(astServer, timeAstPort, astTimeout);

// 时间和位置不是从服务器获取,而是本地生成(其中时间误差不超过3s)
// 23 3E 04 02 10 00 20 E1 07 09 14 0C 22 38 00 00 00 00 00 28 6B EE 22 98
// 23 3E 为同步头
// 04 02 为识别码
// 10 00 表示长度为 16
// --日期--
// 20 E1 表示闰秒改正数为
// E1 07 表示年为 2017 年(十六进制 07E1 转为十进制)
// 09 表示 9 月
// 14 表示 20 日
// 0C 22 38 00 00 00 00 00 表示 UTC时间,为12时34分56.0秒(小数秒建议固定为 0)
// 00 28 6B EE 表示 4 秒的时间精度(十六进制 EE6B2800 转为十进制为 4000000000,乘以比 例因子 10-9就是 4 秒)
// 00 2F 为校验和
// TODO astTimeCmd 组装
String astTimeCmd = "233E0402";
astTimeCmd += "1000";
astTimeCmd += "20E1";
LocalDateTime now = LocalDateTime.now();
int year = now.getYear();
int month = now.getMonthValue();
int day = now.getDayOfMonth();
String hexYearString = Integer.toHexString(year);
hexYearString = "0" + hexYearString;
astTimeCmd += hexYearString.substring(2,2) + hexYearString.substring(0,2);
String hexMonthString = Integer.toHexString(month);
hexMonthString = "0" + hexMonthString;
astTimeCmd += hexMonthString;
String hexDayString = Integer.toHexString(day);
if (day < 16) {
hexDayString = "0" + hexDayString;
}
astTimeCmd += hexDayString;

int hour = now.getHour();
int minitor = now.getMinute();
int second = now.getSecond();
String hexHourString = Integer.toHexString(hour);
if (hour < 16) {
hexHourString = "0" + hexHourString;
}
astTimeCmd += hexHourString;
String hexMinitorString = Integer.toHexString(minitor);
if (minitor < 16) {
hexMinitorString = "0" + hexMinitorString;
}
astTimeCmd += hexMinitorString;
String hexSecondString = Integer.toHexString(second);
if (second < 16) {
hexSecondString = "0" + hexSecondString;
}
astTimeCmd += hexSecondString;
astTimeCmd += "0000000000";
astTimeCmd += "00286BEE";

String hexIn = HexConvert.convertStringToHex(astTimeCmd) + HexConvert.makeChecksum(astTimeCmd);

//String ackAckCheckRef = "233E0101020004020A1D";
//String sendResult = client.sendCmd(hexIn, ackAckCheckRef);
//client.closeConnection();

return hexIn;
}
}

+ 68
- 0
src/main/java/com/telpo/beidouast/service/impl/DipperDataAsyncTaskServiceImpl.java Целия файл

@@ -0,0 +1,68 @@
package com.telpo.dipperposition.service.impl;

import com.telpo.dipperposition.common.HexConvert;
import com.telpo.dipperposition.common.RedisUtil;
import com.telpo.dipperposition.common.SocketClient;
import com.telpo.dipperposition.config.SchedulingExecutorConfig;
import com.telpo.dipperposition.service.IDipperDataAsyncTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

/**
* @program: DipperDataAsyncTaskServiceImpl
* @description: 获取星历数据。
* @author: king
* @create: 2021-01-10 14:01
*/
@Service
@Slf4j
public class DipperDataAsyncTaskServiceImpl implements IDipperDataAsyncTaskService {


private static String DIPPER_DATA_KEY = "TaidouDipperData";
private static String DIPPER_ALL_DATA_REQ = "616C6C";

@Autowired
private RedisUtil redisUtil;
@Autowired
private SchedulingExecutorConfig schedulingExecutorConfig;

@Override
public void pullAstEPH() {
// (1) 发送bds获取星历数据
String dipperData = pullEPHFromDipper();

// (2) 获取星历数据
if (dipperData == null) {
log.error("获取星历数据错误,取不到星历数据。");
} else {
// 保存到DB或者缓存
redisUtil.set(DIPPER_DATA_KEY,dipperData);
}
}


private String pullEPHFromDipper() {

// 创建Socket客户端实例;
SocketClient client = new SocketClient(schedulingExecutorConfig.getAstServer(), schedulingExecutorConfig.getEphAstHexPort(),schedulingExecutorConfig.getAstTimeout());

// astTimeCmd 组装
String astTimeCmd = DIPPER_ALL_DATA_REQ;
String hexIn = astTimeCmd + HexConvert.makeChecksum(astTimeCmd);

String ackAckCheckRef = "233E010102000421293C";
String sendResult = client.sendCmd(hexIn, ackAckCheckRef);
client.closeConnection();

return sendResult;
}

@Override
@Async("asyncServiceExecutor")
public String getAstEPH(){
return (String)redisUtil.get(DIPPER_DATA_KEY);
}
}

+ 62
- 0
src/main/java/com/telpo/beidouast/service/impl/IPProvinceServiceImpl.java Целия файл

@@ -0,0 +1,62 @@
package com.telpo.dipperposition.service.impl;

import com.telpo.dipperposition.entity.mongo.IPProvinceEntity;
import com.telpo.dipperposition.mapper.IPProvinceMapper;
import com.telpo.dipperposition.service.IPProvinceService;
import com.telpo.dipperposition.vo.IPProvinceVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
* @program: DataPushServer
* @description: 推送记录服务接口实现类
* @author: linwl
* @create: 2020-07-20 11:09
*/
@Slf4j
@Service
public class IPProvinceServiceImpl implements IPProvinceService {

@Autowired
private IPProvinceMapper iPProvinceMapper;

@Override
public boolean saveIPProvince(IPProvinceEntity entity) {
iPProvinceMapper.save(entity);
return true;
}

@Override
public boolean updateIPProvince(
IPProvinceEntity query, IPProvinceEntity update) {
iPProvinceMapper.updateFirst(query, update);
return true;
}

@Override
public boolean romveById(String id) {
iPProvinceMapper.deleteById(id);
return false;
}

@Override
public IPProvinceEntity getIPProvince(String ipAddress) {
try {
IPProvinceEntity query = new IPProvinceEntity();
query.setIp(ipAddress);
List<IPProvinceEntity> pushRecords = iPProvinceMapper.queryList(query);
if (ObjectUtils.isNotEmpty(pushRecords)) {
return pushRecords.get(0);
} else {
return null;
}
} catch (Exception e) {
log.error("获取IP省份异常:", e);
return null;
}
}
}

+ 40
- 0
src/main/java/com/telpo/beidouast/task/ScheduleService.java Целия файл

@@ -0,0 +1,40 @@
package com.telpo.dipperposition.task;

import com.telpo.dipperposition.service.IDipperDataAsyncTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;


/**
* @program: ScheduleService
* @description: 定时执行任务服务
* @author: king
* @create: 2021-01-17 16:24
*/
@Component
@Slf4j
public class ScheduleService {

@Autowired
private IDipperDataAsyncTaskService dipperDataAsyncTaskService;

/*
* 调用9012端口的接口获取星历数据。
* 通过TCP连接服务器agnss.techtotop.com:9012,发送bds获取星历数据。
* 每30分钟获取1次,30秒超时,
* 如果失败,则可以等待10秒再获取1次。 *
*/
@Scheduled(cron = "${scheduler.task.cron}")
public void pullData() {
log.info("开始星历数据同步!");
// 获取推送失败的记录
try {
dipperDataAsyncTaskService.pullAstEPH();
} catch (Exception e) {
log.error("执行定时获取星历数据发生异常:", e);
}
}
}

+ 20
- 0
src/main/java/com/telpo/beidouast/vo/IPProvinceVo.java Целия файл

@@ -0,0 +1,20 @@
package com.telpo.dipperposition.vo;

import lombok.Getter;
import lombok.Setter;

/**
* @program: DataPushServer
* @description: 基础类
* @author: linwl
* @create: 2020-07-17 16:41
*/
@Setter
@Getter
public class IPProvinceVo {

/** Ip */
private String ip;
/** Ip所在省份 */
private String province;
}

+ 69
- 0
src/main/resources/bootstrap.yaml Целия файл

@@ -0,0 +1,69 @@
logging:
config: classpath:log/logback-spring.xml
level:
com:
telpo:
dipperposition: debug
spring:
application:
name: dipperposition-service
redis:
database: 1
host: 172.16.192.26
port: 8090
password: telpo#1234
timeout: 3000
lettuce:
pool:
max-active: 100 # 连接池最大连接数(使用负值表示没有限制)
max-idle: 100 # 连接池中的最大空闲连接
min-idle: 50 # 连接池中的最小空闲连接
max-wait: 6000 # 连接池最大阻塞等待时间(使用负值表示没有限制)

scheduler:
pool:
size: 2
#等待任务完成退出最大秒数
await-seconds: 600
task:
cron: "0 0 1 * * ?"

pos:
centerProvinceFilePath: /csv/provinceLonAlt.csv
ipPositionRequestPath: https://restapi.amap.com/v3/ip
ipPositionRequestKey: 65e794b0a1a4b87eeec86f93fea05411
centerProvince: 湖北省
ast:
server: agnss.techtotop.com
ephAstPort: 8012
ephAstHexPort: 9012
timeout: 30000

position-server:
serverAddr: localhost
timeAsycPort: 9011
posAsycPort: 9013
starsAsycPort: 9012

mongo:
datasource:
dblist:
- uri: mongodb://wangjx:wangjx#1234@172.16.192.26:27017/basicdata
database: basicdata
- uri: mongodb://wangjx:wangjx#1234@172.16.192.26:27017/common
database: common


OkHttp-config:
pool:
max-conn: 200
keep-alive: 5
read-timeout: 10
conn-timeout: 10
write-timeout: 10

async:
pool:
corePoolSize: 4
maxPoolSize: 8
queueCapacity: 5000

+ 35
- 0
src/main/resources/csv/provinceLonAlt.csv Целия файл

@@ -0,0 +1,35 @@
城市,经度,纬度,省份
沈阳市,123.429092,41.796768,辽宁省
长春市,125.324501,43.886841,吉林省
哈尔滨市,126.642464,45.756966,黑龙江省
北京市,116.405289,39.904987,北京市
天津市,117.190186,39.125595,天津市
呼和浩特市,111.75199,40.84149,内蒙古自治区
银川市,106.23248,38.48644,宁夏回族自治区
太原市,112.549248,37.857014,山西省
石家庄市,114.502464,38.045475,河北省
济南市,117.000923,36.675808,山东省
郑州市,113.665413,34.757977,河南省
西安市,108.948021,34.263161,陕西省
武汉市,114.298569,30.584354,湖北省
南京市,118.76741,32.041546,江苏省
合肥市,117.283043,31.861191,安徽省
上海市,121.472641,31.231707,上海市
长沙市,112.982277,28.19409,湖南省
南昌市,115.892151,28.676493,江西省
杭州市,120.15358,30.287458,浙江省
福州市,119.306236,26.075302,福建省
广州市,113.28064,23.125177,广东省
台北市,121.520076,25.030724,台湾省
海口市,110.19989,20.04422,海南省
南宁市,108.320007,22.82402,广西壮族自治区
重庆市,106.504959,29.533155,重庆市
昆明市,102.71225,25.040609,云南省
贵阳市,106.713478,26.578342,贵州省
成都市,104.065735,30.659462,四川省
兰州市,103.83417,36.06138,甘肃省
西宁市,101.77782,36.61729,青海省
拉萨市,91.1145,29.64415,西藏自治区
乌鲁木齐市,87.61688,43.82663,新疆维吾尔自治区
香港,114.16546,22.27534,香港特别行政区
澳门,113.54913,22.19875,澳门特别行政区

+ 198
- 0
src/main/resources/log/logback-spring.xml Целия файл

@@ -0,0 +1,198 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="10 seconds">

<!--<include resource="org/springframework/boot/logging/logback/base.xml" />-->
<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
<!-- property name="log.path" value="/var/log/dipperposition"/ -->
<property name="log.path" value="/home/data/dipperposition"/>

<!-- 彩色日志 -->
<!-- 彩色日志依赖的渲染类 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/>
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/>
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/>
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>


<!--输出到控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>debug</level>
</filter>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>


<!--输出到文件-->

<!-- 时间滚动输出 level为 DEBUG 日志 -->
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_debug.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志归档 -->
<fileNamePattern>${log.path}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录debug级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>debug</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<!-- 时间滚动输出 level为 INFO 日志 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_info.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>info</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<!-- 时间滚动输出 level为 WARN 日志 -->
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_warn.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录warn级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>


<!-- 时间滚动输出 level为 ERROR 日志 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_error.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录ERROR级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<!--
<logger>用来设置某一个包或者具体的某一个类的日志打印级别、
以及指定<appender>。<logger>仅有一个name属性,
一个可选的level和一个可选的addtivity属性。
name:用来指定受此logger约束的某一个包或者具体的某一个类。
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。
如果未设置此属性,那么当前logger将会继承上级的级别。
addtivity:是否向上级logger传递打印信息。默认是true。
-->
<!--<logger name="org.springframework.web" level="info"/>-->
<!--<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>-->
<!--
使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
第二种就是单独给dao下目录配置debug模式,代码如下,这样配置sql语句会打印,其他还是正常info级别:
-->


<!--
root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
不能设置为INHERITED或者同义词NULL。默认是DEBUG
可以包含零个或多个元素,标识这个appender将会添加到这个logger。
-->

<!--开发环境:打印控制台-->
<springProfile name="dev">
<logger name="com.telpo.dipperposition" level="debug"/>
</springProfile>

<root level="info">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="DEBUG_FILE"/>
<appender-ref ref="INFO_FILE"/>
<appender-ref ref="WARN_FILE"/>
<appender-ref ref="ERROR_FILE"/>
</root>

<!--生产环境:输出到文件-->
<!--<springProfile name="pro">-->
<!--<root level="info">-->
<!--<appender-ref ref="CONSOLE" />-->
<!--<appender-ref ref="DEBUG_FILE" />-->
<!--<appender-ref ref="INFO_FILE" />-->
<!--<appender-ref ref="ERROR_FILE" />-->
<!--<appender-ref ref="WARN_FILE" />-->
<!--</root>-->
<!--</springProfile>-->

</configuration>

Loading…
Отказ
Запис