Moved SBS1, az_map, and SQL modules to new parser interface. Not tested.

This commit is contained in:
Nick Foster 2013-06-18 18:57:24 -07:00
parent 72ae3abf12
commit 9563972591
5 changed files with 73 additions and 80 deletions

View File

@ -63,15 +63,21 @@ def main():
#ok now relay is gonna get all those tasty strings #ok now relay is gonna get all those tasty strings
#internally we want to distribute parsed data instead, lighten the load #internally we want to distribute parsed data instead, lighten the load
#TODO obviously this should go somewhere besides the main app. But where?
publisher = pubsub() publisher = pubsub()
def send(message): def make_report(pub, message):
[data, ecc, reference, timestamp] = message.split() [data, ecc, reference, timestamp] = message.split()
try: try:
ret = air_modes.modes_report(air_modes.modes_reply(int(data, 16)), int(ecc, 16), 20.0*math.log10(float(reference)), air_modes.stamp(0, float(timestamp))) ret = air_modes.modes_report(air_modes.modes_reply(int(data, 16)),
publisher["modes_dl"] = ret int(ecc, 16),
publisher["type%i_dl" % ret.data.get_type()] = ret 20.0*math.log10(float(reference)),
air_modes.stamp(0, float(timestamp)))
pub["modes_dl"] = ret
pub["type%i_dl" % ret.data.get_type()] = ret
except ADSBError: except ADSBError:
pass pass
send = lambda msg: make_report(publisher, msg)
relay.subscribe("dl_data", send) relay.subscribe("dl_data", send)
@ -84,12 +90,10 @@ def main():
if options.kml is not None: if options.kml is not None:
dbname = 'adsb.db' dbname = 'adsb.db'
lock = threading.Lock() lock = threading.Lock()
sqldb = air_modes.output_sql(my_position, dbname, lock) #input into the db sqldb = air_modes.output_sql(cpr_dec, dbname, lock, publisher) #input into the db
kmlgen = air_modes.output_kml(options.kml, dbname, my_position, lock) #create a KML generating thread to read from the db kmlgen = air_modes.output_kml(options.kml, dbname, my_position, lock) #create a KML generating thread to read from the db
relay.subscribe("dl_data", sqldb.insert)
if options.no_print is not True: if options.no_print is not True:
#relay.subscribe("dl_data", air_modes.output_print(my_position).output)
printer = air_modes.output_print(cpr_dec, publisher) printer = air_modes.output_print(cpr_dec, publisher)
if options.multiplayer is not None: if options.multiplayer is not None:
@ -98,8 +102,7 @@ def main():
relay.subscribe("dl_data", fgout.output) relay.subscribe("dl_data", fgout.output)
if options.sbs1 is True: if options.sbs1 is True:
sbs1port = air_modes.output_sbs1(my_position, 30003) sbs1port = air_modes.output_sbs1(cpr_dec, 30003, publisher)
relay.subscribe("dl_data", sbs1port.output)
tb.run() tb.run()
tb.close() tb.close()

View File

@ -55,22 +55,22 @@ from rx_path import rx_path
from zmq_socket import zmq_pubsub_iface from zmq_socket import zmq_pubsub_iface
from parse import * from parse import *
from msprint import output_print from msprint import output_print
#from sql import output_sql from sql import output_sql
#from sbs1 import output_sbs1 from sbs1 import output_sbs1
#from kml import output_kml from kml import output_kml
#from raw_server import raw_server from raw_server import raw_server
from radio import modes_radio from radio import modes_radio
from exceptions import * from exceptions import *
#from az_map import * from az_map import *
from types import * from types import *
from altitude import * from altitude import *
#this is try/excepted in case the user doesn't have numpy installed #this is try/excepted in case the user doesn't have numpy installed
#try: try:
# from flightgear import output_flightgear from flightgear import output_flightgear
# from Quaternion import * from Quaternion import *
#except ImportError: except ImportError:
# print "gr-air-modes warning: numpy+scipy not installed, FlightGear interface not supported" print "gr-air-modes warning: numpy+scipy not installed, FlightGear interface not supported"
# pass pass
# ---------------------------------------------------------------- # ----------------------------------------------------------------
# Tail of workaround # Tail of workaround

View File

