diff --git a/debian/dump1090-mutability.config b/debian/dump1090-mutability.config index 871c483..8901f89 100644 --- a/debian/dump1090-mutability.config +++ b/debian/dump1090-mutability.config @@ -136,6 +136,14 @@ is_number() { if echo "$1" | grep -Eq '^([+-]?[0-9][0-9]*)(\.[0-9]+)?$'; then return 0; else return 1; fi } +is_unsigned_number() { + if echo "$1" | grep -Eq '^([+]?[0-9][0-9]*)(\.[0-9]+)?$'; then return 0; else return 1; fi +} + +is_positive_number() { + if echo "$1" | grep -Eq '^(([+]?0\.[0-9]*[1-9]+[0-9]*)|([+]?[1-9][0-9]*)(\.[0-9]+)?)$'; then return 0; else return 1; fi +} + is_number_or_empty() { if [ -z "$1" ]; then return 0 elif is_number "$1"; then return 0; @@ -198,15 +206,15 @@ db_go || true; db_get $NAME/auto-start; if [ "$RET" = "true" ]; then db_input_verify low $NAME/net-bo-port is_port_number || true db_input_verify low $NAME/net-sbs-port is_port_number || true db_input_verify low $NAME/net-fatsv-port is_port_number || true - db_input_verify low $NAME/net-heartbeat is_unsigned_int || true + db_input_verify low $NAME/net-heartbeat is_unsigned_number || true db_input_verify low $NAME/net-out-size is_unsigned_int || true - db_input_verify low $NAME/net-out-interval is_unsigned_int || true + db_input_verify low $NAME/net-out-interval is_unsigned_number || true db_input_verify low $NAME/net-buffer is_unsigned_int || true db_input_verify medium $NAME/net-bind-address is_ipaddrish_or_empty || true db_input_verify low $NAME/stats-interval is_unsigned_int || true - db_input_verify low $NAME/json-interval is_positive_int || true + db_input_verify low $NAME/json-interval is_positive_number || true db_input low $NAME/json-location-accuracy || true db_input low $NAME/json-dir || true diff --git a/debian/dump1090-mutability.templates b/debian/dump1090-mutability.templates index 7fbd89e..5152930 100644 --- a/debian/dump1090-mutability.templates +++ b/debian/dump1090-mutability.templates @@ -317,10 +317,18 @@ Template: dump1090-mutability/invalid-is_ipaddrish_or_empty Description: Value must be an IP address or empty. Type: error +Template: dump1090-mutability/invalid-is_number +Description: Value must be a decimal number +Type: error + Template: dump1090-mutability/invalid-is_number_or_empty Description: Value must be a decimal number or empty. Type: error +Template: dump1090-mutability/invalid-is_unsigned_number +Description: Value must be a non-negative number. +Type: error + Template: dump1090-mutability/invalid-is_valid_gain Description: Value must be a numeric gain value, or "max", or "agc". Type: error diff --git a/dump1090.c b/dump1090.c index 3aa9adf..9e91c9d 100644 --- a/dump1090.c +++ b/dump1090.c @@ -118,7 +118,7 @@ void modesInitConfig(void) { Modes.net_fatsv_port = MODES_NET_OUTPUT_FA_TSV_PORT; Modes.interactive_rows = getTermRows(); Modes.interactive_display_ttl = MODES_INTERACTIVE_DISPLAY_TTL; - Modes.json_interval = 1; + Modes.json_interval = 1000; Modes.json_location_accuracy = 1; Modes.maxRange = 1852 * 300; // 300NM default max range } @@ -588,41 +588,6 @@ MODES_DUMP1090_VARIANT " " MODES_DUMP1090_VERSION ); } -#ifdef _WIN32 -void showCopyright(void) { - uint64_t llTime = time(NULL) + 1; - - printf( -"-----------------------------------------------------------------------------\n" -"| dump1090 ModeS Receiver Ver : " MODES_DUMP1090_VERSION " |\n" -"-----------------------------------------------------------------------------\n" -"\n" -" Copyright (C) 2012 by Salvatore Sanfilippo \n" -" Copyright (C) 2014 by Malcolm Robb \n" -"\n" -" All rights reserved.\n" -"\n" -" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" -" ""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" -" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" -" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" -" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" -" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" -" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" -" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" -" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" -" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" -" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" -"\n" -" For further details refer to \n" -"\n" - ); - - // delay for 1 second to give the user a chance to read the copyright - while (llTime >= time(NULL)) {} -} -#endif - static void display_total_stats(void) { struct stats added; @@ -638,11 +603,11 @@ static void display_total_stats(void) // from the net, refreshing the screen in interactive mode, and so forth // void backgroundTasks(void) { - static time_t next_stats_display; - static time_t next_stats_update; - static time_t next_json, next_history; + static uint64_t next_stats_display; + static uint64_t next_stats_update; + static uint64_t next_json, next_history; - time_t now = time(NULL); + uint64_t now = mstime(); icaoFilterExpire(); trackPeriodicUpdate(); @@ -664,7 +629,7 @@ void backgroundTasks(void) { int i; if (next_stats_update == 0) { - next_stats_update = now + 60; + next_stats_update = now + 60000; } else { Modes.stats_latest_1min = (Modes.stats_latest_1min + 1) % 15; Modes.stats_1min[Modes.stats_latest_1min] = Modes.stats_current; @@ -686,11 +651,11 @@ void backgroundTasks(void) { if (Modes.json_dir) writeJsonToFile("stats.json", generateStatsJson); - next_stats_update += 60; + next_stats_update += 60000; } } - if (Modes.stats > 0 && now >= next_stats_display) { + if (Modes.stats && now >= next_stats_display) { if (next_stats_display == 0) { next_stats_display = now + Modes.stats; } else { @@ -835,13 +800,13 @@ int main(int argc, char **argv) { Modes.net = 1; Modes.net_only = 1; } else if (!strcmp(argv[j],"--net-heartbeat") && more) { - Modes.net_heartbeat_interval = atoi(argv[++j]); + Modes.net_heartbeat_interval = (uint64_t)(1000 * atof(argv[++j])); } else if (!strcmp(argv[j],"--net-ro-size") && more) { Modes.net_output_flush_size = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-ro-rate") && more) { - Modes.net_output_flush_interval = atoi(argv[++j]) / 15; // backwards compatibility + Modes.net_output_flush_interval = 1000 * atoi(argv[++j]) / 15; // backwards compatibility } else if (!strcmp(argv[j],"--net-ro-interval") && more) { - Modes.net_output_flush_interval = atoi(argv[++j]); + Modes.net_output_flush_interval = (uint64_t)(1000 * atof(argv[++j])); } else if (!strcmp(argv[j],"--net-ro-port") && more) { if (Modes.beast) // Required for legacy backward compatibility {Modes.net_output_beast_port = atoi(argv[++j]);;} @@ -902,9 +867,10 @@ int main(int argc, char **argv) { f++; } } else if (!strcmp(argv[j],"--stats")) { - Modes.stats = -1; + if (!Modes.stats) + Modes.stats = (uint64_t)1 << 60; // "never" } else if (!strcmp(argv[j],"--stats-every") && more) { - Modes.stats = atoi(argv[++j]); + Modes.stats = (uint64_t) (1000 * atof(argv[++j])); } else if (!strcmp(argv[j],"--snip") && more) { snipMode(atoi(argv[++j])); exit(0); @@ -926,9 +892,9 @@ int main(int argc, char **argv) { } else if (!strcmp(argv[j], "--write-json") && more) { Modes.json_dir = strdup(argv[++j]); } else if (!strcmp(argv[j], "--write-json-every") && more) { - Modes.json_interval = atoi(argv[++j]); - if (Modes.json_interval < 1) - Modes.json_interval = 1; + Modes.json_interval = (uint64_t)(1000 * atof(argv[++j])); + if (Modes.json_interval < 100) // 0.1s + Modes.json_interval = 100; } else if (!strcmp(argv[j], "--json-location-accuracy") && more) { Modes.json_location_accuracy = atoi(argv[++j]); #endif @@ -983,7 +949,7 @@ int main(int argc, char **argv) { if (Modes.net) modesInitNet(); // init stats: - Modes.stats_current.start = Modes.stats_current.end = time(NULL); + Modes.stats_current.start = Modes.stats_current.end = mstime(); // write initial json files so they're not missing writeJsonToFile("receiver.json", generateReceiverJson); diff --git a/dump1090.h b/dump1090.h index 2adf207..15e5b16 100644 --- a/dump1090.h +++ b/dump1090.h @@ -180,7 +180,7 @@ #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 60 // seconds +#define MODES_NET_HEARTBEAT_INTERVAL 60000 // milliseconds #define MODES_NET_SERVICES_NUM 7 #define MODES_NET_INPUT_RAW_PORT 30001 @@ -199,7 +199,7 @@ #endif #define HISTORY_SIZE 120 -#define HISTORY_INTERVAL 30 +#define HISTORY_INTERVAL 30000 #define MODES_NOTUSED(V) ((void) V) @@ -236,7 +236,7 @@ struct net_writer { int connections; // number of active clients void *data; // shared write buffer, sized MODES_OUT_BUF_SIZE int dataUsed; // number of bytes of write buffer currently used - time_t lastWrite; // time of last write to clients + uint64_t lastWrite; // time of last write to clients }; // Program global state @@ -300,10 +300,10 @@ struct { // Internal state int debug; // Debugging mode int net; // Enable networking int net_only; // Enable just networking - int net_heartbeat_interval; // TCP heartbeat interval (seconds) + uint64_t net_heartbeat_interval; // TCP heartbeat interval (milliseconds) int net_output_sbs_port; // SBS output TCP port int net_output_flush_size; // Minimum Size of output data - int net_output_flush_interval; // Maximum interval (in seconds) between outputwrites + uint64_t net_output_flush_interval; // Maximum interval (in milliseconds) between outputwrites int net_output_raw_port; // Raw output TCP port int net_input_raw_port; // Raw input TCP port int net_output_beast_port; // Beast output TCP port @@ -317,13 +317,13 @@ struct { // Internal state int interactive; // Interactive mode int interactive_rows; // Interactive mode: max number of rows uint64_t interactive_display_ttl;// Interactive mode: TTL display - int stats; // Print stats at exit in --ifile mode + uint64_t stats; // Interval (millis) between stats dumps, int onlyaddr; // Print only ICAO addresses int metric; // Use metric units 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. - int json_interval; // Interval between rewriting the json aircraft file + uint64_t json_interval; // Interval between rewriting the json aircraft file, in milliseconds; also the advertised map refresh interval int json_location_accuracy; // Accuracy of location metadata: 0=none, 1=approx, 2=exact int json_aircraft_history_next; diff --git a/icao_filter.c b/icao_filter.c index 7a625eb..70f32b4 100644 --- a/icao_filter.c +++ b/icao_filter.c @@ -22,8 +22,8 @@ // hash table size, must be a power of two: #define ICAO_FILTER_SIZE 4096 -// Seconds between filter expiry flips: -#define MODES_ICAO_FILTER_TTL 60 +// Millis between filter expiry flips: +#define MODES_ICAO_FILTER_TTL 60000 // Open-addressed hash table with linear probing. // We store each address twice to handle Data/Parity @@ -124,8 +124,8 @@ uint32_t icaoFilterTestFuzzy(uint32_t partial) // call this periodically: void icaoFilterExpire() { - static time_t next_flip = 0; - time_t now = time(NULL); + static uint64_t next_flip = 0; + uint64_t now = mstime(); if (now >= next_flip) { if (icao_filter_active == icao_filter_a) { diff --git a/net_io.c b/net_io.c index 8a5528d..59e2a29 100644 --- a/net_io.c +++ b/net_io.c @@ -127,7 +127,7 @@ void modesInitNet(void) { services[j].writer->socket = s; services[j].writer->connections = 0; services[j].writer->dataUsed = 0; - services[j].writer->lastWrite = time(NULL); + services[j].writer->lastWrite = mstime(); } } else { if (Modes.debug & MODES_DEBUG_NET) printf("%s port is disabled\n", services[j].descr); @@ -165,7 +165,7 @@ struct client * modesAcceptClients(void) { if (services[j].writer) { if (++ services[j].writer->connections == 1) { - services[j].writer->lastWrite = time(NULL); // suppress heartbeat initially + services[j].writer->lastWrite = mstime(); // suppress heartbeat initially } } @@ -229,7 +229,7 @@ static void flushWrites(struct net_writer *writer) { } writer->dataUsed = 0; - writer->lastWrite = time(NULL); + writer->lastWrite = mstime(); } // Prepare to write up to 'len' bytes to the given net_writer. @@ -954,9 +954,9 @@ char *generateReceiverJson(const char *url_path, int *len) p += sprintf(p, "{ " \ "\"version\" : \"%s\", " - "\"refresh\" : %d, " + "\"refresh\" : %.0f, " "\"history\" : %d", - MODES_DUMP1090_VERSION, Modes.json_interval * 1000, history_size); + MODES_DUMP1090_VERSION, 1.0*Modes.json_interval, history_size); if (Modes.json_location_accuracy && (Modes.fUserLat != 0.0 || Modes.fUserLon != 0.0)) { if (Modes.json_location_accuracy == 1) { @@ -1541,7 +1541,7 @@ static void writeFATSV() { // void modesNetPeriodicWork(void) { struct client *c, **prev; - time_t now = time(NULL); + uint64_t now = mstime(); int j; int need_heartbeat = 0, need_flush = 0; diff --git a/stats.c b/stats.c index 2c69592..443fda8 100644 --- a/stats.c +++ b/stats.c @@ -59,6 +59,7 @@ void add_timespecs(const struct timespec *x, const struct timespec *y, struct ti void display_stats(struct stats *st) { int j; + time_t tt_start, tt_end; struct tm tm_start, tm_end; char tb_start[30], tb_end[30]; @@ -66,9 +67,11 @@ void display_stats(struct stats *st) { if (Modes.interactive) interactiveShowData(); - localtime_r(&st->start, &tm_start); + tt_start = st->start/1000; + localtime_r(&tt_start, &tm_start); strftime(tb_start, sizeof(tb_start), "%c", &tm_start); - localtime_r(&st->end, &tm_end); + tt_end = st->end/1000; + localtime_r(&tt_end, &tm_end); strftime(tb_end, sizeof(tb_end), "%c", &tm_end); printf("Statistics: %s - %s\n", tb_start, tb_end); @@ -147,7 +150,7 @@ void display_stats(struct stats *st) { " %llu ms for demodulation\n" " %llu ms for reading from USB\n" " %llu ms for network input and background tasks\n", - 0.1 * (demod_cpu_millis + reader_cpu_millis + background_cpu_millis) / (st->end - st->start + 1), + 100.0 * (demod_cpu_millis + reader_cpu_millis + background_cpu_millis) / (st->end - st->start + 1), (unsigned long long) demod_cpu_millis, (unsigned long long) reader_cpu_millis, (unsigned long long) background_cpu_millis); diff --git a/stats.h b/stats.h index 22d4845..5959776 100644 --- a/stats.h +++ b/stats.h @@ -51,8 +51,8 @@ #define DUMP1090_STATS_H struct stats { - time_t start; - time_t end; + uint64_t start; + uint64_t end; // Mode S demodulator counts: uint32_t demod_preambles; diff --git a/view1090.c b/view1090.c index e2ec008..119ad49 100644 --- a/view1090.c +++ b/view1090.c @@ -171,40 +171,6 @@ void showHelp(void) { ); } -#ifdef _WIN32 -void showCopyright(void) { - uint64_t llTime = time(NULL) + 1; - - printf( -"-----------------------------------------------------------------------------\n" -"| view1090 ModeS Viewer Ver : " MODES_DUMP1090_VERSION " |\n" -"-----------------------------------------------------------------------------\n" -"\n" -" Copyright (C) 2012 by Salvatore Sanfilippo \n" -" Copyright (C) 2014 by Malcolm Robb \n" -"\n" -" All rights reserved.\n" -"\n" -" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" -" ""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" -" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" -" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" -" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" -" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" -" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" -" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" -" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" -" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" -" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" -"\n" -" For further details refer to \n" -"\n" - ); - - // delay for 1 second to give the user a chance to read the copyright - while (llTime >= time(NULL)) {} -} -#endif // //========================================================================= //