first commit
This commit is contained in:
commit
8ddb6a0af6
30
.gitignore
vendored
Normal file
30
.gitignore
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
HELP.md
|
||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
log/
|
||||||
|
|
||||||
|
### STS ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
build/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
||||||
31
pom.xml
Normal file
31
pom.xml
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>2.7.5</version>
|
||||||
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<groupId>com.imdroid</groupId>
|
||||||
|
<artifactId>security-monitor</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<modules>
|
||||||
|
<module>sec-common</module>
|
||||||
|
<module>sec-beidou</module>
|
||||||
|
<module>sec-beidou-rtcm</module>
|
||||||
|
<module>sec-api</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<moyu.version>1.0.0</moyu.version>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
<java.version>8</java.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
||||||
93
sec-api/pom.xml
Normal file
93
sec-api/pom.xml
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.imdroid</groupId>
|
||||||
|
<artifactId>security-monitor</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>sec-api</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.yulichang</groupId>
|
||||||
|
<artifactId>mybatis-plus-join-boot-starter</artifactId>
|
||||||
|
<version>1.4.3</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||||
|
<version>3.5.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
<version>8.0.24</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<excludes>
|
||||||
|
<exclude>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</exclude>
|
||||||
|
</excludes>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>central</id>
|
||||||
|
<name>ali-mirror</name>
|
||||||
|
<url>https://maven.aliyun.com/repository/central</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
</project>
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
package com.imdroid.secapi.dto;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GNSS解算结果,每个工作周期解算一次
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName(value = "gnssdevicelocationrecords")
|
||||||
|
public class GnssCalcData {
|
||||||
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
|
Long id;
|
||||||
|
boolean enabled;
|
||||||
|
Timestamp createtime;
|
||||||
|
String deviceid;
|
||||||
|
double b562e;
|
||||||
|
double b562n;
|
||||||
|
double b562d;
|
||||||
|
double r9250e;
|
||||||
|
double r9250n;
|
||||||
|
double r9250d;
|
||||||
|
double resulte;
|
||||||
|
double resultn;
|
||||||
|
double resultd;
|
||||||
|
int tenantid;
|
||||||
|
double rb562e;
|
||||||
|
double rb562d;
|
||||||
|
double rb562n;
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
package com.imdroid.secapi.dto;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface GnssCalcDataMapper extends BaseMapper<GnssCalcData> {
|
||||||
|
@Select({"select * from gnssdevicelocationrecords where deviceid = #{deviceId} limit 1"})
|
||||||
|
GnssCalcData queryByDeviceId(String deviceId);
|
||||||
|
}
|
||||||
42
sec-api/src/main/java/com/imdroid/secapi/dto/GnssDevice.java
Normal file
42
sec-api/src/main/java/com/imdroid/secapi/dto/GnssDevice.java
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package com.imdroid.secapi.dto;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GNSS设备配置数据
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName(value = "gnssdevices")
|
||||||
|
public class GnssDevice {
|
||||||
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
|
private Long id;
|
||||||
|
private Short opmode;
|
||||||
|
private Timestamp createtime;
|
||||||
|
private String createuser;
|
||||||
|
private Timestamp updatetime;
|
||||||
|
private String updateuser;
|
||||||
|
private String deviceid;
|
||||||
|
private String name;
|
||||||
|
private String parentid;
|
||||||
|
private Integer devicetype;
|
||||||
|
private Integer tenantid;
|
||||||
|
private String tenantname;
|
||||||
|
private String gnssconfiguration;
|
||||||
|
private Integer project_id = 0;
|
||||||
|
private Integer group_id = 1;
|
||||||
|
private Integer calc_group_id = 1;
|
||||||
|
private Integer fwd_group_id = 0;
|
||||||
|
private Boolean syn;
|
||||||
|
private String pictures;
|
||||||
|
|
||||||
|
public String getObjectName(){
|
||||||
|
return "gnssdevice";
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
package com.imdroid.secapi.dto;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface GnssDeviceMapper extends BaseMapper<GnssDevice> {
|
||||||
|
@Select({"select * from gnssdevices where deviceid = #{deviceId} limit 1"})
|
||||||
|
GnssDevice queryByDeviceId(String deviceId);
|
||||||
|
}
|
||||||
23
sec-api/src/main/java/com/imdroid/secapi/dto/GnssGroup.java
Normal file
23
sec-api/src/main/java/com/imdroid/secapi/dto/GnssGroup.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package com.imdroid.secapi.dto;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GNSS设备组参数,包括工作周期、工作时间等
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName(value = "gnssgroup")
|
||||||
|
public class GnssGroup implements Serializable {
|
||||||
|
Integer id;
|
||||||
|
int work_cycle;
|
||||||
|
int active_time;
|
||||||
|
int active_offset;
|
||||||
|
short sample;
|
||||||
|
short power_mode;
|
||||||
|
int device_num;
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
package com.imdroid.secapi.dto;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface GnssGroupMapper extends BaseMapper<GnssGroup> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package com.imdroid.secapi.dto;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GNSS解算结果,每个工作周期解算一次
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName(value = "gnsssinglecalcdata")
|
||||||
|
public class GnssSingleCalcData {
|
||||||
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
|
Long id;
|
||||||
|
Timestamp createtime;
|
||||||
|
String deviceid;
|
||||||
|
double b562e = 0;
|
||||||
|
double b562n = 0;
|
||||||
|
double b562d = 0;
|
||||||
|
double roll = 0;
|
||||||
|
double pitch = 0;
|
||||||
|
double yaw = 0;
|
||||||
|
double shock = 0;
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
package com.imdroid.secapi.dto;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface GnssSingleCalcDataMapper extends BaseMapper<GnssSingleCalcData> {
|
||||||
|
|
||||||
|
}
|
||||||
45
sec-api/src/main/java/com/imdroid/secapi/dto/GnssStatus.java
Normal file
45
sec-api/src/main/java/com/imdroid/secapi/dto/GnssStatus.java
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
package com.imdroid.secapi.dto;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GNSS状态信息
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName(value = "gnssstatus")
|
||||||
|
public class GnssStatus {
|
||||||
|
public static final short STATE_OFFLINE = 0;
|
||||||
|
public static final short STATE_ACTIVE = 1;
|
||||||
|
public static final short STATE_IDLE = 2;
|
||||||
|
|
||||||
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
|
Long id;
|
||||||
|
Timestamp updatetime;
|
||||||
|
Timestamp devicetime;
|
||||||
|
String deviceid;
|
||||||
|
String location;
|
||||||
|
|
||||||
|
float roll;
|
||||||
|
float pitch;
|
||||||
|
float yaw;
|
||||||
|
int rssi;
|
||||||
|
int voltage;
|
||||||
|
float temperature;
|
||||||
|
float humidity;
|
||||||
|
int satelliteinview;
|
||||||
|
int satelliteinuse;
|
||||||
|
// 这里的收发都是服务端统计的,终端收发详细统计在msg_trx表里
|
||||||
|
int txbytes;
|
||||||
|
int rxbytes;
|
||||||
|
int b562bytes;
|
||||||
|
int d3xxbytes;
|
||||||
|
short state;
|
||||||
|
short warning;
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
package com.imdroid.secapi.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class GnssStatusJoin {
|
||||||
|
Long id;
|
||||||
|
Timestamp updatetime;
|
||||||
|
Timestamp devicetime;
|
||||||
|
String deviceid;
|
||||||
|
String location;
|
||||||
|
|
||||||
|
float roll;
|
||||||
|
float pitch;
|
||||||
|
float yaw;
|
||||||
|
int rssi;
|
||||||
|
int voltage;
|
||||||
|
float temperature;
|
||||||
|
float humidity;
|
||||||
|
int satelliteinview;
|
||||||
|
int satelliteinuse;
|
||||||
|
// 这里的收发都是服务端统计的,终端收发详细统计在msg_trx表里
|
||||||
|
int txbytes;
|
||||||
|
int rxbytes;
|
||||||
|
int b562bytes;
|
||||||
|
int d3xxbytes;
|
||||||
|
short state;
|
||||||
|
short warning;
|
||||||
|
|
||||||
|
short devicetype;
|
||||||
|
int tenantid;
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package com.imdroid.secapi.dto;
|
||||||
|
|
||||||
|
import com.github.yulichang.base.MPJBaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface GnssStatusMapper extends MPJBaseMapper<GnssStatus> {
|
||||||
|
|
||||||
|
@Select({"select * from gnssstatus where deviceid = #{deviceId} limit 1"})
|
||||||
|
GnssStatus getByDeviceId(String deviceId);
|
||||||
|
|
||||||
|
@Select({"select s.*, d.devicetype, d.tenantid from gnssstatus s ,gnssdevices d where s.deviceid=d.deviceid and s.deviceid = #{deviceId}"})
|
||||||
|
GnssStatusJoin queryByDeviceId(String deviceId);
|
||||||
|
|
||||||
|
@Select({"select s.*, d.devicetype, d.tenantid from gnssstatus s ,gnssdevices d where s.deviceid=d.deviceid"})
|
||||||
|
GnssStatusJoin queryAll();
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package com.imdroid.secapi.dto;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GNSS状态消息,每个工作周期开始时上报一次
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName(value = "gnssstatusmsg")
|
||||||
|
public class GnssStatusMsg {
|
||||||
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
|
Long id;
|
||||||
|
Timestamp updatetime;
|
||||||
|
Timestamp devicetime;
|
||||||
|
String deviceid;
|
||||||
|
float roll;
|
||||||
|
float pitch;
|
||||||
|
float yaw;
|
||||||
|
short dtustate;
|
||||||
|
int rssi;
|
||||||
|
int voltage;
|
||||||
|
float temperature;
|
||||||
|
float humidity;
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
package com.imdroid.secapi.dto;
|
||||||
|
|
||||||
|
import com.github.yulichang.base.MPJBaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface GnssStatusMsgMapper extends MPJBaseMapper<GnssStatusMsg> {
|
||||||
|
|
||||||
|
}
|
||||||
34
sec-api/src/main/java/com/imdroid/secapi/dto/GnssTrxMsg.java
Normal file
34
sec-api/src/main/java/com/imdroid/secapi/dto/GnssTrxMsg.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package com.imdroid.secapi.dto;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GNSS收发统计消息,每个工作周期结束的时候统计一次
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName(value = "gnsstrxmsg")
|
||||||
|
public class GnssTrxMsg {
|
||||||
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
|
Long id;
|
||||||
|
Timestamp updatetime;
|
||||||
|
Timestamp devicetime;
|
||||||
|
String deviceid;
|
||||||
|
long uart1txbytes;
|
||||||
|
long uart1rxbytes;
|
||||||
|
long uart1unknown;
|
||||||
|
long uart2txbytes;
|
||||||
|
long uart2rxbytes;
|
||||||
|
long uart2unknown;
|
||||||
|
// 这里的收发都是服务端统计的,终端收发详细统计在msg_trx表里
|
||||||
|
long servertxbytes;
|
||||||
|
long serverrxbytes;
|
||||||
|
long b562bytes;
|
||||||
|
long d3xxbytes;
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
package com.imdroid.secapi.dto;
|
||||||
|
|
||||||
|
import com.github.yulichang.base.MPJBaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface GnssTrxMsgMapper extends MPJBaseMapper<GnssTrxMsg> {
|
||||||
|
|
||||||
|
}
|
||||||
183
sec-beidou-rtcm/pom.xml
Normal file
183
sec-beidou-rtcm/pom.xml
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.imdroid</groupId>
|
||||||
|
<artifactId>security-monitor</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>sec-beidou-rtcm</artifactId>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<logback.version>1.2.3</logback.version>
|
||||||
|
<dt20.common.version>1.0-SNAPSHOT</dt20.common.version>
|
||||||
|
<dt20.util.version>1.0-SNAPSHOT</dt20.util.version>
|
||||||
|
<java.version>8</java.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-dependencies</artifactId>
|
||||||
|
<version>Greenwich.SR2</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-devtools</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>org.springframework.cloud</groupId>-->
|
||||||
|
<!-- <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
<version>8.0.11</version><!--$NO-MVN-MAN-VER$ -->
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<version>1.7.21</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-classic</artifactId>
|
||||||
|
<version>${logback.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>netty-all</artifactId>
|
||||||
|
<version>4.1.78.Final</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
<version>2.9.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
<version>4.5.13</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<version>31.1-jre</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.12</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-all</artifactId>
|
||||||
|
<version>5.5.8</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.yulichang</groupId>
|
||||||
|
<artifactId>mybatis-plus-join-boot-starter</artifactId>
|
||||||
|
<version>1.4.3</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||||
|
<version>3.5.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.imdroid</groupId>
|
||||||
|
<artifactId>sec-api</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>dt20.io</groupId>
|
||||||
|
<artifactId>dt20-common</artifactId>
|
||||||
|
<version>${dt20.common.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>dt20.io</groupId>
|
||||||
|
<artifactId>dt20-util</artifactId>
|
||||||
|
<version>${dt20.util.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<finalName>sideslope-rtcm-server</finalName>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.8.0</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>central</id>
|
||||||
|
<name>ali-mirror</name>
|
||||||
|
<url>https://maven.aliyun.com/repository/central</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
</project>
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
package com.imdroid.sideslope;
|
||||||
|
|
||||||
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/1/31 20:33
|
||||||
|
*/
|
||||||
|
@SpringBootApplication(scanBasePackages = {"com.imdroid"})
|
||||||
|
@MapperScan({"com.imdroid.secapi.dto","com.imdroid.beidou.entity"})
|
||||||
|
@ComponentScan({"io.dt20.*", "com.imdroid.*"})
|
||||||
|
@EntityScan({"io.dt20.common.persistence", "com.imdroid.*"})
|
||||||
|
@EnableJpaRepositories({"io.dt20.common.repo", "com.imdroid.*"})
|
||||||
|
public class SideSlopeRtcmApp {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(SideSlopeRtcmApp.class, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,644 @@
|
|||||||
|
package com.imdroid.sideslope.bd;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Byte util.
|
||||||
|
*/
|
||||||
|
public class ByteUtil {
|
||||||
|
|
||||||
|
private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5',
|
||||||
|
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||||
|
|
||||||
|
private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5',
|
||||||
|
'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||||
|
|
||||||
|
public static byte[] getBytes(int data) {
|
||||||
|
byte[] bytes = new byte[4];
|
||||||
|
bytes[0] = (byte) (data & 0xff);
|
||||||
|
bytes[1] = (byte) ((data & 0xff00) >> 8);
|
||||||
|
bytes[2] = (byte) ((data & 0xff0000) >> 16);
|
||||||
|
bytes[3] = (byte) ((data & 0xff000000) >> 24);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static short getShort(byte[] bytes) {
|
||||||
|
return (short) ((0xff & bytes[0]) | (0xff00 & (bytes[1] << 8)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static short getShort(byte high, byte low) {
|
||||||
|
return (short) (((high & 0xff) << 8) | (low & 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] getBytes(String data, String charsetName) {
|
||||||
|
Charset charset = Charset.forName(charsetName);
|
||||||
|
return data.getBytes(charset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] getBytes(String data) {
|
||||||
|
return getBytes(data, "GBK");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getString(byte[] bytes) {
|
||||||
|
return getString(bytes, "GBK");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getString(byte[] bytes, String charsetName) {
|
||||||
|
return new String(bytes, Charset.forName(charsetName));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static int toUnsignedInt(byte paramByte) {
|
||||||
|
return paramByte & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取byte类型的时间
|
||||||
|
*
|
||||||
|
* @param time
|
||||||
|
* @return 获取byte类型的时间
|
||||||
|
*/
|
||||||
|
public static byte[] getTimeToBytes(Date time) {
|
||||||
|
String times = new SimpleDateFormat("yy MM dd HH mm ss", Locale.CHINA).format(time)
|
||||||
|
.replaceAll(" ", "");
|
||||||
|
byte[] date = new byte[6];
|
||||||
|
|
||||||
|
for (int i = 0, j = 0; i < times.length(); i += 2, j++) {
|
||||||
|
date[j] = Byte.decode("0x" + times.charAt(i) + ""
|
||||||
|
+ times.charAt(i + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数组转16char数组
|
||||||
|
*
|
||||||
|
* @param data the data
|
||||||
|
* @param toLowerCase the to lower case
|
||||||
|
* @return the char [ ]
|
||||||
|
*/
|
||||||
|
public static char[] encodeHex(byte[] data, boolean toLowerCase) {
|
||||||
|
return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数组转16char数组
|
||||||
|
*
|
||||||
|
* @param data the data
|
||||||
|
* @param toDigits the to digits
|
||||||
|
* @return the char [ ]
|
||||||
|
*/
|
||||||
|
protected static char[] encodeHex(byte[] data, char[] toDigits) {
|
||||||
|
if (data == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int l = data.length;
|
||||||
|
char[] out = new char[l << 1];
|
||||||
|
for (int i = 0, j = 0; i < l; i++) {
|
||||||
|
out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
|
||||||
|
out[j++] = toDigits[0x0F & data[i]];
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数组转16进制字符串
|
||||||
|
*
|
||||||
|
* @param data the data
|
||||||
|
* @return the string
|
||||||
|
*/
|
||||||
|
public static String encodeHexStr(byte[] data) {
|
||||||
|
return encodeHexStr(data, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数组转16进制字符串
|
||||||
|
*
|
||||||
|
* @param data byte[]
|
||||||
|
* @param toLowerCase ture小写 false大写
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
public static String encodeHexStr(byte[] data, boolean toLowerCase) {
|
||||||
|
return encodeHexStr(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 锟斤拷锟街斤拷锟斤拷锟斤拷转锟斤拷为十锟斤拷锟斤拷锟斤拷锟街凤拷锟斤拷
|
||||||
|
*
|
||||||
|
* @param data byte[]
|
||||||
|
* @param toDigits 锟斤拷锟节匡拷锟斤拷锟斤拷锟斤拷锟絚har[]
|
||||||
|
* @return 十锟斤拷锟斤拷锟斤拷String string
|
||||||
|
*/
|
||||||
|
protected static String encodeHexStr(byte[] data, char[] toDigits) {
|
||||||
|
return new String(encodeHex(data, toDigits));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* long转16进制byte数组
|
||||||
|
*
|
||||||
|
* @param iSource the source
|
||||||
|
* @param iArrayLen the array len
|
||||||
|
* @return the byte [ ]
|
||||||
|
*/
|
||||||
|
public static byte[] tobyteArray(long iSource, int iArrayLen) {
|
||||||
|
byte[] bLocalArr = new byte[iArrayLen];
|
||||||
|
int i = 0;
|
||||||
|
int j = iArrayLen - 1;
|
||||||
|
for (; (i < 4) && (i < iArrayLen); i++, j--) {
|
||||||
|
bLocalArr[j] = (byte) (iSource >> 8 * i & 0xFF);
|
||||||
|
}
|
||||||
|
while (j >= 0) {
|
||||||
|
bLocalArr[j] = 0;
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
return bLocalArr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* int转16进制byte数组
|
||||||
|
*
|
||||||
|
* @param iSource the source
|
||||||
|
* @param iArrayLen the array len
|
||||||
|
* @return byte [ ]
|
||||||
|
*/
|
||||||
|
public static byte[] tobyteArray(int iSource, int iArrayLen) {
|
||||||
|
byte[] bLocalArr = new byte[iArrayLen];
|
||||||
|
int i = 0;
|
||||||
|
int j = iArrayLen - 1;
|
||||||
|
for (; (i < 4) && (i < iArrayLen); i++, j--) {
|
||||||
|
bLocalArr[j] = (byte) (iSource >> 8 * i & 0xFF);
|
||||||
|
}
|
||||||
|
while (j >= 0) {
|
||||||
|
bLocalArr[j] = 0;
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
return bLocalArr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 16进制字节转成int
|
||||||
|
*
|
||||||
|
* @param bRefArr the b ref arr
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public static int toInt(byte[] bRefArr) {
|
||||||
|
int iOutcome = 0;
|
||||||
|
byte bLoop;
|
||||||
|
|
||||||
|
for (int i = bRefArr.length - 1; i >= 0; i--) {
|
||||||
|
bLoop = bRefArr[i];
|
||||||
|
iOutcome += (bLoop & 0xFF) << (8 * (bRefArr.length - 1 - i));
|
||||||
|
}
|
||||||
|
return iOutcome;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Char tobyte byte.
|
||||||
|
*
|
||||||
|
* @param c the c
|
||||||
|
* @return the byte
|
||||||
|
*/
|
||||||
|
public static byte charTobyte(char c) {
|
||||||
|
return (byte) "0123456789ABCDEF".indexOf(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2进制转byte
|
||||||
|
*
|
||||||
|
* @param str the str
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public static int Binarytobyte(String str) {
|
||||||
|
String intstr = Integer.toString(Integer.parseInt(str, 2), 10);
|
||||||
|
return Integer.valueOf(intstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2进制字符转byte数组
|
||||||
|
*
|
||||||
|
* @param str the str
|
||||||
|
* @return the byte [ ]
|
||||||
|
*/
|
||||||
|
public static byte[] Binarytobytes(String str) {
|
||||||
|
int tmpint = 0;
|
||||||
|
for (int i = 0, j = 0; i < str.length(); i += 8, j++) {
|
||||||
|
String binarystr = str.charAt(i) + ""
|
||||||
|
+ str.charAt(i + 1) + "" + str.charAt(i + 2) + ""
|
||||||
|
+ str.charAt(i + 3) + "" + str.charAt(i + 4) + ""
|
||||||
|
+ str.charAt(i + 5) + "" + str.charAt(i + 6) + ""
|
||||||
|
+ str.charAt(i + 7);
|
||||||
|
System.out.println(i);
|
||||||
|
tmpint += Binarytobyte(binarystr);
|
||||||
|
}
|
||||||
|
System.out.println(tmpint);
|
||||||
|
return getBytes(tmpint);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将long转为byte数组
|
||||||
|
*
|
||||||
|
* @param number
|
||||||
|
* @return 将long转为byte数组
|
||||||
|
*/
|
||||||
|
public static byte[] longTobyte(long number) {
|
||||||
|
byte[] b = new byte[8];
|
||||||
|
|
||||||
|
b[0] = (byte) (number >> 56);
|
||||||
|
b[1] = (byte) (number >> 48);
|
||||||
|
b[2] = (byte) (number >> 40);
|
||||||
|
b[3] = (byte) (number >> 32);
|
||||||
|
b[4] = (byte) (number >> 24);
|
||||||
|
b[5] = (byte) (number >> 16);
|
||||||
|
b[6] = (byte) (number >> 8);
|
||||||
|
b[7] = (byte) number;
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将short转为byte数组
|
||||||
|
*
|
||||||
|
* @param number
|
||||||
|
* @return 将short转为byte数组
|
||||||
|
*/
|
||||||
|
public static byte[] shortTobyte(short number) {
|
||||||
|
byte[] b = new byte[2];
|
||||||
|
|
||||||
|
b[0] = (byte) (number >> 8);
|
||||||
|
b[1] = (byte) number;
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将int转为byte数组
|
||||||
|
*
|
||||||
|
* @param number
|
||||||
|
* @return 将int转为byte数组
|
||||||
|
*/
|
||||||
|
public static byte[] intTobyte(int number) {
|
||||||
|
byte[] b = new byte[4];
|
||||||
|
|
||||||
|
b[0] = (byte) (number >> 24);
|
||||||
|
b[1] = (byte) (number >> 16);
|
||||||
|
b[2] = (byte) (number >> 8);
|
||||||
|
b[3] = (byte) number;
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 八字节转成long
|
||||||
|
*
|
||||||
|
* @param b the b
|
||||||
|
* @return the long
|
||||||
|
*/
|
||||||
|
public static long toLong(byte[] b)
|
||||||
|
|
||||||
|
{
|
||||||
|
long l = 0;
|
||||||
|
|
||||||
|
l = b[0];
|
||||||
|
|
||||||
|
l |= ((long) b[1] << 8);
|
||||||
|
|
||||||
|
l |= ((long) b[2] << 16);
|
||||||
|
|
||||||
|
l |= ((long) b[3] << 24);
|
||||||
|
|
||||||
|
l |= ((long) b[4] << 32);
|
||||||
|
|
||||||
|
l |= ((long) b[5] << 40);
|
||||||
|
|
||||||
|
l |= ((long) b[6] << 48);
|
||||||
|
|
||||||
|
l |= ((long) b[7] << 56);
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数组转成十六进制字符串
|
||||||
|
*
|
||||||
|
* @param b the b
|
||||||
|
* @return HexString string
|
||||||
|
*/
|
||||||
|
public static String bytesToHexString(byte[] b) {
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
for (int i = 0; i < b.length; ++i) {
|
||||||
|
buffer.append(byteToHexString(b[i]));
|
||||||
|
}
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* byte转成16进制字符串
|
||||||
|
*
|
||||||
|
* @param b the b
|
||||||
|
* @return the string
|
||||||
|
*/
|
||||||
|
public static String byteToHexString(byte b) {
|
||||||
|
String s = Integer.toHexString(b & 0xFF);
|
||||||
|
if (s.length() == 1) {
|
||||||
|
return "0" + s;
|
||||||
|
} else {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 图片路径转成byte
|
||||||
|
*
|
||||||
|
* @param path the path
|
||||||
|
* @return the byte [ ]
|
||||||
|
*/
|
||||||
|
public static byte[] image2byte(String path) {
|
||||||
|
byte[] data = null;
|
||||||
|
FileInputStream input = null;
|
||||||
|
try {
|
||||||
|
input = new FileInputStream(new File(path));
|
||||||
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
|
byte[] buf = new byte[1024];
|
||||||
|
int numBytesRead = 0;
|
||||||
|
while ((numBytesRead = input.read(buf)) != -1) {
|
||||||
|
output.write(buf, 0, numBytesRead);
|
||||||
|
}
|
||||||
|
data = output.toByteArray();
|
||||||
|
output.close();
|
||||||
|
input.close();
|
||||||
|
} catch (FileNotFoundException ex1) {
|
||||||
|
ex1.printStackTrace();
|
||||||
|
} catch (IOException ex1) {
|
||||||
|
ex1.printStackTrace();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Byte 2 image boolean.
|
||||||
|
*
|
||||||
|
* @param data the data
|
||||||
|
* @param path the path
|
||||||
|
* @return the boolean
|
||||||
|
*/
|
||||||
|
// byte数组到图片
|
||||||
|
public static boolean byte2image(byte[] data, String path) {
|
||||||
|
if (data.length < 3 || "".equals(path)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
FileOutputStream imageOutput = new FileOutputStream(
|
||||||
|
new File(path));
|
||||||
|
imageOutput.write(data, 0, data.length);
|
||||||
|
imageOutput.close();
|
||||||
|
System.out.println("Make Picture success,Please find image in "
|
||||||
|
+ path);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
System.out.println("Exception: " + ex);
|
||||||
|
ex.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* byte叠加
|
||||||
|
*
|
||||||
|
* @param data1 the data 1
|
||||||
|
* @param data2 the data 2
|
||||||
|
* @return the byte [ ]
|
||||||
|
*/
|
||||||
|
public static byte[] addBytes(byte[] data1, byte[] data2) {
|
||||||
|
byte[] data3 = new byte[data1.length + data2.length];
|
||||||
|
System.arraycopy(data1, 0, data3, 0, data1.length);
|
||||||
|
System.arraycopy(data2, 0, data3, data1.length, data2.length);
|
||||||
|
return data3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bcd 2 str string.
|
||||||
|
*
|
||||||
|
* @param bytes the bytes
|
||||||
|
* @return the string
|
||||||
|
*/
|
||||||
|
public static String bcd2Str(byte[] bytes) {
|
||||||
|
|
||||||
|
StringBuffer temp = new StringBuffer(bytes.length * 2);
|
||||||
|
|
||||||
|
for (int i = 0; i < bytes.length; i++) {
|
||||||
|
|
||||||
|
temp.append((byte) ((bytes[i] & 0xf0) >>> 4));
|
||||||
|
temp.append((byte) (bytes[i] & 0x0f));
|
||||||
|
}
|
||||||
|
while (temp.charAt(0) == '0') {
|
||||||
|
temp.deleteCharAt(0);
|
||||||
|
}
|
||||||
|
return temp.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得参数内容
|
||||||
|
*/
|
||||||
|
public static byte[] getParameter(byte[] body, int length) {
|
||||||
|
byte[] content = new byte[length];
|
||||||
|
System.arraycopy(body, body.length - length, content, 0, length);
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 把16进制字符串转换成字节数组
|
||||||
|
*
|
||||||
|
* @return byte[]
|
||||||
|
*/
|
||||||
|
public static byte[] hexStringTobyte(String hex) {
|
||||||
|
hex = hex.toUpperCase();
|
||||||
|
int len = (hex.length() / 2);
|
||||||
|
byte[] result = new byte[len];
|
||||||
|
char[] achar = hex.toCharArray();
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
int pos = i * 2;
|
||||||
|
result[i] = (byte) (tobyte(achar[pos]) << 4 | tobyte(achar[pos + 1]));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字符串转16进制字符串
|
||||||
|
*
|
||||||
|
* @param strPart
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String string2HexString(String strPart) {
|
||||||
|
StringBuffer hexString = new StringBuffer();
|
||||||
|
for (int i = 0; i < strPart.length(); i++) {
|
||||||
|
int ch = (int) strPart.charAt(i);
|
||||||
|
String strHex = Integer.toHexString(ch);
|
||||||
|
hexString.append(strHex);
|
||||||
|
}
|
||||||
|
return hexString.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int tobyte(char c) {
|
||||||
|
byte b = (byte) "0123456789ABCDEF".indexOf(c);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换总里程
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @return 转换总里程
|
||||||
|
*/
|
||||||
|
public static String oneDecimal(double value) {
|
||||||
|
BigDecimal b = new BigDecimal(value);
|
||||||
|
return b.setScale(1, BigDecimal.ROUND_HALF_UP).toString();
|
||||||
|
}
|
||||||
|
//------工具区(经纬度解析)--------------------------------------------------
|
||||||
|
public static Double getLONG(Double location) {
|
||||||
|
if (location != 0.0) {
|
||||||
|
int head = Integer.parseInt(String.valueOf(location).substring(0, 3));
|
||||||
|
//System.out.println(head);
|
||||||
|
return head + (location / 100 - head) * 10 / 6;
|
||||||
|
}
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//一度为60分
|
||||||
|
public static Double getLAT(Double location) {
|
||||||
|
if (location != 0.0) {
|
||||||
|
int head = Integer.parseInt(String.valueOf(location).substring(0, 2));
|
||||||
|
// System.out.println(head);
|
||||||
|
return head + (location / 100 - head) * 10 / 6;
|
||||||
|
}
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将byte数组数据转换成float
|
||||||
|
* @param arr
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static float bytes2Float(byte[] arr) {
|
||||||
|
float f = ByteBuffer.wrap(arr).order(ByteOrder.BIG_ENDIAN).getFloat();
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* byte数组中取int数值,本方法适用于(低位在前,高位在后)的顺序
|
||||||
|
*
|
||||||
|
* @param src byte数组
|
||||||
|
* @return int数值
|
||||||
|
*/
|
||||||
|
public static int bytesToInt(byte[] src) {
|
||||||
|
int value;
|
||||||
|
value = (int) ((src[0] & 0xFF)
|
||||||
|
| ((src[1] & 0xFF)<<8)
|
||||||
|
| ((src[2] & 0xFF)<<16)
|
||||||
|
| ((src[3] & 0xFF)<<24));
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 把byte数组转化成2进制字符串
|
||||||
|
* @param bArr
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getBinaryStrFromByteArr(byte[] bArr){
|
||||||
|
String result ="";
|
||||||
|
for(byte b:bArr ){
|
||||||
|
result += getBinaryStrFromByte(b);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 把byte转化成2进制字符串
|
||||||
|
* @param b
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getBinaryStrFromByte(byte b){
|
||||||
|
String result ="";
|
||||||
|
byte a = b; ;
|
||||||
|
for (int i = 0; i < 8; i++){
|
||||||
|
byte c=a;
|
||||||
|
a=(byte)(a>>1);//每移一位如同将10进制数除以2并去掉余数。
|
||||||
|
a=(byte)(a<<1);
|
||||||
|
if(a==c){
|
||||||
|
result="0"+result;
|
||||||
|
}else{
|
||||||
|
result="1"+result;
|
||||||
|
}
|
||||||
|
a=(byte)(a>>1);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 二进制字符串转int
|
||||||
|
* @param binary
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static int binaryToInt(String binary) {
|
||||||
|
if (binary == null ) {
|
||||||
|
System. out .println( "can't input null !" );
|
||||||
|
}
|
||||||
|
if (binary.isEmpty()) {
|
||||||
|
System. out .println( "you input is Empty !" );
|
||||||
|
}
|
||||||
|
int max = binary.length();
|
||||||
|
String new_binary = "" ;
|
||||||
|
if (max >= 2 && binary.startsWith( "0" )) {
|
||||||
|
int position = 0;
|
||||||
|
for ( int i = 0; i < binary.length(); i++) {
|
||||||
|
char a = binary.charAt(i);
|
||||||
|
if (a != '0' ) {
|
||||||
|
position = i;
|
||||||
|
break ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (position == 0) {
|
||||||
|
new_binary = binary.substring(max - 1, max);
|
||||||
|
} else {
|
||||||
|
new_binary = binary.substring(position, max);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
new_binary = binary;
|
||||||
|
}
|
||||||
|
int new_width = new_binary.length();
|
||||||
|
|
||||||
|
long result = 0;
|
||||||
|
if (new_width < 32) {
|
||||||
|
for ( int i = new_width; i > 0; i--) {
|
||||||
|
char c = new_binary.charAt(i - 1);
|
||||||
|
int algorism = c - '0' ;
|
||||||
|
result += Math. pow(2, new_width - i) * algorism;
|
||||||
|
}
|
||||||
|
} else if (new_width == 32) {
|
||||||
|
for ( int i = new_width; i > 1; i--) {
|
||||||
|
char c = new_binary.charAt(i - 1);
|
||||||
|
int algorism = c - '0' ;
|
||||||
|
result += Math. pow(2, new_width - i) * algorism;
|
||||||
|
}
|
||||||
|
result += -2147483648;
|
||||||
|
}
|
||||||
|
int a = new Long(result).intValue();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,325 @@
|
|||||||
|
package com.imdroid.sideslope.bd;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1.过滤
|
||||||
|
* 2.最多取最后300个点计算
|
||||||
|
* 3.取最后100点求重心,画0.25cm的球
|
||||||
|
* 4.求重心,包容百分之68,此重心为所求
|
||||||
|
* 5.否则,扩大半径0.01再求重心,包容百分之68,此重心为所求
|
||||||
|
* 6.。。。。。。
|
||||||
|
*/
|
||||||
|
public class FocusCalculator {
|
||||||
|
|
||||||
|
private List<double[]> list = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
private List<Tilt> tilts = Collections.synchronizedList(new ArrayList<>());
|
||||||
|
private Tilt tilt0;//初始状态
|
||||||
|
private double[] position0;
|
||||||
|
private double r = 10;//杆的长度cm 20230718 测试改为10
|
||||||
|
private boolean flag = false; // 是否是第一次计算
|
||||||
|
private List<Point> pointList = new ArrayList<>();
|
||||||
|
public static double[] lastFocus = null;//
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建计算器,如果tilt0和position0是null,那么计算过程将不考虑与tilts数据融合
|
||||||
|
* @param r 杆的长度,单位厘米
|
||||||
|
* @param tilt0 一个小时前的tilt平均值,用一小时的avgTilt计算得到,如果第一次,用null
|
||||||
|
* @param position0 一个小时前的xyz三维坐标值,用一小时前的ekf计算得到的那个,如果第一次,用null
|
||||||
|
*/
|
||||||
|
public FocusCalculator(double r, Tilt tilt0, double[] position0){
|
||||||
|
this.r = r;
|
||||||
|
this.tilt0 = tilt0;
|
||||||
|
this.position0 = position0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加入list
|
||||||
|
* @param xyz
|
||||||
|
*/
|
||||||
|
public void addXyz(double[] xyz){
|
||||||
|
if(filter(xyz)){
|
||||||
|
list.add(xyz);
|
||||||
|
}
|
||||||
|
if(list.size() > 300){
|
||||||
|
list.remove(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算得到最终结果
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public double[] resultB562(double[] r9250Result){
|
||||||
|
int count = 50;
|
||||||
|
double rate = 0.5;
|
||||||
|
try {
|
||||||
|
double r = 0.25;//初始球半径
|
||||||
|
if(list.size() >= count){
|
||||||
|
List<Point> results = new ArrayList<>();
|
||||||
|
if (r9250Result != null && r9250Result.length > 0){
|
||||||
|
// 计算所有点位与变量之间的距离,并存入集合
|
||||||
|
pointList.clear();
|
||||||
|
for (double[] point : list) {
|
||||||
|
Point point1 = new Point(point[0],point[1],point[2]);
|
||||||
|
double distance = disXY(point,r9250Result); // 计算距离
|
||||||
|
point1.setDistance(distance); // 设置该点到变量的距离
|
||||||
|
results.add(point1); // 将点位加入集合
|
||||||
|
}
|
||||||
|
Collections.sort(results, Comparator.comparing(Point::getDistance));//排序
|
||||||
|
|
||||||
|
results = results.subList(0, Math.min(50, results.size()));
|
||||||
|
|
||||||
|
}else {
|
||||||
|
for (int i = list.size()-count; i < list.size(); i++) {
|
||||||
|
results.add(new Point(list.get(i)[0],list.get(i)[1],list.get(i)[2]));
|
||||||
|
}
|
||||||
|
flag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//重心
|
||||||
|
double[] focus = focusPoint(results);
|
||||||
|
if(globeProportion(focus,r) < rate){
|
||||||
|
do{
|
||||||
|
r += 0.01;
|
||||||
|
//球附近点集个数有可能为0,继续计算会导致focus结果出现NaN
|
||||||
|
List<double[]> doubles1 = globeFilter(focus, r);
|
||||||
|
if(doubles1.size() == 0){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
focus = focus(doubles1);
|
||||||
|
}while (globeProportion(focus,r) < rate);
|
||||||
|
// if (flag){
|
||||||
|
// lastFocus = new double[3];
|
||||||
|
// lastFocus = focus;
|
||||||
|
// }
|
||||||
|
return focus;
|
||||||
|
}else{
|
||||||
|
// if (flag){
|
||||||
|
// lastFocus = new double[3];
|
||||||
|
// lastFocus = focus;
|
||||||
|
// }
|
||||||
|
return focus;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}catch (Exception e){
|
||||||
|
//如果计算过程中修改list,可能引发异常
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return resultB562Sub();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* resultB562替补方法,尽量不返回空
|
||||||
|
* @return x,y,z,有效点数
|
||||||
|
*/
|
||||||
|
private double[] resultB562Sub(){
|
||||||
|
if(list.size() > 0){
|
||||||
|
//重心
|
||||||
|
double[] focus = focus(list);
|
||||||
|
return focus;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过滤,剔除0,无穷大,与nan
|
||||||
|
* @param xyz
|
||||||
|
* @return true表示数据正常
|
||||||
|
*/
|
||||||
|
private boolean filter(double[] xyz){
|
||||||
|
double a = xyz[0]*xyz[1]*xyz[2];
|
||||||
|
if(a == 0 || Double.isInfinite(a) || Double.isNaN(a)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 三维点集重心计算
|
||||||
|
* @param list
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private double[] focus(List<double[]> list){
|
||||||
|
double sumX = 0;
|
||||||
|
double sumY = 0;
|
||||||
|
double sumZ = 0;
|
||||||
|
int count = list.size();
|
||||||
|
for (double[] doubles : list) {
|
||||||
|
sumX += doubles[0];
|
||||||
|
sumY += doubles[1];
|
||||||
|
sumZ += doubles[2];
|
||||||
|
}
|
||||||
|
return new double[]{sumX/count,sumY/count,sumZ/count};
|
||||||
|
}
|
||||||
|
|
||||||
|
private double[] focusPoint(List<Point> list){
|
||||||
|
double sumX = 0;
|
||||||
|
double sumY = 0;
|
||||||
|
double sumZ = 0;
|
||||||
|
int count = list.size();
|
||||||
|
for (Point point : list) {
|
||||||
|
sumX += point.getX();
|
||||||
|
sumY += point.getY();
|
||||||
|
sumZ += point.getZ();
|
||||||
|
}
|
||||||
|
return new double[]{sumX/count,sumY/count,sumZ/count};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算两个三维坐标的距离
|
||||||
|
* @param a
|
||||||
|
* @param b
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static double dis(double[] a, double[] b){
|
||||||
|
return Math.sqrt(Math.pow(a[0]-b[0],2) + Math.pow(a[1]-b[1],2) + Math.pow(a[2]-b[2],2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double disXY(double[] a, double[] b){
|
||||||
|
return Math.sqrt(Math.pow(a[0]-b[0],2) + Math.pow(a[1]-b[1],2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重心附近点集占总数的比例
|
||||||
|
* @param focus
|
||||||
|
* @param r
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private double globeProportion(double[] focus, double r){
|
||||||
|
int in = 0;//在球内的个数
|
||||||
|
for (double[] doubles : list) {
|
||||||
|
double dis = dis(doubles, focus);
|
||||||
|
if(dis < r){
|
||||||
|
in += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
double proportion = 1.00*in/list.size();
|
||||||
|
return proportion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取重心附近r内的所有点
|
||||||
|
* @param focus
|
||||||
|
* @param r
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private List<double[]> globeFilter(double[] focus, double r){
|
||||||
|
ArrayList<double[]> arrayList = new ArrayList<>();
|
||||||
|
for (double[] doubles1 : list) {
|
||||||
|
if(dis(doubles1,focus) < r){
|
||||||
|
arrayList.add(doubles1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arrayList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tilt计算得到的坐标与b562数据得到的坐标融合
|
||||||
|
* 1.可用点数大于50,优先相信b562
|
||||||
|
* 2.可用点数大于0小于50,取b562与9250平均值
|
||||||
|
* 3.可用点数无,用9250
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public double[] ekfResult(double[] b562Xyz, double[] tiltXyz){
|
||||||
|
if(tiltXyz == null){
|
||||||
|
return b562Xyz;
|
||||||
|
}
|
||||||
|
if(b562Xyz == null){
|
||||||
|
return tiltXyz;
|
||||||
|
}
|
||||||
|
double b562Variance;
|
||||||
|
double tiltVariance = 5; //Sherlock 230802 2-》5, 减小惯导的长周期影响
|
||||||
|
if(list.size() >= 50){
|
||||||
|
b562Variance = 1;
|
||||||
|
}else if(list.size() >= 40){
|
||||||
|
b562Variance = 3;
|
||||||
|
}else if(list.size() >= 30){
|
||||||
|
b562Variance = 9;
|
||||||
|
}else if(list.size() >= 20){
|
||||||
|
b562Variance = 30;
|
||||||
|
}else if(list.size() >= 10){
|
||||||
|
b562Variance = 60;
|
||||||
|
}else{
|
||||||
|
b562Variance = 90;
|
||||||
|
}
|
||||||
|
double k = Math.pow(b562Variance,2)/(Math.pow(tiltVariance,2) + Math.pow(b562Variance,2));
|
||||||
|
double x = b562Xyz[0] + k*(tiltXyz[0]-b562Xyz[0]);
|
||||||
|
double y = b562Xyz[1] + k*(tiltXyz[1]-b562Xyz[1]);
|
||||||
|
//z轴更加相信9250; 2023070改为5:1,20230706改为3:1, 20230718 改为 4:1,20230720 改为 5:1
|
||||||
|
b562Variance = 5;
|
||||||
|
tiltVariance = 1;
|
||||||
|
k = Math.pow(b562Variance,2)/(Math.pow(tiltVariance,2) + Math.pow(b562Variance,2));
|
||||||
|
double z = b562Xyz[2] + k*(tiltXyz[2]-b562Xyz[2]);
|
||||||
|
return new double[]{x,y,z};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加入tilts
|
||||||
|
* @param tilt
|
||||||
|
*/
|
||||||
|
public void addTilt(Tilt tilt){
|
||||||
|
tilts.add(tilt);
|
||||||
|
if(tilts.size() > 300){
|
||||||
|
tilts.remove(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取平均
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Tilt avgTilt(){
|
||||||
|
if(tilts.size() == 0){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Iterator<Tilt> iterator = tilts.iterator();
|
||||||
|
int size = tilts.size();
|
||||||
|
double sumP = 0;
|
||||||
|
double sumR = 0;
|
||||||
|
double sumY = 0;
|
||||||
|
while (iterator.hasNext()){
|
||||||
|
Tilt tilt = iterator.next();
|
||||||
|
sumP += Math.sin(tilt.getPitch()*Math.PI/180);
|
||||||
|
sumR += Math.sin(tilt.getRoll()*Math.PI/180);
|
||||||
|
sumY += Math.sin(tilt.getYaw()*Math.PI/180);
|
||||||
|
}
|
||||||
|
double pitch = (Math.asin(sumP/size) * 180/Math.PI + 360)%360;
|
||||||
|
double roll = (Math.asin(sumR/size) * 180/Math.PI + 360)%360;
|
||||||
|
double yaw = (Math.asin(sumY/size) * 180/Math.PI + 360)%360;
|
||||||
|
|
||||||
|
return new Tilt(pitch,roll,yaw);
|
||||||
|
}catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[] result9250(){
|
||||||
|
Tilt avg = avgTilt();
|
||||||
|
if(tilt0 == null || position0 == null || r == 0 || avg == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
double[] _9250_result = TiltUtil.toPosition(avg,tilt0,position0,r);
|
||||||
|
return _9250_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tilt getTilt0(){
|
||||||
|
return tilt0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[] getPosition0(){
|
||||||
|
return position0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getR(){
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
package com.imdroid.sideslope.bd;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class Gga {
|
||||||
|
/**
|
||||||
|
* 纬度
|
||||||
|
*/
|
||||||
|
private double latitude;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 经度
|
||||||
|
*/
|
||||||
|
private double longitude;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 海拔
|
||||||
|
*/
|
||||||
|
private double altitude;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GPS状态,0初始化,1单点定位,2码差分,3无效PPS,4固定解,5浮点解,6正在估算7,人工输入固定值,8模拟模式,9WAAS差分
|
||||||
|
*/
|
||||||
|
private int status;
|
||||||
|
|
||||||
|
public Gga() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Gga(double latitude, double longitude) {
|
||||||
|
this.latitude = latitude;
|
||||||
|
this.longitude = longitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Gga(double latitude, double longitude, double altitude, int status) {
|
||||||
|
this.latitude = latitude;
|
||||||
|
this.longitude = longitude;
|
||||||
|
this.altitude = altitude;
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Gga{" +
|
||||||
|
"latitude=" + latitude +
|
||||||
|
", longitude=" + longitude +
|
||||||
|
", altitude=" + altitude +
|
||||||
|
", status=" + status +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package com.imdroid.sideslope.bd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/19 21:14
|
||||||
|
*/
|
||||||
|
public class NumberUtils {
|
||||||
|
|
||||||
|
public static String doubleArrayToString(double[] result) {
|
||||||
|
if (result == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for (int i = 0; i < result.length; i++) {
|
||||||
|
builder.append(result[i]);
|
||||||
|
if (i < result.length - 1) {
|
||||||
|
builder.append(",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
package com.imdroid.sideslope.bd;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class Point {
|
||||||
|
private double x;
|
||||||
|
private double y;
|
||||||
|
private double z;
|
||||||
|
private double distance;
|
||||||
|
|
||||||
|
public Point(double x, double y, double z) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
package com.imdroid.sideslope.bd;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述杆的倾斜
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class Tilt {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前后仰角 上仰为正0-360
|
||||||
|
*/
|
||||||
|
private double pitch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 左右倾斜角 右下为正0-360
|
||||||
|
*/
|
||||||
|
private double roll;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 航向角 北偏东为正0-360
|
||||||
|
*/
|
||||||
|
private double yaw;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 偏移量
|
||||||
|
*/
|
||||||
|
private double shock;
|
||||||
|
|
||||||
|
public Tilt(double pitch, double roll, double yaw,double shock) {
|
||||||
|
this.pitch = pitch;
|
||||||
|
this.roll = roll;
|
||||||
|
this.yaw = yaw;
|
||||||
|
this.shock = shock;
|
||||||
|
}
|
||||||
|
public Tilt(double pitch, double roll, double yaw) {
|
||||||
|
this.pitch = pitch;
|
||||||
|
this.roll = roll;
|
||||||
|
this.yaw = yaw;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Tilt{" +
|
||||||
|
"pitch=" + pitch +
|
||||||
|
", roll=" + roll +
|
||||||
|
", yaw=" + yaw +", shock:"+shock+
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
package com.imdroid.sideslope.bd;
|
||||||
|
|
||||||
|
public class TiltUtil {
|
||||||
|
public static double[] toPosition(Tilt tilt, Tilt tilt0, double[] position0, double r){
|
||||||
|
if(tilt0 == null || position0 == null || r == 0 || tilt == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
//杆底相对与杆顶的位置
|
||||||
|
double[] rodDownPosition = rodDownPosition(tilt0, r);
|
||||||
|
//杆底相对于基站的位置
|
||||||
|
double[] downPosition = new double[]{position0[0] + rodDownPosition[0], position0[1] + rodDownPosition[1], position0[2] + rodDownPosition[2]};
|
||||||
|
//杆顶相对于杆底的位置
|
||||||
|
double[] rodTopPosition = TiltUtil.rodTopPosition(tilt, r);
|
||||||
|
//杆顶相对于基站的位置
|
||||||
|
double[] topPosition = new double[]{downPosition[0] + rodTopPosition[0], downPosition[1] + rodTopPosition[1], downPosition[2] + rodTopPosition[2]};
|
||||||
|
return topPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算得到杆顶点相对于杆底点的相对位置
|
||||||
|
* @param tilt
|
||||||
|
* @param r 杆的长度
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static double[] rodTopPosition(Tilt tilt, double r){
|
||||||
|
//假设yaw=0
|
||||||
|
//杆在xoz平面投影
|
||||||
|
double xoz = r * Math.cos(toRadians(tilt.getPitch()));
|
||||||
|
double x = xoz * Math.cos(toRadians(90-tilt.getRoll()));
|
||||||
|
double z = xoz * Math.cos(toRadians(tilt.getRoll()));
|
||||||
|
//杆在yoz平面投影
|
||||||
|
double yoz = r * Math.cos(toRadians(tilt.getRoll()));
|
||||||
|
double y = -yoz * Math.cos(toRadians(90-tilt.getPitch()));
|
||||||
|
|
||||||
|
//考虑到yaw,相当于逆时针旋转xoy坐标系
|
||||||
|
double yaw = (tilt.getYaw() + 360)%360;
|
||||||
|
double x1 = x*Math.cos(toRadians(yaw)) - y*Math.sin(toRadians(yaw));
|
||||||
|
double y1 = y*Math.cos(toRadians(yaw)) + x*Math.sin(toRadians(yaw));
|
||||||
|
|
||||||
|
return new double[]{x1,y1,z};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算得到杆底相对于杆顶点的相对位置
|
||||||
|
* @param tilt
|
||||||
|
* @param r 杆的长度
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static double[] rodDownPosition(Tilt tilt, double r){
|
||||||
|
double[] doubles = rodTopPosition(tilt, r);
|
||||||
|
return new double[]{-doubles[0],-doubles[1],-doubles[2]};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 角度转弧度
|
||||||
|
* @param angle
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static double toRadians(double angle) {
|
||||||
|
return angle / 180.0 * Math.PI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
package com.imdroid.sideslope.bd;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* b562 01 3c 4000 01 00 0000 40235d21 8dffffff 08ffffff 00000000 11010000 8af4750100000000ddeab84864000000640000006400000064000000c55100000000000037010000 996e
|
||||||
|
* b562固定开头,01是class,3c是id,40 00是有效数据长度,低字节序号,所以有效数据长度为0x40,接下来是有效数据,最后996e是校验位
|
||||||
|
*/
|
||||||
|
public class UBXUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析UBX数据
|
||||||
|
* @param data UBX数据(b562开头)
|
||||||
|
* @return x,y,z 东,北,竖直 东为正数,北为正数,朝上为正数
|
||||||
|
*/
|
||||||
|
public static double[] getLocation(ByteBuf data){
|
||||||
|
boolean has_b562 = false;
|
||||||
|
byte[] b562_flag = {(byte) 0xb5, (byte)0x62};
|
||||||
|
int pos = 26; // 从惯导之后开始
|
||||||
|
|
||||||
|
for(; pos<data.readableBytes() - 1; pos++){
|
||||||
|
byte d0 = data.getByte(pos);
|
||||||
|
byte d1 = data.getByte(pos+1);
|
||||||
|
if(d0 == b562_flag[0] && d1 == b562_flag[1]){
|
||||||
|
has_b562 = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!has_b562) return null;
|
||||||
|
pos+=6;
|
||||||
|
|
||||||
|
double relPosN = data.getIntLE(pos+8) + data.getByte(pos+32)*0.01;
|
||||||
|
double relPosE = data.getIntLE(pos+12) + data.getByte(pos+33)*0.01;
|
||||||
|
double relPosD = data.getIntLE(pos+16) + data.getByte(pos+34)*0.01;
|
||||||
|
relPosD = -relPosD;
|
||||||
|
short status = (short) ((data.getUnsignedByte(pos+60) & 0x18)>>3); //mask: 00011000
|
||||||
|
if(status == 2){
|
||||||
|
return new double[]{relPosE,relPosN,relPosD};
|
||||||
|
}else{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
package com.imdroid.sideslope.calc;
|
||||||
|
|
||||||
|
import com.imdroid.sideslope.bd.Tilt;
|
||||||
|
import com.imdroid.sideslope.message.D341LocationMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/4 19:18
|
||||||
|
*/
|
||||||
|
public interface GNSSCalcService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算单条GNSS数据
|
||||||
|
*
|
||||||
|
* @param message GNSS数据
|
||||||
|
* @return x,y,z三轴数据
|
||||||
|
*/
|
||||||
|
double[] calcSingle(D341LocationMessage message);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据GNSS数据的中间结果,计算出最终结果
|
||||||
|
*
|
||||||
|
* @param deviceId 设备id
|
||||||
|
* @return x,y,z三轴数据
|
||||||
|
*/
|
||||||
|
double[] calcResult(String deviceId,double[] b562Xyz, double[] tiltXyz);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据GNSS数据的中间结果,计算Tilt的平均值
|
||||||
|
* @param deviceId 设备id
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Tilt calcAvgTilt(String deviceId);
|
||||||
|
|
||||||
|
void cleanTiltByDeviceId(String deviceId);
|
||||||
|
}
|
||||||
@ -0,0 +1,195 @@
|
|||||||
|
package com.imdroid.sideslope.calc;
|
||||||
|
|
||||||
|
import com.imdroid.sideslope.bd.*;
|
||||||
|
import com.imdroid.sideslope.message.D341LocationMessage;
|
||||||
|
import com.imdroid.sideslope.sal.*;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/4 19:22
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class SingleLineGNSSCalcService implements GNSSCalcService {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(SingleLineGNSSCalcService.class);
|
||||||
|
|
||||||
|
private static final Map<String, FocusCalculator> calculatorMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private static final Map<String, ScheduledFuture<?>> timerMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private static final Map<String, Tilt> tiltMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private static final Map<String, double[]> positionMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private static final Map<String, Boolean> cleanTiltStatusMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private static final Map<String, Boolean> cleanPositionStatusMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private static final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(4);
|
||||||
|
//计时器
|
||||||
|
private static final ScheduledExecutorService executorService2 = Executors.newScheduledThreadPool(4);
|
||||||
|
private static Map<String, ScheduledFuture<?>> timerMap2 = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@Resource(name = "local")
|
||||||
|
private DeviceService deviceService;
|
||||||
|
|
||||||
|
private static Map<String, Boolean> isExceedMap = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double[] calcSingle(D341LocationMessage message) {
|
||||||
|
String deviceId = message.getId();
|
||||||
|
Device device = deviceService.findByDeviceId(deviceId);
|
||||||
|
if (device != null && device.getDeviceType() == Device.DEVICE_ROVER) {
|
||||||
|
resultOutputTimer(deviceId);
|
||||||
|
}
|
||||||
|
//todo 创建FocusCalculator对象需获取该测站的杆长度,上一小时的Tilt平均值,上一小时的测站相对坐标融合值ekfResult
|
||||||
|
FocusCalculator focusCalculator = calculatorMap.computeIfAbsent(deviceId, s -> new FocusCalculator(150,tiltMap.get(deviceId),
|
||||||
|
positionMap.get(deviceId)));
|
||||||
|
// 读取惯导
|
||||||
|
Tilt tilt = message.getTilt();
|
||||||
|
//判断阈值
|
||||||
|
if (tilt.getShock() > 1.5) {
|
||||||
|
if (timerMap2.containsKey(deviceId)){
|
||||||
|
timerMap2.get(deviceId).cancel(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ScheduledFuture<?> future = executorService2.schedule(() -> {
|
||||||
|
isExceedMap.put(deviceId, false);
|
||||||
|
}, 6, TimeUnit.HOURS);
|
||||||
|
|
||||||
|
timerMap2.put(deviceId, future);
|
||||||
|
isExceedMap.put(deviceId, true);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
if (isExceedMap.get(deviceId)) {
|
||||||
|
isExceedMap.put(deviceId, true);
|
||||||
|
} else {
|
||||||
|
isExceedMap.put(deviceId, false);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
isExceedMap.put(deviceId, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
focusCalculator.addTilt(tilt);
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("测站" + deviceId + "的9250单次解析结果:{}", tilt.toString() + "," + Arrays.toString(TiltUtil.toPosition(tilt, focusCalculator.getTilt0(), focusCalculator.getPosition0(), focusCalculator.getR())));
|
||||||
|
}
|
||||||
|
|
||||||
|
//计算到单次相对位置xyz并记录
|
||||||
|
//tilt共16个字节,从后边开始找b562
|
||||||
|
double[] doubles = message.getB562_loc();
|
||||||
|
if(doubles != null){
|
||||||
|
focusCalculator.addXyz(doubles);
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("测站" + deviceId + "的b562单次解析结果:{}", Arrays.toString(doubles));
|
||||||
|
}
|
||||||
|
return doubles;
|
||||||
|
}else{
|
||||||
|
return new double[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resultOutputTimer(String deviceId){
|
||||||
|
//20秒没数据后输出结果
|
||||||
|
ScheduledFuture<?> future = timerMap.get(deviceId);
|
||||||
|
if (future != null && !future.isDone()) {
|
||||||
|
future.cancel(true);
|
||||||
|
future = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
future = executorService.schedule(() -> {
|
||||||
|
try {
|
||||||
|
FocusCalculator focusCalculator = calculatorMap.get(deviceId);
|
||||||
|
double[] lastEfk = null;
|
||||||
|
if(positionMap.containsKey(deviceId)){
|
||||||
|
lastEfk = positionMap.get(deviceId);
|
||||||
|
}
|
||||||
|
double[] b562Result = focusCalculator.resultB562(lastEfk);
|
||||||
|
double[] r9250Result = null;
|
||||||
|
//判断 取到的b562 和上次融合坐标做判断,如果距离>100mm 不计算9250
|
||||||
|
if (lastEfk != null && FocusCalculator.disXY(b562Result,lastEfk)<100){
|
||||||
|
r9250Result = focusCalculator.result9250();
|
||||||
|
}
|
||||||
|
double[] result = focusCalculator.ekfResult(b562Result,r9250Result);
|
||||||
|
Tilt tilt = calcAvgTilt(deviceId);
|
||||||
|
calculatorMap.remove(deviceId);
|
||||||
|
logger.info("测站 {} 的b562相对坐标重心:{}", deviceId, Arrays.toString(b562Result));
|
||||||
|
logger.info("测站 {} 的9250相对坐标:{}", deviceId, Arrays.toString(r9250Result));
|
||||||
|
logger.info("测站 {} 的相对坐标融合值:{}", deviceId, Arrays.toString(result));
|
||||||
|
logger.info("测站 {} 的Tilt平均值:{}", deviceId, tilt);
|
||||||
|
|
||||||
|
if (tilt != null) {
|
||||||
|
if (Boolean.TRUE.equals(cleanTiltStatusMap.get(deviceId))) {
|
||||||
|
// 置为false,下一次计算时就可以正常设置惯导值到tiltMap了
|
||||||
|
cleanTiltStatusMap.put(deviceId, Boolean.FALSE);
|
||||||
|
logger.info("置为false,下一次计算时就可以正常设置惯导值到tiltMap了");
|
||||||
|
} else {
|
||||||
|
tiltMap.put(deviceId, tilt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result != null && b562Result != null) {
|
||||||
|
//这里检查一下result,过滤1千米外非正常数据
|
||||||
|
if(focusCalculator.dis(result,b562Result) < 1000_00) {
|
||||||
|
if (Boolean.TRUE.equals(cleanPositionStatusMap.get(deviceId))) {
|
||||||
|
// 置为false,下一次计算时就可以正常设置值到positionMap了
|
||||||
|
cleanPositionStatusMap.put(deviceId, Boolean.FALSE);
|
||||||
|
logger.info("置为false,下一次计算时就可以正常设置值到positionMap了");
|
||||||
|
} else {
|
||||||
|
positionMap.put(deviceId, result);
|
||||||
|
}
|
||||||
|
postLocationRecord(deviceId, b562Result, r9250Result, result);
|
||||||
|
}else{
|
||||||
|
logger.error("融合值异常");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error(e.toString());
|
||||||
|
}
|
||||||
|
},40, TimeUnit.SECONDS);
|
||||||
|
timerMap.put(deviceId, future);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void postLocationRecord(String deviceId, double[] b562Result, double[] r9250Result, double[] result) {
|
||||||
|
LocationRecordDTO locationRecord = new LocationRecordDTO(deviceId, NumberUtils.doubleArrayToString(b562Result),
|
||||||
|
NumberUtils.doubleArrayToString(r9250Result), NumberUtils.doubleArrayToString(result),String.valueOf(isExceedMap.get(deviceId)));
|
||||||
|
deviceService.postLocationRecord(locationRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double[] calcResult(String deviceId,double[] b562Xyz, double[] tiltXyz) {
|
||||||
|
FocusCalculator focusCalculator = calculatorMap.get(deviceId);
|
||||||
|
if (focusCalculator != null) {
|
||||||
|
double[] result = focusCalculator.ekfResult(b562Xyz,tiltXyz);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Tilt calcAvgTilt(String deviceId) {
|
||||||
|
FocusCalculator focusCalculator = calculatorMap.get(deviceId);
|
||||||
|
if (focusCalculator != null) {
|
||||||
|
Tilt tilt = focusCalculator.avgTilt();
|
||||||
|
return tilt;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cleanTiltByDeviceId(String deviceId) {
|
||||||
|
logger.info("清空设备[{}]的tilt和position缓存", deviceId);
|
||||||
|
tiltMap.remove(deviceId);
|
||||||
|
positionMap.remove(deviceId);
|
||||||
|
cleanTiltStatusMap.put(deviceId, Boolean.TRUE);
|
||||||
|
cleanPositionStatusMap.put(deviceId, Boolean.TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package com.imdroid.sideslope.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备消息校验异常
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
* @date 2023/4/8 10:55
|
||||||
|
*/
|
||||||
|
public class MessageValidateFailException extends RuntimeException {
|
||||||
|
|
||||||
|
public MessageValidateFailException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
package com.imdroid.sideslope.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/2 20:43
|
||||||
|
*/
|
||||||
|
public class UnSupportedMessageException extends RuntimeException {
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package com.imdroid.sideslope.executor;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class BizExecutors {
|
||||||
|
|
||||||
|
private final HashMap<Class<?>, Object> executors = new HashMap<>();
|
||||||
|
|
||||||
|
private final List<Executor<?, ?>> executorList;
|
||||||
|
|
||||||
|
public BizExecutors(List<Executor<?, ?>> executorList) {
|
||||||
|
this.executorList = executorList;
|
||||||
|
for (Executor<?, ?> executor : this.executorList) {
|
||||||
|
System.out.println("executor type:" + executor.getMessageType().getName());
|
||||||
|
executors.put(executor.getMessageType(), executor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public <Q, R> R execute(Q query) {
|
||||||
|
Executor<Q, R> executor = (Executor<Q, R>)(executors.get(query.getClass()));
|
||||||
|
return executor.execute(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
package com.imdroid.sideslope.executor;
|
||||||
|
|
||||||
|
import com.imdroid.sideslope.message.D31xConfigAckMessage;
|
||||||
|
import com.imdroid.sideslope.message.D3F0SelfCheckMessage;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/2 20:40
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class D31xConfigAckMessageExecutor implements Executor<D31xConfigAckMessage, Void> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void execute(D31xConfigAckMessage message) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getMessageType() {
|
||||||
|
return D3F0SelfCheckMessage.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
package com.imdroid.sideslope.executor;
|
||||||
|
|
||||||
|
import com.imdroid.sideslope.message.D331RtcmMessage;
|
||||||
|
import com.imdroid.sideslope.sal.Device;
|
||||||
|
import com.imdroid.sideslope.sal.DeviceService;
|
||||||
|
import com.imdroid.sideslope.server.OnlineChannels;
|
||||||
|
import com.imdroid.sideslope.util.ThreadManager;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/2 20:49
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class D331RtcmMessageExecutor implements Executor<D331RtcmMessage, Void> {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
@Resource(name = "local")
|
||||||
|
private DeviceService deviceService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void execute(D331RtcmMessage message) {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("receive d331 rtcm message of device:{}", message.getId());
|
||||||
|
}
|
||||||
|
String id = message.getId();
|
||||||
|
byte[] forwardBytes = message.getSrcData();
|
||||||
|
List<Device> deviceList = deviceService.findByParentId(id);
|
||||||
|
for (Device device : deviceList) {
|
||||||
|
String deviceId = device.getDeviceId();
|
||||||
|
OnlineChannels.INSTANCE.get(deviceId).ifPresent(deviceChannel -> {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("forward d331 rtcm message to device {}", deviceId);
|
||||||
|
}
|
||||||
|
ByteBuf buf = Unpooled.buffer();
|
||||||
|
buf.writeBytes(forwardBytes);
|
||||||
|
deviceChannel.writeAndFlush(buf);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
final Date now = new Date();
|
||||||
|
ThreadManager.getFixedThreadPool().execute(() -> {
|
||||||
|
deviceService.updateLatestDataTime(id, now);
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getMessageType() {
|
||||||
|
return D331RtcmMessage.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
package com.imdroid.sideslope.executor;
|
||||||
|
|
||||||
|
import com.imdroid.sideslope.calc.GNSSCalcService;
|
||||||
|
import com.imdroid.sideslope.message.D341LocationMessage;
|
||||||
|
import com.imdroid.sideslope.service.GNSSDeviceLocationRecordService;
|
||||||
|
import com.imdroid.sideslope.util.ThreadManager;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/2 20:50
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class D341LocationMessageExecutor implements Executor<D341LocationMessage, Void> {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private GNSSCalcService gnssCalcService;
|
||||||
|
@Autowired
|
||||||
|
private GNSSDeviceLocationRecordService dataPersistService;
|
||||||
|
@Override
|
||||||
|
public Void execute(D341LocationMessage message) {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("receive d341 location message of device:{}", message.getId());
|
||||||
|
}
|
||||||
|
ThreadManager.getFixedThreadPool().submit(() -> {
|
||||||
|
gnssCalcService.calcSingle(message);
|
||||||
|
dataPersistService.saveSingleCalcData(message);
|
||||||
|
});
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getMessageType() {
|
||||||
|
return D341LocationMessage.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package com.imdroid.sideslope.executor;
|
||||||
|
|
||||||
|
import com.imdroid.sideslope.message.D3F0SelfCheckMessage;
|
||||||
|
import com.imdroid.sideslope.service.DataPersistService;
|
||||||
|
import com.imdroid.sideslope.util.ThreadManager;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/2 20:40
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class D3F0SelfCheckMessageExecutor implements Executor<D3F0SelfCheckMessage, Void> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DataPersistService dataPersistService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void execute(D3F0SelfCheckMessage message) {
|
||||||
|
// 存储最新设备状态信息到数据库中
|
||||||
|
ThreadManager.getFixedThreadPool().submit(() -> {
|
||||||
|
dataPersistService.saveDeviceState(message);
|
||||||
|
});
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getMessageType() {
|
||||||
|
return D3F0SelfCheckMessage.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,46 @@
|
|||||||
|
package com.imdroid.sideslope.executor;
|
||||||
|
|
||||||
|
import com.imdroid.sideslope.message.D3F2StopIndicationMessage;
|
||||||
|
import com.imdroid.sideslope.sal.DeviceService;
|
||||||
|
import com.imdroid.sideslope.service.DataPersistService;
|
||||||
|
import com.imdroid.sideslope.util.ThreadManager;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停止指示消息处理器
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class D3F2StopIndicationMessageExecutor implements Executor<D3F2StopIndicationMessage, Void> {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DataPersistService dataPersistService;
|
||||||
|
|
||||||
|
@Resource(name = "local")
|
||||||
|
private DeviceService deviceService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void execute(D3F2StopIndicationMessage message) {
|
||||||
|
// 储设备收发字节数统计信息
|
||||||
|
ThreadManager.getFixedThreadPool().submit(() -> {
|
||||||
|
dataPersistService.saveDeviceTrxStat(message);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新设备的最新数据时间
|
||||||
|
final Date now = new Date();
|
||||||
|
ThreadManager.getFixedThreadPool().submit(() -> {
|
||||||
|
deviceService.updateLatestDataTime(message.getId(), now);
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> getMessageType() {
|
||||||
|
return D3F2StopIndicationMessage.class;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
package com.imdroid.sideslope.executor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2022/4/8 22:32
|
||||||
|
*/
|
||||||
|
public interface Executor<Q, R> {
|
||||||
|
|
||||||
|
R execute(Q message);
|
||||||
|
|
||||||
|
Class<?> getMessageType();
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
package com.imdroid.sideslope.executor;
|
||||||
|
|
||||||
|
import com.imdroid.sideslope.exception.UnSupportedMessageException;
|
||||||
|
import com.imdroid.sideslope.message.*;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/2 20:41
|
||||||
|
*/
|
||||||
|
public class MessageParser {
|
||||||
|
|
||||||
|
private static final Map<Short, Class<? extends BaseMessage>> types = new HashMap<>();
|
||||||
|
|
||||||
|
public static final MessageParser instance = new MessageParser();
|
||||||
|
|
||||||
|
private MessageParser() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
types.put((short)0xd3f0, D3F0SelfCheckMessage.class);
|
||||||
|
types.put((short)0xd3f2, D3F2StopIndicationMessage.class);
|
||||||
|
//types.put((short)0xd330, D330RtcmMessage.class);
|
||||||
|
//types.put((short)0xd340, D340LocationMessage.class);
|
||||||
|
types.put((short)0xd331, D331RtcmMessage.class);
|
||||||
|
types.put((short)0xd341, D341LocationMessage.class);
|
||||||
|
types.put((short)0xd310, D31xConfigAckMessage.class);//GNSS配置应答
|
||||||
|
types.put((short)0xd311, D31xConfigAckMessage.class);//单片机配置应答
|
||||||
|
types.put((short)0xd31A, D31xConfigAckMessage.class);//DTU配置应答
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public BaseMessage parse(ByteBuf src) throws Exception {
|
||||||
|
short flag = src.getShort(0);
|
||||||
|
Class<? extends BaseMessage> clz = types.get(flag);
|
||||||
|
if (clz == null) {
|
||||||
|
throw new UnSupportedMessageException();
|
||||||
|
}
|
||||||
|
BaseMessage message = clz.newInstance();
|
||||||
|
message.decode(src);
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,81 @@
|
|||||||
|
package com.imdroid.sideslope.message;
|
||||||
|
|
||||||
|
import com.imdroid.sideslope.util.WrongMessageRecorder;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/2 20:32
|
||||||
|
*/
|
||||||
|
public abstract class BaseMessage {
|
||||||
|
protected byte[] header;
|
||||||
|
protected String id;
|
||||||
|
protected int len;
|
||||||
|
protected int pps;
|
||||||
|
|
||||||
|
protected byte[] srcData;//message在线程中处理,需要把channel传递过来的数据拷贝出来
|
||||||
|
|
||||||
|
public void decode(ByteBuf src) {
|
||||||
|
if (shouldDecodeHeader()) {
|
||||||
|
// read操作会移动ByteBuf内部指针,除D331外,其他都用read来读
|
||||||
|
int packetLen = src.readableBytes();
|
||||||
|
this.header = new byte[2];
|
||||||
|
src.readBytes(header);
|
||||||
|
|
||||||
|
this.len = src.readUnsignedShort();
|
||||||
|
this.id = String.valueOf(src.readUnsignedInt());
|
||||||
|
if (packetLen - 4 != this.len) {
|
||||||
|
String msg = (String.format("id[%s],长度字段值[%s]与包的消息体长度[%s]不匹配", id, this.len, packetLen - 4));
|
||||||
|
WrongMessageRecorder.INSTANCE.append("receive wrong message," + msg);
|
||||||
|
}
|
||||||
|
this.pps = src.readUnsignedShort();
|
||||||
|
}
|
||||||
|
decodeBody(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void decodeBody(ByteBuf src);
|
||||||
|
|
||||||
|
public boolean shouldDecodeHeader() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getHeader() {
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeader(byte[] header) {
|
||||||
|
this.header = header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLen() {
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLen(int len) {
|
||||||
|
this.len = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPps() {
|
||||||
|
return pps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPps(int pps) {
|
||||||
|
this.pps = pps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getSrcData() {
|
||||||
|
return srcData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSrcData(byte[] srcData) {
|
||||||
|
this.srcData = srcData;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package com.imdroid.sideslope.message;
|
||||||
|
|
||||||
|
import com.imdroid.sideslope.util.WrongMessageRecorder;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/2 20:47
|
||||||
|
*/
|
||||||
|
public class D31xConfigAckMessage extends BaseMessage {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void decodeBody(ByteBuf src) {
|
||||||
|
// get操作不会移动指针,这样可以确保整个全转发出去
|
||||||
|
this.header = new byte[2];
|
||||||
|
src.getBytes(0, header); // flag
|
||||||
|
this.len = src.getUnsignedShort(2); // length
|
||||||
|
this.id = String.valueOf(src.getUnsignedInt(4)); //id
|
||||||
|
if (src.readableBytes() - 4 != this.len) {
|
||||||
|
String msg = String.format("id[%s],长度字段值[%s]与包的消息体长度[%s]不匹配", id, this.len, src.readableBytes() - 4);
|
||||||
|
WrongMessageRecorder.INSTANCE.append("receive wrong message," + msg);
|
||||||
|
}
|
||||||
|
this.srcData = new byte[src.readableBytes()];
|
||||||
|
src.readBytes(this.srcData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldDecodeHeader() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package com.imdroid.sideslope.message;
|
||||||
|
|
||||||
|
import com.imdroid.sideslope.util.WrongMessageRecorder;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/2 20:47
|
||||||
|
*/
|
||||||
|
public class D331RtcmMessage extends BaseMessage {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void decodeBody(ByteBuf src) {
|
||||||
|
// get操作不会移动指针,这样可以确保整个全转发出去
|
||||||
|
this.header = new byte[2];
|
||||||
|
src.getBytes(0, header); // flag
|
||||||
|
this.len = src.getUnsignedShort(2); // length
|
||||||
|
this.id = String.valueOf(src.getUnsignedInt(4)); //id
|
||||||
|
if (src.readableBytes() - 4 != this.len) {
|
||||||
|
String msg = String.format("id[%s],长度字段值[%s]与包的消息体长度[%s]不匹配", id, this.len, src.readableBytes() - 4);
|
||||||
|
WrongMessageRecorder.INSTANCE.append("receive wrong message," + msg);
|
||||||
|
}
|
||||||
|
this.srcData = new byte[src.readableBytes()];
|
||||||
|
src.readBytes(this.srcData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldDecodeHeader() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
package com.imdroid.sideslope.message;
|
||||||
|
|
||||||
|
import com.imdroid.sideslope.bd.Tilt;
|
||||||
|
import com.imdroid.sideslope.bd.UBXUtil;
|
||||||
|
import com.imdroid.sideslope.util.WrongMessageRecorder;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/2 20:50
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class D341LocationMessage extends BaseMessage {
|
||||||
|
Tilt tilt;
|
||||||
|
double[] b562_loc;
|
||||||
|
@Override
|
||||||
|
public void decodeBody(ByteBuf src) {
|
||||||
|
// 读到pitch了,readable不不含pitch之前
|
||||||
|
tilt = new Tilt(src.readFloat(), src.readFloat(),src.readFloat(),src.readFloat());
|
||||||
|
// b562
|
||||||
|
b562_loc = UBXUtil.getLocation(src);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
package com.imdroid.sideslope.message;
|
||||||
|
|
||||||
|
import com.imdroid.secapi.dto.GnssStatusMsg;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自检消息
|
||||||
|
*
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/2 20:38
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class D3F0SelfCheckMessage extends BaseMessage {
|
||||||
|
|
||||||
|
GnssStatusMsg statusMsg = new GnssStatusMsg();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void decodeBody(ByteBuf src) {
|
||||||
|
statusMsg.setDeviceid(getId());
|
||||||
|
statusMsg.setUpdatetime(new Timestamp(System.currentTimeMillis()));
|
||||||
|
statusMsg.setDevicetime(new Timestamp(getPps()*1000));
|
||||||
|
statusMsg.setPitch(src.readFloat());
|
||||||
|
statusMsg.setRoll(src.readFloat());
|
||||||
|
statusMsg.setYaw(src.readFloat());
|
||||||
|
// skip shock
|
||||||
|
src.readFloat();
|
||||||
|
statusMsg.setDtustate(src.readUnsignedByte());
|
||||||
|
statusMsg.setRssi(src.readUnsignedByte());
|
||||||
|
statusMsg.setVoltage(src.readUnsignedShort());
|
||||||
|
// skip version
|
||||||
|
src.readUnsignedShort();
|
||||||
|
statusMsg.setTemperature(src.readUnsignedShort()/10);
|
||||||
|
statusMsg.setHumidity(src.readUnsignedShort()/10);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
package com.imdroid.sideslope.message;
|
||||||
|
|
||||||
|
import com.imdroid.secapi.dto.GnssTrxMsg;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停止指示消息
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class D3F2StopIndicationMessage extends BaseMessage {
|
||||||
|
|
||||||
|
private GnssTrxMsg trxMsg = new GnssTrxMsg();;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void decodeBody(ByteBuf src) {
|
||||||
|
trxMsg.setDeviceid(getId());
|
||||||
|
trxMsg.setUpdatetime(new Timestamp(System.currentTimeMillis()));
|
||||||
|
trxMsg.setDevicetime(new Timestamp(getPps()*1000));
|
||||||
|
int keys = (this.len - 6) / 5;
|
||||||
|
for (int i = 0; i < keys; i++) {
|
||||||
|
int key = src.readUnsignedByte();
|
||||||
|
long value = src.readUnsignedInt();
|
||||||
|
if (key == 0) {
|
||||||
|
trxMsg.setUart1txbytes(value);
|
||||||
|
} else if (key == 1) {
|
||||||
|
trxMsg.setUart1rxbytes(value);
|
||||||
|
} else if (key == 2) {
|
||||||
|
trxMsg.setUart1unknown(value);
|
||||||
|
} else if (key == 3) {
|
||||||
|
trxMsg.setUart2txbytes(value);
|
||||||
|
} else if (key == 4) {
|
||||||
|
trxMsg.setUart2rxbytes(value);
|
||||||
|
} else if (key == 5) {
|
||||||
|
trxMsg.setUart2unknown(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
package com.imdroid.sideslope.rabbitmq;
|
||||||
|
|
||||||
|
import org.springframework.amqp.core.*;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rabbitmq 配置类
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class RabbitmqConfig {
|
||||||
|
|
||||||
|
public static final String QUEUE_GNSS_LOCATION_RECORD = "gnss_location_record";
|
||||||
|
public static final String EXCHANGE_GNSS = "exchange_gnss";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 声明交换机
|
||||||
|
*/
|
||||||
|
@Bean(EXCHANGE_GNSS)
|
||||||
|
public Exchange EXCHANGE_GNSS() {
|
||||||
|
return ExchangeBuilder.topicExchange(EXCHANGE_GNSS).durable(true).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 声明QUEUE_INFORM_EMAIL队列
|
||||||
|
* @return Queue
|
||||||
|
*/
|
||||||
|
@Bean(QUEUE_GNSS_LOCATION_RECORD)
|
||||||
|
public Queue QUEUE_INFORM_EMAIL() {
|
||||||
|
return new Queue(QUEUE_GNSS_LOCATION_RECORD);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
package com.imdroid.sideslope.sal;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.imdroid.secapi.dto.GnssDevice;
|
||||||
|
import com.imdroid.secapi.dto.GnssDeviceMapper;
|
||||||
|
import com.imdroid.sideslope.service.GNSSDeviceLocationRecordService;
|
||||||
|
import com.imdroid.sideslope.util.ThreadManager;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
@Component(value = "db")
|
||||||
|
public class DbDeviceServiceImpl implements DeviceService {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(DbDeviceServiceImpl.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private GnssDeviceMapper gnssDeviceRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private GNSSDeviceLocationRecordService gnssDeviceLocationRecordService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Device findByDeviceId(String deviceId) {
|
||||||
|
GnssDevice gnssDevice = gnssDeviceRepository.queryByDeviceId(deviceId);
|
||||||
|
if (gnssDevice == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Device device = new Device();
|
||||||
|
device.setDeviceId(gnssDevice.getDeviceid());
|
||||||
|
device.setDeviceType(gnssDevice.getDevicetype());
|
||||||
|
device.setParentId(gnssDevice.getParentid());
|
||||||
|
device.setName(gnssDevice.getName());
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Device> findByParentId(String parentId) {
|
||||||
|
QueryWrapper<GnssDevice> query = new QueryWrapper();
|
||||||
|
query.eq("parentid", parentId);
|
||||||
|
List<GnssDevice> gnssDeviceList = gnssDeviceRepository.selectList(query);
|
||||||
|
List<Device> deviceList = new ArrayList<>(gnssDeviceList.size());
|
||||||
|
for (GnssDevice gnssDevice : gnssDeviceList) {
|
||||||
|
Device device = new Device();
|
||||||
|
device.setDeviceId(gnssDevice.getDeviceid());
|
||||||
|
device.setDeviceType(gnssDevice.getDevicetype());
|
||||||
|
device.setParentId(gnssDevice.getParentid());
|
||||||
|
device.setName(gnssDevice.getName());
|
||||||
|
deviceList.add(device);
|
||||||
|
}
|
||||||
|
return deviceList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean postLocationRecord(LocationRecordDTO locationRecord) {
|
||||||
|
ThreadManager.getFixedThreadPool().submit(() -> {
|
||||||
|
try {
|
||||||
|
gnssDeviceLocationRecordService.save(locationRecord);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error(e.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateLatestDataTime(String deviceId, Date latestDataTime) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
package com.imdroid.sideslope.sal;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基站 & 测站设备
|
||||||
|
*
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/3 20:39
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class Device {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基站
|
||||||
|
*/
|
||||||
|
public static final int DEVICE_BASE_STATION = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测站
|
||||||
|
*/
|
||||||
|
public static final int DEVICE_ROVER = 0;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String deviceId;
|
||||||
|
|
||||||
|
private String parentId;
|
||||||
|
|
||||||
|
private Integer deviceType;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package com.imdroid.sideslope.sal;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/3 20:37
|
||||||
|
*/
|
||||||
|
public interface DeviceService {
|
||||||
|
|
||||||
|
Device findByDeviceId(String deviceId);
|
||||||
|
|
||||||
|
List<Device> findByParentId(String parentId);
|
||||||
|
|
||||||
|
boolean postLocationRecord(LocationRecordDTO locationRecord);
|
||||||
|
|
||||||
|
void updateLatestDataTime(String deviceId, Date latestDataTime);
|
||||||
|
}
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
package com.imdroid.sideslope.sal;
|
||||||
|
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/3 20:46
|
||||||
|
*/
|
||||||
|
@Component(value = "local")
|
||||||
|
public class LocalDeviceServiceImpl implements DeviceService {
|
||||||
|
|
||||||
|
private static final Cache<String, Device> deviceCache = CacheBuilder.newBuilder().
|
||||||
|
expireAfterWrite(30, TimeUnit.MINUTES).build();
|
||||||
|
|
||||||
|
private static final Cache<String, List<Device>> subDeviceCache = CacheBuilder.newBuilder().
|
||||||
|
expireAfterWrite(10, TimeUnit.MINUTES).build();
|
||||||
|
|
||||||
|
@Resource(name = "db")
|
||||||
|
private DeviceService delegate;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Device findByDeviceId(String deviceId) {
|
||||||
|
Device device = deviceCache.getIfPresent(deviceId);
|
||||||
|
if (device == null) {
|
||||||
|
device = delegate.findByDeviceId(deviceId);
|
||||||
|
if (device != null) {
|
||||||
|
deviceCache.put(deviceId, device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Device> findByParentId(String parentId) {
|
||||||
|
List<Device> device = subDeviceCache.getIfPresent(parentId);
|
||||||
|
if (device == null) {
|
||||||
|
device = delegate.findByParentId(parentId);
|
||||||
|
if (device != null) {
|
||||||
|
subDeviceCache.put(parentId, device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean postLocationRecord(LocationRecordDTO locationRecord) {
|
||||||
|
return delegate.postLocationRecord(locationRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateLatestDataTime(String deviceId, Date latestDataTime) {
|
||||||
|
delegate.updateLatestDataTime(deviceId, latestDataTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,81 @@
|
|||||||
|
package com.imdroid.sideslope.sal;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/15 20:58
|
||||||
|
*/
|
||||||
|
public class LocationRecordDTO {
|
||||||
|
|
||||||
|
private String deviceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 北斗位置(b562),相对坐标
|
||||||
|
*/
|
||||||
|
private String b562;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 惯导位置(9250),相对坐标
|
||||||
|
*/
|
||||||
|
private String r9250;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 融合位置,相对坐标
|
||||||
|
*/
|
||||||
|
private String result;
|
||||||
|
|
||||||
|
|
||||||
|
private String flag;
|
||||||
|
|
||||||
|
public LocationRecordDTO() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocationRecordDTO(String deviceId, String b562, String r9250, String result, String flag) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
this.b562 = b562;
|
||||||
|
this.r9250 = r9250;
|
||||||
|
this.result = result;
|
||||||
|
this.flag = flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFlag() {
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFlag(String flag) {
|
||||||
|
this.flag = flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceId() {
|
||||||
|
return deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceId(String deviceId) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getB562() {
|
||||||
|
return b562;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setB562(String b562) {
|
||||||
|
this.b562 = b562;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getR9250() {
|
||||||
|
return r9250;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setR9250(String r9250) {
|
||||||
|
this.r9250 = r9250;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResult(String result) {
|
||||||
|
this.result = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
package com.imdroid.sideslope.server;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.socket.DatagramPacket;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/2 21:00
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class DeviceChannel {
|
||||||
|
private String deviceId;
|
||||||
|
|
||||||
|
private Channel channel;
|
||||||
|
|
||||||
|
private InetSocketAddress address;
|
||||||
|
|
||||||
|
private long lastTime;
|
||||||
|
|
||||||
|
private boolean tcp;
|
||||||
|
int txbytes = 0;
|
||||||
|
int rxbytes = 0;
|
||||||
|
int d3xxbytes = 0;
|
||||||
|
int b562bytes = 0;
|
||||||
|
|
||||||
|
public DeviceChannel(String deviceId, Channel channel, InetSocketAddress address) {
|
||||||
|
this.deviceId = deviceId;
|
||||||
|
this.channel = channel;
|
||||||
|
this.address = address;
|
||||||
|
lastTime = System.currentTimeMillis();
|
||||||
|
this.tcp = address == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOnline() {
|
||||||
|
if (tcp) {
|
||||||
|
return channel.isActive();
|
||||||
|
}
|
||||||
|
// return (System.currentTimeMillis() - lastTime) < 28 * 1000L;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeAndFlush(ByteBuf buf) {
|
||||||
|
txbytes += buf.readableBytes();
|
||||||
|
if (tcp) {
|
||||||
|
channel.writeAndFlush(buf);
|
||||||
|
} else {
|
||||||
|
channel.writeAndFlush(new DatagramPacket(buf, address));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateRxBytes(int bytes, byte[] header){
|
||||||
|
rxbytes += bytes;
|
||||||
|
int gnss_bytes = header[0]<<8 | header[1];
|
||||||
|
if(gnss_bytes == 0xd331) d3xxbytes += bytes;
|
||||||
|
else if(gnss_bytes == 0xd341) b562bytes += bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
package com.imdroid.sideslope.server;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.ConcurrentHashSet;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.util.Attribute;
|
||||||
|
import io.netty.util.AttributeKey;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/2 21:00
|
||||||
|
*/
|
||||||
|
public class OnlineChannels {
|
||||||
|
|
||||||
|
public static final OnlineChannels INSTANCE = new OnlineChannels();
|
||||||
|
|
||||||
|
// DTU已连接,有imei上报,但deviceId还没上报
|
||||||
|
// 记录DTU连接的好处:当DTU重连接而设备还没上报deviceId时,可以通过IMEI或广播消息来找到设备
|
||||||
|
private final Map<String, Channel> dtuChannels = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
// 设备已连接,deviceId已上报
|
||||||
|
private final Map<String, DeviceChannel> channels = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private OnlineChannels() {}
|
||||||
|
|
||||||
|
public boolean isNewChannel(Channel channel){
|
||||||
|
Attribute<String> attr = channel.attr(AttributeKey.valueOf("imei"));
|
||||||
|
return (attr.get()==null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNewDeviceChannel(Channel channel){
|
||||||
|
Attribute<String> attr = channel.attr(AttributeKey.valueOf("device_id"));
|
||||||
|
return (attr.get()==null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putDtuChannel(Channel channel, String imei){
|
||||||
|
dtuChannels.put(imei, channel);
|
||||||
|
Attribute<String> attr = channel.attr(AttributeKey.valueOf("imei"));
|
||||||
|
attr.set(imei);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putDeviceChannel(DeviceChannel channel) {
|
||||||
|
Attribute<String> attr = channel.getChannel().attr(AttributeKey.valueOf("device_id"));
|
||||||
|
attr.set(channel.getDeviceId());
|
||||||
|
channels.put(channel.getDeviceId(), channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<DeviceChannel> get(String deviceId) {
|
||||||
|
return Optional.ofNullable(channels.get(deviceId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DeviceChannel> getIfPresent(List<String> deviceIds) {
|
||||||
|
return deviceIds.stream().map(x -> channels.get(x)).filter(Objects::nonNull).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeviceChannel getDeviceChannel(String deviceId){
|
||||||
|
return channels.get(deviceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,88 @@
|
|||||||
|
package com.imdroid.sideslope.server.udp;
|
||||||
|
|
||||||
|
import com.imdroid.sideslope.exception.UnSupportedMessageException;
|
||||||
|
import com.imdroid.sideslope.executor.BizExecutors;
|
||||||
|
import com.imdroid.sideslope.executor.MessageParser;
|
||||||
|
import com.imdroid.sideslope.message.BaseMessage;
|
||||||
|
import com.imdroid.sideslope.server.DeviceChannel;
|
||||||
|
import com.imdroid.sideslope.server.OnlineChannels;
|
||||||
|
import com.imdroid.sideslope.util.DataTypeUtil;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.ChannelHandler;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
|
import io.netty.channel.socket.DatagramPacket;
|
||||||
|
import io.netty.util.ReferenceCountUtil;
|
||||||
|
import org.apache.ibatis.javassist.bytecode.ByteArray;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/13 11:47
|
||||||
|
*/
|
||||||
|
@ChannelHandler.Sharable
|
||||||
|
@Component
|
||||||
|
public class RtcmUdpHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(RtcmUdpHandler.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BizExecutors bizExecutors;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||||
|
DatagramPacket packet = (DatagramPacket) msg;
|
||||||
|
OnlineChannels onlineChannels = OnlineChannels.INSTANCE;
|
||||||
|
try {
|
||||||
|
if (packet.content() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
byte[] data = new byte[packet.content().readableBytes()];
|
||||||
|
packet.content().getBytes(0, data);
|
||||||
|
logger.debug("receive message:" + DataTypeUtil.getHexString(data));
|
||||||
|
}
|
||||||
|
// 消息解析
|
||||||
|
BaseMessage message = MessageParser.instance.parse(packet.content());
|
||||||
|
// 更新通道
|
||||||
|
DeviceChannel deviceChannel;
|
||||||
|
if(onlineChannels.isNewDeviceChannel(ctx.channel())){
|
||||||
|
deviceChannel = new DeviceChannel(message.getId(), ctx.channel(), packet.sender());
|
||||||
|
onlineChannels.putDeviceChannel(deviceChannel);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
deviceChannel = onlineChannels.getDeviceChannel(message.getId());
|
||||||
|
}
|
||||||
|
deviceChannel.updateRxBytes(message.getLen(), message.getHeader());
|
||||||
|
// 业务处理
|
||||||
|
bizExecutors.execute(message);
|
||||||
|
} catch (UnSupportedMessageException e) {
|
||||||
|
// DTU注册消息
|
||||||
|
if(onlineChannels.isNewChannel(ctx.channel())){
|
||||||
|
byte[] data = new byte[packet.content().readableBytes()];
|
||||||
|
packet.content().getBytes(0, data);
|
||||||
|
if(data.length == 15 && data[0]=='8' && data[1]=='6') {
|
||||||
|
OnlineChannels.INSTANCE.putDtuChannel(ctx.channel(), new String(data));
|
||||||
|
}
|
||||||
|
else logger.warn("receive un supported message: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
else logger.warn("receive un supported message: {}", e.getMessage());
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("channel read error: {}", e.toString());
|
||||||
|
} finally {
|
||||||
|
ReferenceCountUtil.release(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||||
|
super.exceptionCaught(ctx, cause);
|
||||||
|
ctx.close();
|
||||||
|
logger.error("Exception caught: {}", cause.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
package com.imdroid.sideslope.server.udp;
|
||||||
|
|
||||||
|
import io.netty.bootstrap.Bootstrap;
|
||||||
|
import io.netty.channel.ChannelFuture;
|
||||||
|
import io.netty.channel.ChannelOption;
|
||||||
|
import io.netty.channel.EventLoopGroup;
|
||||||
|
import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
|
import io.netty.channel.socket.nio.NioDatagramChannel;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.ApplicationArguments;
|
||||||
|
import org.springframework.boot.ApplicationRunner;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/13 11:47
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class RtcmUdpServer implements ApplicationRunner {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(RtcmUdpServer.class);
|
||||||
|
|
||||||
|
@Value("${netty.port:9903}")
|
||||||
|
private Integer port;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RtcmUdpHandler rtcmUdpHandler;
|
||||||
|
|
||||||
|
public RtcmUdpServer() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(ApplicationArguments args) throws Exception {
|
||||||
|
new Thread(this::start0, "udp-server").start();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void start0() {
|
||||||
|
EventLoopGroup group = new NioEventLoopGroup();
|
||||||
|
Bootstrap bootstrap = new Bootstrap();
|
||||||
|
bootstrap.group(group)
|
||||||
|
.channel(NioDatagramChannel.class)
|
||||||
|
.option(ChannelOption.SO_SNDBUF, 512)
|
||||||
|
.option(ChannelOption.SO_RCVBUF, 512)
|
||||||
|
.handler(rtcmUdpHandler);
|
||||||
|
try {
|
||||||
|
ChannelFuture future = bootstrap.bind(port).sync().channel().closeFuture();
|
||||||
|
logger.info("udp server start at port {}", port);
|
||||||
|
future.await();
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Error starting Imdroid protocol at port {}", port, e);
|
||||||
|
} finally {
|
||||||
|
group.shutdownGracefully();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package com.imdroid.sideslope.service;
|
||||||
|
|
||||||
|
import com.imdroid.sideslope.message.D3F0SelfCheckMessage;
|
||||||
|
import com.imdroid.sideslope.message.D3F2StopIndicationMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备数据持久化接口
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
public interface DataPersistService {
|
||||||
|
|
||||||
|
void saveDeviceState(D3F0SelfCheckMessage d3F0SelfCheckMessage);
|
||||||
|
|
||||||
|
void saveDeviceTrxStat(D3F2StopIndicationMessage d3F2StopIndicationMessage);
|
||||||
|
}
|
||||||
@ -0,0 +1,86 @@
|
|||||||
|
package com.imdroid.sideslope.service;
|
||||||
|
|
||||||
|
import com.imdroid.secapi.dto.*;
|
||||||
|
import com.imdroid.sideslope.message.D3F0SelfCheckMessage;
|
||||||
|
import com.imdroid.sideslope.message.D3F2StopIndicationMessage;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备数据持久化实现
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class DataPersistServiceImpl implements DataPersistService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private GnssStatusMapper deviceStateRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private GnssStatusMsgMapper statusMsgMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private GnssTrxMsgMapper trxMsgMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveDeviceState(D3F0SelfCheckMessage message) {
|
||||||
|
try {
|
||||||
|
// 保存到statusmsg数据表里
|
||||||
|
GnssStatusMsg statusMsg = message.getStatusMsg();
|
||||||
|
statusMsgMapper.insert(statusMsg);
|
||||||
|
|
||||||
|
//新增或更新到status数据表里
|
||||||
|
GnssStatus deviceState = deviceStateRepository.getByDeviceId(message.getId());
|
||||||
|
boolean new_flag = false;
|
||||||
|
if(null == deviceState) {
|
||||||
|
deviceState = new GnssStatus();
|
||||||
|
new_flag = true;
|
||||||
|
}
|
||||||
|
//deviceState.setId(SequenceUtil.getSequence());
|
||||||
|
deviceState.setDeviceid(message.getId());
|
||||||
|
deviceState.setUpdatetime(statusMsg.getUpdatetime());
|
||||||
|
deviceState.setRoll(statusMsg.getRoll());
|
||||||
|
deviceState.setPitch(statusMsg.getPitch());
|
||||||
|
deviceState.setYaw(statusMsg.getYaw());
|
||||||
|
deviceState.setRssi(statusMsg.getRssi());
|
||||||
|
deviceState.setVoltage(statusMsg.getVoltage());
|
||||||
|
deviceState.setTemperature(statusMsg.getTemperature());
|
||||||
|
deviceState.setHumidity(statusMsg.getHumidity());
|
||||||
|
|
||||||
|
// 检测状态和告警
|
||||||
|
deviceState.setState(GnssStatus.STATE_ACTIVE);
|
||||||
|
|
||||||
|
if(new_flag) deviceStateRepository.insert(deviceState);
|
||||||
|
else deviceStateRepository.updateById(deviceState);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveDeviceTrxStat(D3F2StopIndicationMessage message) {
|
||||||
|
try {
|
||||||
|
// 添加到trxmsg里
|
||||||
|
trxMsgMapper.insert(message.getTrxMsg());
|
||||||
|
|
||||||
|
// 检测该对象是否已存在
|
||||||
|
GnssStatus deviceState = deviceStateRepository.getByDeviceId(message.getId());
|
||||||
|
//新增或更新到status数据表里
|
||||||
|
if(null != deviceState) {
|
||||||
|
// 记录服务端收发统计
|
||||||
|
/*deviceState.setTxbytes(txbytes);
|
||||||
|
deviceState.setRxbytes(rxbytes);
|
||||||
|
deviceState.setD3xxbytes(d3xxbytes);
|
||||||
|
deviceState.setB562bytes(b562bytes);*/
|
||||||
|
deviceState.setState(GnssStatus.STATE_IDLE);
|
||||||
|
deviceStateRepository.updateById(deviceState);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
package com.imdroid.sideslope.service;
|
||||||
|
|
||||||
|
import com.imdroid.sideslope.message.D341LocationMessage;
|
||||||
|
import com.imdroid.sideslope.sal.LocationRecordDTO;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/4 20:18
|
||||||
|
*/
|
||||||
|
public interface GNSSDeviceLocationRecordService {
|
||||||
|
|
||||||
|
public void save(LocationRecordDTO importRecord) throws Exception;
|
||||||
|
public void saveSingleCalcData(D341LocationMessage message);
|
||||||
|
}
|
||||||
@ -0,0 +1,198 @@
|
|||||||
|
package com.imdroid.sideslope.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.imdroid.secapi.dto.*;
|
||||||
|
import com.imdroid.sideslope.bd.Tilt;
|
||||||
|
import com.imdroid.sideslope.message.D341LocationMessage;
|
||||||
|
import com.imdroid.sideslope.rabbitmq.RabbitmqConfig;
|
||||||
|
import com.imdroid.sideslope.sal.LocationRecordDTO;
|
||||||
|
import com.imdroid.sideslope.util.GsonUtil;
|
||||||
|
import com.imdroid.sideslope.util.NumberUtils;
|
||||||
|
import io.dt20.common.persistence.Attribute;
|
||||||
|
import io.dt20.common.repo.AttributeRepository;
|
||||||
|
import io.dt20.util.SequenceUtil;
|
||||||
|
import io.dt20.util.StringUtil;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/15 21:05
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class GNSSDeviceLocationRecordServiceImpl implements GNSSDeviceLocationRecordService{
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(this.getClazz());
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private GnssCalcDataMapper repository;
|
||||||
|
@Autowired
|
||||||
|
private GnssSingleCalcDataMapper singleCalcDataMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private GnssDeviceMapper gnssDeviceRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RabbitTemplate rabbitTemplate;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AttributeRepository attributeRepository;
|
||||||
|
|
||||||
|
private int a, b = 25 * 60 * 60 * 1000;
|
||||||
|
|
||||||
|
|
||||||
|
protected Class<GnssCalcData> getClazz() {
|
||||||
|
return GnssCalcData.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(LocationRecordDTO importRecord) throws Exception {
|
||||||
|
GnssDevice gnssDevice = gnssDeviceRepository.queryByDeviceId(importRecord.getDeviceId());
|
||||||
|
|
||||||
|
GnssCalcData locationRecord = new GnssCalcData();
|
||||||
|
locationRecord.setDeviceid(importRecord.getDeviceId());
|
||||||
|
locationRecord.setCreatetime(new Timestamp(System.currentTimeMillis()));
|
||||||
|
locationRecord.setEnabled(true);
|
||||||
|
locationRecord.setId(SequenceUtil.getSequence());
|
||||||
|
if (!StringUtil.isEmpty(importRecord.getB562())) {
|
||||||
|
String resultStr = NumberUtils.removeBrackets(importRecord.getB562());
|
||||||
|
String[] arr = resultStr.split(",");
|
||||||
|
// 由cm转化为mm
|
||||||
|
locationRecord.setB562e(NumberUtils.scaleTwo(Double.parseDouble(arr[0]) * 10));
|
||||||
|
locationRecord.setB562n(NumberUtils.scaleTwo(Double.parseDouble(arr[1]) * 10));
|
||||||
|
locationRecord.setB562d(NumberUtils.scaleTwo(Double.parseDouble(arr[2]) * 10));
|
||||||
|
}
|
||||||
|
if (!StringUtil.isEmpty(importRecord.getR9250())) {
|
||||||
|
String resultStr = NumberUtils.removeBrackets(importRecord.getR9250());
|
||||||
|
String[] arr = resultStr.split(",");
|
||||||
|
locationRecord.setR9250e(NumberUtils.scaleTwo(arr[0]));
|
||||||
|
locationRecord.setR9250n(NumberUtils.scaleTwo(arr[1]));
|
||||||
|
locationRecord.setR9250d(NumberUtils.scaleTwo(arr[2]));
|
||||||
|
}
|
||||||
|
if (!StringUtil.isEmpty(importRecord.getResult())) {
|
||||||
|
String resultStr = NumberUtils.removeBrackets(importRecord.getResult());
|
||||||
|
String[] arr = resultStr.split(",");
|
||||||
|
locationRecord.setResulte(NumberUtils.scaleTwo(arr[0]));
|
||||||
|
locationRecord.setResultn(NumberUtils.scaleTwo(arr[1]));
|
||||||
|
locationRecord.setResultd(NumberUtils.scaleTwo(arr[2]));
|
||||||
|
|
||||||
|
// 做滤波 水平方向按照shock 若 >1.5 用6h滤波 否则用25h
|
||||||
|
// 垂直方向 用6+12
|
||||||
|
List<Attribute> attributes = attributeRepository.findByObjectAndPid(gnssDevice.getObjectName(), gnssDevice.getId());
|
||||||
|
if (!StringUtil.isEmpty(importRecord.getFlag()) && Boolean.parseBoolean(importRecord.getFlag())) {
|
||||||
|
a = 6 * 60 * 60 * 1000;
|
||||||
|
b = 6 * 60 * 60 * 1000;
|
||||||
|
}
|
||||||
|
for (Attribute attribute : attributes) {
|
||||||
|
if (attribute.getValueNumber() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
double[] avgEND = avgEND(gnssDevice.getDeviceid(), locationRecord, a, b);
|
||||||
|
if (ATTR_B562E.equals(attribute.getKey())) {
|
||||||
|
locationRecord.setRb562e(NumberUtils.scaleTwo(avgEND[0] * 10 - attribute.getValueNumber()));
|
||||||
|
}
|
||||||
|
if (ATTR_B562N.equals(attribute.getKey())) {
|
||||||
|
locationRecord.setRb562n(NumberUtils.scaleTwo(avgEND[1] * 10 - attribute.getValueNumber()));
|
||||||
|
}
|
||||||
|
if (ATTR_B562D.equals(attribute.getKey())) {
|
||||||
|
locationRecord.setRb562d(NumberUtils.scaleTwo(avgEND[2] * 10 - attribute.getValueNumber()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a = 25 * 60 * 60 * 1000;
|
||||||
|
b = 25 * 60 * 60 * 1000;
|
||||||
|
}
|
||||||
|
sendDataToMq(locationRecord);
|
||||||
|
repository.insert(locationRecord);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String ATTR_B562E = "b562e";
|
||||||
|
public static final String ATTR_B562N = "b562n";
|
||||||
|
public static final String ATTR_B562D = "b562d";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算东北天的最近融合数据的加权平均, 刘畅20230725 copy 自 avgEND; id>20, 滤波参数6h 或 25h
|
||||||
|
*/
|
||||||
|
public double[] avgEND(String deviceId, GnssCalcData last, int a, int b) {
|
||||||
|
//double c = 0.5467;
|
||||||
|
double c = 0.5;
|
||||||
|
ArrayList<GnssCalcData> gnssDeviceLocationRecords = new ArrayList<>();
|
||||||
|
QueryWrapper<GnssCalcData> wrapper = new QueryWrapper<>();
|
||||||
|
wrapper.eq("deviceid",deviceId);
|
||||||
|
wrapper.last("limit 20");
|
||||||
|
|
||||||
|
List<GnssCalcData> GNSSDeviceLocationRecords = repository.selectList(wrapper);
|
||||||
|
gnssDeviceLocationRecords.addAll(GNSSDeviceLocationRecords);
|
||||||
|
|
||||||
|
if (gnssDeviceLocationRecords.size() > 0) {
|
||||||
|
double sumE = last.getResulte(), sumE2 = last.getResulte();
|
||||||
|
double sumN = last.getResultn(), sumN2 = last.getResultn();
|
||||||
|
double sumD = last.getResultd(), sumD2 = last.getResultd();
|
||||||
|
double[] lastLocation = {last.getResulte(), last.getResultn(), last.getResultd()};
|
||||||
|
int count = 1, count2 = 1;
|
||||||
|
for (int i = 0; i < gnssDeviceLocationRecords.size(); i++) {
|
||||||
|
double[] findLocation = {gnssDeviceLocationRecords.get(i).getResulte(), gnssDeviceLocationRecords.get(i).getResultn(), gnssDeviceLocationRecords.get(i).getResultd()};
|
||||||
|
if (disXY(lastLocation, findLocation) > 100) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
long time = System.currentTimeMillis() - gnssDeviceLocationRecords.get(i).getCreatetime().getTime();
|
||||||
|
if (time < a) {
|
||||||
|
sumE += gnssDeviceLocationRecords.get(i).getResulte();
|
||||||
|
sumN += gnssDeviceLocationRecords.get(i).getResultn();
|
||||||
|
sumD += gnssDeviceLocationRecords.get(i).getResultd();
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (time < b) {
|
||||||
|
sumE2 += gnssDeviceLocationRecords.get(i).getResulte();
|
||||||
|
sumN2 += gnssDeviceLocationRecords.get(i).getResultn();
|
||||||
|
sumD2 += gnssDeviceLocationRecords.get(i).getResultd();
|
||||||
|
count2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
double e = sumE / count * c + sumE2 / count2 * (1 - c);
|
||||||
|
double n = sumN / count * c + sumN2 / count2 * (1 - c);
|
||||||
|
double d = sumD / count * c + sumD2 / count2 * (1 - c);
|
||||||
|
return new double[]{e, n, d};
|
||||||
|
} else {
|
||||||
|
return new double[]{last.getResulte(), last.getResultn(), last.getResultd()};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static double disXY(double[] a, double[] b) {
|
||||||
|
return Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendDataToMq(GnssCalcData locationRecord) {
|
||||||
|
String message = GsonUtil.toJson(locationRecord);
|
||||||
|
rabbitTemplate.convertAndSend(RabbitmqConfig.EXCHANGE_GNSS, RabbitmqConfig.QUEUE_GNSS_LOCATION_RECORD, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveSingleCalcData(D341LocationMessage message){
|
||||||
|
GnssSingleCalcData data = new GnssSingleCalcData();
|
||||||
|
data.setDeviceid(message.getId());
|
||||||
|
data.setCreatetime(new Timestamp(System.currentTimeMillis()));
|
||||||
|
Tilt tilt = message.getTilt();
|
||||||
|
data.setRoll(tilt.getRoll());
|
||||||
|
data.setPitch(tilt.getPitch());
|
||||||
|
data.setYaw(tilt.getYaw());
|
||||||
|
data.setShock(tilt.getShock());
|
||||||
|
double[] b562_loc = message.getB562_loc();
|
||||||
|
if(b562_loc!=null) {
|
||||||
|
data.setB562e(b562_loc[0]);
|
||||||
|
data.setB562n(b562_loc[1]);
|
||||||
|
data.setB562d(b562_loc[2]);
|
||||||
|
}
|
||||||
|
singleCalcDataMapper.insert(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,393 @@
|
|||||||
|
package com.imdroid.sideslope.util;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2022/3/21 15:36
|
||||||
|
*/
|
||||||
|
public class DataTypeUtil {
|
||||||
|
|
||||||
|
public static byte[] intToByteLittle(int n) {
|
||||||
|
byte[] b = new byte[4];
|
||||||
|
b[0] = (byte) (n & 0xff);
|
||||||
|
b[1] = (byte) (n >> 8 & 0xff);
|
||||||
|
b[2] = (byte) (n >> 16 & 0xff);
|
||||||
|
b[3] = (byte) (n >> 24 & 0xff);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] intToByteBig(int number) {
|
||||||
|
byte[] b = new byte[4];
|
||||||
|
|
||||||
|
b[0] = (byte) (number >> 24);
|
||||||
|
b[1] = (byte) (number >> 16);
|
||||||
|
b[2] = (byte) (number >> 8);
|
||||||
|
b[3] = (byte) number;
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] floatToByteLittle(float n) {
|
||||||
|
int fbit = Float.floatToIntBits(n);
|
||||||
|
return intToByteLittle(fbit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] floatToByteBig(float n) {
|
||||||
|
int fbit = Float.floatToIntBits(n);
|
||||||
|
return intToByteBig(fbit);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将byte数组转换为long数据 (大端模式)
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* length为8的byte数组
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static long byteToLong(byte[] data) {
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(8);
|
||||||
|
|
||||||
|
buffer.put(data, 0, 8);
|
||||||
|
buffer.flip();
|
||||||
|
|
||||||
|
return buffer.getLong();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将byte数组转换为long数据 (大端模式)
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* length为8的byte数组
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static long byteToLong(byte[] data, int offset) {
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(8);
|
||||||
|
|
||||||
|
buffer.put(data, offset, 8);
|
||||||
|
buffer.flip();
|
||||||
|
|
||||||
|
return buffer.getLong();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将byte数组转为int数据 (大端模式)
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* length为4的byte数组
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static int byteToInt(byte[] data) {
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(4);
|
||||||
|
|
||||||
|
buffer.put(data, 0, 4);
|
||||||
|
buffer.flip();
|
||||||
|
|
||||||
|
return buffer.getInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将byte数组转为int数据 (大端模式)
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* length为4的byte数组
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static int byteToInt(byte[] data, int offset) {
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(4);
|
||||||
|
|
||||||
|
buffer.put(data, offset, 4);
|
||||||
|
buffer.flip();
|
||||||
|
|
||||||
|
return buffer.getInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将byte数组转为short数据 (大端模式)
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* length为2的byte数组
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static short byteToShort(byte[] data) {
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(2);
|
||||||
|
|
||||||
|
buffer.put(data, 0, 2);
|
||||||
|
buffer.flip();
|
||||||
|
|
||||||
|
return buffer.getShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将byte数组转为float数据(大端模式)
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* length为4的byte数组
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static float bytesToFloat(byte[] data) {
|
||||||
|
int value = byteToInt(data);
|
||||||
|
return Float.intBitsToFloat(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将byte数组转为float数据(小端模式)
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* length为4的byte数组
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static float lowBytesToFloat(byte[] data) {
|
||||||
|
int len = data.length;
|
||||||
|
// 获得一个反的数组
|
||||||
|
byte[] dest = new byte[len];
|
||||||
|
|
||||||
|
for (int i = 0; i < len; i++) {
|
||||||
|
dest[len - i - 1] = data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
int value = byteToInt(dest);
|
||||||
|
return Float.intBitsToFloat(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* byte数组大小端反转
|
||||||
|
*
|
||||||
|
* @param bytes 数据
|
||||||
|
*/
|
||||||
|
public static void bytesReverse(byte[] bytes) {
|
||||||
|
int half = bytes.length / 2;
|
||||||
|
for (int i = 0; i < half; i++) {
|
||||||
|
byte temp = bytes[i];
|
||||||
|
bytes[i] = bytes[bytes.length - i - 1];
|
||||||
|
bytes[bytes.length - i - 1] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将long转为byte数组 (大端模式)
|
||||||
|
*
|
||||||
|
* @param number
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static byte[] longToByte(long number) {
|
||||||
|
byte[] b = new byte[8];
|
||||||
|
|
||||||
|
b[0] = (byte) (number >> 56);
|
||||||
|
b[1] = (byte) (number >> 48);
|
||||||
|
b[2] = (byte) (number >> 40);
|
||||||
|
b[3] = (byte) (number >> 32);
|
||||||
|
b[4] = (byte) (number >> 24);
|
||||||
|
b[5] = (byte) (number >> 16);
|
||||||
|
b[6] = (byte) (number >> 8);
|
||||||
|
b[7] = (byte) number;
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将short转为byte数组 (小端模式)
|
||||||
|
*
|
||||||
|
* @param number
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static byte[] shortToByteLittle(short number) {
|
||||||
|
|
||||||
|
byte[] src = new byte[2];
|
||||||
|
src[1] = (byte) ((number >> 8) & 0xFF);
|
||||||
|
src[0] = (byte) (number & 0xFF);
|
||||||
|
return src;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将short转为byte数组 (大端模式)
|
||||||
|
*
|
||||||
|
* @param number
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static byte[] shortToByteBig(short number) {
|
||||||
|
|
||||||
|
byte[] src = new byte[2];
|
||||||
|
src[0] = (byte) ((number >> 8) & 0xFF);
|
||||||
|
src[1] = (byte) (number & 0xFF);
|
||||||
|
return src;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static short byteToShort(byte byte0, byte byte1) {
|
||||||
|
return (short) (((byte0 & 0xff) << 8) | (byte1 & 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将byte转换为一个长度为8的byte数组,数组每个值代表bit
|
||||||
|
*
|
||||||
|
* @param b
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static byte[] getBitArray(byte b) {
|
||||||
|
byte[] array = new byte[8];
|
||||||
|
for (int i = 7; i >= 0; i--) {
|
||||||
|
array[i] = (byte) (b & 1);
|
||||||
|
b = (byte) (b >> 1);
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 把byte转为字符串的bit
|
||||||
|
*
|
||||||
|
* @param b
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String byteToBit(byte b) {
|
||||||
|
return ""
|
||||||
|
+ (byte) ((b >> 7) & 0x1) + (byte) ((b >> 6) & 0x1)
|
||||||
|
+ (byte) ((b >> 5) & 0x1) + (byte) ((b >> 4) & 0x1)
|
||||||
|
+ (byte) ((b >> 3) & 0x1) + (byte) ((b >> 2) & 0x1)
|
||||||
|
+ (byte) ((b >> 1) & 0x1) + (byte) ((b >> 0) & 0x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bit 转换为byte
|
||||||
|
*
|
||||||
|
* @param byteStr 位字符串
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static byte bitToByte(String byteStr) {
|
||||||
|
int re, len;
|
||||||
|
if (null == byteStr) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
len = byteStr.length();
|
||||||
|
if (len != 4 && len != 8) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (len == 8) {// 8 bit处理
|
||||||
|
if (byteStr.charAt(0) == '0') {// 正数
|
||||||
|
re = Integer.parseInt(byteStr, 2);
|
||||||
|
} else {// 负数
|
||||||
|
re = Integer.parseInt(byteStr, 2) - 256;
|
||||||
|
}
|
||||||
|
} else {//4 bit处理
|
||||||
|
re = Integer.parseInt(byteStr, 2);
|
||||||
|
}
|
||||||
|
return (byte) re;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getHexString(byte[] bs, int start, int end) {
|
||||||
|
StringBuilder stringBuilder = new StringBuilder("");
|
||||||
|
if (bs == null || bs.length <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (int i = start; i < end; i++) {
|
||||||
|
int v = bs[i] & 0xFF;
|
||||||
|
String hv = Integer.toHexString(v);
|
||||||
|
if (hv.length() < 2) {
|
||||||
|
stringBuilder.append(0);
|
||||||
|
}
|
||||||
|
stringBuilder.append(hv);
|
||||||
|
}
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//bytes to string
|
||||||
|
public static String getHexString(byte[] bs) {
|
||||||
|
StringBuilder stringBuilder = new StringBuilder("");
|
||||||
|
if (bs == null || bs.length <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < bs.length; i++) {
|
||||||
|
int v = bs[i] & 0xFF;
|
||||||
|
String hv = Integer.toHexString(v);
|
||||||
|
if (hv.length() < 2) {
|
||||||
|
stringBuilder.append(0);
|
||||||
|
}
|
||||||
|
stringBuilder.append(hv);
|
||||||
|
}
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Hex String to bytes
|
||||||
|
public static byte[] hexStringToBytes(String hexString) {
|
||||||
|
if (hexString == null || "".equals(hexString)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
hexString = hexString.toUpperCase();
|
||||||
|
int length = hexString.length() / 2;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getString(byte[] bytes) {
|
||||||
|
return getString(bytes, "GBK");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getUTFString(byte[] bytes) {
|
||||||
|
return new String(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getString(byte[] bytes, String charsetName) {
|
||||||
|
return new String(bytes, Charset.forName(charsetName));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ascii转换为字符串
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String asciiToString(String value) {
|
||||||
|
StringBuilder sbu = new StringBuilder();
|
||||||
|
String[] chars = value.split(",");
|
||||||
|
for (int i = 0; i < chars.length; i++) {
|
||||||
|
sbu.append((char) Integer.parseInt(chars[i]));
|
||||||
|
}
|
||||||
|
return sbu.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 浮点转换为字节 (小端模式)
|
||||||
|
*
|
||||||
|
* @param f
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static byte[] floatTobyteLittle(float f) {
|
||||||
|
|
||||||
|
// 把float转换为byte[]
|
||||||
|
int fbit = Float.floatToIntBits(f);
|
||||||
|
|
||||||
|
byte[] b = new byte[4];
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
b[i] = (byte) (fbit >> (24 - i * 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 翻转数组
|
||||||
|
int len = b.length;
|
||||||
|
// 建立一个与源数组元素类型相同的数组
|
||||||
|
byte[] dest = new byte[len];
|
||||||
|
// 为了防止修改源数组,将源数组拷贝一份副本
|
||||||
|
System.arraycopy(b, 0, dest, 0, len);
|
||||||
|
byte temp;
|
||||||
|
// 将顺位第i个与倒数第i个交换
|
||||||
|
for (int i = 0; i < len / 2; ++i) {
|
||||||
|
temp = dest[i];
|
||||||
|
dest[i] = dest[len - i - 1];
|
||||||
|
dest[len - i - 1] = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
package com.imdroid.sideslope.util;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2022/3/28 15:35
|
||||||
|
*/
|
||||||
|
public class GsonUtil {
|
||||||
|
|
||||||
|
private static final Gson gson = new Gson();
|
||||||
|
|
||||||
|
private static final Gson serializeNullGson = new GsonBuilder().serializeNulls().disableHtmlEscaping().create();
|
||||||
|
|
||||||
|
private static final Gson serializeExposeGson = new GsonBuilder().serializeNulls().excludeFieldsWithoutExposeAnnotation().create();
|
||||||
|
|
||||||
|
public static String toJsonSerializeNull(Object c) {
|
||||||
|
return serializeNullGson.toJson(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toJson(Object c) {
|
||||||
|
return gson.toJson(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String toJsonExpose(Object c) {
|
||||||
|
return serializeExposeGson.toJson(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T fromJson(String json, Class<T> clz) {
|
||||||
|
return gson.fromJson(json, clz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T fromJson(String json, Type typeOfT) {
|
||||||
|
return gson.fromJson(json, typeOfT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getValue(JsonObject jsonObject, String key) {
|
||||||
|
JsonElement element = jsonObject.has(key) ? jsonObject.get(key) : null;
|
||||||
|
if (element == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (element.isJsonObject()) {
|
||||||
|
return element.getAsJsonObject().toString();
|
||||||
|
} else if (element.isJsonNull()) {
|
||||||
|
return "";
|
||||||
|
} else if (element.isJsonArray()) {
|
||||||
|
return element.getAsJsonArray().toString();
|
||||||
|
} else {
|
||||||
|
if (element.getAsJsonPrimitive().isBoolean()) {
|
||||||
|
return element.getAsBoolean() ? "true" : "false";
|
||||||
|
} else {
|
||||||
|
return element.getAsString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Number getNumber(JsonElement element) { ;
|
||||||
|
if (element == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (element.isJsonNull()) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
return element.getAsNumber();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,392 @@
|
|||||||
|
package com.imdroid.sideslope.util;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import org.apache.http.HttpEntity;
|
||||||
|
import org.apache.http.HttpEntityEnclosingRequest;
|
||||||
|
import org.apache.http.HttpStatus;
|
||||||
|
import org.apache.http.NameValuePair;
|
||||||
|
import org.apache.http.client.config.RequestConfig;
|
||||||
|
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||||
|
import org.apache.http.client.methods.*;
|
||||||
|
import org.apache.http.client.utils.HttpClientUtils;
|
||||||
|
import org.apache.http.config.Registry;
|
||||||
|
import org.apache.http.config.RegistryBuilder;
|
||||||
|
import org.apache.http.conn.socket.ConnectionSocketFactory;
|
||||||
|
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
|
||||||
|
import org.apache.http.conn.ssl.NoopHostnameVerifier;
|
||||||
|
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||||
|
import org.apache.http.entity.ContentType;
|
||||||
|
import org.apache.http.entity.StringEntity;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClients;
|
||||||
|
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
|
import org.apache.http.message.BasicNameValuePair;
|
||||||
|
import org.apache.http.ssl.SSLContexts;
|
||||||
|
import org.apache.http.ssl.TrustStrategy;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author layton
|
||||||
|
* @date 2021/6/21
|
||||||
|
*/
|
||||||
|
public class HttpUtils {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
|
||||||
|
|
||||||
|
public HttpUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 多线程共享实例
|
||||||
|
*/
|
||||||
|
private static final CloseableHttpClient httpClient;
|
||||||
|
|
||||||
|
static {
|
||||||
|
SSLContext sslContext = createSSLContext();
|
||||||
|
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
|
||||||
|
// 注册http套接字工厂和https套接字工厂
|
||||||
|
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
|
||||||
|
.register("http", PlainConnectionSocketFactory.INSTANCE)
|
||||||
|
.register("https", sslsf)
|
||||||
|
.build();
|
||||||
|
// 连接池管理器
|
||||||
|
PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
|
||||||
|
//连接池最大连接数
|
||||||
|
connMgr.setMaxTotal(50);
|
||||||
|
//每个路由最大连接数,设置的过小,无法支持大并发
|
||||||
|
connMgr.setDefaultMaxPerRoute(50);
|
||||||
|
//在从连接池获取连接时,连接不活跃多长时间后需要进行一次验证
|
||||||
|
connMgr.setValidateAfterInactivity(5 * 1000);
|
||||||
|
// 请求参数配置管理器
|
||||||
|
RequestConfig requestConfig = RequestConfig.custom()
|
||||||
|
.setConnectTimeout(60000)
|
||||||
|
.setSocketTimeout(60000)
|
||||||
|
.setConnectionRequestTimeout(60000)
|
||||||
|
.build();
|
||||||
|
// 获取httpClient客户端
|
||||||
|
httpClient = HttpClients.custom()
|
||||||
|
.setConnectionManager(connMgr)
|
||||||
|
.setDefaultRequestConfig(requestConfig)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET请求
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getUrl(String url) {
|
||||||
|
return sendHttp(HttpMethod.GET, url, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET请求
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getUrl(String url, Map<String, String> param, Map<String, String> header) {
|
||||||
|
return sendHttp(HttpMethod.GET, url, header, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET请求/带头部的信息
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @param header
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getUrl(String url, Map<String, String> header) {
|
||||||
|
return sendHttp(HttpMethod.GET, url, header, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST请求/无参数
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String postJson(String url) {
|
||||||
|
return postJson(url, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST请求/有参数
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @param param
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String postJson(String url, String param) {
|
||||||
|
return postJson(url, null, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST请求/有参数
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @param param
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String postJsonObj(String url, JsonObject param) {
|
||||||
|
return postJsonObj(url, null, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST请求/无参数带头部
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @param header
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String postJson(String url, Map<String, String> header) {
|
||||||
|
return postJson(url, header, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST请求/有参数带头部
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @param header
|
||||||
|
* @param params
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String postJson(String url, Map<String, String> header, String params) {
|
||||||
|
return sendHttp(HttpMethod.POST, url, header, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST请求/有参数带头部
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @param header
|
||||||
|
* @param params
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String postJsonObj(String url, Map<String, String> header, JsonObject params) {
|
||||||
|
return sendHttp(HttpMethod.POST, url, header, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从下载地址获取文件流(如果链接出现双斜杠,请用OKHttp)
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ByteArrayOutputStream getDownloadFileStream(String url) {
|
||||||
|
String infoMessage = new StringBuilder().append("request getDownloadFileStream,url:").append(url).toString();
|
||||||
|
log.info(infoMessage);
|
||||||
|
ByteArrayOutputStream byteOutStream = null;
|
||||||
|
try {
|
||||||
|
CloseableHttpResponse response = httpClient.execute(new HttpGet(url));
|
||||||
|
log.info("getDownloadFileStream response status:{}", response.getStatusLine());
|
||||||
|
int statusCode = response.getStatusLine().getStatusCode();
|
||||||
|
if (statusCode == HttpStatus.SC_OK) {
|
||||||
|
//请求成功
|
||||||
|
HttpEntity entity = response.getEntity();
|
||||||
|
if (entity != null && entity.getContent() != null) {
|
||||||
|
//复制输入流
|
||||||
|
byteOutStream = cloneInputStream(entity.getContent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HttpClientUtils.closeQuietly(response);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(infoMessage + " failure", e);
|
||||||
|
}
|
||||||
|
return byteOutStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送http请求(通用方法)
|
||||||
|
*
|
||||||
|
* @param httpMethod 请求方式(GET、POST、PUT、DELETE)
|
||||||
|
* @param url 请求路径
|
||||||
|
* @param header 请求头
|
||||||
|
* @param params 请求body(json数据)
|
||||||
|
* @return 响应文本
|
||||||
|
*/
|
||||||
|
public static String sendHttp(HttpMethod httpMethod, String url, Map<String, String> header, Object params) {
|
||||||
|
String infoMessage = new StringBuilder().append("request sendHttp,url:").append(url)
|
||||||
|
.append(",method:").append(httpMethod.name()).append(",header:")
|
||||||
|
.append(GsonUtil.toJson(header)).append(",param:").append(params).toString();
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug(infoMessage);
|
||||||
|
}
|
||||||
|
//返回结果
|
||||||
|
String result = null;
|
||||||
|
long beginTime = System.currentTimeMillis();
|
||||||
|
try {
|
||||||
|
ContentType contentType = ContentType.APPLICATION_JSON.withCharset("UTF-8");
|
||||||
|
HttpRequestBase request = buildHttpMethod(httpMethod, url);
|
||||||
|
if (Objects.nonNull(header) && !header.isEmpty()) {
|
||||||
|
for (Map.Entry<String, String> entry : header.entrySet()) {
|
||||||
|
//打印头部信息
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug(entry.getKey() + ":" + entry.getValue());
|
||||||
|
}
|
||||||
|
request.setHeader(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (params != null) {
|
||||||
|
if (HttpMethod.POST.equals(httpMethod) || HttpMethod.PUT.equals(httpMethod)) {
|
||||||
|
if (params instanceof JsonObject || params instanceof String) {
|
||||||
|
String jsonString = params.toString();
|
||||||
|
if (jsonString != null && jsonString.length() > 0) {
|
||||||
|
((HttpEntityEnclosingRequest) request).setEntity(new StringEntity(jsonString, contentType));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Map<String, String> paramsHashMap = (Map<String, String>) params;
|
||||||
|
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
|
||||||
|
for (String key : paramsHashMap.keySet()) {
|
||||||
|
formparams.add(new BasicNameValuePair(key, paramsHashMap.get(key)));
|
||||||
|
}
|
||||||
|
((HttpEntityEnclosingRequest) request).setEntity(new UrlEncodedFormEntity(formparams, "UTF-8"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CloseableHttpResponse response = httpClient.execute(request);
|
||||||
|
HttpEntity httpEntity = response.getEntity();
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("sendHttp response status:{}", response.getStatusLine());
|
||||||
|
}
|
||||||
|
if (Objects.nonNull(httpEntity)) {
|
||||||
|
result = EntityUtils.toString(httpEntity, "UTF-8");
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("sendHttp response body:{}", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//关闭返回对象
|
||||||
|
HttpClientUtils.closeQuietly(response);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(infoMessage + " failure", e);
|
||||||
|
}
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("request sendHttp response time cost:" + (endTime - beginTime) + " ms");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求方法(全大些)GET POST PUT DELETE
|
||||||
|
*/
|
||||||
|
public enum HttpMethod {
|
||||||
|
GET, POST, PUT, DELETE
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建请求方法
|
||||||
|
*
|
||||||
|
* @param method
|
||||||
|
* @param url
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static HttpRequestBase buildHttpMethod(HttpMethod method, String url) {
|
||||||
|
if (HttpMethod.GET.equals(method)) {
|
||||||
|
return new HttpGet(url);
|
||||||
|
} else if (HttpMethod.POST.equals(method)) {
|
||||||
|
return new HttpPost(url);
|
||||||
|
} else if (HttpMethod.PUT.equals(method)) {
|
||||||
|
return new HttpPut(url);
|
||||||
|
} else if (HttpMethod.DELETE.equals(method)) {
|
||||||
|
return new HttpDelete(url);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置证书
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static SSLContext createSSLContext() {
|
||||||
|
try {
|
||||||
|
//信任所有,支持导入ssl证书
|
||||||
|
TrustStrategy acceptingTrustStrategy = (cert, authType) -> true;
|
||||||
|
SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
|
||||||
|
return sslContext;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("初始化ssl配置失败", e);
|
||||||
|
throw new RuntimeException("初始化ssl配置失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 复制文件流
|
||||||
|
*
|
||||||
|
* @param input
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static ByteArrayOutputStream cloneInputStream(InputStream input) {
|
||||||
|
try {
|
||||||
|
ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream();
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
int len;
|
||||||
|
while ((len = input.read(buffer)) > -1) {
|
||||||
|
byteOutStream.write(buffer, 0, len);
|
||||||
|
}
|
||||||
|
byteOutStream.flush();
|
||||||
|
return byteOutStream;
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.warn("copy InputStream error,", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入流转字节流
|
||||||
|
*
|
||||||
|
* @param in
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static byte[] inputStream2byte(InputStream in) {
|
||||||
|
ByteArrayOutputStream bos = null;
|
||||||
|
try {
|
||||||
|
bos = new ByteArrayOutputStream();
|
||||||
|
byte[] b = new byte[1024];
|
||||||
|
int n;
|
||||||
|
while ((n = in.read(b)) != -1) {
|
||||||
|
bos.write(b, 0, n);
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
bos.close();
|
||||||
|
byte[] buffer = bos.toByteArray();
|
||||||
|
return buffer;
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.warn("inputStream transfer byte error,", e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (in != null) {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("clone inputStream error", e);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (bos != null) {
|
||||||
|
bos.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("clone outputStream error", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
package com.imdroid.sideslope.util;
|
||||||
|
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/19 20:17
|
||||||
|
*/
|
||||||
|
public class NumberUtils {
|
||||||
|
|
||||||
|
public static Double scaleTwo(String str) {
|
||||||
|
return BigDecimal.valueOf(Double.parseDouble(str)).setScale(2, RoundingMode.HALF_UP).doubleValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Double scaleTwo(Double value) {
|
||||||
|
return BigDecimal.valueOf(value).setScale(2, RoundingMode.HALF_UP).doubleValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Double scale(Double value, int scale) {
|
||||||
|
return BigDecimal.valueOf(value).setScale(scale, RoundingMode.HALF_UP).doubleValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String removeBrackets(String str) {
|
||||||
|
if (StringUtils.isEmpty(str)) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
return str.replaceAll("\\[", "").replaceAll("]", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,261 @@
|
|||||||
|
package com.imdroid.sideslope.util;
|
||||||
|
|
||||||
|
import com.imdroid.sideslope.bd.ByteUtil;
|
||||||
|
import com.imdroid.sideslope.bd.Gga;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import static java.lang.Math.*;
|
||||||
|
|
||||||
|
public class RtcmGgaUtil {
|
||||||
|
|
||||||
|
//gga样本:*后面跟的是校验和,其中76代表校验和,对$和*之间的数据(不包括这两个字符)按字节进行异或运算(二进制)的结果
|
||||||
|
private static final String ggaExample = "$GNGGA,020850.50,2258.10508,N,11317.67958,E,4,12,0.74,3.9,M,-5.4,M,1.3,0000*76";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取rtcm数据类型
|
||||||
|
* @param bytes
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static int getType(byte[] bytes){
|
||||||
|
String binaryStrFromByteArr = ByteUtil.getBinaryStrFromByteArr(bytes);
|
||||||
|
if(binaryStrFromByteArr.length() > 8 + 6 + 10 + 12){
|
||||||
|
String substring = binaryStrFromByteArr.substring(8 + 6 + 10, 8 + 6 + 10 + 12);
|
||||||
|
int i = ByteUtil.binaryToInt(substring);
|
||||||
|
return i;
|
||||||
|
}else{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String ggaMock(double lat, double lon){
|
||||||
|
String originLat = getOriginLatLon(lat);
|
||||||
|
String originLon = getOriginLatLon(lon);
|
||||||
|
StringBuilder sb = new StringBuilder(ggaExample);
|
||||||
|
sb.replace(sb.indexOf(",N,")-10,sb.indexOf(",N,"),originLat);
|
||||||
|
sb.replace(sb.indexOf(",E,")-11,sb.indexOf(",E,"),originLon);
|
||||||
|
String substring = sb.substring(sb.indexOf("$") + 1, sb.indexOf("*"));
|
||||||
|
byte[] bytes = substring.getBytes();
|
||||||
|
//校验位
|
||||||
|
byte b = bytes[0];
|
||||||
|
for (int i = 1; i < bytes.length; i++) {
|
||||||
|
b ^= bytes[i];
|
||||||
|
}
|
||||||
|
sb.replace(sb.length()-2,sb.length(),ByteUtil.byteToHexString(b));
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getGNGGAString(byte[] bytes){
|
||||||
|
String hex = ByteUtil.bytesToHexString(bytes);
|
||||||
|
int start = hex.indexOf("24474e474741");//$GNGGA
|
||||||
|
int end = hex.indexOf("0d0a");//\r\n
|
||||||
|
if(start != -1 && end > start){
|
||||||
|
String substring = hex.substring(start,end);
|
||||||
|
//System.out.println(new String(ByteUtil.hexStringTobyte(substring)));
|
||||||
|
return new String(ByteUtil.hexStringTobyte(substring));
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Gga getGga(String msg){
|
||||||
|
try{
|
||||||
|
String[] strings = msg.split(",");
|
||||||
|
double latitude = getLatLon(Double.parseDouble(strings[2]));
|
||||||
|
double longitude = getLatLon(Double.parseDouble(strings[4]));
|
||||||
|
double altitude = 100*(Double.parseDouble(strings[9]) + Double.parseDouble(strings[11]));
|
||||||
|
int status = Integer.parseInt(strings[6]);
|
||||||
|
return new Gga(latitude,longitude,altitude,status);
|
||||||
|
}catch (Exception e){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析阉割版gga,为了那点流量...
|
||||||
|
* @param msg
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Gga getGga2(String msg){
|
||||||
|
try{
|
||||||
|
String[] split = msg.split(",");
|
||||||
|
double lat = getLatLon(Double.parseDouble(split[1]));
|
||||||
|
double lon = getLatLon(Double.parseDouble(split[3]));
|
||||||
|
double altitude = Double.parseDouble(split[5]);
|
||||||
|
return new Gga(lat,lon,altitude,0);
|
||||||
|
}catch (Exception e){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析阉割版gga,为了那点流量...
|
||||||
|
* @param msg
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Gga getGga3(String msg){
|
||||||
|
try{
|
||||||
|
String[] split = msg.split(",");
|
||||||
|
double lat = getLatLon(Double.parseDouble(split[1]));
|
||||||
|
double lon = getLatLon(Double.parseDouble(split[3]));
|
||||||
|
int status = Integer.parseInt(split[5]);
|
||||||
|
double altitude = Double.parseDouble(split[6]);
|
||||||
|
return new Gga(lat,lon,altitude,status);
|
||||||
|
}catch (Exception e){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 求相对坐标
|
||||||
|
* @param gps_info
|
||||||
|
* @param origin
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static double[] ggaToXyz(Gga gps_info,Gga origin){
|
||||||
|
return ggaToXyz(gps_info,origin,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 求相对坐标
|
||||||
|
* @param gps_info
|
||||||
|
* @param origin
|
||||||
|
* @param angle 与北偏角
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static double[] ggaToXyz(Gga gps_info,Gga origin, double angle){
|
||||||
|
double Ea = 6378137 * 100; //赤道的半径,单位是cm
|
||||||
|
//cout << "Ea" << Ea << endl;
|
||||||
|
double Eb = 6356725 * 100; //极半径,单位是cm
|
||||||
|
double Db = 39940638; //极周长,单位是cm,如果直接 39940538*100 double类型会溢出,所以把*100放到 dN 的计算式中
|
||||||
|
//cout << "Db=" << Db << endl;
|
||||||
|
double R = Eb + (Ea - Eb) * (90 - origin.getLatitude()) / 90;
|
||||||
|
double pD = R * 2 * PI * cos(origin.getLatitude() * PI / 180);
|
||||||
|
double dE = pD * (gps_info.getLongitude() - origin.getLongitude()) / 360; //计算在正东方向上的位移
|
||||||
|
double dN = Db * (gps_info.getLatitude() - origin.getLatitude()) / 360 * 100; //计算在正北方向上的位移
|
||||||
|
//接下来根据场地的朝向来把朝东朝北的偏移转化成x方向和y方向的位移
|
||||||
|
//这个位移也就是车辆在场地中的x坐标和y坐标
|
||||||
|
double x = dE * cos(angle * PI / 180) - dN * sin(angle * PI / 180);
|
||||||
|
double y = dN * cos(angle * PI / 180) + dE * sin(angle * PI / 180);
|
||||||
|
double z = gps_info.getAltitude() - origin.getAltitude();
|
||||||
|
return new double[]{x,y,z};
|
||||||
|
}
|
||||||
|
|
||||||
|
//一度为60分
|
||||||
|
public static double getLatLon(Double location) {
|
||||||
|
if (location != 0.0) {
|
||||||
|
//int head = Integer.parseInt(String.valueOf(location).substring(0, 2));
|
||||||
|
int head = (int)(location/100);
|
||||||
|
// System.out.println(head);
|
||||||
|
return head + (location / 100 - head) * 10 / 6;
|
||||||
|
}
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//逆向转化
|
||||||
|
public static String getOriginLatLon(double latlon){
|
||||||
|
double result = 100*((int)latlon) + (latlon-(int)latlon)*6/10*100;
|
||||||
|
BigDecimal bd = new BigDecimal(result);
|
||||||
|
result = bd.setScale(5,BigDecimal.ROUND_HALF_EVEN).doubleValue();
|
||||||
|
return StringUtil.roundByScale(result, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 求航向角
|
||||||
|
* @param backLat
|
||||||
|
* @param backLon
|
||||||
|
* @param frontLat
|
||||||
|
* @param frontLon
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static double latLonToAngle(double backLat, double backLon, double frontLat, double frontLon){
|
||||||
|
double[] doubles = ggaToXyz(new Gga(frontLat, frontLon), new Gga(backLat, backLon));
|
||||||
|
double angle = Math.atan2(doubles[0],doubles[1]) * 180/ Math.PI;
|
||||||
|
angle = (angle + 360) % 360;
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 正北
|
||||||
|
* ^ ^ y轴
|
||||||
|
* \ |
|
||||||
|
* \ +-----------+ (x,y)
|
||||||
|
* \ | |
|
||||||
|
* \ | |
|
||||||
|
* \| |
|
||||||
|
* -------+-----------+---->
|
||||||
|
* origin| x轴
|
||||||
|
* |
|
||||||
|
*
|
||||||
|
* 求某一个坐标的经纬度
|
||||||
|
* @param x 单位厘米
|
||||||
|
* @param y
|
||||||
|
* @param origin 参考点的经纬度
|
||||||
|
* @param angle_from_north y轴与正北夹角
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Gga xyToGga(double x, double y, Gga origin, double angle_from_north){
|
||||||
|
double latitude1 = -x * sin(angle_from_north * PI /180)
|
||||||
|
+ y * cos(angle_from_north * PI /180);
|
||||||
|
double longitude1 = x / cos(angle_from_north * PI /180)
|
||||||
|
+ (y - (x * tan(angle_from_north * PI /180)))
|
||||||
|
* sin(angle_from_north * PI /180);
|
||||||
|
|
||||||
|
Gga ggaInfo1 = new Gga();
|
||||||
|
ggaInfo1.setLatitude(origin.getLatitude() + 0.000001);
|
||||||
|
ggaInfo1.setLongitude(origin.getLongitude());
|
||||||
|
Gga ggaInfo2 = new Gga();
|
||||||
|
ggaInfo2.setLatitude(origin.getLatitude());
|
||||||
|
ggaInfo2.setLongitude(origin.getLongitude() + 0.000001);
|
||||||
|
|
||||||
|
double[] location1 = ggaToXyz(ggaInfo1,origin);
|
||||||
|
double[] location2 = ggaToXyz(ggaInfo2,origin);
|
||||||
|
|
||||||
|
double a = location1[1];
|
||||||
|
double b = location2[0];
|
||||||
|
|
||||||
|
double latitude = latitude1 / a * 0.000001;
|
||||||
|
double longitude = longitude1 / b * 0.000001;
|
||||||
|
|
||||||
|
Gga ggaInfo = new Gga();
|
||||||
|
ggaInfo.setLatitude(origin.getLatitude() + latitude);
|
||||||
|
ggaInfo.setLongitude(origin.getLongitude() + longitude);
|
||||||
|
return ggaInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算两点之间距离,10厘米以下也能计算,精度更高,单位厘米,
|
||||||
|
*/
|
||||||
|
public static double getDistance2(double latitude, double longitude, double nowLatitude, double nowLongitude) {
|
||||||
|
Gga gga1 = new Gga(latitude, longitude);
|
||||||
|
Gga gga2 = new Gga(nowLatitude, nowLongitude);
|
||||||
|
double[] doubles = ggaToXyz(gga1, gga2);
|
||||||
|
return Math.sqrt(Math.pow(doubles[0],2) + Math.pow(doubles[1],2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算两点之间距离,单位米
|
||||||
|
*/
|
||||||
|
public static double getDistance(double sourceLat, double sourceLog, double desLat, double desLog) {
|
||||||
|
//转为弧度
|
||||||
|
double lat1 = (Math.PI / 180) * sourceLat;
|
||||||
|
double lat2 = (Math.PI / 180) * desLat;
|
||||||
|
|
||||||
|
double lon1 = (Math.PI / 180) * sourceLog;
|
||||||
|
double lon2 = (Math.PI / 180) * desLog;
|
||||||
|
|
||||||
|
//地球半径
|
||||||
|
double R = 6371.004;
|
||||||
|
|
||||||
|
//两点间距离 km,如果想要米的话,结果*1000
|
||||||
|
double d = Math.acos(Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1)) * R;
|
||||||
|
|
||||||
|
if (Double.isNaN(d * 1000)) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return d * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
package com.imdroid.sideslope.util;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class StringUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param data 指定字符串
|
||||||
|
* @param str 需要定位的特殊字符或者字符串
|
||||||
|
* @param num 第n次出现
|
||||||
|
* @return 第n次出现的位置索引
|
||||||
|
*/
|
||||||
|
public static int getIndexOf(String data,String str,int num){
|
||||||
|
Pattern pattern = Pattern.compile(str);
|
||||||
|
Matcher findMatcher = pattern.matcher(data);
|
||||||
|
//标记遍历字符串的位置
|
||||||
|
int indexNum=0;
|
||||||
|
while(findMatcher.find()) {
|
||||||
|
indexNum++;
|
||||||
|
if(indexNum==num){
|
||||||
|
return findMatcher.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//System.out.println("字符或者字符串"+str+"第"+num+"次出现的位置为:"+findMatcher.start());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保留小数点多少位,不足补零
|
||||||
|
* @param v
|
||||||
|
* @param scale 大于等于0
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String roundByScale(double v, int scale) {
|
||||||
|
if(scale == 0){
|
||||||
|
return new DecimalFormat("0").format(v);
|
||||||
|
}
|
||||||
|
String formatStr = "0.";
|
||||||
|
for(int i=0;i<scale;i++){
|
||||||
|
formatStr = formatStr + "0";
|
||||||
|
}
|
||||||
|
return new DecimalFormat(formatStr).format(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
package com.imdroid.sideslope.util;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
|
||||||
|
public class ThreadManager {
|
||||||
|
|
||||||
|
//单线程池
|
||||||
|
private static final Map<String, ExecutorService> mExecutorServiceMap = new HashMap<>();
|
||||||
|
private static final Object lock = new Object();
|
||||||
|
|
||||||
|
private static final class FixedThreadPoolHolder {
|
||||||
|
//固定线程池
|
||||||
|
static final ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ExecutorService getFixedThreadPool() {
|
||||||
|
return FixedThreadPoolHolder.fixedThreadPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class ScheduledThreadPoolHolder {
|
||||||
|
//定时线程池
|
||||||
|
static final ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ScheduledExecutorService getScheduledThreadPool() {
|
||||||
|
return ScheduledThreadPoolHolder.scheduledThreadPool;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static ExecutorService getSingleThreadPool(String name) {
|
||||||
|
ExecutorService singleThreadExecutor = mExecutorServiceMap.get(name);
|
||||||
|
if (singleThreadExecutor == null) {
|
||||||
|
synchronized (lock) {
|
||||||
|
singleThreadExecutor = mExecutorServiceMap.get(name);
|
||||||
|
if (singleThreadExecutor == null) {
|
||||||
|
singleThreadExecutor = Executors.newSingleThreadExecutor();
|
||||||
|
mExecutorServiceMap.put(name, singleThreadExecutor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return singleThreadExecutor;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
package com.imdroid.sideslope.util;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import cn.hutool.core.io.file.FileAppender;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备发送过来的错误消息记录器
|
||||||
|
* 错误消息:长度字段与实际消息体长度不匹配
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
* @date 2023/4/8 11:15
|
||||||
|
*/
|
||||||
|
public class WrongMessageRecorder {
|
||||||
|
|
||||||
|
private FileAppender appender;
|
||||||
|
|
||||||
|
public static final WrongMessageRecorder INSTANCE = new WrongMessageRecorder();
|
||||||
|
|
||||||
|
private WrongMessageRecorder() {
|
||||||
|
try {
|
||||||
|
String filePath = "/home/devop/runtime/sideslope_wrong_message_" + DateUtil.today() + ".log";
|
||||||
|
File file = new File(filePath);
|
||||||
|
if (!file.exists()) {
|
||||||
|
file.createNewFile();
|
||||||
|
}
|
||||||
|
appender = new FileAppender(file, 2, true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void append(String message) {
|
||||||
|
try {
|
||||||
|
appender.append(DateUtil.now() + ": " + message);
|
||||||
|
appender.flush();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,107 @@
|
|||||||
|
package com.imdroid.sideslope.web;
|
||||||
|
|
||||||
|
import com.imdroid.sideslope.calc.GNSSCalcService;
|
||||||
|
import com.imdroid.sideslope.server.DeviceChannel;
|
||||||
|
import com.imdroid.sideslope.server.OnlineChannels;
|
||||||
|
import com.imdroid.sideslope.util.DataTypeUtil;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author LiGang
|
||||||
|
* @date 2023/9/24 10:01
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
public class ApiController {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(ApiController.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private GNSSCalcService gnssCalcService;
|
||||||
|
|
||||||
|
@RequestMapping(value = "/config")
|
||||||
|
public HttpResp config(String deviceId, String configuration) {
|
||||||
|
Map<String, Object> status = new HashMap<>();
|
||||||
|
HttpResp resp = new HttpResp();
|
||||||
|
OnlineChannels.INSTANCE
|
||||||
|
.get(deviceId)
|
||||||
|
.filter(DeviceChannel::isOnline)
|
||||||
|
.ifPresent(x -> {
|
||||||
|
status.put("status", "Online");
|
||||||
|
status.put("lastUpdate", x.getLastTime());
|
||||||
|
// send command
|
||||||
|
ByteBuf buf = Unpooled.buffer();
|
||||||
|
byte[] data = getBinaryData(ConfigDataTypeEnum.JSON, configuration);
|
||||||
|
logger.info("send command:{}", configuration);
|
||||||
|
buf.writeBytes(data);
|
||||||
|
x.writeAndFlush(buf);
|
||||||
|
});
|
||||||
|
if (status.isEmpty()) {
|
||||||
|
status.put("status", "Offline");
|
||||||
|
resp.setResponseCode("-10001");
|
||||||
|
resp.setResponseMessage("Offline.");
|
||||||
|
} else {
|
||||||
|
resp.setResponseMessage("Command sent.");
|
||||||
|
}
|
||||||
|
resp.setResponseObject(status);
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/gnssconfig")
|
||||||
|
public HttpResp gnssConfig(String deviceId, String configuration) {
|
||||||
|
Map<String, Object> status = new HashMap<>();
|
||||||
|
HttpResp resp = new HttpResp();
|
||||||
|
OnlineChannels.INSTANCE
|
||||||
|
.get(deviceId)
|
||||||
|
.filter(DeviceChannel::isOnline)
|
||||||
|
.ifPresent(x -> {
|
||||||
|
status.put("status", "Online");
|
||||||
|
status.put("lastUpdate", x.getLastTime());
|
||||||
|
// send command
|
||||||
|
ByteBuf buf = Unpooled.buffer();
|
||||||
|
byte[] data = getBinaryData(ConfigDataTypeEnum.HEX, configuration);
|
||||||
|
logger.info("send command:{}", configuration);
|
||||||
|
buf.writeBytes(data);
|
||||||
|
x.writeAndFlush(buf);
|
||||||
|
});
|
||||||
|
if (status.isEmpty()) {
|
||||||
|
status.put("status", "Offline");
|
||||||
|
resp.setResponseCode("-10001");
|
||||||
|
resp.setResponseMessage("Offline.");
|
||||||
|
} else {
|
||||||
|
resp.setResponseMessage("Command sent.");
|
||||||
|
}
|
||||||
|
resp.setResponseObject(status);
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/clean-tilt")
|
||||||
|
public HttpResp config(String deviceId) {
|
||||||
|
// 清空指定设备的惯导值
|
||||||
|
gnssCalcService.cleanTiltByDeviceId(deviceId);
|
||||||
|
HttpResp resp = new HttpResp();
|
||||||
|
resp.setResponseMessage("succeed");
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] getBinaryData(ConfigDataTypeEnum dataTypeEnum, String text) {
|
||||||
|
if (dataTypeEnum == ConfigDataTypeEnum.HEX) {
|
||||||
|
return DataTypeUtil.hexStringToBytes(text);
|
||||||
|
} else if (dataTypeEnum == ConfigDataTypeEnum.JSON) {
|
||||||
|
String content = URLDecoder.decode(text);
|
||||||
|
return content.getBytes(StandardCharsets.UTF_8);
|
||||||
|
} else {
|
||||||
|
return text.getBytes(StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
package com.imdroid.sideslope.web;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Layton
|
||||||
|
* @date 2023/2/13 19:20
|
||||||
|
*/
|
||||||
|
public enum ConfigDataTypeEnum {
|
||||||
|
|
||||||
|
HEX, JSON;
|
||||||
|
}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
package com.imdroid.sideslope.web;
|
||||||
|
|
||||||
|
public class HttpResp<T> {
|
||||||
|
private String responseCode = "10000";
|
||||||
|
private String responseMessage;
|
||||||
|
private String responseType;
|
||||||
|
private int rows;
|
||||||
|
private T responseObject;
|
||||||
|
|
||||||
|
public String getResponseCode() {
|
||||||
|
return responseCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResponseCode(String responseCode) {
|
||||||
|
this.responseCode = responseCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResponseMessage() {
|
||||||
|
return responseMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResponseMessage(String responseMessage) {
|
||||||
|
this.responseMessage = responseMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResponseType() {
|
||||||
|
return responseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResponseType(String responseType) {
|
||||||
|
this.responseType = responseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRows() {
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRows(int rows) {
|
||||||
|
this.rows = rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getResponseObject() {
|
||||||
|
return responseObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResponseObject(T responseObject) {
|
||||||
|
this.responseObject = responseObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
sec-beidou-rtcm/src/main/resources/application.properties
Normal file
29
sec-beidou-rtcm/src/main/resources/application.properties
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
server.port=9904
|
||||||
|
server.servlet.context-path=/gnss
|
||||||
|
|
||||||
|
spring.application.name=bis-gnss
|
||||||
|
spring.application.build=20230924
|
||||||
|
|
||||||
|
spring.jpa.show-sql = true
|
||||||
|
spring.jpa.hibernate.ddl-auto = none
|
||||||
|
spring.jpa.database-platform = org.hibernate.dialect.MySQLDialect
|
||||||
|
spring.datasource.url = jdbc:mysql://localhost:3306/bis-device?characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
|
||||||
|
spring.datasource.username = root
|
||||||
|
spring.datasource.password =
|
||||||
|
spring.datasource.driverClassName = com.mysql.cj.jdbc.Driver
|
||||||
|
|
||||||
|
spring.jackson.dateFormat = yyyy-MM-dd HH:mm:ss
|
||||||
|
spring.jackson.time-zone = GMT+8
|
||||||
|
|
||||||
|
# rabbitmq
|
||||||
|
spring.rabbitmq.host=127.0.0.1
|
||||||
|
spring.rabbitmq.port=5672
|
||||||
|
spring.rabbitmq.username=guest
|
||||||
|
spring.rabbitmq.password=guest
|
||||||
|
spring.rabbitmq.virtualHost=/
|
||||||
|
|
||||||
|
netty.port=9903
|
||||||
|
|
||||||
|
app.format.date = yyyy-MM-dd
|
||||||
|
app.format.time = HH:mm:ss
|
||||||
|
app.format.datetime = yyyy-MM-dd HH:mm:ss
|
||||||
27
sec-beidou-rtcm/src/main/resources/logback.xml
Normal file
27
sec-beidou-rtcm/src/main/resources/logback.xml
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<configuration scan="true" scanPeriod="30 seconds">
|
||||||
|
<property name="LOG_HOME" value="/opt/log"/>
|
||||||
|
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n"/>
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||||
|
<pattern>${LOG_PATTERN}</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${LOG_HOME}/sideslopertcm.log</file>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>${LOG_HOME}/sideslopertcm.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||||
|
<maxFileSize>10MB</maxFileSize>
|
||||||
|
<maxHistory>20</maxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
|
||||||
|
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||||
|
<pattern>${LOG_PATTERN}</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="debug">
|
||||||
|
<appender-ref ref="STDOUT" />
|
||||||
|
</root>
|
||||||
|
<logger name="org.springframework" level="warn" />
|
||||||
|
</configuration>
|
||||||
48
sec-beidou-rtcm/src/test/java/UBXTest.java
Normal file
48
sec-beidou-rtcm/src/test/java/UBXTest.java
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import com.imdroid.sideslope.bd.FocusCalculator;
|
||||||
|
import com.imdroid.sideslope.bd.UBXUtil;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class UBXTest {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
test();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void test() throws IOException {
|
||||||
|
//读取本地数据模拟
|
||||||
|
/* FileInputStream fileInputStream = new FileInputStream("2023-02-02-151826.txt");
|
||||||
|
int mSize = 0;
|
||||||
|
int temp;
|
||||||
|
List<Byte> mList = new ArrayList<>();
|
||||||
|
FocusCalculator focusCalculator = new FocusCalculator(150,null,null);
|
||||||
|
while ((temp = fileInputStream.read()) != -1){
|
||||||
|
mList.add((byte)temp); //添加数据
|
||||||
|
mSize++;
|
||||||
|
if (mList.size() >= 2 && mList.get(mSize - 2) == '\r' && mList.get(mSize - 1) == '\n') {
|
||||||
|
byte[] bytes = new byte[mList.size() - 2];
|
||||||
|
for (int i = 0; i < bytes.length; i++) {
|
||||||
|
bytes[i] = mList.get(i);
|
||||||
|
}
|
||||||
|
//提取得到b562数据
|
||||||
|
double[] doubles = UBXUtil.dataAnalysis(bytes,16);
|
||||||
|
//计算到单次相对位置xyz并记录
|
||||||
|
System.out.println(Arrays.toString(doubles));
|
||||||
|
focusCalculator.addXyz(doubles);
|
||||||
|
mList.clear();
|
||||||
|
mSize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//融合
|
||||||
|
double[] result = focusCalculator.resultB562(null);
|
||||||
|
if(result != null){
|
||||||
|
System.out.println("result:"+ Arrays.toString(result));
|
||||||
|
}
|
||||||
|
fileInputStream.close();*/
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
162
sec-beidou/pom.xml
Normal file
162
sec-beidou/pom.xml
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.imdroid</groupId>
|
||||||
|
<artifactId>security-monitor</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<groupId>com.imdroid</groupId>
|
||||||
|
<artifactId>sec-beidou</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<name>beidou</name>
|
||||||
|
<description>beidou</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<java.version>8</java.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- <dependency>-->
|
||||||
|
<!-- <groupId>org.springframework.boot</groupId>-->
|
||||||
|
<!-- <artifactId>spring-boot-starter-security</artifactId>-->
|
||||||
|
<!-- </dependency>-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.thymeleaf.extras</groupId>
|
||||||
|
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.yulichang</groupId>
|
||||||
|
<artifactId>mybatis-plus-join-boot-starter</artifactId>
|
||||||
|
<version>1.4.3</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||||
|
<version>3.5.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
<version>8.0.24</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.security</groupId>
|
||||||
|
<artifactId>spring-security-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>netty-all</artifactId>
|
||||||
|
<version>4.1.85.Final</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>fastjson</artifactId>
|
||||||
|
<version>1.2.76</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.pagehelper</groupId>
|
||||||
|
<artifactId>pagehelper</artifactId>
|
||||||
|
<version>4.1.6</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt</artifactId>
|
||||||
|
<version>0.9.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
<version>2.9.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- apache http client -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
<version>4.5.7</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- request parameters validate -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.validation</groupId>
|
||||||
|
<artifactId>jakarta.validation-api</artifactId>
|
||||||
|
<version>2.0.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- aliyun oss -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun.oss</groupId>
|
||||||
|
<artifactId>aliyun-sdk-oss</artifactId>
|
||||||
|
<version>3.10.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.imdroid</groupId>
|
||||||
|
<artifactId>sec-api</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<excludes>
|
||||||
|
<exclude>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</exclude>
|
||||||
|
</excludes>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>central</id>
|
||||||
|
<name>ali-mirror</name>
|
||||||
|
<url>https://maven.aliyun.com/repository/central</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
</project>
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
package com.imdroid.beidou;
|
||||||
|
|
||||||
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@SpringBootApplication(scanBasePackages = {"com.imdroid"})
|
||||||
|
@MapperScan({"com.imdroid.secapi","com.imdroid.beidou.entity"})
|
||||||
|
public class BeidouApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(BeidouApplication.class, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
package com.imdroid.beidou;
|
||||||
|
|
||||||
|
import com.imdroid.beidou.common.HttpResult;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@ControllerAdvice
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
|
||||||
|
@ExceptionHandler(Exception.class)
|
||||||
|
@ResponseBody
|
||||||
|
public HttpResult handleException(Exception e) {
|
||||||
|
log.error("全局捕获异常:", e);
|
||||||
|
return HttpResult.fail(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
package com.imdroid.beidou.auth;
|
||||||
|
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
import org.springframework.web.servlet.ModelAndView;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录拦截器
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class AuthInterceptor implements HandlerInterceptor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||||
|
String username = SessionUtils.getCurrentUser(request);
|
||||||
|
if (!StringUtils.isEmpty(username)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
response.sendRedirect("/login");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
package com.imdroid.beidou.auth;
|
||||||
|
|
||||||
|
import com.imdroid.beidou.entity.Tenant;
|
||||||
|
import com.imdroid.beidou.entity.User;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* session 工具类
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
public class SessionUtils {
|
||||||
|
|
||||||
|
public static final String SESSION_CURRENT_USER = "login_user";
|
||||||
|
|
||||||
|
public static String getCurrentUser(HttpServletRequest request) {
|
||||||
|
return (String) request.getSession().getAttribute(SESSION_CURRENT_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setCurrentUser(HttpServletRequest request, User user, Tenant tenant) {
|
||||||
|
HttpSession session = request.getSession();
|
||||||
|
session.setAttribute(SESSION_CURRENT_USER, user.getName());
|
||||||
|
session.setAttribute("tenant_id", user.getTenant_id());
|
||||||
|
session.setAttribute("tenant_name", tenant.getName());
|
||||||
|
session.setAttribute("role", user.getRole());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Integer getTenantId(HttpServletRequest request) {
|
||||||
|
return (Integer) request.getSession().getAttribute("tenant_id");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getRole(HttpServletRequest request) {
|
||||||
|
return (String) request.getSession().getAttribute("role");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
package com.imdroid.beidou.auth;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录拦截器配置
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class WebMvcConfig implements WebMvcConfigurer {
|
||||||
|
|
||||||
|
private final AuthInterceptor authInterceptor;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
|
registry.addInterceptor(authInterceptor)
|
||||||
|
.addPathPatterns("/**")
|
||||||
|
.excludePathPatterns("/**/*.js","/**/*.css","/**/*.jpg","/**/*.png", "/do_login", "/mini-register", "/login");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
package com.imdroid.beidou.common;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class HttpResult implements Serializable {
|
||||||
|
public static int HTTP_RSP_OK = 0;
|
||||||
|
public static int HTTP_RSP_FAILED = 1;
|
||||||
|
public static int HTTP_RSP_USER_NOT_EXIST = 2;
|
||||||
|
int code;
|
||||||
|
String msg;
|
||||||
|
Object data;
|
||||||
|
|
||||||
|
public static String result(int code, String msg) {
|
||||||
|
HttpResult rsp = new HttpResult();
|
||||||
|
rsp.code = code;
|
||||||
|
rsp.msg = msg;
|
||||||
|
return JSONObject.toJSONString(rsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String ok() {
|
||||||
|
return result(HTTP_RSP_OK, "ok");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String failed() {
|
||||||
|
return result(HTTP_RSP_FAILED, "failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HttpResult success(Object data) {
|
||||||
|
return new HttpResult(HTTP_RSP_OK, "ok", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HttpResult fail(String msg) {
|
||||||
|
return new HttpResult(HTTP_RSP_FAILED, msg, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HttpResult fail(int code, String msg) {
|
||||||
|
return new HttpResult(code, msg, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
15
sec-beidou/src/main/java/com/imdroid/beidou/common/Role.java
Normal file
15
sec-beidou/src/main/java/com/imdroid/beidou/common/Role.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package com.imdroid.beidou.common;
|
||||||
|
|
||||||
|
/****************************************
|
||||||
|
* 1)系统管理员:ADMIN,所有权限,并且可以设置自己的企业ID
|
||||||
|
* 2)企业管理员:MANAGER,本企业内数据的查改增删、增加和删除本企业的账号、查看操作日志。
|
||||||
|
* 不能看设备消息和设置设备数据LOG
|
||||||
|
* 3)普通用户:USER,本企业内的数据查看和设备配置
|
||||||
|
* 用户角色以字节传到页面,bit1:admin;bit2:manager;bit3:user
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Role {
|
||||||
|
public static final String ADMIN = "ADMIN";
|
||||||
|
public static final String MANAGER = "MANAGER";
|
||||||
|
public static final String USER = "USER";
|
||||||
|
}
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
package com.imdroid.beidou.config;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 阿里云oss配置类
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "aliyun.oss")
|
||||||
|
public class AliyunOssProperties {
|
||||||
|
|
||||||
|
private String endpoint;
|
||||||
|
|
||||||
|
private String accessKey;
|
||||||
|
|
||||||
|
private String accessSecret;
|
||||||
|
|
||||||
|
private String bucket;
|
||||||
|
|
||||||
|
private String publicReadUrl;
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
package com.imdroid.beidou.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信小程序配置
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties("app.bis")
|
||||||
|
public class WxMiniProperties {
|
||||||
|
|
||||||
|
private String appid;
|
||||||
|
|
||||||
|
private String secret;
|
||||||
|
|
||||||
|
|
||||||
|
public String getAppid() {
|
||||||
|
return appid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppid(String appid) {
|
||||||
|
this.appid = appid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSecret() {
|
||||||
|
return secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSecret(String secret) {
|
||||||
|
this.secret = secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package com.imdroid.beidou.controller;
|
||||||
|
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 利用HTTP Session保存会话期的用户信息,并发送到页面,用于显示控制
|
||||||
|
*/
|
||||||
|
public class BasicController {
|
||||||
|
public static int QUERY_ALL = -1;
|
||||||
|
|
||||||
|
public void initModel(Model m, HttpSession session)
|
||||||
|
{
|
||||||
|
String role = (String) session.getAttribute("role");
|
||||||
|
int tenant_id = (int) session.getAttribute("tenant_id");
|
||||||
|
m.addAttribute("login_user", session.getAttribute("login_user"));
|
||||||
|
m.addAttribute("role", role);
|
||||||
|
m.addAttribute("tenant_id", tenant_id);
|
||||||
|
m.addAttribute("tenant_name", session.getAttribute("tenant_name"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,189 @@
|
|||||||
|
package com.imdroid.beidou.controller;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.github.pagehelper.PageHelper;
|
||||||
|
import com.github.pagehelper.PageInfo;
|
||||||
|
import com.github.pagehelper.StringUtil;
|
||||||
|
import com.imdroid.beidou.common.HttpResult;
|
||||||
|
import com.imdroid.beidou.data.vo.device.DeviceInstallVO;
|
||||||
|
import com.imdroid.beidou.data.vo.device.DeviceStatusVO;
|
||||||
|
import com.imdroid.beidou.entity.*;
|
||||||
|
import com.imdroid.secapi.dto.*;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class GnssDeviceController extends BasicController{
|
||||||
|
@Autowired
|
||||||
|
GnssGroupMapper gnssGroupMapper;
|
||||||
|
@Autowired
|
||||||
|
GnssGroupCalcMapper gnssGroupCalcMapper;
|
||||||
|
@Autowired
|
||||||
|
GnssGroupFwdMapper gnssGroupFwdMapper;
|
||||||
|
@Autowired
|
||||||
|
GnssDeviceMapper gnssDeviceMapper;
|
||||||
|
@Autowired
|
||||||
|
TenantMapper tenantMapper;
|
||||||
|
@Autowired
|
||||||
|
private GnssStatusMapper gnssStatusMapper;
|
||||||
|
|
||||||
|
/**** 推送页面 *****/
|
||||||
|
@RequestMapping("/page/gnss_dev_cfg")
|
||||||
|
public String gnssDevCfg(Model m, HttpSession session)throws Exception {
|
||||||
|
initModel(m, session);
|
||||||
|
|
||||||
|
return "/page/gnss_dev_cfg";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/page/table/gnss_add_dev")
|
||||||
|
public String gnssUpdateDev(Model m)throws Exception {
|
||||||
|
//以下用于下拉框数据
|
||||||
|
List<GnssGroup> gnssGroups = gnssGroupMapper.selectList(null);
|
||||||
|
List<GnssGroupCalc> gnssGroupCalcs = gnssGroupCalcMapper.selectList(null);
|
||||||
|
List<GnssGroupFwd> gnssGroupFwds = gnssGroupFwdMapper.selectList(null);
|
||||||
|
List<Tenant> tenants = tenantMapper.selectList(null);
|
||||||
|
|
||||||
|
m.addAttribute("tenant_list", tenants);
|
||||||
|
m.addAttribute("gnss_group_list", gnssGroups);
|
||||||
|
m.addAttribute("gnss_group_calc_list", gnssGroupCalcs);
|
||||||
|
m.addAttribute("gnss_group_fwd_list", gnssGroupFwds);
|
||||||
|
|
||||||
|
return "/page/table/gnss_add_dev";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**** 推送数据 *****/
|
||||||
|
@RequestMapping("/gnss/device/list")
|
||||||
|
@ResponseBody
|
||||||
|
public JSONObject list(HttpSession session, int page, int limit, String searchParams) {
|
||||||
|
PageHelper.startPage(page, limit);
|
||||||
|
QueryWrapper<GnssDevice> queryWrapper = new QueryWrapper<>();
|
||||||
|
|
||||||
|
// 条件查询
|
||||||
|
if(searchParams != null) {
|
||||||
|
JSONObject search = (JSONObject) JSONObject.parse(searchParams);
|
||||||
|
//设备号
|
||||||
|
String deviceid = search.getString("deviceid");
|
||||||
|
if (StringUtil.isNotEmpty(deviceid)) {
|
||||||
|
queryWrapper.like("deviceid", deviceid);
|
||||||
|
}
|
||||||
|
//父设备号
|
||||||
|
String parentid = search.getString("parentid");
|
||||||
|
if (StringUtil.isNotEmpty(parentid)) {
|
||||||
|
queryWrapper.like("parentid", parentid);
|
||||||
|
}
|
||||||
|
//设备类型
|
||||||
|
Integer devicetype = search.getInteger("devicetype");
|
||||||
|
if (devicetype != null && devicetype != QUERY_ALL) {
|
||||||
|
queryWrapper.eq("devicetype", devicetype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<GnssDevice> cs = gnssDeviceMapper.selectList(queryWrapper);
|
||||||
|
PageInfo<GnssDevice> pageInfo = new PageInfo<>(cs);
|
||||||
|
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
jsonObject.put("code", 0);
|
||||||
|
jsonObject.put("msg", "");
|
||||||
|
jsonObject.put("count", pageInfo.getTotal());
|
||||||
|
jsonObject.put("data", pageInfo.getList());
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/gnss/device/update")
|
||||||
|
@ResponseBody
|
||||||
|
public String update(HttpSession session, @RequestBody JSONObject object) throws Exception {
|
||||||
|
// 从请求参数中创建对象
|
||||||
|
GnssDevice device = JSONObject.toJavaObject(object,GnssDevice.class);
|
||||||
|
QueryWrapper<Tenant> tenantQueryWrapper = new QueryWrapper<>();
|
||||||
|
tenantQueryWrapper.eq("name", device.getTenantname());
|
||||||
|
Tenant tenant = tenantMapper.selectOne(tenantQueryWrapper);
|
||||||
|
if(tenant==null) return HttpResult.result(2, "invalid tenant");
|
||||||
|
device.setTenantid(tenant.getId());
|
||||||
|
device.setUpdatetime(new Timestamp(System.currentTimeMillis()));
|
||||||
|
device.setUpdateuser((String) session.getAttribute("login_user"));
|
||||||
|
|
||||||
|
// 检测该对象是否已存在
|
||||||
|
QueryWrapper<GnssDevice> wrapper = new QueryWrapper<>();
|
||||||
|
wrapper.eq("deviceid",device.getDeviceid());
|
||||||
|
GnssDevice old_device = gnssDeviceMapper.selectOne(wrapper);
|
||||||
|
//新增或更新
|
||||||
|
int num = 0;
|
||||||
|
if(null != old_device) {
|
||||||
|
device.setId(old_device.getId());
|
||||||
|
device.setCreateuser(old_device.getCreateuser());
|
||||||
|
device.setCreatetime(old_device.getCreatetime());
|
||||||
|
num = gnssDeviceMapper.updateById(device);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
device.setCreatetime(new Timestamp(System.currentTimeMillis()));
|
||||||
|
device.setCreateuser((String) session.getAttribute("login_user"));
|
||||||
|
num = gnssDeviceMapper.insert(device); //id自增
|
||||||
|
}
|
||||||
|
if (num == 0) {
|
||||||
|
return HttpResult.failed();
|
||||||
|
} else return HttpResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/gnss/device/delete")
|
||||||
|
@ResponseBody
|
||||||
|
public String delete(@RequestParam String del_id) throws Exception {
|
||||||
|
QueryWrapper<GnssDevice> wrapper = new QueryWrapper<>();
|
||||||
|
wrapper.eq("deviceid",del_id);
|
||||||
|
int num = gnssDeviceMapper.delete(wrapper);
|
||||||
|
if (num == 0) {
|
||||||
|
return HttpResult.failed();
|
||||||
|
} else return HttpResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备现场安装
|
||||||
|
*
|
||||||
|
* @param deviceInstallVO 设备安装信息
|
||||||
|
* @return HttpResult
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@PostMapping("/gnss/device/install")
|
||||||
|
@ResponseBody
|
||||||
|
public HttpResult install(@Validated DeviceInstallVO deviceInstallVO) throws Exception {
|
||||||
|
QueryWrapper<GnssDevice> wrapper = new QueryWrapper<>();
|
||||||
|
wrapper.eq("deviceid",deviceInstallVO.getDeviceId());
|
||||||
|
GnssDevice gnssDevice = gnssDeviceMapper.selectOne(wrapper);
|
||||||
|
if (gnssDevice == null) {
|
||||||
|
return HttpResult.fail("");
|
||||||
|
}
|
||||||
|
GnssDevice tempDevice = new GnssDevice();
|
||||||
|
tempDevice.setId(gnssDevice.getId());
|
||||||
|
//安装位置通过GNSS坐标自动获取
|
||||||
|
//tempDevice.setLocation(deviceInstallVO.getLocation());
|
||||||
|
tempDevice.setPictures(deviceInstallVO.getPictures());
|
||||||
|
gnssDeviceMapper.updateById(tempDevice);
|
||||||
|
|
||||||
|
return HttpResult.success(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据主键id查找设备信息
|
||||||
|
*
|
||||||
|
* @param id 主键id
|
||||||
|
* @return 设备信息 DeviceStatusVO
|
||||||
|
*/
|
||||||
|
@PostMapping("/gnss/device/status")
|
||||||
|
@ResponseBody
|
||||||
|
public HttpResult findById(Long id) {
|
||||||
|
GnssDevice gnssDevice = gnssDeviceMapper.selectById(id);
|
||||||
|
if (gnssDevice == null) {
|
||||||
|
return HttpResult.fail("");
|
||||||
|
}
|
||||||
|
GnssStatusJoin gnssStatus = gnssStatusMapper.queryByDeviceId(gnssDevice.getDeviceid());
|
||||||
|
DeviceStatusVO deviceStatusVO = new DeviceStatusVO(gnssDevice, gnssStatus);
|
||||||
|
return HttpResult.success(deviceStatusVO);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,168 @@
|
|||||||
|
package com.imdroid.beidou.controller;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.github.pagehelper.PageHelper;
|
||||||
|
import com.github.pagehelper.PageInfo;
|
||||||
|
import com.imdroid.beidou.common.HttpResult;
|
||||||
|
import com.imdroid.beidou.entity.*;
|
||||||
|
import com.imdroid.secapi.dto.GnssGroup;
|
||||||
|
import com.imdroid.secapi.dto.GnssGroupMapper;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class GnssGroupController {
|
||||||
|
@Autowired
|
||||||
|
GnssGroupMapper gnssGroupMapper;
|
||||||
|
@Autowired
|
||||||
|
GnssGroupCalcMapper gnssGroupCalcMapper;
|
||||||
|
@Autowired
|
||||||
|
GnssGroupFwdMapper gnssGroupFwdMapper;
|
||||||
|
|
||||||
|
/********* 推送页面 *********/
|
||||||
|
@RequestMapping("/page/table/gnss_add_group")
|
||||||
|
public String gnssAddGroup()throws Exception {
|
||||||
|
return "/page/table/gnss_add_group";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/page/table/gnss_add_group_calc")
|
||||||
|
public String gnssAddCalcGroup()throws Exception {
|
||||||
|
return "/page/table/gnss_add_group_calc";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/page/table/gnss_add_group_fwd")
|
||||||
|
public String gnssAddPushGroup()throws Exception {
|
||||||
|
return "/page/table/gnss_add_group_fwd";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/page/gnss_group_cfg")
|
||||||
|
public String gnssGroupCfg()throws Exception {
|
||||||
|
return "/page/gnss_group_cfg";
|
||||||
|
}
|
||||||
|
|
||||||
|
/********* 基本参数组 *********/
|
||||||
|
@RequestMapping("/gnss/group/list")
|
||||||
|
@ResponseBody
|
||||||
|
public JSONObject list(int page, int limit) {
|
||||||
|
PageHelper.startPage(page, limit);
|
||||||
|
List<GnssGroup> cs = gnssGroupMapper.selectList(null);
|
||||||
|
PageInfo<GnssGroup> pageInfo = new PageInfo<>(cs);
|
||||||
|
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
jsonObject.put("code", 0);
|
||||||
|
jsonObject.put("msg", "");
|
||||||
|
jsonObject.put("count", pageInfo.getTotal());
|
||||||
|
jsonObject.put("data", pageInfo.getList());
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/gnss/group/update")
|
||||||
|
@ResponseBody
|
||||||
|
public String update(@RequestBody JSONObject object) throws Exception {
|
||||||
|
int num = 0;
|
||||||
|
GnssGroup group = JSONObject.toJavaObject(object,GnssGroup.class);
|
||||||
|
if(null != gnssGroupMapper.selectById(group.getId())) {
|
||||||
|
num = gnssGroupMapper.updateById(group);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
num = gnssGroupMapper.insert(group);
|
||||||
|
}
|
||||||
|
if (num == 0) {
|
||||||
|
return HttpResult.failed();
|
||||||
|
} else return HttpResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/gnss/group/delete")
|
||||||
|
@ResponseBody
|
||||||
|
public String delete(@RequestParam int del_id) throws Exception {
|
||||||
|
int num = gnssGroupMapper.deleteById(del_id);
|
||||||
|
if (num == 0) {
|
||||||
|
return HttpResult.failed();
|
||||||
|
} else return HttpResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
/********* 解算参数组 *********/
|
||||||
|
@RequestMapping("/gnss/group/list_calc")
|
||||||
|
@ResponseBody
|
||||||
|
public JSONObject listCalc(int page, int limit) {
|
||||||
|
PageHelper.startPage(page, limit);
|
||||||
|
List<GnssGroupCalc> cs = gnssGroupCalcMapper.selectList(null);
|
||||||
|
PageInfo<GnssGroupCalc> pageInfo = new PageInfo<>(cs);
|
||||||
|
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
jsonObject.put("code", 0);
|
||||||
|
jsonObject.put("msg", "");
|
||||||
|
jsonObject.put("count", pageInfo.getTotal());
|
||||||
|
jsonObject.put("data", pageInfo.getList());
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/gnss/group/update_calc")
|
||||||
|
@ResponseBody
|
||||||
|
public String updateCalc(@RequestBody JSONObject object) throws Exception {
|
||||||
|
int num = 0;
|
||||||
|
GnssGroupCalc group = JSONObject.toJavaObject(object,GnssGroupCalc.class);
|
||||||
|
if(null != gnssGroupCalcMapper.selectById(group.getId())) {
|
||||||
|
num = gnssGroupCalcMapper.updateById(group);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
num = gnssGroupCalcMapper.insert(group);
|
||||||
|
}
|
||||||
|
if (num == 0) {
|
||||||
|
return HttpResult.failed();
|
||||||
|
} else return HttpResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/gnss/group/delete_calc")
|
||||||
|
@ResponseBody
|
||||||
|
public String deleteCalc(@RequestParam int del_id) throws Exception {
|
||||||
|
int num = gnssGroupCalcMapper.deleteById(del_id);
|
||||||
|
if (num == 0) {
|
||||||
|
return HttpResult.failed();
|
||||||
|
} else return HttpResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
/********* 转发参数组 *********/
|
||||||
|
@RequestMapping("/gnss/group/list_fwd")
|
||||||
|
@ResponseBody
|
||||||
|
public JSONObject listFwd(int page, int limit) {
|
||||||
|
PageHelper.startPage(page, limit);
|
||||||
|
List<GnssGroupFwd> cs = gnssGroupFwdMapper.selectList(null);
|
||||||
|
PageInfo<GnssGroupFwd> pageInfo = new PageInfo<>(cs);
|
||||||
|
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
jsonObject.put("code", 0);
|
||||||
|
jsonObject.put("msg", "");
|
||||||
|
jsonObject.put("count", pageInfo.getTotal());
|
||||||
|
jsonObject.put("data", pageInfo.getList());
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/gnss/group/update_fwd")
|
||||||
|
@ResponseBody
|
||||||
|
public String updateFwd(@RequestBody JSONObject object) throws Exception {
|
||||||
|
int num = 0;
|
||||||
|
GnssGroupFwd group = JSONObject.toJavaObject(object,GnssGroupFwd.class);
|
||||||
|
if(null != gnssGroupFwdMapper.selectById(group.getId())) {
|
||||||
|
num = gnssGroupFwdMapper.updateById(group);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
num = gnssGroupFwdMapper.insert(group);
|
||||||
|
}
|
||||||
|
if (num == 0) {
|
||||||
|
return HttpResult.failed();
|
||||||
|
} else return HttpResult.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/gnss/group/delete_fwd")
|
||||||
|
@ResponseBody
|
||||||
|
public String deleteFwd(@RequestParam int del_id) throws Exception {
|
||||||
|
int num = gnssGroupFwdMapper.deleteById(del_id);
|
||||||
|
if (num == 0) {
|
||||||
|
return HttpResult.failed();
|
||||||
|
} else return HttpResult.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
package com.imdroid.beidou.controller;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
import com.github.pagehelper.PageHelper;
|
||||||
|
import com.github.pagehelper.StringUtil;
|
||||||
|
import com.github.yulichang.query.MPJQueryWrapper;
|
||||||
|
import com.imdroid.secapi.dto.GnssStatus;
|
||||||
|
import com.imdroid.secapi.dto.GnssStatusJoin;
|
||||||
|
import com.imdroid.secapi.dto.GnssStatusMapper;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class GnssStatusController extends BasicController{
|
||||||
|
@Autowired
|
||||||
|
GnssStatusMapper gnssStatusMapper;
|
||||||
|
|
||||||
|
/**** 推送页面 *****/
|
||||||
|
@RequestMapping("/page/gnss_status")
|
||||||
|
public String gnssStatus(Model m, HttpSession session)throws Exception {
|
||||||
|
initModel(m, session);
|
||||||
|
|
||||||
|
return "/page/gnss_status";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**** 推送数据 *****/
|
||||||
|
@RequestMapping("/gnss/status/list")
|
||||||
|
@ResponseBody
|
||||||
|
public JSONObject list(HttpSession session, int page, int limit, String searchParams) {
|
||||||
|
PageHelper.startPage(page, limit);
|
||||||
|
|
||||||
|
MPJQueryWrapper wrapper = new MPJQueryWrapper<GnssStatus>()
|
||||||
|
.selectAll(GnssStatus.class)
|
||||||
|
.select("d.devicetype as devicetype","d.tenantid as tenantid")
|
||||||
|
.leftJoin("gnssdevices d on t.deviceid = d.deviceid");
|
||||||
|
|
||||||
|
// 条件查询
|
||||||
|
if(searchParams != null) {
|
||||||
|
JSONObject search = (JSONObject) JSONObject.parse(searchParams);
|
||||||
|
//设备号
|
||||||
|
String deviceid = search.getString("deviceid");
|
||||||
|
if (StringUtil.isNotEmpty(deviceid)) {
|
||||||
|
wrapper.like("deviceid", deviceid);
|
||||||
|
}
|
||||||
|
//状态
|
||||||
|
Integer state = search.getInteger("state");
|
||||||
|
if(state!=null && state != QUERY_ALL){
|
||||||
|
wrapper.eq("state", state);
|
||||||
|
}
|
||||||
|
//告警
|
||||||
|
Integer warning = search.getInteger("warning");
|
||||||
|
if(warning!=null && warning != QUERY_ALL){
|
||||||
|
wrapper.eq("warning", warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//分页查询 (需要启用 mybatis plus 分页插件)
|
||||||
|
Page<GnssStatusJoin> listPage = gnssStatusMapper.selectJoinPage(new Page<>(page, limit), GnssStatusJoin.class, wrapper);
|
||||||
|
|
||||||
|
JSONObject jsonObject = new JSONObject();
|
||||||
|
jsonObject.put("code", 0);
|
||||||
|
jsonObject.put("msg", "");
|
||||||
|
jsonObject.put("count", listPage.getTotal());
|
||||||
|
jsonObject.put("data", listPage.getRecords());
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
package com.imdroid.beidou.controller;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class LayuiController extends BasicController{
|
||||||
|
@RequestMapping("/login")
|
||||||
|
public String login() throws Exception {
|
||||||
|
return "/login";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/")
|
||||||
|
public String index0()throws Exception {
|
||||||
|
return "/index";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/index")
|
||||||
|
public String index()throws Exception {
|
||||||
|
return "/index";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/page/device_overview")
|
||||||
|
public String deviceOverview()throws Exception {
|
||||||
|
return "/page/device_overview";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/page/gnss_data_calc")
|
||||||
|
public String gnssDataCalc()throws Exception {
|
||||||
|
return "/page/gnss_data_calc";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/page/gnss_data_raw")
|
||||||
|
public String gnssDataRaw()throws Exception {
|
||||||
|
return "/page/gnss_data_raw";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/page/gnss_data_tools")
|
||||||
|
public String gnssDataTools()throws Exception {
|
||||||
|
return "/page/gnss_data_tools";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@RequestMapping("/page/gnss_msg")
|
||||||
|
public String gnssMsg()throws Exception {
|
||||||
|
return "/page/gnss_msg";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/page/gnss_msg_status")
|
||||||
|
public String gnssMsgStatus()throws Exception {
|
||||||
|
return "/page/gnss_msg_status";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/page/gnss_msg_trx")
|
||||||
|
public String gnssMsgTrx()throws Exception {
|
||||||
|
return "/page/gnss_msg_trx";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/page/warning")
|
||||||
|
public String warning()throws Exception {
|
||||||
|
return "/page/warning";
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,120 @@
|
|||||||
|
package com.imdroid.beidou.controller;
|
||||||
|
|
||||||
|
import com.imdroid.beidou.auth.SessionUtils;
|
||||||
|
import com.imdroid.beidou.common.HttpResult;
|
||||||
|
import com.imdroid.beidou.data.WxMiniUserSession;
|
||||||
|
import com.imdroid.beidou.data.vo.MiniUserRegisterVO;
|
||||||
|
import com.imdroid.beidou.data.vo.MiniUserVO;
|
||||||
|
import com.imdroid.beidou.data.vo.UserLoginVO;
|
||||||
|
import com.imdroid.beidou.entity.Tenant;
|
||||||
|
import com.imdroid.beidou.entity.TenantMapper;
|
||||||
|
import com.imdroid.beidou.entity.User;
|
||||||
|
import com.imdroid.beidou.entity.UserMapper;
|
||||||
|
import com.imdroid.beidou.utils.WXUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
@RequestMapping
|
||||||
|
@RestController
|
||||||
|
public class LoginController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserMapper userMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TenantMapper tenantMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WXUtils wxUtils;
|
||||||
|
|
||||||
|
@PostMapping(value = "/do_login")
|
||||||
|
@ResponseBody
|
||||||
|
public HttpResult login(UserLoginVO userLoginVO, HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||||
|
if (UserLoginVO.LOGIN_TYPE_MINI.equals(userLoginVO.getType())) {
|
||||||
|
// 小程序登录
|
||||||
|
WxMiniUserSession wxMiniUserSession = wxUtils.getMiniProgramUserOpenid(userLoginVO.getCode());
|
||||||
|
if (wxMiniUserSession == null) {
|
||||||
|
return HttpResult.fail("用户code错误");
|
||||||
|
}
|
||||||
|
User user = userMapper.queryByOpenid(wxMiniUserSession.getOpenid());
|
||||||
|
if (user == null) {
|
||||||
|
return HttpResult.fail(HttpResult.HTTP_RSP_USER_NOT_EXIST, "用户不存在");
|
||||||
|
}
|
||||||
|
Tenant tenant = tenantMapper.selectById(user.getTenant_id());
|
||||||
|
SessionUtils.setCurrentUser(request, user, tenant);
|
||||||
|
|
||||||
|
return HttpResult.success(buildMiniUser(user, tenant));
|
||||||
|
} else {
|
||||||
|
// web登录
|
||||||
|
User user = userMapper.queryByName(userLoginVO.getUsername());
|
||||||
|
if (user == null) {
|
||||||
|
return HttpResult.fail("用户不存在");
|
||||||
|
}
|
||||||
|
if (!user.getPassword().equals(userLoginVO.getPassword())) {
|
||||||
|
return HttpResult.fail("用户名或密码错误");
|
||||||
|
}
|
||||||
|
Tenant tenant = tenantMapper.selectById(user.getTenant_id());
|
||||||
|
SessionUtils.setCurrentUser(request, user, tenant);
|
||||||
|
//response.sendRedirect("/index"); //发这条没用,会导致login.html收不到应答,也跳转不了
|
||||||
|
HttpResult rsp = HttpResult.success(null);
|
||||||
|
return HttpResult.success(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private MiniUserVO buildMiniUser(User user, Tenant tenant) {
|
||||||
|
MiniUserVO miniUserVO = new MiniUserVO();
|
||||||
|
miniUserVO.setUsername(user.getUsername());
|
||||||
|
miniUserVO.setMobile(user.getMobile());
|
||||||
|
miniUserVO.setNickName(user.getNickname());
|
||||||
|
miniUserVO.setAvatarUrl(user.getAvatar_url());
|
||||||
|
miniUserVO.setTenantName(tenant.getName());
|
||||||
|
return miniUserVO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序用户注册
|
||||||
|
*
|
||||||
|
* @param miniUserRegisterVO miniUserRegisterVO
|
||||||
|
* @return HttpResult
|
||||||
|
*/
|
||||||
|
@PostMapping(value = "/mini-register")
|
||||||
|
public HttpResult miniUserRegister(@Validated MiniUserRegisterVO miniUserRegisterVO) {
|
||||||
|
WxMiniUserSession wxMiniUserSession = wxUtils.getMiniProgramUserOpenid(miniUserRegisterVO.getCode());
|
||||||
|
if (wxMiniUserSession == null) {
|
||||||
|
return HttpResult.fail("用户code错误");
|
||||||
|
}
|
||||||
|
User user = userMapper.queryByOpenid(wxMiniUserSession.getOpenid());
|
||||||
|
if (user != null) {
|
||||||
|
return HttpResult.fail("用户已注册");
|
||||||
|
}
|
||||||
|
user = userMapper.queryByMobile(miniUserRegisterVO.getMobile());
|
||||||
|
if (user == null) {
|
||||||
|
return HttpResult.fail(HttpResult.HTTP_RSP_USER_NOT_EXIST, "用户不存在");
|
||||||
|
}
|
||||||
|
// 更新用户信息
|
||||||
|
User newUser = new User();
|
||||||
|
newUser.setId(user.getId());
|
||||||
|
newUser.setAvatar_url(miniUserRegisterVO.getAvatarUrl());
|
||||||
|
newUser.setOpenid(wxMiniUserSession.getOpenid());
|
||||||
|
newUser.setNickname(miniUserRegisterVO.getNickName());
|
||||||
|
userMapper.updateById(newUser);
|
||||||
|
|
||||||
|
return HttpResult.success(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/do_logout")
|
||||||
|
public void logout(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||||
|
request.getSession().invalidate();
|
||||||
|
response.sendRedirect("/login");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
package com.imdroid.beidou.controller;
|
||||||
|
|
||||||
|
import com.imdroid.beidou.common.HttpResult;
|
||||||
|
import com.imdroid.beidou.utils.AliyunOssUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件上次接口
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/file")
|
||||||
|
public class OssFileController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AliyunOssUtils aliyunOssUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传文件通用接口
|
||||||
|
*
|
||||||
|
* @param multipartFile multipartFile
|
||||||
|
* @return HttpResult
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
@RequestMapping("/upload")
|
||||||
|
public HttpResult upload(@RequestParam("file") MultipartFile multipartFile) throws Exception {
|
||||||
|
String filename = multipartFile.getOriginalFilename();
|
||||||
|
String url = aliyunOssUtils.uploadFile(multipartFile, filename, "common");
|
||||||
|
return HttpResult.success(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传设备现场安装图片,保存到oss
|
||||||
|
*
|
||||||
|
* @param multipartFile multipartFile
|
||||||
|
* @return HttpResult
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
@RequestMapping("/upload-device-image")
|
||||||
|
public HttpResult upload(@RequestParam("file") MultipartFile multipartFile, String deviceId) throws Exception {
|
||||||
|
String filename = deviceId + "_" + UUID.randomUUID().toString().replace("-", "") + ".jpg";
|
||||||
|
String url = aliyunOssUtils.uploadFile(multipartFile, filename, "device-img");
|
||||||
|
return HttpResult.success(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
package com.imdroid.beidou.data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
public class WxMiniUserSession {
|
||||||
|
|
||||||
|
private String sessionKey;
|
||||||
|
private String openid;
|
||||||
|
|
||||||
|
public WxMiniUserSession() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public WxMiniUserSession(String sessionKey, String openid) {
|
||||||
|
this.sessionKey = sessionKey;
|
||||||
|
this.openid = openid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSessionKey() {
|
||||||
|
return sessionKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSessionKey(String sessionKey) {
|
||||||
|
this.sessionKey = sessionKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOpenid() {
|
||||||
|
return openid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOpenid(String openid) {
|
||||||
|
this.openid = openid;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
package com.imdroid.beidou.data.vo;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序用户注册VO
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class MiniUserRegisterVO {
|
||||||
|
|
||||||
|
|
||||||
|
@NotBlank(message = "用户code不能为空")
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
@NotBlank(message = "用户头像不能为空")
|
||||||
|
private String avatarUrl;
|
||||||
|
|
||||||
|
@NotBlank(message = "手机号不能为空")
|
||||||
|
private String mobile;
|
||||||
|
|
||||||
|
@NotBlank(message = "昵称不能为空")
|
||||||
|
private String nickName;
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package com.imdroid.beidou.data.vo;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序用户信息VO
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class MiniUserVO {
|
||||||
|
|
||||||
|
private String avatarUrl;
|
||||||
|
|
||||||
|
private String mobile;
|
||||||
|
|
||||||
|
private String nickName;
|
||||||
|
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
private String tenantName;
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package com.imdroid.beidou.data.vo;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户登录VO
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class UserLoginVO {
|
||||||
|
|
||||||
|
public static final String LOGIN_TYPE_WEB = "web";
|
||||||
|
|
||||||
|
public static final String LOGIN_TYPE_MINI = "mini";
|
||||||
|
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序用户code
|
||||||
|
*/
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
package com.imdroid.beidou.data.vo.device;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备现场安装VO类
|
||||||
|
*
|
||||||
|
* @author LiGang
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class DeviceInstallVO {
|
||||||
|
|
||||||
|
@NotBlank(message = "设备编号不能为空")
|
||||||
|
private String deviceId;
|
||||||
|
|
||||||
|
@NotBlank(message = "设备安装位置的经纬度不能为空")
|
||||||
|
private String location;
|
||||||
|
|
||||||
|
@NotBlank(message = "现场图片不能为空")
|
||||||
|
private String pictures;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,85 @@
|
|||||||
|
package com.imdroid.beidou.data.vo.device;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import com.imdroid.secapi.dto.GnssDevice;
|
||||||
|
import com.imdroid.secapi.dto.GnssStatusJoin;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author LiGang
|
||||||
|
* @date 2023/10/13 21:50
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class DeviceStatusVO {
|
||||||
|
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String deviceId;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String location;
|
||||||
|
|
||||||
|
private String pictures;
|
||||||
|
|
||||||
|
private String tenantName;
|
||||||
|
|
||||||
|
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
private Date latestDataTime;
|
||||||
|
|
||||||
|
private Float roll;
|
||||||
|
private Float pitch;
|
||||||
|
private Float yaw;
|
||||||
|
private Integer rssi;
|
||||||
|
private Integer voltage;
|
||||||
|
private Float temperature;
|
||||||
|
private Float humidity;
|
||||||
|
private Integer txbytes;
|
||||||
|
private Integer rxbytes;
|
||||||
|
private Integer b562bytes;
|
||||||
|
private Integer d3xxbytes;
|
||||||
|
private Integer satelliteinview;
|
||||||
|
private Integer satelliteinuse;
|
||||||
|
|
||||||
|
private Short dtuState;
|
||||||
|
|
||||||
|
|
||||||
|
public DeviceStatusVO() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeviceStatusVO(GnssDevice gnssDevice, GnssStatusJoin gnssStatus) {
|
||||||
|
this.id = gnssDevice.getId();
|
||||||
|
this.deviceId = gnssDevice.getDeviceid();
|
||||||
|
this.name = gnssDevice.getName();
|
||||||
|
//this.location = gnssDevice.getLocation();
|
||||||
|
this.pictures = gnssDevice.getPictures();
|
||||||
|
this.tenantName = gnssDevice.getTenantname();
|
||||||
|
//this.latestDataTime = gnssDevice.getLatest_data_time();
|
||||||
|
|
||||||
|
if (gnssStatus != null) {
|
||||||
|
this.latestDataTime = gnssStatus.getUpdatetime();
|
||||||
|
this.location = gnssStatus.getLocation();
|
||||||
|
this.roll = gnssStatus.getRoll();
|
||||||
|
this.pitch = gnssStatus.getPitch();
|
||||||
|
this.yaw = gnssStatus.getYaw();
|
||||||
|
this.rssi = gnssStatus.getRssi();
|
||||||
|
this.voltage = gnssStatus.getVoltage();
|
||||||
|
this.temperature = gnssStatus.getTemperature();
|
||||||
|
this.humidity = gnssStatus.getHumidity();
|
||||||
|
this.txbytes = gnssStatus.getTxbytes();
|
||||||
|
this.rxbytes = gnssStatus.getRxbytes();
|
||||||
|
this.d3xxbytes = gnssStatus.getD3xxbytes();
|
||||||
|
this.b562bytes = gnssStatus.getB562bytes();
|
||||||
|
this.satelliteinview = gnssStatus.getSatelliteinview();
|
||||||
|
this.satelliteinuse = gnssStatus.getSatelliteinuse();
|
||||||
|
this.dtuState = gnssStatus.getState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package com.imdroid.beidou.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName(value = "gnssgroupcalc")
|
||||||
|
public class GnssGroupCalc {
|
||||||
|
int id;
|
||||||
|
int long_cycle;
|
||||||
|
int short_cycle;
|
||||||
|
float shock;
|
||||||
|
float h_weight;
|
||||||
|
float v_weight;
|
||||||
|
int device_num;
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
package com.imdroid.beidou.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface GnssGroupCalcMapper extends BaseMapper<GnssGroupCalc> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package com.imdroid.beidou.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName(value = "gnssgroupfwd")
|
||||||
|
public class GnssGroupFwd {
|
||||||
|
int id;
|
||||||
|
String description;
|
||||||
|
String addr;
|
||||||
|
int port;
|
||||||
|
String fwd_template;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user