@ -169,29 +169,26 @@ class az_map(QtGui.QWidget):
self.ringsize = ringsize self.ringsize = ringsize
self.drawPath() self.drawPath()
class az_map_output(air_modes.parse): class az_map_output:
def __init__(self, mypos, model): def __init__(self, cprdec, model, pub):
air_modes.parse.__init__(self, mypos) self._cpr = cprdec
self.model = model self.model = model
pub.subscribe("type17_dl", output)
def output(self, msg): def output(self, msg):
try: try:
[data, ecc, reference, timestamp] = msg.split() msgtype = msg.data["df"]
data = air_modes.modes_reply(long(data, 16))
ecc = long(ecc, 16)
rssi = 10.*math.log10(float(reference))
msgtype = data["df"]
now = time.time() now = time.time()
if msgtype == 17: if msgtype == 17:
icao = data["aa"] icao = msg.data["aa"]
subtype = data["ftc"] subtype = msg.data["ftc"]
distance, altitude, bearing = [0,0,0] distance, altitude, bearing = [0,0,0]
if 5 <= subtype <= 8: if 5 <= subtype <= 8:
(ground_track, decoded_lat, decoded_lon, distance, bearing) = self.parseBDS06(data) (ground_track, decoded_lat, decoded_lon, distance, bearing) = air_modes.parseBDS06(msg.data, self._cpr)
altitude = 0 altitude = 0
elif 9 <= subtype <= 18: elif 9 <= subtype <= 18:
(altitude, decoded_lat, decoded_lon, distance, bearing) = self.parseBDS05(data) (altitude, decoded_lat, decoded_lon, distance, bearing) = air_modes.parseBDS05(msg.data, self._cpr)
self.model.addRecord(bearing, altitude, distance) self.model.addRecord(bearing, altitude, distance)
except ADSBError: except ADSBError:

View File

