Merge pull request #98 from TimA346/implement_tc29
Decoder for ADS-B TC=29 (target state and status message)
This commit is contained in:
commit
83e22892ba
@ -71,6 +71,68 @@ def tell(msg: str) -> None:
|
|||||||
_print("CPR Longitude", cprlon)
|
_print("CPR Longitude", cprlon)
|
||||||
_print("Altitude", alt, "feet")
|
_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:
|
if df == 20:
|
||||||
_print("Protocol", "Mode-S Comm-B altitude reply")
|
_print("Protocol", "Mode-S Comm-B altitude reply")
|
||||||
_print("Altitude", common.altcode(msg), "feet")
|
_print("Altitude", common.altcode(msg), "feet")
|
||||||
|
@ -29,6 +29,23 @@ from pyModeS.decoder.bds.bds06 import (
|
|||||||
from pyModeS.decoder.bds.bds08 import category, callsign
|
from pyModeS.decoder.bds.bds08 import category, callsign
|
||||||
from pyModeS.decoder.bds.bds09 import airborne_velocity, altitude_diff
|
from pyModeS.decoder.bds.bds09 import airborne_velocity, altitude_diff
|
||||||
from pyModeS.decoder.bds.bds61 import is_emergency, emergency_state, emergency_squawk
|
from pyModeS.decoder.bds.bds61 import is_emergency, emergency_state, emergency_squawk
|
||||||
|
from pyModeS.decoder.bds.bds62 import (
|
||||||
|
selected_altitude,
|
||||||
|
selected_heading,
|
||||||
|
target_altitude,
|
||||||
|
target_angle,
|
||||||
|
tcas_operational,
|
||||||
|
tcas_ra,
|
||||||
|
baro_pressure_setting,
|
||||||
|
vertical_mode,
|
||||||
|
horizontal_mode,
|
||||||
|
vnav_mode,
|
||||||
|
lnav_mode,
|
||||||
|
autopilot,
|
||||||
|
altitude_hold_mode,
|
||||||
|
approach_mode,
|
||||||
|
emergency_status
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def df(msg):
|
def df(msg):
|
||||||
|
@ -38,6 +38,7 @@ from pyModeS.decoder.bds import (
|
|||||||
bds50,
|
bds50,
|
||||||
bds53,
|
bds53,
|
||||||
bds60,
|
bds60,
|
||||||
|
bds62
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
474
pyModeS/decoder/bds/bds62.py
Normal file
474
pyModeS/decoder/bds/bds62.py
Normal file
@ -0,0 +1,474 @@
|
|||||||
|
# ------------------------------------------
|
||||||
|
# BDS 6,2
|
||||||
|
# ADS-B TC=29
|
||||||
|
# Target State and Status
|
||||||
|
# ------------------------------------------
|
||||||
|
|
||||||
|
from pyModeS import common
|
||||||
|
|
||||||
|
def selected_altitude(msg):
|
||||||
|
"""Decode selected altitude.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg (str): 28 hexdigits string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: Selected altitude (ft)
|
||||||
|
string: Source ('MCP/FCU' or 'FMS')
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
if common.typecode(msg) != 29:
|
||||||
|
raise RuntimeError("%s: Not a target state and status message, expecting TC=29" % msg)
|
||||||
|
|
||||||
|
mb = common.hex2bin(msg)[32:]
|
||||||
|
|
||||||
|
subtype = common.bin2int(mb[5:7])
|
||||||
|
|
||||||
|
if subtype == 0:
|
||||||
|
raise RuntimeError("%s: ADS-B version 1 target state and status message does not contain selected altitude, use target altitude instead" % msg)
|
||||||
|
|
||||||
|
alt = common.bin2int(mb[9:20])
|
||||||
|
alt = None if alt == 0 else (alt - 1) * 32
|
||||||
|
alt_source = "MCP/FCU" if int(mb[8]) == 0 else "FMS"
|
||||||
|
|
||||||
|
return alt, alt_source
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def target_altitude(msg):
|
||||||
|
"""Decode target altitude.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg (str): 28 hexdigits string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: Target altitude (ft)
|
||||||
|
string: Source ('MCP/FCU', 'Holding mode' or 'FMS/RNAV')
|
||||||
|
string: Altitude reference, either pressure altitude or barometric corrected altitude ('FL' or 'MSL')
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
if common.typecode(msg) != 29:
|
||||||
|
raise RuntimeError("%s: Not a target state and status message, expecting TC=29" % msg)
|
||||||
|
|
||||||
|
mb = common.hex2bin(msg)[32:]
|
||||||
|
|
||||||
|
subtype = common.bin2int(mb[5:7])
|
||||||
|
|
||||||
|
if subtype == 1:
|
||||||
|
raise RuntimeError("%s: ADS-B version 2 target state and status message does not contain target altitude, use selected altitude instead" % msg)
|
||||||
|
|
||||||
|
alt_avail = common.bin2int(mb[7:9])
|
||||||
|
if alt_avail == 0:
|
||||||
|
return None
|
||||||
|
elif alt_avail == 1:
|
||||||
|
alt_source = "MCP/FCU"
|
||||||
|
elif alt_avail == 2:
|
||||||
|
alt_source = "Holding mode"
|
||||||
|
else:
|
||||||
|
alt_source = "FMS/RNAV"
|
||||||
|
|
||||||
|
alt_ref = "FL" if int(mb[9]) == 0 else "MSL"
|
||||||
|
|
||||||
|
alt = -1000 + common.bin2int(mb[15:25]) * 100
|
||||||
|
|
||||||
|
return alt, alt_source, alt_ref
|
||||||
|
|
||||||
|
|
||||||
|
def vertical_mode(msg):
|
||||||
|
"""Decode vertical mode.
|
||||||
|
|
||||||
|
Value Meaning
|
||||||
|
----- -----------------------
|
||||||
|
1 "Acquiring" mode
|
||||||
|
2 "Capturing" or "Maintaining" mode
|
||||||
|
3 Reserved
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg (str): 28 hexdigits string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: Vertical mode
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
if common.typecode(msg) != 29:
|
||||||
|
raise RuntimeError("%s: Not a target state and status message, expecting TC=29" % msg)
|
||||||
|
|
||||||
|
mb = common.hex2bin(msg)[32:]
|
||||||
|
|
||||||
|
subtype = common.bin2int(mb[5:7])
|
||||||
|
|
||||||
|
if subtype == 1:
|
||||||
|
raise RuntimeError("%s: ADS-B version 2 target state and status message does not contain vertical mode, use vnav mode instead" % msg)
|
||||||
|
|
||||||
|
vertical_mode = common.bin2int(mb[13:15])
|
||||||
|
if vertical_mode == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return vertical_mode
|
||||||
|
|
||||||
|
|
||||||
|
def horizontal_mode(msg):
|
||||||
|
"""Decode horizontal mode.
|
||||||
|
|
||||||
|
Value Meaning
|
||||||
|
----- -----------------------
|
||||||
|
1 "Acquiring" mode
|
||||||
|
2 "Capturing" or "Maintaining" mode
|
||||||
|
3 Reserved
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg (str): 28 hexdigits string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: Horizontal mode
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
if common.typecode(msg) != 29:
|
||||||
|
raise RuntimeError("%s: Not a target state and status message, expecting TC=29" % msg)
|
||||||
|
|
||||||
|
mb = common.hex2bin(msg)[32:]
|
||||||
|
|
||||||
|
subtype = common.bin2int(mb[5:7])
|
||||||
|
|
||||||
|
if subtype == 1:
|
||||||
|
raise RuntimeError("%s: ADS-B version 2 target state and status message does not contain horizontal mode, use lnav mode instead" % msg)
|
||||||
|
|
||||||
|
horizontal_mode = common.bin2int(mb[25:27])
|
||||||
|
if horizontal_mode == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return horizontal_mode
|
||||||
|
|
||||||
|
|
||||||
|
def selected_heading(msg):
|
||||||
|
"""Decode selected heading.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg (str): 28 bytes hexadecimal message string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
float: Selected heading (degree)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
if common.typecode(msg) != 29:
|
||||||
|
raise RuntimeError("%s: Not a target state and status message, expecting TC=29" % msg)
|
||||||
|
|
||||||
|
mb = common.hex2bin(msg)[32:]
|
||||||
|
|
||||||
|
subtype = common.bin2int(mb[5:7])
|
||||||
|
|
||||||
|
if subtype == 0:
|
||||||
|
raise RuntimeError("%s: ADS-B version 1 target state and status message does not contain selected heading, use target angle instead" % msg)
|
||||||
|
|
||||||
|
if int(mb[29]) == 0:
|
||||||
|
hdg = None
|
||||||
|
else:
|
||||||
|
hdg_sign = int(mb[30])
|
||||||
|
hdg = (hdg_sign+1) * common.bin2int(mb[31:39]) * (180/256)
|
||||||
|
hdg = round(hdg, 2)
|
||||||
|
|
||||||
|
return hdg
|
||||||
|
|
||||||
|
|
||||||
|
def target_angle(msg):
|
||||||
|
"""Decode target heading/track angle.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg (str): 28 bytes hexadecimal message string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: Target angle (degree)
|
||||||
|
string: Angle type ('Heading' or 'Track')
|
||||||
|
string: Source ('MCP/FCU', 'Autopilot Mode' or 'FMS/RNAV')
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
if common.typecode(msg) != 29:
|
||||||
|
raise RuntimeError("%s: Not a target state and status message, expecting TC=29" % msg)
|
||||||
|
|
||||||
|
mb = common.hex2bin(msg)[32:]
|
||||||
|
|
||||||
|
subtype = common.bin2int(mb[5:7])
|
||||||
|
|
||||||
|
if subtype == 1:
|
||||||
|
raise RuntimeError("%s: ADS-B version 2 target state and status message does not contain target angle, use selected heading instead" % msg)
|
||||||
|
|
||||||
|
angle_avail = common.bin2int(mb[25:27])
|
||||||
|
if angle_avail == 0:
|
||||||
|
angle = None
|
||||||
|
else:
|
||||||
|
angle = common.bin2int(mb[27:36])
|
||||||
|
|
||||||
|
if angle_avail == 1:
|
||||||
|
angle_source = "MCP/FCU"
|
||||||
|
elif angle_avail == 2:
|
||||||
|
angle_source = "Autopilot mode"
|
||||||
|
else:
|
||||||
|
angle_source = "FMS/RNAV"
|
||||||
|
|
||||||
|
angle_type = "Heading" if int(mb[36]) else "Track"
|
||||||
|
|
||||||
|
return angle, angle_type, angle_source
|
||||||
|
|
||||||
|
|
||||||
|
def baro_pressure_setting(msg):
|
||||||
|
"""Decode barometric pressure setting.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg (str): 28 hexdigits string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
float: Barometric pressure setting (millibars)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
if common.typecode(msg) != 29:
|
||||||
|
raise RuntimeError("%s: Not a target state and status message, expecting TC=29" % msg)
|
||||||
|
|
||||||
|
mb = common.hex2bin(msg)[32:]
|
||||||
|
|
||||||
|
subtype = common.bin2int(mb[5:7])
|
||||||
|
|
||||||
|
if subtype == 0:
|
||||||
|
raise RuntimeError("%s: ADS-B version 1 target state and status message does not contain barometric pressure setting" % msg)
|
||||||
|
|
||||||
|
baro = common.bin2int(mb[20:29])
|
||||||
|
baro = None if baro == 0 else 800 + (baro - 1) * 0.8
|
||||||
|
baro = round(baro, 1)
|
||||||
|
|
||||||
|
return baro
|
||||||
|
|
||||||
|
def autopilot(msg) -> bool:
|
||||||
|
"""Decode autopilot engagement.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg (str): 28 hexdigits string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: Autopilot engaged
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
if common.typecode(msg) != 29:
|
||||||
|
raise RuntimeError("%s: Not a target state and status message, expecting TC=29" % msg)
|
||||||
|
|
||||||
|
mb = common.hex2bin(msg)[32:]
|
||||||
|
|
||||||
|
subtype = common.bin2int(mb[5:7])
|
||||||
|
|
||||||
|
if subtype == 0:
|
||||||
|
raise RuntimeError("%s: ADS-B version 1 target state and status message does not contain autopilot engagement" % msg)
|
||||||
|
|
||||||
|
if int(mb[46]) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
autopilot = True if int(mb[47]) == 1 else False
|
||||||
|
|
||||||
|
return autopilot
|
||||||
|
|
||||||
|
def vnav_mode(msg) -> bool:
|
||||||
|
"""Decode VNAV mode.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg (str): 28 hexdigits string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: VNAV mode engaged
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
if common.typecode(msg) != 29:
|
||||||
|
raise RuntimeError("%s: Not a target state and status message, expecting TC=29" % msg)
|
||||||
|
|
||||||
|
mb = common.hex2bin(msg)[32:]
|
||||||
|
|
||||||
|
subtype = common.bin2int(mb[5:7])
|
||||||
|
|
||||||
|
if subtype == 0:
|
||||||
|
raise RuntimeError("%s: ADS-B version 1 target state and status message does not contain vnav mode, use vertical mode instead" % msg)
|
||||||
|
|
||||||
|
if int(mb[46]) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
vnav_mode = True if int(mb[48]) == 1 else False
|
||||||
|
|
||||||
|
return vnav_mode
|
||||||
|
|
||||||
|
|
||||||
|
def altitude_hold_mode(msg) -> bool:
|
||||||
|
"""Decode altitude hold mode.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg (str): 28 hexdigits string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: Altitude hold mode engaged
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
if common.typecode(msg) != 29:
|
||||||
|
raise RuntimeError("%s: Not a target state and status message, expecting TC=29" % msg)
|
||||||
|
|
||||||
|
mb = common.hex2bin(msg)[32:]
|
||||||
|
|
||||||
|
subtype = common.bin2int(mb[5:7])
|
||||||
|
|
||||||
|
if subtype == 0:
|
||||||
|
raise RuntimeError("%s: ADS-B version 1 target state and status message does not contain altitude hold mode" % msg)
|
||||||
|
|
||||||
|
if int(mb[46]) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
alt_hold_mode = True if int(mb[49]) == 1 else False
|
||||||
|
|
||||||
|
return alt_hold_mode
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def approach_mode(msg) -> bool:
|
||||||
|
"""Decode approach mode.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg (str): 28 hexdigits string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: Approach mode engaged
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
if common.typecode(msg) != 29:
|
||||||
|
raise RuntimeError("%s: Not a target state and status message, expecting TC=29" % msg)
|
||||||
|
|
||||||
|
mb = common.hex2bin(msg)[32:]
|
||||||
|
|
||||||
|
subtype = common.bin2int(mb[5:7])
|
||||||
|
|
||||||
|
if subtype == 0:
|
||||||
|
raise RuntimeError("%s: ADS-B version 1 target state and status message does not contain approach mode" % msg)
|
||||||
|
|
||||||
|
if int(mb[46]) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
app_mode = True if int(mb[51]) == 1 else False
|
||||||
|
|
||||||
|
return app_mode
|
||||||
|
|
||||||
|
|
||||||
|
def lnav_mode(msg) -> bool:
|
||||||
|
"""Decode LNAV mode.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg (str): 28 hexdigits string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: LNAV mode engaged
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
if common.typecode(msg) != 29:
|
||||||
|
raise RuntimeError("%s: Not a target state and status message, expecting TC=29" % msg)
|
||||||
|
|
||||||
|
mb = common.hex2bin(msg)[32:]
|
||||||
|
|
||||||
|
subtype = common.bin2int(mb[5:7])
|
||||||
|
|
||||||
|
if subtype == 0:
|
||||||
|
raise RuntimeError("%s: ADS-B version 1 target state and status message does not contain lnav mode, use horizontal mode instead" % msg)
|
||||||
|
|
||||||
|
if int(mb[46]) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
lnav_mode = True if int(mb[53]) == 1 else False
|
||||||
|
|
||||||
|
return lnav_mode
|
||||||
|
|
||||||
|
|
||||||
|
def tcas_operational(msg) -> bool:
|
||||||
|
"""Decode TCAS/ACAS operational.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg (str): 28 bytes hexadecimal message string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: TCAS/ACAS operational
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
if common.typecode(msg) != 29:
|
||||||
|
raise RuntimeError("%s: Not a target state and status message, expecting TC=29" % msg)
|
||||||
|
|
||||||
|
mb = common.hex2bin(msg)[32:]
|
||||||
|
|
||||||
|
subtype = common.bin2int(mb[5:7])
|
||||||
|
|
||||||
|
if subtype == 0:
|
||||||
|
tcas = True if int(mb[51]) == 0 else False
|
||||||
|
else:
|
||||||
|
tcas = True if int(mb[52]) == 1 else False
|
||||||
|
|
||||||
|
return tcas
|
||||||
|
|
||||||
|
def tcas_ra(msg) -> bool:
|
||||||
|
"""Decode TCAS/ACAS Resolution advisory.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg (str): 28 bytes hexadecimal message string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: TCAS/ACAS Resolution advisory active
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
if common.typecode(msg) != 29:
|
||||||
|
raise RuntimeError("%s: Not a target state and status message, expecting TC=29" % msg)
|
||||||
|
|
||||||
|
mb = common.hex2bin(msg)[32:]
|
||||||
|
|
||||||
|
subtype = common.bin2int(mb[5:7])
|
||||||
|
|
||||||
|
if subtype == 1:
|
||||||
|
raise RuntimeError("%s: ADS-B version 2 target state and status message does not contain TCAS/ACAS RA" % msg)
|
||||||
|
|
||||||
|
tcas_ra = True if int(mb[52]) == 1 else False
|
||||||
|
|
||||||
|
return tcas_ra
|
||||||
|
|
||||||
|
|
||||||
|
def emergency_status(msg) -> int:
|
||||||
|
"""Decode aircraft emergency status.
|
||||||
|
|
||||||
|
Value Meaning
|
||||||
|
----- -----------------------
|
||||||
|
0 No emergency
|
||||||
|
1 General emergency
|
||||||
|
2 Lifeguard/medical emergency
|
||||||
|
3 Minimum fuel
|
||||||
|
4 No communications
|
||||||
|
5 Unlawful interference
|
||||||
|
6 Downed aircraft
|
||||||
|
7 Reserved
|
||||||
|
|
||||||
|
Args:
|
||||||
|
msg (str): 28 bytes hexadecimal message string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: Emergency status
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
if common.typecode(msg) != 29:
|
||||||
|
raise RuntimeError("%s: Not a target state and status message, expecting TC=29" % msg)
|
||||||
|
|
||||||
|
mb = common.hex2bin(msg)[32:]
|
||||||
|
|
||||||
|
subtype = common.bin2int(mb[5:7])
|
||||||
|
|
||||||
|
if subtype == 1:
|
||||||
|
raise RuntimeError("%s: ADS-B version 2 target state and status message does not contain emergency status" % msg)
|
||||||
|
|
||||||
|
return common.bin2int(mb[53:56])
|
@ -86,6 +86,20 @@ def test_adsb_emergency():
|
|||||||
assert adsb.emergency_squawk("8DA2C1B6E112B600000000760759") == "6615"
|
assert adsb.emergency_squawk("8DA2C1B6E112B600000000760759") == "6615"
|
||||||
|
|
||||||
|
|
||||||
|
def test_adsb_target_state_status():
|
||||||
|
sel_alt = adsb.selected_altitude("8DA05629EA21485CBF3F8CADAEEB")
|
||||||
|
assert sel_alt == (16992, "MCP/FCU")
|
||||||
|
assert adsb.baro_pressure_setting("8DA05629EA21485CBF3F8CADAEEB") == 1012.8
|
||||||
|
assert adsb.selected_heading("8DA05629EA21485CBF3F8CADAEEB")== 66.8
|
||||||
|
assert adsb.autopilot("8DA05629EA21485CBF3F8CADAEEB") == True
|
||||||
|
assert adsb.vnav_mode("8DA05629EA21485CBF3F8CADAEEB") == True
|
||||||
|
assert adsb.altitude_hold_mode("8DA05629EA21485CBF3F8CADAEEB") == False
|
||||||
|
assert adsb.approach_mode("8DA05629EA21485CBF3F8CADAEEB") == False
|
||||||
|
assert adsb.tcas_operational("8DA05629EA21485CBF3F8CADAEEB") == True
|
||||||
|
assert adsb.lnav_mode("8DA05629EA21485CBF3F8CADAEEB") == True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# def test_nic():
|
# def test_nic():
|
||||||
# assert adsb.nic('8D3C70A390AB11F55B8C57F65FE6') == 0
|
# assert adsb.nic('8D3C70A390AB11F55B8C57F65FE6') == 0
|
||||||
# assert adsb.nic('8DE1C9738A4A430B427D219C8225') == 1
|
# assert adsb.nic('8DE1C9738A4A430B427D219C8225') == 1
|
||||||
|
Loading…
Reference in New Issue
Block a user