diff --git a/dump1090.h b/dump1090.h index 6cc0275..c71f5f0 100644 --- a/dump1090.h +++ b/dump1090.h @@ -215,6 +215,18 @@ typedef enum { NAV_MODE_TCAS = 32 } nav_modes_t; +// Matches encoding of the ES type 28/1 emergency/priority status subfield +typedef enum { + EMERGENCY_NONE = 0, + EMERGENCY_GENERAL = 1, + EMERGENCY_LIFEGUARD = 2, + EMERGENCY_MINFUEL = 3, + EMERGENCY_NORDO = 4, + EMERGENCY_UNLAWFUL = 5, + EMERGENCY_DOWNED = 6, + EMERGENCY_RESERVED = 7 +} emergency_t; + #define MODES_NON_ICAO_ADDRESS (1<<24) // Set on addresses to indicate they are not ICAO addresses #define MODES_DEBUG_DEMOD (1<<0) @@ -450,6 +462,7 @@ struct modesMessage { unsigned spi : 1; unsigned alert_valid : 1; unsigned alert : 1; + unsigned emergency_valid : 1; unsigned metype; // DF17/18 ME type unsigned mesub; // DF17/18 ME subtype @@ -486,6 +499,7 @@ struct modesMessage { unsigned squawk; // 13 bits identity (Squawk), encoded as 4 hex digits char callsign[9]; // 8 chars flight number, NUL-terminated unsigned category; // A0 - D7 encoded as a single hex byte + emergency_t emergency; // emergency/priority status // valid if cpr_valid cpr_type_t cpr_type; // The encoding type used (surface, airborne, coarse TIS-B) diff --git a/mode_s.c b/mode_s.c index 9e5f206..54e9c74 100644 --- a/mode_s.c +++ b/mode_s.c @@ -986,7 +986,10 @@ static void decodeESAircraftStatus(struct modesMessage *mm, int check_imf) mm->mesub = getbits(me, 6, 8); if (mm->mesub == 1) { // Emergency status squawk field - int ID13Field = getbits(me, 12, 24); + mm->emergency_valid = 1; + mm->emergency = (emergency_t) getbits(me, 9, 11); + + unsigned ID13Field = getbits(me, 12, 24); if (ID13Field) { mm->squawk_valid = 1; mm->squawk = decodeID13Field(ID13Field); @@ -1130,7 +1133,9 @@ static void decodeESTargetStatus(struct modesMessage *mm, int check_imf) } - // 54-56: emergency/priority (ignored) + // 54-56: emergency/priority + mm->emergency_valid = 1; + mm->emergency = (emergency_t) getbits(me, 54, 56); } else if (mm->mesub == 1) { // Target state and status, V2 // 8: SIL unsigned is_fms = getbit(me, 9); @@ -1590,6 +1595,20 @@ static const char *sil_type_to_string(sil_type_t type) } } +static const char *emergency_to_string(emergency_t emergency) +{ + switch (emergency) { + case EMERGENCY_NONE: return "no emergency"; + case EMERGENCY_GENERAL: return "general emergency (7700)"; + case EMERGENCY_LIFEGUARD: return "lifeguard / medical emergency"; + case EMERGENCY_MINFUEL: return "minimum fuel"; + case EMERGENCY_NORDO: return "no communications (7600)"; + case EMERGENCY_UNLAWFUL: return "unlawful interference (7500)"; + case EMERGENCY_DOWNED: return "downed aircraft"; + default: return "reserved"; + } +} + static void print_hex_bytes(unsigned char *data, size_t len) { size_t i; for (i = 0; i < len; ++i) { @@ -2050,6 +2069,9 @@ void displayModesMessage(struct modesMessage *mm) { printf(" Nav modes: %s\n", nav_modes_to_string(mm->nav.modes)); } + if (mm->emergency_valid) { + printf(" Emergency/priority: %s\n", emergency_to_string(mm->emergency)); + } printf("\n"); fflush(stdout); diff --git a/net_io.c b/net_io.c index 1ba7635..b69da15 100644 --- a/net_io.c +++ b/net_io.c @@ -1977,6 +1977,20 @@ static const char *airground_string(airground_t ag) } } +static const char *emergency_enum_string(emergency_t emergency) +{ + switch (emergency) { + case EMERGENCY_NONE: return "none"; + case EMERGENCY_GENERAL: return "general"; + case EMERGENCY_LIFEGUARD: return "lifeguard"; + case EMERGENCY_MINFUEL: return "minfuel"; + case EMERGENCY_NORDO: return "nordo"; + case EMERGENCY_UNLAWFUL: return "unlawful"; + case EMERGENCY_DOWNED: return "downed"; + default: return "reserved"; + } +} + static void writeFATSVBanner() { char *p = prepareWrite(&Modes.fatsv_out, TSV_MAX_PACKET_SIZE); @@ -2152,6 +2166,7 @@ static void writeFATSV() p = appendFATSVMeta(p, end, "nav_heading", a, &a->nav_heading_valid, "%.1f", a->nav_heading); p = appendFATSVMeta(p, end, "nav_modes", a, &a->nav_modes_valid, "{%s}", nav_modes_string(a->nav_modes)); p = appendFATSVMeta(p, end, "nav_qnh", a, &a->nav_qnh_valid, "%.1f", a->nav_qnh); + p = appendFATSVMeta(p, end, "emergency", a, &a->emergency_valid, "%s", emergency_enum_string(a->emergency)); // if we didn't get anything interesting, bail out. // We don't need to do anything special to unwind prepareWrite(). diff --git a/track.c b/track.c index 1f4ed8e..dd1b0d0 100644 --- a/track.c +++ b/track.c @@ -876,6 +876,10 @@ struct aircraft *trackUpdateFromMessage(struct modesMessage *mm) a->squawk = mm->squawk; } + if (mm->emergency_valid && accept_data(&a->emergency_valid, mm->source)) { + a->emergency = mm->emergency; + } + if (mm->altitude_geom_valid && accept_data(&a->altitude_geom_valid, mm->source)) { a->altitude_geom = altitude_to_feet(mm->altitude_geom, mm->altitude_geom_unit); } diff --git a/track.h b/track.h index f78af1a..40323d4 100644 --- a/track.h +++ b/track.h @@ -140,6 +140,9 @@ struct aircraft { data_validity squawk_valid; unsigned squawk; // Squawk + data_validity emergency_valid; + emergency_t emergency; // Emergency/priority status + unsigned category; // Aircraft category A0 - D7 encoded as a single hex byte data_validity airground_valid;