@ -47,9 +47,8 @@ class dumb_task_runner(threading.Thread):
self.shutdown.set() self.shutdown.set()
self.finished.wait(self._interval) self.finished.wait(self._interval)
class output_sbs1(air_modes.parse): class output_sbs1:
def __init__(self, mypos, port): def __init__(self, cprdec, port, pub):
air_modes.parse.__init__(self, mypos)
self._s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self._s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self._s.bind(('', port)) self._s.bind(('', port))
@ -59,6 +58,13 @@ class output_sbs1(air_modes.parse):
self._aircraft_id_map = {} # dictionary of icao24 to aircraft IDs self._aircraft_id_map = {} # dictionary of icao24 to aircraft IDs
self._aircraft_id_count = 0 # Current Aircraft ID count self._aircraft_id_count = 0 # Current Aircraft ID count
self._cpr = cprdec
#it could be cleaner if there were separate output_* fns
#but this works
for i in (0, 4, 5, 11, 17):
pub.subscribe("type%i_dl" % i, output)
#spawn thread to add new connections as they come in #spawn thread to add new connections as they come in
self._runner = dumb_task_runner(self.add_pending_conns, 0.1) self._runner = dumb_task_runner(self.add_pending_conns, 0.1)
@ -124,35 +130,30 @@ class output_sbs1(air_modes.parse):
else: else:
return ",,," return ",,,"
def parse(self, message): def parse(self, msg):
#assembles a SBS-1-style output string from the received message #assembles a SBS-1-style output string from the received message
[data, ecc, reference, timestamp] = message.split() msgtype = msg.data["df"]
data = air_modes.modes_reply(long(data, 16))
ecc = long(ecc, 16)
msgtype = data["df"]
outmsg = None outmsg = None
if msgtype == 0: if msgtype == 0:
outmsg = self.pp0(data, ecc) outmsg = self.pp0(msg.data, msg.ecc)
elif msgtype == 4: elif msgtype == 4:
outmsg = self.pp4(data, ecc) outmsg = self.pp4(msg.data, msg.ecc)
elif msgtype == 5: elif msgtype == 5:
outmsg = self.pp5(data, ecc) outmsg = self.pp5(msg.data, msg.ecc)
elif msgtype == 11: elif msgtype == 11:
outmsg = self.pp11(data, ecc) outmsg = self.pp11(msg.data, msg.ecc)
elif msgtype == 17: elif msgtype == 17:
outmsg = self.pp17(data) outmsg = self.pp17(msg.data)
else: else:
raise NoHandlerError(msgtype) raise NoHandlerError(msgtype)
return outmsg return outmsg
def pp0(self, shortdata, ecc): def pp0(self, shortdata, ecc):
[datestr, timestr] = self.current_time() [datestr, timestr] = self.current_time()
[vs, cc, sl, ri, altitude] = self.parse0(shortdata)
aircraft_id = self.get_aircraft_id(ecc) aircraft_id = self.get_aircraft_id(ecc)
retstr = "MSG,7,0,%i,%06X,%i,%s,%s,%s,%s,,%s,,,,,,,,,," % (aircraft_id, ecc, aircraft_id+100, datestr, timestr, datestr, timestr, altitude) retstr = "MSG,7,0,%i,%06X,%i,%s,%s,%s,%s,,%s,,,,,,,,,," % (aircraft_id, ecc, aircraft_id+100, datestr, timestr, datestr, timestr, air_modes.decode_alt(shortdata["ac"], True))
if vs: if vs:
retstr += "1\r\n" retstr += "1\r\n"
else: else:
@ -161,23 +162,20 @@ class output_sbs1(air_modes.parse):
def pp4(self, shortdata, ecc): def pp4(self, shortdata, ecc):
[datestr, timestr] = self.current_time() [datestr, timestr] = self.current_time()
[fs, dr, um, altitude] = self.parse4(shortdata)
aircraft_id = self.get_aircraft_id(ecc) aircraft_id = self.get_aircraft_id(ecc)
retstr = "MSG,5,0,%i,%06X,%i,%s,%s,%s,%s,,%s,,,,,,," % (aircraft_id, ecc, aircraft_id+100, datestr, timestr, datestr, timestr, altitude) retstr = "MSG,5,0,%i,%06X,%i,%s,%s,%s,%s,,%s,,,,,,," % (aircraft_id, ecc, aircraft_id+100, datestr, timestr, datestr, timestr, air_modes.decode_alt(shortdata["ac"], True))
return retstr + self.decode_fs(fs) + "\r\n" return retstr + self.decode_fs(shortdata["fs"]) + "\r\n"
def pp5(self, shortdata, ecc): def pp5(self, shortdata, ecc):
[datestr, timestr] = self.current_time() [datestr, timestr] = self.current_time()
[fs, dr, um, ident] = self.parse5(shortdata)
aircraft_id = self.get_aircraft_id(ecc) aircraft_id = self.get_aircraft_id(ecc)
retstr = "MSG,6,0,%i,%06X,%i,%s,%s,%s,%s,,,,,,,,%04i," % (aircraft_id, ecc, aircraft_id+100, datestr, timestr, datestr, timestr, ident) retstr = "MSG,6,0,%i,%06X,%i,%s,%s,%s,%s,,,,,,,,%04i," % (aircraft_id, ecc, aircraft_id+100, datestr, timestr, datestr, timestr, air_modes.decode_id(shortdata["id"]))
return retstr + self.decode_fs(fs) + "\r\n" return retstr + self.decode_fs(shortdata["fs"]) + "\r\n"
def pp11(self, shortdata, ecc): def pp11(self, shortdata, ecc):
[datestr, timestr] = self.current_time() [datestr, timestr] = self.current_time()
[icao24, interrogator, ca] = self.parse11(shortdata, ecc)
aircraft_id = self.get_aircraft_id(icao24) aircraft_id = self.get_aircraft_id(icao24)
return "MSG,8,0,%i,%06X,%i,%s,%s,%s,%s,,,,,,,,,,,,\r\n" % (aircraft_id, icao24, aircraft_id+100, datestr, timestr, datestr, timestr) return "MSG,8,0,%i,%06X,%i,%s,%s,%s,%s,,,,,,,,,,,,\r\n" % (aircraft_id, shortdata["aa"], aircraft_id+100, datestr, timestr, datestr, timestr)
def pp17(self, data): def pp17(self, data):
icao24 = data["aa"] icao24 = data["aa"]
@ -191,12 +189,12 @@ class output_sbs1(air_modes.parse):
if bdsreg == 0x08: if bdsreg == 0x08:
# Aircraft Identification # Aircraft Identification
(msg, typestring) = self.parseBDS08(data) (msg, typestring) = air_modes.parseBDS08(data)
retstr = "MSG,1,0,%i,%06X,%i,%s,%s,%s,%s,%s,,,,,,,,,,,\r\n" % (aircraft_id, icao24, aircraft_id+100, datestr, timestr, datestr, timestr, msg) retstr = "MSG,1,0,%i,%06X,%i,%s,%s,%s,%s,%s,,,,,,,,,,,\r\n" % (aircraft_id, icao24, aircraft_id+100, datestr, timestr, datestr, timestr, msg)
elif bdsreg == 0x06: elif bdsreg == 0x06:
# Surface position measurement # Surface position measurement
[ground_track, decoded_lat, decoded_lon, rnge, bearing] = self.parseBDS06(data) [ground_track, decoded_lat, decoded_lon, rnge, bearing] = air_modes.parseBDS06(data, self._cpr)
altitude = 0 altitude = 0
if decoded_lat is None: #no unambiguously valid position available if decoded_lat is None: #no unambiguously valid position available
retstr = None retstr = None
@ -206,7 +204,7 @@ class output_sbs1(air_modes.parse):
elif bdsreg == 0x05: elif bdsreg == 0x05:
# Airborne position measurements # Airborne position measurements
# WRONG (rnge, bearing), is this still true? # WRONG (rnge, bearing), is this still true?
[altitude, decoded_lat, decoded_lon, rnge, bearing] = self.parseBDS05(data) [altitude, decoded_lat, decoded_lon, rnge, bearing] = air_modes.parseBDS05(data, self._cpr)
if decoded_lat is None: #no unambiguously valid position available if decoded_lat is None: #no unambiguously valid position available
retstr = None retstr = None
else: else:
@ -217,7 +215,7 @@ class output_sbs1(air_modes.parse):
# WRONG (heading, vert_spd), Is this still true? # WRONG (heading, vert_spd), Is this still true?
subtype = data["bds09"].get_type() subtype = data["bds09"].get_type()
if subtype == 0 or subtype == 1: if subtype == 0 or subtype == 1:
parser = self.parseBDS09_0 if subtype == 0 else self.parseBDS09_1 parser = air_modes.parseBDS09_0 if subtype == 0 else air_modes.parseBDS09_1
[velocity, heading, vert_spd] = parser(data) [velocity, heading, vert_spd] = parser(data)
retstr = "MSG,4,0,%i,%06X,%i,%s,%s,%s,%s,,,%.1f,%.1f,,,%i,,,,,\r\n" % (aircraft_id, icao24, aircraft_id+100, datestr, timestr, datestr, timestr, velocity, heading, vert_spd) retstr = "MSG,4,0,%i,%06X,%i,%s,%s,%s,%s,,,%.1f,%.1f,,,%i,,,,,\r\n" % (aircraft_id, icao24, aircraft_id+100, datestr, timestr, datestr, timestr, velocity, heading, vert_spd)

