Merge branch 'master' into feature/beidou

This commit is contained in:
fengyarnom 2025-02-12 17:44:05 +08:00
commit 6080c9646b
32 changed files with 325 additions and 361 deletions

View File

@ -1,6 +1,7 @@
package com.imdroid.secapi.client;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
@ -11,7 +12,10 @@ public interface RtcmClient {
@PostMapping("/config_by_udp")
HttpResp configByUdp(@RequestParam(name = "deviceId") String deviceId, @RequestParam(name = "configuration") String configData);
@PostMapping(value = "/config_device")
public HttpResp configDevice(@RequestParam(name = "deviceId") String deviceId, @RequestParam(name = "configuration") String configData);
@GetMapping(value = "/get_device_info")
public HttpResp getDeviceInfo(@RequestParam(name = "deviceId") String deviceId, @RequestParam(name = "cmd") String cmd);
@PostMapping("/device_param_changed")
HttpResp deviceParamChanged(@RequestParam(name = "deviceId") String deviceId,@RequestParam(name = "oldParentId") String oldParentId);

View File

@ -65,5 +65,5 @@ public class GnssDevice {
// 日志记录控制
private Short loggingmode;
private String remark;
}

View File

@ -92,4 +92,6 @@ public class GnssStatusJoin {
Double longitude;
@ExcelProperty("海拔")
Double altitude;
@ExcelProperty("备注")
String remark;
}

View File

@ -18,6 +18,7 @@ public class ResendRecord {
static public final short STATE_FWD_OK = 0;
static public final short STATE_FWD_FAILED = 1;
static public final short STATE_BREAK_POINT = 2;
static public final short STATE_FWDING = 3;
@TableId(value = "id", type = IdType.AUTO)
Long id;
Integer tenantid;

View File

@ -1,6 +1,7 @@
package com.imdroid.beidou_fwd.task;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.yulichang.query.MPJQueryWrapper;
import com.imdroid.beidou_fwd.entity.GZYMQTTData;
import com.imdroid.common.util.GsonUtil;
@ -198,7 +199,8 @@ public class Forwarder {
int sendNum = send(projectId, records, sendTime);
// 记录推送
// 非重发的才产生推送记录
if(resendRecord==null) {
FwdRecord fwdRecord = new FwdRecord();
fwdRecord.setProjectid(projectId);
fwdRecord.setTenantid(tenantId);
@ -206,19 +208,13 @@ public class Forwarder {
fwdRecord.setRecordtime(sendTime);
fwdRecord.setCreatetime(LocalDateTime.now());
fwdRecord.setFwd_group_id(fwdGroupId);
if(sendNum > 0) {
if (sendNum > 0) {
totalSendNum += sendNum;
fwdRecord.setResult(FwdRecord.RESULT_OK);
if(resendRecord != null){
resendRecord.setState(ResendRecord.STATE_FWD_OK);
resendRecordMapper.updateById(resendRecord);
}
}
else{
} else {
fwdResult = false;
fwdRecord.setResult(FwdRecord.RESULT_FAILED);
// 新增重发记录
if(resendRecord == null) {
resendRecord = new ResendRecord();
resendRecord.setProjectid(projectId);
resendRecord.setTenantid(tenantId);
@ -229,17 +225,15 @@ public class Forwarder {
resendRecord.setState(ResendRecord.STATE_FWD_FAILED);
resendRecordMapper.insert(resendRecord);
}
else{
resendRecord.setState(ResendRecord.STATE_FWD_FAILED);
resendRecordMapper.updateById(resendRecord);
}
}
fwdRecordsMapper.insert(fwdRecord);
}
}
// 更新推送记录
if(totalSendNum>0) updateFwd(totalSendNum, true);
else if(!fwdResult) updateFwd(totalSendNum, false);
if(resendRecord==null) {
if (totalSendNum > 0) updateFwd(totalSendNum, true);
else if (!fwdResult) updateFwd(totalSendNum, false);
}
return fwdResult;
}
@ -258,10 +252,20 @@ public class Forwarder {
QueryWrapper<ResendRecord> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("fwd_group_id",fwdGroupId);
queryWrapper.ne("state",ResendRecord.STATE_FWD_OK);
queryWrapper.ne("state",ResendRecord.STATE_FWDING);
queryWrapper.ge("createtime", LocalDateTime.now().minusDays(30));
List<ResendRecord> resendRecordsList = resendRecordMapper.selectList(queryWrapper);
if(resendRecordsList!=null){
logger.info("{} forward history records: {}",fwdGroupId, resendRecordsList.size());
//修改状态
UpdateWrapper<ResendRecord> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("fwd_group_id",fwdGroupId);
updateWrapper.ne("state",ResendRecord.STATE_FWD_OK);
updateWrapper.ne("state",ResendRecord.STATE_FWDING);
updateWrapper.ge("createtime", LocalDateTime.now().minusDays(30));
updateWrapper.set("state",ResendRecord.STATE_FWDING);
int updateNum = resendRecordMapper.update(null, updateWrapper);
logger.info("{} forward history records: {}, update {}",fwdGroupId, resendRecordsList.size(),updateNum);
// 2.检索这个这个时间段的解算结果如果有数据则单个终端转发标志记录为已补传
for(ResendRecord record:resendRecordsList){
if(record.getProjectid()!=null)
@ -273,10 +277,21 @@ public class Forwarder {
void forwardBatchGnssRecords(ResendRecord record) {
LocalDateTime sendTime = record.getStarttime();
int totalSend = 0;
while(sendTime.isBefore(record.getEndtime()) || sendTime.isEqual(record.getEndtime())){
forwardGnssRecords(sendTime,record);
if(forwardGnssRecords(sendTime,record)) totalSend++;
sendTime = sendTime.plusMinutes(fwdCycleMinutes);
}
if(totalSend>0) {
record.setState(ResendRecord.STATE_FWD_OK);
}
else{
record.setState(ResendRecord.STATE_FWD_FAILED);
}
resendRecordMapper.updateById(record);
}
int send(String projectId, List<GnssCalcData> records, LocalDateTime sentTime) {

View File

@ -1,124 +1,30 @@
package com.imdroid.beidou_fwd.task;
import com.imdroid.beidou_fwd.entity.XFZData;
import com.imdroid.beidou_fwd.service.TCPClient;
import com.imdroid.beidou_fwd.service.TCPListener;
import com.imdroid.common.util.GsonUtil;
import com.imdroid.common.util.NumberUtils;
import com.imdroid.secapi.dto.GnssCalcData;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Component
@Configuration
@EnableScheduling
public class GXXfz2Forwarder extends Forwarder{
static final String FORWARDER_NAME = "广西路建";
public class GXXfz2Forwarder extends GXXfzForwarder{
private String FORWARDER_NAME = "广西路建";
@Value("${gxlj.server.host}")
private String host;
@Value("${gxlj.server.port}")
private int port;
private TCPClient xfzTcpClient;
static class XFZTCPListener implements TCPListener{
public static final int STATE_NO_ACK = 0;
public static final int STATE_OK = 1;
public static final int STATE_FAILED = 2;
public int state = STATE_NO_ACK;
public void clear(){
state = STATE_NO_ACK;
}
@Override
public void onConnected() {
}
@Override
public void onDisconnect() {
}
@Override
public void onMessage(String msg) {
if(msg.contains("succeed")) state = STATE_OK;
else state = STATE_FAILED;
}
}
XFZTCPListener listener = new XFZTCPListener();
@PostConstruct
@Override
void registerMe(){
init(FORWARDER_NAME, "TCP "+host+":"+port,6,FWD_DEVICE_ID,30);
xfzTcpClient = new TCPClient();
xfzTcpClient.init(host, port,listener);
xfzTcpClient.start();
}
/**
* 每半小时转发GNSS解算结果
*/
@Scheduled(cron = "0 0/30 * * * ?") // 每30分钟执行一次
private void forwardGnss() {
logger.info("xfz forwardGnss");
forwardCurrentGnss();
}
@Override
int send(String projectId, List<GnssCalcData> records, LocalDateTime sentTime){
int sendNum = 0;
if(records.size() == 0) return 0;
XFZData xfzTcpMessage = new XFZData();
xfzTcpMessage.setProjectID(projectId);
xfzTcpMessage.setWorkPointID(projectId);
List<XFZData.Data> dataList = new ArrayList<>(records.size());
xfzTcpMessage.setData(dataList);
for(GnssCalcData locationRecord: records) {
XFZData.Data data = new XFZData.Data();
dataList.add(data);
data.setDataTime(locationRecord.getCreatetime().format(formatter));
data.setDevNum(locationRecord.getDeviceid());
data.setDevtype("GNSS");
// 单位由mm转化为m
data.setX(NumberUtils.scale(locationRecord.getRpose() * 0.001, 5));
data.setY(NumberUtils.scale(locationRecord.getRposn() * 0.001, 5));
data.setZ(NumberUtils.scale(locationRecord.getRposd() * 0.001, 5));
sendNum++;
}
String json = "#" + GsonUtil.toJson(xfzTcpMessage) + "!";
logger.info("project " + projectId + ": push calculation result to XFZ");
logger.info(json);
try {
listener.clear();
xfzTcpClient.writeAndFlush(json);
//等待应答
if(!checkResult()) sendNum = 0;
} catch (Exception e1) {
sendNum = 0;
e1.printStackTrace();
}
return sendNum;
}
boolean checkResult() throws InterruptedException {
// 等待应答最多等1s
for(int i=0; i<10; i++){
Thread.sleep(100);
if(listener.state == XFZTCPListener.STATE_OK) return true;
else if(listener.state == XFZTCPListener.STATE_FAILED) return false;
}
return false;
}
}

View File

@ -21,14 +21,14 @@ import java.util.List;
@Configuration
@EnableScheduling
public class GXXfzForwarder extends Forwarder{
static final String FORWARDER_NAME = "广西新发展";
private String FORWARDER_NAME = "广西新发展";
@Value("${xfz.server.host}")
private String host;
@Value("${xfz.server.port}")
private int port;
private TCPClient xfzTcpClient;
TCPClient xfzTcpClient;
static class XFZTCPListener implements TCPListener{
public static final int STATE_NO_ACK = 0;

View File

@ -0,0 +1,31 @@
package com.imdroid.beidou_fwd.task;
import com.imdroid.beidou_fwd.service.TCPClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
@Configuration
@EnableScheduling
public class GZBForwarder extends GXXfzForwarder{
private String FORWARDER_NAME = "葛洲坝";
@Value("${gzb.server.host}")
private String host;
@Value("${gzb.server.port}")
private int port;
@PostConstruct
@Override
void registerMe(){
init(FORWARDER_NAME, "TCP "+host+":"+port,1,FWD_DEVICE_ID,30);
xfzTcpClient = new TCPClient();
xfzTcpClient.init(host, port,listener);
xfzTcpClient.start();
}
}

View File

@ -152,7 +152,7 @@ public class FocusCalculator1 implements FocusCalculator{
// 求初始重心
double[] focus = focusPointObj(selectPoints);
logger.info("seed focus {},{},{},select size {}",focus[0],focus[1],focus[2],selectPoints.size());
logger.debug("seed focus {},{},{},select size {}",focus[0],focus[1],focus[2],selectPoints.size());
// 迭代计算重心直到选出50%的点
List<double[]> filteredPoints=null;
@ -165,10 +165,10 @@ public class FocusCalculator1 implements FocusCalculator{
if(filteredPoints.size() == 0) continue;
focus = focusPoint(filteredPoints);
}while ((double)filteredPoints.size()/pointList.size() < pointSelectedRate);
if(null!=filteredPoints) logger.info("calc focus r:{}, point num:{}",r,filteredPoints.size());
if(null!=filteredPoints) logger.debug("calc focus r:{}, point num:{}",r,filteredPoints.size());
return focus;
}else{
logger.info("calc focus iter num:0, point num:{}",selectPoints.size());
logger.debug("calc focus iter num:0, point num:{}",selectPoints.size());
return focus;
}

View File

@ -99,7 +99,7 @@ public class FocusCalculator2 extends FocusCalculator1{
while (iterator.hasNext()){
pointList.addAll(iterator.next().getValue());
}
logger.info("total fixed point num to calculated: {},{},{}",pointList.size(),
logger.debug("total fixed point num to calculated: {},{},{}",pointList.size(),
cyclePointList.get(0).getKey(), cyclePointList.get(cyclePointList.size()-1).getKey());
if(pointList.size() >= gravityMaxCount){

View File

@ -14,37 +14,19 @@ import static com.imdroid.sideslope.bd.GeoCoordConverterUtil.*;
* 博通用GGA绝对坐标代替相对位置
*/
public class FocusCalculator3 extends FocusCalculator1{
//final static long scale = 100000000L;//地球1°111km放大到mm乘以100,000,000
final static int bad_change_mm = 500;//固定解跳变连续10次超过500mm认为是周跳
final static int bad_duration = 10;
int bad_count = 0;
Device bsDevice;
public FocusCalculator3(Device bsDevice){
super();
this.bsDevice = bsDevice;
gravityMinCount = 80;
}
/*
static class EComparator implements Comparator<double[]>{
@Override
public int compare(double[] point1, double[] point2) {
return Double.compare(point1[1], point2[1]);
//return (int) ((point1[0] - point2[0])*100);
}
}
static class NComparator implements Comparator<double[]>{
@Override
public int compare(double[] point1, double[] point2) {
return Double.compare(point1[1], point2[1]);
//return (int) ((point1[1] - point2[1])*100);
}
}
static class DComparator implements Comparator<double[]>{
@Override
public int compare(double[] point1, double[] point2) {
return Double.compare(point1[1], point2[1]);
//return (int) ((point1[2] - point2[2])*100);
}
}
*/
@Override
public void addGGA(Gga gga) {
if(gga == null) return;
@ -69,7 +51,6 @@ public class FocusCalculator3 extends FocusCalculator1{
// 以基站为站心的 ENU 坐标
ENU_Coordinate difference_enu = ECEF2ENU(reference_ecef, rover_ecef);
System.out.println("DIFF ENU:" + difference_enu.ENU_E + " " + difference_enu.ENU_N + " " + difference_enu.ENU_U);
end = new double[]{
difference_enu.ENU_E*1000,
difference_enu.ENU_N*1000,
@ -79,7 +60,17 @@ public class FocusCalculator3 extends FocusCalculator1{
if(gga.isFixed()) {
counterFixedResult++;
//pointList.add(xyz);
if(pointList.size()>0){
double[] lastXyz = pointList.get(pointList.size()-1);
if(Math.abs(end[0]-lastXyz[0])>bad_change_mm ||
Math.abs(end[1]-lastXyz[1])>bad_change_mm ||
Math.abs(end[2]-lastXyz[2])>bad_change_mm){
bad_count++;
return;
}
}
bad_count = 0;
pointList.add(end);
}
else if(gga.getQuality() == 5) counterNoFixed++;
@ -95,33 +86,6 @@ public class FocusCalculator3 extends FocusCalculator1{
}
/*double calcGravity(List<double[]> list , int index){
double sum = 0;
int begin = (int) (list.size() * 0.25);
int end = (int) (list.size() * 0.75);
if(end-begin == 0) return 0;
for(int i=begin; i<end; i++){
sum += list.get(i)[index];
}
return sum/(end-begin);
}
@Override
public double[] resultB562(){
if(pointList.size() >= 3){
Collections.sort(pointList, new EComparator());
double e = calcGravity(pointList,0);
Collections.sort(pointList, new NComparator());
double n = calcGravity(pointList,1);
Collections.sort(pointList, new DComparator());
double d = calcGravity(pointList,2);
return new double[]{e,n,d};
}
return null;
}*/
@Override
public double[] resultB562(){
try {
@ -166,9 +130,23 @@ public class FocusCalculator3 extends FocusCalculator1{
return null;
}
@Override
public void reset(){
super.reset();
bad_count = 0;
}
@Override
public int getVer() {
return 3;
}
public boolean isJump(){
if (bad_count>bad_duration){
bad_count = 0;
return true;
}
else return false;
}
}

View File

@ -87,7 +87,7 @@ public class FocusCalculator5 implements FocusCalculator{
pointList.clear();
}
else{
logger.info("{} num of fixed points:{}, less than {}",deviceId, pointList.size(),minPointNum);
logger.debug("{} num of fixed points:{}, less than {}",deviceId, pointList.size(),minPointNum);
}
tilts.clear();
counterNoB562 = 0;
@ -148,7 +148,7 @@ public class FocusCalculator5 implements FocusCalculator{
//取交集
eList.retainAll(nList);
eList.retainAll(uList);
logger.info("{} fixed point selected: {}", deviceId, eList.size());
logger.debug("{} fixed point selected: {}", deviceId, eList.size());
if(eList.size() == 0) return null;
//求均值

View File

@ -63,7 +63,7 @@ public class FocusCalculator6 implements FocusCalculator{
pointList.clear();
}
else{
logger.info("{} num of fixed points:{}, less than {}",deviceId, pointList.size(),minPointNum);
logger.debug("{} num of fixed points:{}, less than {}",deviceId, pointList.size(),minPointNum);
}
tilts.clear();
counterNoB562 = 0;

View File

@ -1,117 +0,0 @@
package com.imdroid.sideslope.bd;
import com.imdroid.sideslope.sal.Device;
import static com.imdroid.sideslope.bd.GeoCoordConverterUtil.ECEF2ENU;
import static com.imdroid.sideslope.bd.GeoCoordConverterUtil.LLA2ECEF;
/**
* 博通用GGA绝对坐标代替相对位置
*/
public class FocusCalculator7 extends FocusCalculator3{
//final static long scale = 100000000L;//地球1°111km放大到mm乘以100,000,000
final static int bad_change_mm = 500;//固定解跳变连续10次超过500mm认为是周跳
final static int bad_duration = 10;
int bad_count = 0;
public FocusCalculator7(Device bsDevice) {
super(bsDevice);
}
/*@Override
public void addGGA(Gga gga) {
if(gga == null) return;
double[] xyz = new double[]{gga.getLongitude()*scale, gga.getLatitude()*scale, gga.getAltitude()*1000, gga.getQuality()};
if(gga.isFixed()) {
counterFixedResult++;
if(pointList.size()>0){
double[] lastXyz = pointList.get(pointList.size()-1);
if(Math.abs(xyz[0]-lastXyz[0])>bad_change_mm ||
Math.abs(xyz[1]-lastXyz[1])>bad_change_mm ||
Math.abs(xyz[2]-lastXyz[2])>bad_change_mm){
bad_count++;
return;
}
}
bad_count = 0;
pointList.add(xyz);
}
else if(gga.getQuality() == 5) counterNoFixed++;
else counterNoB562 ++;
}*/
@Override
public void addGGA(Gga gga) {
if(gga == null) return;
double[] end;
// 测站的GGA - 测站 LLA 数据
GeoCoordConverterUtil.LLA_Coordinate rover_lla = new GeoCoordConverterUtil.LLA_Coordinate(gga.getLatitude(),gga.getLongitude(),gga.getAltitude());
// 测站 LLA 坐标转 ECEF 坐标单位米
GeoCoordConverterUtil.ECEF_Coordinate rover_ecef = LLA2ECEF(rover_lla);
if(bsDevice==null || bsDevice.getEcefx()==null){
end = new double[]{
rover_ecef.getECEF_X()*1000,
rover_ecef.getECEF_Y()*1000,
rover_ecef.getECEF_Z()*1000,
gga.getQuality()};
}
else {
// 查询测站的绑定的基站
GeoCoordConverterUtil.ECEF_Coordinate reference_ecef = new GeoCoordConverterUtil.ECEF_Coordinate(bsDevice.getEcefx(), bsDevice.getEcefy(), bsDevice.getEcefz());
// 以基站为站心的 ENU 坐标
GeoCoordConverterUtil.ENU_Coordinate difference_enu = ECEF2ENU(reference_ecef, rover_ecef);
end = new double[]{
difference_enu.ENU_E*1000,
difference_enu.ENU_N*1000,
difference_enu.ENU_U*1000,
gga.getQuality()};
}
if(gga.isFixed()) {
counterFixedResult++;
if(pointList.size()>0){
double[] lastXyz = pointList.get(pointList.size()-1);
if(Math.abs(end[0]-lastXyz[0])>bad_change_mm ||
Math.abs(end[1]-lastXyz[1])>bad_change_mm ||
Math.abs(end[2]-lastXyz[2])>bad_change_mm){
bad_count++;
return;
}
}
bad_count = 0;
pointList.add(end);
}
else if(gga.getQuality() == 5) counterNoFixed++;
else counterNoB562 ++;
}
@Override
public void reset(){
super.reset();
bad_count = 0;
}
@Override
public int getVer() {
return 7;
}
public boolean isJump(){
if (bad_count>bad_duration){
bad_count = 0;
return true;
}
else return false;
}
}

View File

@ -85,16 +85,13 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
if(device == null) return;
GnssGroupCalc groupCalc = getGroupCalc(device.getCalcGroupId());
if(groupCalc==null) return;
device.setB562AsCalc(groupCalc.getVer()!=3 && groupCalc.getVer()!=7);
device.setB562AsCalc(groupCalc.getVer()!=3);
if(completeWhenIdle) resultOutputTimer(device, groupCalc, message.getCreateTime());
//todo 创建FocusCalculator对象需获取该测站的杆长度上一小时的Tilt平均值上一小时的测站相对坐标融合值ekfResult
FocusCalculator focusCalculator;
if(groupCalc.getVer() == 7){
focusCalculator = calculatorMap.computeIfAbsent(deviceId,s -> new FocusCalculator7(null));
}
else if(groupCalc.getVer() == 6){
if(groupCalc.getVer() == 6){
focusCalculator = calculatorMap.computeIfAbsent(deviceId,s -> new FocusCalculator6(deviceId, 50));
}
else if(groupCalc.getVer() == 5){
@ -136,16 +133,16 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
double[] doubles = message.getB562_loc();//unit: mm
if(doubles !=null) {
focusCalculator.addXyz(doubles, message.getCreateTime());
logger.info("测站{}的b562单次解析结果:{}", deviceId,Arrays.toString(doubles));
logger.debug("测站{}的b562单次解析结果:{}", deviceId,Arrays.toString(doubles));
}
// 单次GGA
Gga gga = message.getGga();
if(gga != null) {
focusCalculator.addGGA(gga);
logger.info("测站{}的gga单次解析结果:{},{},{},{}",deviceId,
logger.debug("测站{}的gga单次解析结果:{},{},{},{}",deviceId,
gga.getLongitude(), gga.getLatitude(), gga.getAltitude(), gga.getQuality());
if(groupCalc.getVer() == 7 && focusCalculator.isJump()){
if(groupCalc.getVer() == 3 && focusCalculator.isJump()){
logger.info("{}发生周跳",deviceId);
hardResetDevice(deviceId);
}
@ -227,11 +224,11 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
}*/
Tilt tilt = focusCalculator.avgTilt();
logger.info("测站 {} 的b562相对坐标重心:{}", deviceId, Arrays.toString(b562Result));
logger.info("测站 {} 参考坐标:{}", deviceId, Arrays.toString(referPos));
logger.debug("测站 {} 的b562相对坐标重心:{}", deviceId, Arrays.toString(b562Result));
logger.debug("测站 {} 参考坐标:{}", deviceId, Arrays.toString(referPos));
//logger.info("测站 {} 的惯导相对坐标:{}", deviceId, Arrays.toString(r9250Result));
//logger.info("测站 {} 的相对坐标融合值:{}", deviceId, Arrays.toString(mergeResult));
logger.info("测站 {} 的Tilt平均值:{}", deviceId, tilt);
logger.debug("测站 {} 的Tilt平均值:{}", deviceId, tilt);
/*
if (mergeResult != null && b562Result != null) {
//这里检查一下result过滤1千米外非正常数据
@ -273,7 +270,7 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
gnssCalcFilterService.calc(device, groupCalc, locationRecord, latestRpos);
}
else {
if(focusCalculator.getVer()==1 || focusCalculator.getVer()==3 || focusCalculator.getVer()==5 || focusCalculator.getVer()==7){
if(focusCalculator.getVer()==1 || focusCalculator.getVer()==3 || focusCalculator.getVer()==5){
gnssCalcFilterService.calc(device, groupCalc, locationRecord, null);
}
else {
@ -299,7 +296,7 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
if(latestRpos != null) focusCalculator.setReferPoint(latestRpos);
else {
double[] avgEnu = gnssCalcFilterService.calcFilterValueByLastDay(locationRecord);
logger.info("{} calc 24 hours filtered pos", deviceId);
logger.debug("{} calc 24 hours filtered pos", deviceId);
if (avgEnu != null) {
((FocusCalculator6) focusCalculator).setOriginalReferPoint(avgEnu);
}
@ -316,7 +313,7 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
else focusCalculator.setReferPoint(b562Result);
}
}
else if(focusCalculator.getVer()==1 || focusCalculator.getVer()==3 || focusCalculator.getVer()==5 || focusCalculator.getVer()==7) {
else if(focusCalculator.getVer()==1 || focusCalculator.getVer()==3 || focusCalculator.getVer()==5) {
focusCalculator.setReferPoint(b562Result);
}
else {
@ -324,23 +321,23 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
if(focusCalculator2.isOriginalReferPointSet()) {
if (locationRecord.getEnabled() && locationRecord.getRpose() != null) {
focusCalculator2.setReferPoint(new double[]{locationRecord.getRpose(), locationRecord.getRposn(), locationRecord.getRposd()});
logger.info("{} set reference pos to filter result:{},{},{}",
logger.debug("{} set reference pos to filter result:{},{},{}",
deviceId, locationRecord.getRpose(), locationRecord.getRposn(), locationRecord.getRposd());
}
else{
logger.info("{} reference pos not changed",deviceId);
logger.debug("{} reference pos not changed",deviceId);
}
}
else{
// 查询设备有没有配置初始位置
if(device.getIPose()!=null){
focusCalculator2.setOriginalReferPoint(new double[]{device.getIPose(),device.getIPosn(),device.getIPosd()});
logger.info("{} set reference pos to init pos:{},{},{}",
logger.debug("{} set reference pos to init pos:{},{},{}",
deviceId,device.getIPose(),device.getIPosn(),device.getIPosd());
}
else{
focusCalculator.setReferPoint(b562Result);
logger.info("{} set reference pos to b562 result",deviceId);
logger.debug("{} set reference pos to b562 result",deviceId);
}
}
}
@ -386,7 +383,7 @@ public class SingleLineGNSSCalcService implements GNSSDataCalcService {
queryWrapper.last("limit 1");
GnssCalcData gnssCalcData = dataMapper.selectOne(queryWrapper);
if(gnssCalcData != null){
logger.info("{} getLatestPos", deviceId);
logger.debug("{} getLatestPos", deviceId);
return new double[]{gnssCalcData.getRpose(),gnssCalcData.getRposn(),gnssCalcData.getRposd()};
}
return null;

View File

@ -8,6 +8,7 @@ import com.imdroid.sideslope.bd.Gga;
import com.imdroid.sideslope.message.D331RtcmMessage;
import com.imdroid.sideslope.sal.Device;
import com.imdroid.sideslope.sal.DeviceService;
import com.imdroid.sideslope.server.DeviceChannel;
import com.imdroid.sideslope.server.OnlineChannels;
import com.imdroid.sideslope.service.DataPersistService;
import io.netty.buffer.ByteBuf;
@ -49,10 +50,18 @@ public class D331RtcmMessageExecutor implements Executor<D331RtcmMessage, Void>
// 要求快速转发因此用缓存不要每次都查数据库
List<Device> deviceList = deviceService.findByParentId(id);
//logger.debug("base station {} has {} rovers: ", message.getId(),deviceList.size());
DeviceChannel deviceChannel = null;
for (Device device : deviceList) {
if (device.getOpMode() != GnssDevice.OP_MODE_USE) continue;
String deviceId = device.getDeviceId();
OnlineChannels.INSTANCE.get(deviceId).ifPresent(deviceChannel -> {
if(device.getDataChannelType() == Device.CHANNEL_TYPE_UDP) {
deviceChannel = OnlineChannels.INSTANCE.getDataChannel(deviceId);
}
else {
deviceChannel = OnlineChannels.INSTANCE.getConfigChannel(deviceId);
}
if(deviceChannel!=null && deviceChannel.isOnline()){
if (logger.isDebugEnabled()) {
logger.debug("forward d331 rtcm to device {}", deviceId);
}
@ -62,7 +71,7 @@ public class D331RtcmMessageExecutor implements Executor<D331RtcmMessage, Void>
ByteBuf buf = Unpooled.buffer();
buf.writeBytes(forwardBytes);
deviceChannel.writeAndFlush(buf);
});
}
}
}

View File

@ -100,13 +100,13 @@ public class D341LocationMessageExecutor implements Executor<D341LocationMessage
if(device.getLoggingmode() == GnssDevice.LOGGING_MODE_FULL){
logger.info("receive {} d341 message: {}", message.getId(), DataTypeUtil.getHexString(message.getSrcData()));
}
else {
/*else {
Gga gga1 = message.getGga();
if (gga1 != null && !gga1.isFixed()) {
// 若不是固定解则打印原始码流到日志里
logger.info("receive {} d341 message: {}", message.getId(), DataTypeUtil.getHexString(message.getSrcData()));
}
}
}*/
});
return null;

View File

@ -53,7 +53,7 @@ public class D3F0SelfCheckMessageExecutor implements Executor<D3F0SelfCheckMessa
@Override
public Void execute(D3F0SelfCheckMessage message) {
logger.info("receive d3f0 message of {} device: {}", message.getId(), DataTypeUtil.getHexString(message.getSrcData()));
logger.debug("receive d3f0 message of {} device: {}", message.getId(), DataTypeUtil.getHexString(message.getSrcData()));
Device device = deviceService.findByDeviceId(message.getId());
if(device == null) return null;
@ -111,9 +111,21 @@ public class D3F0SelfCheckMessageExecutor implements Executor<D3F0SelfCheckMessa
}
}*/
boolean isBaseStationFwd(Device device){
Device bsDevice = deviceService.findByDeviceId(device.getParentId());
if(bsDevice != null){
LocalDateTime lastRxTime = bsDevice.getLastRxTime();
if(lastRxTime != null &&
lastRxTime.isAfter(LocalDateTime.now().minusMinutes(10))){
return true;
}
}
return false; //最近10分钟基站没有转发数据可能是基站故障
}
private void checkAndSendF9PColdStartCommand(Device device){
if((device.getWarningcode()&WarningCfg.TYPE_NO_FIXED_RESULT) !=0){
startF9PColdStartTask(device);
if(isBaseStationFwd(device)) startF9PColdStartTask(device);
device.clearNoResultStat();
}
}
@ -169,11 +181,11 @@ public class D3F0SelfCheckMessageExecutor implements Executor<D3F0SelfCheckMessa
private void checkAndResetBTGnss(Device device){
if(device.getNoFixedAndFloatResult()>0 &&device.getAbnormalD341Num()>10){
startBTResetTask(device);
if(isBaseStationFwd(device)) startBTResetTask(device);
device.clearNoResultStat();
}
else if((device.getWarningcode()&WarningCfg.TYPE_CONT_INVALID_RESULT) !=0){
startBTHotStartTask(device);
if(isBaseStationFwd(device)) startBTHotStartTask(device);
device.clearNoResultStat();
}
}

View File

@ -48,7 +48,7 @@ public class D3F2StopIndicationMessageExecutor implements Executor<D3F2StopIndic
@Override
public Void execute(D3F2StopIndicationMessage message) {
logger.info("receive d3f2 message of {} device: {}", message.getId(), DataTypeUtil.getHexString(message.getSrcData()));
logger.debug("receive d3f2 message of {} device: {}", message.getId(), DataTypeUtil.getHexString(message.getSrcData()));
// 补齐tenantId
String deviceId = message.getId();

View File

@ -26,6 +26,9 @@ public class Device {
*/
public static final int DEVICE_ROVER = 0;
public static final byte CHANNEL_TYPE_TCP = 0;
public static final byte CHANNEL_TYPE_UDP = 1;
private String name;
private Integer tenantId;
@ -77,6 +80,8 @@ public class Device {
LocalDateTime lastValidCalcDataTime; //最近一次有效解
int warningcode = 0;
short abnormalD341Num = 0;
byte cfgChannelType = CHANNEL_TYPE_TCP; // 0:TCP;1:DUP
byte dataChannelType = CHANNEL_TYPE_UDP; // 0:TCP;1:DUP
public void updateRx(int head, int bytes,int count){
lastRxHead = head;

View File

@ -49,7 +49,7 @@ public class RtcmTcpHandler extends SimpleChannelInboundHandler<ByteBuf> {
@Override
public void channelInactive(ChannelHandlerContext ctx)
throws Exception {
logger.info("channel inactive");
logger.debug("channel inactive");
ctx.close();
}

View File

@ -46,7 +46,9 @@ public class RtcmUdpHandler extends ChannelInboundHandlerAdapter {
}
BizExecutors.execute(message);
} catch (UnSupportedMessageException e) {
logger.warn("receive un supported message: {}", e.getMessage());
byte[] data = new byte[packet.content().readableBytes()];
packet.content().getBytes(0, data);
logger.warn("receive un supported message: {}", DataTypeUtil.getHexString(data));
} catch (Exception e) {
logger.error("channel read error: {}", e.toString());
} finally {

View File

@ -286,7 +286,6 @@ public class WarningServiceImpl implements WarningService {
queryWrapper.last("limit 1");
WarningMsg warningMsg = warningMsgMapper.selectOne(queryWrapper);
if(warningMsg!=null){
logger.info("update warningMsg {}",warningMsg.getId());
warningMsg.setCleartime(LocalDateTime.now());
warningMsgMapper.updateById(warningMsg);
}

View File

@ -4,6 +4,7 @@ import com.imdroid.common.util.DataTypeUtil;
import com.imdroid.secapi.client.HttpResp;
import com.imdroid.sideslope.calc.MultiLineGNSSCalcService;
import com.imdroid.sideslope.calc.SingleLineGNSSCalcService;
import com.imdroid.sideslope.sal.Device;
import com.imdroid.sideslope.sal.LocalDeviceServiceImpl;
import com.imdroid.sideslope.server.DeviceChannel;
import com.imdroid.sideslope.server.OnlineChannels;
@ -13,6 +14,7 @@ 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.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@ -54,7 +56,7 @@ public class ApiController {
// send command
ByteBuf buf = Unpooled.buffer();
byte[] data = getBinaryData(ConfigDataTypeEnum.HEX, configuration);
logger.info("send command:{}", configuration);
logger.debug("send command:{}", configuration);
buf.writeBytes(data);
deviceChannel.writeAndFlush(buf);
}
@ -81,7 +83,7 @@ public class ApiController {
// send command
ByteBuf buf = Unpooled.buffer();
byte[] data = getBinaryData(ConfigDataTypeEnum.HEX, configuration);
logger.info("send command:{}", configuration);
logger.debug("send command:{}", configuration);
buf.writeBytes(data);
deviceChannel.writeAndFlush(buf);
}
@ -97,6 +99,75 @@ public class ApiController {
return resp;
}
@PostMapping(value = "/config_device")
public HttpResp configDevice(String deviceId, String configuration) {
Map<String, Object> status = new HashMap<>();
HttpResp resp = new HttpResp();
// set channel0/channel1 tcp/udp
String[] paras = configuration.split("=| ");
Device device = localDeviceService.findByDeviceId(deviceId);
if(device!=null){
resp.setResponseMessage("set OK.");
if(paras.length>=3){
if(paras[1].equals("channel1")){
if(paras[2].equals("tcp")) device.setDataChannelType(Device.CHANNEL_TYPE_TCP);
else device.setDataChannelType(Device.CHANNEL_TYPE_UDP);
}
else if(paras[1].equals("channel0")){
if(paras[2].equals("tcp")) device.setCfgChannelType(Device.CHANNEL_TYPE_TCP);
else device.setCfgChannelType(Device.CHANNEL_TYPE_UDP);
}
}
else{
status.put("paras", "error");
}
}
else {
status.put("status", "Offline");
resp.setCode(HttpResp.HTTP_RSP_FAILED);
resp.setResponseMessage("Offline.");
}
resp.setResponseObject(status);
return resp;
}
@GetMapping(value = "/get_device_info")
public HttpResp getDeviceInfo(String deviceId, String cmd) {
Map<String, Object> status = new HashMap<>();
HttpResp resp = new HttpResp();
// get channel0/channel1 type
String[] paras = cmd.split("=| ");
Device device = localDeviceService.findByDeviceId(deviceId);
if(device!=null){
resp.setResponseMessage("set OK.");
if(paras.length>=3){
if(paras[2].equals("type")) {
if (paras[1].equals("channel1")) {
if (device.getDataChannelType()==Device.CHANNEL_TYPE_TCP) {
resp.setResponseMessage(paras[1]+" tcp");
}
else resp.setResponseMessage(paras[1]+" udp");
} else if (paras[1].equals("channel0")) {
if (device.getCfgChannelType()==Device.CHANNEL_TYPE_TCP) {
resp.setResponseMessage(paras[1]+" tcp");
}
else resp.setResponseMessage(paras[1]+" udp");
}
}
}
else{
status.put("paras", "error");
}
}
else {
status.put("status", "Offline");
resp.setCode(HttpResp.HTTP_RSP_FAILED);
resp.setResponseMessage("Offline.");
}
resp.setResponseObject(status);
return resp;
}
@PostMapping("/device_param_changed")
public HttpResp deviceParamChanged(String deviceId, String oldParentId) {
// 更新设备缓存

View File

@ -70,9 +70,21 @@ public class CmdLineController extends BasicController{
return HttpResult.fail("设备号不能为空");
}
String sendCmd = cmd.replaceAll(" +","");
String sendCmd;
short len = 0;
int msgType = 0xD310 + cmdType;
HttpResp<HashMap<String, Object>> rsp;
if(cmd.startsWith("set")||cmd.startsWith("get")){
msgType = 0xD3FF;//后台命令
sendCmd = cmd;
len = (short) cmd.length();
if(cmd.charAt(0)=='s') rsp = rtcmClient.configDevice(deviceId,sendCmd);
else rsp = rtcmClient.getDeviceInfo(deviceId,sendCmd);
}
else{
sendCmd = cmd.replaceAll(" +","");
if(cmdType == 10 || cmdType==11){ // DTU,string format
len = (short) (sendCmd.length() + 5);
sendCmd = Integer.toHexString(msgType) + HexUtil.Short2HexString(len)+
@ -84,10 +96,10 @@ public class CmdLineController extends BasicController{
sendCmd = Integer.toHexString(msgType) + HexUtil.Short2HexString(len)+
HexUtil.Int2HexString(Integer.parseInt(deviceId))+sendCmd;
}
HttpResp<HashMap<String, Object>> rsp;
if(sendChannel == 0)
rsp = rtcmClient.config(deviceId,sendCmd);
else rsp = rtcmClient.configByUdp(deviceId,sendCmd);
}
String txInfo = "TX "+ dateFormat.format(System.currentTimeMillis())+
" "+deviceId+" "+sendCmd;
@ -95,6 +107,9 @@ public class CmdLineController extends BasicController{
if(rsp.getCode() != HttpResp.HTTP_RSP_OK){
txInfo += "\r\n" + rsp.getResponseMessage();
}
else if(msgType == 0xD3FF){
txInfo += "\r\n" + rsp.getResponseMessage();
}
// 保存
GnssMsg gnssMsg = new GnssMsg();

View File

@ -135,6 +135,11 @@ public class GnssDeviceController extends BasicController{
if (StringUtils.hasText(appver)) {
queryWrapper.like("appver", appver);
}
//备注
String remark = search.getString("remark");
if (StringUtils.hasText(remark)) {
queryWrapper.like("remark", remark);
}
//使用状态
Integer opmode = search.getInteger("opmode");
if (opmode != null && opmode != QUERY_ALL) {

View File

@ -99,7 +99,7 @@ public class GnssStatusController extends BasicController implements CommonExcel
public MPJQueryWrapper<GnssStatus> prepareQueryWrapper() {
return new MPJQueryWrapper<GnssStatus>()
.selectAll(GnssStatus.class)
.select("d.devicetype as devicetype")
.select("d.devicetype as devicetype,d.remark as remark")
.leftJoin("gnssdevices d on t.deviceid = d.deviceid")
.orderByDesc("t.updatetime");
}

View File

@ -82,6 +82,12 @@
</select>
</div>
</div>
<div class="layui-inline" th:if="${role=='SUPER_ADMIN'}">
<label class="layui-form-label">备注</label>
<div class="layui-input-inline">
<input type="text" name="remark" id="remark" autocomplete="off" class="layui-input">
</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>
</div>
@ -113,6 +119,7 @@
table = layui.table;
var cfg_cols = [
{field: 'deviceid', title: '设备号', width: 100, sort: true},
{field: 'remark', title: '备注', width: 100},
{field: 'project_id', title: '项目号', width: 120, sort: true},
{field: 'sector', title: '桩号', width: 120, sort: true},
{field: 'name', title: '监测点号', width: 80},
@ -131,10 +138,13 @@
{title: '操作', toolbar: '#currentTableBar', fixed: "right", width: 120}
];
if([[${role}]] == "USER") {
cfg_cols[15].hide = true;
cfg_cols[17].hide = true;
}
else if([[${role}]] != "SUPER_ADMIN") {
cfg_cols[1].hide = true;
}
if([[${tenant_id}]] != 0) {
cfg_cols[10].hide = true;
cfg_cols[11].hide = true;
}
/**
* 初始化表单,要加上,不然刷新部分组件可能会不加载

View File

@ -61,6 +61,12 @@
</select>
</div>
</div>
<div class="layui-inline" th:if="${role=='SUPER_ADMIN'}">
<label class="layui-form-label">备注</label>
<div class="layui-input-inline">
<input type="text" name="sl_d.remark" autocomplete="off" class="layui-input">
</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-export-btn"><i class="layui-icon">&#xe67d;</i>导出</button>
@ -92,6 +98,7 @@
table = layui.table;
var cfg_cols = [
{field: 'deviceid', title: '设备号', sort: true},
{field: 'remark', title: '备注', width: 100},
{field: 'devicetype', title: '设备类型',templet: '#typeTrans'},
{field: 'updatetime', title: '更新时间', templet: "<div>{{layui.util.toDateString(d.updatetime, 'yyyy-MM-dd HH:mm:ss')}}</div>"},
{field: 'state', title: '状态',templet: '#stateTrans'},
@ -107,6 +114,9 @@
{field: 'latitude', title: '纬度'},
{title: '操作', toolbar: '#currentTableBar', fixed: "right", width: 80}
];
if([[${role}]] != "SUPER_ADMIN") {
cfg_cols[1].hide = true;
}
/**
* 初始化表单,要加上,不然刷新部分组件可能会不加载
*/

View File

@ -128,8 +128,10 @@
<span class="layui-badge layui-bg-green">推送成功</span>
{{# } else if(d.state == 1){ }}
<span class="layui-badge layui-bg-red">推送失败</span>
{{# } else if(d.state == 2){ }}
<span class="layui-badge layui-bg-red">断点补传</span>
{{# } else { }}
<span class="layui-badge layui-bg-orange">断点补传</span>
<span class="layui-badge layui-bg-orange">推送中</span>
{{# } }}
</script>

View File

@ -207,6 +207,13 @@
</div>
</div>
<hr>
<div class="layui-form-item" th:if="${role=='SUPER_ADMIN'}">
<label class="layui-form-label">备注</label>
<div class="layui-input-block">
<input type="text" name="remark" id="remark" class="layui-input">
</div>
</div>
<hr th:if="${role=='SUPER_ADMIN'}">
<div class="layui-form-item">
<div class="layui-input-block" style="float:right" >
<button class="layui-btn layui-btn-normal" lay-submit lay-filter="saveBtn">确认保存</button>
@ -312,6 +319,7 @@
$('#ecefz').val(data.ecefz);
$('#model').val(data.model);
$('#sector').val(data.sector);
$('#remark').val(data.remark);
setEcefEditor();
form.render();
}

View File

@ -39,7 +39,6 @@
<option value="4">4</option>
<option value="5">5</option>
<option value="6">6</option>
<option value="7">7</option>
</select>
</div>
</div>