diff --git a/pyModeS/decoder/adsb.py b/pyModeS/decoder/adsb.py index 15d6467..f17fd29 100644 --- a/pyModeS/decoder/adsb.py +++ b/pyModeS/decoder/adsb.py @@ -34,6 +34,7 @@ from pyModeS.decoder.bds.bds06 import ( ) from pyModeS.decoder.bds.bds08 import category, callsign from pyModeS.decoder.bds.bds09 import airborne_velocity, altitude_diff +from pyModeS.decoder.bds.bds61 import is_emergency, emergency, emergency_squawk def df(msg): diff --git a/pyModeS/decoder/bds/bds61.py b/pyModeS/decoder/bds/bds61.py new file mode 100644 index 0000000..495382e --- /dev/null +++ b/pyModeS/decoder/bds/bds61.py @@ -0,0 +1,98 @@ +# ------------------------------------------ +# BDS 6,1 +# ADS-B TC=28 +# Aircraft Airborne status +# ------------------------------------------ + +from __future__ import absolute_import, print_function, division + +from pyModeS import common + + +def is_emergency(msg): + """ + Check if the aircraft is reporting an emergency + Non-emergencies are either a subtype of zero (no information) or + subtype of one and a value of zero (no emergency). + Subtype = 2 indicates an ACAS RA broadcast, look in BDS 3,0 + :param msg: + :return: if the aircraft has declared an emergency + """ + if common.typecode(msg) != 28: + raise RuntimeError("%s: Not an airborne status message, expecting TC=28" % msg) + + mb = common.hex2bin(msg)[32:] + + subtype = common.bin2int(mb[5:8]) + emergency_state = common.bin2int(mb[8:11]) + + if subtype == 2: + raise RuntimeError("%s: Emergency message is ACAS-RA, not implemented") + + if subtype == 0: + return False + elif subtype == 1 and emergency_state == 0: + return False + else: + return True + + +def emergency(msg): + """ + Return the aircraft emergency + + ===== ======= + Value Meaning + ===== ======= + 1 General emergency + 2 Lifeguard/Medical + 3 Minimum fuel + 4 No communications + 5 Unlawful communications + 6 Reserved + 7 Reserved + :param msg: + :return: If the aircraft has declared an emergency, the type + """ + if not is_emergency(msg): + raise RuntimeError("%s: Aircraft not declared an emergency" % msg) + else: + mb = common.hex2bin(msg)[32:] + + subtype = common.bin2int(mb[5:8]) + emergency_state = common.bin2int(mb[8:11]) + + return emergency_state + + +def emergency_squawk(msg): + """ + Squawk code of the transmitting aircraft + Emergency value 1 will be squawk 7700 + Emergency value 4 will be squawk 7600 + Emergency value 5 will be squawk 7500 + :param msg: + :return: aircraft squawk code + """ + if common.typecode(msg) != 28: + raise RuntimeError("%s: Not an airborne status message, expecting TC=28" % msg) + + mb = common.hex2bin(msg)[32:] + C1 = mb[11] + A1 = mb[12] + C2 = mb[13] + A2 = mb[14] + C4 = mb[15] + A4 = mb[16] + B1 = mb[17] + D1 = mb[18] + B2 = mb[19] + D2 = mb[20] + B4 = mb[21] + D4 = mb[22] + + byte1 = int(A4 + A2 + A1, 2) + byte2 = int(B4 + B2 + B1, 2) + byte3 = int(C4 + C2 + C1, 2) + byte4 = int(D4 + D2 + D1, 2) + return str(byte1) + str(byte2) + str(byte3) + str(byte4) diff --git a/tests/test_adsb.py b/tests/test_adsb.py index 64599ab..45db5fa 100644 --- a/tests/test_adsb.py +++ b/tests/test_adsb.py @@ -80,6 +80,11 @@ def test_adsb_velocity(): assert adsb.altitude_diff("8D485020994409940838175B284F") == 550 +def test_adsb_emergency(): + assert not adsb.is_emergency('8DA2C1B6E112B600000000760759') + assert adsb.emergency_squawk('8DA2C1B6E112B600000000760759') == '6615' + + # def test_nic(): # assert adsb.nic('8D3C70A390AB11F55B8C57F65FE6') == 0 # assert adsb.nic('8DE1C9738A4A430B427D219C8225') == 1