1、增加组织配置

2、把util模块从rtcm模块中分离出来,供其他模块共用
This commit is contained in:
weidong 2023-12-19 17:56:03 +08:00
parent a6c2d58461
commit 240ee77768
60 changed files with 977 additions and 850 deletions

View File

@ -10,11 +10,152 @@
</parent> </parent>
<artifactId>sec-beidou-fwd</artifactId> <artifactId>sec-beidou-fwd</artifactId>
<packaging>jar</packaging>
<properties> <properties>
<maven.compiler.source>11</maven.compiler.source> <maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target> <maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<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>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>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</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>com.imdroid</groupId>
<artifactId>sec-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 矩阵工具 -->
<dependency>
<groupId>org.ejml</groupId>
<artifactId>ejml-all</artifactId>
<version>0.41</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</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> </project>

View File

@ -1,4 +1,4 @@
package entity; package com.imdroid.beidou_fwd.entity;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;

View File

@ -1,4 +1,4 @@
package entity; package com.imdroid.beidou_fwd.entity;
import java.util.List; import java.util.List;

View File

@ -1,4 +1,4 @@
package entity; package com.imdroid.beidou_fwd.entity;
import java.util.List; import java.util.List;

View File

@ -0,0 +1,4 @@
package com.imdroid.beidou_fwd.service;
public class HTTPClient {
}

View File

@ -0,0 +1,100 @@
package com.imdroid.beidou_fwd.service;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;
public class TCPClient {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
//@Value("${xfz.server.host}")
private String host="171.106.48.63";
//@Value("${xfz.server.port}")
private int port=52000;
//@Value("${xfz.server.data.send}")
private boolean send=true;
private Bootstrap bootstrap;
private EventLoopGroup group;
private Channel channel;
public void start() {
new Thread(this::connect, "xfz-tcp-client").start();
}
private void init() {
//客户端需要一个事件循环组
group = new NioEventLoopGroup();
//创建客户端启动对象
// bootstrap 可重用, 只需在NettyClient实例化的时候初始化即可.
bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
//加入处理器
ch.pipeline().addLast(new TcpMessageHandler(TCPClient.this));
}
});
}
public void connect() {
logger.info("netty client starting");
//启动客户端去连接服务器端
try {
ChannelFuture cf = bootstrap.connect(host, port);
cf.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
//重连交给后端线程执行
future.channel().eventLoop().schedule(() -> {
logger.info("xfz tcp client reconnect");
try {
connect();
} catch (Exception e) {
e.printStackTrace();
}
}, 3000, TimeUnit.MILLISECONDS);
} else {
logger.info("xfz tcp client start success!");
}
}
});
//对通道关闭进行监听
this.channel = cf.channel();
this.channel.closeFuture().sync();
} catch (Exception e) {
logger.error("xfz netty client error:", e);
}
}
public void writeAndFlush(String json) {
if (!send) {
return;
}
String str = "#" + json + "!";
ByteBuf buf = Unpooled.buffer();
buf.writeBytes(str.getBytes(StandardCharsets.UTF_8));
channel.writeAndFlush(buf).addListener(future -> {
if (future.isSuccess()) {
logger.info("send {} to xfz server succeed.", str);
} else {
logger.info("send {} to xfz server failed.", str);
}
});
}
}

View File

@ -0,0 +1,50 @@
package com.imdroid.beidou_fwd.service;
import com.imdroid.common.util.DataTypeUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author Layton
* @date 2023/2/18 20:36
*/
public class TcpMessageHandler extends SimpleChannelInboundHandler<ByteBuf> {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final TCPClient tcpClient;
public TcpMessageHandler(TCPClient tcpClient) {
this.tcpClient = tcpClient;
}
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf buf) throws Exception {
if (logger.isDebugEnabled()) {
byte[] data = new byte[buf.readableBytes()];
buf.getBytes(0, data);
logger.debug("receive server message:" + DataTypeUtil.getHexString(data));
}
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
logger.info("xfz tcp channel active");
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
logger.info("xfz tcp channel inactive");
tcpClient.connect();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
logger.error("XFZTcpMessageHandler error: {}", cause.toString());
ctx.close();
}
}

View File

@ -0,0 +1,4 @@
package com.imdroid.beidou_fwd.service;
public class TemplateRegister {
}

View File

@ -0,0 +1,4 @@
package com.imdroid.beidou_fwd.service;
public class UDPClient {
}

View File

