SQL parser modified to use flat aircraft table. This breaks KML horribly and eventually you should integrate the flat table into the GUI app and revert to the old method for the KML generator.
This commit is contained in:
parent
5c0ccaa833
commit
0a1d863f5f
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import os, sys, time, threading, datetime
|
import os, sys, time, threading, datetime
|
||||||
from PyQt4 import QtCore,QtGui,QtSql
|
from PyQt4 import QtCore,QtGui,QtSql
|
||||||
|
from PyQt4.Qwt5 import Qwt
|
||||||
from gnuradio import gr, gru, optfir, eng_notation, blks2
|
from gnuradio import gr, gru, optfir, eng_notation, blks2
|
||||||
import gnuradio.gr.gr_threading as _threading
|
import gnuradio.gr.gr_threading as _threading
|
||||||
import air_modes
|
import air_modes
|
||||||
@ -30,6 +31,9 @@ class mainwindow(QtGui.QMainWindow):
|
|||||||
#default to 3dB
|
#default to 3dB
|
||||||
self.ui.line_threshold.insert("3")
|
self.ui.line_threshold.insert("3")
|
||||||
|
|
||||||
|
self.ui.prog_rssi.setMinimum(-20)
|
||||||
|
self.ui.prog_rssi.setMaximum(0)
|
||||||
|
|
||||||
self.ui.combo_ant.setCurrentIndex(self.ui.combo_ant.findText("RX2"))
|
self.ui.combo_ant.setCurrentIndex(self.ui.combo_ant.findText("RX2"))
|
||||||
|
|
||||||
#check KML by default, leave the rest unchecked.
|
#check KML by default, leave the rest unchecked.
|
||||||
@ -66,22 +70,52 @@ class mainwindow(QtGui.QMainWindow):
|
|||||||
self.ui.list_aircraft.setModel(self.datamodel)
|
self.ui.list_aircraft.setModel(self.datamodel)
|
||||||
self.ui.list_aircraft.setModelColumn(0)
|
self.ui.list_aircraft.setModelColumn(0)
|
||||||
|
|
||||||
|
#set up dashboard views
|
||||||
self.icaodelegate = ICAOViewDelegate()
|
self.icaodelegate = ICAOViewDelegate()
|
||||||
self.ui.list_aircraft.setItemDelegate(self.icaodelegate)
|
self.ui.list_aircraft.setItemDelegate(self.icaodelegate)
|
||||||
self.dashboard_mapper = QtGui.QDataWidgetMapper()
|
self.dashboard_mapper = QtGui.QDataWidgetMapper()
|
||||||
self.dashboard_mapper.setModel(self.datamodel)
|
self.dashboard_mapper.setModel(self.datamodel)
|
||||||
self.dashboard_mapper.addMapping(self.ui.prog_rssi, 2)
|
#self.dashboard_mapper.addMapping(self.ui.prog_rssi, 2)
|
||||||
self.dashboard_mapper.addMapping(self.ui.line_latitude, 3)
|
self.dashboard_mapper.addMapping(self.ui.line_latitude, 3)
|
||||||
self.dashboard_mapper.addMapping(self.ui.line_longitude, 4)
|
self.dashboard_mapper.addMapping(self.ui.line_longitude, 4)
|
||||||
self.dashboard_mapper.addMapping(self.ui.line_alt, 5)
|
self.dashboard_mapper.addMapping(self.ui.line_alt, 5)
|
||||||
self.dashboard_mapper.addMapping(self.ui.line_speed, 6)
|
self.dashboard_mapper.addMapping(self.ui.line_speed, 6)
|
||||||
#self.dashboard_mapper.addMapping(self.ui.line_heading, 7)
|
#self.dashboard_mapper.addMapping(self.ui.compass_heading, 7)
|
||||||
self.dashboard_mapper.addMapping(self.ui.line_climb, 8)
|
self.dashboard_mapper.addMapping(self.ui.line_climb, 8)
|
||||||
self.dashboard_mapper.addMapping(self.ui.line_ident, 9)
|
self.dashboard_mapper.addMapping(self.ui.line_ident, 9)
|
||||||
self.dashboard_mapper.addMapping(self.ui.line_type, 10)
|
self.dashboard_mapper.addMapping(self.ui.line_type, 10)
|
||||||
|
|
||||||
|
compass_palette = QtGui.QPalette()
|
||||||
|
compass_palette.setColor(QtGui.QPalette.Foreground, QtCore.Qt.white)
|
||||||
|
self.ui.compass_heading.setPalette(compass_palette)
|
||||||
|
self.ui.compass_heading.setNeedle(Qwt.QwtDialSimpleNeedle(Qwt.QwtDialSimpleNeedle.Ray, False, QtCore.Qt.black))
|
||||||
|
self.ui.compass_heading.setValue(315.0)
|
||||||
|
|
||||||
#hook up the update signal
|
#hook up the update signal
|
||||||
self.ui.list_aircraft.selectionModel().currentRowChanged.connect(self.dashboard_mapper.setCurrentModelIndex)
|
self.ui.list_aircraft.selectionModel().currentRowChanged.connect(self.dashboard_mapper.setCurrentModelIndex)
|
||||||
|
self.ui.list_aircraft.selectionModel().currentRowChanged.connect(self.update_heading_widget)
|
||||||
|
self.ui.list_aircraft.selectionModel().currentRowChanged.connect(self.update_rssi_widget)
|
||||||
|
|
||||||
|
def update_heading_widget(self, index):
|
||||||
|
heading = index.model().data(index.model().index(index.row(), 7)).toFloat()[0]
|
||||||
|
self.ui.compass_heading.setValue(heading)
|
||||||
|
|
||||||
|
def update_rssi_widget(self, index):
|
||||||
|
rssi = index.model().data(index.model().index(index.row(), 2)).toFloat()[0]
|
||||||
|
self.ui.prog_rssi.setValue(rssi)
|
||||||
|
|
||||||
|
#this is fired off by the main loop each time a packet comes in.
|
||||||
|
#eventually you might have this set to just QTimer, depending on how fast things go
|
||||||
|
#this is also updated on EVERY mode S packet, not just valid ADS-B
|
||||||
|
#the RIGHT way to do this is:
|
||||||
|
#all SQL is done inside the datamodel, which can be a QSqlTableModel type.
|
||||||
|
#No fields are editable by the user.
|
||||||
|
#when an update happens, the SQL model determines the row which has changed (by ICAO)
|
||||||
|
#the SQL model then invalidates that row, which will selectively update the list and hopefully the mapper.
|
||||||
|
def update_gui_widgets(self, msg):
|
||||||
|
#self.datamodel.reset() #this is hella bad
|
||||||
|
self.datamodel.setQuery("select * from aircraft order by icao")
|
||||||
|
self.dashboard_mapper.revert()
|
||||||
|
|
||||||
#goes and gets valid antenna, sample rate options from the device and grays out appropriate things
|
#goes and gets valid antenna, sample rate options from the device and grays out appropriate things
|
||||||
def populate_source_options(self):
|
def populate_source_options(self):
|
||||||
@ -173,7 +207,7 @@ class mainwindow(QtGui.QMainWindow):
|
|||||||
except:
|
except:
|
||||||
my_position = None
|
my_position = None
|
||||||
|
|
||||||
self.outputs = []
|
self.outputs = [self.update_gui_widgets]
|
||||||
self.updates = []
|
self.updates = []
|
||||||
|
|
||||||
#output options to populate outputs, updates
|
#output options to populate outputs, updates
|
||||||
@ -222,7 +256,7 @@ class ICAOViewDelegate(QtGui.QStyledItemDelegate):
|
|||||||
def paint(self, painter, option, index):
|
def paint(self, painter, option, index):
|
||||||
paintstr = "%x" % index.model().data(index.model().index(index.row(), 0)).toInt()[0]
|
paintstr = "%x" % index.model().data(index.model().index(index.row(), 0)).toInt()[0]
|
||||||
last_report = str(index.model().data(index.model().index(index.row(), 1)).toString())
|
last_report = str(index.model().data(index.model().index(index.row(), 1)).toString())
|
||||||
age = (datetime.datetime.now() - datetime.datetime.strptime(last_report, "%Y-%m-%d %H:%M:%S")).total_seconds()
|
age = (datetime.datetime.utcnow() - datetime.datetime.strptime(last_report, "%Y-%m-%d %H:%M:%S")).total_seconds()
|
||||||
#minimum alpha is 0x40 (oldest), max is 0xFF (newest)
|
#minimum alpha is 0x40 (oldest), max is 0xFF (newest)
|
||||||
alpha = 0xFF - (0xBF / 600.) * min(age, 600)
|
alpha = 0xFF - (0xBF / 600.) * min(age, 600)
|
||||||
painter.setPen(QtGui.QColor(0, 0, 0, alpha))
|
painter.setPen(QtGui.QColor(0, 0, 0, alpha))
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
# Boston, MA 02110-1301, USA.
|
# Boston, MA 02110-1301, USA.
|
||||||
#
|
#
|
||||||
|
|
||||||
import time, os, sys
|
import time, os, sys, math
|
||||||
from string import split, join
|
from string import split, join
|
||||||
import modes_parse
|
import modes_parse
|
||||||
import sqlite3
|
import sqlite3
|
||||||
@ -54,6 +54,20 @@ class modes_output_sql(modes_parse.modes_parse):
|
|||||||
"ident" TEXT NOT NULL
|
"ident" TEXT NOT NULL
|
||||||
);"""
|
);"""
|
||||||
c.execute(query)
|
c.execute(query)
|
||||||
|
query = """CREATE TABLE IF NOT EXISTS "aircraft" (
|
||||||
|
"icao" integer primary key not null,
|
||||||
|
"seen" text not null,
|
||||||
|
"rssi" real,
|
||||||
|
"latitude" real,
|
||||||
|
"longitude" real,
|
||||||
|
"altitude" real,
|
||||||
|
"speed" real,
|
||||||
|
"heading" real,
|
||||||
|
"vertical" real,
|
||||||
|
"ident" text,
|
||||||
|
"type" text
|
||||||
|
);"""
|
||||||
|
c.execute(query)
|
||||||
c.close()
|
c.close()
|
||||||
#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()
|
||||||
@ -71,12 +85,8 @@ class modes_output_sql(modes_parse.modes_parse):
|
|||||||
if self.db is None:
|
if self.db is None:
|
||||||
self.db = sqlite3.connect(self.filename)
|
self.db = sqlite3.connect(self.filename)
|
||||||
|
|
||||||
query = self.make_insert_query(message)
|
self.make_insert_query(message)
|
||||||
if query is not None:
|
self.db.commit() #don't know if this is necessary
|
||||||
c = self.db.cursor()
|
|
||||||
c.execute(query)
|
|
||||||
c.close()
|
|
||||||
self.db.commit() #don't know if this is necessary
|
|
||||||
except ADSBError:
|
except ADSBError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -87,49 +97,60 @@ class modes_output_sql(modes_parse.modes_parse):
|
|||||||
|
|
||||||
data = modes_parse.modes_reply(long(data, 16))
|
data = modes_parse.modes_reply(long(data, 16))
|
||||||
ecc = long(ecc, 16)
|
ecc = long(ecc, 16)
|
||||||
# reference = float(reference)
|
rssi = 10.0*math.log10(float(reference))
|
||||||
|
|
||||||
|
|
||||||
query = None
|
query = None
|
||||||
msgtype = data["df"]
|
msgtype = data["df"]
|
||||||
if msgtype == 17:
|
if msgtype == 17:
|
||||||
query = self.sql17(data)
|
query = self.sql17(data, rssi)
|
||||||
|
|
||||||
return query
|
return query
|
||||||
|
|
||||||
def sql17(self, data):
|
def sql17(self, data, rssi):
|
||||||
icao24 = data["aa"]
|
icao24 = data["aa"]
|
||||||
subtype = data["ftc"]
|
subtype = data["ftc"]
|
||||||
|
c = self.db.cursor()
|
||||||
retstr = None
|
|
||||||
|
|
||||||
if subtype == 4:
|
if subtype == 4:
|
||||||
(msg, typename) = self.parseBDS08(data)
|
(ident, typename) = self.parseBDS08(data)
|
||||||
retstr = "INSERT OR REPLACE INTO ident (icao, ident) VALUES (" + "%i" % icao24 + ", '" + msg + "')"
|
c.execute("insert or ignore into aircraft (icao, seen, rssi, ident, type) values (%i, datetime('now'), %f, '%s', '%s')" % (icao24, rssi, ident, typename))
|
||||||
|
c.execute("update aircraft set seen=datetime('now'), rssi=%f, ident='%s', type='%s' where icao=%i" % (rssi, ident, typename, icao24))
|
||||||
|
|
||||||
elif subtype >= 5 and subtype <= 8:
|
elif subtype >= 5 and subtype <= 8:
|
||||||
[ground_track, decoded_lat, decoded_lon, rnge, bearing] = self.parseBDS06(data)
|
[ground_track, decoded_lat, decoded_lon, rnge, bearing] = self.parseBDS06(data)
|
||||||
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
|
c.execute("insert or ignore into aircraft (icao, seen, rssi) values (%i, datetime('now'), %f)" % (icao24, rssi))
|
||||||
|
c.execute("update aircraft set seen=datetime('now'), rssi=%f where icao=%i" % (icao24, rssi))
|
||||||
else:
|
else:
|
||||||
retstr = "INSERT INTO positions (icao, seen, alt, lat, lon) VALUES (" + "%i" % icao24 + ", datetime('now'), " + str(altitude) + ", " + "%.6f" % decoded_lat + ", " + "%.6f" % decoded_lon + ")"
|
c.execute("insert or ignore into aircraft (icao, seen, rssi, latitude, longitude, altitude) \
|
||||||
|
values (%i, datetime('now'), %f, %.6f, %.6f, %i)" % (icao24, rssi, decoded_lat, decoded_lon, altitude))
|
||||||
|
c.execute("update aircraft set seen=datetime('now'), rssi=%f, latitude=%.6f, longitude=%.6f, altitude=%i" % (rssi, decoded_lat, decoded_lon, altitude))
|
||||||
|
|
||||||
elif subtype >= 9 and subtype <= 18 and subtype != 15: #i'm eliminating type 15 records because they don't appear to be valid position reports.
|
elif subtype >= 9 and subtype <= 18 and subtype != 15: #i'm eliminating type 15 records because they don't appear to be valid position reports.
|
||||||
[altitude, decoded_lat, decoded_lon, rnge, bearing] = self.parseBDS05(data)
|
[altitude, decoded_lat, decoded_lon, rnge, bearing] = self.parseBDS05(data)
|
||||||
if decoded_lat is None: #no unambiguously valid position available
|
if decoded_lat is None: #no unambiguously valid position available
|
||||||
retstr = None
|
c.execute("insert or ignore into aircraft (icao, seen, rssi) values (%i, datetime('now'), %f);" % (icao24, rssi))
|
||||||
|
c.execute("update aircraft set seen=datetime('now'), rssi=%f where icao=%i" % (icao24, rssi))
|
||||||
else:
|
else:
|
||||||
retstr = "INSERT INTO positions (icao, seen, alt, lat, lon) VALUES (" + "%i" % icao24 + ", datetime('now'), " + str(altitude) + ", " + "%.6f" % decoded_lat + ", " + "%.6f" % decoded_lon + ")"
|
c.execute("insert or ignore into aircraft (icao, seen, rssi, latitude, longitude, altitude) \
|
||||||
|
values (%i, datetime('now'), %f, %.6f, %.6f, %i)" % (icao24, rssi, decoded_lat, decoded_lon, altitude))
|
||||||
|
c.execute("update aircraft set seen=datetime('now'), rssi=%f, latitude=%.6f, longitude=%.6f, altitude=%i where icao=%i" % (rssi, decoded_lat, decoded_lon, altitude, icao24))
|
||||||
|
|
||||||
elif subtype == 19:
|
elif subtype == 19:
|
||||||
subsubtype = data["sub"]
|
subsubtype = data["sub"]
|
||||||
if subsubtype == 0:
|
if subsubtype == 0:
|
||||||
[velocity, heading, vert_spd] = self.parseBDS09_0(data)
|
[velocity, heading, vert_spd] = self.parseBDS09_0(data)
|
||||||
retstr = "INSERT INTO vectors (icao, seen, speed, heading, vertical) VALUES (" + "%i" % icao24 + ", datetime('now'), " + "%.0f" % velocity + ", " + "%.0f" % heading + ", " + "%.0f" % vert_spd + ")";
|
|
||||||
|
|
||||||
elif 1 <= subsubtype <= 2:
|
elif 1 <= subsubtype <= 2:
|
||||||
[velocity, heading, vert_spd] = self.parseBDS09_1(data)
|
[velocity, heading, vert_spd] = self.parseBDS09_1(data)
|
||||||
retstr = "INSERT INTO vectors (icao, seen, speed, heading, vertical) VALUES (" + "%i" % icao24 + ", datetime('now'), " + "%.0f" % velocity + ", " + "%.0f" % heading + ", " + "%.0f" % vert_spd + ")";
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
return retstr
|
c.execute("insert or ignore into aircraft (icao, seen, rssi, speed, heading, vertical) \
|
||||||
|
values (%i, datetime('now'), %f, %.0f, %.0f, %.0f);" % (icao24, rssi, velocity, heading, vert_spd))
|
||||||
|
c.execute("update aircraft set seen=datetime('now'), rssi=%f, speed=%.0f, heading=%.0f, vertical=%.0f where icao=%i" % (rssi, velocity, heading, vert_spd, icao24))
|
||||||
|
|
||||||
|
|
||||||
|
c.close()
|
||||||
|
@ -776,6 +776,19 @@
|
|||||||
<string>Climb</string>
|
<string>Climb</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QwtCompass" name="compass_heading">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>200</x>
|
||||||
|
<y>30</y>
|
||||||
|
<width>161</width>
|
||||||
|
<height>91</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="lineWidth">
|
||||||
|
<number>4</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="browsertab">
|
<widget class="QWidget" name="browsertab">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
@ -863,6 +876,18 @@
|
|||||||
</widget>
|
</widget>
|
||||||
<widget class="QStatusBar" name="statusbar"/>
|
<widget class="QStatusBar" name="statusbar"/>
|
||||||
</widget>
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>QwtCompass</class>
|
||||||
|
<extends>QwtDial</extends>
|
||||||
|
<header>qwt_compass.h</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>QwtDial</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>qwt_dial.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
Loading…
Reference in New Issue
Block a user