diff --git a/dump1090.h b/dump1090.h index d3748b6..7ab45d1 100644 --- a/dump1090.h +++ b/dump1090.h @@ -165,6 +165,7 @@ typedef struct rtlsdr_dev rtlsdr_dev_t; #define MODES_ACFLAGS_FROM_MLAT (1<<18) // Data was derived from multilateration #define MODES_ACFLAGS_ALTITUDE_HAE_VALID (1<<19) // altitude_hae is valid #define MODES_ACFLAGS_HAE_DELTA_VALID (1<<20) // hae_delta is valid +#define MODES_ACFLAGS_FROM_TISB (1<<21) // Data was derived from TIS-B messages #define MODES_ACFLAGS_LLEITHER_VALID (MODES_ACFLAGS_LLEVEN_VALID | MODES_ACFLAGS_LLODD_VALID) #define MODES_ACFLAGS_LLBOTH_VALID (MODES_ACFLAGS_LLEVEN_VALID | MODES_ACFLAGS_LLODD_VALID) diff --git a/mode_s.c b/mode_s.c index b53bd4f..b487a01 100644 --- a/mode_s.c +++ b/mode_s.c @@ -714,6 +714,11 @@ static void decodeExtendedSquitter(struct modesMessage *mm) // Check CF on DF18 to work out the format of the ES and whether we need to look for an IMF bit if (mm->msgtype == 18) { + /* we just globally tag any DF18 as TIS-B, + * which is not strictly true but close enough + */ + mm->bFlags |= MODES_ACFLAGS_FROM_TISB; + switch (mm->cf) { case 0: // ADS-B ES/NT devices that report the ICAO 24-bit address in the AA field break; diff --git a/net_io.c b/net_io.c index 361c668..261cc88 100644 --- a/net_io.c +++ b/net_io.c @@ -879,6 +879,31 @@ static const char *jsonEscapeString(const char *str) { return buf; } +static char *append_flags(char *p, char *end, int flags) +{ + p += sprintf(p, end-p, "["); + if (flags & MODES_ACFLAGS_SQUAWK_VALID) + p += snprintf(p, end-p, "\"squawk\","); + if (flags & MODES_ACFLAGS_CALLSIGN_VALID) + p += snprintf(p, end-p, "\"callsign\","); + if (flags & MODES_ACFLAGS_LATLON_VALID) + p += snprintf(p, end-p, "\"lat\",\"lon\","); + if (flags & MODES_ACFLAGS_ALTITUDE_VALID) + p += snprintf(p, end-p, "\"altitude\","); + if (flags & MODES_ACFLAGS_HEADING_VALID) + p += snprintf(p, end-p, "\"track\","); + if (flags & MODES_ACFLAGS_SPEED_VALID) + p += snprintf(p, end-p, "\"speed\","); + if (flags & MODES_ACFLAGS_VERTRATE_VALID) + p += snprintf(p, end-p, "\"vert_rate\","); + if (flags & MODES_ACFLAGS_CATEGORY_VALID) + p += snprintf(p, end-p, "\"category\","); + if (p[-1] != '[') + --p; + p += snprintf(p, end-p, "]"); + return p; +} + char *generateAircraftJson(const char *url_path, int *len) { uint64_t now = mstime(); struct aircraft *a; @@ -929,26 +954,12 @@ char *generateAircraftJson(const char *url_path, int *len) { if (a->bFlags & MODES_ACFLAGS_CATEGORY_VALID) p += snprintf(p, end-p, ",\"category\":\"%02X\"", a->category); if (a->mlatFlags) { - p += snprintf(p, end-p, ",\"mlat\":["); - if (a->mlatFlags & MODES_ACFLAGS_SQUAWK_VALID) - p += snprintf(p, end-p, "\"squawk\","); - if (a->mlatFlags & MODES_ACFLAGS_CALLSIGN_VALID) - p += snprintf(p, end-p, "\"callsign\","); - if (a->mlatFlags & MODES_ACFLAGS_LATLON_VALID) - p += snprintf(p, end-p, "\"lat\",\"lon\","); - if (a->mlatFlags & MODES_ACFLAGS_ALTITUDE_VALID) - p += snprintf(p, end-p, "\"altitude\","); - if (a->mlatFlags & MODES_ACFLAGS_HEADING_VALID) - p += snprintf(p, end-p, "\"track\","); - if (a->mlatFlags & MODES_ACFLAGS_SPEED_VALID) - p += snprintf(p, end-p, "\"speed\","); - if (a->mlatFlags & MODES_ACFLAGS_VERTRATE_VALID) - p += snprintf(p, end-p, "\"vert_rate\","); - if (a->mlatFlags & MODES_ACFLAGS_CATEGORY_VALID) - p += snprintf(p, end-p, "\"category\","); - if (p[-1] != '[') - --p; - p += snprintf(p, end-p, "]"); + p += snprintf(p, end-p, ",\"mlat\":"); + p = append_flags(p, end, a->mlatFlags); + } + if (a->tisbFlags) { + p += snprintf(p, end-p, ",\"tisb\":"); + p = append_flags(p, end, a->tisbFlags); } p += snprintf(p, end-p, ",\"messages\":%ld,\"seen\":%.1f,\"rssi\":%.1f}", @@ -1554,7 +1565,7 @@ static void modesReadFromClient(struct client *c) { } } -#define TSV_MAX_PACKET_SIZE 160 +#define TSV_MAX_PACKET_SIZE 180 static void writeFATSV() { @@ -1599,6 +1610,7 @@ static void writeFATSV() char *p, *end; int flags; + int used_tisb = 0; // skip non-ICAO if (a->addr & MODES_NON_ICAO_ADDRESS) @@ -1621,6 +1633,7 @@ static void writeFATSV() alt = a->altitude; altAge = now - a->seenAltitude; altValid = (altAge <= 30000); + used_tisb |= (a->tisbFlags & MODES_ACFLAGS_ALTITUDE_VALID); } if (flags & MODES_ACFLAGS_AOG_VALID) { @@ -1633,21 +1646,26 @@ static void writeFATSV() altAge = 0; ground = 1; } + + used_tisb |= (a->tisbFlags & MODES_ACFLAGS_AOG_VALID); } if (flags & MODES_ACFLAGS_LATLON_VALID) { latlonAge = now - a->seenLatLon; latlonValid = (latlonAge <= 30000); + used_tisb |= (a->tisbFlags & MODES_ACFLAGS_LATLON_VALID); } if (flags & MODES_ACFLAGS_HEADING_VALID) { trackAge = now - a->seenTrack; trackValid = (trackAge <= 30000); + used_tisb |= (a->tisbFlags & MODES_ACFLAGS_HEADING_VALID); } if (flags & MODES_ACFLAGS_SPEED_VALID) { speedAge = now - a->seenSpeed; speedValid = (speedAge <= 30000); + used_tisb |= (a->tisbFlags & MODES_ACFLAGS_SPEED_VALID); } // don't send mode S very often @@ -1729,6 +1747,10 @@ static void writeFATSV() useful = 1; } + if (used_tisb) { + p += snprintf(p, bufsize(p,end), "\ttisb\t1"); + } + // if we didn't get at least an alt or a speed or a latlon or // a heading, bail out. We don't need to do anything special // to unwind prepareWrite(). diff --git a/track.c b/track.c index 744bf88..eb22eb3 100644 --- a/track.c +++ b/track.c @@ -597,6 +597,12 @@ struct aircraft *trackUpdateFromMessage(struct modesMessage *mm) else a->mlatFlags = (a->mlatFlags & a->bFlags) & ~mm->bFlags; + // Same for TIS-B + if (mm->bFlags & MODES_ACFLAGS_FROM_TISB) + a->tisbFlags = (a->tisbFlags & a->bFlags) | mm->bFlags; + else + a->tisbFlags = (a->tisbFlags & a->bFlags) & ~mm->bFlags; + if (mm->msgtype == 32) { int flags = a->modeACflags; if ((flags & (MODEAC_MSG_MODEC_HIT | MODEAC_MSG_MODEC_OLD)) == MODEAC_MSG_MODEC_OLD) { diff --git a/track.h b/track.h index 84ee85b..9153050 100644 --- a/track.h +++ b/track.h @@ -78,6 +78,7 @@ struct aircraft { uint64_t seenTrack; // Time (millis) at which track was measured int mlatFlags; // Data derived from mlat messages + int tisbFlags; // Data derived from TIS-B messages long messages; // Number of Mode S messages received int modeA; // Squawk