Mapview: added highlighting of selected aircraft
This commit is contained in:
parent
7fef37d34d
commit
b594fe2799
@ -118,8 +118,9 @@ class mainwindow(QtGui.QMainWindow):
|
|||||||
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_heading_widget)
|
||||||
self.ui.list_aircraft.selectionModel().currentRowChanged.connect(self.update_bearing_widget)
|
self.ui.list_aircraft.selectionModel().currentRowChanged.connect(self.update_bearing_widget)
|
||||||
self.datamodel.dataChanged.connect(self.unmapped_widgets_dataChanged)
|
|
||||||
self.ui.list_aircraft.selectionModel().currentRowChanged.connect(self.update_rssi_widget)
|
self.ui.list_aircraft.selectionModel().currentRowChanged.connect(self.update_rssi_widget)
|
||||||
|
self.ui.list_aircraft.selectionModel().currentRowChanged.connect(self.update_map_highlight)
|
||||||
|
self.datamodel.dataChanged.connect(self.unmapped_widgets_dataChanged)
|
||||||
|
|
||||||
#hook up live data text box update signal
|
#hook up live data text box update signal
|
||||||
self.live_data_changed_signal.connect(self.on_append_live_data)
|
self.live_data_changed_signal.connect(self.on_append_live_data)
|
||||||
@ -149,7 +150,7 @@ class mainwindow(QtGui.QMainWindow):
|
|||||||
if index.model() is not None:
|
if index.model() is not None:
|
||||||
rssi = index.model().data(index.model().index(index.row(), 2)).toDouble()[0]
|
rssi = index.model().data(index.model().index(index.row(), 2)).toDouble()[0]
|
||||||
self.ui.prog_rssi.setValue(rssi)
|
self.ui.prog_rssi.setValue(rssi)
|
||||||
|
|
||||||
def increment_reportspersec(self, msg):
|
def increment_reportspersec(self, msg):
|
||||||
self.num_reports += 1
|
self.num_reports += 1
|
||||||
|
|
||||||
@ -160,6 +161,12 @@ class mainwindow(QtGui.QMainWindow):
|
|||||||
self.ui.line_reports.setText("%i" % self.num_reports)
|
self.ui.line_reports.setText("%i" % self.num_reports)
|
||||||
self.num_reports = 0
|
self.num_reports = 0
|
||||||
|
|
||||||
|
def update_map_highlight(self, index):
|
||||||
|
if index.model() is not None:
|
||||||
|
icaostr = index.model().data(index.model().index(index.row(), self.datamodel._colnames.index("icao"))).toString()
|
||||||
|
icao = int(str(icaostr), 16)
|
||||||
|
self.jsonpgen.set_highlight(icao)
|
||||||
|
|
||||||
##################### dynamic option population ########################
|
##################### dynamic option population ########################
|
||||||
#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):
|
||||||
@ -167,7 +174,7 @@ class mainwindow(QtGui.QMainWindow):
|
|||||||
self.rates = []
|
self.rates = []
|
||||||
self.ratetext = []
|
self.ratetext = []
|
||||||
self.antennas = []
|
self.antennas = []
|
||||||
|
|
||||||
if sourceid == "UHD":
|
if sourceid == "UHD":
|
||||||
try:
|
try:
|
||||||
from gnuradio import uhd
|
from gnuradio import uhd
|
||||||
@ -184,7 +191,7 @@ class mainwindow(QtGui.QMainWindow):
|
|||||||
self.ui.combo_ant.setEnabled(False)
|
self.ui.combo_ant.setEnabled(False)
|
||||||
self.ui.combo_rate.setEnabled(False)
|
self.ui.combo_rate.setEnabled(False)
|
||||||
self.ui.stack_source.setCurrentIndex(0)
|
self.ui.stack_source.setCurrentIndex(0)
|
||||||
|
|
||||||
elif sourceid == "Osmocom":
|
elif sourceid == "Osmocom":
|
||||||
try:
|
try:
|
||||||
import osmosdr
|
import osmosdr
|
||||||
@ -346,7 +353,7 @@ class mainwindow(QtGui.QMainWindow):
|
|||||||
cursor.movePosition(QtGui.QTextCursor.Start)
|
cursor.movePosition(QtGui.QTextCursor.Start)
|
||||||
cursor.select(QtGui.QTextCursor.LineUnderCursor)
|
cursor.select(QtGui.QTextCursor.LineUnderCursor)
|
||||||
cursor.removeSelectedText()
|
cursor.removeSelectedText()
|
||||||
|
|
||||||
self.ui.text_livedata.append(msgstr)
|
self.ui.text_livedata.append(msgstr)
|
||||||
self.ui.text_livedata.verticalScrollBar().setSliderPosition(self.ui.text_livedata.verticalScrollBar().maximum())
|
self.ui.text_livedata.verticalScrollBar().setSliderPosition(self.ui.text_livedata.verticalScrollBar().maximum())
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
def html_template(my_position, json_file):
|
def html_template(my_position, json_file):
|
||||||
if my_position is None:
|
if my_position is None:
|
||||||
my_position = [37, -122]
|
my_position = [37, -122]
|
||||||
|
|
||||||
return """
|
return """
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
@ -20,7 +20,7 @@ def html_template(my_position, json_file):
|
|||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
border: 2px solid black;
|
border: 2px solid black;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
@ -61,27 +61,33 @@ def html_template(my_position, json_file):
|
|||||||
type: results[i].type,
|
type: results[i].type,
|
||||||
ident: results[i].ident,
|
ident: results[i].ident,
|
||||||
speed: results[i].speed,
|
speed: results[i].speed,
|
||||||
vertical: results[i].vertical
|
vertical: results[i].vertical,
|
||||||
|
highlight: results[i].highlight
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
refreshIcons();
|
refreshIcons();
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshIcons() {
|
function refreshIcons() {
|
||||||
for (var airplane in airplanes) {
|
for (var airplane in airplanes) {
|
||||||
|
if (airplanes[airplane].highlight != 0) {
|
||||||
|
icon_file = "http://www.nerdnetworks.org/~bistromath/airplane_sprite_highlight.png";
|
||||||
|
} else {
|
||||||
|
icon_file = "http://www.nerdnetworks.org/~bistromath/airplane_sprite.png";
|
||||||
|
};
|
||||||
var plane_icon = {
|
var plane_icon = {
|
||||||
url: "http://www.nerdnetworks.org/~bistromath/airplane_sprite.png",
|
url: icon_file,
|
||||||
size: new google.maps.Size(128,128),
|
size: new google.maps.Size(128,128),
|
||||||
origin: new google.maps.Point(parseInt(airplanes[airplane].heading/10)*128,0),
|
origin: new google.maps.Point(parseInt(airplanes[airplane].heading/10)*128,0),
|
||||||
anchor: new google.maps.Point(64,64),
|
anchor: new google.maps.Point(64,64),
|
||||||
//scaledSize: new google.maps.Size(4608,126)
|
//scaledSize: new google.maps.Size(4608,126)
|
||||||
};
|
};
|
||||||
|
|
||||||
identstr = airplanes[airplane].ident;
|
identstr = airplanes[airplane].ident;
|
||||||
if (identstr === "" || !identstr) {
|
if (identstr === "" || !identstr) {
|
||||||
identstr = airplanes[airplane].icao;
|
identstr = airplanes[airplane].icao;
|
||||||
};
|
};
|
||||||
|
|
||||||
var planeOptions = {
|
var planeOptions = {
|
||||||
map: map,
|
map: map,
|
||||||
position: airplanes[airplane].center,
|
position: airplanes[airplane].center,
|
||||||
@ -99,13 +105,13 @@ def html_template(my_position, json_file):
|
|||||||
|
|
||||||
function initialize()
|
function initialize()
|
||||||
{
|
{
|
||||||
var myOptions =
|
var myOptions =
|
||||||
{
|
{
|
||||||
zoom: defaultZoomLevel,
|
zoom: defaultZoomLevel,
|
||||||
center: defaultLocation,
|
center: defaultLocation,
|
||||||
disableDefaultUI: true,
|
disableDefaultUI: true,
|
||||||
mapTypeId: google.maps.MapTypeId.TERRAIN
|
mapTypeId: google.maps.MapTypeId.TERRAIN
|
||||||
};
|
};
|
||||||
|
|
||||||
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
|
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ class output_kml(threading.Thread):
|
|||||||
self.my_coords = localpos
|
self.my_coords = localpos
|
||||||
self._timeout = timeout
|
self._timeout = timeout
|
||||||
self._lock = lock
|
self._lock = lock
|
||||||
|
|
||||||
self.shutdown = threading.Event()
|
self.shutdown = threading.Event()
|
||||||
self.finished = threading.Event()
|
self.finished = threading.Event()
|
||||||
self.setDaemon(1)
|
self.setDaemon(1)
|
||||||
@ -41,7 +41,7 @@ class output_kml(threading.Thread):
|
|||||||
while self.shutdown.is_set() is False:
|
while self.shutdown.is_set() is False:
|
||||||
self.writekml()
|
self.writekml()
|
||||||
time.sleep(self._timeout)
|
time.sleep(self._timeout)
|
||||||
|
|
||||||
self._db.close()
|
self._db.close()
|
||||||
self._db = None
|
self._db = None
|
||||||
self.finished.set()
|
self.finished.set()
|
||||||
@ -52,8 +52,8 @@ class output_kml(threading.Thread):
|
|||||||
#there's a bug here where self._timeout is long and close() has
|
#there's a bug here where self._timeout is long and close() has
|
||||||
#to wait for the sleep to expire before closing. we just bail
|
#to wait for the sleep to expire before closing. we just bail
|
||||||
#instead with the 0.2 param above.
|
#instead with the 0.2 param above.
|
||||||
|
|
||||||
|
|
||||||
def writekml(self):
|
def writekml(self):
|
||||||
kmlstr = self.genkml()
|
kmlstr = self.genkml()
|
||||||
if kmlstr is not None:
|
if kmlstr is not None:
|
||||||
@ -64,7 +64,7 @@ class output_kml(threading.Thread):
|
|||||||
def locked_execute(self, c, query):
|
def locked_execute(self, c, query):
|
||||||
with self._lock:
|
with self._lock:
|
||||||
c.execute(query)
|
c.execute(query)
|
||||||
|
|
||||||
def draw_circle(self, center, rng):
|
def draw_circle(self, center, rng):
|
||||||
retstr = ""
|
retstr = ""
|
||||||
steps=30
|
steps=30
|
||||||
@ -91,7 +91,7 @@ class output_kml(threading.Thread):
|
|||||||
|
|
||||||
retstr = string.lstrip(retstr)
|
retstr = string.lstrip(retstr)
|
||||||
return retstr
|
return retstr
|
||||||
|
|
||||||
def genkml(self):
|
def genkml(self):
|
||||||
#first let's draw the static content
|
#first let's draw the static content
|
||||||
retstr="""<?xml version="1.0" encoding="UTF-8"?>\n<kml xmlns="http://www.opengis.net/kml/2.2">\n<Document>\n\t<Style id="airplane">\n\t\t<IconStyle>\n\t\t\t<Icon><href>airports.png</href></Icon>\n\t\t</IconStyle>\n\t</Style>\n\t<Style id="rangering">\n\t<LineStyle>\n\t\t<color>9f4f4faf</color>\n\t\t<width>2</width>\n\t</LineStyle>\n\t</Style>\n\t<Style id="track">\n\t<LineStyle>\n\t\t<color>5fff8f8f</color>\n\t\t<width>4</width>\n\t</LineStyle>\n\t</Style>"""
|
retstr="""<?xml version="1.0" encoding="UTF-8"?>\n<kml xmlns="http://www.opengis.net/kml/2.2">\n<Document>\n\t<Style id="airplane">\n\t\t<IconStyle>\n\t\t\t<Icon><href>airports.png</href></Icon>\n\t\t</IconStyle>\n\t</Style>\n\t<Style id="rangering">\n\t<LineStyle>\n\t\t<color>9f4f4faf</color>\n\t\t<width>2</width>\n\t</LineStyle>\n\t</Style>\n\t<Style id="track">\n\t<LineStyle>\n\t\t<color>5fff8f8f</color>\n\t\t<width>4</width>\n\t</LineStyle>\n\t</Style>"""
|
||||||
@ -101,7 +101,7 @@ class output_kml(threading.Thread):
|
|||||||
for rng in [100, 200, 300]:
|
for rng in [100, 200, 300]:
|
||||||
retstr += """\n\t\t<Placemark>\n\t\t\t<name>%inm</name>\n\t\t\t<styleUrl>#rangering</styleUrl>\n\t\t\t<LinearRing>\n\t\t\t\t<coordinates>%s</coordinates>\n\t\t\t</LinearRing>\n\t\t</Placemark>""" % (rng, self.draw_circle(self.my_coords, rng),)
|
retstr += """\n\t\t<Placemark>\n\t\t\t<name>%inm</name>\n\t\t\t<styleUrl>#rangering</styleUrl>\n\t\t\t<LinearRing>\n\t\t\t\t<coordinates>%s</coordinates>\n\t\t\t</LinearRing>\n\t\t</Placemark>""" % (rng, self.draw_circle(self.my_coords, rng),)
|
||||||
retstr += """\t</Folder>\n"""
|
retstr += """\t</Folder>\n"""
|
||||||
|
|
||||||
retstr += """\t<Folder>\n\t\t<name>Aircraft locations</name>\n\t\t<open>0</open>"""
|
retstr += """\t<Folder>\n\t\t<name>Aircraft locations</name>\n\t\t<open>0</open>"""
|
||||||
|
|
||||||
#read the database and add KML
|
#read the database and add KML
|
||||||
@ -124,11 +124,11 @@ class output_kml(threading.Thread):
|
|||||||
if lon is None: lon = 0
|
if lon is None: lon = 0
|
||||||
alt = track[0][2]
|
alt = track[0][2]
|
||||||
if alt is None: alt = 0
|
if alt is None: alt = 0
|
||||||
|
|
||||||
metric_alt = alt * 0.3048 #google earth takes meters, the commie bastards
|
metric_alt = alt * 0.3048 #google earth takes meters, the commie bastards
|
||||||
|
|
||||||
trackstr = ""
|
trackstr = ""
|
||||||
|
|
||||||
for pos in track:
|
for pos in track:
|
||||||
trackstr += " %f,%f,%f" % (pos[4], pos[3], pos[2]*0.3048)
|
trackstr += " %f,%f,%f" % (pos[4], pos[3], pos[2]*0.3048)
|
||||||
|
|
||||||
@ -162,7 +162,7 @@ class output_kml(threading.Thread):
|
|||||||
seen = 0
|
seen = 0
|
||||||
speed = 0
|
speed = 0
|
||||||
heading = 0
|
heading = 0
|
||||||
vertical = 0
|
vertical = 0
|
||||||
#now generate some KML
|
#now generate some KML
|
||||||
retstr+= "\n\t\t<Placemark>\n\t\t\t<name>%s</name>\n\t\t\t<Style><IconStyle><heading>%i</heading></IconStyle></Style>\n\t\t\t<styleUrl>#airplane</styleUrl>\n\t\t\t<description>\n\t\t\t\t<![CDATA[Altitude: %s<br/>Heading: %i<br/>Speed: %i<br/>Vertical speed: %i<br/>ICAO: %x<br/>Last seen: %s]]>\n\t\t\t</description>\n\t\t\t<Point>\n\t\t\t\t<altitudeMode>absolute</altitudeMode>\n\t\t\t\t<extrude>1</extrude>\n\t\t\t\t<coordinates>%s,%s,%i</coordinates>\n\t\t\t</Point>\n\t\t</Placemark>" % (ident, heading, alt, heading, speed, vertical, icao[0], seen, lon, lat, metric_alt, )
|
retstr+= "\n\t\t<Placemark>\n\t\t\t<name>%s</name>\n\t\t\t<Style><IconStyle><heading>%i</heading></IconStyle></Style>\n\t\t\t<styleUrl>#airplane</styleUrl>\n\t\t\t<description>\n\t\t\t\t<![CDATA[Altitude: %s<br/>Heading: %i<br/>Speed: %i<br/>Vertical speed: %i<br/>ICAO: %x<br/>Last seen: %s]]>\n\t\t\t</description>\n\t\t\t<Point>\n\t\t\t\t<altitudeMode>absolute</altitudeMode>\n\t\t\t\t<extrude>1</extrude>\n\t\t\t\t<coordinates>%s,%s,%i</coordinates>\n\t\t\t</Point>\n\t\t</Placemark>" % (ident, heading, alt, heading, speed, vertical, icao[0], seen, lon, lat, metric_alt, )
|
||||||
|
|
||||||
@ -173,15 +173,18 @@ class output_kml(threading.Thread):
|
|||||||
|
|
||||||
#we just inherit from output_kml because we're doing the same thing, only in a different format.
|
#we just inherit from output_kml because we're doing the same thing, only in a different format.
|
||||||
class output_jsonp(output_kml):
|
class output_jsonp(output_kml):
|
||||||
|
def set_highlight(self, icao):
|
||||||
|
self.highlight = icao
|
||||||
|
|
||||||
def genkml(self):
|
def genkml(self):
|
||||||
retstr="""jsonp_callback(["""
|
retstr="""jsonp_callback(["""
|
||||||
|
|
||||||
# if self.my_coords is not None:
|
# if self.my_coords is not None:
|
||||||
# retstr += """\n\t<Folder>\n\t\t<name>Range rings</name>\n\t\t<open>0</open>"""
|
# retstr += """\n\t<Folder>\n\t\t<name>Range rings</name>\n\t\t<open>0</open>"""
|
||||||
# for rng in [100, 200, 300]:
|
# for rng in [100, 200, 300]:
|
||||||
# retstr += """\n\t\t<Placemark>\n\t\t\t<name>%inm</name>\n\t\t\t<styleUrl>#rangering</styleUrl>\n\t\t\t<LinearRing>\n\t\t\t\t<coordinates>%s</coordinates>\n\t\t\t</LinearRing>\n\t\t</Placemark>""" % (rng, self.draw_circle(self.my_coords, rng),)
|
# retstr += """\n\t\t<Placemark>\n\t\t\t<name>%inm</name>\n\t\t\t<styleUrl>#rangering</styleUrl>\n\t\t\t<LinearRing>\n\t\t\t\t<coordinates>%s</coordinates>\n\t\t\t</LinearRing>\n\t\t</Placemark>""" % (rng, self.draw_circle(self.my_coords, rng),)
|
||||||
# retstr += """\t</Folder>\n"""
|
# retstr += """\t</Folder>\n"""
|
||||||
|
|
||||||
# retstr += """\t<Folder>\n\t\t<name>Aircraft locations</name>\n\t\t<open>0</open>"""
|
# retstr += """\t<Folder>\n\t\t<name>Aircraft locations</name>\n\t\t<open>0</open>"""
|
||||||
|
|
||||||
#read the database and add KML
|
#read the database and add KML
|
||||||
@ -193,33 +196,6 @@ class output_jsonp(output_kml):
|
|||||||
|
|
||||||
for icao in icaolist:
|
for icao in icaolist:
|
||||||
icao = icao[0]
|
icao = icao[0]
|
||||||
#print "ICAO: %x" % icao
|
|
||||||
# q = "select * from positions where icao=%i and seen > datetime('now', '-2 hour') ORDER BY seen DESC limit 1" % icao
|
|
||||||
# self.locked_execute(c, q)
|
|
||||||
# pos = c.fetchall()
|
|
||||||
#print "Track length: %i" % len(track)
|
|
||||||
# if len(track) != 0:
|
|
||||||
# lat = track[0][3]
|
|
||||||
# if lat is None: lat = 0
|
|
||||||
# lon = track[0][4]
|
|
||||||
# if lon is None: lon = 0
|
|
||||||
# alt = track[0][2]
|
|
||||||
# if alt is None: alt = 0
|
|
||||||
|
|
||||||
# metric_alt = alt * 0.3048 #google earth takes meters, the commie bastards
|
|
||||||
|
|
||||||
# trackstr = ""
|
|
||||||
|
|
||||||
# for pos in track:
|
|
||||||
# trackstr += " %f,%f,%f" % (pos[4], pos[3], pos[2]*0.3048)
|
|
||||||
|
|
||||||
# trackstr = string.lstrip(trackstr)
|
|
||||||
# else:
|
|
||||||
# alt = 0
|
|
||||||
# metric_alt = 0
|
|
||||||
# lat = 0
|
|
||||||
# lon = 0
|
|
||||||
# trackstr = str("")
|
|
||||||
|
|
||||||
#now get metadata
|
#now get metadata
|
||||||
q = "select ident, type from ident where icao=%i" % icao
|
q = "select ident, type from ident where icao=%i" % icao
|
||||||
@ -228,7 +204,9 @@ class output_jsonp(output_kml):
|
|||||||
if len(r) != 0:
|
if len(r) != 0:
|
||||||
ident = r[0][0]
|
ident = r[0][0]
|
||||||
actype = r[0][1]
|
actype = r[0][1]
|
||||||
else: ident=""
|
else:
|
||||||
|
ident=""
|
||||||
|
actype = ""
|
||||||
if ident is None: ident = ""
|
if ident is None: ident = ""
|
||||||
#get most recent speed/heading/vertical
|
#get most recent speed/heading/vertical
|
||||||
q = "select seen, speed, heading, vertical from vectors where icao=%i order by seen desc limit 1" % icao
|
q = "select seen, speed, heading, vertical from vectors where icao=%i order by seen desc limit 1" % icao
|
||||||
@ -257,8 +235,14 @@ class output_jsonp(output_kml):
|
|||||||
lat = 0
|
lat = 0
|
||||||
lon = 0
|
lon = 0
|
||||||
alt = 0
|
alt = 0
|
||||||
#now generate some KML
|
|
||||||
retstr+= """{"icao": "%.6x", "lat": %f, "lon": %f, "alt": %i, "hdg": %i, "speed": %i, "vertical": %i, "ident": "%s", "type": "%s"},""" % (icao, lat, lon, alt, heading, speed, vertical, ident, actype)
|
highlight = 0
|
||||||
|
if hasattr(self, 'highlight'):
|
||||||
|
if self.highlight == icao:
|
||||||
|
highlight = 1
|
||||||
|
|
||||||
|
#now generate some JSONP
|
||||||
|
retstr+= """{"icao": "%.6x", "lat": %f, "lon": %f, "alt": %i, "hdg": %i, "speed": %i, "vertical": %i, "ident": "%s", "type": "%s", "highlight": %i},""" % (icao, lat, lon, alt, heading, speed, vertical, ident, actype, highlight)
|
||||||
|
|
||||||
retstr+= """]);"""
|
retstr+= """]);"""
|
||||||
return retstr
|
return retstr
|
||||||
|
@ -74,7 +74,7 @@ class output_sql:
|
|||||||
#constructor.
|
#constructor.
|
||||||
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)
|
query = self.make_insert_query(message)
|
||||||
if query is not None:
|
if query is not None:
|
||||||
c = self._db.cursor()
|
c = self._db.cursor()
|
||||||
|
Loading…
Reference in New Issue
Block a user