def wrapper(msg): df = common.df(msg) if df != 11: raise RuntimeError( "Incorrect downlink format, expect 11, got {}".format(df) ) return func(msg)
def commb_decode_all(df, n=None): import csv print("===== Decode Comm-B sample data (DF=%s)=====" % df) f = open("tests/data/sample_data_commb_df%s.csv" % df, "rt") for i, r in enumerate(csv.reader(f)): if n and i > n: break ts = r[0] m = r[2] df = common.df(m) icao = common.icao(m) BDS = bds.infer(m) code = common.altcode(m) if df == 20 else common.idcode(m) if not BDS: print(ts, m, icao, df, "%5s" % code, "UNKNOWN") continue if len(BDS.split(",")) > 1: print(ts, m, icao, df, "%5s" % code, end=" ") for i, _bds in enumerate(BDS.split(",")): if i == 0: print(_bds, *bds_info(_bds, m)) else: print(" " * 55, _bds, *bds_info(_bds, m)) else: print(ts, m, icao, df, "%5s" % code, BDS, *bds_info(BDS, m))
def is60(msg): """Check if a message is likely to be BDS code 6,0 Args: msg (str): 28 hexdigits string Returns: bool: True or False """ if common.allzeros(msg): return False d = common.hex2bin(common.data(msg)) # status bit 1, 13, 24, 35, 46 if common.wrongstatus(d, 1, 2, 12): return False if common.wrongstatus(d, 13, 14, 23): return False if common.wrongstatus(d, 24, 25, 34): return False if common.wrongstatus(d, 35, 36, 45): return False if common.wrongstatus(d, 46, 47, 56): return False ias = ias60(msg) if ias is not None and ias > 500: return False mach = mach60(msg) if mach is not None and mach > 1: return False vr_baro = vr60baro(msg) if vr_baro is not None and abs(vr_baro) > 6000: return False vr_ins = vr60ins(msg) if vr_ins is not None and abs(vr_ins) > 6000: return False # additional check knowing altitude if (mach is not None) and (ias is not None) and (common.df(msg) == 20): alt = common.altcode(msg) if alt is not None: ias_ = aero.mach2cas(mach, alt * aero.ft) / aero.kts if abs(ias - ias_) > 20: return False return True
def check_msg(self, msg): df = common.df(msg) msglen = len(msg) if df == 17 and msglen == 28: if common.crc(msg) == 0: return True elif df in [20, 21] and msglen == 28: return True elif df in [4, 5, 11] and msglen == 14: return True else: return False
def df(msg): return common.df(msg)
def infer(msg, mrar=False): """Estimate the most likely BDS code of an message. Args: msg (str): 28 hexdigits string mrar (bool): Also infer MRAR (BDS 44) and MHR (BDS 45). Defaults to False. Returns: String or None: BDS version, or possible versions, or None if nothing matches. """ df = common.df(msg) if common.allzeros(msg): return "EMPTY" # For ADS-B / Mode-S extended squitter if df == 17: tc = common.typecode(msg) if 1 <= tc <= 4: return "BDS08" # identification and category if 5 <= tc <= 8: return "BDS06" # surface movement if 9 <= tc <= 18: return "BDS05" # airborne position, baro-alt if tc == 19: return "BDS09" # airborne velocity if 20 <= tc <= 22: return "BDS05" # airborne position, gnss-alt if tc == 28: return "BDS61" # aircraft status if tc == 29: return "BDS62" # target state and status if tc == 31: return "BDS65" # operational status # For Comm-B replies IS10 = bds10.is10(msg) IS17 = bds17.is17(msg) IS20 = bds20.is20(msg) IS30 = bds30.is30(msg) IS40 = bds40.is40(msg) IS50 = bds50.is50(msg) IS60 = bds60.is60(msg) IS44 = bds44.is44(msg) IS45 = bds45.is45(msg) if mrar: allbds = np.array([ "BDS10", "BDS17", "BDS20", "BDS30", "BDS40", "BDS44", "BDS45", "BDS50", "BDS60", ]) mask = [IS10, IS17, IS20, IS30, IS40, IS44, IS45, IS50, IS60] else: allbds = np.array( ["BDS10", "BDS17", "BDS20", "BDS30", "BDS40", "BDS50", "BDS60"]) mask = [IS10, IS17, IS20, IS30, IS40, IS50, IS60] bds = ",".join(sorted(allbds[mask])) if len(bds) == 0: return None else: return bds
def tell(msg: str) -> None: from pyModeS import common, adsb, commb, bds def _print(label, value, unit=None): print("%20s: " % label, end="") print("%s " % value, end="") if unit: print(unit) else: print() df = common.df(msg) icao = common.icao(msg) _print("Message", msg) _print("ICAO address", icao) _print("Downlink Format", df) if df == 17: _print("Protocol", "Mode-S Extended Squitter (ADS-B)") tc = common.typecode(msg) if 1 <= tc <= 4: # callsign callsign = adsb.callsign(msg) _print("Type", "Identitification and category") _print("Callsign:", callsign) if 5 <= tc <= 8: # surface position _print("Type", "Surface position") oe = adsb.oe_flag(msg) msgbin = common.hex2bin(msg) cprlat = common.bin2int(msgbin[54:71]) / 131072.0 cprlon = common.bin2int(msgbin[71:88]) / 131072.0 v = adsb.surface_velocity(msg) _print("CPR format", "Odd" if oe else "Even") _print("CPR Latitude", cprlat) _print("CPR Longitude", cprlon) _print("Speed", v[0], "knots") _print("Track", v[1], "degrees") if 9 <= tc <= 18: # airborne position _print("Type", "Airborne position (with barometric altitude)") alt = adsb.altitude(msg) oe = adsb.oe_flag(msg) msgbin = common.hex2bin(msg) cprlat = common.bin2int(msgbin[54:71]) / 131072.0 cprlon = common.bin2int(msgbin[71:88]) / 131072.0 _print("CPR format", "Odd" if oe else "Even") _print("CPR Latitude", cprlat) _print("CPR Longitude", cprlon) _print("Altitude", alt, "feet") if tc == 19: _print("Type", "Airborne velocity") spd, trk, vr, t = adsb.velocity(msg) types = {"GS": "Ground speed", "TAS": "True airspeed"} _print("Speed", spd, "knots") _print("Track", trk, "degrees") _print("Vertical rate", vr, "feet/minute") _print("Type", types[t]) if 20 <= tc <= 22: # airborne position _print("Type", "Airborne position (with GNSS altitude)") alt = adsb.altitude(msg) oe = adsb.oe_flag(msg) msgbin = common.hex2bin(msg) cprlat = common.bin2int(msgbin[54:71]) / 131072.0 cprlon = common.bin2int(msgbin[71:88]) / 131072.0 _print("CPR format", "Odd" if oe else "Even") _print("CPR Latitude", cprlat) _print("CPR Longitude", cprlon) _print("Altitude", alt, "feet") if df == 20: _print("Protocol", "Mode-S Comm-B altitude reply") _print("Altitude", common.altcode(msg), "feet") if df == 21: _print("Protocol", "Mode-S Comm-B identity reply") _print("Squawk code", common.idcode(msg)) if df == 20 or df == 21: labels = { "BDS10": "Data link capability", "BDS17": "GICB capability", "BDS20": "Aircraft identification", "BDS30": "ACAS resolution", "BDS40": "Vertical intention report", "BDS50": "Track and turn report", "BDS60": "Heading and speed report", "BDS44": "Meteorological routine air report", "BDS45": "Meteorological hazard report", "EMPTY": "[No information available]", } BDS = bds.infer(msg, mrar=True) if BDS in labels.keys(): _print("BDS", "%s (%s)" % (BDS, labels[BDS])) else: _print("BDS", BDS) if BDS == "BDS20": callsign = commb.cs20(msg) _print("Callsign", callsign) if BDS == "BDS40": _print("MCP target alt", commb.selalt40mcp(msg), "feet") _print("FMS Target alt", commb.selalt40fms(msg), "feet") _print("Pressure", commb.p40baro(msg), "millibar") if BDS == "BDS50": _print("Roll angle", commb.roll50(msg), "degrees") _print("Track angle", commb.trk50(msg), "degrees") _print("Track rate", commb.rtrk50(msg), "degree/second") _print("Ground speed", commb.gs50(msg), "knots") _print("True airspeed", commb.tas50(msg), "knots") if BDS == "BDS60": _print("Megnatic Heading", commb.hdg60(msg), "degrees") _print("Indicated airspeed", commb.ias60(msg), "knots") _print("Mach number", commb.mach60(msg)) _print("Vertical rate (Baro)", commb.vr60baro(msg), "feet/minute") _print("Vertical rate (INS)", commb.vr60ins(msg), "feet/minute") if BDS == "BDS44": _print("Wind speed", commb.wind44(msg)[0], "knots") _print("Wind direction", commb.wind44(msg)[1], "degrees") _print("Temperature 1", commb.temp44(msg)[0], "Celsius") _print("Temperature 2", commb.temp44(msg)[1], "Celsius") _print("Pressure", commb.p44(msg), "hPa") _print("Humidity", commb.hum44(msg), "%") _print("Turbulence", commb.turb44(msg)) if BDS == "BDS45": _print("Turbulence", commb.turb45(msg)) _print("Wind shear", commb.ws45(msg)) _print("Microbust", commb.mb45(msg)) _print("Icing", commb.ic45(msg)) _print("Wake vortex", commb.wv45(msg)) _print("Temperature", commb.temp45(msg), "Celsius") _print("Pressure", commb.p45(msg), "hPa") _print("Radio height", commb.rh45(msg), "feet")
def message(self, msg): # Printout of statistics if self.signal_hup == 1: self.logstats() self.signal_hup = 0 ret_dict = {} ret_dict['ret'] = 0 ret_dict['type'] = "" self.msgs_curr_total = self.msgs_curr_total + 1 if len(msg) == 26 or len(msg) == 40: # Some version of dump1090 have the 12 first characters used w/ # some date (timestamp ?). E.g. sdbr245 feeding flightradar24. # Strip 12 first characters. msg = msg[12:] if len(msg) < 28: # Message length 112 bits self.msgs_curr_short = self.msgs_curr_short + 1 else: self.msgs_curr_len28 = self.msgs_curr_len28 + 1 ret_dict['crc'] = self.check_msg(msg) if ret_dict['crc']: self.parity_check_ok = self.parity_check_ok + 1 else: self.parity_check_ko = self.parity_check_ko + 1 # Do not manage messages with bad CRC if ret_dict['crc'] is not True: raise ValueError("CrcKO") dfmt = common.df(msg) ret_dict['dfmt'] = dfmt self.df[dfmt] = self.df[dfmt] + 1 ret_dict['ic'] = common.icao(msg) if dfmt in [17, 18]: # Downlink format 17 or 18 tc = common.typecode(msg) ret_dict['tc'] = tc self.tc[tc] = self.tc[tc] + 1 lat_ref = float(self.params["lat"]) long_ref = float(self.params["long"]) if tc == 4: # Aircraft identification self.msgs_discovered = self.msgs_discovered + 1 ret_dict['type'] = "CS" ret_dict['cs'] = adsb.callsign(msg) ca = adsb_ca(msg) ret_dict['ca'] = ca_msg[ca] self.ca[ca] = self.ca[ca] + 1 elif 9 <= tc <= 18: self.msgs_discovered = self.msgs_discovered + 1 ret_dict['type'] = "LB" ret_dict['altb'] = adsb.altitude(msg) (lat, long) = adsb.position_with_ref(msg, lat_ref, long_ref) ret_dict['lat'] = lat ret_dict['long'] = long elif tc == 19: self.msgs_discovered = self.msgs_discovered + 1 ret_dict['type'] = "VH" _dict = adsb.velocity(msg) if _dict is None: raise ValueError("AdsbVelocity") (ret_dict['speed'], ret_dict['head'], ret_dict['rocd'], var) = _dict if ret_dict['head'] is None: raise ValueError("AdsbHeading") if ret_dict['rocd'] is None: raise ValueError("AdsbRocd") elif 20 <= tc <= 22: self.msgs_discovered = self.msgs_discovered + 1 ret_dict['type'] = "LG" ret_dict['altg'] = adsb.altitude(msg) (lat, long) = adsb.position_with_ref(msg, lat_ref, long_ref) ret_dict['lat'] = lat ret_dict['long'] = long elif dfmt in [5, 21]: self.msgs_discovered = self.msgs_discovered + 1 ret_dict['type'] = "SQ" ret_dict['sq'] = common.idcode(msg) if dfmt in [0, 4, 16, 20]: self.msgs_discovered = self.msgs_discovered + 1 ret_dict['type'] = "AL" _alt = common.altcode(msg) alt = _alt if _alt is not None else 0 ret_dict['alt'] = alt return ret_dict
def tell(msg: str) -> None: from pyModeS import common, adsb, commb, bds def _print(label, value, unit=None): print("%20s: " % label, end="") print("%s " % value, end="") if unit: print(unit) else: print() df = common.df(msg) icao = common.icao(msg) _print("Message", msg) _print("ICAO address", icao) _print("Downlink Format", df) if df == 17: _print("Protocol", "Mode-S Extended Squitter (ADS-B)") tc = common.typecode(msg) if 1 <= tc <= 4: # callsign callsign = adsb.callsign(msg) _print("Type", "Identification and category") _print("Callsign:", callsign) if 5 <= tc <= 8: # surface position _print("Type", "Surface position") oe = adsb.oe_flag(msg) msgbin = common.hex2bin(msg) cprlat = common.bin2int(msgbin[54:71]) / 131072.0 cprlon = common.bin2int(msgbin[71:88]) / 131072.0 v = adsb.surface_velocity(msg) _print("CPR format", "Odd" if oe else "Even") _print("CPR Latitude", cprlat) _print("CPR Longitude", cprlon) _print("Speed", v[0], "knots") _print("Track", v[1], "degrees") if 9 <= tc <= 18: # airborne position _print("Type", "Airborne position (with barometric altitude)") alt = adsb.altitude(msg) oe = adsb.oe_flag(msg) msgbin = common.hex2bin(msg) cprlat = common.bin2int(msgbin[54:71]) / 131072.0 cprlon = common.bin2int(msgbin[71:88]) / 131072.0 _print("CPR format", "Odd" if oe else "Even") _print("CPR Latitude", cprlat) _print("CPR Longitude", cprlon) _print("Altitude", alt, "feet") if tc == 19: _print("Type", "Airborne velocity") spd, trk, vr, t = adsb.velocity(msg) types = {"GS": "Ground speed", "TAS": "True airspeed"} _print("Speed", spd, "knots") _print("Track", trk, "degrees") _print("Vertical rate", vr, "feet/minute") _print("Type", types[t]) if 20 <= tc <= 22: # airborne position _print("Type", "Airborne position (with GNSS altitude)") alt = adsb.altitude(msg) oe = adsb.oe_flag(msg) msgbin = common.hex2bin(msg) cprlat = common.bin2int(msgbin[54:71]) / 131072.0 cprlon = common.bin2int(msgbin[71:88]) / 131072.0 _print("CPR format", "Odd" if oe else "Even") _print("CPR Latitude", cprlat) _print("CPR Longitude", cprlon) _print("Altitude", alt, "feet") if tc == 29: # target state and status _print("Type", "Target State and Status") subtype = common.bin2int((common.hex2bin(msg)[32:])[5:7]) _print("Subtype", subtype) tcas_operational = adsb.tcas_operational(msg) types = {0: "Not Engaged", 1: "Engaged"} tcas_operational_types = {0: "Not Operational", 1: "Operational"} if subtype == 0: emergency_types = { 0: "No emergency", 1: "General emergency", 2: "Lifeguard/medical emergency", 3: "Minimum fuel", 4: "No communications", 5: "Unlawful interference", 6: "Downed aircraft", 7: "Reserved" } vertical_horizontal_types = { 1: "Acquiring mode", 2: "Capturing/Maintaining mode" } tcas_ra_types = {0: "Not active", 1: "Active"} alt, alt_source, alt_ref = adsb.target_altitude(msg) angle, angle_type, angle_source = adsb.target_angle(msg) vertical_mode = adsb.vertical_mode(msg) horizontal_mode = adsb.horizontal_mode(msg) tcas_ra = adsb.tcas_ra(msg) emergency_status = adsb.emergency_status(msg) _print("Target altitude", alt, "feet") _print("Altitude source", alt_source) _print("Altitude reference", alt_ref) _print("Angle", angle, "°") _print("Angle Type", angle_type) _print("Angle Source", angle_source) _print("Vertical mode", vertical_horizontal_types[vertical_mode]) _print("Horizontal mode", vertical_horizontal_types[horizontal_mode]) _print("TCAS/ACAS", tcas_operational_types[tcas_operational]) _print("TCAS/ACAS RA", tcas_ra_types[tcas_ra]) _print("Emergency status", emergency_types[emergency_status]) else: alt, alt_source = adsb.selected_altitude(msg) baro = adsb.baro_pressure_setting(msg) hdg = adsb.selected_heading(msg) autopilot = adsb.autopilot(msg) vnav = adsb.vnav_mode(msg) alt_hold = adsb.altitude_hold_mode(msg) app = adsb.approach_mode(msg) lnav = adsb.lnav_mode(msg) _print("Selected altitude", alt, "feet") _print("Altitude source", alt_source) _print("Barometric pressure setting", baro, "millibars") _print("Selected Heading", hdg, "°") if not (common.bin2int((common.hex2bin(msg)[32:])[46]) == 0): _print("Autopilot", types[autopilot]) _print("VNAV mode", types[vnav]) _print("Altitude hold mode", types[alt_hold]) _print("Approach mode", types[app]) _print("TCAS/ACAS", tcas_operational_types[tcas_operational]) _print("LNAV mode", types[lnav]) if df == 20: _print("Protocol", "Mode-S Comm-B altitude reply") _print("Altitude", common.altcode(msg), "feet") if df == 21: _print("Protocol", "Mode-S Comm-B identity reply") _print("Squawk code", common.idcode(msg)) if df == 20 or df == 21: labels = { "BDS10": "Data link capability", "BDS17": "GICB capability", "BDS20": "Aircraft identification", "BDS30": "ACAS resolution", "BDS40": "Vertical intention report", "BDS50": "Track and turn report", "BDS60": "Heading and speed report", "BDS44": "Meteorological routine air report", "BDS45": "Meteorological hazard report", "EMPTY": "[No information available]", } BDS = bds.infer(msg, mrar=True) if BDS in labels.keys(): _print("BDS", "%s (%s)" % (BDS, labels[BDS])) else: _print("BDS", BDS) if BDS == "BDS20": callsign = commb.cs20(msg) _print("Callsign", callsign) if BDS == "BDS40": _print("MCP target alt", commb.selalt40mcp(msg), "feet") _print("FMS Target alt", commb.selalt40fms(msg), "feet") _print("Pressure", commb.p40baro(msg), "millibar") if BDS == "BDS50": _print("Roll angle", commb.roll50(msg), "degrees") _print("Track angle", commb.trk50(msg), "degrees") _print("Track rate", commb.rtrk50(msg), "degree/second") _print("Ground speed", commb.gs50(msg), "knots") _print("True airspeed", commb.tas50(msg), "knots") if BDS == "BDS60": _print("Megnatic Heading", commb.hdg60(msg), "degrees") _print("Indicated airspeed", commb.ias60(msg), "knots") _print("Mach number", commb.mach60(msg)) _print("Vertical rate (Baro)", commb.vr60baro(msg), "feet/minute") _print("Vertical rate (INS)", commb.vr60ins(msg), "feet/minute") if BDS == "BDS44": _print("Wind speed", commb.wind44(msg)[0], "knots") _print("Wind direction", commb.wind44(msg)[1], "degrees") _print("Temperature 1", commb.temp44(msg)[0], "Celsius") _print("Temperature 2", commb.temp44(msg)[1], "Celsius") _print("Pressure", commb.p44(msg), "hPa") _print("Humidity", commb.hum44(msg), "%") _print("Turbulence", commb.turb44(msg)) if BDS == "BDS45": _print("Turbulence", commb.turb45(msg)) _print("Wind shear", commb.ws45(msg)) _print("Microbust", commb.mb45(msg)) _print("Icing", commb.ic45(msg)) _print("Wake vortex", commb.wv45(msg)) _print("Temperature", commb.temp45(msg), "Celsius") _print("Pressure", commb.p45(msg), "hPa") _print("Radio height", commb.rh45(msg), "feet")
def wrapper(msg): df = common.df(msg) if df not in [4, 5]: raise RuntimeError( "Incorrect downlink format, expect 4 or 5, got {}".format(df)) return func(msg)
def get_all(msg: str) -> dict: from pyModeS import common, adsb, commb, bds _dict = {} def push(key, data, unit=None): _dict[key] = data df = common.df(msg) icao = common.icao(msg) push("message", msg) push("icao", icao) push("downlink_format", df) if df == 17: push("protocol", "Mode-S Extended Squitter (ADS-B)") tc = common.typecode(msg) if 1 <= tc <= 4: # callsign callsign = adsb.callsign(msg) push("type", "Identitification and category") push("callsign:", callsign) if 5 <= tc <= 8: # surface position push("type", "Surface position") oe = adsb.oe_flag(msg) msgbin = common.hex2bin(msg) cprlat = common.bin2int(msgbin[54:71]) / 131072.0 cprlon = common.bin2int(msgbin[71:88]) / 131072.0 v = adsb.surface_velocity(msg) push("cpr_format", "Odd" if oe else "Even") push("cpr_latitude", cprlat) push("cpr_longitude", cprlon) push("speed", v[0] * 1.85200, "km") push("track", v[1], "degrees") if 9 <= tc <= 18: # airborne position push("type", "Airborne position (with barometric altitude)") alt = adsb.altitude(msg) oe = adsb.oe_flag(msg) msgbin = common.hex2bin(msg) cprlat = common.bin2int(msgbin[54:71]) / 131072.0 cprlon = common.bin2int(msgbin[71:88]) / 131072.0 push("cpr_format", "Odd" if oe else "Even") push("cpr_latitude", cprlat) push("cpr_longitude", cprlon) push("altitude", alt, "feet") if tc == 19: push("type", "Airborne velocity") spd, trk, vr, t = adsb.velocity(msg) types = {"GS": "Ground speed", "TAS": "True airspeed"} push("speed", spd * 1.85200, "km") push("track", trk, "degrees") push("vertical rate", vr, "feet/minute") push("type", types[t]) if 20 <= tc <= 22: # airborne position push("type", "Airborne position (with GNSS altitude)") alt = adsb.altitude(msg) oe = adsb.oe_flag(msg) msgbin = common.hex2bin(msg) cprlat = common.bin2int(msgbin[54:71]) / 131072.0 cprlon = common.bin2int(msgbin[71:88]) / 131072.0 push("cpr_format", "Odd" if oe else "Even") push("cpr_latitude", cprlat) push("cpr_longitude", cprlon) push("altitude", alt, "feet") if tc == 29: # target state and status push("type", "Target State and Status") subtype = common.bin2int((common.hex2bin(msg)[32:])[5:7]) push("subtype", subtype) tcas_operational = adsb.tcas_operational(msg) types = {0: "Not Engaged", 1: "Engaged"} tcas_operational_types = {0: "Not Operational", 1: "Operational"} if subtype == 0: emergency_types = { 0: "No emergency", 1: "General emergency", 2: "Lifeguard/medical emergency", 3: "Minimum fuel", 4: "No communications", 5: "Unlawful interference", 6: "Downed aircraft", 7: "Reserved" } vertical_horizontal_types = { 1: "Acquiring mode", 2: "Capturing/Maintaining mode" } tcas_ra_types = {0: "Not active", 1: "Active"} altitude = adsb.target_altitude(msg) if altitude is not None: alt, alt_source, alt_ref = altitude angle, angle_type, angle_source = adsb.target_angle(msg) vertical_mode = adsb.vertical_mode(msg) horizontal_mode = adsb.horizontal_mode(msg) tcas_ra = adsb.tcas_ra(msg) emergency_status = adsb.emergency_status(msg) push("target_altitude", alt, "feet") push("altitude_source", alt_source) push("altitude_reference", alt_ref) push("angle", angle, "°") push("angle Type", angle_type) push("angle Source", angle_source) push("vertical mode", vertical_horizontal_types[vertical_mode]) push("horizontal mode", vertical_horizontal_types[horizontal_mode]) push("TCAS/ACAS", tcas_operational_types[tcas_operational]) push("TCAS/ACAS_RA", tcas_ra_types[tcas_ra]) push("emergency_status", emergency_types[emergency_status]) else: alt, alt_source = adsb.selected_altitude(msg) baro = adsb.baro_pressure_setting(msg) hdg = adsb.selected_heading(msg) autopilot = adsb.autopilot(msg) vnav = adsb.vnav_mode(msg) alt_hold = adsb.altitude_hold_mode(msg) app = adsb.approach_mode(msg) lnav = adsb.lnav_mode(msg) push("selected_altitude", alt, "feet") push("altitude_source", alt_source) push("barometric_pressure_setting", baro, "millibars") push("selected_Heading", hdg, "°") if not (common.bin2int((common.hex2bin(msg)[32:])[46]) == 0): push("autopilot", types[autopilot]) push("VNAV_mode", types[vnav]) push("altitude_hold_mode", types[alt_hold]) push("approach_mode", types[app]) push("TCAS/ACAS", tcas_operational_types[tcas_operational]) push("LNAV_mode", types[lnav]) if df == 20: push("protocol", "Mode-S Comm-B altitude reply") push("altitude", common.altcode(msg), "feet") if df == 21: push("protocol", "Mode-S Comm-B identity reply") push("squawk_code", common.idcode(msg)) if df == 20 or df == 21: labels = { "BDS10": "Data link capability", "BDS17": "GICB capability", "BDS20": "Aircraft identification", "BDS30": "ACAS resolution", "BDS40": "Vertical intention report", "BDS50": "Track and turn report", "BDS60": "Heading and speed report", "BDS44": "Meteorological routine air report", "BDS45": "Meteorological hazard report", "EMPTY": "[No information available]", } BDS = bds.infer(msg, mrar=True) if BDS in labels.keys(): push("BDS", "%s (%s)" % (BDS, labels[BDS])) else: push("BDS", BDS) if BDS == "BDS20": callsign = commb.cs20(msg) push("callsign", callsign) if BDS == "BDS40": push("MCP_target_alt", commb.selalt40mcp(msg), "feet") push("FMS_Target_alt", commb.selalt40fms(msg), "feet") push("pressure", commb.p40baro(msg), "millibar") if BDS == "BDS50": push("roll_angle", commb.roll50(msg), "degrees") push("track_angle", commb.trk50(msg), "degrees") push("track_rate", commb.rtrk50(msg), "degree/second") push("ground_speed", commb.gs50(msg) * 1.85200, "km") push("true_airspeed", commb.tas50(msg) * 1.85200, "km") if BDS == "BDS60": push("megnatic Heading", commb.hdg60(msg), "degrees") push("indicated airspeed", commb.ias60(msg) * 1.85200, "km") push("mach number", commb.mach60(msg)) push("vertical rate (Baro)", commb.vr60baro(msg), "feet/minute") push("vertical rate (INS)", commb.vr60ins(msg), "feet/minute") if BDS == "BDS44": push("wind_speed", commb.wind44(msg)[0] * 1.85200, "km") push("wind_direction", commb.wind44(msg)[1], "degrees") push("temperature_1", commb.temp44(msg)[0], "Celsius") push("temperature_2", commb.temp44(msg)[1], "Celsius") push("pressure", commb.p44(msg), "hPa") push("humidity", commb.hum44(msg), "%") push("turbulence", commb.turb44(msg)) if BDS == "BDS45": push("turbulence", commb.turb45(msg)) push("wind_shear", commb.ws45(msg)) push("microbust", commb.mb45(msg)) push("icing", commb.ic45(msg)) push("wake_vortex", commb.wv45(msg)) push("temperature", commb.temp45(msg), "Celsius") push("pressure", commb.p45(msg), "hPa") push("radio_height", commb.rh45(msg), "feet") return _dict