add rtcm processing, add rtcmtool
parent
9e37f6ad40
commit
2829ca9cd8
13
Makefile
13
Makefile
|
@ -25,7 +25,7 @@ endif
|
|||
CHEAT_ARG := $(shell ./update-git-hash-if-necessary)
|
||||
|
||||
PROGRAMS = navparse ubxtool navnexus navcat navrecv navdump testrunner navdisplay tlecatch reporter \
|
||||
galmonmon rinreport
|
||||
galmonmon rinreport rtcmtool
|
||||
|
||||
all: navmon.pb.cc $(PROGRAMS)
|
||||
|
||||
|
@ -35,7 +35,7 @@ all: navmon.pb.cc $(PROGRAMS)
|
|||
|
||||
navmon.pb.h: navmon.proto
|
||||
protoc --cpp_out=./ navmon.proto
|
||||
|
||||
|
||||
navmon.pb.cc: navmon.proto
|
||||
protoc --cpp_out=./ navmon.proto
|
||||
|
||||
|
@ -74,7 +74,7 @@ download-raspbian-package:
|
|||
decrypt: decrypt.o bits.o ext/fmt-6.1.2/src/format.o
|
||||
$(CXX) -std=gnu++17 $^ -o $@
|
||||
|
||||
navparse: navparse.o ext/fmt-6.1.2/src/format.o $(H2OPP) $(SIMPLESOCKETS) minicurl.o ubx.o bits.o navmon.pb.o gps.o ephemeris.o beidou.o glonass.o $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) tle.o navmon.o coverage.o osen.o trkmeas.o influxpush.o ${EXTRADEP} githash.o sbas.o
|
||||
navparse: navparse.o ext/fmt-6.1.2/src/format.o $(H2OPP) $(SIMPLESOCKETS) minicurl.o ubx.o bits.o navmon.pb.o gps.o ephemeris.o beidou.o glonass.o $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) tle.o navmon.o coverage.o osen.o trkmeas.o influxpush.o ${EXTRADEP} githash.o sbas.o rtcm.o
|
||||
$(CXX) -std=gnu++17 $^ -o $@ -pthread -L/usr/local/lib -L/usr/local/opt/openssl/lib/ -lh2o-evloop -lssl -lcrypto -lz -lcurl -lprotobuf $(WSLAY)
|
||||
|
||||
reporter: reporter.o ext/fmt-6.1.2/src/format.o $(SIMPLESOCKETS) minicurl.o ubx.o bits.o navmon.pb.o gps.o ephemeris.o beidou.o glonass.o $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) tle.o navmon.o coverage.o osen.o githash.o
|
||||
|
@ -84,7 +84,7 @@ galmonmon: galmonmon.o ext/fmt-6.1.2/src/format.o $(SIMPLESOCKETS) minicurl.o ub
|
|||
$(CXX) -std=gnu++17 $^ -o $@ -pthread -L/usr/local/lib -lprotobuf -lcurl
|
||||
|
||||
|
||||
navdump: navdump.o ext/fmt-6.1.2/src/format.o bits.o navmon.pb.o gps.o ephemeris.o beidou.o glonass.o navmon.o $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) tle.o sp3.o osen.o trkmeas.o githash.o rinex.o sbas.o ${EXTRADEP}
|
||||
navdump: navdump.o ext/fmt-6.1.2/src/format.o bits.o navmon.pb.o gps.o ephemeris.o beidou.o glonass.o navmon.o $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) tle.o sp3.o osen.o trkmeas.o githash.o rinex.o sbas.o rtcm.o ${EXTRADEP}
|
||||
$(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -pthread -lprotobuf -lz
|
||||
|
||||
navdisplay: navdisplay.o ext/fmt-6.1.2/src/format.o bits.o navmon.pb.o gps.o ephemeris.o beidou.o glonass.o ephemeris.o navmon.o osen.o githash.o
|
||||
|
@ -107,8 +107,11 @@ tlecatch: tlecatch.o $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) gith
|
|||
rinreport: rinreport.o rinex.o githash.o navmon.o ext/fmt-6.1.2/src/format.o ephemeris.o osen.o
|
||||
$(CXX) -std=gnu++17 $^ -o $@ -lz -pthread
|
||||
|
||||
rtcmtool: rtcmtool.o navmon.pb.o githash.o ext/fmt-6.1.2/src/format.o bits.o nmmsender.o $(SIMPLESOCKETS) navmon.o rtcm.o
|
||||
$(CXX) -std=gnu++17 $^ -o $@ -lz -pthread -lprotobuf
|
||||
|
||||
ubxtool: navmon.pb.o ubxtool.o ubx.o bits.o ext/fmt-6.1.2/src/format.o galileo.o gps.o beidou.o navmon.o ephemeris.o $(SIMPLESOCKETS) osen.o githash.o
|
||||
|
||||
ubxtool: navmon.pb.o ubxtool.o ubx.o bits.o ext/fmt-6.1.2/src/format.o galileo.o gps.o beidou.o navmon.o ephemeris.o $(SIMPLESOCKETS) osen.o githash.o nmmsender.o
|
||||
$(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -lprotobuf -pthread
|
||||
|
||||
testrunner: navmon.pb.o testrunner.o ubx.o bits.o ext/fmt-6.1.2/src/format.o galileo.o gps.o beidou.o ephemeris.o sp3.o osen.o navmon.o rinex.o githash.o
|
||||
|
|
21
navcat.cc
21
navcat.cc
|
@ -81,27 +81,6 @@ vector<uint64_t> getSources(string_view dirname)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static size_t writen2(int fd, const void *buf, size_t count)
|
||||
{
|
||||
const char *ptr = (char*)buf;
|
||||
const char *eptr = ptr + count;
|
||||
|
||||
ssize_t res;
|
||||
while(ptr != eptr) {
|
||||
res = ::write(fd, ptr, eptr - ptr);
|
||||
if(res < 0) {
|
||||
throw runtime_error("failed in writen2: "+string(strerror(errno)));
|
||||
}
|
||||
else if (res == 0)
|
||||
throw EofException();
|
||||
|
||||
ptr += (size_t) res;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void sendProtobuf(string_view dir, time_t startTime, time_t stopTime=0)
|
||||
{
|
||||
|
|
18
navdump.cc
18
navdump.cc
|
@ -30,6 +30,7 @@
|
|||
#include "version.hh"
|
||||
#include "gpscnav.hh"
|
||||
#include "rinex.hh"
|
||||
#include "rtcm.hh"
|
||||
|
||||
static char program[]="navdump";
|
||||
|
||||
|
@ -646,6 +647,23 @@ try
|
|||
|
||||
cout<<"\n";
|
||||
}
|
||||
else if(nmm.type() == NavMonMessage::RTCMMessageType) {
|
||||
etstamp();
|
||||
RTCMMessage rm;
|
||||
rm.parse(nmm.rm().contents());
|
||||
if(rm.type == 1057 || rm.type == 1240) {
|
||||
for(const auto& ed : rm.d_ephs) {
|
||||
cout<<makeSatPartialName(ed.id)<<": iode "<< ed.iod<<" ("<< ed.radial<<", "<<ed.along<<", "<<ed.cross<<") mm -> (";
|
||||
cout<< ed.dradial<<", "<<ed.dalong<<", "<<ed.dcross<< ") mm/s\n";
|
||||
}
|
||||
}
|
||||
else if(rm.type == 1058 || rm.type == 1241) {
|
||||
for(const auto& cd : rm.d_clocks) {
|
||||
cout<<makeSatPartialName(cd.id)<<": dclock0 "<< cd.dclock0 <<" dclock1 " << cd.dclock1 <<" dclock2 "<< cd.dclock2 << endl;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if(nmm.type() == NavMonMessage::GPSCnavType) {
|
||||
int sv = nmm.gpsc().gnsssv();
|
||||
int sigid = nmm.gpsc().sigid();
|
||||
|
|
20
navmon.cc
20
navmon.cc
|
@ -331,3 +331,23 @@ std::string sbasName(int prn)
|
|||
sbas+=" " + std::to_string(prn);
|
||||
return sbas;
|
||||
}
|
||||
|
||||
size_t writen2(int fd, const void *buf, size_t count)
|
||||
{
|
||||
const char *ptr = (char*)buf;
|
||||
const char *eptr = ptr + count;
|
||||
|
||||
ssize_t res;
|
||||
while(ptr != eptr) {
|
||||
res = ::write(fd, ptr, eptr - ptr);
|
||||
if(res < 0) {
|
||||
throw runtime_error("failed in writen2: "+string(strerror(errno)));
|
||||
}
|
||||
else if (res == 0)
|
||||
throw EofException();
|
||||
|
||||
ptr += (size_t) res;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -77,3 +77,4 @@ double utcFromGST(int wn, double tow);
|
|||
double utcFromGPS(int wn, double tow);
|
||||
|
||||
std::string makeHexDump(const std::string& str);
|
||||
size_t writen2(int fd, const void *buf, size_t count);
|
||||
|
|
|
@ -16,6 +16,7 @@ message NavMonMessage {
|
|||
UbloxJammingStatsType = 12;
|
||||
SBASMessageType = 13;
|
||||
GPSCnavType = 14;
|
||||
RTCMMessageType = 15;
|
||||
}
|
||||
|
||||
required uint64 sourceID = 1;
|
||||
|
@ -171,6 +172,11 @@ message NavMonMessage {
|
|||
required uint32 sigid = 6;
|
||||
}
|
||||
|
||||
message RTCMMessage {
|
||||
required bytes contents =5;
|
||||
}
|
||||
|
||||
|
||||
|
||||
optional GalileoInav gi=5;
|
||||
optional ReceptionData rd=6;
|
||||
|
@ -185,5 +191,6 @@ message NavMonMessage {
|
|||
optional ObserverDetails od = 15;
|
||||
optional UbloxJammingStats ujs = 16;
|
||||
optional SBASMessage sbm = 17;
|
||||
optional GPSCnav gpsc=18;
|
||||
optional GPSCnav gpsc = 18;
|
||||
optional RTCMMessage rm = 19;
|
||||
}
|
||||
|
|
43
navparse.cc
43
navparse.cc
|
@ -34,8 +34,10 @@
|
|||
|
||||
#include "CLI/CLI.hpp"
|
||||
#include "gpscnav.hh"
|
||||
#include "rtcm.hh"
|
||||
#include "version.hh"
|
||||
|
||||
|
||||
static char program[]="navparse";
|
||||
|
||||
using namespace std;
|
||||
|
@ -2159,6 +2161,47 @@ try
|
|||
// if(g_svstats[id].wn < 512) // XXX ROLLOVER
|
||||
// g_svstats[id].wn += 2048;
|
||||
}
|
||||
else if(nmm.type() == NavMonMessage::RTCMMessageType) {
|
||||
RTCMMessage rm;
|
||||
rm.parse(nmm.rm().contents());
|
||||
if(rm.type == 1057 || rm.type == 1240) {
|
||||
for(const auto& ed : rm.d_ephs) {
|
||||
idb.addValue(ed.id, "rtcm-eph-correction", {
|
||||
{"iod", ed.iod},
|
||||
{"radial", ed.radial},
|
||||
{"along", ed.along},
|
||||
{"cross", ed.cross},
|
||||
{"dradial", ed.dradial},
|
||||
{"dalong", ed.dalong},
|
||||
{"dcross", ed.dcross},
|
||||
{"ssr-iod", rm.ssrIOD},
|
||||
{"ssr-provider", rm.ssrProvider},
|
||||
{"ssr-solution", rm.ssrSolution},
|
||||
{"tow", rm.sow},
|
||||
{"udi", rm.udi}},
|
||||
nmm.localutcseconds(),
|
||||
nmm.sourceid());
|
||||
|
||||
}
|
||||
}
|
||||
else if(rm.type == 1058 || rm.type == 1241) {
|
||||
for(const auto& cd : rm.d_clocks) {
|
||||
idb.addValue(cd.id, "rtcm-clock-correction", {
|
||||
{"dclock0", cd.dclock0},
|
||||
{"dclock1", cd.dclock1},
|
||||
{"dclock2", cd.dclock2},
|
||||
{"ssr-iod", rm.ssrIOD},
|
||||
{"ssr-provider", rm.ssrProvider},
|
||||
{"ssr-solution", rm.ssrSolution},
|
||||
{"tow", rm.sow},
|
||||
{"udi", rm.udi}},
|
||||
nmm.localutcseconds(),
|
||||
nmm.sourceid());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if(nmm.type()== NavMonMessage::GPSCnavType) {
|
||||
SatID id{nmm.gpsc().gnssid(), nmm.gpsc().gnsssv(), nmm.gpsc().sigid()};
|
||||
g_svstats[id].perrecv[nmm.sourceid()].t = nmm.localutcseconds();
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
#include "rtcm.hh"
|
||||
#include "bits.hh"
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void RTCMMessage::parse(const std::string& str)
|
||||
{
|
||||
auto gbu=[&str](int offset, int bits) {
|
||||
return getbitu((const unsigned char*)str.c_str(), offset, bits);
|
||||
};
|
||||
auto gbs=[&str](int offset, int bits) {
|
||||
return getbits((const unsigned char*)str.c_str(), offset, bits);
|
||||
};
|
||||
|
||||
type = gbu(0, 12);
|
||||
// cout<<"Message number: "<<type << " of size "<<str.size()<<"\n";
|
||||
if(type == 1057 || type == 1240) {
|
||||
d_ephs.clear();
|
||||
int stride;
|
||||
int iodlen;
|
||||
if(type == 1057) { // GPS
|
||||
stride = 135;
|
||||
iodlen=8;
|
||||
}
|
||||
else { // Galileo
|
||||
stride=137;
|
||||
iodlen=10;
|
||||
}
|
||||
|
||||
int sats = gbu(62, 6);
|
||||
sow = gbu(12, 20);
|
||||
udi = gbu(32, 4);
|
||||
mmi = gbu(36, 1);
|
||||
reference = gbu(37,1);
|
||||
ssrIOD = gbu(38,4);
|
||||
ssrProvider = gbu(42, 16);
|
||||
ssrSolution = gbu(58, 4);
|
||||
|
||||
// cout <<" sow "<< sow <<" sats "<<sats<<" update interval " << udi <<" mmi " << mmi;
|
||||
// cout <<" reference "<< reference << " iod-ssr "<< ssrIOD << " ssr-provider " << ssrProvider << " ssr-solution ";
|
||||
// cout<< ssrSolution <<":\n";
|
||||
|
||||
for(int n = 0; n < sats; ++n) {
|
||||
EphemerisDelta ed;
|
||||
|
||||
int off = 68+stride*n;
|
||||
ed.radial = gbs(off+ iodlen + 6, 22) * 0.1;
|
||||
ed.along = gbs(off+ iodlen+ 28, 20) * 0.4;
|
||||
ed.cross = gbs(off+ iodlen+48, 20) * 0.4;
|
||||
|
||||
|
||||
ed.dradial = gbs(off + iodlen+ 68, 21) * 0.001;
|
||||
ed.dalong = gbs(off + iodlen + 89, 19) * 0.004;
|
||||
ed.dcross = gbs(off + iodlen +108, 19) * 0.004;
|
||||
ed.iod = gbu(off +6, iodlen);
|
||||
if(type == 1057) {
|
||||
ed.id.gnss = 0;
|
||||
ed.id.sigid = 0;
|
||||
}
|
||||
else if(type == 1240) {
|
||||
ed.id.gnss = 2;
|
||||
ed.id.sigid = 1;
|
||||
}
|
||||
|
||||
ed.id.sv = gbu(off + 0, 6);
|
||||
// cout<<" "<<makeSatIDName(ed.id)<<" iode "<< ed.iod<<" ("<< ed.radial<<", "<<ed.along<<", "<<ed.cross<<") mm -> (";
|
||||
// cout<< ed.dradial<<", "<<ed.dalong<<", "<<ed.dcross<< ") mm/s\n";
|
||||
d_ephs.push_back(ed);
|
||||
}
|
||||
}
|
||||
else if(type == 1058 || type == 1241) {
|
||||
d_clocks.clear();
|
||||
int sats = gbu(61, 6);
|
||||
sow = gbu(12, 20);
|
||||
udi = gbu(32, 4);
|
||||
mmi = gbu(36, 1);
|
||||
ssrIOD = gbu(37, 4);
|
||||
ssrProvider = gbu(41, 16);
|
||||
ssrSolution=gbu(57, 4);
|
||||
|
||||
// cout <<" sow "<< sow <<" sats "<<sats<<" update interval " << udi <<" mmi " << mmi;
|
||||
// cout << " iod-ssr "<< ssrIOD << " ssr-provider " << ssrProvider << " ssr-solution ";
|
||||
// cout<< ssrSolution <<":\n";
|
||||
|
||||
for(int n = 0; n < sats; ++n) {
|
||||
ClockDelta cd;
|
||||
if(type == 1058) {
|
||||
cd.id.gnss = 0;
|
||||
cd.id.sigid = 0;
|
||||
}
|
||||
else if(type == 1241) {
|
||||
cd.id.gnss = 2;
|
||||
cd.id.sigid = 1;
|
||||
}
|
||||
|
||||
int off = 67+76*n;
|
||||
cd.id.sv = gbu(off +0, 6);
|
||||
cd.dclock0 = gbs(off + 6, 22)*1e-4;
|
||||
cd.dclock1 = gbs(off + 28, 21)*1e-6;
|
||||
cd.dclock2 = gbs(off + 49, 27)*2e-8;
|
||||
d_clocks.push_back(cd);
|
||||
// cout<<" "<< makeSatIDName(cd.id)<<" ";
|
||||
// cout<< cd.dclock0 <<" ";
|
||||
// cout<< cd.dclock1 <<" ";
|
||||
// cout<< cd.dclock2 << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include "navmon.hh"
|
||||
#include <vector>
|
||||
struct RTCMFrame
|
||||
{
|
||||
std::string payload;
|
||||
};
|
||||
|
||||
class RTCMReader
|
||||
{
|
||||
public:
|
||||
explicit RTCMReader(int fd) : d_fp(fdopen(fd, "r")) {}
|
||||
bool get(RTCMFrame& rf);
|
||||
private:
|
||||
FILE* d_fp;
|
||||
};
|
||||
|
||||
|
||||
struct RTCMMessage
|
||||
{
|
||||
void parse(const std::string& str);
|
||||
int type;
|
||||
int sow;
|
||||
int udi;
|
||||
bool mmi;
|
||||
bool reference;
|
||||
int ssrIOD, ssrProvider, ssrSolution;
|
||||
struct EphemerisDelta
|
||||
{
|
||||
SatID id;
|
||||
// in millimeters
|
||||
double radial, along, cross;
|
||||
double dradial, dalong, dcross;
|
||||
int iod;
|
||||
};
|
||||
struct ClockDelta
|
||||
{
|
||||
SatID id;
|
||||
double dclock0; // in meters
|
||||
double dclock1;
|
||||
double dclock2;
|
||||
};
|
||||
|
||||
std::vector<EphemerisDelta> d_ephs;
|
||||
std::vector<ClockDelta> d_clocks;
|
||||
|
||||
};
|
|
@ -0,0 +1,166 @@
|
|||
#include "rtcm.hh"
|
||||
#include "bits.hh"
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include "nmmsender.hh"
|
||||
#include "CLI/CLI.hpp"
|
||||
#include "swrappers.hh"
|
||||
#include "sclasses.hh"
|
||||
#include "version.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool RTCMReader::get(RTCMFrame& rf)
|
||||
{
|
||||
int c;
|
||||
while( ((c=fgetc(d_fp)) != -1) && c != 211) {
|
||||
cerr<<"Skipped.. "<<endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(c != 211) {
|
||||
cerr<<"EOF"<<endl;
|
||||
return false;
|
||||
}
|
||||
// cout<<"Found preamble"<<endl;
|
||||
unsigned char buffer[2];
|
||||
if(fread((char*)buffer, 1, 2, d_fp) != 2)
|
||||
return false;
|
||||
|
||||
// cout<<"Got two byte buffer"<<endl;
|
||||
// 6 bits reserved, 10 bits of size
|
||||
int size = getbitu(buffer, 6, 10);
|
||||
size += 3;
|
||||
// cout<<"Now reading "<<size<<" bytes"<<endl;
|
||||
vector<char> buf(size);
|
||||
if((int)fread(&buf[0], 1, size, d_fp) != size)
|
||||
return false;
|
||||
|
||||
// cout<<"Returning true"<<endl;
|
||||
rf.payload.assign(&buf[0], size - 3);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Message types:
|
||||
Type 1240, Galileo orbit corrections to Broadcast Ephemeris
|
||||
Type 1241, Galileo clock corrections to Broadcast Ephemeris
|
||||
1057 message for GPS orbit corrections to Broadcast Ephemeris,
|
||||
1058 message for GPS clock corrections to Broadcast Ephemeris,
|
||||
*/
|
||||
|
||||
|
||||
/* 1057 (GPS), 1240 (Galileo)
|
||||
0 12 bits message number
|
||||
12 20 bits galileo SOW
|
||||
32 4 bits SSR update interval
|
||||
36 1 bit multiple message indicator
|
||||
37 1 bit Satellite Reference Datum (0: ITRF, 1: regional)
|
||||
38 4 bit (IOD SSR)
|
||||
42 16 bits SSR provider ID
|
||||
58 4 bits SSR solution ID
|
||||
62 6 bits number of satellites
|
||||
68
|
||||
Repeat, starting from pos 68:
|
||||
0 6 bits sv
|
||||
6 10 bits IODE nav / 8 for GPS, a shift of -2 everywhere below
|
||||
16 22 bits delta radial (0.1mm)
|
||||
38 20 bits along track (0.4mm)
|
||||
58 20 bits cross track (0.4mm)
|
||||
78 21 bits dot delta radial (0.001 mm/s)
|
||||
99 19 bits dot delta along (0.004 mm/s)
|
||||
118 19 bits dot delta cross-track (0.004 mm/s)
|
||||
137
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
1058 (GPS), 1241 (Galileo)
|
||||
0 12 bits message number
|
||||
12 20 bits galileo SOW (GPS Epoch time)
|
||||
32 4 bits "UDI" ("SSR Update interval")
|
||||
36 1 bit "sync" ("multiple message indicator")
|
||||
37 4 bit (IOD SSR, link to 1240 I think)
|
||||
41 16 bits SSR provider ID
|
||||
57 4 bits SSR solution ID
|
||||
61 6 bits number of satellites
|
||||
67
|
||||
|
||||
67
|
||||
Repeat, starting from pos 68:
|
||||
0 6 bits sv
|
||||
6 22 bits dclk[0] 1e-4 meter // 0.1 mm
|
||||
28 21 bits dclk[1] 1e-6 meter/s // 0.001 mm/s
|
||||
49 27 bits dclk[2] 2e-8 meter // 0.0002mm/s^2
|
||||
76
|
||||
|
||||
Reference time is Epoch Time + 0.5* SSR update interval, which can be zero.
|
||||
*/
|
||||
|
||||
/*
|
||||
CLKA[0,1]_DEU1 – containing the SSR corrections regarding the satellites’ Antenna Phase Center
|
||||
CLKC[0,1]_DEU1 – containing the SSR corrections regarding the satellites’ Center of Mass.
|
||||
*/
|
||||
|
||||
static char program[]="rtcmtool";
|
||||
uint16_t g_srcid{0};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// time_t starttime=time(0);
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
vector<string> destinations;
|
||||
|
||||
bool doVERSION{false}, doSTDOUT{false};
|
||||
CLI::App app(program);
|
||||
app.add_option("--destination,-d", destinations, "Send output to this IPv4/v6 address");
|
||||
app.add_option("--station", g_srcid, "Station id")->required();
|
||||
app.add_flag("--version", doVERSION, "show program version and copyright");
|
||||
app.add_flag("--stdout", doSTDOUT, "Emit output to stdout");
|
||||
try {
|
||||
app.parse(argc, argv);
|
||||
} catch(const CLI::Error &e) {
|
||||
return app.exit(e);
|
||||
}
|
||||
|
||||
if(doVERSION) {
|
||||
showVersion(program, g_gitHash);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
NMMSender ns;
|
||||
ns.d_debug = true;
|
||||
for(const auto& s : destinations) {
|
||||
auto res=resolveName(s, true, true);
|
||||
if(res.empty()) {
|
||||
cerr<<"Unable to resolve '"<<s<<"' as destination for data, exiting"<<endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
ns.addDestination(s); // ComboAddress(s, 29603));
|
||||
}
|
||||
if(doSTDOUT)
|
||||
ns.addDestination(1);
|
||||
|
||||
ns.launch();
|
||||
|
||||
RTCMReader rr(0);
|
||||
RTCMFrame rf;
|
||||
while(rr.get(rf)) {
|
||||
// cout<<"Got a "<<rf.payload.size()<<" byte frame"<<endl;
|
||||
RTCMMessage rm;
|
||||
NavMonMessage nmm;
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, & ts);
|
||||
nmm.set_type(NavMonMessage::RTCMMessageType);
|
||||
nmm.set_localutcseconds(ts.tv_sec);
|
||||
nmm.set_localutcnanoseconds(ts.tv_nsec);
|
||||
nmm.set_sourceid(g_srcid);
|
||||
nmm.mutable_rm()->set_contents(rf.payload);
|
||||
ns.emitNMM(nmm);
|
||||
|
||||
// rm.parse(rf.payload);
|
||||
}
|
||||
}
|
163
ubxtool.cc
163
ubxtool.cc
|
@ -33,7 +33,7 @@
|
|||
#include "comboaddress.hh"
|
||||
#include "swrappers.hh"
|
||||
#include "sclasses.hh"
|
||||
|
||||
#include "nmmsender.hh"
|
||||
#include "version.hh"
|
||||
|
||||
static char program[]="ubxtool";
|
||||
|
@ -70,25 +70,6 @@ static int getBaudrate(int baud)
|
|||
|
||||
static int g_baudval;
|
||||
|
||||
size_t writen2(int fd, const void *buf, size_t count)
|
||||
{
|
||||
const char *ptr = (char*)buf;
|
||||
const char *eptr = ptr + count;
|
||||
|
||||
ssize_t res;
|
||||
while(ptr != eptr) {
|
||||
res = ::write(fd, ptr, eptr - ptr);
|
||||
if(res < 0) {
|
||||
throw runtime_error("failed in writen2: "+string(strerror(errno)));
|
||||
}
|
||||
else if (res == 0)
|
||||
throw EofException();
|
||||
|
||||
ptr += (size_t) res;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* inav schedule:
|
||||
1) Find plausible start time of next cycle
|
||||
|
@ -294,147 +275,6 @@ bool sendAndWaitForUBXAckNack(int fd, int seconds, basic_string_view<uint8_t> ms
|
|||
}
|
||||
|
||||
|
||||
class NMMSender
|
||||
{
|
||||
struct Destination
|
||||
{
|
||||
int fd{-1};
|
||||
std::string dst;
|
||||
std::string fname;
|
||||
|
||||
deque<string> queue;
|
||||
std::mutex mut;
|
||||
void emitNMM(const NavMonMessage& nmm);
|
||||
};
|
||||
|
||||
public:
|
||||
void addDestination(int fd)
|
||||
{
|
||||
auto d = std::make_unique<Destination>();
|
||||
d->fd = fd;
|
||||
d_dests.push_back(std::move(d));
|
||||
}
|
||||
void addDestination(const std::string& dest)
|
||||
{
|
||||
auto d = std::make_unique<Destination>();
|
||||
d->dst = dest;
|
||||
d_dests.push_back(std::move(d));
|
||||
}
|
||||
|
||||
void launch()
|
||||
{
|
||||
for(auto& d : d_dests) {
|
||||
if(!d->dst.empty()) {
|
||||
thread t(&NMMSender::sendTCPThread, this, d.get());
|
||||
t.detach();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sendTCPThread(Destination* d)
|
||||
{
|
||||
struct NameError{};
|
||||
for(;;) {
|
||||
ComboAddress chosen;
|
||||
try {
|
||||
vector<ComboAddress> addrs;
|
||||
for(;;) {
|
||||
addrs=resolveName(d->dst, true, true);
|
||||
if(!addrs.empty())
|
||||
break;
|
||||
|
||||
cerr<<humanTimeNow()<<" Unable to resolve "<<d->dst<<", sleeping and trying again later"<<endl;
|
||||
throw NameError();
|
||||
}
|
||||
|
||||
std::random_device rng;
|
||||
std::mt19937 urng(rng());
|
||||
std::shuffle(addrs.begin(), addrs.end(), urng);
|
||||
|
||||
for(auto& addr: addrs) {
|
||||
if(!addr.sin4.sin_port)
|
||||
addr.sin4.sin_port = ntohs(29603);
|
||||
chosen=addr;
|
||||
Socket s(addr.sin4.sin_family, SOCK_STREAM);
|
||||
SocketCommunicator sc(s);
|
||||
sc.setTimeout(3);
|
||||
sc.connect(addr);
|
||||
if (doDEBUG) { cerr<<humanTimeNow()<<" Connected to "<<d->dst<<" on "<<addr.toStringWithPort()<<endl; }
|
||||
for(;;) {
|
||||
std::string msg;
|
||||
{
|
||||
std::lock_guard<std::mutex> mut(d->mut);
|
||||
if(!d->queue.empty()) {
|
||||
msg = d->queue.front();
|
||||
}
|
||||
}
|
||||
if(!msg.empty()) {
|
||||
sc.writen(msg);
|
||||
std::lock_guard<std::mutex> mut(d->mut);
|
||||
d->queue.pop_front();
|
||||
}
|
||||
else usleep(100000);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(NameError&) {
|
||||
{
|
||||
std::lock_guard<std::mutex> mut(d->mut);
|
||||
if (doDEBUG) { cerr<<humanTimeNow()<<" There are now "<<d->queue.size()<<" messages queued for "<<d->dst<<endl; }
|
||||
}
|
||||
sleep(30);
|
||||
}
|
||||
catch(std::exception& e) {
|
||||
if (doDEBUG) { cerr<<humanTimeNow()<<" Sending thread for "<<d->dst<<" via "<<chosen.toStringWithPort()<<" had error: "<<e.what()<<endl; }
|
||||
{
|
||||
std::lock_guard<std::mutex> mut(d->mut);
|
||||
if (doDEBUG) { cerr<<humanTimeNow()<<" There are now "<<d->queue.size()<<" messages queued for "<<d->dst<<endl; }
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
catch(...) {
|
||||
if (doDEBUG) { cerr<<humanTimeNow()<<" Sending thread for "<<d->dst <<" via "<<chosen.toStringWithPort()<<" had error"; }
|
||||
{
|
||||
std::lock_guard<std::mutex> mut(d->mut);
|
||||
if (doDEBUG) { cerr<<"There are now "<<d->queue.size()<<" messages queued for "<<d->dst<<" via "<<chosen.toStringWithPort()<<endl; }
|
||||
}
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void emitNMM(const NavMonMessage& nmm);
|
||||
|
||||
private:
|
||||
|
||||
vector<unique_ptr<Destination>> d_dests;
|
||||
};
|
||||
|
||||
void NMMSender::emitNMM(const NavMonMessage& nmm)
|
||||
{
|
||||
for(auto& d : d_dests) {
|
||||
d->emitNMM(nmm);
|
||||
}
|
||||
}
|
||||
|
||||
void NMMSender::Destination::emitNMM(const NavMonMessage& nmm)
|
||||
{
|
||||
string out;
|
||||
nmm.SerializeToString(& out);
|
||||
string msg("bert");
|
||||
|
||||
uint16_t len = htons(out.size());
|
||||
msg.append((char*)&len, 2);
|
||||
msg.append(out);
|
||||
|
||||
if(!dst.empty()) {
|
||||
std::lock_guard<std::mutex> l(mut);
|
||||
queue.push_back(msg);
|
||||
}
|
||||
else
|
||||
writen2(fd, msg.c_str(), msg.size());
|
||||
}
|
||||
|
||||
|
||||
bool version9 = false;
|
||||
void enableUBXMessageOnPort(int fd, uint8_t ubxClass, uint8_t ubxType, uint8_t port, uint8_t rate=1)
|
||||
|
@ -641,6 +481,7 @@ int main(int argc, char** argv)
|
|||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
NMMSender ns;
|
||||
ns.d_debug = doDEBUG;
|
||||
for(const auto& s : destinations) {
|
||||
auto res=resolveName(s, true, true);
|
||||
if(res.empty()) {
|
||||
|
|
Loading…
Reference in New Issue