It works, still some bugs.

This commit is contained in:
Nick Foster 2012-06-23 17:26:47 -07:00
parent b7cc18c41f
commit 03b41f14be
3 changed files with 73 additions and 123 deletions

View File

@ -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

View File

@ -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):

View File

@ -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"