From 84c62555674445ed43181b8c3cca998e2fd82b19 Mon Sep 17 00:00:00 2001 From: boringow <62092582+boringow@users.noreply.github.com> Date: Tue, 10 Nov 2020 20:44:32 +0100 Subject: [PATCH 1/7] Update allcall.py Tested, it is all functioning well, I created a new decoder since I couldn't understand yours. It may not be the most optimum, I am quite new into coding so it may no be optimal, but for sure it is working :) Hope you like it! --- pyModeS/decoder/allcall.py | 53 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/pyModeS/decoder/allcall.py b/pyModeS/decoder/allcall.py index 6e296ca..ebd132c 100644 --- a/pyModeS/decoder/allcall.py +++ b/pyModeS/decoder/allcall.py @@ -1,5 +1,54 @@ +from pyModeS import common """ Decoding all call replies DF=11 - -[To be implemented] """ + + +def ipcode(msg): + '''Returns the IP code of the Mode S all-call reply (DF11)''' + binaryraw=common.hex2bin(msg) + PI=binaryraw[-24:] + DATA=binaryraw[:-24] + + Gx='1111111111111010000001001000' + Mx=DATA[::-1].zfill(len(DATA)+24)[::-1] + initialdifference=len(Mx)-len(Gx) + Gx = Gx[::-1].zfill(len(Mx))[::-1] + while len(Mx)>initialdifference: + MSB=Mx[0] + if MSB=='1': + result=int(Mx,2)^int(Gx,2) + Mx = str(bin(result)[2:]) + Gx = Gx.rstrip('0')[::-1].zfill(len(Mx))[::-1] + + else: #If the Mx starts with a 0 + Mx=Mx[1:] + Gx=Gx[:-1] + + SIcode=(int(Mx,2)^int(PI,2)) #Mx is the parity sequence and PI is the last field of the DF11. + return SIcode + + +def capability(msg): + '''return the capability code''' + if common.df(msg) == 11:#check that the msg is DF11 + binaryraw=common.hex2bin(msg) + CA = (int(binaryraw[5:8],2)) + if CA == 0: #level 1 transponder + return 0 + if CA in [1, 2, 3]: #reserved + return None + if CA == 4:#level 2 transponder, ability to set CA to 7 and on ground + return 4 + if CA == 5:#level 2 transponder, ability to set CA to 7 and airborn + return 5 + if CA == 6:#level 2 transponder, ability to set CA to 7 and either airborn on ground + return 6 + if CA == 7:# (either DR field is 0 or FS field is 2,3,4 or 5), and either airborn on ground + return 7 + else: + raise RuntimeError("Incorrect or inconsistent message types") + +def AA(msg): + '''returns the icao code of the aircraft''' + return (msg[2:8]) From 35c0bfa5137c3828341280e33ece3d33334dbefc Mon Sep 17 00:00:00 2001 From: boringow <62092582+boringow@users.noreply.github.com> Date: Thu, 12 Nov 2020 14:46:33 +0100 Subject: [PATCH 2/7] Update allcall.py --- pyModeS/decoder/allcall.py | 75 +++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 21 deletions(-) diff --git a/pyModeS/decoder/allcall.py b/pyModeS/decoder/allcall.py index ebd132c..4e9fdf2 100644 --- a/pyModeS/decoder/allcall.py +++ b/pyModeS/decoder/allcall.py @@ -3,31 +3,61 @@ from pyModeS import common Decoding all call replies DF=11 """ - def ipcode(msg): - '''Returns the IP code of the Mode S all-call reply (DF11)''' - binaryraw=common.hex2bin(msg) - PI=binaryraw[-24:] - DATA=binaryraw[:-24] + if common.df(msg) == 11: # check that the msg is DF11 + '''Returns the IP code of the Mode S all-call reply (DF11)''' + binaryraw=common.hex2bin(msg) + PI=binaryraw[-24:] + DATA=binaryraw[:-24] - Gx='1111111111111010000001001000' - Mx=DATA[::-1].zfill(len(DATA)+24)[::-1] - initialdifference=len(Mx)-len(Gx) - Gx = Gx[::-1].zfill(len(Mx))[::-1] - while len(Mx)>initialdifference: - MSB=Mx[0] - if MSB=='1': - result=int(Mx,2)^int(Gx,2) - Mx = str(bin(result)[2:]) - Gx = Gx.rstrip('0')[::-1].zfill(len(Mx))[::-1] + Gx='1111111111111010000001001000' + Mx=DATA[::-1].zfill(len(DATA)+24)[::-1] + initialdifference=len(Mx)-len(Gx) + Gx = Gx[::-1].zfill(len(Mx))[::-1] + while len(Mx)>initialdifference: + MSB=Mx[0] + if MSB=='1': + result=int(Mx,2)^int(Gx,2) + Mx = str(bin(result)[2:]) + Gx = Gx.rstrip('0')[::-1].zfill(len(Mx))[::-1] - else: #If the Mx starts with a 0 - Mx=Mx[1:] - Gx=Gx[:-1] + else: #If the Mx starts with a 0 + Mx=Mx[1:] + Gx=Gx[:-1] - SIcode=(int(Mx,2)^int(PI,2)) #Mx is the parity sequence and PI is the last field of the DF11. - return SIcode + SIcode=bin(int(Mx,2)^int(PI,2)).zfill(7) #Mx is the parity sequence and PI is the last field of the DF11. + if int(SIcode[0:3],2)>0: + return str("SI" + str(int(SIcode[3:],2))) + else: + return str("II" + str(int(SIcode,2))) + else: + raise RuntimeError("Incorrect or inconsistent message types") +def flight_status(msg): + '''returns the flight status''' + if common.df(msg) == 11: # check that the msg is DF11 + binaryraw=common.hex2bin(msg) + CA = (int(binaryraw[5:8],2)) + if CA in [0, 1, 2, 3, 6, 7]: #reserved + return None + if CA == 4:#level 2 transponder, ability to set CA to 7 and on ground + return "on ground" + if CA == 5:#level 2 transponder, ability to set CA to 7 and airborn + return "airborne" + else: + raise RuntimeError("Incorrect or inconsistent message types") + +def transponder_level(msg): + '''returns the transponder level''' + if common.df(msg) == 11:#check that the msg is DF11 + binaryraw=common.hex2bin(msg) + CA = (int(binaryraw[5:8],2)) + if CA in [1, 2, 3, 4, 5, 6, 7]: #reserved + return 2 + if CA == 0: + return 1 + else: + raise RuntimeError("Incorrect or inconsistent message types") def capability(msg): '''return the capability code''' @@ -51,4 +81,7 @@ def capability(msg): def AA(msg): '''returns the icao code of the aircraft''' - return (msg[2:8]) + if common.df(msg) == 11: # check that the msg is DF11 + return (msg[2:8]) + else: + raise RuntimeError("Incorrect or inconsistent message types") From 4ba900f500f91ddfe53c098ed9ece6df8942fe12 Mon Sep 17 00:00:00 2001 From: boringow <62092582+boringow@users.noreply.github.com> Date: Thu, 12 Nov 2020 14:49:52 +0100 Subject: [PATCH 3/7] Update allcall.py --- pyModeS/decoder/allcall.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyModeS/decoder/allcall.py b/pyModeS/decoder/allcall.py index 4e9fdf2..9ecd194 100644 --- a/pyModeS/decoder/allcall.py +++ b/pyModeS/decoder/allcall.py @@ -3,7 +3,7 @@ from pyModeS import common Decoding all call replies DF=11 """ -def ipcode(msg): +def interrogator_code(msg): if common.df(msg) == 11: # check that the msg is DF11 '''Returns the IP code of the Mode S all-call reply (DF11)''' binaryraw=common.hex2bin(msg) From eacc828b75a19ed62cf7df072e610308d3dbc893 Mon Sep 17 00:00:00 2001 From: boringow <62092582+boringow@users.noreply.github.com> Date: Sat, 14 Nov 2020 09:37:08 +0100 Subject: [PATCH 4/7] Update surv.py I have completed the allcall.py and the surv.py, but I can not commit the two files at the same time. Hope you like how it looks, If necessary, tell me what could I change. Have a nice weekend! --- pyModeS/decoder/surv.py | 117 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/pyModeS/decoder/surv.py b/pyModeS/decoder/surv.py index 746f47f..abda10d 100644 --- a/pyModeS/decoder/surv.py +++ b/pyModeS/decoder/surv.py @@ -1,5 +1,120 @@ """ Warpper for short roll call surveillance replies DF=4/5 -[To be implemented] """ + +from pyModeS import common + +def fs(msg): + '''tell the flight status of the aircraft, returns airborne, ground or None''' + if common.df(msg) in [4,5]: + binaryraw=common.hex2bin(msg) + fs=int(binaryraw[5:8],2) + if fs in [0,2]: + return "airborne" + if fs in [1,3]: + return "ground" + else: + return None + else: + raise RuntimeError("Incorrect or inconsistent message types") + +def alert(msg): + '''returns True if there is an alert, False otherwise ''' + #The alert indicates that the TXPPR Mode A code is changed manually by the pilot. Icao Annex10, Vol IV, 3.1.2.6.10.1.1 + if common.df(msg) in [4,5]: + binaryraw = common.hex2bin(msg) + fs = int(binaryraw[5:8], 2) + if fs in [2,3,4]: + return True + if fs in [0,1,5]: + return False + else: + return None + else: + raise RuntimeError("Incorrect or inconsistent message types") + + +def SPI(msg): + '''returns True if there there is Special Pulse Indicator, False otherwise ''' + if common.df(msg) in [4, 5]: + binaryraw = common.hex2bin(msg) + fs = int(binaryraw[5:8], 2) + if fs in [4, 5]: + return True + if fs in [0, 1, 2, 3]: + return False + else: + return None + else: + raise RuntimeError("Incorrect or inconsistent message types") + +def dr(msg): + '''Returns Downlink Request Status. + Args: + msg (str): 14 hexdigits string, + Returns: + str: Downlink Request Status + ''' + if common.df(msg) in [4,5]: + binaryraw = common.hex2bin(msg) + dr = int(binaryraw[8:13], 2) + if dr in [2,3,6,7]: + return "ACAS" + if dr == 0: + return "no downlink request" + if dr == 1: + return "request to send Comm-B message" + if dr in 4: + return "Comm-B broadcast 1 available" + if dr in 5: + return "Comm-B broadcast 2 available" + if dr > 7 and dr < 16: + return None + else: + return str(15-dr)+" downlink ELM segments available" + else: + raise RuntimeError("Incorrect or inconsistent message types") + +def um(msg): + '''returns the Interrogator Identifier and the type of reservation + Args: + msg (str): 14 hexdigits string, + Returns: + int: II code of the identifier that triggered the reply + str: type of reservation made by the interrogator + ''' + if common.df(msg) in [4,5]: + binaryraw = common.hex2bin(msg) + iis = int(binaryraw[13:17], 2) + ds = int(binaryraw[17:19], 2) + if ds == 0: + ds=None + if ds == 1: + ds='Comm-B' + if ds == 2: + ds='Comm-C' + if ds == 3: + ds='Comm-D' + return iis, ds + + else: + raise RuntimeError("Incorrect or inconsistent message types") + +def ac(msg): + '''return the altitude in ft''' + if common.df(msg) == 4: + binaryraw = common.hex2bin(msg) + altcode = binaryraw[19:32] # Here we could also put the common.altcode(msg). + return common.altitude(altcode) + else: + raise RuntimeError("Incorrect or inconsistent message types") + +def id(msg): + '''return the squawk code (identifier)''' + if common.df(msg) == 5: + binaryraw = common.hex2bin(msg) + altcode = binaryraw[19:32] # Here we could also put the common.idcode(msg). + return common.squawk(altcode) + else: + raise RuntimeError("Incorrect or inconsistent message types") From 668d6580d025b2df436baacd62089a19034484df Mon Sep 17 00:00:00 2001 From: Junzi Sun Date: Sat, 14 Nov 2020 21:57:08 +0100 Subject: [PATCH 5/7] Update allcall.py --- pyModeS/decoder/allcall.py | 140 +++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 76 deletions(-) diff --git a/pyModeS/decoder/allcall.py b/pyModeS/decoder/allcall.py index 9ecd194..5f352f4 100644 --- a/pyModeS/decoder/allcall.py +++ b/pyModeS/decoder/allcall.py @@ -1,87 +1,75 @@ +""" +Decode all-call reply messages, with dowlink format 11 +""" + from pyModeS import common -""" -Decoding all call replies DF=11 -""" -def interrogator_code(msg): - if common.df(msg) == 11: # check that the msg is DF11 - '''Returns the IP code of the Mode S all-call reply (DF11)''' - binaryraw=common.hex2bin(msg) - PI=binaryraw[-24:] - DATA=binaryraw[:-24] - Gx='1111111111111010000001001000' - Mx=DATA[::-1].zfill(len(DATA)+24)[::-1] - initialdifference=len(Mx)-len(Gx) - Gx = Gx[::-1].zfill(len(Mx))[::-1] - while len(Mx)>initialdifference: - MSB=Mx[0] - if MSB=='1': - result=int(Mx,2)^int(Gx,2) - Mx = str(bin(result)[2:]) - Gx = Gx.rstrip('0')[::-1].zfill(len(Mx))[::-1] +def _checkdf(func): + """Ensure downlink format is 11.""" - else: #If the Mx starts with a 0 - Mx=Mx[1:] - Gx=Gx[:-1] + def wrapper(msg): + df = common.df(msg) + if df != 11: + raise RuntimeError( + "Incorrect downlink format, expect 11, got {}".format(df) + ) + return func(msg) - SIcode=bin(int(Mx,2)^int(PI,2)).zfill(7) #Mx is the parity sequence and PI is the last field of the DF11. - if int(SIcode[0:3],2)>0: - return str("SI" + str(int(SIcode[3:],2))) - else: - return str("II" + str(int(SIcode,2))) - else: - raise RuntimeError("Incorrect or inconsistent message types") + return wrapper -def flight_status(msg): - '''returns the flight status''' - if common.df(msg) == 11: # check that the msg is DF11 - binaryraw=common.hex2bin(msg) - CA = (int(binaryraw[5:8],2)) - if CA in [0, 1, 2, 3, 6, 7]: #reserved - return None - if CA == 4:#level 2 transponder, ability to set CA to 7 and on ground - return "on ground" - if CA == 5:#level 2 transponder, ability to set CA to 7 and airborn - return "airborne" - else: - raise RuntimeError("Incorrect or inconsistent message types") -def transponder_level(msg): - '''returns the transponder level''' - if common.df(msg) == 11:#check that the msg is DF11 - binaryraw=common.hex2bin(msg) - CA = (int(binaryraw[5:8],2)) - if CA in [1, 2, 3, 4, 5, 6, 7]: #reserved - return 2 - if CA == 0: - return 1 - else: - raise RuntimeError("Incorrect or inconsistent message types") +@_checkdf +def icao(msg): + """Decode transponder code (ICAO address). + Args: + msg (str): 14 hexdigits string + Returns: + string: ICAO address + + """ + return common.icao(msg) + + +@_checkdf +def interrogator(msg): + """Decode interrogator identifier code. + + Args: + msg (str): 14 hexdigits string + Returns: + int: interrogator identifier code + + """ + # simply the CRC reminder + return common.crc(msg) + + +@_checkdf def capability(msg): - '''return the capability code''' - if common.df(msg) == 11:#check that the msg is DF11 - binaryraw=common.hex2bin(msg) - CA = (int(binaryraw[5:8],2)) - if CA == 0: #level 1 transponder - return 0 - if CA in [1, 2, 3]: #reserved - return None - if CA == 4:#level 2 transponder, ability to set CA to 7 and on ground - return 4 - if CA == 5:#level 2 transponder, ability to set CA to 7 and airborn - return 5 - if CA == 6:#level 2 transponder, ability to set CA to 7 and either airborn on ground - return 6 - if CA == 7:# (either DR field is 0 or FS field is 2,3,4 or 5), and either airborn on ground - return 7 - else: - raise RuntimeError("Incorrect or inconsistent message types") + """Decode transponder capability. -def AA(msg): - '''returns the icao code of the aircraft''' - if common.df(msg) == 11: # check that the msg is DF11 - return (msg[2:8]) + Args: + msg (str): 14 hexdigits string + Returns: + int, str: transponder capability, description + + """ + msgbin = common.hex2bin(msg) + ca = common.bin2int(msgbin[5:8]) + + if ca == 0: + text = "level 1 transponder" + elif ca == 4: + text = "level 2 transponder, ability to set CA to 7, on ground" + elif ca == 5: + text = "level 2 transponder, ability to set CA to 7, airborne" + elif ca == 6: + text = "evel 2 transponder, ability to set CA to 7, either airborne or ground" + elif ca == 7: + text = "Downlink Request value is 0,or the Flight Status is 2, 3, 4 or 5, either airborne or on the ground" else: - raise RuntimeError("Incorrect or inconsistent message types") + text = None + + return ca, text From a3e5e7e1417295187749b86fba5fd5ee4a2ec34d Mon Sep 17 00:00:00 2001 From: Junzi Sun Date: Sat, 14 Nov 2020 21:57:34 +0100 Subject: [PATCH 6/7] Update surv.py --- pyModeS/decoder/surv.py | 228 +++++++++++++++++++++------------------- 1 file changed, 120 insertions(+), 108 deletions(-) diff --git a/pyModeS/decoder/surv.py b/pyModeS/decoder/surv.py index abda10d..ceec90c 100644 --- a/pyModeS/decoder/surv.py +++ b/pyModeS/decoder/surv.py @@ -1,120 +1,132 @@ """ -Warpper for short roll call surveillance replies DF=4/5 - +Decode short roll call surveillance replies, with downlink format 4 or 5 """ from pyModeS import common + +def _checkdf(func): + """Ensure downlink format is 4 or 5.""" + + 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) + + return wrapper + + +@_checkdf def fs(msg): - '''tell the flight status of the aircraft, returns airborne, ground or None''' - if common.df(msg) in [4,5]: - binaryraw=common.hex2bin(msg) - fs=int(binaryraw[5:8],2) - if fs in [0,2]: - return "airborne" - if fs in [1,3]: - return "ground" - else: - return None - else: - raise RuntimeError("Incorrect or inconsistent message types") + """Decode flight status. -def alert(msg): - '''returns True if there is an alert, False otherwise ''' - #The alert indicates that the TXPPR Mode A code is changed manually by the pilot. Icao Annex10, Vol IV, 3.1.2.6.10.1.1 - if common.df(msg) in [4,5]: - binaryraw = common.hex2bin(msg) - fs = int(binaryraw[5:8], 2) - if fs in [2,3,4]: - return True - if fs in [0,1,5]: - return False - else: - return None - else: - raise RuntimeError("Incorrect or inconsistent message types") - - -def SPI(msg): - '''returns True if there there is Special Pulse Indicator, False otherwise ''' - if common.df(msg) in [4, 5]: - binaryraw = common.hex2bin(msg) - fs = int(binaryraw[5:8], 2) - if fs in [4, 5]: - return True - if fs in [0, 1, 2, 3]: - return False - else: - return None - else: - raise RuntimeError("Incorrect or inconsistent message types") - -def dr(msg): - '''Returns Downlink Request Status. - Args: - msg (str): 14 hexdigits string, - Returns: - str: Downlink Request Status - ''' - if common.df(msg) in [4,5]: - binaryraw = common.hex2bin(msg) - dr = int(binaryraw[8:13], 2) - if dr in [2,3,6,7]: - return "ACAS" - if dr == 0: - return "no downlink request" - if dr == 1: - return "request to send Comm-B message" - if dr in 4: - return "Comm-B broadcast 1 available" - if dr in 5: - return "Comm-B broadcast 2 available" - if dr > 7 and dr < 16: - return None - else: - return str(15-dr)+" downlink ELM segments available" - else: - raise RuntimeError("Incorrect or inconsistent message types") - -def um(msg): - '''returns the Interrogator Identifier and the type of reservation Args: - msg (str): 14 hexdigits string, + msg (str): 14 hexdigits string Returns: - int: II code of the identifier that triggered the reply - str: type of reservation made by the interrogator - ''' - if common.df(msg) in [4,5]: - binaryraw = common.hex2bin(msg) - iis = int(binaryraw[13:17], 2) - ds = int(binaryraw[17:19], 2) - if ds == 0: - ds=None - if ds == 1: - ds='Comm-B' - if ds == 2: - ds='Comm-C' - if ds == 3: - ds='Comm-D' - return iis, ds + int, str: flight status, description - else: - raise RuntimeError("Incorrect or inconsistent message types") + """ + msgbin = common.hex2bin(msg) + fs = common.bin2int(msgbin[5:8]) + text = None -def ac(msg): - '''return the altitude in ft''' - if common.df(msg) == 4: - binaryraw = common.hex2bin(msg) - altcode = binaryraw[19:32] # Here we could also put the common.altcode(msg). - return common.altitude(altcode) - else: - raise RuntimeError("Incorrect or inconsistent message types") + if fs == 0: + text = "no alert, no SPI, aircraft is airborne" + elif fs == 1: + text = "no alert, no SPI, aircraft is on-ground" + elif fs == 2: + text = "alert, no SPI, aircraft is airborne" + elif fs == 3: + text = "alert, no SPI, aircraft is on-ground" + elif fs == 4: + text = "alert, SPI, aircraft is airborne or on-ground" + elif fs == 5: + text = "no alert, SPI, aircraft is airborne or on-ground" -def id(msg): - '''return the squawk code (identifier)''' - if common.df(msg) == 5: - binaryraw = common.hex2bin(msg) - altcode = binaryraw[19:32] # Here we could also put the common.idcode(msg). - return common.squawk(altcode) - else: - raise RuntimeError("Incorrect or inconsistent message types") + return fs, text + + +@_checkdf +def dr(msg): + """Decode downlink request. + + Args: + msg (str): 14 hexdigits string + Returns: + int, str: downlink request, description + + """ + msgbin = common.hex2bin(msg) + dr = common.bin2int(msgbin[8:13]) + + text = None + + if dr == 0: + text = "no downlink request" + elif dr == 1: + text = "request to send Comm-B message" + elif dr == 4: + text = "Comm-B broadcast 1 available" + elif dr == 5: + text = "Comm-B broadcast 2 available" + elif dr >= 16: + text = "ELM downlink segments available: {}".format(dr - 15) + + return dr, text + + +@_checkdf +def um(msg): + """Decode utility message. + + Utility message contains interrogator identifier and reservation type. + + Args: + msg (str): 14 hexdigits string + Returns: + int, str: interrogator identifier code that triggered the reply, and + reservation type made by the interrogator + """ + msgbin = common.hex2bin(msg) + iis = common.bin2int(msgbin[13:17]) + ids = common.bin2int(msgbin[17:19]) + if ids == 0: + ids_text = None + if ids == 1: + ids_text = "Comm-B interrogator identifier code" + if ids == 2: + ids_text = "Comm-C interrogator identifier code" + if ids == 3: + ids_text = "Comm-D interrogator identifier code" + return iis, ids, ids_text + + +@_checkdf +def altitude(msg): + """Decode altitude. + + Args: + msg (String): 14 hexdigits string + + Returns: + int: altitude in ft + + """ + return common.altcode(msg) + + +@_checkdf +def identity(msg): + """Decode squawk code. + + Args: + msg (String): 14 hexdigits string + + Returns: + string: squawk code + + """ + return common.idcode(msg) From f65ffd13f75e623717011b2311ace359f4e6bf9d Mon Sep 17 00:00:00 2001 From: Junzi Sun Date: Sat, 14 Nov 2020 22:05:48 +0100 Subject: [PATCH 7/7] add tests --- tests/test_allcall.py | 13 +++++++++++++ tests/test_surv.py | 22 ++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 tests/test_allcall.py create mode 100644 tests/test_surv.py diff --git a/tests/test_allcall.py b/tests/test_allcall.py new file mode 100644 index 0000000..e727d4b --- /dev/null +++ b/tests/test_allcall.py @@ -0,0 +1,13 @@ +from pyModeS import allcall + + +def test_icao(): + assert allcall.icao("5D484FDEA248F5") == "484FDE" + + +def test_interrogator(): + assert allcall.interrogator("5D484FDEA248F5") == 22 + + +def test_capability(): + assert allcall.capability("5D484FDEA248F5")[0] == 5 diff --git a/tests/test_surv.py b/tests/test_surv.py new file mode 100644 index 0000000..0286e27 --- /dev/null +++ b/tests/test_surv.py @@ -0,0 +1,22 @@ +from pyModeS import surv + + +def test_fs(): + assert surv.fs("2A00516D492B80")[0] == 2 + + +def test_dr(): + assert surv.dr("2A00516D492B80")[0] == 0 + + +def test_um(): + assert surv.um("200CBE4ED80137")[0] == 9 + assert surv.um("200CBE4ED80137")[1] == 1 + + +def test_identity(): + assert surv.identity("2A00516D492B80") == "0356" + + +def test_altitude(): + assert surv.altitude("20001718029FCD") == 36000