It works, still some bugs.
This commit is contained in:
parent
b7cc18c41f
commit
03b41f14be
@ -180,8 +180,8 @@ int air_modes_slicer::work(int noutput_items,
|
||||
if(rx_packet.crc && (rx_packet.message_type == 11 || rx_packet.message_type == 17)) {continue;}
|
||||
|
||||
d_payload.str("");
|
||||
for(int m = 0; m < 14; m++) {
|
||||
d_payload << std::setw(2) << std::setfill('0') << unsigned(rx_packet.data[m]);
|
||||
for(int m = 0; m < packet_length/8; m++) {
|
||||
d_payload << std::hex << std::setw(2) << std::setfill('0') << unsigned(rx_packet.data[m]);
|
||||
}
|
||||
|
||||
d_payload << " " << std::setw(6) << rx_packet.crc << " " << std::dec << rx_packet.reference_level
|
||||
|
@ -38,13 +38,17 @@ class data_field:
|
||||
|
||||
#get a particular field from the data
|
||||
def __getitem__(self, fieldname):
|
||||
if self.get_type() in self.types:
|
||||
if fieldname in self.types[self.get_type()]: #verify it exists in this packet type
|
||||
if fieldname in self.subfields:
|
||||
#create a new subfield object and return it
|
||||
return self.subfields[fieldname](self.get_bits(self.fields[fieldname]))
|
||||
else:
|
||||
return self.get_bits(self.fields[fieldname])
|
||||
else:
|
||||
raise FieldNotInPacket(fieldname)
|
||||
else:
|
||||
raise NoHandlerError(self.get_type())
|
||||
|
||||
#grab all the fields in the packet as a dict
|
||||
def get_fields(self):
|
||||
@ -88,7 +92,7 @@ class mb_reply(data_field):
|
||||
bds2 = self.get_bits(self.fields["bds2"])
|
||||
if bds1 not in (0,1,2,3) or bds2 not in (0,):
|
||||
raise NoHandlerError
|
||||
return bds1
|
||||
return int(bds1)
|
||||
|
||||
def get_numbits(self):
|
||||
return 56
|
||||
@ -146,11 +150,6 @@ class me_reply(data_field):
|
||||
class modes_reply(data_field):
|
||||
def __init__(self, data):
|
||||
data_field.__init__(self, data)
|
||||
#TODO FIX PARITY FIELDS
|
||||
self.parity_fields = {
|
||||
"ap": (33+(self.get_numbits()-56),24),
|
||||
"pi": (33+(self.get_numbits()-56),24)
|
||||
}
|
||||
|
||||
#bitfield definitions according to Mode S spec
|
||||
#(start bit, num bits)
|
||||
@ -158,7 +157,8 @@ class modes_reply(data_field):
|
||||
"sl": (9,3), "ri": (14,4), "ac": (20,13), "dr": (9,5),
|
||||
"um": (14,6), "id": (20,13), "ca": (6,3), "aa": (9,24),
|
||||
"mv": (33,56), "me": (33,56), "mb": (33,56), "ke": (6,1),
|
||||
"nd": (7,4), "md": (11,80)
|
||||
"nd": (7,4), "md": (11,80), "ap": (33,24), "pi": (33,24),
|
||||
"lap": (88,24), "lpi": (88,24)
|
||||
}
|
||||
|
||||
#fields in each packet type (DF value)
|
||||
@ -166,11 +166,11 @@ class modes_reply(data_field):
|
||||
4: ["df", "fs", "dr", "um", "ac", "ap"],
|
||||
5: ["df", "fs", "dr", "um", "id", "ap"],
|
||||
11: ["df", "ca", "aa", "pi"],
|
||||
16: ["df", "vs", "sl", "ri", "ac", "mv", "ap"],
|
||||
17: ["df", "ca", "aa", "me", "pi"],
|
||||
20: ["df", "fs", "dr", "um", "ac", "mb", "ap"],
|
||||
21: ["df", "fs", "dr", "um", "id", "mb", "ap"],
|
||||
24: ["df", "ke", "nd", "md", "ap"]
|
||||
16: ["df", "vs", "sl", "ri", "ac", "mv", "lap"],
|
||||
17: ["df", "ca", "aa", "me", "lpi"],
|
||||
20: ["df", "fs", "dr", "um", "ac", "mb", "lap"],
|
||||
21: ["df", "fs", "dr", "um", "id", "mb", "lap"],
|
||||
24: ["df", "ke", "nd", "md", "lap"]
|
||||
}
|
||||
|
||||
subfields = { "mb": mb_reply, "me": me_reply } #TODO MV
|
||||
@ -196,83 +196,34 @@ class modes_parse:
|
||||
self.my_location = mypos
|
||||
self.cpr = cpr.cpr_decoder(self.my_location)
|
||||
|
||||
def parse0(self, shortdata):
|
||||
vs = bool(shortdata >> 26 & 0x1) #ground sensor -- airborne when 0
|
||||
cc = bool(shortdata >> 25 & 0x1) #crosslink capability, binary
|
||||
sl = shortdata >> 21 & 0x07 #operating sensitivity of onboard TCAS system. 0 means no TCAS sensitivity reported, 1-7 give TCAS sensitivity
|
||||
ri = shortdata >> 15 & 0x0F #speed coding: 0 = no onboard TCAS, 1 = NA, 2 = TCAS w/inhib res, 3 = TCAS w/vert only, 4 = TCAS w/vert+horiz, 5-7 = NA, 8 = no max A/S avail,
|
||||
#9 = A/S <= 75kt, 10 = A/S (75-150]kt, 11 = (150-300]kt, 12 = (300-600]kt, 13 = (600-1200]kt, 14 = >1200kt, 15 = NA
|
||||
def parse0(self, data):
|
||||
fields = data.get_fields()
|
||||
altitude = decode_alt(data["ac"], True)
|
||||
return [fields["vs"], fields["cc"], fields["sl"], fields["ri"], altitude]
|
||||
|
||||
altitude = decode_alt(shortdata & 0x1FFF, True) #bit 13 is set for type 0
|
||||
def parse4(self, data):
|
||||
fields = data.get_fields()
|
||||
altitude = decode_alt(data["ac"], True)
|
||||
return [data["fs"], data["dr"], data["um"], altitude]
|
||||
|
||||
return [vs, cc, sl, ri, altitude]
|
||||
def parse5(self, data):
|
||||
return [data["fs"], data["dr"], data["um"], data["id"]]
|
||||
|
||||
def parse4(self, shortdata):
|
||||
fs = shortdata >> 24 & 0x07 #flight status: 0 is airborne normal, 1 is ground normal, 2 is airborne alert, 3 is ground alert, 4 is alert SPI, 5 is normal SPI
|
||||
dr = shortdata >> 19 & 0x1F #downlink request: 0 means no req, bit 0 is Comm-B msg rdy bit, bit 1 is TCAS info msg rdy, bit 2 is Comm-B bcast #1 msg rdy, bit2+bit0 is Comm-B bcast #2 msg rdy,
|
||||
#bit2+bit1 is TCAS info and Comm-B bcast #1 msg rdy, bit2+bit1+bit0 is TCAS info and Comm-B bcast #2 msg rdy, 8-15 N/A, 16-31 req to send N-15 segments
|
||||
um = shortdata >> 13 & 0x3F #transponder status readouts, no decoding information available
|
||||
|
||||
altitude = decode_alt(shortdata & 0x1FFF, True)
|
||||
|
||||
return [fs, dr, um, altitude]
|
||||
|
||||
|
||||
def parse5(self, shortdata):
|
||||
fs = shortdata >> 24 & 0x07 #flight status: 0 is airborne normal, 1 is ground normal, 2 is airborne alert, 3 is ground alert, 4 is alert SPI, 5 is normal SPI
|
||||
dr = shortdata >> 19 & 0x1F #downlink request: 0 means no req, bit 0 is Comm-B msg rdy bit, bit 1 is TCAS info msg rdy, bit 2 is Comm-B bcast #1 msg rdy, bit2+bit0 is Comm-B bcast #2 msg rdy,
|
||||
#bit2+bit1 is TCAS info and Comm-B bcast #1 msg rdy, bit2+bit1+bit0 is TCAS info and Comm-B bcast #2 msg rdy, 8-15 N/A, 16-31 req to send N-15 segments
|
||||
um = shortdata >> 13 & 0x3F #transponder status readouts, no decoding information available
|
||||
ident = shortdata & 0x1FFF
|
||||
|
||||
return [fs, dr, um, ident]
|
||||
|
||||
def parse11(self, shortdata, ecc):
|
||||
def parse11(self, data, ecc):
|
||||
interrogator = ecc & 0x0F
|
||||
|
||||
ca = shortdata >> 13 & 0x3F #capability
|
||||
icao24 = shortdata & 0xFFFFFF
|
||||
|
||||
return [icao24, interrogator, ca]
|
||||
|
||||
#the Type 17 subtypes are:
|
||||
#0: No position information
|
||||
#1: Identification (Category set D)
|
||||
#2: Identification (Category set C)
|
||||
#3: "" (B)
|
||||
#4: "" (A)
|
||||
#5: Surface position accurate to 7.5m
|
||||
#6: "" to 25m
|
||||
#7: "" to 185.2m (0.1nm)
|
||||
#8: "" above 185.2m
|
||||
#9: Airborne position to 7.5m
|
||||
#10-18: Same with less accuracy
|
||||
#19: Airborne velocity
|
||||
#20: Airborne position w/GNSS height above earth
|
||||
#21: same to 25m
|
||||
#22: same above 25m
|
||||
#23: Reserved
|
||||
#24: Reserved for surface system status
|
||||
#25-27: Reserved
|
||||
#28: Extended squitter aircraft status
|
||||
#29: Current/next trajectory change point
|
||||
#30: Aircraft operational coordination
|
||||
#31: Aircraft operational status
|
||||
return [data["aa"], interrogator, data["ca"]]
|
||||
|
||||
categories = [["NO INFO", "RESERVED", "RESERVED", "RESERVED", "RESERVED", "RESERVED", "RESERVED", "RESERVED"],\
|
||||
["NO INFO", "SURFACE EMERGENCY VEHICLE", "SURFACE SERVICE VEHICLE", "FIXED OBSTRUCTION", "RESERVED", "RESERVED", "RESERVED"],\
|
||||
["NO INFO", "GLIDER", "BALLOON/BLIMP", "PARACHUTE", "ULTRALIGHT", "RESERVED", "UAV", "SPACECRAFT"],\
|
||||
["NO INFO", "LIGHT", "SMALL", "LARGE", "LARGE HIGH VORTEX", "HEAVY", "HIGH PERFORMANCE", "ROTORCRAFT"]]
|
||||
|
||||
def parseBDS08(self, shortdata, longdata):
|
||||
icao24 = shortdata & 0xFFFFFF
|
||||
subtype = (longdata >> 51) & 0x1F
|
||||
category = (longdata >> 48) & 0x07
|
||||
catstring = self.categories[subtype-1][category]
|
||||
def parseBDS08(self, data):
|
||||
catstring = self.categories[data["me"]["ftc"]-1][data["me"]["cat"]]
|
||||
|
||||
msg = ""
|
||||
for i in range(0, 8):
|
||||
msg += self.charmap( longdata >> (42-6*i) & 0x3F)
|
||||
msg += self.charmap( data["me"]["ident"] >> (42-6*i) & 0x3F)
|
||||
return (msg, catstring)
|
||||
|
||||
def charmap(self, d):
|
||||
@ -287,16 +238,13 @@ class modes_parse:
|
||||
|
||||
return retval
|
||||
|
||||
def parseBDS05(self, shortdata, longdata):
|
||||
icao24 = shortdata & 0xFFFFFF
|
||||
def parseBDS05(self, data):
|
||||
icao24 = data["aa"]
|
||||
|
||||
encoded_lon = longdata & 0x1FFFF
|
||||
encoded_lat = (longdata >> 17) & 0x1FFFF
|
||||
cpr_format = (longdata >> 34) & 1
|
||||
|
||||
enc_alt = (longdata >> 36) & 0x0FFF
|
||||
|
||||
altitude = decode_alt(enc_alt, False)
|
||||
encoded_lon = data["me"]["lon"]
|
||||
encoded_lat = data["me"]["lat"]
|
||||
cpr_format = data["me"]["cpr"]
|
||||
altitude = decode_alt(data["me"]["alt"], False)
|
||||
|
||||
[decoded_lat, decoded_lon, rnge, bearing] = self.cpr.decode(icao24, encoded_lat, encoded_lon, cpr_format, 0)
|
||||
|
||||
@ -304,17 +252,14 @@ class modes_parse:
|
||||
|
||||
|
||||
#welp turns out it looks like there's only 17 bits in the BDS0,6 ground packet after all.
|
||||
def parseBDS06(self, shortdata, longdata):
|
||||
icao24 = shortdata & 0xFFFFFF
|
||||
|
||||
encoded_lon = longdata & 0x1FFFF
|
||||
encoded_lat = (longdata >> 17) & 0x1FFFF
|
||||
cpr_format = (longdata >> 34) & 1
|
||||
|
||||
altitude = 0
|
||||
def parseBDS06(self, data):
|
||||
icao24 = data["aa"]
|
||||
|
||||
encoded_lon = data["me"]["lon"]
|
||||
encoded_lat = data["me"]["lat"]
|
||||
cpr_format = data["me"]["cpr"]
|
||||
altitude = decode_alt(data["me"]["alt"], False)
|
||||
[decoded_lat, decoded_lon, rnge, bearing] = self.cpr.decode(icao24, encoded_lat, encoded_lon, cpr_format, 1)
|
||||
|
||||
return [altitude, decoded_lat, decoded_lon, rnge, bearing]
|
||||
|
||||
def parseBDS09_0(self, shortdata, longdata):
|
||||
|
@ -33,12 +33,16 @@ class modes_output_print(modes_parse.modes_parse):
|
||||
[data, ecc, reference, timestamp] = message.split()
|
||||
|
||||
#TODO FIXME HALP
|
||||
data = modes_data(long(data, 16))
|
||||
data = modes_parse.modes_reply(long(data, 16))
|
||||
ecc = long(ecc, 16)
|
||||
reference = float(reference)
|
||||
timestamp = float(timestamp)
|
||||
|
||||
try:
|
||||
msgtype = data["df"]
|
||||
except NoHandlerError as err:
|
||||
print "No handler for msgtype %s" % err.msgtype
|
||||
return
|
||||
|
||||
#TODO this is suspect
|
||||
if reference == 0.0:
|
||||
@ -119,31 +123,31 @@ class modes_output_print(modes_parse.modes_parse):
|
||||
|
||||
return retstr
|
||||
|
||||
def print11(self, shortdata, ecc):
|
||||
[icao24, interrogator, ca] = self.parse11(shortdata, ecc)
|
||||
def print11(self, data, ecc):
|
||||
[icao24, interrogator, ca] = self.parse11(data, ecc)
|
||||
|
||||
retstr = "Type 11 (all call reply) from " + "%x" % icao24 + " in reply to interrogator " + str(interrogator)
|
||||
return retstr
|
||||
|
||||
def print17(self, shortdata, longdata):
|
||||
icao24 = shortdata & 0xFFFFFF
|
||||
subtype = (longdata >> 51) & 0x1F;
|
||||
def print17(self, data):
|
||||
icao24 = data["aa"]
|
||||
subtype = data["me"]["ftc"]
|
||||
|
||||
retstr = None
|
||||
retstr = ""
|
||||
|
||||
if 1 <= subtype <= 4:
|
||||
(msg, typestring) = self.parseBDS08(shortdata, longdata)
|
||||
(msg, typestring) = self.parseBDS08(data)
|
||||
retstr = "Type 17 subtype 04 (ident) from " + "%x" % icao24 + " of type " + typestring + " with ident " + msg
|
||||
|
||||
elif subtype >= 5 and subtype <= 8:
|
||||
[altitude, decoded_lat, decoded_lon, rnge, bearing] = self.parseBDS06(shortdata, longdata)
|
||||
[altitude, decoded_lat, decoded_lon, rnge, bearing] = self.parseBDS06(data)
|
||||
if decoded_lat is not None:
|
||||
retstr = "Type 17 subtype 06 (surface report) from " + "%x" % icao24 + " at (" + "%.6f" % decoded_lat + ", " + "%.6f" % decoded_lon + ")"
|
||||
if rnge is not None and bearing is not None:
|
||||
retstr += " (" + "%.2f" % rnge + " @ " + "%.0f" % bearing + ")"
|
||||
|
||||
elif subtype >= 9 and subtype <= 18:
|
||||
[altitude, decoded_lat, decoded_lon, rnge, bearing] = self.parseBDS05(shortdata, longdata)
|
||||
[altitude, decoded_lat, decoded_lon, rnge, bearing] = self.parseBDS05(data)
|
||||
if decoded_lat is not None:
|
||||
retstr = "Type 17 subtype 05 (position report) from " + "%x" % icao24 + " at (" + "%.6f" % decoded_lat + ", " + "%.6f" % decoded_lon + ")"
|
||||
if rnge is not None and bearing is not None:
|
||||
@ -151,17 +155,18 @@ class modes_output_print(modes_parse.modes_parse):
|
||||
retstr += " at " + str(altitude) + "ft"
|
||||
|
||||
elif subtype == 19:
|
||||
subsubtype = (longdata >> 48) & 0x07
|
||||
if subsubtype == 0:
|
||||
[velocity, heading, vert_spd] = self.parseBDS09_0(shortdata, longdata)
|
||||
retstr = "Type 17 subtype 09-0 (track report) from " + "%x" % icao24 + " with velocity " + "%.0f" % velocity + "kt heading " + "%.0f" % heading + " VS " + "%.0f" % vert_spd
|
||||
pass
|
||||
# subsubtype = (longdata >> 48) & 0x07
|
||||
# if subsubtype == 0:
|
||||
# [velocity, heading, vert_spd] = self.parseBDS09_0(shortdata, longdata)
|
||||
# retstr = "Type 17 subtype 09-0 (track report) from " + "%x" % icao24 + " with velocity " + "%.0f" % velocity + "kt heading " + "%.0f" % heading + " VS " + "%.0f" % vert_spd
|
||||
|
||||
elif subsubtype == 1:
|
||||
[velocity, heading, vert_spd] = self.parseBDS09_1(shortdata, longdata)
|
||||
retstr = "Type 17 subtype 09-1 (track report) from " + "%x" % icao24 + " with velocity " + "%.0f" % velocity + "kt heading " + "%.0f" % heading + " VS " + "%.0f" % vert_spd
|
||||
# elif subsubtype == 1:
|
||||
# [velocity, heading, vert_spd] = self.parseBDS09_1(shortdata, longdata)
|
||||
# retstr = "Type 17 subtype 09-1 (track report) from " + "%x" % icao24 + " with velocity " + "%.0f" % velocity + "kt heading " + "%.0f" % heading + " VS " + "%.0f" % vert_spd
|
||||
|
||||
else:
|
||||
retstr = "Type 17 subtype 09-%i" % (subsubtype) + " not implemented"
|
||||
# else:
|
||||
# retstr = "Type 17 subtype 09-%i" % (subsubtype) + " not implemented"
|
||||
else:
|
||||
retstr = "Type 17 subtype " + str(subtype) + " not implemented"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user