diff options
author | Bastian Bloessl <mail@bastibl.net> | 2019-06-18 09:24:35 +0200 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2019-06-19 13:00:00 -0700 |
commit | cb044a4c4b2c6657876f996617a24a44d1ac3b5d (patch) | |
tree | dd6815d0eb2fc9173f726dc602e994a01e94e418 /gnuradio-runtime | |
parent | 3750f748501ec83d60c489dfa700522f3be21b00 (diff) |
ctrport-monitor: fix error handling
Diffstat (limited to 'gnuradio-runtime')
4 files changed, 87 insertions, 123 deletions
diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/GNURadioControlPortClient.py b/gnuradio-runtime/python/gnuradio/ctrlport/GNURadioControlPortClient.py index bee5cd15ed..46ef3cbbae 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/GNURadioControlPortClient.py +++ b/gnuradio-runtime/python/gnuradio/ctrlport/GNURadioControlPortClient.py @@ -30,14 +30,12 @@ is currently the only supported transport. from __future__ import print_function from __future__ import unicode_literals -from argparse import ArgumentParser - from gnuradio.ctrlport.RPCConnection import RPCMethods try: from gnuradio.ctrlport.RPCConnectionThrift import RPCConnectionThrift from thrift.transport.TTransport import TTransportException except ImportError: - # Thrift support not provided we should remove it from RPCMethods + print("ControlPort requires Thrift, but it was not found!") pass @@ -45,8 +43,6 @@ except ImportError: GNURadioControlPortClient is the main class for creating a GNU Radio ControlPort client application for all transports. -Two constructors are provided for creating a connection to ControlPort. - """ class GNURadioControlPortClient(object): @@ -79,61 +75,16 @@ class GNURadioControlPortClient(object): such as QtGui.QApplication.exec_ """ - - def __init__(self, host = None, port = None, rpcmethod = 'thrift', callback = None, blockingcallback = None): - __init__([host, port], rpcmethod, callback, blockingcallback) - - """ - Constructor for creating a ControlPort from a tuple of command line arguments (i.e. sys.argv) - - Args: - argv: List of command line arguments. Future implementations may parse the argument list - for OptionParser style key / value pairs, however the current implementation - simply takes argv[1] and argv[2] as the connection hostname and port, respectively. - - Example Usage: - - In the following QT client example, the ControlPort host and port are specified to - the Client application as the first two command line arguments. The MAINWindow class is - of the type QtGui.QMainWindow, and is the main window for the QT application. MyApp - is a simple helper class for starting the application. - - class MAINWindow(QtGui.QMainWindow): - ... QT Application implementation ... - - class MyApp(object): - def __init__(self, args): - from GNURadioControlPortClient import GNURadioControlPortClient - GNURadioControlPortClient(args, 'thrift', self.run, QtGui.QApplication(sys.argv).exec_) - - def run(self, client): - MAINWindow(client).show() - - MyApp(sys.argv) - - - """ - - def __init__(self, argv = [], rpcmethod = 'thrift', callback = None, blockingcallback = None): - - parser = ArgumentParser(description="GNU Radio Control Port Monitor") - parser.add_argument("host", nargs="?", default="localhost", help="host name or IP") - parser.add_argument("port", help="port") - args = parser.parse_args() - + def __init__(self, host=None, port=None, rpcmethod='thrift', callback=None, blockingcallback=None): self.client = None if rpcmethod in RPCMethods: if rpcmethod == 'thrift': - #print("making RPCConnectionThrift") - self.client = RPCConnectionThrift(args.host, args.port) - #print("made %s" % self.client) + self.client = RPCConnectionThrift(host, port) - #print("making callback call") if not callback is None: callback(self.client) - #print("making blockingcallback call") if not blockingcallback is None: blockingcallback() else: diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnectionThrift.py b/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnectionThrift.py index 3bc4c87308..25618e892c 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnectionThrift.py +++ b/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnectionThrift.py @@ -39,6 +39,8 @@ class ThriftRadioClient(object): self.radio = ControlPort.Client(self.protocol) self.transport.open() + self.host = host + self.port = port def __del__(self): try: @@ -75,7 +77,7 @@ class RPCConnectionThrift(RPCConnection.RPCConnection): # config file, if one is set. Defaults to 9090 otherwise. if port is None: p = gr.prefs() - thrift_config_file = p.get_string("ControlPort", "config", ""); + thrift_config_file = p.get_string("ControlPort", "config", "") if(len(thrift_config_file) > 0): p.add_config_file(thrift_config_file) port = p.get_long("thrift", "port", 9090) @@ -123,6 +125,11 @@ class RPCConnectionThrift(RPCConnection.RPCConnection): self.BaseTypes.C32VECTOR: lambda k: ttypes.Knob(type=k.ktype, value=ttypes.KnobBase(a_c32vector = k.value)), } + def __str__(self): + return "Apache Thrift connection to {0}:{1}".format( + self.thriftclient.host, + self.thriftclient.port) + def unpackKnob(self, key, knob): f = self.unpack_dict.get(knob.type, None) if(f): @@ -140,11 +147,7 @@ class RPCConnectionThrift(RPCConnection.RPCConnection): raise exceptions.ValueError def newConnection(self, host=None, port=None): - try: - self.thriftclient = ThriftRadioClient(host, int(port)) - except: - return None - return self + self.thriftclient = ThriftRadioClient(host, int(port)) def properties(self, *args): knobprops = self.thriftclient.radio.properties(*args) @@ -215,8 +218,7 @@ class RPCConnectionThrift(RPCConnection.RPCConnection): ''' self.thriftclient.radio.postMessage(pmt.serialize_str(pmt.intern(blk_alias)), pmt.serialize_str(pmt.intern(port)), - pmt.serialize_str(msg)); - + pmt.serialize_str(msg)) def printProperties(self, props): info = "" info += "Item:\t\t{0}\n".format(props.description) diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor b/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor index dfaba52c0c..b1f4f321ec 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor +++ b/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor @@ -21,27 +21,30 @@ # from PyQt5 import QtCore, Qt +from argparse import ArgumentParser + import os, sys, time, struct from gnuradio import gr, ctrlport from gnuradio.ctrlport.GrDataPlotter import * +from gnuradio.ctrlport.GNURadioControlPortClient import GNURadioControlPortClient class RateDialog(Qt.QDialog): def __init__(self, delay, parent=None): super(RateDialog, self).__init__(parent) self.gridLayout = Qt.QGridLayout(self) - self.setWindowTitle("Update Delay (ms)"); - self.delay = Qt.QLineEdit(self); - self.delay.setText(str(delay)); + self.setWindowTitle("Update Delay (ms)") + self.delay = Qt.QLineEdit(self) + self.delay.setText(str(delay)) self.buttonBox = Qt.QDialogButtonBox(Qt.QDialogButtonBox.Ok | Qt.QDialogButtonBox.Cancel) - self.gridLayout.addWidget(self.delay); - self.gridLayout.addWidget(self.buttonBox); + self.gridLayout.addWidget(self.delay) + self.gridLayout.addWidget(self.buttonBox) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) def accept(self): - self.done(1); + self.done(1) def reject(self): - self.done(0); + self.done(0) class MAINWindow(Qt.QMainWindow): def minimumSizeHint(self): @@ -50,8 +53,7 @@ class MAINWindow(Qt.QMainWindow): def __init__(self, radioclient): super(MAINWindow, self).__init__() - self.radioclient = radioclient - self.updateRate = 1000; + self.updateRate = 1000 self.conns = [] self.plots = [] self.knobprops = [] @@ -85,16 +87,17 @@ class MAINWindow(Qt.QMainWindow): os.environ['GR_CONF_CONTROLPORT_ON'] = 'False' def setUpdateRate(self,nur): - self.updateRate = int(nur); + self.updateRate = int(nur) for c in self.conns: - c.updateRate = self.updateRate; - c.timer.setInterval(self.updateRate); + c.updateRate = self.updateRate + c.timer.setInterval(self.updateRate) - def newCon(self, csomeBool): - child = MForm(self.radioclient, len(self.conns), parent = self, dialogprompt = not csomeBool) + def newCon(self, radioclient=None): + child = MForm(radioclient, len(self.conns), parent = self) if(child.radioclient is not None): child.setWindowTitle(str(child.radioclient)) self.mdiArea.addSubWindow(child) + child.show() self.mdiArea.currentSubWindow().showMaximized() self.conns.append(child) self.plots.append([]) @@ -316,7 +319,7 @@ class MAINWindow(Qt.QMainWindow): def createActions(self): self.newConAct = Qt.QAction("&New Connection", self, shortcut=Qt.QKeySequence.New, - statusTip="Create a new file", triggered=self.newCon) + statusTip="Create a new file", triggered=lambda x: self.newCon(None)) self.exitAct = Qt.QAction("E&xit", self, shortcut="Ctrl+Q", statusTip="Exit the application", @@ -334,13 +337,13 @@ class MAINWindow(Qt.QMainWindow): statusTip="Change Update Rate", triggered=self.updateRateShow) - qks = Qt.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_T); + qks = Qt.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_T) self.tileAct = Qt.QAction("&Tile", self, statusTip="Tile the windows", triggered=self.mdiArea.tileSubWindows, shortcut=qks) - qks = Qt.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_C); + qks = Qt.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_C) self.cascadeAct = Qt.QAction("&Cascade", self, statusTip="Cascade the windows", shortcut=qks, triggered=self.mdiArea.cascadeSubWindows) @@ -384,13 +387,13 @@ class MAINWindow(Qt.QMainWindow): self.helpMenu.addAction(self.aboutQtAct) def updateRateShow(self): - askrate = RateDialog(self.updateRate, self); + askrate = RateDialog(self.updateRate, self) if askrate.exec_(): - ur = float(str(askrate.delay.text())); - self.setUpdateRate(ur); - return; + ur = float(str(askrate.delay.text())) + self.setUpdateRate(ur) + return else: - return; + return def createToolBars(self): self.fileToolBar = self.addToolBar("File") @@ -451,33 +454,33 @@ class ConInfoDialog(Qt.QDialog): self.gridLayout = Qt.QGridLayout(self) - self.host = Qt.QLineEdit(self); - self.port = Qt.QLineEdit(self); - self.host.setText("localhost"); - self.port.setText("43243"); + self.host = Qt.QLineEdit(self) + self.port = Qt.QLineEdit(self) + self.host.setText("localhost") + self.port.setText("43243") self.buttonBox = Qt.QDialogButtonBox(Qt.QDialogButtonBox.Ok | Qt.QDialogButtonBox.Cancel) - self.gridLayout.addWidget(self.host); - self.gridLayout.addWidget(self.port); - self.gridLayout.addWidget(self.buttonBox); + self.gridLayout.addWidget(self.host) + self.gridLayout.addWidget(self.port) + self.gridLayout.addWidget(self.buttonBox) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) def accept(self): - self.done(1); + self.done(1) def reject(self): - self.done(0); + self.done(0) class UpdaterWindow(Qt.QDialog): def __init__(self, key, radio, parent): Qt.QDialog.__init__(self, parent) - self.key = key; + self.key = key self.radio = radio self.resize(300,200) @@ -594,16 +597,15 @@ class UpdaterWindow(Qt.QDialog): class MForm(Qt.QWidget): def update(self): - # TODO: revisit this try-except block, figure out what it's doing, and if we need to keep it. at very lease makes debugging dificult try: - st = time.time(); + st = time.time() knobs = self.radioclient.getKnobs([]) - ft = time.time(); - latency = ft-st; + ft = time.time() + latency = ft-st self.parent.statusBar().showMessage("Current GNU Radio Control Port Query Latency: %f ms"%(latency*1000)) except Exception as e: - sys.stderr.write("ctrlport-monitor: radio.get threw exception ({0}).\n".format(e)) + sys.stderr.write("ctrlport-monitor: lost connection ({0}).\n".format(e)) if(type(self.parent) is MAINWindow): # Find window of connection remove = [] @@ -614,12 +616,12 @@ class MForm(Qt.QWidget): # Find any subplot windows of connection for p in self.parent.mdiArea.subWindowList(): for plot in self.parent.plots[self.uid]: - if plot.qwidget() == p.widget(): + if plot == p.widget(): remove.append(p) # Clean up local references to these - self.parent.conns.remove(self.parent.conns[self.uid]) - self.parent.plots.remove(self.parent.plots[self.uid]) + self.parent.conns[self.uid] = [] + self.parent.plots[self.uid] = [] # Remove subwindows for connection and plots for r in remove: @@ -640,20 +642,24 @@ class MForm(Qt.QWidget): self.parent.update(knobs, self.uid) - def __init__(self, radioclient, uid=0, updateRate=2000, parent=None, dialogprompt = False): + def __init__(self, radioclient, uid=0, updateRate=2000, parent=None): super(MForm, self).__init__() - self.radioclient = radioclient - if(dialogprompt or radioclient.getHost() is None or radioclient.getPort() is None): - askinfo = ConInfoDialog(self); + + self.radioclient = None + if radioclient is None: + askinfo = ConInfoDialog(self) if askinfo.exec_(): - host = str(askinfo.host.text()); - port = str(askinfo.port.text()); - self.radioclient = self.radioclient.newConnection(host, port) - if self.radioclient is None: - print("Cannot connect to %s:%s" % (host, port)) - else: + host = str(askinfo.host.text()) + port = str(askinfo.port.text()) + + try: + self.radioclient = GNURadioControlPortClient(host, port, 'thrift').client print("Connected to %s:%s" % (host, port)) + except: + print("Cannot connect to %s:%s" % (host, port)) + else: + self.radioclient = radioclient if self.radioclient is None: return @@ -684,7 +690,7 @@ class MForm(Qt.QWidget): # set up timer self.timer.timeout.connect(self.update) - self.updateRate = updateRate; + self.updateRate = updateRate self.timer.start(self.updateRate) # set up context menu .. @@ -737,8 +743,17 @@ def get_minmax(p): class MyApp(object): def __init__(self, args): - from gnuradio.ctrlport.GNURadioControlPortClient import GNURadioControlPortClient - GNURadioControlPortClient(args, 'thrift', self.run, Qt.QApplication(sys.argv).exec_) + + parser = ArgumentParser(description="GNU Radio Control Port Monitor") + parser.add_argument("host", nargs="?", default="localhost", help="host name or IP") + parser.add_argument("port", help="port") + args = parser.parse_args() + + try: + GNURadioControlPortClient(args.host, args.port, 'thrift', self.run, Qt.QApplication(sys.argv).exec_) + except: + print("Control Port failed to connect.") + sys.exit(1) def run(self, client): MAINWindow(client).show() diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/monitor.py b/gnuradio-runtime/python/gnuradio/ctrlport/monitor.py index 3215fa5b26..f8e5882e59 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/monitor.py +++ b/gnuradio-runtime/python/gnuradio/ctrlport/monitor.py @@ -34,15 +34,11 @@ class monitor(object): atexit.register(self.shutdown) # setup export prefs - gr.prefs().singleton().set_bool("ControlPort","on",True); + gr.prefs().singleton().set_bool("ControlPort","on",True) if(tool == "gr-perf-monitorx"): - gr.prefs().singleton().set_bool("ControlPort","edges_list",True); - gr.prefs().singleton().set_bool("PerfCounters","on",True); - gr.prefs().singleton().set_bool("PerfCounters","export",True); - - def __del__(self): - if(self.started): - self.stop() + gr.prefs().singleton().set_bool("ControlPort","edges_list",True) + gr.prefs().singleton().set_bool("PerfCounters","on",True) + gr.prefs().singleton().set_bool("PerfCounters","export",True) def start(self): print("monitor::endpoints() = %s" % (gr.rpcmanager_get().endpoints())) @@ -50,7 +46,7 @@ class monitor(object): ep = gr.rpcmanager_get().endpoints()[0] cmd = [self.tool, re.search(r"-h (\S+|\d+\.\d+\.\d+\.\d+)", ep).group(1), re.search(r"-p (\d+)", ep).group(1)] print("running: %s"%(str(cmd))) - self.proc = subprocess.Popen(cmd); + self.proc = subprocess.Popen(cmd) self.started = True except (ValueError, OSError): self.proc = None @@ -65,6 +61,6 @@ class monitor(object): print("\tno proc to shut down, exiting") def shutdown(self): - print("ctrlport.monitor received shutdown signal") + print("ctrlport monitor received shutdown signal") if(self.started): self.stop() |