def adsb_get_alt(msg): """ :param msg: bit string of extended squitter for DF17 :returns: tuple of integers (qbit, altitude), altitude is in feet; altitude may be None if msg is invalid """ qbit = btoi(msg[47]) if qbit: # [20:26][27:33] (bits M and Q removed) altstr = msg[40:47] + msg[48:52] alt = btoi(altstr) * 25 - 1000 else: # Swap bits around, see Annex 10, 3.1.1.7.12.2.3 # Squitter bit order: # C1 A1 C2 A2 C4 A4 [no-M] B1 Q B2 D2 B4 D4 # 40 41 42 43 44 45 46 47 48 49 50 51 # Transponder bit order: # D2 D4 A1 A2 A4 B1 B2 B4 C1 C2 C4 altstr = msg[49]+msg[51] + msg[41]+msg[43]+msg[45] + \ msg[46]+msg[48]+msg[50] + msg[40]+msg[42]+msg[44] try: alt = glie.xpdr.code_to_alt(altstr) except ValueError: return (0, None) return (qbit, alt)
def adsb_get_alt(msg): """ :param msg: bit string of extended squitter for DF17 :returns: tuple of integers (qbit, altitude), altitude is in feet; altitude may be None if msg is invalid """ qbit = btoi(msg[47]) if qbit: # [20:26][27:33] (bits M and Q removed) altstr = msg[40:47]+msg[48:52] alt = btoi(altstr) * 25 - 1000 else: # Swap bits around, see Annex 10, 3.1.1.7.12.2.3 # Squitter bit order: # C1 A1 C2 A2 C4 A4 [no-M] B1 Q B2 D2 B4 D4 # 40 41 42 43 44 45 46 47 48 49 50 51 # Transponder bit order: # D2 D4 A1 A2 A4 B1 B2 B4 C1 C2 C4 altstr = msg[49]+msg[51] + msg[41]+msg[43]+msg[45] + \ msg[46]+msg[48]+msg[50] + msg[40]+msg[42]+msg[44] try: alt = glie.xpdr.code_to_alt(altstr) except ValueError: return (0, None) return (qbit, alt)
def cpr_decode_lat(oddstr, cprstr, ourlat): """ :param oddstr: odd/even flag as 1-char bitstr :param cprstr: the CPR of target latitude :param ourlat: the latitude of the station in float degrees :returns: the target latitude in float degrees """ Nb = 17 # 17 for airborne, 14 for ground/intent, 12 for TIS-B. NZ = 15 # Doc 9871 C.2.6.2 if len(cprstr) != Nb: raise AppError("Latitude bit string size is not 17: %d" % len(cprstr)) if oddstr != '0' and oddstr != '1': raise AppError("Invalid odd/even: %d" % oddstr) lat_s = ourlat i = btoi(oddstr) # Formulas only use the arc fraction, so convert YZ to fraction right away. YZf = float(btoi(cprstr)) / (1 << Nb) # Dlat_i is either 6.0 or 360/59==6.1016949152 Dlat_i = 360.0 / (4.0 * NZ - i) # Zone index number j = math.floor(lat_s/Dlat_i) + \ math.floor(0.5 + (lat_s % Dlat_i)/Dlat_i - YZf) Rlat = Dlat_i * (j + YZf) return Rlat
def cpr_decode_lat(oddstr, cprstr, ourlat): """ :param oddstr: odd/even flag as 1-char bitstr :param cprstr: the CPR of target latitude :param ourlat: the latitude of the station in float degrees :returns: the target latitude in float degrees """ Nb = 17 # 17 for airborne, 14 for ground/intent, 12 for TIS-B. NZ = 15 # Doc 9871 C.2.6.2 if len(cprstr) != Nb: raise AppError("Latitude bit string size is not 17: %d" % len(cprstr)) if oddstr != '0' and oddstr != '1': raise AppError("Invalid odd/even: %d" % oddstr) lat_s = ourlat i = btoi(oddstr) # Formulas only use the arc fraction, so convert YZ to fraction right away. YZf = float(btoi(cprstr))/(1<<Nb) # Dlat_i is either 6.0 or 360/59==6.1016949152 Dlat_i = 360.0 / (4.0 * NZ - i) # Zone index number j = math.floor(lat_s/Dlat_i) + \ math.floor(0.5 + (lat_s % Dlat_i)/Dlat_i - YZf) Rlat = Dlat_i * (j + YZf) return Rlat
def recv_msg_adsb(linestr): x = linestr.find('*') if x != 0: return x = linestr.find(';') if x == -1: print(TAG+": bad message format", file=sys.stderr) return msglen = x-1 if msglen != 14 and msglen != 28: print(TAG+": bad message length", msglen, file=sys.stderr) return msg = scatter_bits(linestr[1:x]) df = msg[0:5] if df == '10001': # DF17 addr = msg[8:32] c_crc = glie.crc.esq_crc(msg[0:-24]) a_crc = msg[-24:] if c_crc == a_crc: crc_status = "OK" else: x_crc = glie.crc.xor(addr, c_crc) if x_crc == a_crc: crc_status = "aOK" else: crc_status = "Error" ca = msg[5:8] if ca == '101': # CA5 typ = btoi(msg[32:37]) if 9 <= typ <= 18: # Airborne Position with barometric altitude qbit, alt = adsb_get_alt(msg) if alt is None: alt = -1 lat, lon = adsb_get_pos(msg) print("addr %x alt (Q=%d) %d lat %f lon %f CRC:%s" % \ (btoi(addr), qbit, alt, lat, lon, crc_status)) # XXX string value, really? if crc_status == 'OK': craft.update(addr, (time.time(), alt, lat, lon)) elif typ == 19: # Airborne Velocity # P3 print(" DF17 CA5 Type 19 CRC:%s" % (crc_status,)) else: # P3 print(" DF17 CA5 Type", typ, "CRC:%s" % (crc_status,)) else: # P3 print(" DF17 CA", btoi(ca), "CRC:%s" % (crc_status,)) else: # P3 print(" DF", df, btoi(df))
def recv_msg_adsb(linestr): x = linestr.find('*') if x != 0: return x = linestr.find(';') if x == -1: print(TAG + ": bad message format", file=sys.stderr) return msglen = x - 1 if msglen != 14 and msglen != 28: print(TAG + ": bad message length", msglen, file=sys.stderr) return msg = scatter_bits(linestr[1:x]) df = msg[0:5] if df == '10001': # DF17 addr = msg[8:32] c_crc = glie.crc.esq_crc(msg[0:-24]) a_crc = msg[-24:] if c_crc == a_crc: crc_status = "OK" else: x_crc = glie.crc.xor(addr, c_crc) if x_crc == a_crc: crc_status = "aOK" else: crc_status = "Error" ca = msg[5:8] if ca == '101': # CA5 typ = btoi(msg[32:37]) if 9 <= typ <= 18: # Airborne Position with barometric altitude qbit, alt = adsb_get_alt(msg) if alt is None: alt = -1 lat, lon = adsb_get_pos(msg) print("addr %x alt (Q=%d) %d lat %f lon %f CRC:%s" % \ (btoi(addr), qbit, alt, lat, lon, crc_status)) # XXX string value, really? if crc_status == 'OK': craft.update(addr, (time.time(), alt, lat, lon)) elif typ == 19: # Airborne Velocity # P3 print(" DF17 CA5 Type 19 CRC:%s" % (crc_status, )) else: # P3 print(" DF17 CA5 Type", typ, "CRC:%s" % (crc_status, )) else: # P3 print(" DF17 CA", btoi(ca), "CRC:%s" % (crc_status, )) else: # P3 print(" DF", df, btoi(df))
def xor(a, b): length = len(a) if length != len(b): raise AppTraceback('xor on unequal length arguments') step = 20 ret = "" for i in range(0,length,step): len1 = min(length - i, step) ai = btoi(a[i:i+len1]) bi = btoi(b[i:i+len1]) res = ai ^ bi ret += format(res, "0>%db" % len1) return ret
def cpr_decode_lon(oddstr, cprstr, tgtlat, ourlon): Nb = 17 # 17 for airborne, 14 for ground/intent, 12 for TIS-B. if len(cprstr) != 17: raise AppError("Longitude bit string size is not 17: %d" % len(cprstr)) if oddstr != '0' and oddstr != '1': raise AppError("Invalid odd/even: %d" % oddstr) Rlat = tgtlat lon_s = ourlon i = btoi(oddstr) XZf = float(btoi(cprstr)) / (1 << Nb) # NL() defined in AppC.2.6.2.d Note 5 nl = NL(Rlat) if nl - i == 0: Dlon_i = 360.0 else: Dlon_i = 360.0 / (nl - i) m = math.floor(lon_s/Dlon_i) + \ math.floor(0.5 + (lon_s % Dlon_i)/Dlon_i - XZf) Rlon_i = Dlon_i * (m + XZf) return Rlon_i
def cpr_decode_lon(oddstr, cprstr, tgtlat, ourlon): Nb = 17 # 17 for airborne, 14 for ground/intent, 12 for TIS-B. if len(cprstr) != 17: raise AppError("Longitude bit string size is not 17: %d" % len(cprstr)) if oddstr != '0' and oddstr != '1': raise AppError("Invalid odd/even: %d" % oddstr) Rlat = tgtlat lon_s = ourlon i = btoi(oddstr) XZf = float(btoi(cprstr))/(1<<Nb) # NL() defined in AppC.2.6.2.d Note 5 nl = NL(Rlat) if nl - i == 0: Dlon_i = 360.0 else: Dlon_i = 360.0/(nl - i) m = math.floor(lon_s/Dlon_i) + \ math.floor(0.5 + (lon_s % Dlon_i)/Dlon_i - XZf) Rlon_i = Dlon_i * (m + XZf) return Rlon_i