From 5169dc2ca30dbdee19fc9ee84f6a8ac8cf0a4375 Mon Sep 17 00:00:00 2001 From: bert hubert Date: Mon, 23 Sep 2019 14:23:03 +0200 Subject: [PATCH] cleanup of ubxtool, with buffered writing ability to multiple destination --- Makefile | 4 +- navdump.cc | 6 +- ubxtool.cc | 311 ++++++++++++++++++++++++++++++++++------------------- 3 files changed, 207 insertions(+), 114 deletions(-) diff --git a/Makefile b/Makefile index c5ba2fa..f2d4bfa 100644 --- a/Makefile +++ b/Makefile @@ -42,8 +42,8 @@ tlecatch: tlecatch.o $(patsubst %.cc,%.o,$(wildcard ext/sgp4/libsgp4/*.cc)) navmon.pb.cc: navmon.proto protoc --cpp_out=./ navmon.proto -ubxtool: navmon.pb.o ubxtool.o ubx.o bits.o ext/fmt-5.2.1/src/format.o galileo.o gps.o beidou.o navmon.o ephemeris.o - $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -lprotobuf +ubxtool: navmon.pb.o ubxtool.o ubx.o bits.o ext/fmt-5.2.1/src/format.o galileo.o gps.o beidou.o navmon.o ephemeris.o $(SIMPLESOCKETS) + $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -lprotobuf -pthread testrunner: navmon.pb.o testrunner.o ubx.o bits.o ext/fmt-5.2.1/src/format.o galileo.o gps.o beidou.o ephemeris.o $(CXX) -std=gnu++17 $^ -o $@ -L/usr/local/lib -lprotobuf diff --git a/navdump.cc b/navdump.cc index 8cd13ce..a0d9f9e 100644 --- a/navdump.cc +++ b/navdump.cc @@ -92,10 +92,10 @@ try tles.parseFile("gps-ops.txt"); tles.parseFile("beidou.txt"); - bool skipGPS{true}; - bool skipBeidou{true}; + bool skipGPS{false}; + bool skipBeidou{false}; bool skipGalileo{false}; - bool skipGlonass{true}; + bool skipGlonass{false}; ofstream almanac("almanac.txt"); ofstream iodstream("iodstream.csv"); diff --git a/ubxtool.cc b/ubxtool.cc index faa6717..f2f6a1e 100644 --- a/ubxtool.cc +++ b/ubxtool.cc @@ -26,11 +26,19 @@ #include "glonass.hh" #include "beidou.hh" #include "CLI/CLI.hpp" -struct timespec g_gstutc; -uint16_t g_wn; +#include +#include +#include "comboaddress.hh" +#include "swrappers.hh" +#include "sclasses.hh" + +struct timespec g_gnssutc; +uint16_t g_galwn; + using namespace std; -uint16_t g_srcid{2}; +uint16_t g_srcid{0}; + #define BAUDRATE B115200 @@ -77,30 +85,6 @@ t n w 28 15: 0 WN/TOW */ -/* - if(ubxClass == 2 && ubxType == 89) { // SAR - string hexstring; - for(int n = 0; n < 15; ++n) - hexstring+=fmt::format("%x", (int)getbitu(msg.c_str(), 36 + 4*n, 4)); - - // int sv = (int)msg[2]; - // wk.emitLine(sv, "SAR "+hexstring); - // cout<<"SAR: sv = "<< (int)msg[2] <<" "; - // for(int n=4; n < 12; ++n) - // fmt::printf("%02x", (int)msg[n]); - - // for(int n = 0; n < 15; ++n) - // fmt::printf("%x", (int)getbitu(msg.c_str(), 36 + 4*n, 4)); - - // cout << " Type: "<< (int) msg[12] <<"\n"; - // cout<<"Parameter: (len = "< queue; + std::mutex mut; + void emitNMM(const NavMonMessage& nmm); + }; + +public: + void addDestination(int fd) + { + auto d = std::make_unique(); + d->fd = fd; + d_dests.push_back(std::move(d)); + } + void addDestination(const ComboAddress& dest) + { + auto d = std::make_unique(); + d->dst = dest; + d_dests.push_back(std::move(d)); + } + + void launch() + { + for(auto& d : d_dests) { + if(d->dst.sin4.sin_port != 0) { + thread t(&NMMSender::sendTCPThread, this, d.get()); + t.detach(); + } + } + } + + void sendTCPThread(Destination* d) + { + for(;;) { + try { + Socket s(d->dst.sin4.sin_family, SOCK_STREAM); + SocketCommunicator sc(s); + sc.setTimeout(3); + sc.connect(d->dst); + cerr<<"Connected to "<dst.toStringWithPort()< mut(d->mut); + if(!d->queue.empty()) { + msg = d->queue.front(); + } + } + if(!msg.empty()) { + sc.writen(msg); + d->queue.pop_front(); + } + else usleep(100000); + } + } + catch(std::exception& e) { + cerr<<"Sending thread for "<dst.toStringWithPort()<<" had error: "< mut(d->mut); + cerr<<"There are now "<queue.size()<<" messages queued for "<dst.toStringWithPort()<dst.toStringWithPort()<<" had error"; + { + std::lock_guard mut(d->mut); + cerr<<"There are now "<queue.size()<<" messages queued for "<dst.toStringWithPort()<> 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"); @@ -238,10 +317,16 @@ void emitNMM(int fd, const NavMonMessage& nmm) uint16_t len = htons(out.size()); msg.append((char*)&len, 2); msg.append(out); - - writen2(fd, msg.c_str(), msg.size()); + + if(dst.sin4.sin_port) { + std::lock_guard l(mut); + queue.push_back(msg); + } + else + writen2(fd, msg.c_str(), msg.size()); } + void enableUBXMessageUSB(int fd, uint8_t ubxClass, uint8_t ubxType, uint8_t rate=1) { for(int n=0 ; n < 5; ++n) { @@ -335,15 +420,16 @@ int main(int argc, char** argv) CLI::App app("ubxtool"); - vector serial; - bool doGPS{true}, doGalileo{true}, doGlonass{false}, doBeidou{true}, doReset{false}, doWait{false}, doRTSCTS{true}, doSBAS{false}; + bool doGPS{true}, doGalileo{true}, doGlonass{false}, doBeidou{true}, doReset{false}, doWait{true}, doRTSCTS{true}, doSBAS{false}; + bool doSTDOUT=false; #ifdef OpenBSD doRTSCTS = false; #endif - app.add_option("serial", serial, "Serial"); - + vector destinations; + string portName; + app.add_option("--destination,-d", destinations, "Send output to this IPv4/v6 address"); app.add_flag("--wait", doWait, "Wait a bit, do not try to read init messages"); app.add_flag("--reset", doReset, "Reset UBX device"); app.add_flag("--beidou,-c", doBeidou, "Enable BeiDou reception"); @@ -352,22 +438,18 @@ int main(int argc, char** argv) app.add_flag("--galileo,-e", doGalileo, "Enable Galileo reception"); app.add_flag("--sbas,-s", doSBAS, "Enable SBAS (EGNOS/WAAS/etc) reception"); app.add_option("--rtscts", doRTSCTS, "Set hardware handshaking"); - - + app.add_flag("--stdout", doSTDOUT, "Emit output to stdout"); + app.add_option("--port,-p", portName, "Device or file to read serial from"); + app.add_option("--station", g_srcid, "Station id"); try { app.parse(argc, argv); } catch(const CLI::Error &e) { return app.exit(e); } - if(serial.size() != 2) { - cout<, struct timeval> lasttv, tv; int curCycleTOW{-1}; // means invalid - + signal(SIGPIPE, SIG_IGN); + NMMSender ns; + for(const auto& s : destinations) + ns.addDestination(ComboAddress(s, 29603)); + if(doSTDOUT) + ns.addDestination(1); + ns.launch(); + + cerr<<"Entering main loop"< %.4f or %d:%f\n", tm.tm_hour, tm.tm_min, seconds, satutc, timegm(&tm), pvt.nano/1000.0); - - if(!g_fromFile) { - // struct tm ourtime; - // time_t ourt = timestamp.tv_sec; - // gmtime_r(&ourt, &ourtime); - // - //double ourutc = ourt + timestamp.tv_usec/1000000.0; - - // seconds = ourtime.tm_sec + timestamp.tv_usec/1000000.0; - // fmt::fprintf(stderr, "Our UTC : %02d:%02d:%06.4f -> %.4f or %d:%f -> delta = %.4fs\n", tm.tm_hour, tm.tm_min, seconds, ourutc, timestamp.tv_sec, 1.0*timestamp.tv_usec, ourutc - satutc); - } + if(!g_gnssutc.tv_sec) + cerr<<"Got initial timestamp"<set_gnssid(gnssid); @@ -659,7 +738,7 @@ int main(int argc, char** argv) nmm.mutable_rfd()->set_dostd(ldexp(0.002, doStddev)); nmm.mutable_rfd()->set_cpstd(cpStddev*0.4); nmm.mutable_rfd()->set_locktimems(locktimems); - emitNMM(1, nmm); + ns.emitNMM( nmm); } } else if(msg.getClass() == 0x01 && msg.getType() == 0x01) { // POSECF @@ -681,14 +760,14 @@ int main(int argc, char** argv) NavMonMessage nmm; nmm.set_type(NavMonMessage::ObserverPositionType); - nmm.set_localutcseconds(g_gstutc.tv_sec); - nmm.set_localutcnanoseconds(g_gstutc.tv_nsec); + nmm.set_localutcseconds(g_gnssutc.tv_sec); + nmm.set_localutcnanoseconds(g_gnssutc.tv_nsec); nmm.set_sourceid(g_srcid); nmm.mutable_op()->set_x(p.ecefX /100.0); nmm.mutable_op()->set_y(p.ecefY /100.0); nmm.mutable_op()->set_z(p.ecefZ /100.0); nmm.mutable_op()->set_acc(p.pAcc /100.0); - emitNMM(1, nmm); + ns.emitNMM( nmm); } else if(msg.getClass() == 2 && msg.getType() == 0x13) { // SFRBX @@ -716,8 +795,8 @@ int main(int argc, char** argv) if(id.first == 0 && !sigid) { // can only parse the old stuff NavMonMessage nmm; nmm.set_type(NavMonMessage::GPSInavType); - nmm.set_localutcseconds(g_gstutc.tv_sec); - nmm.set_localutcnanoseconds(g_gstutc.tv_nsec); + nmm.set_localutcseconds(g_gnssutc.tv_sec); + nmm.set_localutcnanoseconds(g_gnssutc.tv_nsec); nmm.set_sourceid(g_srcid); // cerr<<"GPS frame, numwords: "<<(int)payload[4]<<", version: "<<(int)payload[6]<set_gnssid(id.first); nmm.mutable_gpsi()->set_gnsssv(id.second); nmm.mutable_gpsi()->set_contents(string((char*)gpsframe.c_str(), gpsframe.size())); - emitNMM(1, nmm); + ns.emitNMM( nmm); continue; } else if(id.first ==2) { @@ -744,12 +823,12 @@ int main(int argc, char** argv) // cerr<<" res1 "<<(int)payload[2]<<" numwords "<<(int)payload[4] << " channel "<< (int)payload[5] << " version " << (int)payload[6]<<" res2 "<<(int)payload[7]<set_gnsswn(g_wn); + nmm.mutable_gi()->set_gnsswn(g_galwn); nmm.mutable_gi()->set_gnsstow(msgTOW); nmm.mutable_gi()->set_gnssid(id.first); @@ -797,7 +876,7 @@ int main(int argc, char** argv) nmm.mutable_gi()->set_sigid(sigid); nmm.mutable_gi()->set_contents((const char*)&inav[0], inav.size()); - emitNMM(1, nmm); + ns.emitNMM( nmm); } else if(id.first==3) { auto gstr = getGlonassFromSFRBXMsg(payload); @@ -813,20 +892,23 @@ int main(int argc, char** argv) continue; } NavMonMessage nmm; - nmm.set_localutcseconds(g_gstutc.tv_sec); - nmm.set_localutcnanoseconds(g_gstutc.tv_nsec); + nmm.set_localutcseconds(g_gnssutc.tv_sec); + nmm.set_localutcnanoseconds(g_gnssutc.tv_nsec); nmm.set_sourceid(g_srcid); if(id.second > 5) { // this **HARDCODES** that C01,02,03,04,05 emit D2 messages! nmm.set_type(NavMonMessage::BeidouInavTypeD1); - nmm.mutable_bid1()->set_gnsswn(bm.wn); + nmm.mutable_bid1()->set_gnsswn(bm.wn); // only sent in word 1!! nmm.mutable_bid1()->set_gnsstow(bm.sow); nmm.mutable_bid1()->set_gnssid(id.first); nmm.mutable_bid1()->set_gnsssv(id.second); nmm.mutable_bid1()->set_sigid(sigid); nmm.mutable_bid1()->set_contents(string((char*)gstr.c_str(), gstr.size())); + ns.emitNMM( nmm); } else { + // not sending this: we can't even get the week number right! + /* nmm.set_type(NavMonMessage::BeidouInavTypeD2); nmm.mutable_bid2()->set_gnsswn(bm.wn); nmm.mutable_bid2()->set_gnsstow(bm.sow); @@ -834,8 +916,10 @@ int main(int argc, char** argv) nmm.mutable_bid2()->set_gnsssv(id.second); nmm.mutable_bid2()->set_sigid(sigid); nmm.mutable_bid2()->set_contents(string((char*)gstr.c_str(), gstr.size())); + */ + } - emitNMM(1, nmm); + continue; } else if(id.first==6) { @@ -848,8 +932,8 @@ int main(int argc, char** argv) */ if(id.second != 255) { NavMonMessage nmm; - nmm.set_localutcseconds(g_gstutc.tv_sec); - nmm.set_localutcnanoseconds(g_gstutc.tv_nsec); + nmm.set_localutcseconds(g_gnssutc.tv_sec); + nmm.set_localutcnanoseconds(g_gnssutc.tv_nsec); nmm.set_sourceid(g_srcid); nmm.set_type(NavMonMessage::GlonassInavType); nmm.mutable_gloi()->set_freq(payload[3]); @@ -858,21 +942,14 @@ int main(int argc, char** argv) nmm.mutable_gloi()->set_sigid(sigid); nmm.mutable_gloi()->set_contents(string((char*)gstr.c_str(), gstr.size())); - emitNMM(1, nmm); + ns.emitNMM( nmm); } } + else if(id.first == 1) {// SBAS + } else cerr<<"SFRBX from unsupported GNSSID/sigid combination "< %d:%d, delta=%d\n", - payload[0], payload[1], wtype, lasttv[id].tv_sec, lasttv[id].tv_usec, tv[id].tv_sec, tv[id].tv_usec, tv[id].tv_usec - lasttv[id].tv_usec); - } -#endif - lasttv[id]=tv[id]; - - } catch(CRCMismatch& cm) { cerr<<"Had CRC mismatch!"<set_gnssid(gnssid); @@ -902,7 +979,23 @@ int main(int argc, char** argv) nmm.mutable_rd()->set_el(el); nmm.mutable_rd()->set_azi(azi); nmm.mutable_rd()->set_prres(*((int16_t*)(payload.c_str()+ 14 +12*n)) *0.1); - emitNMM(1, nmm); + /* + uint32_t status; + memcpy(&status, &payload[16+12*n], 4); + cerr<> 8)&7); + cerr<<" eph-avail " << !!(status & (1<<11)); + cerr<<" alm-avail " << !!(status & (1<<12)); + cerr<set_gnssid(gnssid); @@ -938,7 +1031,7 @@ int main(int argc, char** argv) nmm.mutable_rd()->set_el(0); nmm.mutable_rd()->set_azi(0); - emitNMM(1, nmm); + ns.emitNMM( nmm); } } else if(msg.getClass() == 1 && msg.getType() == 0x30) { // UBX-NAV-SVINFO @@ -965,8 +1058,8 @@ int main(int argc, char** argv) NavMonMessage nmm; nmm.set_sourceid(g_srcid); - nmm.set_localutcseconds(g_gstutc.tv_sec); - nmm.set_localutcnanoseconds(g_gstutc.tv_nsec); + nmm.set_localutcseconds(g_gnssutc.tv_sec); + nmm.set_localutcnanoseconds(g_gnssutc.tv_nsec); nmm.set_type(NavMonMessage::SARResponseType); nmm.mutable_sr()->set_gnssid(2); // Galileo only for now