update squawk decoding

This commit is contained in:
Junzi Sun 2020-05-23 20:29:18 +02:00
parent ba84cd7c39
commit 2fc376abae
3 changed files with 68 additions and 90 deletions

View File

@ -17,7 +17,10 @@ cpdef bint is_icao_assigned(str icao)
cpdef int typecode(str msg) cpdef int typecode(str msg)
cpdef int cprNL(double lat) cpdef int cprNL(double lat)
cpdef str idcode(str msg) cpdef str idcode(str msg)
cpdef str squawk(str binstr)
cpdef int altcode(str msg) cpdef int altcode(str msg)
cpdef int altitude(str binstr) cpdef int altitude(str binstr)

View File

@ -160,17 +160,7 @@ cpdef long floor(double x):
return <long> c_floor(x) return <long> c_floor(x)
cpdef str icao(str msg): cpdef str icao(str msg):
"""Calculate the ICAO address from an Mode-S message. """Calculate the ICAO address from an Mode-S message."""
Applicable only with DF4, DF5, DF20, DF21 messages.
Args:
msg (String): 28 bytes hexadecimal message string
Returns:
String: ICAO address in 6 bytes hexadecimal string
"""
cdef unsigned char DF = df(msg) cdef unsigned char DF = df(msg)
cdef long c0, c1 cdef long c0, c1
@ -217,14 +207,7 @@ cpdef bint is_icao_assigned(str icao):
@cython.boundscheck(False) @cython.boundscheck(False)
@cython.wraparound(False) @cython.wraparound(False)
cpdef int typecode(str msg): cpdef int typecode(str msg):
"""Type code of ADS-B message """Type code of ADS-B message"""
Args:
msg (string): 28 bytes hexadecimal message string
Returns:
int: type code number
"""
if df(msg) not in (17, 18): if df(msg) not in (17, 18):
return -1 return -1
# return None # return None
@ -253,39 +236,41 @@ cpdef int cprNL(double lat):
@cython.boundscheck(False) @cython.boundscheck(False)
@cython.wraparound(False) @cython.wraparound(False)
cpdef str idcode(str msg): cpdef str idcode(str msg):
"""Compute identity (squawk code). """Compute identity (squawk code)."""
Applicable only for DF5 or DF21 messages, bit 20-32.
Args:
msg (String): 28 bytes hexadecimal message string
Returns:
string: squawk code
"""
if df(msg) not in [5, 21]: if df(msg) not in [5, 21]:
raise RuntimeError("Message must be Downlink Format 5 or 21.") raise RuntimeError("Message must be Downlink Format 5 or 21.")
cdef bytearray _mbin = bytearray(hex2bin(msg).encode()) squawk_code = squawk(hex2bin(msg)[19:32])
return squawk_code
@cython.boundscheck(False)
@cython.wraparound(False)
cpdef str squawk(str binstr):
"""Compute identity (squawk code)."""
if len(binstr) != 13 or set(binstr) != set('01'):
raise RuntimeError("Input must be 13 bits binary string")
cdef bytearray _mbin = bytearray(binstr.encode())
cdef unsigned char[:] mbin = _mbin cdef unsigned char[:] mbin = _mbin
cdef bytearray _idcode = bytearray(4) cdef bytearray _idcode = bytearray(4)
cdef unsigned char[:] idcode = _idcode cdef unsigned char[:] idcode = _idcode
cdef unsigned char C1 = mbin[19] cdef unsigned char C1 = mbin[0]
cdef unsigned char A1 = mbin[20] cdef unsigned char A1 = mbin[1]
cdef unsigned char C2 = mbin[21] cdef unsigned char C2 = mbin[2]
cdef unsigned char A2 = mbin[22] cdef unsigned char A2 = mbin[3]
cdef unsigned char C4 = mbin[23] cdef unsigned char C4 = mbin[4]
cdef unsigned char A4 = mbin[24] cdef unsigned char A4 = mbin[5]
# X = mbin[25] # X = mbin[6]
cdef unsigned char B1 = mbin[26] cdef unsigned char B1 = mbin[7]
cdef unsigned char D1 = mbin[27] cdef unsigned char D1 = mbin[8]
cdef unsigned char B2 = mbin[28] cdef unsigned char B2 = mbin[9]
cdef unsigned char D2 = mbin[29] cdef unsigned char D2 = mbin[10]
cdef unsigned char B4 = mbin[30] cdef unsigned char B4 = mbin[11]
cdef unsigned char D4 = mbin[31] cdef unsigned char D4 = mbin[12]
idcode[0] = int_to_char((char_to_int(A4)*2 + char_to_int(A2))*2 + char_to_int(A1)) idcode[0] = int_to_char((char_to_int(A4)*2 + char_to_int(A2))*2 + char_to_int(A1))
idcode[1] = int_to_char((char_to_int(B4)*2 + char_to_int(B2))*2 + char_to_int(B1)) idcode[1] = int_to_char((char_to_int(B4)*2 + char_to_int(B2))*2 + char_to_int(B1))
@ -294,29 +279,15 @@ cpdef str idcode(str msg):
return _idcode.decode() return _idcode.decode()
#return str(byte1) + str(byte2) + str(byte3) + str(byte4)
@cython.boundscheck(False) @cython.boundscheck(False)
@cython.wraparound(False) @cython.wraparound(False)
cpdef int altcode(str msg): cpdef int altcode(str msg):
"""Compute the altitude. """Compute the altitude."""
Applicable only for DF4 or DF20 message, bit 20-32.
credit: @fbyrkjeland
Args:
msg (String): 28 bytes hexadecimal message string
Returns:
int: altitude in ft
"""
if df(msg) not in [0, 4, 16, 20]: if df(msg) not in [0, 4, 16, 20]:
raise RuntimeError("Message must be Downlink Format 0, 4, 16, or 20.") raise RuntimeError("Message must be Downlink Format 0, 4, 16, or 20.")
alt = altitude(hex2bin(msg)[19:32]) alt = altitude(hex2bin(msg)[19:32])
return alt return alt
@ -360,7 +331,6 @@ cpdef int altitude(str binstr):
graybytes[0] = mbin[10] graybytes[0] = mbin[10]
graybytes[7] = mbin[11] graybytes[7] = mbin[11]
graybytes[1] = mbin[12] graybytes[1] = mbin[12]
# graybytes = D2 + D4 + A1 + A2 + A4 + B1 + B2 + B4 + C1 + C2 + C4
alt = gray2alt(_graybytes.decode()) alt = gray2alt(_graybytes.decode())
@ -409,15 +379,7 @@ cpdef str data(str msg):
cpdef bint allzeros(str msg): cpdef bint allzeros(str msg):
"""Check if the data bits are all zeros. """Check if the data bits are all zeros."""
Args:
msg (String): 28 bytes hexadecimal message string
Returns:
bool: True or False
"""
d = hex2bin(data(msg)) d = hex2bin(data(msg))
if bin2int(d) > 0: if bin2int(d) > 0:

