Merge remote-tracking branch 'origin/feature/beidou' into feature/beidou

This commit is contained in:
fengyarnom 2025-02-18 12:26:57 +08:00
commit 74a0747a3c
4 changed files with 246 additions and 8 deletions

View File

@ -5,6 +5,9 @@ import com.imdroid.common.util.ByteUtil;
import com.imdroid.common.util.StringUtil; import com.imdroid.common.util.StringUtil;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import static java.lang.Math.*; import static java.lang.Math.*;
@ -13,6 +16,110 @@ public class RtcmGgaUtil {
//gga样本*后面跟的是校验和其中76代表校验和对$和*之间的数据不包括这两个字符按字节进行异或运算二进制的结果 //gga样本*后面跟的是校验和其中76代表校验和对$和*之间的数据不包括这两个字符按字节进行异或运算二进制的结果
private static final String ggaExample = "$GNGGA,020850.50,2258.10508,N,11317.67958,E,4,12,0.74,3.9,M,-5.4,M,1.3,0000*76"; private static final String ggaExample = "$GNGGA,020850.50,2258.10508,N,11317.67958,E,4,12,0.74,3.9,M,-5.4,M,1.3,0000*76";
/**
* 提取多条rtcm
* 因为存在d331...rtcm...d331...rtcm..这样的数据
* 还存在d331...rtcm rtcm rtcm...这样的数据
* @param hex
* @return
*/
public static List<String> getRtcms(String hex){
return splitStartWith(hex,"d300","d301","d302").stream()
.map(com.imdroid.sideslope.bd.RtcmGgaUtil::getRtcm)
.filter(s -> s != null && !s.isEmpty())
.collect(Collectors.toList());
}
/**
* 提取一条rtcm
* @param hex
* @return
*/
public static String getRtcm(String hex){
try {
int index = getIndex(hex,"d300","d301","d302");
if (index != -1 && index < hex.length()-6) {
//d300数据长度
int length = Integer.parseInt(hex.substring(index + 3, index + 6), 16);
if(index + (3+length +3)*2 <= hex.length()){
return hex.substring(index, index + (3 + length + 3) * 2);
}
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
private static int getIndex(String... regex){
for (int i = 1; i < regex.length; i++) {
if(regex[0].contains(regex[i])){
return regex[0].indexOf(regex[i]);
}
}
return -1;
}
/**
* 按前缀切割分段
* @param regex 第一个是要处理的数据其他是要检测的前缀
* @return
*/
public static List<String> splitStartWith(String... regex){
ArrayList<String> list = new ArrayList<>();
try{
List<Integer> indexs = getIndexs(regex);
int start = 0;
for (int i = 0; i < indexs.size(); i++) {
if(indexs.get(i) != 0){
list.add(regex[0].substring(start,indexs.get(i)));
start = indexs.get(i);
}
if(i == indexs.size() -1){
list.add(regex[0].substring(indexs.get(i)));
}
}
}catch (Exception e){
e.printStackTrace();
}
return list;
}
/**
* 按多个规则搜索索引
* @param regex
* @return
*/
public static List<Integer> getIndexs(String... regex){
List<Integer> list =new ArrayList<>();
for (int i = 1; i < regex.length; i++) {
list.addAll(findAllIndex(regex[0],0,regex[i]));
}
list.sort((o1, o2) -> o1-o2);
return list;
}
/**
* 按规则搜索所有索引
* @param string
* @param index
* @param findStr
* @return
*/
public static List<Integer> findAllIndex(String string, int index, String findStr){
List<Integer> list =new ArrayList<>();
int num = string.indexOf(findStr,index);
if(num != -1){
list.add(num);
//递归进行查找
List myList = findAllIndex(string,num+1,findStr);
list.addAll(myList);
}
return list;
}
/** /**
* 获取rtcm数据类型 * 获取rtcm数据类型
* @param bytes * @param bytes

View File

@ -4,13 +4,17 @@ import com.imdroid.common.util.DataTypeUtil;
import com.imdroid.common.util.ThreadManager; import com.imdroid.common.util.ThreadManager;
import com.imdroid.secapi.client.BeidouClient; import com.imdroid.secapi.client.BeidouClient;
import com.imdroid.secapi.dto.GnssDevice; import com.imdroid.secapi.dto.GnssDevice;
import com.imdroid.common.util.ByteUtil;
import com.imdroid.sideslope.bd.Gga; import com.imdroid.sideslope.bd.Gga;
import com.imdroid.sideslope.message.D331RtcmMessage; import com.imdroid.sideslope.message.D331RtcmMessage;
import com.imdroid.sideslope.ntrip.UdpNtripServer;
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.server.DeviceChannel; import com.imdroid.sideslope.server.DeviceChannel;
import com.imdroid.sideslope.server.OnlineChannels; import com.imdroid.sideslope.server.OnlineChannels;
import com.imdroid.sideslope.service.DataPersistService; import com.imdroid.sideslope.service.DataPersistService;
import com.imdroid.sideslope.bd.RtcmGgaUtil;
//import com.imdroid.common.util.RtcmGgaUtil;
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;
@ -21,6 +25,8 @@ import org.springframework.stereotype.Component;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import java.util.Optional;
/** /**
* @author Layton * @author Layton
@ -37,13 +43,19 @@ public class D331RtcmMessageExecutor implements Executor<D331RtcmMessage, Void>
private BeidouClient beidouClient; private BeidouClient beidouClient;
@Autowired @Autowired
private DataPersistService dataPersistService; private DataPersistService dataPersistService;
@Override @Override
public Void execute(D331RtcmMessage message) { public Void execute(D331RtcmMessage message) {
String id = message.getId(); String id = message.getId();
byte[] srcdata = message.getSrcData();
String rtcm = ByteUtil.bytesToHexString(srcdata);
// 补齐tenantId // 补齐tenantId
Device deviceBs = deviceService.findByDeviceId(id); Device deviceBs = deviceService.findByDeviceId(id);
if(deviceBs == null || deviceBs.getOpMode() == GnssDevice.OP_MODE_UNUSE) return null; if(deviceBs == null || deviceBs.getOpMode() == GnssDevice.OP_MODE_UNUSE) return null;
// 添加NTRIP处理
ntrip(id, rtcm);
// 推送基站数据 // 推送基站数据
if(deviceBs.getOpMode() == GnssDevice.OP_MODE_USE) { if(deviceBs.getOpMode() == GnssDevice.OP_MODE_USE) {
byte[] forwardBytes = message.getSrcData(); byte[] forwardBytes = message.getSrcData();
@ -79,8 +91,8 @@ public class D331RtcmMessageExecutor implements Executor<D331RtcmMessage, Void>
if(deviceBs.getD3xxbytes()>0){ if(deviceBs.getD3xxbytes()>0){
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
if(deviceBs.getLastRxTime().isBefore(now.minusMinutes(1)) && if(deviceBs.getLastRxTime().isBefore(now.minusMinutes(1)) &&
(deviceBs.getLastD3f2Time() == null || (deviceBs.getLastD3f2Time() == null ||
deviceBs.getLastD3f2Time().isBefore(now.minusMinutes(30)))) { deviceBs.getLastD3f2Time().isBefore(now.minusMinutes(30)))) {
// new cycle // new cycle
logger.info("device {} rx {} d331 in a cycle while not d3f0f2",deviceBs.getDeviceId(),deviceBs.getD3xxCount()); logger.info("device {} rx {} d331 in a cycle while not d3f0f2",deviceBs.getDeviceId(),deviceBs.getD3xxCount());
@ -115,11 +127,9 @@ public class D331RtcmMessageExecutor implements Executor<D331RtcmMessage, Void>
Gga gga = message.getGga(); Gga gga = message.getGga();
if(gga != null) { if(gga != null) {
deviceBs.updateSatelitesNum(gga.getSatellitesInUsed()); deviceBs.updateSatelitesNum(gga.getSatellitesInUsed());
//if(gga.isFixed()) { //基站的quality不会是4 deviceBs.setLatitude(gga.getLatitude());
deviceBs.setLatitude(gga.getLatitude()); deviceBs.setLongitude(gga.getLongitude());
deviceBs.setLongitude(gga.getLongitude()); deviceBs.setAltitude(gga.getAltitude());
deviceBs.setAltitude(gga.getAltitude());
//}
} }
ThreadManager.getFixedThreadPool().submit(() -> { ThreadManager.getFixedThreadPool().submit(() -> {
@ -133,8 +143,29 @@ public class D331RtcmMessageExecutor implements Executor<D331RtcmMessage, Void>
return null; return null;
} }
private void ntrip(String mountpoint, String hexData) {
try {
// 将原始字节转换为16进制字符串用于RTCM提取
//String hexData = ByteUtil.bytesToHexString(rawData);
System.out.println(hexData);
// 提取RTCM数据并发送到NtripServer,使用设备ID作为挂载点
Optional.ofNullable(RtcmGgaUtil.getRtcms(hexData))
.ifPresent(rtcm -> {
System.out.println("挂载点: " + mountpoint);
System.out.println("RTCM数据: " + rtcm);
UdpNtripServer.send(mountpoint, rtcm);
});
} catch (Exception e) {
logger.error("处理NTRIP数据失败, 挂载点: {}, 错误: {}", mountpoint, e.getMessage());
}
}
@Override @Override
public Class<?> getMessageType() { public Class<?> getMessageType() {
return D331RtcmMessage.class; return D331RtcmMessage.class;
} }
}
}

View File

@ -0,0 +1,31 @@
package com.imdroid.sideslope.ntrip;
import com.imdroid.common.util.HttpUtils;
import com.imdroid.common.util.ThreadManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author likongyong
* @date 2023/10/19 11:49
*/
public class HttpNtripServer {
private static final Logger logger = LoggerFactory.getLogger(HttpNtripServer.class);
/**
* 修改挂载点获取xingyu差分的gga
* @param mount
* @param gga
*/
public static void sendGGA(String mount, String gga){
ThreadManager.getSingleThreadPool(HttpNtripServer.class.getName()).execute(()->{
try{
String url = "http://localhost:11001/ntrip/sendGGA/" + mount + "/" + gga;
String result = HttpUtils.getUrl(url);
logger.debug("{} send gga {} {}",mount, gga, result);
}catch (Exception e){
logger.error(e.toString());
}
});
}
}

View File

@ -0,0 +1,69 @@
package com.imdroid.sideslope.ntrip;
import com.imdroid.common.util.ByteUtil;
import com.imdroid.common.util.ThreadManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.List;
/**
* 本地udp发送差分数据到ntrip-forward-server项目
*/
public class UdpNtripServer {
private static final Logger logger = LoggerFactory.getLogger(UdpNtripServer.class);
private static DatagramSocket socket;
private static DatagramPacket outPacket;
/**
* 向某挂载点提供差分信息
* @param mount 挂载点名称
* @param hexRtcm 差分信息16进制字符串
*/
public static void send(String mount, String hexRtcm){
ThreadManager.getSingleThreadPool(UdpNtripServer.class.getName()).execute(()->{
try{
//随机端口
if(socket == null) socket = new DatagramSocket();
if(outPacket == null) outPacket = new DatagramPacket(new byte[0],0, InetAddress.getByName("localhost"),11100);
outPacket.setData(encode(ByteUtil.addBytes(mount.getBytes(), ByteUtil.hexStringTobyte(hexRtcm))));
socket.send(outPacket);
}catch (Exception e){
socket = null;
outPacket = null;
e.printStackTrace();
}
});
}
/**
* 向某挂载点提供差分信息
* @param mount 挂载点名称
* @param hexRtcm 差分信息16进制字符串
*/
public static void send(String mount, List<String> hexRtcm){
logger.debug(mount + ":" + hexRtcm.size());
for (String s : hexRtcm) {
send(mount,s);
}
}
//加入校验位用于校验数据是否完整
private static byte[] encode(byte[] bytes) {
byte[] bytes1 = new byte[bytes.length + 1];
//校验位
byte b = bytes[0];
bytes1[0] = bytes[0];
for (int i = 1; i < bytes.length; i++) {
b ^= bytes[i];
bytes1[i] = bytes[i];
}
bytes1[bytes1.length - 1] = b;
return bytes1;
}
}