Stats rearrangement, based on experimental branch changes.
This commit is contained in:
parent
e02a2cdd44
commit
b9b76da02d
4
Makefile
4
Makefile
|
@ -21,10 +21,10 @@ all: dump1090 view1090
|
|||
%.o: %.c dump1090.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(EXTRACFLAGS) -c $<
|
||||
|
||||
dump1090: dump1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o crc.o demod_2000.o demod_2400.o
|
||||
dump1090: dump1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o crc.o demod_2000.o demod_2400.o stats.o
|
||||
$(CC) -g -o dump1090 $^ $(LIBS) $(LIBS_RTL) $(LDFLAGS)
|
||||
|
||||
view1090: view1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o crc.o
|
||||
view1090: view1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o crc.o stats.o
|
||||
$(CC) -g -o view1090 $^ $(LIBS) $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
|
|
12
demod_2000.c
12
demod_2000.c
|
@ -347,7 +347,7 @@ void demodulate2000(uint16_t *m, uint32_t mlen) {
|
|||
useModesMessage(&mm);
|
||||
|
||||
j += MODEAC_MSG_SAMPLES;
|
||||
Modes.stat_ModeAC++;
|
||||
Modes.stats_current.ModeAC++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -399,7 +399,7 @@ void demodulate2000(uint16_t *m, uint32_t mlen) {
|
|||
dumpRawMessage("Too high level in samples between 10 and 15", msg, m, j);
|
||||
continue;
|
||||
}
|
||||
Modes.stat_valid_preamble++;
|
||||
Modes.stats_current.valid_preamble++;
|
||||
}
|
||||
|
||||
else {
|
||||
|
@ -408,7 +408,7 @@ void demodulate2000(uint16_t *m, uint32_t mlen) {
|
|||
// Make a copy of the Payload, and phase correct the copy
|
||||
memcpy(aux, &pPreamble[-1], sizeof(aux));
|
||||
applyPhaseCorrection(&aux[1]);
|
||||
Modes.stat_out_of_phase++;
|
||||
Modes.stats_current.out_of_phase++;
|
||||
pPayload = &aux[1 + MODES_PREAMBLE_SAMPLES];
|
||||
// TODO ... apply other kind of corrections
|
||||
}
|
||||
|
@ -476,7 +476,7 @@ void demodulate2000(uint16_t *m, uint32_t mlen) {
|
|||
msglen = MODES_SHORT_MSG_BITS;
|
||||
msg[0] ^= theErrs; errorsTy = 0;
|
||||
errors = errors56; // revert to the number of errors prior to bit 56
|
||||
Modes.stat_DF_Len_Corrected++;
|
||||
Modes.stats_current.DF_Len_Corrected++;
|
||||
|
||||
} else if (i < MODES_LONG_MSG_BITS) {
|
||||
msglen = MODES_SHORT_MSG_BITS;
|
||||
|
@ -518,7 +518,7 @@ void demodulate2000(uint16_t *m, uint32_t mlen) {
|
|||
if (validDFbits & thisDFbit) {
|
||||
// Yep, more likely, so update the main message
|
||||
msg[0] = theByte;
|
||||
Modes.stat_DF_Type_Corrected++;
|
||||
Modes.stats_current.DF_Type_Corrected++;
|
||||
errors--; // decrease the error count so we attempt to use the modified DF.
|
||||
}
|
||||
}
|
||||
|
@ -549,7 +549,7 @@ void demodulate2000(uint16_t *m, uint32_t mlen) {
|
|||
|
||||
// Update statistics
|
||||
if (Modes.stats) {
|
||||
struct demod_stats *dstats = (use_correction ? &Modes.stat_demod_phasecorrected : &Modes.stat_demod);
|
||||
struct demod_stats *dstats = (use_correction ? &Modes.stats_current.demod_phasecorrected : &Modes.stats_current.demod);
|
||||
|
||||
switch (errors) {
|
||||
case 0: dstats->demodulated0++; break;
|
||||
|
|
16
demod_2400.c
16
demod_2400.c
|
@ -252,19 +252,19 @@ void demodulate2400(uint16_t *m, uint32_t mlen)
|
|||
preamble[16] >= high ||
|
||||
preamble[17] >= high ||
|
||||
preamble[18] >= high) {
|
||||
++Modes.stat_preamble_not_quiet;
|
||||
++Modes.stats_current.preamble_not_quiet;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Crosscorrelate against the first few bits to find a likely phase offset
|
||||
initial_phase = best_phase(&preamble[19]);
|
||||
if (initial_phase < 0) {
|
||||
++Modes.stat_preamble_no_correlation;
|
||||
++Modes.stats_current.preamble_no_correlation;
|
||||
continue; // nothing satisfactory
|
||||
}
|
||||
|
||||
Modes.stat_valid_preamble++;
|
||||
Modes.stat_preamble_phase[initial_phase%MODES_MAX_PHASE_STATS]++;
|
||||
Modes.stats_current.valid_preamble++;
|
||||
Modes.stats_current.preamble_phase[initial_phase%MODES_MAX_PHASE_STATS]++;
|
||||
|
||||
try_phase = initial_phase;
|
||||
|
||||
|
@ -395,7 +395,7 @@ void demodulate2400(uint16_t *m, uint32_t mlen)
|
|||
msglen = MODES_SHORT_MSG_BITS;
|
||||
msg[0] ^= theErrs; errorsTy = 0;
|
||||
errors = errors56; // revert to the number of errors prior to bit 56
|
||||
Modes.stat_DF_Len_Corrected++;
|
||||
Modes.stats_current.DF_Len_Corrected++;
|
||||
} else if (i < MODES_LONG_MSG_BITS) {
|
||||
msglen = MODES_SHORT_MSG_BITS;
|
||||
errors = errors56;
|
||||
|
@ -435,7 +435,7 @@ void demodulate2400(uint16_t *m, uint32_t mlen)
|
|||
if (validDFbits & thisDFbit) {
|
||||
// Yep, more likely, so update the main message
|
||||
msg[0] = theByte;
|
||||
Modes.stat_DF_Type_Corrected++;
|
||||
Modes.stats_current.DF_Type_Corrected++;
|
||||
errors--; // decrease the error count so we attempt to use the modified DF.
|
||||
}
|
||||
}
|
||||
|
@ -466,7 +466,7 @@ void demodulate2400(uint16_t *m, uint32_t mlen)
|
|||
|
||||
// Update statistics
|
||||
if (Modes.stats) {
|
||||
struct demod_stats *dstats = (mm.phase_corrected ? &Modes.stat_demod_phasecorrected : &Modes.stat_demod);
|
||||
struct demod_stats *dstats = (mm.phase_corrected ? &Modes.stats_current.demod_phasecorrected : &Modes.stats_current.demod);
|
||||
|
||||
switch (errors) {
|
||||
case 0: dstats->demodulated0++; break;
|
||||
|
@ -508,7 +508,7 @@ void demodulate2400(uint16_t *m, uint32_t mlen)
|
|||
// peak detection
|
||||
if (Modes.phase_enhance && !mm.crcok && !mm.correctedbits) {
|
||||
if (try_phase == initial_phase)
|
||||
++Modes.stat_out_of_phase;
|
||||
++Modes.stats_current.out_of_phase;
|
||||
try_phase++;
|
||||
if (try_phase == 9)
|
||||
try_phase = 4;
|
||||
|
|
200
dump1090.c
200
dump1090.c
|
@ -586,111 +586,13 @@ void showCopyright(void) {
|
|||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void display_demod_stats(const char *prefix, struct demod_stats *dstats) {
|
||||
int j;
|
||||
|
||||
printf("%d %sdemodulated with 0 errors\n", dstats->demodulated0, prefix);
|
||||
printf("%d %sdemodulated with 1 error\n", dstats->demodulated1, prefix);
|
||||
printf("%d %sdemodulated with 2 errors\n", dstats->demodulated2, prefix);
|
||||
printf("%d %sdemodulated with > 2 errors\n", dstats->demodulated3, prefix);
|
||||
printf("%d %swith good crc\n", dstats->goodcrc, prefix);
|
||||
for (j = 0; j < MODES_MAX_PHASE_STATS; ++j)
|
||||
if (dstats->goodcrc_byphase[j] > 0)
|
||||
printf(" %d %swith phase offset %d\n", dstats->goodcrc_byphase[j], prefix, j);
|
||||
printf("%d %swith bad crc\n", dstats->badcrc, prefix);
|
||||
printf("%d %serrors corrected\n", dstats->fixed, prefix);
|
||||
|
||||
for (j = 0; j < MODES_MAX_BITERRORS; j++) {
|
||||
printf(" %d %swith %d bit %s\n", dstats->bit_fix[j], prefix, j+1, (j==0)?"error":"errors");
|
||||
}
|
||||
static void display_total_stats(void)
|
||||
{
|
||||
struct stats added;
|
||||
add_stats(&Modes.stats_alltime, &Modes.stats_current, &added);
|
||||
display_stats(&added);
|
||||
}
|
||||
|
||||
static void reset_demod_stats(struct demod_stats *dstats) {
|
||||
int j;
|
||||
|
||||
dstats->demodulated0 =
|
||||
dstats->demodulated1 =
|
||||
dstats->demodulated2 =
|
||||
dstats->goodcrc =
|
||||
dstats->badcrc =
|
||||
dstats->fixed = 0;
|
||||
|
||||
for (j = 0; j < MODES_MAX_BITERRORS; j++) {
|
||||
dstats->bit_fix[j] = 0;
|
||||
}
|
||||
|
||||
for (j = 0; j < MODES_MAX_PHASE_STATS; j++) {
|
||||
dstats->goodcrc_byphase[j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (Modes.stat_blocks_processed > 0) {
|
||||
long cpu_millis = (long)Modes.stat_cputime.tv_sec*1000L + Modes.stat_cputime.tv_nsec/1000000L;
|
||||
long sample_millis = (long) ((uint64_t)Modes.stat_blocks_processed * MODES_ASYNC_BUF_SAMPLES / (Modes.oversample ? 2400 : 2000));
|
||||
printf("%ld ms CPU time used to process %ld ms samples, %.1f%% load\n",
|
||||
cpu_millis, sample_millis, 100.0 * cpu_millis / sample_millis);
|
||||
}
|
||||
|
||||
printf("%d ModeA/C detected\n", Modes.stat_ModeAC);
|
||||
printf("%d Mode-S preambles with poor correlation\n", Modes.stat_preamble_no_correlation);
|
||||
printf("%d Mode-S preambles with noise in the quiet period\n", Modes.stat_preamble_not_quiet);
|
||||
printf("%d valid Mode-S preambles\n", Modes.stat_valid_preamble);
|
||||
for (j = 0; j < MODES_MAX_PHASE_STATS; ++j)
|
||||
if (Modes.stat_preamble_phase[j] > 0)
|
||||
printf(" %d with phase offset %d\n", Modes.stat_preamble_phase[j], j);
|
||||
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);
|
||||
|
||||
display_demod_stats("", &Modes.stat_demod);
|
||||
if (Modes.phase_enhance) {
|
||||
printf("%d phase enhancement attempts\n", Modes.stat_out_of_phase);
|
||||
display_demod_stats("phase enhanced ", &Modes.stat_demod_phasecorrected);
|
||||
}
|
||||
|
||||
printf("%d total usable messages\n",
|
||||
Modes.stat_messages_total);
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
Modes.stat_cputime.tv_sec = 0;
|
||||
Modes.stat_cputime.tv_nsec = 0;
|
||||
|
||||
Modes.stat_blocks_processed =
|
||||
Modes.stat_blocks_dropped = 0;
|
||||
|
||||
Modes.stat_ModeAC =
|
||||
Modes.stat_preamble_no_correlation =
|
||||
Modes.stat_preamble_not_quiet =
|
||||
Modes.stat_valid_preamble =
|
||||
Modes.stat_DF_Len_Corrected =
|
||||
Modes.stat_DF_Type_Corrected =
|
||||
Modes.stat_out_of_phase = 0;
|
||||
|
||||
Modes.stat_messages_total = 0;
|
||||
|
||||
for (j = 0; j < MODES_MAX_PHASE_STATS; j++) {
|
||||
Modes.stat_preamble_phase[j] = 0;
|
||||
}
|
||||
|
||||
reset_demod_stats(&Modes.stat_demod);
|
||||
reset_demod_stats(&Modes.stat_demod_phasecorrected);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
//=========================================================================
|
||||
//
|
||||
|
@ -699,7 +601,8 @@ static void display_stats(void) {
|
|||
// from the net, refreshing the screen in interactive mode, and so forth
|
||||
//
|
||||
void backgroundTasks(void) {
|
||||
static time_t next_stats;
|
||||
static time_t next_stats_display;
|
||||
static time_t next_stats_update;
|
||||
static time_t next_json, next_history;
|
||||
|
||||
time_t now = time(NULL);
|
||||
|
@ -718,29 +621,68 @@ void backgroundTasks(void) {
|
|||
interactiveShowData();
|
||||
}
|
||||
|
||||
if (Modes.stats > 0) {
|
||||
if (now > next_stats) {
|
||||
if (next_stats != 0)
|
||||
display_stats();
|
||||
next_stats = now + Modes.stats;
|
||||
// always update end time so it is current when requests arrive
|
||||
Modes.stats_current.end = now;
|
||||
|
||||
if (now >= next_stats_update) {
|
||||
int i;
|
||||
|
||||
if (next_stats_update == 0) {
|
||||
next_stats_update = now + 60;
|
||||
} else {
|
||||
Modes.stats_latest_1min = (Modes.stats_latest_1min + 1) % 15;
|
||||
Modes.stats_1min[Modes.stats_latest_1min] = Modes.stats_current;
|
||||
|
||||
add_stats(&Modes.stats_current, &Modes.stats_alltime, &Modes.stats_alltime);
|
||||
add_stats(&Modes.stats_current, &Modes.stats_periodic, &Modes.stats_periodic);
|
||||
|
||||
reset_stats(&Modes.stats_5min);
|
||||
for (i = 0; i < 5; ++i)
|
||||
add_stats(&Modes.stats_1min[(Modes.stats_latest_1min - i + 15) % 15], &Modes.stats_5min, &Modes.stats_5min);
|
||||
|
||||
reset_stats(&Modes.stats_15min);
|
||||
for (i = 0; i < 15; ++i)
|
||||
add_stats(&Modes.stats_1min[i], &Modes.stats_15min, &Modes.stats_15min);
|
||||
|
||||
reset_stats(&Modes.stats_current);
|
||||
Modes.stats_current.start = Modes.stats_current.end = now;
|
||||
|
||||
if (Modes.json_dir)
|
||||
writeJsonToFile("stats.json", generateStatsJson);
|
||||
|
||||
next_stats_update += 60;
|
||||
}
|
||||
}
|
||||
|
||||
if ((Modes.json_dir || Modes.net_http_port) && now >= next_json) {
|
||||
if (Modes.stats > 0 && now >= next_stats_display) {
|
||||
if (next_stats_display == 0) {
|
||||
next_stats_display = now + Modes.stats;
|
||||
} else {
|
||||
add_stats(&Modes.stats_periodic, &Modes.stats_current, &Modes.stats_periodic);
|
||||
display_stats(&Modes.stats_periodic);
|
||||
reset_stats(&Modes.stats_periodic);
|
||||
|
||||
next_stats_display += Modes.stats;
|
||||
}
|
||||
}
|
||||
|
||||
if (Modes.json_dir && now >= next_json) {
|
||||
writeJsonToFile("aircraft.json", generateAircraftJson);
|
||||
next_json = now + Modes.json_interval;
|
||||
}
|
||||
|
||||
if ((Modes.json_dir || Modes.net_http_port) && now >= next_history) {
|
||||
char filebuf[PATH_MAX];
|
||||
int rewrite_receiver_json = (Modes.json_aircraft_history[HISTORY_SIZE-1].content == NULL);
|
||||
|
||||
free(Modes.json_aircraft_history[Modes.json_aircraft_history_next].content); // might be NULL, that's OK.
|
||||
Modes.json_aircraft_history[Modes.json_aircraft_history_next].content =
|
||||
generateAircraftJson("/data/aircraft.json", &Modes.json_aircraft_history[Modes.json_aircraft_history_next].clen);
|
||||
|
||||
snprintf(filebuf, PATH_MAX, "history_%d.json", Modes.json_aircraft_history_next);
|
||||
writeJsonToFile(filebuf, generateHistoryJson);
|
||||
if (Modes.json_dir) {
|
||||
char filebuf[PATH_MAX];
|
||||
snprintf(filebuf, PATH_MAX, "history_%d.json", Modes.json_aircraft_history_next);
|
||||
writeJsonToFile(filebuf, generateHistoryJson);
|
||||
}
|
||||
|
||||
Modes.json_aircraft_history_next = (Modes.json_aircraft_history_next+1) % HISTORY_SIZE;
|
||||
|
||||
|
@ -1002,13 +944,19 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
if (Modes.net) modesInitNet();
|
||||
|
||||
writeJsonToFile("receiver.json", generateReceiverJson); // once on startup
|
||||
// init stats:
|
||||
Modes.stats_current.start = Modes.stats_current.end = time(NULL);
|
||||
|
||||
// write initial json files so they're not missing
|
||||
writeJsonToFile("receiver.json", generateReceiverJson);
|
||||
writeJsonToFile("stats.json", generateStatsJson);
|
||||
writeJsonToFile("aircraft.json", generateAircraftJson);
|
||||
|
||||
// If the user specifies --net-only, just run in order to serve network
|
||||
// clients without reading data from the RTL device
|
||||
while (Modes.net_only) {
|
||||
if (Modes.exit) {
|
||||
display_stats();
|
||||
display_total_stats();
|
||||
exit(0); // If we exit net_only nothing further in main()
|
||||
}
|
||||
backgroundTasks();
|
||||
|
@ -1044,7 +992,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.stats_current.blocks_dropped += Modes.iDataLost;
|
||||
Modes.iDataLost = 0;
|
||||
}
|
||||
|
||||
|
@ -1064,14 +1012,14 @@ int main(int argc, char **argv) {
|
|||
demodulate2000(Modes.magnitude, MODES_ASYNC_BUF_SAMPLES);
|
||||
|
||||
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &cpu_end_time);
|
||||
Modes.stat_cputime.tv_sec += (cpu_end_time.tv_sec - cpu_start_time.tv_sec);
|
||||
Modes.stat_cputime.tv_nsec += (cpu_end_time.tv_nsec - cpu_start_time.tv_nsec);
|
||||
if (Modes.stat_cputime.tv_nsec < 0) {
|
||||
Modes.stat_cputime.tv_nsec += 1000000000L;
|
||||
Modes.stat_cputime.tv_sec--;
|
||||
} else if (Modes.stat_cputime.tv_nsec > 1000000000L) {
|
||||
Modes.stat_cputime.tv_nsec -= 1000000000L;
|
||||
Modes.stat_cputime.tv_sec++;
|
||||
Modes.stats_current.cputime.tv_sec += (cpu_end_time.tv_sec - cpu_start_time.tv_sec);
|
||||
Modes.stats_current.cputime.tv_nsec += (cpu_end_time.tv_nsec - cpu_start_time.tv_nsec);
|
||||
if (Modes.stats_current.cputime.tv_nsec < 0) {
|
||||
Modes.stats_current.cputime.tv_nsec += 1000000000L;
|
||||
Modes.stats_current.cputime.tv_sec--;
|
||||
} else if (Modes.stats_current.cputime.tv_nsec > 1000000000L) {
|
||||
Modes.stats_current.cputime.tv_nsec -= 1000000000L;
|
||||
Modes.stats_current.cputime.tv_sec++;
|
||||
}
|
||||
|
||||
// Update the timestamp ready for the next block
|
||||
|
@ -1079,7 +1027,7 @@ int main(int argc, char **argv) {
|
|||
Modes.timestampBlk += (MODES_ASYNC_BUF_SAMPLES*5);
|
||||
else
|
||||
Modes.timestampBlk += (MODES_ASYNC_BUF_SAMPLES*6);
|
||||
Modes.stat_blocks_processed++;
|
||||
Modes.stats_current.blocks_processed++;
|
||||
} else {
|
||||
pthread_cond_signal (&Modes.data_cond);
|
||||
pthread_mutex_unlock(&Modes.data_mutex);
|
||||
|
@ -1093,7 +1041,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
// If --stats were given, print statistics
|
||||
if (Modes.stats) {
|
||||
display_stats();
|
||||
display_total_stats();
|
||||
}
|
||||
|
||||
if (Modes.filename == NULL) {
|
||||
|
|
65
dump1090.h
65
dump1090.h
|
@ -89,11 +89,7 @@
|
|||
#include "winstubs.h" //Put everything Windows specific in here
|
||||
#endif
|
||||
|
||||
#include "rtl-sdr.h"
|
||||
#include "anet.h"
|
||||
#include "crc.h"
|
||||
#include "demod_2000.h"
|
||||
#include "demod_2400.h"
|
||||
#include <rtl-sdr.h>
|
||||
|
||||
// ============================= #defines ===============================
|
||||
//
|
||||
|
@ -223,8 +219,18 @@
|
|||
#define HTMLPATH "./public_html" // default path for gmap.html etc
|
||||
#endif
|
||||
|
||||
#define HISTORY_SIZE 120
|
||||
#define HISTORY_INTERVAL 30
|
||||
|
||||
#define MODES_NOTUSED(V) ((void) V)
|
||||
|
||||
#include "anet.h"
|
||||
#include "crc.h"
|
||||
#include "demod_2000.h"
|
||||
#include "demod_2400.h"
|
||||
#include "stats.h"
|
||||
|
||||
|
||||
//======================== structure declarations =========================
|
||||
|
||||
// Structure used to describe a networking client
|
||||
|
@ -236,9 +242,6 @@ struct client {
|
|||
char buf[MODES_CLIENT_BUF_SIZE+1]; // Read buffer
|
||||
};
|
||||
|
||||
#define HISTORY_SIZE 120
|
||||
#define HISTORY_INTERVAL 30
|
||||
|
||||
// Structure used to describe an aircraft in iteractive mode
|
||||
struct aircraft {
|
||||
uint32_t addr; // ICAO address
|
||||
|
@ -275,22 +278,6 @@ struct aircraft {
|
|||
struct aircraft *next; // Next aircraft in our linked list
|
||||
};
|
||||
|
||||
// Common stats for non-phase-corrected vs phase-corrected cases
|
||||
struct demod_stats {
|
||||
unsigned int demodulated0;
|
||||
unsigned int demodulated1;
|
||||
unsigned int demodulated2;
|
||||
unsigned int demodulated3;
|
||||
unsigned int goodcrc;
|
||||
unsigned int goodcrc_byphase[MODES_MAX_PHASE_STATS];
|
||||
unsigned int badcrc;
|
||||
unsigned int fixed;
|
||||
|
||||
// Histogram of fixed bit errors: index 0 for single bit erros,
|
||||
// index 1 for double bit errors etc.
|
||||
unsigned int bit_fix[MODES_MAX_BITERRORS];
|
||||
};
|
||||
|
||||
// Common writer state for all output sockets of one type
|
||||
struct net_writer {
|
||||
int socket; // listening socket FD, used to identify the owning service
|
||||
|
@ -405,28 +392,13 @@ struct { // Internal state
|
|||
time_t last_cleanup_time; // Last cleanup time in seconds
|
||||
|
||||
// Statistics
|
||||
unsigned int stat_preamble_no_correlation;
|
||||
unsigned int stat_preamble_not_quiet;
|
||||
unsigned int stat_valid_preamble;
|
||||
unsigned int stat_preamble_phase[MODES_MAX_PHASE_STATS];
|
||||
|
||||
struct demod_stats stat_demod;
|
||||
struct demod_stats stat_demod_phasecorrected;
|
||||
|
||||
unsigned int stat_http_requests;
|
||||
unsigned int stat_out_of_phase;
|
||||
|
||||
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;
|
||||
|
||||
struct timespec stat_cputime;
|
||||
|
||||
// total messages:
|
||||
unsigned int stat_messages_total;
|
||||
struct stats stats_current;
|
||||
struct stats stats_alltime;
|
||||
struct stats stats_periodic;
|
||||
struct stats stats_1min[15];
|
||||
int stats_latest_1min;
|
||||
struct stats stats_5min;
|
||||
struct stats stats_15min;
|
||||
} Modes;
|
||||
|
||||
// The struct we use to store information about a decoded message.
|
||||
|
@ -518,6 +490,7 @@ void modesNetPeriodicWork (void);
|
|||
void writeJsonToFile(const char *file, char * (*generator) (const char*,int*));
|
||||
char *generateAircraftJson(const char *url_path, int *len);
|
||||
char *generateReceiverJson(const char *url_path, int *len);
|
||||
char *generateStatsJson(const char *url_path, int *len);
|
||||
char *generateHistoryJson(const char *url_path, int *len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
2
mode_s.c
2
mode_s.c
|
@ -935,7 +935,7 @@ void computeMagnitudeVector(uint16_t *p) {
|
|||
//
|
||||
void useModesMessage(struct modesMessage *mm) {
|
||||
if ((Modes.check_crc == 0) || (mm->crcok) || (mm->correctedbits)) { // not checking, ok or fixed
|
||||
++Modes.stat_messages_total;
|
||||
++Modes.stats_current.messages_total;
|
||||
|
||||
// If we are decoding, track aircraft
|
||||
interactiveReceiveData(mm);
|
||||
|
|
58
net_io.c
58
net_io.c
|
@ -48,6 +48,9 @@
|
|||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "dump1090.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
//
|
||||
// ============================= Networking =============================
|
||||
//
|
||||
|
@ -699,7 +702,7 @@ char *generateAircraftJson(const char *url_path, int *len) {
|
|||
"{ \"now\" : %d,\n"
|
||||
" \"messages\" : %u,\n"
|
||||
" \"aircraft\" : [",
|
||||
(int)now, Modes.stat_messages_total);
|
||||
(int)now, Modes.stats_current.messages_total);
|
||||
|
||||
while(a) {
|
||||
if (a->modeACflags & MODEAC_MSG_FLAG) { // skip any fudged ICAO records Mode A/C
|
||||
|
@ -750,6 +753,57 @@ char *generateAircraftJson(const char *url_path, int *len) {
|
|||
return buf;
|
||||
}
|
||||
|
||||
static char * appendStatsJson(char *p,
|
||||
char *end,
|
||||
struct stats *st,
|
||||
const char *key)
|
||||
{
|
||||
p += snprintf(p, end-p,
|
||||
" \"%s\" : {\n"
|
||||
" \"start\" : %d,\n"
|
||||
" \"end\" : %d,\n"
|
||||
" \"messages\" : %u,\n",
|
||||
key,
|
||||
(int)st->start,
|
||||
(int)st->end,
|
||||
st->messages_total);
|
||||
|
||||
p += snprintf(p, end-p, "\n }");
|
||||
return p;
|
||||
}
|
||||
|
||||
char *generateStatsJson(const char *url_path, int *len) {
|
||||
struct stats add;
|
||||
char *buf = (char *) malloc(2048), *p = buf, *end = buf + 2048;
|
||||
|
||||
MODES_NOTUSED(url_path);
|
||||
|
||||
p += snprintf(p, end-p, "{\n");
|
||||
p = appendStatsJson(p, end, &Modes.stats_current, "latest");
|
||||
p += snprintf(p, end-p, ",\n");
|
||||
|
||||
add_stats(&Modes.stats_1min[Modes.stats_latest_1min], &Modes.stats_current, &add);
|
||||
p = appendStatsJson(p, end, &add, "last1min");
|
||||
p += snprintf(p, end-p, ",\n");
|
||||
|
||||
add_stats(&Modes.stats_5min, &Modes.stats_current, &add);
|
||||
p = appendStatsJson(p, end, &add, "last5min");
|
||||
p += snprintf(p, end-p, ",\n");
|
||||
|
||||
add_stats(&Modes.stats_15min, &Modes.stats_current, &add);
|
||||
p = appendStatsJson(p, end, &add, "last15min");
|
||||
p += snprintf(p, end-p, ",\n");
|
||||
|
||||
add_stats(&Modes.stats_alltime, &Modes.stats_current, &add);
|
||||
p = appendStatsJson(p, end, &add, "total");
|
||||
p += snprintf(p, end-p, "\n}\n");
|
||||
|
||||
assert(p <= end);
|
||||
|
||||
*len = p-buf;
|
||||
return buf;
|
||||
}
|
||||
|
||||
//
|
||||
// Return a description of the receiver in json.
|
||||
//
|
||||
|
@ -1046,7 +1100,7 @@ int handleHTTPRequest(struct client *c, char *p) {
|
|||
return 1;
|
||||
}
|
||||
free(content);
|
||||
Modes.stat_http_requests++;
|
||||
Modes.stats_current.http_requests++;
|
||||
return !keepalive;
|
||||
}
|
||||
//
|
||||
|
|
196
stats.c
Normal file
196
stats.c
Normal file
|
@ -0,0 +1,196 @@
|
|||
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
|
||||
//
|
||||
// stats.c: statistics helpers.
|
||||
//
|
||||
// Copyright (c) 2015 Oliver Jowett <oliver@mutability.co.uk>
|
||||
//
|
||||
// This file is free software: you may copy, redistribute and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation, either version 2 of the License, or (at your
|
||||
// option) any later version.
|
||||
//
|
||||
// This file is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// This file incorporates work covered by the following copyright and
|
||||
// permission notice:
|
||||
//
|
||||
// Copyright (C) 2012 by Salvatore Sanfilippo <antirez@gmail.com>
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "dump1090.h"
|
||||
|
||||
static void display_demod_stats(const char *prefix, struct demod_stats *dstats) {
|
||||
int j;
|
||||
|
||||
printf("%d %sdemodulated with 0 errors\n", dstats->demodulated0, prefix);
|
||||
printf("%d %sdemodulated with 1 error\n", dstats->demodulated1, prefix);
|
||||
printf("%d %sdemodulated with 2 errors\n", dstats->demodulated2, prefix);
|
||||
printf("%d %sdemodulated with > 2 errors\n", dstats->demodulated3, prefix);
|
||||
printf("%d %swith good crc\n", dstats->goodcrc, prefix);
|
||||
for (j = 0; j < MODES_MAX_PHASE_STATS; ++j)
|
||||
if (dstats->goodcrc_byphase[j] > 0)
|
||||
printf(" %d %swith phase offset %d\n", dstats->goodcrc_byphase[j], prefix, j);
|
||||
printf("%d %swith bad crc\n", dstats->badcrc, prefix);
|
||||
printf("%d %serrors corrected\n", dstats->fixed, prefix);
|
||||
|
||||
for (j = 0; j < Modes.nfix_crc; j++) {
|
||||
printf(" %d %swith %d bit %s\n", dstats->bit_fix[j], prefix, j+1, (j==0)?"error":"errors");
|
||||
}
|
||||
}
|
||||
|
||||
void display_stats(struct stats *st) {
|
||||
int j;
|
||||
struct tm tm_start, tm_end;
|
||||
char tb_start[30], tb_end[30];
|
||||
|
||||
printf("\n\n");
|
||||
if (Modes.interactive)
|
||||
interactiveShowData();
|
||||
|
||||
localtime_r(&st->start, &tm_start);
|
||||
strftime(tb_start, sizeof(tb_start), "%c", &tm_start);
|
||||
localtime_r(&st->end, &tm_end);
|
||||
strftime(tb_end, sizeof(tb_end), "%c", &tm_end);
|
||||
|
||||
printf("Statistics: %s - %s\n", tb_start, tb_end);
|
||||
|
||||
if (!Modes.net_only) {
|
||||
printf("%d sample blocks processed\n", st->blocks_processed);
|
||||
printf("%d sample blocks dropped\n", st->blocks_dropped);
|
||||
|
||||
if (st->blocks_processed > 0) {
|
||||
long cpu_millis = (long)st->cputime.tv_sec*1000L + st->cputime.tv_nsec/1000000L;
|
||||
long sample_millis = (long) ((uint64_t)st->blocks_processed * MODES_ASYNC_BUF_SAMPLES / (Modes.oversample ? 2400 : 2000));
|
||||
printf("%ld ms CPU time used to process %ld ms samples, %.1f%% load\n",
|
||||
cpu_millis, sample_millis, 100.0 * cpu_millis / sample_millis);
|
||||
}
|
||||
|
||||
printf("%d ModeA/C detected\n", st->ModeAC);
|
||||
printf("%d Mode-S preambles with poor correlation\n", st->preamble_no_correlation);
|
||||
printf("%d Mode-S preambles with noise in the quiet period\n", st->preamble_not_quiet);
|
||||
printf("%d valid Mode-S preambles\n", st->valid_preamble);
|
||||
for (j = 0; j < MODES_MAX_PHASE_STATS; ++j)
|
||||
if (st->preamble_phase[j] > 0)
|
||||
printf(" %d with phase offset %d\n", st->preamble_phase[j], j);
|
||||
printf("%d DF-?? fields corrected for length\n", st->DF_Len_Corrected);
|
||||
printf("%d DF-?? fields corrected for type\n", st->DF_Type_Corrected);
|
||||
|
||||
display_demod_stats("", &st->demod);
|
||||
if (Modes.phase_enhance) {
|
||||
printf("%d phase enhancement attempts\n", st->out_of_phase);
|
||||
display_demod_stats("phase enhanced ", &st->demod_phasecorrected);
|
||||
}
|
||||
}
|
||||
|
||||
printf("%d remote messages accepted\n"
|
||||
"%d remote messages rejected\n",
|
||||
st->remote_accepted,
|
||||
st->remote_rejected);
|
||||
|
||||
printf("%d total usable messages\n",
|
||||
st->messages_total);
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void reset_stats(struct stats *st) {
|
||||
static struct stats st_zero;
|
||||
*st = st_zero;
|
||||
}
|
||||
|
||||
static void add_demod_stats(const struct demod_stats *st1, const struct demod_stats *st2, struct demod_stats *target)
|
||||
{
|
||||
int i;
|
||||
|
||||
target->demodulated0 = st1->demodulated0 + st2->demodulated0;
|
||||
target->demodulated1 = st1->demodulated1 + st2->demodulated1;
|
||||
target->demodulated2 = st1->demodulated2 + st2->demodulated2;
|
||||
target->demodulated3 = st1->demodulated3 + st2->demodulated3;
|
||||
target->goodcrc = st1->goodcrc + st2->goodcrc;
|
||||
|
||||
for (i = 0; i < MODES_MAX_PHASE_STATS; ++i)
|
||||
target->goodcrc_byphase[i] = st1->goodcrc_byphase[i] + st2->goodcrc_byphase[i];
|
||||
|
||||
target->badcrc = st1->badcrc + st2->badcrc;
|
||||
target->fixed = st1->fixed + st2->fixed;
|
||||
|
||||
for (i = 0; i < MODES_MAX_BITERRORS; ++i)
|
||||
target->bit_fix[i] = st1->bit_fix[i] + st2->bit_fix[i];
|
||||
}
|
||||
|
||||
void add_stats(const struct stats *st1, const struct stats *st2, struct stats *target) {
|
||||
int i;
|
||||
|
||||
if (st1->start == 0)
|
||||
target->start = st2->start;
|
||||
else if (st2->start == 0)
|
||||
target->start = st1->start;
|
||||
else if (st1->start < st2->start)
|
||||
target->start = st1->start;
|
||||
else
|
||||
target->start = st2->start;
|
||||
|
||||
target->end = st1->end > st2->end ? st1->end : st2->end;
|
||||
|
||||
target->preamble_no_correlation = st1->preamble_no_correlation + st2->preamble_no_correlation;
|
||||
target->preamble_not_quiet = st1->preamble_not_quiet + st2->preamble_not_quiet;
|
||||
target->valid_preamble = st1->valid_preamble + st2->valid_preamble;
|
||||
for (i = 0; i < MODES_MAX_PHASE_STATS; ++i)
|
||||
target->preamble_phase[i] = st1->preamble_phase[i] + st2->preamble_phase[i];
|
||||
|
||||
add_demod_stats(&st1->demod, &st2->demod, &target->demod);
|
||||
add_demod_stats(&st1->demod_phasecorrected, &st2->demod_phasecorrected, &target->demod_phasecorrected);
|
||||
|
||||
target->http_requests = st1->http_requests + st2->http_requests;
|
||||
target->out_of_phase = st1->out_of_phase + st2->out_of_phase;
|
||||
|
||||
target->DF_Len_Corrected = st1->DF_Len_Corrected + st2->DF_Len_Corrected;
|
||||
target->DF_Type_Corrected = st1->DF_Type_Corrected + st2->DF_Type_Corrected;
|
||||
target->ModeAC = st1->ModeAC + st2->ModeAC;
|
||||
|
||||
target->blocks_processed = st1->blocks_processed + st2->blocks_processed;
|
||||
target->blocks_dropped = st1->blocks_dropped + st2->blocks_dropped;
|
||||
|
||||
target->cputime.tv_sec = st1->cputime.tv_sec + st2->cputime.tv_sec;
|
||||
target->cputime.tv_nsec = st1->cputime.tv_nsec + st2->cputime.tv_nsec;
|
||||
target->cputime.tv_sec += target->cputime.tv_nsec / 1000000000L;
|
||||
target->cputime.tv_nsec %= 1000000000L;
|
||||
|
||||
// remote messages:
|
||||
target->remote_accepted = st1->remote_accepted + st2->remote_accepted;
|
||||
target->remote_rejected = st1->remote_rejected + st2->remote_rejected;
|
||||
|
||||
// total messages:
|
||||
target->messages_total = st1->messages_total + st2->messages_total;
|
||||
}
|
||||
|
106
stats.h
Normal file
106
stats.h
Normal file
|
@ -0,0 +1,106 @@
|
|||
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
|
||||
//
|
||||
// stats.c: statistics structures and prototypes.
|
||||
//
|
||||
// Copyright (c) 2015 Oliver Jowett <oliver@mutability.co.uk>
|
||||
//
|
||||
// This file is free software: you may copy, redistribute and/or modify it
|
||||
// under the terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation, either version 2 of the License, or (at your
|
||||
// option) any later version.
|
||||
//
|
||||
// This file is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// This file incorporates work covered by the following copyright and
|
||||
// permission notice:
|
||||
//
|
||||
// Copyright (C) 2012 by Salvatore Sanfilippo <antirez@gmail.com>
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef DUMP1090_STATS_H
|
||||
#define DUMP1090_STATS_H
|
||||
|
||||
// Common stats for non-phase-corrected vs phase-corrected cases
|
||||
struct demod_stats {
|
||||
unsigned int demodulated0;
|
||||
unsigned int demodulated1;
|
||||
unsigned int demodulated2;
|
||||
unsigned int demodulated3;
|
||||
unsigned int goodcrc;
|
||||
unsigned int goodcrc_byphase[MODES_MAX_PHASE_STATS];
|
||||
unsigned int badcrc;
|
||||
unsigned int fixed;
|
||||
|
||||
// Histogram of fixed bit errors: index 0 for single bit erros,
|
||||
// index 1 for double bit errors etc.
|
||||
unsigned int bit_fix[MODES_MAX_BITERRORS];
|
||||
};
|
||||
|
||||
struct stats {
|
||||
time_t start;
|
||||
time_t end;
|
||||
|
||||
// Statistics
|
||||
unsigned int preamble_no_correlation;
|
||||
unsigned int preamble_not_quiet;
|
||||
unsigned int valid_preamble;
|
||||
unsigned int preamble_phase[MODES_MAX_PHASE_STATS];
|
||||
|
||||
struct demod_stats demod;
|
||||
struct demod_stats demod_phasecorrected;
|
||||
|
||||
unsigned int http_requests;
|
||||
unsigned int out_of_phase;
|
||||
|
||||
unsigned int DF_Len_Corrected;
|
||||
unsigned int DF_Type_Corrected;
|
||||
unsigned int ModeAC;
|
||||
|
||||
unsigned int blocks_processed;
|
||||
unsigned int blocks_dropped;
|
||||
|
||||
struct timespec cputime;
|
||||
|
||||
// remote messages:
|
||||
unsigned int remote_accepted;
|
||||
unsigned int remote_rejected;
|
||||
|
||||
// total messages:
|
||||
unsigned int messages_total;
|
||||
};
|
||||
|
||||
void add_stats(const struct stats *st1, const struct stats *st2, struct stats *target);
|
||||
void display_stats(struct stats *st);
|
||||
void reset_stats(struct stats *st);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue