Everything is basically in place for at least live text. For some reason spawning the flowgraph is broken.

This commit is contained in:
Nick Foster 2012-07-03 07:45:34 -07:00
parent 3b533f6b35
commit 113c23b634
5 changed files with 360 additions and 86 deletions

View File

@ -183,7 +183,7 @@ if __name__ == '__main__':
updates = [] #registry of plugin update functions
if options.raw is True:
rawport = air_modes.modes_raw_server()
rawport = air_modes.modes_raw_server(9988) #port
outputs.append(rawport.output)
outputs.append(printraw)
updates.append(rawport.add_pending_conns)
@ -194,7 +194,7 @@ if __name__ == '__main__':
outputs.append(kmlgen.output)
if options.sbs1 is True:
sbs1port = air_modes.modes_output_sbs1(my_position)
sbs1port = air_modes.modes_output_sbs1(my_position, 30003)
outputs.append(sbs1port.output)
updates.append(sbs1port.add_pending_conns)

View File

@ -25,9 +25,9 @@ from string import split, join
from datetime import *
class modes_raw_server:
def __init__(self):
def __init__(self, port):
self._s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._s.bind(('', 9988))
self._s.bind(('', port))
self._s.listen(1)
self._s.setblocking(0) #nonblocking
self._conns = [] #list of active connections

View File

@ -27,11 +27,11 @@ from datetime import *
from modes_exceptions import *
class modes_output_sbs1(modes_parse.modes_parse):
def __init__(self, mypos):
def __init__(self, mypos, port):
modes_parse.modes_parse.__init__(self, mypos)
self._s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self._s.bind(('', 30003))
self._s.bind(('', port))
self._s.listen(1)
self._s.setblocking(0) #nonblocking
self._conns = [] #list of active connections

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
<height>618</height>
</rect>
</property>
<property name="windowTitle">
@ -18,7 +18,7 @@
<property name="geometry">
<rect>
<x>10</x>
<y>220</y>
<y>240</y>
<width>91</width>
<height>281</height>
</rect>
@ -30,7 +30,7 @@
<x>10</x>
<y>10</y>
<width>221</width>
<height>181</height>
<height>191</height>
</rect>
</property>
<property name="title">
@ -62,20 +62,7 @@
<string>Source</string>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>10</x>
<y>90</y>
<width>66</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Gain</string>
</property>
</widget>
<widget class="QComboBox" name="comboSource">
<widget class="QComboBox" name="combo_source">
<property name="geometry">
<rect>
<x>90</x>
@ -85,24 +72,11 @@
</rect>
</property>
</widget>
<widget class="QLabel" name="label_4">
<property name="geometry">
<rect>
<x>10</x>
<y>150</y>
<width>66</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Antenna</string>
</property>
</widget>
<widget class="QLabel" name="label_3">
<property name="geometry">
<rect>
<x>10</x>
<y>120</y>
<y>90</y>
<width>66</width>
<height>17</height>
</rect>
@ -121,54 +95,21 @@
</rect>
</property>
</widget>
<widget class="QLineEdit" name="line_gain">
<property name="geometry">
<rect>
<x>90</x>
<y>90</y>
<width>71</width>
<height>27</height>
</rect>
</property>
</widget>
<widget class="QLineEdit" name="line_threshold">
<property name="geometry">
<rect>
<x>90</x>
<y>120</y>
<y>90</y>
<width>71</width>
<height>27</height>
</rect>
</property>
</widget>
<widget class="QComboBox" name="combo_ant">
<property name="geometry">
<rect>
<x>90</x>
<y>150</y>
<width>121</width>
<height>27</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="label_18">
<property name="geometry">
<rect>
<x>160</x>
<y>90</y>
<width>31</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>dB</string>
</property>
</widget>
<widget class="QLabel" name="label_19">
<property name="geometry">
<rect>
<x>160</x>
<y>120</y>
<y>90</y>
<width>31</width>
<height>17</height>
</rect>
@ -190,13 +131,112 @@
<string>Msps</string>
</property>
</widget>
<widget class="QStackedWidget" name="stack_source">
<property name="geometry">
<rect>
<x>0</x>
<y>120</y>
<width>221</width>
<height>71</height>
</rect>
</property>
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="page_rf">
<widget class="QComboBox" name="combo_ant">
<property name="geometry">
<rect>
<x>90</x>
<y>40</y>
<width>121</width>
<height>27</height>
</rect>
</property>
</widget>
<widget class="QLineEdit" name="line_gain">
<property name="geometry">
<rect>
<x>90</x>
<y>10</y>
<width>71</width>
<height>27</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>66</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Gain</string>
</property>
</widget>
<widget class="QLabel" name="label_4">
<property name="geometry">
<rect>
<x>10</x>
<y>40</y>
<width>66</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Antenna</string>
</property>
</widget>
<widget class="QLabel" name="label_18">
<property name="geometry">
<rect>
<x>160</x>
<y>10</y>
<width>31</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>dB</string>
</property>
</widget>
</widget>
<widget class="QWidget" name="page_file">
<widget class="QLineEdit" name="line_inputfile">
<property name="geometry">
<rect>
<x>90</x>
<y>10</y>
<width>113</width>
<height>27</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="label_13">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>66</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Filename</string>
</property>
</widget>
</widget>
</widget>
</widget>
<widget class="QGroupBox" name="group_output">
<property name="geometry">
<rect>
<x>260</x>
<y>10</y>
<width>341</width>
<width>281</width>
<height>151</height>
</rect>
</property>
@ -365,7 +405,7 @@
<property name="geometry">
<rect>
<x>100</x>
<y>220</y>
<y>240</y>
<width>16</width>
<height>281</height>
</rect>
@ -378,7 +418,7 @@
<property name="geometry">
<rect>
<x>130</x>
<y>200</y>
<y>220</y>
<width>651</width>
<height>301</height>
</rect>
@ -692,7 +732,7 @@
<property name="geometry">
<rect>
<x>10</x>
<y>200</y>
<y>220</y>
<width>101</width>
<height>17</height>
</rect>
@ -704,7 +744,7 @@
<widget class="QPushButton" name="button_start">
<property name="geometry">
<rect>
<x>640</x>
<x>670</x>
<y>30</y>
<width>98</width>
<height>27</height>
@ -718,7 +758,7 @@
<property name="geometry">
<rect>
<x>10</x>
<y>520</y>
<y>540</y>
<width>271</width>
<height>22</height>
</rect>
@ -727,6 +767,68 @@
<string>Show ADS-B-equipped aircraft only</string>
</property>
</widget>
<widget class="QGroupBox" name="groupBox">
<property name="geometry">
<rect>
<x>570</x>
<y>90</y>
<width>211</width>
<height>111</height>
</rect>
</property>
<property name="title">
<string>RX position</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<widget class="QLabel" name="label_29">
<property name="geometry">
<rect>
<x>20</x>
<y>60</y>
<width>71</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Longitude</string>
</property>
</widget>
<widget class="QLineEdit" name="line_my_lon">
<property name="geometry">
<rect>
<x>90</x>
<y>60</y>
<width>113</width>
<height>27</height>
</rect>
</property>
</widget>
<widget class="QLineEdit" name="line_my_lat">
<property name="geometry">
<rect>
<x>90</x>
<y>30</y>
<width>113</width>
<height>27</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="label_28">
<property name="geometry">
<rect>
<x>30</x>
<y>40</y>
<width>61</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Latitude</string>
</property>
</widget>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">

View File

