def hdg60(msg): """Megnetic heading of aircraft Args: msg (str): 28 hexdigits string Returns: float: heading in degrees to megnetic north (from 0 to 360) """ d = common.hex2bin(common.data(msg)) if d[0] == "0": return None sign = int(d[1]) # 1 -> west value = common.bin2int(d[2:12]) if sign: value = value - 1024 hdg = value * 90 / 512 # degree # convert from [-180, 180] to [0, 360] if hdg < 0: hdg = 360 + hdg return round(hdg, 3)
def is20(msg): """Check if a message is likely to be BDS code 2,0 Args: msg (str): 28 hexdigits string Returns: bool: True or False """ if common.allzeros(msg): return False d = common.hex2bin(common.data(msg)) if d[0:8] != "00100000": return False # allow empty callsign if common.bin2int(d[8:56]) == 0 return True if "#" in cs20(msg): return False return True
def temp44(msg): """Static air temperature. Args: msg (str): 28 hexdigits string Returns: float, float: temperature and alternative temperature in Celsius degree. Note: Two values returns due to what seems to be an inconsistency error in ICAO 9871 (2008) Appendix A-67. """ d = common.hex2bin(common.data(msg)) sign = int(d[23]) value = common.bin2int(d[24:34]) if sign: value = value - 1024 temp = value * 0.25 # celsius temp = round(temp, 2) temp_alternative = value * 0.125 # celsius temp_alternative = round(temp_alternative, 3) return temp, temp_alternative
def is10(msg): """Check if a message is likely to be BDS code 1,0 Args: msg (str): 28 hexdigits string Returns: bool: True or False """ if common.allzeros(msg): return False d = common.hex2bin(common.data(msg)) # first 8 bits must be 0x10 if d[0:8] != "00010000": return False # bit 10 to 14 are reserved if common.bin2int(d[9:14]) != 0: return False # overlay capability conflict if d[14] == "1" and common.bin2int(d[16:23]) < 5: return False if d[14] == "0" and common.bin2int(d[16:23]) > 4: return False return True
def trk50(msg): """True track angle, BDS 5,0 message Args: msg (str): 28 hexdigits string Returns: float: angle in degrees to true north (from 0 to 360) """ d = common.hex2bin(common.data(msg)) if d[11] == "0": return None sign = int(d[12]) # 1 -> west value = common.bin2int(d[13:23]) if sign: value = value - 1024 trk = value * 90.0 / 512.0 # convert from [-180, 180] to [0, 360] if trk < 0: trk = 360 + trk return round(trk, 3)
def is17(msg): """Check if a message is likely to be BDS code 1,7 Args: msg (String): 28 bytes hexadecimal message string Returns: bool: True or False """ if common.allzeros(msg): return False d = common.hex2bin(common.data(msg)) if common.bin2int(d[28:56]) != 0: return False caps = cap17(msg) # basic BDS codes for ADS-B shall be supported # assuming ADS-B out is installed (2017EU/2020US mandate) # if not set(['BDS05', 'BDS06', 'BDS08', 'BDS09', 'BDS20']).issubset(caps): # return False # at least you can respond who you are if "BDS20" not in caps: return False return True
def hdg53(msg): """Magnetic heading, BDS 5,3 message Args: msg (String): 28 bytes hexadecimal message (BDS53) string Returns: float: angle in degrees to true north (from 0 to 360) """ d = common.hex2bin(common.data(msg)) if d[0] == "0": return None sign = int(d[1]) # 1 -> west value = common.bin2int(d[2:12]) if sign: value = value - 1024 hdg = value * 90.0 / 512.0 # degree # convert from [-180, 180] to [0, 360] if hdg < 0: hdg = 360 + hdg return round(hdg, 3)
def is30(msg): """Check if a message is likely to be BDS code 2,0 Args: msg (str): 28 hexdigits string Returns: bool: True or False """ if common.allzeros(msg): return False d = common.hex2bin(common.data(msg)) if d[0:8] != "00110000": return False # threat type 3 not assigned if d[28:30] == "11": return False # reserved for ACAS III, in far future if common.bin2int(d[15:22]) >= 48: return False return True
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 ovc10(msg): """Return the overlay control capability Args: msg (str): 28 hexdigits string Returns: int: Whether the transponder is OVC capable """ d = common.hex2bin(common.data(msg)) return int(d[14])
def ovc10(msg): """Return the overlay control capability Args: msg (String): 28 bytes hexadecimal message string Returns: int: Whether the transponder is OVC capable """ d = common.hex2bin(common.data(msg)) return int(d[14])
def is45(msg): """Check if a message is likely to be BDS code 4,5. Meteorological hazard report 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, 4, 7, 10, 13, 16, 27, 39 if common.wrongstatus(d, 1, 2, 3): return False if common.wrongstatus(d, 4, 5, 6): return False if common.wrongstatus(d, 7, 8, 9): return False if common.wrongstatus(d, 10, 11, 12): return False if common.wrongstatus(d, 13, 14, 15): return False if common.wrongstatus(d, 16, 17, 26): return False if common.wrongstatus(d, 27, 28, 38): return False if common.wrongstatus(d, 39, 40, 51): return False # reserved if common.bin2int(d[51:56]) != 0: return False temp = temp45(msg) if temp: if temp > 60 or temp < -80: return False return True
def is53(msg): """Check if a message is likely to be BDS code 5,3 (Air-referenced state vector) Args: msg (String): 28 bytes hexadecimal message string Returns: bool: True or False """ if common.allzeros(msg): return False d = common.hex2bin(common.data(msg)) # status bit 1, 13, 24, 34, 47 if common.wrongstatus(d, 1, 3, 12): return False if common.wrongstatus(d, 13, 14, 23): return False if common.wrongstatus(d, 24, 25, 33): return False if common.wrongstatus(d, 34, 35, 46): return False if common.wrongstatus(d, 47, 49, 56): return False ias = ias53(msg) if ias is not None and ias > 500: return False mach = mach53(msg) if mach is not None and mach > 1: return False tas = tas53(msg) if tas is not None and tas > 500: return False vr = vr53(msg) if vr is not None and abs(vr) > 8000: return False return True
def is50(msg): """Check if a message is likely to be BDS code 5,0 (Track and turn report) 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, 12, 24, 35, 46 if common.wrongstatus(d, 1, 3, 11): return False if common.wrongstatus(d, 12, 13, 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 roll = roll50(msg) if (roll is not None) and abs(roll) > 50: return False gs = gs50(msg) if gs is not None and gs > 600: return False tas = tas50(msg) if tas is not None and tas > 500: return False if (gs is not None) and (tas is not None) and (abs(tas - gs) > 200): return False return True
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 return True
def rh45(msg): """Radio height. Args: msg (String): 28 bytes hexadecimal message string Returns: int: radio height in ft """ d = common.hex2bin(common.data(msg)) if d[38] == "0": return None rh = common.bin2int(d[39:51]) * 16 return rh
def rh45(msg): """Radio height. Args: msg (str): 28 hexdigits string Returns: int: radio height in ft """ d = common.hex2bin(common.data(msg)) if d[38] == "0": return None rh = common.bin2int(d[39:51]) * 16 return rh
def p45(msg): """Average static pressure. Args: msg (str): 28 hexdigits string Returns: int: static pressure in hPa """ d = common.hex2bin(common.data(msg)) if d[26] == "0": return None p = common.bin2int(d[27:38]) # hPa return p
def p45(msg): """Average static pressure. Args: msg (String): 28 bytes hexadecimal message string Returns: int: static pressure in hPa """ d = common.hex2bin(common.data(msg)) if d[26] == "0": return None p = common.bin2int(d[27:38]) # hPa return p
def mach60(msg): """Aircraft MACH number Args: msg (str): 28 hexdigits string Returns: float: MACH number """ d = common.hex2bin(common.data(msg)) if d[23] == "0": return None mach = common.bin2int(d[24:34]) * 2.048 / 512.0 return round(mach, 3)
def gs50(msg): """Ground speed, BDS 5,0 message Args: msg (String): 28 bytes hexadecimal message (BDS50) string Returns: int: ground speed in knots """ d = common.hex2bin(common.data(msg)) if d[23] == "0": return None spd = common.bin2int(d[24:34]) * 2 # kts return spd
def mb45(msg): """Microburst. Args: msg (str): 28 hexdigits string Returns: int: Microburst level. 0=NIL, 1=Light, 2=Moderate, 3=Severe """ d = common.hex2bin(common.data(msg)) if d[6] == "0": return None mb = common.bin2int(d[7:9]) return mb
def ws45(msg): """Wind shear. Args: msg (str): 28 hexdigits string Returns: int: Wind shear level. 0=NIL, 1=Light, 2=Moderate, 3=Severe """ d = common.hex2bin(common.data(msg)) if d[3] == "0": return None ws = common.bin2int(d[4:6]) return ws
def tas50(msg): """Aircraft true airspeed, BDS 5,0 message Args: msg (str): 28 hexdigits string Returns: int: true airspeed in knots """ d = common.hex2bin(common.data(msg)) if d[45] == "0": return None tas = common.bin2int(d[46:56]) * 2 # kts return tas
def gs50(msg): """Ground speed, BDS 5,0 message Args: msg (str): 28 hexdigits string Returns: int: ground speed in knots """ d = common.hex2bin(common.data(msg)) if d[23] == "0": return None spd = common.bin2int(d[24:34]) * 2 # kts return spd
def mach53(msg): """MACH number, DBS 5,3 message Args: msg (String): 28 bytes hexadecimal message Returns: float: MACH number """ d = common.hex2bin(common.data(msg)) if d[23] == "0": return None mach = common.bin2int(d[24:33]) * 0.008 return round(mach, 3)
def ias53(msg): """Indicated airspeed, DBS 5,3 message Args: msg (String): 28 bytes hexadecimal message Returns: int: indicated arispeed in knots """ d = common.hex2bin(common.data(msg)) if d[12] == "0": return None ias = common.bin2int(d[13:23]) # knots return ias
def tas53(msg): """Aircraft true airspeed, BDS 5,3 message Args: msg (String): 28 bytes hexadecimal message Returns: float: true airspeed in knots """ d = common.hex2bin(common.data(msg)) if d[33] == "0": return None tas = common.bin2int(d[34:46]) * 0.5 # kts return round(tas, 1)
def ias60(msg): """Indicated airspeed Args: msg (str): 28 hexdigits string Returns: int: indicated airspeed in knots """ d = common.hex2bin(common.data(msg)) if d[12] == "0": return None ias = common.bin2int(d[13:23]) # kts return ias
def tas50(msg): """Aircraft true airspeed, BDS 5,0 message Args: msg (String): 28 bytes hexadecimal message (BDS50) string Returns: int: true airspeed in knots """ d = common.hex2bin(common.data(msg)) if d[45] == "0": return None tas = common.bin2int(d[46:56]) * 2 # kts return tas