View File

@ -26,11 +26,10 @@ import sqlite3
from air_modes.exceptions import * from air_modes.exceptions import *
from gnuradio.gr.pubsub import pubsub from gnuradio.gr.pubsub import pubsub
class output_sql(air_modes.parse, pubsub): class output_sql:
def __init__(self, mypos, filename, lock): def __init__(self, cpr, filename, lock, publisher):
air_modes.parse.__init__(self, mypos) #pubsub.__init__(self)
pubsub.__init__(self) self._cpr = cpr
self._lock = lock; self._lock = lock;
#create the database #create the database
self.filename = filename self.filename = filename
@ -63,6 +62,7 @@ class output_sql(air_modes.parse, pubsub):
#we close the db conn now to reopen it in the output() thread context. #we close the db conn now to reopen it in the output() thread context.
self._db.close() self._db.close()
self._db = None self._db = None
publisher.subscribe("type17_dl", self.insert)
def insert(self, message): def insert(self, message):
with self._lock: with self._lock:
@ -84,19 +84,14 @@ class output_sql(air_modes.parse, pubsub):
except ADSBError: except ADSBError:
pass pass
def make_insert_query(self, message): def make_insert_query(self, msg):
#assembles a SQL query tailored to our database #assembles a SQL query tailored to our database
#this version ignores anything that isn't Type 17 for now, because we just don't care #this version ignores anything that isn't Type 17 for now, because we just don't care
[data, ecc, reference, timestamp] = message.split()
data = air_modes.modes_reply(long(data, 16))
ecc = long(ecc, 16)
# reference = float(reference)
query = None query = None
msgtype = data["df"] msgtype = msg.data["df"]
if msgtype == 17: if msgtype == 17:
query = self.sql17(data) query = self.sql17(msg.data)
self["new_adsb"] = data["aa"] #publish change notification #self["new_adsb"] = data["aa"] #publish change notification
return query return query
@ -111,20 +106,20 @@ class output_sql(air_modes.parse, pubsub):
def sql17(self, data): def sql17(self, data):
icao24 = data["aa"] icao24 = data["aa"]
bdsreg = data["me"].get_type() bdsreg = data["me"].get_type()
self["bds%.2i" % bdsreg] = icao24 #publish under "bds08", "bds06", etc. #self["bds%.2i" % bdsreg] = icao24 #publish under "bds08", "bds06", etc.
if bdsreg == 0x08: if bdsreg == 0x08:
(msg, typename) = self.parseBDS08(data) (msg, typename) = air_modes.parseBDS08(data)
return "INSERT OR REPLACE INTO ident (icao, ident) VALUES (" + "%i" % icao24 + ", '" + msg + "')" return "INSERT OR REPLACE INTO ident (icao, ident) VALUES (" + "%i" % icao24 + ", '" + msg + "')"
elif bdsreg == 0x06: elif bdsreg == 0x06:
[ground_track, decoded_lat, decoded_lon, rnge, bearing] = self.parseBDS06(data) [ground_track, decoded_lat, decoded_lon, rnge, bearing] = air_modes.parseBDS06(data, self._cpr)
altitude = 0 altitude = 0
if decoded_lat is None: #no unambiguously valid position available if decoded_lat is None: #no unambiguously valid position available
raise CPRNoPositionError raise CPRNoPositionError
else: else:
return "INSERT INTO positions (icao, seen, alt, lat, lon) VALUES (" + "%i" % icao24 + ", datetime('now'), " + str(altitude) + ", " + "%.6f" % decoded_lat + ", " + "%.6f" % decoded_lon + ")" return "INSERT INTO positions (icao, seen, alt, lat, lon) VALUES (" + "%i" % icao24 + ", datetime('now'), " + str(altitude) + ", " + "%.6f" % decoded_lat + ", " + "%.6f" % decoded_lon + ")"
elif bdsreg == 0x05: elif bdsreg == 0x05:
[altitude, decoded_lat, decoded_lon, rnge, bearing] = self.parseBDS05(data) [altitude, decoded_lat, decoded_lon, rnge, bearing] = air_modes.parseBDS05(data, self._cpr)
if decoded_lat is None: #no unambiguously valid position available if decoded_lat is None: #no unambiguously valid position available
raise CPRNoPositionError raise CPRNoPositionError
else: else:
@ -132,10 +127,10 @@ class output_sql(air_modes.parse, pubsub):
elif bdsreg == 0x09: elif bdsreg == 0x09:
subtype = data["bds09"].get_type() subtype = data["bds09"].get_type()
if subtype == 0: if subtype == 0:
[velocity, heading, vert_spd, turnrate] = self.parseBDS09_0(data) [velocity, heading, vert_spd, turnrate] = air_modes.parseBDS09_0(data)
return "INSERT INTO vectors (icao, seen, speed, heading, vertical) VALUES (" + "%i" % icao24 + ", datetime('now'), " + "%.0f" % velocity + ", " + "%.0f" % heading + ", " + "%.0f" % vert_spd + ")" return "INSERT INTO vectors (icao, seen, speed, heading, vertical) VALUES (" + "%i" % icao24 + ", datetime('now'), " + "%.0f" % velocity + ", " + "%.0f" % heading + ", " + "%.0f" % vert_spd + ")"
elif subtype == 1: elif subtype == 1:
[velocity, heading, vert_spd] = self.parseBDS09_1(data) [velocity, heading, vert_spd] = air_modes.parseBDS09_1(data)
return "INSERT INTO vectors (icao, seen, speed, heading, vertical) VALUES (" + "%i" % icao24 + ", datetime('now'), " + "%.0f" % velocity + ", " + "%.0f" % heading + ", " + "%.0f" % vert_spd + ")" return "INSERT INTO vectors (icao, seen, speed, heading, vertical) VALUES (" + "%i" % icao24 + ", datetime('now'), " + "%.0f" % velocity + ", " + "%.0f" % heading + ", " + "%.0f" % vert_spd + ")"
else: else:
raise NoHandlerError raise NoHandlerError