@ -1,4 +1,4 @@
package task; package com.imdroid.beidou_fwd.task;
public class ThirdPartyForwarder { public class ThirdPartyForwarder {
public void forward(){ public void forward(){

View File

@ -1,4 +0,0 @@
package service;
public class HTTPClient {
}

View File

@ -1,4 +0,0 @@
package service;
public class TCPClient {
}

View File

@ -1,4 +0,0 @@
package service;
public class TemplateRegister {
}

View File

@ -1,4 +0,0 @@
package service;
public class UDPClient {
}

View File

@ -108,6 +108,11 @@
<artifactId>sec-api</artifactId> <artifactId>sec-api</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>com.imdroid</groupId>
<artifactId>sec-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>

View File

@ -1,22 +0,0 @@
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();
}
}

View File

@ -1,7 +1,8 @@
package com.imdroid.sideslope.util; package com.imdroid.sideslope.bd;
import com.imdroid.sideslope.bd.ByteUtil;
import com.imdroid.sideslope.bd.Gga; import com.imdroid.common.util.ByteUtil;
import com.imdroid.common.util.StringUtil;
import java.math.BigDecimal; import java.math.BigDecimal;

View File

@ -0,0 +1,216 @@
package com.imdroid.sideslope.calc;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.imdroid.secapi.dto.*;
import com.imdroid.sideslope.sal.Device;
import com.imdroid.sideslope.sal.DeviceService;
import com.imdroid.common.util.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
@Service
public class GNSSCalcFilterService {
private final Logger logger = LoggerFactory.getLogger(GNSSCalcFilterService.class);
@Resource(name = "local")
DeviceService gnssDeviceRepository;
@Autowired
private GnssGroupCalcMapper groupCalcMapper;
@Autowired
private GnssCalcDataMapper repository;
public static final int FILTER_MIN_CYCLE_HOUR = 2;
public static final int FILTER_DEFAULT_CYCLE_HOUR = 8;
static final int FILTER_MIN_RECORD_NUM = 10;
static final float XY_THRESHOLD = 30; //水平异常点30mm
static final float Z_THRESHOLD = 30; //高程异常点30mm
static final float AUTO_THRESHOLD = 50; //触发自适应滤波的门限50mm
static class VaryFilterCycle{
public LocalDateTime startTime;
public int filterCycleHour;
}
final private ConcurrentHashMap<String, VaryFilterCycle> autoCycleDevices = new ConcurrentHashMap<>();
final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public void calc(GnssCalcData locationRecord, boolean isExceed) {
String deviceId = locationRecord.getDeviceid();
Device gnssDevice = gnssDeviceRepository.findByDeviceId(deviceId);
if(gnssDevice == null) return;
//补充解算记录的设备信息
locationRecord.setTenantid(gnssDevice.getTenantId());
locationRecord.setEnabled(true);
// 获取平滑参数
GnssGroupCalc groupCalc = getCalcParams(gnssDevice.getCalcGroupId());
// 计算平滑周期
int filterCycle = groupCalc.getFilter_hour();
VaryFilterCycle varyCycle = autoCycleDevices.get(deviceId);
if(varyCycle!=null){
filterCycle = varyCycle.filterCycleHour;
}
// 平滑处理
calcFilterLocation(locationRecord, filterCycle,
groupCalc.getXy_threshold(), groupCalc.getZ_threshold());
repository.insert(locationRecord);
// 更新平滑周期
if(groupCalc.getAuto_filter()) {
refreshFilterCycle(deviceId, groupCalc, locationRecord);
}
}
GnssGroupCalc getCalcParams(int calcGroupId){
GnssGroupCalc calcParam = groupCalcMapper.selectById(calcGroupId);
if(calcParam == null){
calcParam = new GnssGroupCalc();
calcParam.setAuto_filter(false);
calcParam.setFilter_hour(FILTER_DEFAULT_CYCLE_HOUR);
calcParam.setFilter_min_hour(FILTER_MIN_CYCLE_HOUR);
calcParam.setXy_threshold(XY_THRESHOLD);
calcParam.setZ_threshold(Z_THRESHOLD);
calcParam.setAuto_threshold(AUTO_THRESHOLD);
}
return calcParam;
}
/**
* 计算东北天的最近融合数据的加权平均, 刘畅20230725 copy avgEND; id>20, 滤波参数6h 25h
*/
public boolean calcFilterLocation(GnssCalcData newRecord, int filterCycleHour, float xyThreshold, float zThreshold){
String deviceId = newRecord.getDeviceid();
// 选取[newRecordTime-filterCycleHour, newRcordTime]之间的记录做平滑
// 如果这个时间段的记录数少于FILTER_MIN_RECORD_NUM本次不做平滑
LocalDateTime newRecordTime = newRecord.getCreatetime();
LocalDateTime filterAfterTime = newRecordTime.minusHours(filterCycleHour);
QueryWrapper<GnssCalcData> query = new QueryWrapper<>();
query.eq("deviceid", deviceId);
query.ge("createtime", filterAfterTime.format(dateFormatter));
query.le("createtime", newRecordTime.format(dateFormatter));
query.orderByDesc("createtime");
List<GnssCalcData> gnssDeviceLocationRecords = repository.selectList(query);
if(gnssDeviceLocationRecords.size() == 0){
//第一个点无参考当作坏点处理
newRecord.setEnabled(false);
}
else {
GnssCalcData record0 = gnssDeviceLocationRecords.get(0);
// 检查是不是坏点
if (Math.abs(newRecord.getB562e() - record0.getB562e()) > xyThreshold ||
Math.abs(newRecord.getB562n() - record0.getB562n()) > xyThreshold ||
Math.abs(newRecord.getB562d() - record0.getB562d()) > zThreshold) {
newRecord.setEnabled(false); //记录为坏点下次不参与滤波
logger.info(deviceId + " abnormal gnss data");
}
else {
// 求本组和最近recordNum组原始值的平均值
double sumE = newRecord.getB562e();
double sumN = newRecord.getB562n();
double sumD = newRecord.getB562d();
int count = 1;
for (GnssCalcData record : gnssDeviceLocationRecords) {
if (record.getEnabled()) {//只选取好点参与滤波
sumE += record.getB562e();
sumN += record.getB562n();
sumD += record.getB562d();
count++;
}
}
logger.info(deviceId + " filter records num: " + count);
if (count >= FILTER_MIN_RECORD_NUM) {
newRecord.setRb562e(NumberUtils.scaleTwo(sumE / count));
newRecord.setRb562n(NumberUtils.scaleTwo(sumN / count));
newRecord.setRb562d(NumberUtils.scaleTwo(sumD / count));
return true;
}
}
}
return false;
}
void refreshFilterCycle(String deviceId, GnssGroupCalc groupCalc, GnssCalcData curCalcData){
LocalDateTime now = LocalDateTime.now();
VaryFilterCycle varyCycle = autoCycleDevices.get(deviceId);
// 如果当前处于变周期阶段则根据时间调整周期
if(varyCycle != null){
if(varyCycle.filterCycleHour >= groupCalc.getFilter_hour()){
//变周期结束
autoCycleDevices.remove(deviceId);
}
else {
if (now.isAfter(varyCycle.startTime.plusHours(1))) {
varyCycle.filterCycleHour++;
varyCycle.startTime = now;
logger.info(deviceId + ": refresh filter cycle "+varyCycle.filterCycleHour);
}
}
}
// 否则判断是否将进入变周期
else{
// 比较当前均值和FilterMinHour前的均值之差是否超过门限
LocalDateTime cmpTime = now.minusHours(groupCalc.getFilter_min_hour());
QueryWrapper<GnssCalcData> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("deviceid", deviceId);
queryWrapper.ge("createtime",cmpTime.format(dateFormatter));
queryWrapper.last("limit 1");
GnssCalcData gnssCalcData = repository.selectOne(queryWrapper);
if(gnssCalcData != null && gnssCalcData.getEnabled()){
if(gnssCalcData.getRb562e()!=null && gnssCalcData.getRb562d()!=null){
double gapE = Math.abs(gnssCalcData.getRb562e() - curCalcData.getRb562e());
double gapN = Math.abs(gnssCalcData.getRb562n() - curCalcData.getRb562n());
if(gapE>=groupCalc.getAuto_threshold() || gapN>=groupCalc.getAuto_threshold()){
VaryFilterCycle varyCycle1 = new VaryFilterCycle();
varyCycle1.startTime = now;
varyCycle1.filterCycleHour = groupCalc.getFilter_min_hour();
autoCycleDevices.put(deviceId, varyCycle1);
logger.info(deviceId + ": filter cycle change to "+varyCycle1.filterCycleHour);
}
}
}
}
}
public LocalDateTime updateRb562(String deviceId, LocalDateTime afterTime){
// 获取平滑参数
Device gnssDevice = gnssDeviceRepository.findByDeviceId(deviceId);
if(gnssDevice == null) return afterTime;
GnssGroupCalc groupCalc = getCalcParams(gnssDevice.getCalcGroupId());
// 平滑处理
LocalDateTime beforTime = afterTime.plusHours(groupCalc.getFilter_hour());
QueryWrapper<GnssCalcData> query = new QueryWrapper<>();
query.eq("deviceid", deviceId);
query.le("createtime", beforTime.format(dateFormatter));
query.ge("createtime", afterTime.format(dateFormatter));
query.orderByAsc("createtime");
LocalDateTime lastTime = afterTime;
List<GnssCalcData> calcDataListToUpdate = repository.selectList(query);
for(GnssCalcData calcData:calcDataListToUpdate){
if(calcData.getEnabled()) {
calcFilterLocation(calcData, groupCalc.getFilter_hour(),
groupCalc.getXy_threshold(), groupCalc.getZ_threshold());
repository.updateById(calcData);
lastTime = calcData.getCreatetime();
logger.info(deviceId + " update rb562");
}
}
return lastTime;
}
}

View File

@ -25,7 +25,8 @@ public class MultiLineGNSSCalcService {
SingleLineGNSSCalcService calcService; SingleLineGNSSCalcService calcService;
@Autowired @Autowired
private GNSSDeviceLocationRecordService dataPersistService; private GNSSDeviceLocationRecordService dataPersistService;
@Autowired
GNSSCalcFilterService gnssCalcFilterService;
@Autowired @Autowired
private FwdRecordMapper fwdRecordMapper; private FwdRecordMapper fwdRecordMapper;
@ -47,7 +48,7 @@ public class MultiLineGNSSCalcService {
// 计算上轮结果 // 计算上轮结果
calcService.calSingleDone(deviceId, d342Message.getTenantId(),lastDate); calcService.calSingleDone(deviceId, d342Message.getTenantId(),lastDate);
// 重算最近的 // 重算最近的
lastDate = dataPersistService.updateRb562(deviceId,lastDate); lastDate = gnssCalcFilterService.updateRb562(deviceId,lastDate);
// 记录转发表更新为upload done // 记录转发表更新为upload done
FwdRecord fwdRecord = fwdRecordMap.get(deviceId); FwdRecord fwdRecord = fwdRecordMap.get(deviceId);
if(fwdRecord != null){ if(fwdRecord != null){

View File

@ -39,12 +39,12 @@ public class SingleLineGNSSCalcService implements GNSSCalcService {
private static final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(4); private static final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(4);
@Resource(name = "local")
private DeviceService deviceService;
@Autowired @Autowired
WarningService warningService; WarningService warningService;
@Autowired
GNSSCalcFilterService gnssCalcFilterService;
@Override @Override
public double[] calcSingle(D341LocationMessage message, boolean completeWhenIdle) { public double[] calcSingle(D341LocationMessage message, boolean completeWhenIdle) {
String deviceId = message.getId(); String deviceId = message.getId();
@ -168,18 +168,9 @@ public class SingleLineGNSSCalcService implements GNSSCalcService {
} }
locationRecord.setPps(delay); locationRecord.setPps(delay);
deviceService.postLocationRecord(locationRecord, isShocked); gnssCalcFilterService.calc(locationRecord, isShocked);
} }
/*
@Override
public double[] calcResult(String deviceId,double[] b562Xyz, double[] tiltXyz) {
FocusCalculator1 focusCalculator = calculatorMap.get(deviceId);
if (focusCalculator != null) {
return focusCalculator.ekfResult(b562Xyz,tiltXyz);
}
return null;
}
*/
@Override @Override
public Tilt calcAvgTilt(String deviceId) { public Tilt calcAvgTilt(String deviceId) {
FocusCalculator1 focusCalculator = calculatorMap.get(deviceId); FocusCalculator1 focusCalculator = calculatorMap.get(deviceId);

View File

@ -1,7 +1,7 @@
package com.imdroid.sideslope.executor; package com.imdroid.sideslope.executor;
import com.imdroid.secapi.client.BeidouClient; import com.imdroid.secapi.client.BeidouClient;
import com.imdroid.sideslope.bd.ByteUtil; import com.imdroid.common.util.ByteUtil;
import com.imdroid.sideslope.message.D31xConfigAckMessage; import com.imdroid.sideslope.message.D31xConfigAckMessage;
import com.imdroid.sideslope.sal.Device; import com.imdroid.sideslope.sal.Device;
import com.imdroid.sideslope.sal.DeviceService; import com.imdroid.sideslope.sal.DeviceService;

View File

@ -37,6 +37,7 @@ public class D331RtcmMessageExecutor implements Executor<D331RtcmMessage, Void>
String id = message.getId(); String id = message.getId();
byte[] forwardBytes = message.getSrcData(); byte[] forwardBytes = message.getSrcData();
// 要求快速转发因此用缓存不要每次都查数据库
List<Device> deviceList = deviceService.findByParentId(id); List<Device> deviceList = deviceService.findByParentId(id);
for (Device device : deviceList) { for (Device device : deviceList) {
String deviceId = device.getDeviceId(); String deviceId = device.getDeviceId();

View File

@ -5,7 +5,7 @@ import com.imdroid.sideslope.message.D341LocationMessage;
import com.imdroid.sideslope.sal.Device; import com.imdroid.sideslope.sal.Device;
import com.imdroid.sideslope.sal.DeviceService; import com.imdroid.sideslope.sal.DeviceService;
import com.imdroid.sideslope.service.GNSSDeviceLocationRecordService; import com.imdroid.sideslope.service.GNSSDeviceLocationRecordService;
import com.imdroid.sideslope.util.ThreadManager; import com.imdroid.common.util.ThreadManager;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -34,7 +34,7 @@ public class D341LocationMessageExecutor implements Executor<D341LocationMessage
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug("receive d341 location message of device:{}", message.getId()); logger.debug("receive d341 location message of device:{}", message.getId());
} }
// 补齐tenantId // 补齐tenantId要求快速处理因此用缓存不要每次都查数据库
Device device = deviceService.findByDeviceId(message.getId()); Device device = deviceService.findByDeviceId(message.getId());
if(device == null) return null; if(device == null) return null;
message.setTenantId(device.getTenantId()); message.setTenantId(device.getTenantId());

View File

@ -4,7 +4,7 @@ import com.imdroid.sideslope.calc.MultiLineGNSSCalcService;
import com.imdroid.sideslope.message.D342LocationMessage; import com.imdroid.sideslope.message.D342LocationMessage;
import com.imdroid.sideslope.sal.Device; import com.imdroid.sideslope.sal.Device;
import com.imdroid.sideslope.sal.DeviceService; import com.imdroid.sideslope.sal.DeviceService;
import com.imdroid.sideslope.util.ThreadManager; import com.imdroid.common.util.ThreadManager;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;

View File

@ -5,7 +5,7 @@ import com.imdroid.sideslope.message.D3F0SelfCheckMessage;
import com.imdroid.sideslope.sal.DeviceService; import com.imdroid.sideslope.sal.DeviceService;
import com.imdroid.sideslope.sal.Device; import com.imdroid.sideslope.sal.Device;
import com.imdroid.sideslope.service.DataPersistService; import com.imdroid.sideslope.service.DataPersistService;
import com.imdroid.sideslope.util.ThreadManager; import com.imdroid.common.util.ThreadManager;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;

View File

@ -5,7 +5,7 @@ import com.imdroid.sideslope.message.D3F2StopIndicationMessage;
import com.imdroid.sideslope.sal.Device; import com.imdroid.sideslope.sal.Device;
import com.imdroid.sideslope.sal.DeviceService; import com.imdroid.sideslope.sal.DeviceService;
import com.imdroid.sideslope.service.DataPersistService; import com.imdroid.sideslope.service.DataPersistService;
import com.imdroid.sideslope.util.ThreadManager; import com.imdroid.common.util.ThreadManager;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;

View File

@ -2,8 +2,8 @@ package com.imdroid.sideslope.fwd;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.imdroid.secapi.dto.*; import com.imdroid.secapi.dto.*;
import com.imdroid.sideslope.util.GsonUtil; import com.imdroid.common.util.GsonUtil;
import com.imdroid.sideslope.util.NumberUtils; import com.imdroid.common.util.NumberUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;

View File

@ -9,7 +9,6 @@ import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.channel.socket.nio.NioSocketChannel;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner; import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;

View File

@ -1,6 +1,6 @@
package com.imdroid.sideslope.fwd; package com.imdroid.sideslope.fwd;
import com.imdroid.sideslope.util.DataTypeUtil; import com.imdroid.common.util.DataTypeUtil;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.SimpleChannelInboundHandler;

View File

@ -1,6 +1,6 @@
package com.imdroid.sideslope.message; package com.imdroid.sideslope.message;
import com.imdroid.sideslope.util.WrongMessageRecorder; import com.imdroid.common.util.WrongMessageRecorder;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import lombok.Data; import lombok.Data;

View File

@ -1,6 +1,6 @@
package com.imdroid.sideslope.message; package com.imdroid.sideslope.message;
import com.imdroid.sideslope.util.WrongMessageRecorder; import com.imdroid.common.util.WrongMessageRecorder;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
/** /**

View File

@ -1,6 +1,6 @@
package com.imdroid.sideslope.message; package com.imdroid.sideslope.message;
import com.imdroid.sideslope.util.WrongMessageRecorder; import com.imdroid.common.util.WrongMessageRecorder;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
/** /**

View File

@ -2,7 +2,7 @@ package com.imdroid.sideslope.message;
import com.imdroid.sideslope.bd.Tilt; import com.imdroid.sideslope.bd.Tilt;
import com.imdroid.sideslope.bd.UBXUtil; import com.imdroid.sideslope.bd.UBXUtil;
import com.imdroid.sideslope.util.WrongMessageRecorder; import com.imdroid.common.util.WrongMessageRecorder;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;

View File

@ -1,11 +1,9 @@
package com.imdroid.sideslope.sal; package com.imdroid.sideslope.sal;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.imdroid.secapi.dto.GnssCalcData;
import com.imdroid.secapi.dto.GnssDevice; import com.imdroid.secapi.dto.GnssDevice;
import com.imdroid.secapi.dto.GnssDeviceMapper; import com.imdroid.secapi.dto.GnssDeviceMapper;
import com.imdroid.sideslope.service.GNSSDeviceLocationRecordService; import com.imdroid.sideslope.service.GNSSDeviceLocationRecordService;
import com.imdroid.sideslope.util.ThreadManager;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -22,14 +20,9 @@ import java.util.List;
@Component(value = "db") @Component(value = "db")
public class DbDeviceServiceImpl implements DeviceService { public class DbDeviceServiceImpl implements DeviceService {
private final Logger logger = LoggerFactory.getLogger(DbDeviceServiceImpl.class);
@Autowired @Autowired
private GnssDeviceMapper gnssDeviceRepository; private GnssDeviceMapper gnssDeviceRepository;
@Autowired
private GNSSDeviceLocationRecordService gnssDeviceLocationRecordService;
@Override @Override
public Device findByDeviceId(String deviceId) { public Device findByDeviceId(String deviceId) {
GnssDevice gnssDevice = gnssDeviceRepository.queryByDeviceId(deviceId); GnssDevice gnssDevice = gnssDeviceRepository.queryByDeviceId(deviceId);
@ -66,16 +59,4 @@ public class DbDeviceServiceImpl implements DeviceService {
return deviceList; return deviceList;
} }
@Override
public boolean postLocationRecord(GnssCalcData locationRecord, boolean isExceed) {
ThreadManager.getFixedThreadPool().submit(() -> {
try {
gnssDeviceLocationRecordService.save(locationRecord, isExceed);
} catch (Exception e) {
logger.error(e.toString());
}
});
return true;
}
} }

View File

@ -1,7 +1,5 @@
package com.imdroid.sideslope.sal; package com.imdroid.sideslope.sal;
import com.imdroid.secapi.dto.GnssCalcData;
import java.util.List; import java.util.List;
/** /**
@ -13,7 +11,4 @@ public interface DeviceService {
Device findByDeviceId(String deviceId); Device findByDeviceId(String deviceId);
List<Device> findByParentId(String parentId); List<Device> findByParentId(String parentId);
boolean postLocationRecord(GnssCalcData locationRecord, boolean isExceed);
} }

View File

@ -2,7 +2,6 @@ package com.imdroid.sideslope.sal;
import com.google.common.cache.Cache; import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.imdroid.secapi.dto.GnssCalcData;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -49,8 +48,4 @@ public class LocalDeviceServiceImpl implements DeviceService {
return device; return device;
} }
@Override
public boolean postLocationRecord(GnssCalcData locationRecord, boolean isExceed) {
return delegate.postLocationRecord(locationRecord, isExceed);
}
} }

View File

@ -6,7 +6,7 @@ import com.imdroid.sideslope.executor.MessageParser;
import com.imdroid.sideslope.message.BaseMessage; import com.imdroid.sideslope.message.BaseMessage;
import com.imdroid.sideslope.server.DeviceChannel; import com.imdroid.sideslope.server.DeviceChannel;
import com.imdroid.sideslope.server.OnlineChannels; import com.imdroid.sideslope.server.OnlineChannels;
import com.imdroid.sideslope.util.DataTypeUtil; import com.imdroid.common.util.DataTypeUtil;
import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInboundHandlerAdapter;

View File

@ -1,10 +1,6 @@
package com.imdroid.sideslope.service; package com.imdroid.sideslope.service;
import com.imdroid.secapi.dto.GnssCalcData;
import com.imdroid.sideslope.message.D341LocationMessage; import com.imdroid.sideslope.message.D341LocationMessage;
import com.imdroid.sideslope.sal.Device;
import java.time.LocalDateTime;
/** /**
@ -12,7 +8,5 @@ import java.time.LocalDateTime;
* @date 2023/2/4 20:18 * @date 2023/2/4 20:18
*/ */
public interface GNSSDeviceLocationRecordService { public interface GNSSDeviceLocationRecordService {
void save(GnssCalcData locationRecord, boolean isExceed) throws Exception;
void saveRawData(D341LocationMessage message); void saveRawData(D341LocationMessage message);
LocalDateTime updateRb562(String deviceId, LocalDateTime afterTime);
} }

View File

@ -1,24 +1,13 @@
package com.imdroid.sideslope.service; package com.imdroid.sideslope.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.imdroid.secapi.dto.*; import com.imdroid.secapi.dto.*;
import com.imdroid.sideslope.bd.Tilt; import com.imdroid.sideslope.bd.Tilt;
import com.imdroid.sideslope.bd.UBXUtil; import com.imdroid.sideslope.bd.UBXUtil;
import com.imdroid.sideslope.message.D341LocationMessage; import com.imdroid.sideslope.message.D341LocationMessage;
import com.imdroid.sideslope.sal.Device; import com.imdroid.common.util.NumberUtils;
import com.imdroid.sideslope.sal.DeviceService;
import com.imdroid.sideslope.util.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/** /**
* @author Layton * @author Layton
* @date 2023/2/15 21:05 * @date 2023/2/15 21:05
@ -26,180 +15,9 @@ import java.util.concurrent.ConcurrentHashMap;
@Service @Service
public class GNSSDeviceLocationRecordServiceImpl implements GNSSDeviceLocationRecordService{ public class GNSSDeviceLocationRecordServiceImpl implements GNSSDeviceLocationRecordService{
private final Logger logger = LoggerFactory.getLogger(this.getClazz());
@Autowired
private GnssCalcDataMapper repository;
@Autowired @Autowired
private GnssRawDataMapper gnssRawDataMapper; private GnssRawDataMapper gnssRawDataMapper;
@Autowired
private GnssDeviceMapper gnssDeviceRepository;
@Autowired
private GnssGroupCalcMapper groupCalcMapper;
public static final int FILTER_MIN_CYCLE_HOUR = 2;
public static final int FILTER_DEFAULT_CYCLE_HOUR = 8;
static final int FILTER_MIN_RECORD_NUM = 10;
static final float XY_THRESHOLD = 30; //水平异常点30mm
static final float Z_THRESHOLD = 30; //高程异常点30mm
static final float AUTO_THRESHOLD = 50; //触发自适应滤波的门限50mm
static class VaryFilterCycle{
public LocalDateTime startTime;
public int filterCycleHour;
}
final private ConcurrentHashMap<String, VaryFilterCycle> autoCycleDevices = new ConcurrentHashMap<>();
final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
protected Class<GnssCalcData> getClazz() {
return GnssCalcData.class;
}
@Override
public void save(GnssCalcData locationRecord, boolean isExceed) {
String deviceId = locationRecord.getDeviceid();
GnssDevice gnssDevice = gnssDeviceRepository.queryByDeviceId(deviceId);
if(gnssDevice == null) return;
//补充解算记录的设备信息
locationRecord.setTenantid(gnssDevice.getTenantid());
locationRecord.setEnabled(true);
// 获取平滑参数
GnssGroupCalc groupCalc = getCalcParams(gnssDevice.getCalc_group_id());
// 计算平滑周期
int filterCycle = groupCalc.getFilter_hour();
VaryFilterCycle varyCycle = autoCycleDevices.get(deviceId);
if(varyCycle!=null){
filterCycle = varyCycle.filterCycleHour;
}
// 平滑处理
calcFilterLocation(locationRecord, filterCycle,
groupCalc.getXy_threshold(), groupCalc.getZ_threshold());
repository.insert(locationRecord);
// 更新平滑周期
if(groupCalc.getAuto_filter()) {
refreshFilterCycle(deviceId, groupCalc, locationRecord);
}
}
void refreshFilterCycle(String deviceId, GnssGroupCalc groupCalc, GnssCalcData curCalcData){
LocalDateTime now = LocalDateTime.now();
VaryFilterCycle varyCycle = autoCycleDevices.get(deviceId);
// 如果当前处于变周期阶段则根据时间调整周期
if(varyCycle != null){
if(varyCycle.filterCycleHour >= groupCalc.getFilter_hour()){
//变周期结束
autoCycleDevices.remove(deviceId);
}
else {
if (now.isAfter(varyCycle.startTime.plusHours(1))) {
varyCycle.filterCycleHour++;
varyCycle.startTime = now;
logger.info(deviceId + ": refresh filter cycle "+varyCycle.filterCycleHour);
}
}
}
// 否则判断是否将进入变周期
else{
// 比较当前均值和FilterMinHour前的均值之差是否超过门限
LocalDateTime cmpTime = now.minusHours(groupCalc.getFilter_min_hour());
QueryWrapper<GnssCalcData> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("deviceid", deviceId);
queryWrapper.ge("createtime",cmpTime.format(dateFormatter));
queryWrapper.last("limit 1");
GnssCalcData gnssCalcData = repository.selectOne(queryWrapper);
if(gnssCalcData != null && gnssCalcData.getEnabled()){
if(gnssCalcData.getRb562e()!=null && gnssCalcData.getRb562d()!=null){
double gapE = Math.abs(gnssCalcData.getRb562e() - curCalcData.getRb562e());
double gapN = Math.abs(gnssCalcData.getRb562n() - curCalcData.getRb562n());
if(gapE>=groupCalc.getAuto_threshold() || gapN>=groupCalc.getAuto_threshold()){
VaryFilterCycle varyCycle1 = new VaryFilterCycle();
varyCycle1.startTime = now;
varyCycle1.filterCycleHour = groupCalc.getFilter_min_hour();
autoCycleDevices.put(deviceId, varyCycle1);
logger.info(deviceId + ": filter cycle change to "+varyCycle1.filterCycleHour);
}
}
}
}
}
GnssGroupCalc getCalcParams(int calcGroupId){
GnssGroupCalc calcParam = groupCalcMapper.selectById(calcGroupId);
if(calcParam == null){
calcParam = new GnssGroupCalc();
calcParam.setAuto_filter(false);
calcParam.setFilter_hour(FILTER_DEFAULT_CYCLE_HOUR);
calcParam.setFilter_min_hour(FILTER_MIN_CYCLE_HOUR);
calcParam.setXy_threshold(XY_THRESHOLD);
calcParam.setZ_threshold(Z_THRESHOLD);
calcParam.setAuto_threshold(AUTO_THRESHOLD);
}
return calcParam;
}
/**
* 计算东北天的最近融合数据的加权平均, 刘畅20230725 copy avgEND; id>20, 滤波参数6h 25h
*/
public boolean calcFilterLocation(GnssCalcData newRecord, int filterCycleHour, float xyThreshold, float zThreshold){
String deviceId = newRecord.getDeviceid();
// 选取[newRecordTime-filterCycleHour, newRcordTime]之间的记录做平滑
// 如果这个时间段的记录数少于FILTER_MIN_RECORD_NUM本次不做平滑
LocalDateTime newRecordTime = newRecord.getCreatetime();
LocalDateTime filterAfterTime = newRecordTime.minusHours(filterCycleHour);
QueryWrapper<GnssCalcData> query = new QueryWrapper<>();
query.eq("deviceid", deviceId);
query.ge("createtime", filterAfterTime.format(dateFormatter));
query.le("createtime", newRecordTime.format(dateFormatter));
query.orderByDesc("createtime");
List<GnssCalcData> gnssDeviceLocationRecords = repository.selectList(query);
if(gnssDeviceLocationRecords.size() == 0){
//第一个点无参考当作坏点处理
newRecord.setEnabled(false);
}
else {
GnssCalcData record0 = gnssDeviceLocationRecords.get(0);
// 检查是不是坏点
if (Math.abs(newRecord.getB562e() - record0.getB562e()) > xyThreshold ||
Math.abs(newRecord.getB562n() - record0.getB562n()) > xyThreshold ||
Math.abs(newRecord.getB562d() - record0.getB562d()) > zThreshold) {
newRecord.setEnabled(false); //记录为坏点下次不参与滤波
logger.info(deviceId + " abnormal gnss data");
}
else {
// 求本组和最近recordNum组原始值的平均值
double sumE = newRecord.getB562e();
double sumN = newRecord.getB562n();
double sumD = newRecord.getB562d();
int count = 1;
for (GnssCalcData record : gnssDeviceLocationRecords) {
if (record.getEnabled()) {//只选取好点参与滤波
sumE += record.getB562e();
sumN += record.getB562n();
sumD += record.getB562d();
count++;
}
}
logger.info(deviceId + " filter records num: " + count);
if (count >= FILTER_MIN_RECORD_NUM) {
newRecord.setRb562e(NumberUtils.scaleTwo(sumE / count));
newRecord.setRb562n(NumberUtils.scaleTwo(sumN / count));
newRecord.setRb562d(NumberUtils.scaleTwo(sumD / count));
return true;
}
}
}
return false;
}
@Override @Override
public void saveRawData(D341LocationMessage message){ public void saveRawData(D341LocationMessage message){
GnssRawData data = new GnssRawData(); GnssRawData data = new GnssRawData();
@ -219,70 +37,4 @@ public class GNSSDeviceLocationRecordServiceImpl implements GNSSDeviceLocationRe
} }
gnssRawDataMapper.insert(data); gnssRawDataMapper.insert(data);
} }
/**
* 计算平滑窗口有3种模式
* 1清零平滑窗口从1个工作周期开始增长
* 2固定平滑窗口大小始终固定
* 3自适应当isExceed为true时平滑窗口为SHORT_CYCLE过了SHORT_CYCLE后逐渐增长到LONG_CYCLE
*/
/* int calcFilterCycle(String deviceId, boolean isExceed, GnssGroupCalc groupCalc){
int filterCycle = groupCalc.getFilter_max_hour();
LocalDateTime now = LocalDateTime.now();
if (isExceed) {
FilterSetting filterData = new FilterSetting();
filterData.startTime = now;
filterData.filterCycleHour = groupCalc.getFilter_hour();
shortCycleDevices.put(deviceId, filterData);
filterCycle = filterData.filterCycleHour;
logger.info(deviceId + " switch to short cycle");
} else {
FilterSetting filterData = shortCycleDevices.get(deviceId);
if (filterData != null) {
Duration duration = Duration.between(now, filterData.startTime); // start - now
if (Math.abs(duration.toHours()) >= groupCalc.getFilter_max_hour()) {
shortCycleDevices.remove(deviceId);
logger.info(deviceId + " switch to long cycle");
}
else {
if (Math.abs(duration.toHours()) >= groupCalc.getFilter_hour()) {
filterData.filterCycleHour = (int) duration.toHours();
}
filterCycle = filterData.filterCycleHour;
}
}
}
return filterCycle;
}
*/
@Override
public LocalDateTime updateRb562(String deviceId, LocalDateTime afterTime){
// 获取平滑参数
GnssDevice gnssDevice = gnssDeviceRepository.queryByDeviceId(deviceId);
if(gnssDevice == null) return afterTime;
GnssGroupCalc groupCalc = getCalcParams(gnssDevice.getCalc_group_id());
// 平滑处理
LocalDateTime beforTime = afterTime.plusHours(groupCalc.getFilter_hour());
QueryWrapper<GnssCalcData> query = new QueryWrapper<>();
query.eq("deviceid", deviceId);
query.le("createtime", beforTime.format(dateFormatter));
query.ge("createtime", afterTime.format(dateFormatter));
query.orderByAsc("createtime");
LocalDateTime lastTime = afterTime;
List<GnssCalcData> calcDataListToUpdate = repository.selectList(query);
for(GnssCalcData calcData:calcDataListToUpdate){
if(calcData.getEnabled()) {
calcFilterLocation(calcData, groupCalc.getFilter_hour(),
groupCalc.getXy_threshold(), groupCalc.getZ_threshold());
repository.updateById(calcData);
lastTime = calcData.getCreatetime();
logger.info(deviceId + " update rb562");
}
}
return lastTime;
}
} }

View File

@ -3,7 +3,7 @@ package com.imdroid.sideslope.web;
import com.imdroid.secapi.client.HttpResp; import com.imdroid.secapi.client.HttpResp;
import com.imdroid.sideslope.server.DeviceChannel; import com.imdroid.sideslope.server.DeviceChannel;
import com.imdroid.sideslope.server.OnlineChannels; import com.imdroid.sideslope.server.OnlineChannels;
import com.imdroid.sideslope.util.DataTypeUtil; import com.imdroid.common.util.DataTypeUtil;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import org.slf4j.Logger; import org.slf4j.Logger;

View File

@ -1,436 +0,0 @@
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.imdroid.secapi.dto.GnssCalcData;
import com.imdroid.secapi.dto.GnssCalcDataMapper;
import com.imdroid.sideslope.service.GNSSDeviceLocationRecordServiceImpl;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.sql.DataSource;
import java.util.Date;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest(
classes = {
GnssLocationFilterTest.class,
GnssCalcDataMapper.class,
DataSourceAutoConfiguration.class,
MybatisPlusAutoConfiguration.class,
DataSource.class,
SqlSessionFactory.class
}
)
@MapperScan({"com.imdroid.secapi","com.imdroid.beidou.entity"})
public class GnssLocationFilterTest {
@Autowired
GnssCalcDataMapper gnssCalcDataMapper;
static final String TEST_DEVICE_ID = "2307042";
@Test
public void test() {
// 读东北天原始数据写入数据库时间为当前时间+n*30分钟
int begin = 0;
int end = 0;
int pos = 0;
boolean beginFound = false;
double[] value = {0,0,0};
int valueId = 0;
long now = System.currentTimeMillis();
String dataSrc = rawData3;
QueryWrapper<GnssCalcData> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("deviceid", TEST_DEVICE_ID);
gnssCalcDataMapper.delete(queryWrapper);
int recordNum = 0;
while(pos<dataSrc.length()-1){
pos++;
// 找起始空格
if(!beginFound) {
if (dataSrc.charAt(pos) != ' '){
beginFound = true;
begin = pos;
}
else continue;
}
// 找结束位
if (dataSrc.charAt(pos) == ' ') {
end = pos;
}
else continue;
// 读数据
value[valueId] = Double.parseDouble(dataSrc.substring(begin, end));
valueId++;
if(valueId == 3){
valueId = 0;
testFilter(value, now);
recordNum++;
if(recordNum>=33){
now += 5*60*1000;
}
else now += 30*60*1000;
}
beginFound = false;
}
}
public void testFilter(double[] xyz, long recordTime){
//写入数据库
GnssCalcData gnssCalcData = new GnssCalcData();
gnssCalcData.setDeviceid(TEST_DEVICE_ID);
gnssCalcData.setB562e(xyz[0]);
gnssCalcData.setB562n(xyz[1]);
gnssCalcData.setB562d(xyz[2]);
gnssCalcData.setCreatetime(new Date(recordTime));
gnssCalcData.setTenantid(0);
gnssCalcData.setEnabled(true);
double[] avgEND = calcFilterLocation(gnssCalcData, GNSSDeviceLocationRecordServiceImpl.FILTER_SHORT_CYCLE);
if(avgEND!=null) {
gnssCalcData.setRb562e(avgEND[0]);
gnssCalcData.setRb562n(avgEND[1]);
gnssCalcData.setRb562d(avgEND[2]);
}
gnssCalcDataMapper.insert(gnssCalcData);
}
public static final long FILTER_SHORT_CYCLE = 4 * 60 * 60 * 1000;
public static final long FILTER_LONG_CYCLE = 25 * 60 * 60 * 1000;
static final int FILTER_MAX_RECORD_NUM = 50;
static final double xyThreshold = 30; //水平异常点50mm
static final double zThreshold = 30; //高程异常点50mm
public double[] calcFilterLocation(GnssCalcData newRecord, long filterCycle){
String deviceId = newRecord.getDeviceid();
// 读取最近recordNum个原始值按时间倒序排序
QueryWrapper<GnssCalcData> query = new QueryWrapper<>();
query.orderByDesc("createtime");
query.eq("deviceid", deviceId);
query.last("limit "+FILTER_MAX_RECORD_NUM);
List<GnssCalcData> gnssDeviceLocationRecords = gnssCalcDataMapper.selectList(query);
long now = newRecord.getCreatetime().getTime();
boolean hasCheck = false;
if(gnssDeviceLocationRecords.size() > 0){
// 求本组和最近recordNum组原始值的平均值
double sumE = newRecord.getB562e();
double sumN = newRecord.getB562n();
double sumD = newRecord.getB562d();
int count = 1;
for (int i = 0; i < gnssDeviceLocationRecords.size(); i++) {
GnssCalcData record = gnssDeviceLocationRecords.get(i);
if(now - record.getCreatetime().getTime()>=filterCycle) break;
if(record.getB562e()!=null && record.getB562n()!=null && record.getB562d()!=null) {
if (record.getEnabled()) {//只选取好点参与滤波
sumE += record.getB562e();
sumN += record.getB562n();
sumD += record.getB562d();
count++;
}
if(!hasCheck){
// 检查是不是坏点
if(Math.abs(newRecord.getB562e() - record.getB562e())>xyThreshold ||
Math.abs(newRecord.getB562n() - record.getB562n())>xyThreshold ||
Math.abs(newRecord.getB562d() - record.getB562d())>zThreshold ){
newRecord.setEnabled(false); //记录为坏点下次不参与滤波
return null;
}
hasCheck = true;
}
}
}
return new double[]{sumE/count, sumN/count, sumD/count};
}
else{
return new double[]{newRecord.getB562e(),newRecord.getB562n(),newRecord.getB562d()};
}
}
static final String rawData3 =
" -2784.55 -8.27 4.25" +
" -2790.43 -3.82 12.74" +
" -2786.11 -0.07 3.23" +
" -2790.22 -2.63 13.1" +
" -2787.42 -2.73 17.82" +
" -2788.14 -4.44 11.35" +
" -2786.61 -4.34 13.65" +
" -2793.29 -15.65 -11.22" +
" -2786.61 -1.64 5.83" +
" -2790.22 -3.01 -18.59" +
" -2781.82 -15.34 27.69" +
" -2778.48 -7.88 29.69" +
" -2789.48 -6.44 -6.35" +
" -2793.03 -5.43 1.17" +
" -2782.46 -12.38 -15.17" +
" -2773.29 -9.73 28.58" +
" -2777.49 -9.86 -8.57" +
" -2785.1 -6.15 10.3" +
" -2789.49 -5.79 -4.94" +
" -2786.8 -5.76 10.71" +
" -2780.04 -12.41 -3.85" +
" -2776.79 -14.54 8.01" +
" -2783.01 -4.54 2.09" +
" -2801.79 -11.24 -6.14" +
" -2789.49 -10.19 0.17" +
" -2793.58 -7.94 1.44" +
" -2784.39 -1.69 9.48" +
" -2784.74 -8.14 4.71" +
" -2785.63 -7.56 -12.44" +
" -2786.87 -5.98 12.29" +
" -2787.83 -2.07 21.57" +
" -2782.36 -1.86 5.05" +
" -2784.5 -8.61 3.72" +
" -2784.4 -1.77 5.31" +
" -2783.07 0.76 24.7" +
" -2782.23 1.64 33.96" +
" -2779.99 -2.9 5.85" +
" -2780.51 -5.21 -15.16" +
" ";
static final String rawData2 =
" -2771.61 -23.6 14.29" +
" -2774.32 -26.05 2.73" +
" -2775.04 -26.71 1.69" +
" -2779.98 -30.9 -24.99" +
" -2776.69 -25.03 14.35" +
" -2778.41 -29.94 -9.64" +
" -2768.78 -33.27 -10.58" +
" -2785.64 -24.95 -5.39" +
" -2773.86 -26.16 6.12" +
" -2778.37 -24.03 6.21" +
" -2778.06 -24.37 -14.03" +
" -2772.17 -23.71 15.6" +
" -2778.0 -26.93 -40.69" +
" -2775.69 -28.74 -17.0" +
" -2777.47 -26.95 53.94" +
" -2776.39 -27.39 -10.91" +
" -2776.76 -24.43 -8.69" +
" -2772.69 -26.14 9.64" +
" -2772.63 -26.59 6.58" +
" -2776.69 -25.35 -6.73" +
" -2771.68 -30.45 -4.91" +
" -2776.42 -24.67 10.56" +
" -2777.8 -22.52 -6.14" +
" -2780.48 -23.99 0.57" +
" -2778.01 -24.55 0.08" +
" -2785.1 -28.97 1.72" +
" -2788.77 -31.86 66.39" +
" -2785.8 -33.42 -29.34" +
" -2772.48 -19.88 3.69" +
" -2778.84 -26.71 -4.64" +
" -2775.28 -32.29 2.42" +
" -2775.61 -27.95 -0.6" +
" -2776.84 -32.72 7.84" +
" -2773.98 -28.91 -6.3" +
" -2776.17 -26.56 -4.51" +
" -2768.58 -25.69 4.36" +
" -2780.64 -23.62 12.62" +
" -2778.19 -24.95 -29.35" +
" -2780.77 -24.8 10.8" +
" -2779.79 -31.14 -22.01" +
" -2779.45 -23.63 -3.87" +
" -2777.01 -25.48 -8.7" +
" -2769.97 -28.98 7.92" +
" -2777.6 -24.9 10.51" +
" -2774.66 -27.99 -3.74" +
" -2777.29 -25.76 9.28" +
" -2785.99 -40.79 1.53" +
" -2773.99 -31.04 -13.19" +
" -6543.25 2227.9 2180.2" +
" -2777.01 -26.15 9.51" +
" -2777.95 -23.99 8.05" +
" -2785.42 -26.95 -11.81" +
" -2772.32 -23.72 15.74" +
" -2785.0 -19.53 46.75" +
" -2788.44 -21.22 19.61" +
" -2784.99 -25.87 -5.73" +
" -2779.51 -27.28 0.16" +
" -2779.09 -23.88 -5.4" +
" -2775.5 -30.29 -1.82" +
" -2774.46 -22.86 12.4" +
" -2775.0 -27.17 -67.82" +
" -2768.79 -19.75 -19.86" +
" -2775.03 -29.28 -11.72" +
" -2773.4 -21.26 -10.24" +
" -2773.42 -27.87 -6.55" +
" -2773.76 -23.28 8.66" +
" -2781.95 -1.55 14.24" +
" -2779.13 -5.96 20.53" +
" -2784.52 -4.91 15.8" +
" -2786.2 -4.07 -0.39" +
" -2784.15 0.43 25.79" +
" -2788.45 -0.35 7.52" +
" -2782.57 -4.38 25.11" +
" -2788.21 -2.77 -4.44" +
" -2781.03 -1.65 22.15" +
" -2788.64 -3.55 19.85" +
" -2779.44 -8.32 -13.16" +
" -2787.04 -8.07 -5.37" +
" -2788.56 -12.58 29.69" +
" -2791.25 -0.85 8.52" +
" -2780.79 -10.17 2.97" +
" -2780.89 -1.32 7.31" +
" -2783.53 -4.6 14.93" +
" -2787.58 -1.87 25.1" +
" -2784.64 -2.59 19.12" +
" -2788.56 -8.89 3.02" +
" -2786.02 -6.85 -0.2" +
" -2790.14 -2.75 -9.8" +
" -2780.93 -4.28 11.32" +
" -2786.74 -3.6 5.6" +
" -2785.27 -5.86 13.69" +
" -2780.52 0.74 19.85" +
" -2783.07 -20.28 -24.34" +
" -2782.29 -6.53 10.94" +
" -2782.51 -5.73 30.72" +
" -2783.22 -7.89 13.02" +
" -2780.98 -5.21 13.42" +
" -2789.51 -0.19 1.76" +
" -2790.0 4.9 15.22" +
" -2780.27 -16.51 15.72" +
" -2782.71 -8.84 1.96" +
" -2785.64 -6.69 16.81" +
" -2782.44 -2.75 17.68" +
" -2787.95 -3.18 -10.92" +
" -2782.86 -4.27 13.28" +
" -2784.33 -3.13 -8.5" +
" -2783.1 -2.5 28.88" +
" -2788.09 -5.28 0.97" +
" -2783.41 -3.81 7.66" +
" ";
static final String rawData =
" -15167.87 -28982.95 73.65" +
" -15173.15 -28984.5 74.48" +
" -15172.93 -28984.37 75.23" +
" -15172.46 -28983.92 76.02" +
" -15172.15 -28984.23 76.78" +
" -15172.77 -28983.73 77.5" +
" -15173.36 -28984.07 78.21" +
" -15173.97 -28984.21 78.97" +
" -15173.26 -28983.64 79.66" +
" -15172.64 -28984.6 80.25" +
" -15172.04 -28985.3 80.79" +
" -15173.01 -28985.33 81.29" +
" -15172.71 -28983.66 81.83" +
" -15172.52 -28984.8 82.44" +
" -15172.08 -28984.03 82.9" +
" -15172.1 -28984.83 83.26" +
" -15172.14 -28983.71 83.73" +
" -15173.8 -28984.9 84.13" +
" -15172.51 -28984.54 84.52" +
" -15171.96 -28985.22 84.96" +
" -15173.1 -28984.92 85.39" +
" -15171.65 -28984.14 85.81" +
" -15172.7 -28983.77 86.2" +
" -15172.51 -28983.93 86.53" +
" -15173.5 -28984.58 86.88" +
" -15172.16 -28984.0 87.24" +
" -15172.78 -28983.86 87.62" +
" -15173.34 -28984.54 87.96" +
" -15172.85 -28984.4 88.23" +
" -15170.84 -28983.74 88.39" +
" -15172.5 -28983.91 88.67" +
" -15172.92 -28984.29 88.94" +
" -15171.54 -28983.71 89.21" +
" -15171.85 -28983.73 89.49" +
" -15171.88 -28983.9 89.8" +
" -15172.16 -28983.89 90.11" +
" -15176.26 -28983.51 90.55" +
" -15173.43 -28984.14 90.75" +
" -15173.23 -28983.78 90.98" +
" -15172.9 -28983.38 91.19" +
" -15172.65 -28983.36 91.37" +
" -15172.88 -28984.08 91.54" +
" -15172.92 -28983.84 91.72" +
" -15173.12 -28983.23 91.93" +
" -15172.81 -28983.72 92.06" +
" -15172.71 -28983.37 92.23" +
" -15172.81 -28984.04 92.38" +
" -15172.95 -28984.47 92.5" +
" -15173.05 -28984.12 92.61" +
" -15173.85 -28984.07 92.78" +
" -15174.06 -28984.15 92.76" +
" -15172.73 -28984.1 92.82" +
" -15170.81 -28983.95 92.85" +
" -15172.96 -28983.54 92.99" +
" -15173.03 -28983.86 93.07" +
" -15172.72 -28983.9 93.17" +
" -15173.02 -28984.17 93.26" +
" -15171.72 -28984.39 93.25" +
" -15172.57 -28984.65 93.32" +
" -15172.85 -28984.0 93.39" +
" -15172.85 -28983.84 93.47" +
" -15172.87 -28984.55 93.59" +
" -15172.8 -28984.06 93.67" +
" -15173.82 -28984.86 93.86" +
" -15172.29 -28983.91 93.94" +
" -15172.68 -28984.71 94.08" +
" -15172.77 -28984.35 94.12" +
" -15171.91 -28984.53 94.16" +
" -15173.35 -28985.08 94.21" +
" -15168.49 -28983.83 94.52" +
" -15172.26 -28983.64 94.52" +
" -15172.63 -28984.67 94.52" +
" -15173.19 -28984.43 94.6" +
" -15173.15 -28983.84 94.66" +
" -15173.19 -28983.99 94.7" +
" -15173.13 -28983.4 94.73" +
" -15172.23 -28984.36 94.67" +
" -15171.84 -28984.05 94.65" +
" -15172.41 -28983.27 94.74" +
" -15172.28 -28983.66 94.77" +
" -15172.69 -28983.48 94.84" +
" -15172.31 -28983.56 94.94" +
" -15072.78 -29087.37 -87.22" +
" -15173.77 -28984.38 95.74" +
" -15173.39 -28984.88 95.74" +
" -15171.91 -28983.1 95.8" +
" -15172.32 -28984.13 95.8" +
" -15172.77 -28984.42 95.78" +
" -15172.74 -28984.61 95.75" +
" -15173.0 -28984.16 95.71" +
" -15173.85 -28984.0 95.74" +
" -15172.84 -28983.8 95.75" +
" -15173.17 -28984.77 95.84" +
" -15173.42 -28983.67 95.9" +
" -15172.49 -28983.32 95.83" +
" -15172.83 -28983.31 95.84" +
" -15172.52 -28984.76 95.76" +
" -15172.64 -28984.54 95.72" +
" -15172.68 -28984.18 95.67" +
" -15172.88 -28983.91 95.61" +
" -15172.34 -28983.42 95.88" +
" -15171.84 -28985.56 95.96" +
" -15173.43 -28983.87 95.96" +
" -15028.18 -28928.66 -250.01" +
" -15170.16 -28982.11 92.71" +
" -15171.16 -28983.76 92.78" +
" -15172.35 -28982.81 92.91" +
" -15171.39 -28983.43 92.94" +
" -15170.86 -28984.09 92.9" +
" -15172.53 -28982.87 93.05" +
" -15171.53 -28983.34 93.1" +
" -15173.05 -28982.6 93.37" +
" -15173.2 -28983.79 93.36" +
" -15172.24 -28983.24 93.44" +
" -15241.91 -28843.47 -291.16" +
" -15173.18 -28984.66 96.36" +
" -15172.39 -28982.85 96.34" +
" -15173.17 -28984.03 96.25" +
" -15173.52 -28984.71 96.12" +
" -15174.61 -28986.6 95.76" +
" -15224.7 -28977.24 101.79" +
" ";
}

View File

@ -46,6 +46,8 @@ public class GnssDeviceController extends BasicController{
@RequestMapping("/page/gnss_dev_cfg") @RequestMapping("/page/gnss_dev_cfg")
public String gnssDevCfg(Model m, HttpSession session) { public String gnssDevCfg(Model m, HttpSession session) {
initModel(m, session); initModel(m, session);
List<Tenant> tenants = tenantMapper.selectList(null);
m.addAttribute("tenant_list", tenants);
return "/page/gnss_dev_cfg"; return "/page/gnss_dev_cfg";
} }
@ -90,6 +92,11 @@ public class GnssDeviceController extends BasicController{
if (!StringUtils.isEmpty(parentid)) { if (!StringUtils.isEmpty(parentid)) {
queryWrapper.like("parentid", parentid); queryWrapper.like("parentid", parentid);
} }
//所属组织
String tenantname = search.getString("tenantname");
if (!StringUtils.isEmpty(tenantname)) {
queryWrapper.like("tenantname", tenantname);
}
//设备类型 //设备类型
Integer devicetype = search.getInteger("devicetype"); Integer devicetype = search.getInteger("devicetype");
if (devicetype != null && devicetype != QUERY_ALL) { if (devicetype != null && devicetype != QUERY_ALL) {

View File

@ -0,0 +1,111 @@
package com.imdroid.beidou.controller;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.imdroid.beidou.common.HttpResult;
import com.imdroid.beidou.data.vo.device.DeviceInstallVO;
import com.imdroid.beidou.data.vo.device.DeviceListVO;
import com.imdroid.beidou.data.vo.device.DeviceStatusVO;
import com.imdroid.beidou.entity.Tenant;
import com.imdroid.beidou.entity.TenantMapper;
import com.imdroid.secapi.client.RtcmClient;
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.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpSession;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Controller
public class TenantController extends BasicController{
@Autowired
TenantMapper tenantMapper;
/**** 推送页面 *****/
@RequestMapping("/sys/tenant")
public String listTenant(Model m, HttpSession session) {
initModel(m, session);
return "/page/tenant_cfg";
}
@RequestMapping("/sys/tenant/add")
public String addTenant(Model m){
return "/page/table/tenant_add";
}
@RequestMapping("/sys/tenant/edit")
public String editTenant(Model m){
return "/page/table/tenant_add";
}
/**** 推送数据 *****/
@RequestMapping("/sys/tenant/list")
@ResponseBody
public JSONObject list(HttpSession session, int page, int limit, String searchParams) {
Page<Tenant> pageable = new Page<>(page, limit);
QueryWrapper<Tenant> queryWrapper = new QueryWrapper<>();
IPage<Tenant> cs = tenantMapper.selectPage(pageable, queryWrapper);
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", 0);
jsonObject.put("msg", "");
jsonObject.put("count", cs.getTotal());
jsonObject.put("data", cs.getRecords());
return jsonObject;
}
@PostMapping("/sys/tenant/update")
@ResponseBody
public String update(HttpSession session, @RequestBody JSONObject object) throws Exception {
// 从请求参数中创建对象
Tenant tenantNew = JSONObject.toJavaObject(object,Tenant.class);
// 检测该对象是否已存在
Tenant tenantOld = tenantMapper.selectById(tenantNew.getId());
//新增或更新
int num = 0;
LocalDateTime now = LocalDateTime.now();
if(null != tenantOld) {
tenantNew.setCreate_time(tenantOld.getCreate_time());
tenantNew.setUpdate_time(now);
num = tenantMapper.updateById(tenantNew);
}
else{
QueryWrapper<Tenant> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("id");
queryWrapper.last("limit 1");
Tenant maxTenant = tenantMapper.selectOne(queryWrapper);
tenantNew.setId(maxTenant.getId()+1);
tenantNew.setCreate_time(now);
tenantNew.setUpdate_time(now);
num = tenantMapper.insert(tenantNew); //id自增
}
if (num == 0) {
return HttpResult.failed();
} else {
return HttpResult.ok();
}
}
@PostMapping("/sys/tenant/delete")
@ResponseBody
public String delete(@RequestParam String name) throws Exception {
QueryWrapper<Tenant> wrapper = new QueryWrapper<>();
wrapper.eq("name",name);
int num = tenantMapper.delete(wrapper);
if (num == 0) {
return HttpResult.failed();
} else return HttpResult.ok();
}
}

View File

@ -1,5 +1,7 @@
package com.imdroid.beidou.entity; package com.imdroid.beidou.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
@ -12,8 +14,10 @@ public class Tenant implements Serializable {
// SAAS服务商可以查看和操作全部数据 // SAAS服务商可以查看和操作全部数据
public final static int SAAS_PROVIDER_ID = 0; public final static int SAAS_PROVIDER_ID = 0;
public final static String SAAS_PROVIDER_NAME = "SAAS服务商"; public final static String SAAS_PROVIDER_NAME = "SAAS服务商";
@TableId(value = "id", type = IdType.AUTO)
Integer id; Integer id;
String name; String name;
LocalDateTime create_time; LocalDateTime create_time;
LocalDateTime update_time;
String contact; String contact;
} }

View File

@ -59,7 +59,7 @@ public class ServiceEnvInit implements ApplicationRunner {
user.setName(default_user_name); user.setName(default_user_name);
user.setPwd(bCryptPasswordEncoderUtil.encode(default_pwd)); user.setPwd(bCryptPasswordEncoderUtil.encode(default_pwd));
user.setRole("ADMIN"); user.setRole("ADMIN");
user.setTenant_id(0); user.setTenant_id(Tenant.SAAS_PROVIDER_ID);
userMapper.insert(user); userMapper.insert(user);
} }

View File

@ -17,6 +17,7 @@ CREATE TABLE IF NOT EXISTS `TenantCfg` (
`id` int NOT NULL, `id` int NOT NULL,
`name` varchar(128) NOT NULL, `name` varchar(128) NOT NULL,
`create_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP(3), `create_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP(3),
`update_time` timestamp(3) DEFAULT CURRENT_TIMESTAMP(3),
`contact` varchar(64) default NULL, `contact` varchar(64) default NULL,
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8; ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View File

@ -195,37 +195,23 @@
"href": "", "href": "",
"target": "_self", "target": "_self",
"child": [ "child": [
{ {
"title": "系统状态", "title": "系统参数",
"href": "", "href": "",
"icon": "fa fa-server", "icon": "fa fa-gears",
"target": "_self" "target": "_self"
}, },
{ {
"title": "系统参数", "title": "组织管理",
"href": "", "href": "sys/tenant",
"icon": "fa fa-gears", "icon": "fa fa-university",
"target": "_self" "target": "_self"
}, },
{ {
"title": "用户管理", "title": "用户管理",
"href": "", "href": "",
"icon": "fa fa-user", "icon": "fa fa-user",
"target": "_self", "target": "_self"
"child": [
{
"title": "组织管理",
"href": "",
"icon": "fa fa-university",
"target": "_self"
},
{
"title": "账号管理",
"href": "",
"icon": "fa fa-key",
"target": "_self"
}
]
}, },
{ {
"title": "操作日志", "title": "操作日志",

View File

@ -18,6 +18,16 @@
<input type="text" name="parentid" autocomplete="off" class="layui-input"> <input type="text" name="parentid" autocomplete="off" class="layui-input">
</div> </div>
</div> </div>
<div class="layui-inline">
<label class="layui-form-label">所属部门</label>
<div class="layui-input-inline">
</select>
<select name="tenantname" id="tenantname" lay-search="">
<option value="">全部</option>
<option th:each="item : ${tenant_list}" th:text="${item.name}" th:value="${item.name}"></option>
</select>
</div>
</div>
<div class="layui-inline"> <div class="layui-inline">
<label class="layui-form-label">设备类型</label> <label class="layui-form-label">设备类型</label>
<div class="layui-input-inline"> <div class="layui-input-inline">

View File

@ -0,0 +1,63 @@
<div class="layuimini-main">
<div class="layui-form layuimini-form">
<input type="hidden" name="id" id="id">
<div class="layui-form-item">
<label class="layui-form-label required">企业名称</label>
<div class="layui-input-block">
<input type="text" name="name" id="name" lay-verify="required" lay-reqtext="不能为空" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label required">联系方式</label>
<div class="layui-input-block">
<input type="text" name="contact" id="contact" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn layui-btn-normal" lay-submit lay-filter="saveBtn">确认保存</button>
</div>
</div>
</div>
</div>
<script>
layui.use(['form', 'table'], function () {
var form = layui.form,
layer = layui.layer,
$ = layui.$;
/**
* 延迟初始化表单,以便传值显示
*/
setTimeout(function(){
//console.log("timeout!");
form.render();
},200)
// 当前弹出层防止ID被覆盖
var parentIndex = layer.index;
//监听提交
form.on('submit(saveBtn)', function (data) {
console.log(JSON.stringify(data.field));
$.ajax({
type:"POST",
url:"/sys/tenant/update",
contentType: "application/json;charset=UTF-8",
data: JSON.stringify(data.field),
success: function (result) {
console.log(result);
parent.onBaseParaUpdated();
},
error: function () {
console.log("ajax error");
}
});
layer.close(parentIndex);
return false;
});
});
</script>

View File

@ -0,0 +1,123 @@
<div class="layuimini-container layuimini-page-anim">
<div class="layuimini-main">
<table class="layui-hide" id="currentTableId" lay-filter="currentTableFilter"></table>
<script type="text/html" id="currentTableBar">
<a class="layui-btn layui-btn-normal layui-btn-xs data-count-edit" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-xs layui-btn-danger data-count-delete" lay-event="delete">删除</a>
</script>
<script type="text/html" id="toolbarTop">
<div class="layui-btn-container">
<button class="layui-btn layui-btn-normal layui-btn-sm data-add-btn" lay-event="add"> 添加 </button>
</div>
</script>
</div>
</div>
<script th:inline="none">
layui.use(['form', 'table','miniPage','element'], function () {
var $ = layui.jquery,
form = layui.form,
table = layui.table,
miniPage = layui.miniPage;
/**
* 初始化表单,要加上,不然刷新部分组件可能会不加载
*/
form.render();
table.render({
elem: '#currentTableId',
url: '/sys/tenant/list',
toolbar: '#toolbarTop',
cols: [[
{field: 'name', title: '企业名称'},
{field: 'contact', title: '联系方式'},
{title: '操作', toolbar: '#currentTableBar', align: "center", minWidth: 120}
]],
limits: [10, 15, 20, 25, 50, 100],
limit: 15,
page: true,
skin: 'line'
});
/**
* toolbar事件监听
*/
table.on('toolbar(currentTableFilter)', function (obj) {
if (obj.event === 'add') { // 监听添加操作
var content = miniPage.getHrefContent('sys/tenant/add');
var openWH = miniPage.getOpenWidthHeight();
var index = layer.open({
title: '新增组织',
type: 1,
shade: 0.2,
maxmin:true,
shadeClose: true,
area: [openWH[0] + 'px', openWH[1] + 'px'],
offset: [openWH[2] + 'px', openWH[3] + 'px'],
content: content,
});
$(window).on("resize", function () {
layer.full(index);
});
}
});
table.on('tool(currentTableFilter)', function (obj) {
var data = obj.data;
if (obj.event === 'edit') {
var content = miniPage.getHrefContent('sys/tenant/edit');
var openWH = miniPage.getOpenWidthHeight();
var index = layer.open({
title: '修改组织',
type: 1,
shade: 0.2,
maxmin:true,
shadeClose: true,
area: [openWH[0] + 'px', openWH[1] + 'px'],
offset: [openWH[2] + 'px', openWH[3] + 'px'],
content: content,
success: function (layero, index) {
layero.find('#id').val(data.id);
layero.find('#name').val(data.name);
layero.find('#contact').val(data.contact);
}
});
$(window).on("resize", function () {
layer.full(index);
});
return false;
} else if (obj.event === 'delete') {
layer.confirm('确定删除'+data.name+"?", function(index){
$.ajax({
type:"POST",
url:"/sys/tenant/delete",
data:{
'name':data.name
},
success: function (data) {
//data是cotroller相应处理函数的返回值
table.reload('currentTableId');
},
error: function () {
console.log("ajax error");
}
});
layer.close(index);
});
}
});
});
function onBaseParaUpdated(){
layui.table.reload('currentTableId');
}
</script>

View File

@ -7,28 +7,18 @@
<form class="layui-form layui-form-pane" action=""> <form class="layui-form layui-form-pane" action="">
<div class="layui-form-item"> <div class="layui-form-item">
<div class="layui-inline"> <div class="layui-inline">
<label class="layui-form-label">设备号</label> <label class="layui-form-label">用户名</label>
<div class="layui-input-inline"> <div class="layui-input-inline">
<input type="text" name="deviceid" autocomplete="off" class="layui-input"> <input type="text" name="username" autocomplete="off" class="layui-input">
</div> </div>
</div> </div>
<div class="layui-inline"> <div class="layui-inline">
<label class="layui-form-label">父设备</label> <label class="layui-form-label">手机</label>
<div class="layui-input-inline"> <div class="layui-input-inline">
<input type="text" name="parentid" autocomplete="off" class="layui-input"> <input type="text" name="mobile" autocomplete="off" class="layui-input">
</div> </div>
</div> </div>
<div class="layui-inline"> <div class="layui-inline">
<label class="layui-form-label">设备类型</label>
<div class="layui-input-inline">
<select name="devicetype" id="devicetype" lay-search="">
<option value="-1">全部</option>
<option value="0">监测站</option>
<option value="1">基准站</option>
</select>
</div>
</div>
<div class="layui-inline">
<button type="submit" class="layui-btn layui-btn-primary" lay-submit lay-filter="data-search-btn"><i class="layui-icon"></i> 搜 索</button> <button type="submit" class="layui-btn layui-btn-primary" lay-submit lay-filter="data-search-btn"><i class="layui-icon"></i> 搜 索</button>
</div> </div>
</div> </div>

View File

@ -10,11 +10,83 @@
</parent> </parent>
<artifactId>sec-common</artifactId> <artifactId>sec-common</artifactId>
<packaging>jar</packaging>
<properties> <properties>
<maven.compiler.source>8</maven.compiler.source> <maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target> <maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</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>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.5.8</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</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> </project>

View File

@ -1,4 +1,4 @@
package com.imdroid.sideslope.bd; package com.imdroid.common.util;
import java.io.*; import java.io.*;

View File

@ -1,4 +1,4 @@
package com.imdroid.sideslope.util; package com.imdroid.common.util;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.Charset; import java.nio.charset.Charset;

View File

@ -1,4 +1,4 @@
package com.imdroid.sideslope.util; package com.imdroid.common.util;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;

View File

@ -1,4 +1,4 @@
package com.imdroid.sideslope.util; package com.imdroid.common.util;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;

View File

@ -1,4 +1,4 @@
package com.imdroid.sideslope.util; package com.imdroid.common.util;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;

View File

@ -1,4 +1,4 @@
package com.imdroid.sideslope.util; package com.imdroid.common.util;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.regex.Matcher; import java.util.regex.Matcher;

View File

@ -1,4 +1,4 @@
package com.imdroid.sideslope.util; package com.imdroid.common.util;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;

View File

@ -1,4 +1,4 @@
package com.imdroid.sideslope.util; package com.imdroid.common.util;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.file.FileAppender; import cn.hutool.core.io.file.FileAppender;