add rtcm processing, add rtcmtool

pull/111/head
bert hubert 2020-02-29 14:28:36 +01:00
parent 9e37f6ad40
commit 2829ca9cd8
11 changed files with 426 additions and 188 deletions

View File

@ -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

View File

@ -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)
{

View File

@ -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();

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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();

111
rtcm.cc 100644
View File

@ -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;
}
}
}

49
rtcm.hh 100644
View File

@ -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;
};

166
rtcmtool.cc 100644
View File

@ -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);
}
}

View File

@ -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()) {