View File

@ -206,9 +206,7 @@ def cprNL(lat: float) -> int:
def idcode(msg: str) -> str: def idcode(msg: str) -> str:
"""Compute identity (squawk code). """Compute identity code (squawk) encoded in DF5 or DF21 message.
Applicable only for DF5 or DF21 messages, bit 20-32.
Args: Args:
msg (String): 28 bytes hexadecimal message string msg (String): 28 bytes hexadecimal message string
@ -221,20 +219,37 @@ def idcode(msg: str) -> str:
raise RuntimeError("Message must be Downlink Format 5 or 21.") raise RuntimeError("Message must be Downlink Format 5 or 21.")
mbin = hex2bin(msg) mbin = hex2bin(msg)
idcodebin = mbin[19:32]
C1 = mbin[19] return squawk(idcodebin)
A1 = mbin[20]
C2 = mbin[21]
A2 = mbin[22] def squawk(binstr: str) -> str:
C4 = mbin[23] """Decode 13 bits identity (squawk) code.
A4 = mbin[24]
# X = mbin[25] Args:
B1 = mbin[26] binstr (String): 13 bits binary string
D1 = mbin[27]
B2 = mbin[28] Returns:
D2 = mbin[29] int: altitude in ft
B4 = mbin[30]
D4 = mbin[31] """
if len(binstr) != 13 or set(binstr) != set("01"):
raise RuntimeError("Input must be 13 bits binary string")
C1 = binstr[0]
A1 = binstr[1]
C2 = binstr[2]
A2 = binstr[3]
C4 = binstr[4]
A4 = binstr[5]
# X = binstr[6]
B1 = binstr[7]
D1 = binstr[8]
B2 = binstr[9]
D2 = binstr[10]
B4 = binstr[11]
D4 = binstr[12]
byte1 = int(A4 + A2 + A1, 2) byte1 = int(A4 + A2 + A1, 2)
byte2 = int(B4 + B2 + B1, 2) byte2 = int(B4 + B2 + B1, 2)
@ -245,9 +260,7 @@ def idcode(msg: str) -> str:
def altcode(msg: str) -> Optional[int]: def altcode(msg: str) -> Optional[int]:
"""Compute the altitude of DF4 or DF20. """Compute altitude encoded in DF4 or DF20 message.
Applicable only for DF4 or DF20 message, bit 20-32.
Args: Args:
msg (String): 28 bytes hexadecimal message string msg (String): 28 bytes hexadecimal message string
@ -256,7 +269,6 @@ def altcode(msg: str) -> Optional[int]:
int: altitude in ft int: altitude in ft
""" """
alt: Optional[int] alt: Optional[int]
if df(msg) not in [0, 4, 16, 20]: if df(msg) not in [0, 4, 16, 20]:
@ -272,7 +284,7 @@ def altcode(msg: str) -> Optional[int]:
return alt return alt
def altitude(binstr): def altitude(binstr: str) -> Optional[int]:
"""Decode 13 bits altitude code. """Decode 13 bits altitude code.
Args: Args:
@ -282,6 +294,7 @@ def altitude(binstr):
int: altitude in ft int: altitude in ft
""" """
alt: Optional[int]
if len(binstr) != 13 or set(binstr) != set("01"): if len(binstr) != 13 or set(binstr) != set("01"):
raise RuntimeError("Input must be 13 bits binary string") raise RuntimeError("Input must be 13 bits binary string")