From f6b1b94c7dca1b407b8e4f02ef3206e3ca3ad28f Mon Sep 17 00:00:00 2001 From: Oliver Jowett Date: Tue, 11 Oct 2016 20:37:28 +0100 Subject: [PATCH] Use ncurses for interactive mode (reduces flicker on slow connections a lot!) --- Makefile | 4 +- debian/control | 2 +- dump1090.c | 37 ++----------- dump1090.h | 5 +- interactive.c | 144 +++++++++++++++++++++++++------------------------ view1090.c | 35 +----------- 6 files changed, 84 insertions(+), 143 deletions(-) diff --git a/Makefile b/Makefile index 38ffa8405..a09c267cc 100644 --- a/Makefile +++ b/Makefile @@ -28,10 +28,10 @@ all: dump1090 view1090 $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ dump1090: dump1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o crc.o demod_2400.o stats.o cpr.o icao_filter.o track.o util.o convert.o $(COMPAT) - $(CC) -g -o $@ $^ $(LDFLAGS) $(LIBS) $(LIBS_RTLSDR) + $(CC) -g -o $@ $^ $(LDFLAGS) $(LIBS) $(LIBS_RTLSDR) -lncurses view1090: view1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o crc.o stats.o cpr.o icao_filter.o track.o util.o $(COMPAT) - $(CC) -g -o $@ $^ $(LDFLAGS) $(LIBS) + $(CC) -g -o $@ $^ $(LDFLAGS) $(LIBS) -lncurses faup1090: faup1090.o anet.o mode_ac.o mode_s.o net_io.o crc.o stats.o cpr.o icao_filter.o track.o util.o $(COMPAT) $(CC) -g -o $@ $^ $(LDFLAGS) $(LIBS) diff --git a/debian/control b/debian/control index 4245f738b..1ee5bdbc9 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: dump1090-fa Section: embedded Priority: extra Maintainer: Oliver Jowett -Build-Depends: debhelper(>=9), librtlsdr-dev, libusb-1.0-0-dev, pkg-config, dh-systemd +Build-Depends: debhelper(>=9), librtlsdr-dev, libusb-1.0-0-dev, pkg-config, dh-systemd, libncurses5-dev Standards-Version: 3.9.3 Homepage: https://github.com/mutability/dump1090 Vcs-Git: https://github.com/mutability/dump1090.git diff --git a/dump1090.c b/dump1090.c index ef0504d50..3561c7c04 100644 --- a/dump1090.c +++ b/dump1090.c @@ -95,27 +95,6 @@ static void sigtermHandler(int dummy) { Modes.exit = 1; // Signal to threads that we are done log_with_timestamp("Caught SIGTERM, shutting down..\n"); } -// -// =============================== Terminal handling ======================== -// -#ifndef _WIN32 -// Get the number of rows after the terminal changes size. -int getTermRows() { - struct winsize w; - ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); - return (w.ws_row); -} - -// Handle resizing terminal -void sigWinchCallback() { - signal(SIGWINCH, SIG_IGN); - Modes.interactive_rows = getTermRows(); - interactiveShowData(); - signal(SIGWINCH, sigWinchCallback); -} -#else -int getTermRows() { return MODES_INTERACTIVE_ROWS;} -#endif static void start_cpu_timing(struct timespec *start_time) { @@ -153,7 +132,6 @@ void modesInitConfig(void) { #ifdef ENABLE_WEBSERVER Modes.net_http_ports = strdup("8080"); #endif - Modes.interactive_rows = getTermRows(); Modes.interactive_display_ttl = MODES_INTERACTIVE_DISPLAY_TTL; Modes.html_dir = HTMLPATH; Modes.json_interval = 1000; @@ -244,6 +222,7 @@ void modesInit(void) { modesChecksumInit(Modes.nfix_crc); icaoFilterInit(); modeACInit(); + interactiveInit(); if (Modes.show_only) icaoFilterAdd(Modes.show_only); @@ -675,9 +654,7 @@ void showHelp(void) { "--iformat Sample format for --ifile: UC8 (default), SC16, or SC16Q11\n" "--throttle When reading from a file, play back in realtime, not at max speed\n" "--interactive Interactive mode refreshing data on screen. Implies --throttle\n" -"--interactive-rows Max number of rows in interactive mode (default: 15)\n" "--interactive-ttl Remove from list if idle for (default: 60)\n" -"--interactive-rtl1090 Display flight table in RTL1090 format\n" "--raw Show only messages hex values\n" "--net Enable networking\n" "--modeac Enable decoding of SSR Modes 3/A & 3/C\n" @@ -1031,8 +1008,6 @@ int main(int argc, char **argv) { Modes.interactive = Modes.throttle = 1; } else if (!strcmp(argv[j],"--throttle")) { Modes.throttle = 1; - } else if (!strcmp(argv[j],"--interactive-rows") && more) { - Modes.interactive_rows = atoi(argv[++j]); } else if (!strcmp(argv[j],"--interactive-ttl") && more) { Modes.interactive_display_ttl = (uint64_t)(1000 * atof(argv[++j])); } else if (!strcmp(argv[j],"--lat") && more) { @@ -1080,9 +1055,6 @@ int main(int argc, char **argv) { Modes.show_only = (uint32_t) strtoul(argv[++j], NULL, 16); } else if (!strcmp(argv[j],"--mlat")) { Modes.mlat = 1; - } else if (!strcmp(argv[j],"--interactive-rtl1090")) { - Modes.interactive = 1; - Modes.interactive_rtl1090 = 1; } else if (!strcmp(argv[j],"--oversample")) { // Ignored } else if (!strcmp(argv[j], "--html-dir") && more) { @@ -1111,11 +1083,6 @@ int main(int argc, char **argv) { if (!Modes.quiet) {showCopyright();} #endif -#ifndef _WIN32 - // Setup for SIGWINCH for handling lines - if (Modes.interactive) {signal(SIGWINCH, sigWinchCallback);} -#endif - // Initialization log_with_timestamp("%s %s starting up.", MODES_DUMP1090_VARIANT, MODES_DUMP1090_VERSION); modesInit(); @@ -1252,6 +1219,8 @@ int main(int argc, char **argv) { pthread_mutex_destroy(&Modes.data_mutex); } + interactiveCleanup(); + // If --stats were given, print statistics if (Modes.stats) { display_total_stats(); diff --git a/dump1090.h b/dump1090.h index 704284a82..ccfd389d3 100644 --- a/dump1090.h +++ b/dump1090.h @@ -210,7 +210,6 @@ typedef enum { #define MODES_DEBUG_NOPREAMBLE_LEVEL 25 #define MODES_INTERACTIVE_REFRESH_TIME 250 // Milliseconds -#define MODES_INTERACTIVE_ROWS 22 // Rows on screen #define MODES_INTERACTIVE_DISPLAY_TTL 60000 // Delete from display after 60 seconds #define MODES_NET_HEARTBEAT_INTERVAL 60000 // milliseconds @@ -330,7 +329,6 @@ struct { // Internal state int quiet; // Suppress stdout uint32_t show_only; // Only show messages from this ICAO int interactive; // Interactive mode - int interactive_rows; // Interactive mode: max number of rows uint64_t interactive_display_ttl;// Interactive mode: TTL display uint64_t stats; // Interval (millis) between stats dumps, int stats_range_histo; // Collect/show a range histogram? @@ -338,7 +336,6 @@ struct { // Internal state int metric; // Use metric units int use_gnss; // Use GNSS altitudes with H suffix ("HAE", though it isn't always) when available int mlat; // Use Beast ascii format for raw data output, i.e. @...; iso *...; - int interactive_rtl1090; // flight table in interactive mode is formatted like RTL1090 char *json_dir; // Path to json base directory, or NULL not to write json. uint64_t json_interval; // Interval between rewriting the json aircraft file, in milliseconds; also the advertised map refresh interval char *html_dir; // Path to www base directory. @@ -559,7 +556,9 @@ void useModesMessage (struct modesMessage *mm); // // Functions exported from interactive.c // +void interactiveInit(void); void interactiveShowData(void); +void interactiveCleanup(void); #ifdef __cplusplus } diff --git a/interactive.c b/interactive.c index 6dfca6df2..c26800bfd 100644 --- a/interactive.c +++ b/interactive.c @@ -49,6 +49,8 @@ #include "dump1090.h" +#include + // //========================= Interactive mode =============================== @@ -74,11 +76,29 @@ static int convert_speed(int kts) // // Show the currently captured interactive data on screen. // + +void interactiveInit() { + if (!Modes.interactive) + return; + + initscr(); + clear(); + refresh(); + + mvprintw(0, 0, " Hex Mode Sqwk Flight Alt Spd Hdg Lat Long RSSI Msgs Ti"); + mvhline(1, 0, ACS_HLINE, 80); +} + +void interactiveCleanup(void) { + if (Modes.interactive) { + endwin(); + } +} + void interactiveShowData(void) { struct aircraft *a = Modes.aircrafts; static uint64_t next_update; uint64_t now = mstime(); - int count = 3; char progress; char spinner[4] = "|/-\\"; @@ -89,24 +109,12 @@ void interactiveShowData(void) { next_update = now + MODES_INTERACTIVE_REFRESH_TIME; progress = spinner[(now/1000)%4]; + mvaddch(0, 79, progress); -#ifndef _WIN32 - printf("\x1b[H\x1b[2J"); // Clear the screen -#else - cls(); -#endif - - if (Modes.interactive_rtl1090 == 0) { - printf ( -" Hex Mode Sqwk Flight Alt Spd Hdg Lat Long RSSI Msgs Ti%c\n", progress); - } else { - printf ( -" Hex Flight Alt V/S GS TT SSR G*456^ Msgs Seen %c\n", progress); - } - printf( -"-------------------------------------------------------------------------------\n"); + int rows = getmaxy(stdscr); + int row = 2; - while(a && (count < Modes.interactive_rows)) { + while (a && row < rows) { if ((now - a->seen) < Modes.interactive_display_ttl) { @@ -134,51 +142,42 @@ void interactiveShowData(void) { msgs = 99999; } - if (Modes.interactive_rtl1090) { // RTL1090 display mode - if (trackDataValid(&a->altitude_valid)) { - snprintf(strFl,6,"F%03d",((a->altitude+50)/100)); - } - printf("%06x %-8s %-4s %-3s %-3s %4s %-6d %-2.0f\n", - a->addr, a->callsign, strFl, strGs, strTt, strSquawk, msgs, (now - a->seen)/1000.0); - - } else { // Dump1090 display mode - char strMode[5] = " "; - char strLat[8] = " "; - char strLon[9] = " "; - double * pSig = a->signalLevel; - double signalAverage = (pSig[0] + pSig[1] + pSig[2] + pSig[3] + - pSig[4] + pSig[5] + pSig[6] + pSig[7]) / 8.0; - - strMode[0] = 'S'; - if (a->modeA_hit) {strMode[2] = 'a';} - if (a->modeC_hit) {strMode[3] = 'c';} - - if (trackDataValid(&a->position_valid)) { - snprintf(strLat, 8,"%7.03f", a->lat); - snprintf(strLon, 9,"%8.03f", a->lon); - } - - if (trackDataValid(&a->airground_valid) && a->airground == AG_GROUND) { - snprintf(strFl, 7," grnd"); - } else if (Modes.use_gnss && trackDataValid(&a->altitude_gnss_valid)) { - snprintf(strFl, 7, "%5dH", convert_altitude(a->altitude_gnss)); - } else if (trackDataValid(&a->altitude_valid)) { - snprintf(strFl, 7, "%5d ", convert_altitude(a->altitude)); - } - - printf("%s%06X %-4s %-4s %-8s %6s %3s %3s %7s %8s %5.1f %5d %2.0f\n", - (a->addr & MODES_NON_ICAO_ADDRESS) ? "~" : " ", (a->addr & 0xffffff), - strMode, strSquawk, a->callsign, strFl, strGs, strTt, - strLat, strLon, 10 * log10(signalAverage), msgs, (now - a->seen)/1000.0); + char strMode[5] = " "; + char strLat[8] = " "; + char strLon[9] = " "; + double * pSig = a->signalLevel; + double signalAverage = (pSig[0] + pSig[1] + pSig[2] + pSig[3] + + pSig[4] + pSig[5] + pSig[6] + pSig[7]) / 8.0; + + strMode[0] = 'S'; + if (a->modeA_hit) {strMode[2] = 'a';} + if (a->modeC_hit) {strMode[3] = 'c';} + + if (trackDataValid(&a->position_valid)) { + snprintf(strLat, 8,"%7.03f", a->lat); + snprintf(strLon, 9,"%8.03f", a->lon); + } + + if (trackDataValid(&a->airground_valid) && a->airground == AG_GROUND) { + snprintf(strFl, 7," grnd"); + } else if (Modes.use_gnss && trackDataValid(&a->altitude_gnss_valid)) { + snprintf(strFl, 7, "%5dH", convert_altitude(a->altitude_gnss)); + } else if (trackDataValid(&a->altitude_valid)) { + snprintf(strFl, 7, "%5d ", convert_altitude(a->altitude)); } - count++; + + mvprintw(row, 0, "%s%06X %-4s %-4s %-8s %6s %3s %3s %7s %8s %5.1f %5d %2.0f", + (a->addr & MODES_NON_ICAO_ADDRESS) ? "~" : " ", (a->addr & 0xffffff), + strMode, strSquawk, a->callsign, strFl, strGs, strTt, + strLat, strLon, 10 * log10(signalAverage), msgs, (now - a->seen)/1000.0); + ++row; } } a = a->next; } - if (!Modes.interactive_rtl1090 && Modes.mode_ac) { - for (unsigned i = 1; i < 4096 && count < Modes.interactive_rows; ++i) { + if (Modes.mode_ac) { + for (unsigned i = 1; i < 4096 && row < rows; ++i) { if (modeAC_match[i] || modeAC_count[i] < 100) continue; @@ -191,22 +190,27 @@ void interactiveShowData(void) { snprintf(strFl, 7, "%5d ", convert_altitude(modeC * 100)); } - printf("%7s %-4s %04x %-8s %6s %3s %3s %7s %8s %5s %5d %2s\n", - "", /* address */ - strMode, /* mode */ - modeA, /* squawk */ - "", /* callsign */ - strFl, /* altitude */ - "", /* gs */ - "", /* heading */ - "", /* lat */ - "", /* lon */ - "", /* signal */ - modeAC_count[i], /* messages */ - ""); /* seen */ - count++; + mvprintw(row, 0, + "%7s %-4s %04x %-8s %6s %3s %3s %7s %8s %5s %5d %2s\n", + "", /* address */ + strMode, /* mode */ + modeA, /* squawk */ + "", /* callsign */ + strFl, /* altitude */ + "", /* gs */ + "", /* heading */ + "", /* lat */ + "", /* lon */ + "", /* signal */ + modeAC_count[i], /* messages */ + ""); /* seen */ + ++row; } } + + move(row, 0); + clrtobot(); + refresh(); } // diff --git a/view1090.c b/view1090.c index 38b2fc4ef..e099abc36 100644 --- a/view1090.c +++ b/view1090.c @@ -36,27 +36,7 @@ void sigintHandler(int dummy) { signal(SIGINT, SIG_DFL); // reset signal handler - bit extra safety Modes.exit = 1; // Signal to threads that we are done } -// -// =============================== Terminal handling ======================== -// -#ifndef _WIN32 -// Get the number of rows after the terminal changes size. -int getTermRows() { - struct winsize w; - ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); - return (w.ws_row); -} -// Handle resizing terminal -void sigWinchCallback() { - signal(SIGWINCH, SIG_IGN); - Modes.interactive_rows = getTermRows(); - interactiveShowData(); - signal(SIGWINCH, sigWinchCallback); -} -#else -int getTermRows() { return MODES_INTERACTIVE_ROWS;} -#endif // // =============================== Initialization =========================== // @@ -66,7 +46,6 @@ void view1090InitConfig(void) { // Now initialise things that should not be 0/NULL to their defaults Modes.check_crc = 1; - Modes.interactive_rows = getTermRows(); Modes.interactive_display_ttl = MODES_INTERACTIVE_DISPLAY_TTL; Modes.interactive = 1; Modes.maxRange = 1852 * 300; // 300NM default max range @@ -113,6 +92,7 @@ void view1090Init(void) { modesChecksumInit(Modes.nfix_crc); icaoFilterInit(); modeACInit(); + interactiveInit(); } // @@ -124,9 +104,7 @@ void showHelp(void) { "| view1090 ModeS Viewer %45s |\n" "-----------------------------------------------------------------------------\n" "--no-interactive Disable interactive mode, print messages to stdout\n" - "--interactive-rows Max number of rows in interactive mode (default: 15)\n" "--interactive-ttl Remove from list if idle for (default: 60)\n" - "--interactive-rtl1090 Display flight table in RTL1090 format\n" "--modeac Enable decoding of SSR modes 3/A & 3/C\n" "--net-bo-ipaddr TCP Beast output listen IPv4 (default: 127.0.0.1)\n" "--net-bo-port TCP Beast output listen port (default: 30005)\n" @@ -169,8 +147,6 @@ int main(int argc, char **argv) { bo_connect_ipaddr = argv[++j]; } else if (!strcmp(argv[j],"--modeac")) { Modes.mode_ac = 1; - } else if (!strcmp(argv[j],"--interactive-rows") && more) { - Modes.interactive_rows = atoi(argv[++j]); } else if (!strcmp(argv[j],"--no-interactive")) { Modes.interactive = 0; } else if (!strcmp(argv[j],"--show-only") && more) { @@ -178,9 +154,6 @@ int main(int argc, char **argv) { Modes.interactive = 0; } else if (!strcmp(argv[j],"--interactive-ttl") && more) { Modes.interactive_display_ttl = (uint64_t)(1000 * atof(argv[++j])); - } else if (!strcmp(argv[j],"--interactive-rtl1090")) { - Modes.interactive = 1; - Modes.interactive_rtl1090 = 1; } else if (!strcmp(argv[j],"--lat") && more) { Modes.fUserLat = atof(argv[++j]); } else if (!strcmp(argv[j],"--lon") && more) { @@ -213,11 +186,6 @@ int main(int argc, char **argv) { #define MSG_DONTWAIT 0 #endif -#ifndef _WIN32 - // Setup for SIGWINCH for handling lines - if (Modes.interactive) {signal(SIGWINCH, sigWinchCallback);} -#endif - // Initialization view1090Init(); modesInitNet(); @@ -249,6 +217,7 @@ int main(int argc, char **argv) { usleep(100000); } + interactiveCleanup(); return (0); } //