将基站RTCM推入NtripCaster
This commit is contained in:
parent
974e5025ec
commit
6cd67adc19
@ -5,6 +5,9 @@ import com.imdroid.common.util.ByteUtil;
|
||||
import com.imdroid.common.util.StringUtil;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.lang.Math.*;
|
||||
|
||||
@ -13,6 +16,110 @@ public class RtcmGgaUtil {
|
||||
//gga样本:*后面跟的是校验和,其中76代表校验和,对$和*之间的数据(不包括这两个字符)按字节进行异或运算(二进制)的结果
|
||||
private static final String ggaExample = "$GNGGA,020850.50,2258.10508,N,11317.67958,E,4,12,0.74,3.9,M,-5.4,M,1.3,0000*76";
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 提取多条rtcm
|
||||
* 因为存在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数据类型
|
||||
* @param bytes
|
||||
|
||||
@ -4,13 +4,17 @@ import com.imdroid.common.util.DataTypeUtil;
|
||||
import com.imdroid.common.util.ThreadManager;
|
||||
import com.imdroid.secapi.client.BeidouClient;
|
||||
import com.imdroid.secapi.dto.GnssDevice;
|
||||
import com.imdroid.common.util.ByteUtil;
|
||||
import com.imdroid.sideslope.bd.Gga;
|
||||
import com.imdroid.sideslope.message.D331RtcmMessage;
|
||||
import com.imdroid.sideslope.ntrip.UdpNtripServer;
|
||||
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 com.imdroid.sideslope.bd.RtcmGgaUtil;
|
||||
//import com.imdroid.common.util.RtcmGgaUtil;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import org.slf4j.Logger;
|
||||
@ -21,6 +25,8 @@ import org.springframework.stereotype.Component;
|
||||
import javax.annotation.Resource;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
/**
|
||||
* @author Layton
|
||||
@ -37,13 +43,19 @@ public class D331RtcmMessageExecutor implements Executor<D331RtcmMessage, Void>
|
||||
private BeidouClient beidouClient;
|
||||
@Autowired
|
||||
private DataPersistService dataPersistService;
|
||||
|
||||
@Override
|
||||
public Void execute(D331RtcmMessage message) {
|
||||
String id = message.getId();
|
||||
byte[] srcdata = message.getSrcData();
|
||||
String rtcm = ByteUtil.bytesToHexString(srcdata);
|
||||
// 补齐tenantId
|
||||
Device deviceBs = deviceService.findByDeviceId(id);
|
||||
if(deviceBs == null || deviceBs.getOpMode() == GnssDevice.OP_MODE_UNUSE) return null;
|
||||
|
||||
// 添加NTRIP处理
|
||||
ntrip(id, rtcm);
|
||||
|
||||
// 推送基站数据
|
||||
if(deviceBs.getOpMode() == GnssDevice.OP_MODE_USE) {
|
||||
byte[] forwardBytes = message.getSrcData();
|
||||
@ -115,11 +127,9 @@ public class D331RtcmMessageExecutor implements Executor<D331RtcmMessage, Void>
|
||||
Gga gga = message.getGga();
|
||||
if(gga != null) {
|
||||
deviceBs.updateSatelitesNum(gga.getSatellitesInUsed());
|
||||
//if(gga.isFixed()) { //基站的quality不会是4
|
||||
deviceBs.setLatitude(gga.getLatitude());
|
||||
deviceBs.setLongitude(gga.getLongitude());
|
||||
deviceBs.setAltitude(gga.getAltitude());
|
||||
//}
|
||||
}
|
||||
|
||||
ThreadManager.getFixedThreadPool().submit(() -> {
|
||||
@ -133,8 +143,29 @@ public class D331RtcmMessageExecutor implements Executor<D331RtcmMessage, Void>
|
||||
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
|
||||
public Class<?> getMessageType() {
|
||||
return D331RtcmMessage.class;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user