@ -1,11 +1,12 @@
#!/usr/bin/python
import os, sys
import os, sys, time, threading
from PyQt4 import QtCore,QtGui
from test import Ui_MainWindow
from gnuradio import gr, gru, optfir, eng_notation, blks2
import gnuradio.gr.gr_threading as _threading
import air_modes
from test import Ui_MainWindow
import csv
class mainwindow(QtGui.QMainWindow):
def __init__(self):
@ -16,8 +17,8 @@ class mainwindow(QtGui.QMainWindow):
#set defaults
#add file, RTL, UHD sources
self.ui.comboSource.addItems(["UHD device", "RTL-SDR", "File"])
self.ui.comboSource.setCurrentIndex(0)
self.ui.combo_source.addItems(["UHD device", "RTL-SDR", "File"])
self.ui.combo_source.setCurrentIndex(0)
#populate antenna, rate combo boxes based on source
self.populate_source_options()
@ -44,9 +45,17 @@ class mainwindow(QtGui.QMainWindow):
#disable by default
self.ui.check_adsbonly.setCheckState(QtCore.Qt.Unchecked)
self.queue = gr.msg_queue(10)
self.runner = None
self.fg = None
self.outputs = []
self.updates = []
self.output_handler = None
self.kmlgen = None #necessary bc we stop its thread in shutdown
#goes and gets valid antenna, sample rate options from the device and grays out appropriate things
def populate_source_options(self):
sourceid = self.ui.comboSource.currentText()
sourceid = self.ui.combo_source.currentText()
self.rates = []
self.ratetext = []
self.antennas = []
@ -60,23 +69,27 @@ class mainwindow(QtGui.QMainWindow):
self.src = None #deconstruct UHD source for now
self.ui.combo_ant.setEnabled(True)
self.ui.combo_rate.setEnabled(True)
self.ui.stack_source.setCurrentIndex(0)
except:
self.rates = []
self.antennas = []
self.ui.combo_ant.setEnabled(False)
self.ui.combo_rate.setEnabled(False)
self.ui.stack_source.setCurrentIndex(0)
elif sourceid == "RTL-SDR":
self.rates = [2.4e6]
self.antennas = ["RX"]
self.ui.combo_ant.setEnabled(False)
self.ui.combo_rate.setEnabled(False)
self.ui.stack_source.setCurrentIndex(0)
elif sourceid == "File":
self.rates = [2e6, 4e6, 6e6, 8e6, 10e6]
self.antennas = ["None"]
self.ui.combo_ant.setEnabled(False)
self.ui.combo_rate.setEnabled(True)
self.ui.stack_source.setCurrentIndex(1)
self.ui.combo_rate.clear()
self.ratetext = ["%.3f" % (rate / 1.e6) for rate in self.rates]
@ -89,9 +102,168 @@ class mainwindow(QtGui.QMainWindow):
if 4e6 in self.rates:
self.ui.combo_rate.setCurrentIndex(self.rates.index(4e6))
def on_comboSource_currentIndexChanged(self, index):
def on_combo_source_currentIndexChanged(self, index):
self.populate_source_options()
def on_button_start_released(self):
#if we're already running, kill it!
if self.runner is not None:
self.output_handler.done = True
self.output_handler = None
self.fg.stop()
self.runner = None
if self.kmlgen is not None:
self.kmlgen.done = True
#TODO FIXME KMLGEN NEEDS SELFDESTRUCT
#self.kmlgen = None
self.ui.button_start.setText("Start")
else: #we aren't already running, let's get this party started
options = {}
options["source"] = self.ui.combo_source.currentText()
options["rate"] = int(self.ui.combo_rate.currentIndex())
options["antenna"] = self.ui.combo_ant.currentText()
options["gain"] = float(self.ui.line_gain.text())
options["threshold"] = float(self.ui.line_threshold.text())
options["filename"] = str(self.ui.line_inputfile.text())
self.fg = adsb_rx_block(options, self.queue) #create top RX block
self.runner = top_block_runner(self.fg) #spawn new thread to do RX
try:
my_position = [float(self.ui.line_my_lat.text()), float(self.ui.line_my_lon.text())]
except:
my_position = None
self.outputs = []
self.updates = []
#output options to populate outputs, updates
if self.ui.check_kml.checkState():
#we spawn a thread to run every 30 seconds (or whatever) to generate KML
self.kmlgen = air_modes.modes_kml(self.ui.line_kmlfilename.text(), my_position) #create a KML generating thread
self.outputs.append(self.kmlgen.output)
if self.ui.check_sbs1.checkState():
sbs1port = int(self.ui.line_sbs1port.text())
sbs1out = air_modes.modes_output_sbs1(my_position, sbs1port)
self.outputs.append(sbs1out.output)
self.updates.append(sbs1out.add_pending_conns)
if self.ui.check_fgfs.checkState():
fghost = "127.0.0.1" #TODO FIXME
fgport = self.ui.line_fgfsport.currentText()
fgout = air_modes.modes_flightgear(my_position, fghost, int(fgport))
self.outputs.append(fgout.output)
if self.ui.check_raw.checkState():
rawport = air_modes.modes_raw_server(int(self.ui.line_raw.text()))
self.outputs.append(rawport.output)
self.updates.append(rawport.add_pending_conns)
#add output for live data box
self.outputs.append(self.output_live_data)
#create output handler
self.output_handler = output_handler(self.outputs, self.updates, self.queue)
self.ui.button_start.setText("Stop") #modify button text
def output_live_data(self, msg):
self.ui.text_livedata.append(msg)
class output_handler(threading.Thread):
def __init__(self, outputs, updates, queue):
threading.Thread.__init__(self)
self.setDaemon(1)
self.outputs = outputs
self.updates = updates
self.queue = queue
self.done = False
self.start()
def run(self):
while self.done is False:
for update in self.updates:
update()
if not self.queue.empty_p():
msg = self.queue.delete_head()
for output in self.outputs:
try:
output(msg.to_string())
except ADSBError:
pass
time.sleep(0.3)
self.done = True
class top_block_runner(_threading.Thread):
def __init__(self, tb):
_threading.Thread.__init__(self)
self.setDaemon(1)
self.tb = tb
self.done = False
self.start()
def run(self):
self.tb.run()
self.done = True
#Top block for ADSB receiver. If you define a standard interface you
#can make this common code between the GUI app and the cmdline app
class adsb_rx_block (gr.top_block):
def __init__(self, options, queue):
gr.top_block.__init__(self)
self.options = options
rate = int(options["rate"])
use_resampler = False
if options["source"] == "UHD device":
from gnuradio import uhd
self.u = uhd.single_usrp_source("", uhd.io_type_t.COMPLEX_FLOAT32, 1)
time_spec = uhd.time_spec(0.0)
self.u.set_time_now(time_spec)
self.u.set_antenna(options["antenna"])
self.u.set_samp_rate(rate)
self.u.set_gain(options["gain"])
elif options["source"] == "RTL-SDR":
import osmosdr
self.u = osmosdr.source_c()
self.u.set_sample_rate(2.4e6) #fixed for RTL dongles
self.u.set_gain_mode(0) #manual gain mode
self.u.set_gain(options["gain"])
use_resampler = True
elif options["source"] == "File":
self.u = gr.file_source(gr.sizeof_gr_complex, options["filename"])
self.demod = gr.complex_to_mag()
self.avg = gr.moving_average_ff(100, 1.0/100, 400)
self.preamble = air_modes.modes_preamble(rate, options["threshold"])
self.slicer = air_modes.modes_slicer(rate, queue)
if use_resampler:
self.lpfiltcoeffs = gr.firdes.low_pass(1, 5*2.4e6, 1.2e6, 300e3)
self.resample = blks2.rational_resampler_ccf(interpolation=5, decimation=3, taps=self.lpfiltcoeffs)
self.connect(self.u, self.resample, self.demod)
else:
self.connect(self.u, self.demod)
self.connect(self.demod, self.avg)
self.connect(self.demod, (self.preamble, 0))
self.connect(self.avg, (self.preamble, 1))
self.connect((self.preamble, 0), (self.slicer, 0))
def tune(self, freq):
result = self.u.set_center_freq(freq, 0)
return result
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = mainwindow()