diff --git a/dump1090.c b/dump1090.c index 7a7addd..e8096a3 100644 --- a/dump1090.c +++ b/dump1090.c @@ -428,6 +428,7 @@ void showHelp(void) { "--aggressive More CPU for more messages (two bits fixes, ...)\n" "--mlat display raw messages in Beast ascii mode\n" "--stats With --ifile print stats at exit. No other output\n" +"--stats-every Show and reset stats every seconds\n" "--onlyaddr Show only ICAO addresses (testing purposes)\n" "--metric Use metric units (meters, km/h, ...)\n" "--snip Strip IQ file removing samples < level\n" @@ -480,6 +481,86 @@ void showCopyright(void) { while (llTime >= time(NULL)) {} } #endif + + +static void display_stats(void) { + int j; + time_t now = time(NULL); + + printf("\n\n"); + if (Modes.interactive) + interactiveShowData(); + + printf("Statistics as at %s", ctime(&now)); + + printf("%d sample blocks processed\n", Modes.stat_blocks_processed); + printf("%d sample blocks dropped\n", Modes.stat_blocks_dropped); + + printf("%d ModeA/C detected\n", Modes.stat_ModeAC); + printf("%d valid Mode-S preambles\n", Modes.stat_valid_preamble); + printf("%d DF-?? fields corrected for length\n", Modes.stat_DF_Len_Corrected); + printf("%d DF-?? fields corrected for type\n", Modes.stat_DF_Type_Corrected); + printf("%d demodulated with 0 errors\n", Modes.stat_demodulated0); + printf("%d demodulated with 1 error\n", Modes.stat_demodulated1); + printf("%d demodulated with 2 errors\n", Modes.stat_demodulated2); + printf("%d demodulated with > 2 errors\n", Modes.stat_demodulated3); + printf("%d with good crc\n", Modes.stat_goodcrc); + printf("%d with bad crc\n", Modes.stat_badcrc); + printf("%d errors corrected\n", Modes.stat_fixed); + + for (j = 0; j < MODES_MAX_BITERRORS; j++) { + printf(" %d with %d bit %s\n", Modes.stat_bit_fix[j], j+1, (j==0)?"error":"errors"); + } + + if (Modes.phase_enhance) { + printf("%d phase enhancement attempts\n", Modes.stat_out_of_phase); + printf("%d phase enhanced demodulated with 0 errors\n", Modes.stat_ph_demodulated0); + printf("%d phase enhanced demodulated with 1 error\n", Modes.stat_ph_demodulated1); + printf("%d phase enhanced demodulated with 2 errors\n", Modes.stat_ph_demodulated2); + printf("%d phase enhanced demodulated with > 2 errors\n", Modes.stat_ph_demodulated3); + printf("%d phase enhanced with good crc\n", Modes.stat_ph_goodcrc); + printf("%d phase enhanced with bad crc\n", Modes.stat_ph_badcrc); + printf("%d phase enhanced errors corrected\n", Modes.stat_ph_fixed); + + for (j = 0; j < MODES_MAX_BITERRORS; j++) { + printf(" %d with %d bit %s\n", Modes.stat_ph_bit_fix[j], j+1, (j==0)?"error":"errors"); + } + } + + printf("%d total usable messages\n", Modes.stat_goodcrc + Modes.stat_ph_goodcrc + Modes.stat_fixed + Modes.stat_ph_fixed); + fflush(stdout); + + Modes.stat_blocks_processed = + Modes.stat_blocks_dropped = 0; + + Modes.stat_ModeAC = + Modes.stat_valid_preamble = + Modes.stat_DF_Len_Corrected = + Modes.stat_DF_Type_Corrected = + Modes.stat_demodulated0 = + Modes.stat_demodulated1 = + Modes.stat_demodulated2 = + Modes.stat_demodulated3 = + Modes.stat_goodcrc = + Modes.stat_badcrc = + Modes.stat_fixed = 0; + + Modes.stat_out_of_phase = + Modes.stat_ph_demodulated0 = + Modes.stat_ph_demodulated1 = + Modes.stat_ph_demodulated2 = + Modes.stat_ph_demodulated3 = + Modes.stat_ph_goodcrc = + Modes.stat_ph_badcrc = + Modes.stat_ph_fixed = 0; + + for (j = 0; j < MODES_MAX_BITERRORS; j++) { + Modes.stat_ph_bit_fix[j] = 0; + Modes.stat_bit_fix[j] = 0; + } +} + + // //========================================================================= // @@ -488,6 +569,8 @@ void showCopyright(void) { // from the net, refreshing the screen in interactive mode, and so forth // void backgroundTasks(void) { + static time_t next_stats; + if (Modes.net) { modesReadFromClients(); } @@ -501,6 +584,15 @@ void backgroundTasks(void) { if (Modes.interactive) { interactiveShowData(); } + + if (Modes.stats > 0) { + time_t now = time(NULL); + if (now > next_stats) { + if (next_stats != 0) + display_stats(); + next_stats = now + Modes.stats; + } + } } // //========================================================================= @@ -665,7 +757,9 @@ int main(int argc, char **argv) { f++; } } else if (!strcmp(argv[j],"--stats")) { - Modes.stats = 1; + Modes.stats = -1; + } else if (!strcmp(argv[j],"--stats-every") && more) { + Modes.stats = atoi(argv[++j]); } else if (!strcmp(argv[j],"--snip") && more) { snipMode(atoi(argv[++j])); exit(0); @@ -759,6 +853,7 @@ int main(int argc, char **argv) { // If we lost some blocks, correct the timestamp if (Modes.iDataLost) { Modes.timestampBlk += (MODES_ASYNC_BUF_SAMPLES * 6 * Modes.iDataLost); + Modes.stat_blocks_dropped += Modes.iDataLost; Modes.iDataLost = 0; } @@ -773,7 +868,7 @@ int main(int argc, char **argv) { // Update the timestamp ready for the next block Modes.timestampBlk += (MODES_ASYNC_BUF_SAMPLES*6); - + Modes.stat_blocks_processed++; } else { pthread_cond_signal (&Modes.data_cond); pthread_mutex_unlock(&Modes.data_mutex); @@ -785,37 +880,7 @@ int main(int argc, char **argv) { // If --stats were given, print statistics if (Modes.stats) { - printf("\n\n"); - if (Modes.interactive) - interactiveShowData(); - printf("%d ModeA/C detected\n", Modes.stat_ModeAC); - printf("%d valid Mode-S preambles\n", Modes.stat_valid_preamble); - printf("%d DF-?? fields corrected for length\n", Modes.stat_DF_Len_Corrected); - printf("%d DF-?? fields corrected for type\n", Modes.stat_DF_Type_Corrected); - printf("%d demodulated with 0 errors\n", Modes.stat_demodulated0); - printf("%d demodulated with 1 error\n", Modes.stat_demodulated1); - printf("%d demodulated with 2 errors\n", Modes.stat_demodulated2); - printf("%d demodulated with > 2 errors\n", Modes.stat_demodulated3); - printf("%d with good crc\n", Modes.stat_goodcrc); - printf("%d with bad crc\n", Modes.stat_badcrc); - printf("%d errors corrected\n", Modes.stat_fixed); - for (j = 0; j < MODES_MAX_BITERRORS; j++) { - printf(" %d with %d bit %s\n", Modes.stat_bit_fix[j], j+1, (j==0)?"error":"errors"); - } - if (Modes.phase_enhance) { - printf("%d phase enhancement attempts\n", Modes.stat_out_of_phase); - printf("%d phase enhanced demodulated with 0 errors\n", Modes.stat_ph_demodulated0); - printf("%d phase enhanced demodulated with 1 error\n", Modes.stat_ph_demodulated1); - printf("%d phase enhanced demodulated with 2 errors\n", Modes.stat_ph_demodulated2); - printf("%d phase enhanced demodulated with > 2 errors\n", Modes.stat_ph_demodulated3); - printf("%d phase enhanced with good crc\n", Modes.stat_ph_goodcrc); - printf("%d phase enhanced with bad crc\n", Modes.stat_ph_badcrc); - printf("%d phase enhanced errors corrected\n", Modes.stat_ph_fixed); - for (j = 0; j < MODES_MAX_BITERRORS; j++) { - printf(" %d with %d bit %s\n", Modes.stat_ph_bit_fix[j], j+1, (j==0)?"error":"errors"); - } - } - printf("%d total usable messages\n", Modes.stat_goodcrc + Modes.stat_ph_goodcrc + Modes.stat_fixed + Modes.stat_ph_fixed); + display_stats(); } if (Modes.filename == NULL) { diff --git a/dump1090.h b/dump1090.h index 77584bb..b7adae3 100644 --- a/dump1090.h +++ b/dump1090.h @@ -366,6 +366,9 @@ struct { // Internal state unsigned int stat_DF_Len_Corrected; unsigned int stat_DF_Type_Corrected; unsigned int stat_ModeAC; + + unsigned int stat_blocks_processed; + unsigned int stat_blocks_dropped; } Modes; // The struct we use to store information about a decoded message. @@ -433,7 +436,7 @@ void decodeModesMessage (struct modesMessage *mm, unsigned char *msg); void displayModesMessage(struct modesMessage *mm); void useModesMessage (struct modesMessage *mm); void computeMagnitudeVector(uint16_t *pData); -void decodeCPR (struct aircraft *a, int fflag, int surface); +int decodeCPR (struct aircraft *a, int fflag, int surface); int decodeCPRrelative (struct aircraft *a, int fflag, int surface); void modesInitErrorInfo (); // diff --git a/interactive.c b/interactive.c index 6d08fc8..4f7e029 100644 --- a/interactive.c +++ b/interactive.c @@ -343,6 +343,7 @@ struct aircraft *interactiveReceiveData(struct modesMessage *mm) { // If we've got a new cprlat or cprlon if (mm->bFlags & MODES_ACFLAGS_LLEITHER_VALID) { + int location_ok = 0; if (mm->bFlags & MODES_ACFLAGS_LLODD_VALID) { a->odd_cprlat = mm->raw_latitude; @@ -354,23 +355,23 @@ struct aircraft *interactiveReceiveData(struct modesMessage *mm) { a->even_cprtime = mstime(); } - if (((mm->bFlags | a->bFlags) & MODES_ACFLAGS_LLEITHER_VALID) == MODES_ACFLAGS_LLBOTH_VALID) { - // If we now have both even and odd, decode the CPR - - // Try relative CPR first - if (decodeCPRrelative(a, (mm->bFlags & MODES_ACFLAGS_LLODD_VALID), (mm->bFlags & MODES_ACFLAGS_AOG))) { - // If relative CPR fails then try global if the two data are less than 10 seconds apart - if (abs((int)(a->even_cprtime - a->odd_cprtime)) <= 10000) { - decodeCPR(a, (mm->bFlags & MODES_ACFLAGS_LLODD_VALID), (mm->bFlags & MODES_ACFLAGS_AOG)); - } + // If we have enough recent data, try global CPR + if (((mm->bFlags | a->bFlags) & MODES_ACFLAGS_LLEITHER_VALID) == MODES_ACFLAGS_LLBOTH_VALID && abs((int)(a->even_cprtime - a->odd_cprtime)) <= 10000) { + if (decodeCPR(a, (mm->bFlags & MODES_ACFLAGS_LLODD_VALID), (mm->bFlags & MODES_ACFLAGS_AOG)) == 0) { + location_ok = 1; } + } - //If we sucessfully decoded, back copy the results to mm so that we can print them in list output - if (a->bFlags & MODES_ACFLAGS_LATLON_VALID) { - mm->bFlags |= MODES_ACFLAGS_LATLON_VALID; - mm->fLat = a->lat; - mm->fLon = a->lon; - } + // Otherwise try relative CPR. + if (!location_ok && decodeCPRrelative(a, (mm->bFlags & MODES_ACFLAGS_LLODD_VALID), (mm->bFlags & MODES_ACFLAGS_AOG)) == 0) { + location_ok = 1; + } + + //If we sucessfully decoded, back copy the results to mm so that we can print them in list output + if (location_ok) { + mm->bFlags |= MODES_ACFLAGS_LATLON_VALID; + mm->fLat = a->lat; + mm->fLon = a->lon; } } diff --git a/mode_s.c b/mode_s.c index 3dc2806..bb0da2c 100644 --- a/mode_s.c +++ b/mode_s.c @@ -909,7 +909,7 @@ void decodeModesMessage(struct modesMessage *mm, unsigned char *msg) { // If we're checking CRC and the CRC is invalid, then we can't trust any // of the data contents, so save time and give up now. - if ((Modes.check_crc) && (!mm->crcok)) { return;} + if ((Modes.check_crc) && (!mm->crcok) && (!mm->correctedbits)) { return;} // Fields for DF0, DF16 if (mm->msgtype == 0 || mm->msgtype == 16) { @@ -2014,11 +2014,8 @@ double cprDlonFunction(double lat, int fflag, int surface) { // // A few remarks: // 1) 131072 is 2^17 since CPR latitude and longitude are encoded in 17 bits. -// 2) We assume that we always received the odd packet as last packet for -// simplicity. This may provide a position that is less fresh of a few -// seconds. // -void decodeCPR(struct aircraft *a, int fflag, int surface) { +int decodeCPR(struct aircraft *a, int fflag, int surface) { double AirDlat0 = (surface ? 90.0 : 360.0) / 60.0; double AirDlat1 = (surface ? 90.0 : 360.0) / 59.0; double lat0 = a->even_cprlat; @@ -2044,7 +2041,8 @@ void decodeCPR(struct aircraft *a, int fflag, int surface) { surface_rlat = Modes.fUserLat; surface_rlon = Modes.fUserLon; } else { - return; + // No local reference, give up + return (-1); } rlat0 += floor(surface_rlat / 90.0) * 90.0; // Move from 1st quadrant to our quadrant rlat1 += floor(surface_rlat / 90.0) * 90.0; @@ -2054,10 +2052,12 @@ void decodeCPR(struct aircraft *a, int fflag, int surface) { } // Check to see that the latitude is in range: -90 .. +90 - if (rlat0 < -90 || rlat0 > 90 || rlat1 < -90 || rlat1 > 90) return; + if (rlat0 < -90 || rlat0 > 90 || rlat1 < -90 || rlat1 > 90) + return (-1); // Check that both are in the same latitude zone, or abort. - if (cprNLFunction(rlat0) != cprNLFunction(rlat1)) return; + if (cprNLFunction(rlat0) != cprNLFunction(rlat1)) + return (-1); // Compute ni and the Longitude Index "m" if (fflag) { // Use odd packet. @@ -2083,6 +2083,8 @@ void decodeCPR(struct aircraft *a, int fflag, int surface) { a->seenLatLon = a->seen; a->timestampLatLon = a->timestamp; a->bFlags |= (MODES_ACFLAGS_LATLON_VALID | MODES_ACFLAGS_LATLON_REL_OK); + + return 0; } // //========================================================================= diff --git a/net_io.c b/net_io.c index a1ccfda..fbb18b8 100644 --- a/net_io.c +++ b/net_io.c @@ -88,7 +88,7 @@ void modesInitNet(void) { int s = anetTcpServer(Modes.aneterr, services[j].port, NULL); if (s == -1) { fprintf(stderr, "Error opening the listening port %d (%s): %s\n", - services[j].port, services[j].descr, strerror(errno)); + services[j].port, services[j].descr, Modes.aneterr); exit(1); } anetNonBlock(Modes.aneterr, s); @@ -304,8 +304,8 @@ void modesSendRawOutput(struct modesMessage *mm) { void modesSendSBSOutput(struct modesMessage *mm) { char msg[256], *p = msg; uint32_t offset; - struct timeb epocTime; - struct tm stTime; + struct timeb epocTime_receive, epocTime_now; + struct tm stTime_receive, stTime_now; int msgType; // @@ -347,26 +347,33 @@ void modesSendSBSOutput(struct modesMessage *mm) { // Fields 1 to 6 : SBS message type and ICAO address of the aircraft and some other stuff p += sprintf(p, "MSG,%d,111,11111,%06X,111111,", msgType, mm->addr); - // Fields 7 & 8 are the message reception time and date - if (mm->timestampMsg && !mm->remote) { // Make sure the records' timestamp is valid before outputing it - epocTime = Modes.stSystemTimeBlk; // This is the time of the start of the Block we're processing + // Find current system time + ftime(&epocTime_now); // get the current system time & date + stTime_now = *localtime(&epocTime_now.time); + + // Find message reception time + if (mm->timestampMsg && !mm->remote) { // Make sure the records' timestamp is valid before using it + epocTime_receive = Modes.stSystemTimeBlk; // This is the time of the start of the Block we're processing offset = (int) (mm->timestampMsg - Modes.timestampBlk); // This is the time (in 12Mhz ticks) into the Block offset = offset / 12000; // convert to milliseconds - epocTime.millitm += offset; // add on the offset time to the Block start time - if (epocTime.millitm > 999) // if we've caused an overflow into the next second... - {epocTime.millitm -= 1000; epocTime.time ++;} // ..correct the overflow - stTime = *localtime(&epocTime.time); // convert the time to year, month day, hours, min, sec - p += sprintf(p, "%04d/%02d/%02d,", (stTime.tm_year+1900),(stTime.tm_mon+1), stTime.tm_mday); - p += sprintf(p, "%02d:%02d:%02d.%03d,", stTime.tm_hour, stTime.tm_min, stTime.tm_sec, epocTime.millitm); + epocTime_receive.millitm += offset; // add on the offset time to the Block start time + if (epocTime_receive.millitm > 999) { // if we've caused an overflow into the next second... + epocTime_receive.millitm -= 1000; + epocTime_receive.time ++; // ..correct the overflow + } + stTime_receive = *localtime(&epocTime_receive.time); } else { - p += sprintf(p, ",,"); - } + epocTime_receive = epocTime_now; // We don't have a usable reception time; use the current system time + stTime_receive = stTime_now; + } + + // Fields 7 & 8 are the message reception time and date + p += sprintf(p, "%04d/%02d/%02d,", (stTime_receive.tm_year+1900),(stTime_receive.tm_mon+1), stTime_receive.tm_mday); + p += sprintf(p, "%02d:%02d:%02d.%03d,", stTime_receive.tm_hour, stTime_receive.tm_min, stTime_receive.tm_sec, epocTime_receive.millitm); // Fields 9 & 10 are the current time and date - ftime(&epocTime); // get the current system time & date - stTime = *localtime(&epocTime.time); // convert the time to year, month day, hours, min, sec - p += sprintf(p, "%04d/%02d/%02d,", (stTime.tm_year+1900),(stTime.tm_mon+1), stTime.tm_mday); - p += sprintf(p, "%02d:%02d:%02d.%03d", stTime.tm_hour, stTime.tm_min, stTime.tm_sec, epocTime.millitm); + p += sprintf(p, "%04d/%02d/%02d,", (stTime_now.tm_year+1900),(stTime_now.tm_mon+1), stTime_now.tm_mday); + p += sprintf(p, "%02d:%02d:%02d.%03d", stTime_now.tm_hour, stTime_now.tm_min, stTime_now.tm_sec, epocTime_now.millitm); // Field 11 is the callsign (if we have it) if (mm->bFlags & MODES_ACFLAGS_CALLSIGN_VALID) {p += sprintf(p, ",%s", mm->flight);} @@ -867,11 +874,12 @@ void modesReadFromClient(struct client *c, char *sep, bContinue = 0; } #ifndef _WIN32 - if ( (nread < 0) && (errno != EAGAIN)) { // Error, or end of file + if ( (nread < 0 && errno != EAGAIN && errno != EWOULDBLOCK) || nread == 0 ) { // Error, or end of file #else if ( (nread < 0) && (errno != EWOULDBLOCK)) { // Error, or end of file #endif modesCloseClient(c); + return; } if (nread <= 0) { break; // Serve next client