#include #include #include #include #include "fmt/format.h" #include "fmt/printf.h" #include #include #include #include #include #include "galileo.hh" #include "navmon.pb.h" #include #include "navmon.hh" #include "CLI/CLI.hpp" #include "version.hh" static char program[]="navdisplay"; using namespace std; extern const char* g_gitHash; struct WinKeeper { WinKeeper(); struct Window { WINDOW *header, *text; int sv; void setHeader(std::string_view line) { wclear(header); wmove(header, 0, 0); wattron(header, A_BOLD | A_UNDERLINE); wprintw(header, "%s", &line[0]); wattroff(header, A_BOLD | A_UNDERLINE); wrefresh(header); } void setStatus(std::string_view line) { wmove(header, 1, 0); wattron(header, A_BOLD); wprintw(header, "%s", &line[0]); wattroff(header, A_BOLD); wrefresh(header); } void emitLine(std::string_view line) { wprintw(text, "%s\n", &line[0]); wrefresh(text); } void clear() { wclear(header); wrefresh(header); wclear(text); wrefresh(text); } time_t lastTime{0}; }; vector d_windows; static int d_h, d_w; void emitLine(int sv, std::string_view line); void setStatus(int sv, std::string_view line); }; int WinKeeper::d_h; int WinKeeper::d_w; WinKeeper::WinKeeper() { initscr(); getmaxyx(stdscr, d_h, d_w); int winwidth = d_w / 7; for(int n=0; n < 8 ; ++n) { d_windows.push_back({ newwin(3, winwidth, 0, n*(winwidth+2)), newwin(d_h-3, winwidth, 3, n*(winwidth+2)), 0}); scrollok(d_windows[n].text, 1); } }; void WinKeeper::emitLine(int sv, std::string_view line) { for(auto& w: d_windows) { if(w.sv == sv) { w.emitLine(line); return; } } // nothing matched, need to find a new window for(auto& w: d_windows) { if(!w.sv) { w.sv = sv; w.setHeader(std::to_string(sv)); w.emitLine(line); return; } } // all windows are in use, take over oldest one int age=0; time_t now = time(0); auto *wptr = &*d_windows.begin(); for(auto& w: d_windows) { if(now - w.lastTime > age) { age = now - w.lastTime; wptr = &w; } } wptr->sv = sv; wptr->setHeader(std::to_string(sv)); wptr->emitLine(line); wptr->lastTime = now; } void WinKeeper::setStatus(int sv, std::string_view line) { for(auto& w: d_windows) { if(w.sv == sv) { w.setStatus(line); return; } } // nothing matched for(auto& w: d_windows) { if(!w.sv) { w.sv = sv; w.setHeader(std::to_string(sv)); w.setStatus(line); return; } } throw std::runtime_error("Ran out of windows searching for sv "+std::to_string(sv)); } int main(int argc, char** argv) { bool doVERSION{false}; CLI::App app(program); app.add_flag("--version", doVERSION, "show program version and copyright"); try { app.parse(argc, argv); } catch(const CLI::Error &e) { return app.exit(e); } if(doVERSION) { showVersion(program, g_gitHash); exit(0); } WinKeeper wk; for(;;) { char bert[4]; if(readn2(0, bert, 4) != 4 || bert[0]!='b' || bert[1]!='e' || bert[2] !='r' || bert[3]!='t') { cerr<<"EOF or bad magic"< gms; GalileoMessage& gm = gms[nmm.gi().gnsssv()]; basic_string inav((uint8_t*)nmm.gi().contents().c_str(), nmm.gi().contents().size()); int wtype =gm.parse(inav); wk.emitLine(sv, "src "+to_string(nmm.sourceid())+" wtype " + to_string(wtype)); // wk.setStatus(sv, "Hlth: "+std::to_string(getbitu(&inav[0], 67, 2)) +", el="+to_string(g_svstats[sv].el)+", db="+to_string(g_svstats[sv].db) ); // wk.emitLine(sv, "GST-UTC6, a0="+to_string(a0)+", a1="+to_string(a1)+", age="+to_string(tow/3600-t0t)+"h, dw="+to_string(dw) // +", wn0t="+to_string(wn0t)+", wn8="+to_string(wn&0xff)); // wk.emitLine(sv, "GST-UTC6, a0="+to_string(a0)+", a1="+to_string(a1)); // wk.emitLine(sv, "Alm"+to_string(wtype)+" IODa="+to_string(ioda)); // wk.emitLine(sv, "GST-GPS, a0g="+to_string(a0g)+", a1g="+to_string(a1g)+", t0g="+to_string(t0g)+", age="+to_string(tow/3600-t0g)+"h, dw="+to_string(dw) // +", wn0g="+to_string(wn0g)+", wn6="+to_string(wn&(1+2+4+8+16+32))); } } }