summaryrefslogtreecommitdiff
path: root/gr-zeromq/examples
diff options
context:
space:
mode:
authorJohannes Schmitz <schmitz@ti.rwth-aachen.de>2013-11-25 11:06:20 -0800
committerJohnathan Corgan <johnathan@corganlabs.com>2014-04-22 15:07:20 -0700
commit8672457c57006498b1760ccd59fb11d164333e53 (patch)
tree29433e9596a35c93dd3fef77aa3e9e5aeba2b697 /gr-zeromq/examples
parent73f138eca0dede47a69ab34b1fb1abab76e6bf38 (diff)
Initial import of gr-zmqblocks OOT project as-is, prior to rework for in-tree
Diffstat (limited to 'gr-zeromq/examples')
-rw-r--r--gr-zeromq/examples/CMakeLists.txt25
-rwxr-xr-xgr-zeromq/examples/client.py119
-rwxr-xr-xgr-zeromq/examples/fixui4py.sh2
-rwxr-xr-xgr-zeromq/examples/gui.py165
-rwxr-xr-xgr-zeromq/examples/loop.py141
-rw-r--r--gr-zeromq/examples/main_window.ui199
-rwxr-xr-xgr-zeromq/examples/run_app.sh4
-rwxr-xr-xgr-zeromq/examples/server.py128
8 files changed, 783 insertions, 0 deletions
diff --git a/gr-zeromq/examples/CMakeLists.txt b/gr-zeromq/examples/CMakeLists.txt
new file mode 100644
index 0000000000..c837d77f67
--- /dev/null
+++ b/gr-zeromq/examples/CMakeLists.txt
@@ -0,0 +1,25 @@
+# Copyright 2011 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+include(GrPython)
+
+GR_PYTHON_INSTALL(
+ PROGRAMS
+ DESTINATION bin
+)
diff --git a/gr-zeromq/examples/client.py b/gr-zeromq/examples/client.py
new file mode 100755
index 0000000000..455ae33f50
--- /dev/null
+++ b/gr-zeromq/examples/client.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 Institute for Theoretical Information Technology,
+# RWTH Aachen University
+#
+# Authors: Johannes Schmitz <schmitz@ti.rwth-aachen.de>
+#
+# This is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# This software is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this software; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+
+###############################################################################
+# Imports
+###############################################################################
+import zmqblocks
+from gnuradio import gr
+from gnuradio import blocks
+from gnuradio import analog
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import numpy
+import sys
+from threading import Thread
+import time
+
+###############################################################################
+# GNU Radio top_block
+###############################################################################
+class top_block(gr.top_block):
+ def __init__(self, options):
+ gr.top_block.__init__(self)
+
+ self.options = options
+
+ # socket addresses
+ rpc_adr = "tcp://*:6667"
+ probe_adr = "tcp://*:5557"
+ source_adr = "tcp://"+self.options.servername+":5555"
+
+ # blocks
+ #self.zmq_source = zmqblocks.source_reqrep_nopoll(gr.sizeof_float,source_adr)
+ self.zmq_source = zmqblocks.source_reqrep(gr.sizeof_float,source_adr)
+ #self.zmq_source = zmqblocks.source_pushpull(gr.sizeof_float,source_adr)
+ #self.zmq_probe = zmqblocks.sink_pushpull(gr.sizeof_float,probe_adr)
+ self.zmq_probe = zmqblocks.sink_pubsub(gr.sizeof_float,probe_adr)
+
+ # connects
+ self.connect(self.zmq_source, self.zmq_probe)
+
+ # ZeroMQ
+ self.rpc_manager = zmqblocks.rpc_manager()
+ self.rpc_manager.set_reply_socket(rpc_adr)
+ self.rpc_manager.add_interface("start_fg",self.start_fg)
+ self.rpc_manager.add_interface("stop_fg",self.stop_fg)
+ self.rpc_manager.start_watcher()
+
+ def start_fg(self):
+ print "Start Flowgraph"
+ try:
+ self.start()
+ except RuntimeError:
+ print "Can't start, flowgraph already running!"
+
+ def stop_fg(self):
+ print "Stop Flowgraph"
+ self.stop()
+ self.wait()
+
+###############################################################################
+# Options Parser
+###############################################################################
+def parse_options():
+ """ Options parser. """
+ parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
+ parser.add_option("-s", "--servername", type="string", default="localhost",
+ help="Server hostname")
+ (options, args) = parser.parse_args()
+ return options
+
+###############################################################################
+# Waiter Thread
+###############################################################################
+class waiter(Thread):
+ """ To keep the program alive when flowgraph is stopped. """
+ def run(self):
+ while keep_running:
+ time.sleep(1)
+
+###############################################################################
+# Main
+###############################################################################
+if __name__ == "__main__":
+ options = parse_options()
+ tb = top_block(options)
+ try:
+ # keep the program running when flowgraph is stopped
+ while True:
+ time.sleep(1)
+ except KeyboardInterrupt:
+ pass
+ print "Shutting down flowgraph."
+ tb.rpc_manager.stop_watcher()
+ tb.stop()
+ tb.wait()
+ tb = None
diff --git a/gr-zeromq/examples/fixui4py.sh b/gr-zeromq/examples/fixui4py.sh
new file mode 100755
index 0000000000..d2978000bf
--- /dev/null
+++ b/gr-zeromq/examples/fixui4py.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+sed -i 's/qwt_plot.h/PyQt4.Qwt5.Qwt/' $1
diff --git a/gr-zeromq/examples/gui.py b/gr-zeromq/examples/gui.py
new file mode 100755
index 0000000000..eaa72da323
--- /dev/null
+++ b/gr-zeromq/examples/gui.py
@@ -0,0 +1,165 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 Institute for Theoretical Information Technology,
+# RWTH Aachen University
+#
+# Authors: Johannes Schmitz <schmitz@ti.rwth-aachen.de>
+#
+# This is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# This software is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this software; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+###############################################################################
+# Imports
+###############################################################################
+from optparse import OptionParser
+from gnuradio.eng_option import eng_option
+import gui
+import sys
+import os
+from PyQt4 import Qt, QtGui, QtCore, uic
+import PyQt4.Qwt5 as Qwt
+import zmqblocks
+import signal
+
+class gui(QtGui.QMainWindow):
+ def __init__(self, window_name, options, parent=None):
+ QtGui.QMainWindow.__init__(self, parent)
+
+ # give Ctrl+C back to system
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
+
+ self.gui = uic.loadUi(os.path.join(os.path.dirname(__file__),'main_window.ui'), self)
+
+ self.update_timer = Qt.QTimer()
+
+ # socket addresses
+ rpc_adr_server = "tcp://"+options.servername+":6666"
+ rpc_adr_client = "tcp://"+options.clientname+":6667"
+ probe_adr_server = "tcp://"+options.servername+":5556"
+ probe_adr_client = "tcp://"+options.clientname+":5557"
+
+ # ZeroMQ
+ self.probe_manager = zmqblocks.probe_manager()
+ self.probe_manager.add_socket(probe_adr_server, 'float32', self.plot_data_server)
+ self.probe_manager.add_socket(probe_adr_client, 'float32', self.plot_data_client)
+
+ self.rpc_mgr_server = zmqblocks.rpc_manager()
+ self.rpc_mgr_server.set_request_socket(rpc_adr_server)
+ self.rpc_mgr_client = zmqblocks.rpc_manager()
+ self.rpc_mgr_client.set_request_socket(rpc_adr_client)
+
+ self.gui.setWindowTitle(window_name)
+ self.gui.qwtPlotServer.setTitle("Signal Scope")
+ self.gui.qwtPlotServer.setAxisTitle(Qwt.QwtPlot.xBottom, "Samples")
+ self.gui.qwtPlotServer.setAxisTitle(Qwt.QwtPlot.yLeft, "Amplitude")
+ self.gui.qwtPlotServer.setAxisScale(Qwt.QwtPlot.xBottom, 0, 100)
+ self.gui.qwtPlotServer.setAxisScale(Qwt.QwtPlot.yLeft, -2, 2)
+ self.gui.qwtPlotClient.setTitle("Signal Scope")
+ self.gui.qwtPlotClient.setAxisTitle(Qwt.QwtPlot.xBottom, "Samples")
+ self.gui.qwtPlotClient.setAxisTitle(Qwt.QwtPlot.yLeft, "Amplitude")
+ self.gui.qwtPlotClient.setAxisScale(Qwt.QwtPlot.xBottom, 0, 100)
+ self.gui.qwtPlotClient.setAxisScale(Qwt.QwtPlot.yLeft, -2, 2)
+
+ # Grid
+ pen = Qt.QPen(Qt.Qt.DotLine)
+ pen.setColor(Qt.Qt.black)
+ pen.setWidth(0)
+ grid_server = Qwt.QwtPlotGrid()
+ grid_client = Qwt.QwtPlotGrid()
+ grid_server.setPen(pen)
+ grid_client.setPen(pen)
+ grid_server.attach(self.gui.qwtPlotServer)
+ grid_client.attach(self.gui.qwtPlotClient)
+
+ #Signals
+ self.connect(self.update_timer, QtCore.SIGNAL("timeout()"), self.probe_manager.watcher)
+ self.connect(self.gui.pushButtonRunServer, QtCore.SIGNAL("clicked()"), self.start_fg_server)
+ self.connect(self.gui.pushButtonStopServer, QtCore.SIGNAL("clicked()"), self.stop_fg_server)
+ self.connect(self.gui.pushButtonRunClient, QtCore.SIGNAL("clicked()"), self.start_fg_client)
+ self.connect(self.gui.pushButtonStopClient, QtCore.SIGNAL("clicked()"), self.stop_fg_client)
+ self.connect(self.gui.comboBox, QtCore.SIGNAL("currentIndexChanged(QString)"), self.set_waveform)
+ self.connect(self.gui.spinBox, QtCore.SIGNAL("valueChanged(int)"), self.set_gain)
+ self.shortcut_start = QtGui.QShortcut(Qt.QKeySequence("Ctrl+S"), self.gui)
+ self.shortcut_stop = QtGui.QShortcut(Qt.QKeySequence("Ctrl+C"), self.gui)
+ self.shortcut_exit = QtGui.QShortcut(Qt.QKeySequence("Ctrl+D"), self.gui)
+ self.connect(self.shortcut_exit, QtCore.SIGNAL("activated()"), self.gui.close)
+
+ # start update timer
+ self.update_timer.start(30)
+
+ def start_fg_server(self):
+ self.rpc_mgr_server.request("start_fg")
+
+ def stop_fg_server(self):
+ self.rpc_mgr_server.request("stop_fg")
+
+ def start_fg_client(self):
+ self.rpc_mgr_client.request("start_fg")
+
+ def stop_fg_client(self):
+ self.rpc_mgr_client.request("stop_fg")
+
+ # plot the data from the queues
+ def plot_data(self, plot, samples):
+ self.x = range(0,len(samples),1)
+ self.y = samples
+ # clear the previous points from the plot
+ plot.clear()
+ # draw curve with new points and plot
+ curve = Qwt.QwtPlotCurve()
+ curve.setPen(Qt.QPen(Qt.Qt.blue, 2))
+ curve.attach(plot)
+ curve.setData(self.x, self.y)
+ plot.replot()
+
+ def plot_data_server(self, samples):
+ self.plot_data(self.gui.qwtPlotServer, samples)
+
+ def plot_data_client(self, samples):
+ self.plot_data(self.gui.qwtPlotClient, samples)
+
+ def set_waveform(self, waveform_str):
+ self.rpc_mgr_server.request("set_waveform",str(waveform_str))
+
+ def set_gain(self, gain):
+ self.rpc_set_gain(gain)
+
+ def rpc_set_gain(self, gain):
+ self.rpc_mgr_server.request("set_k",gain)
+
+###############################################################################
+# Options Parser
+###############################################################################
+def parse_options():
+ """ Options parser. """
+ parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
+ parser.add_option("-s", "--servername", type="string", default="localhost",
+ help="Server hostname")
+ parser.add_option("-c", "--clientname", type="string", default="localhost",
+ help="Server hostname")
+ (options, args) = parser.parse_args()
+ return options
+
+
+###############################################################################
+# Main
+###############################################################################
+if __name__ == "__main__":
+ options = parse_options()
+ qapp = Qt.QApplication(sys.argv)
+ qapp.main_window = gui("Remote GNU Radio GUI",options)
+ qapp.main_window.show()
+ qapp.exec_()
+
diff --git a/gr-zeromq/examples/loop.py b/gr-zeromq/examples/loop.py
new file mode 100755
index 0000000000..d2c822b8f7
--- /dev/null
+++ b/gr-zeromq/examples/loop.py
@@ -0,0 +1,141 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 Institute for Theoretical Information Technology,
+# RWTH Aachen University
+#
+# Authors: Johannes Schmitz <schmitz@ti.rwth-aachen.de>
+#
+# This is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# This software is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this software; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+###############################################################################
+# Imports
+###############################################################################
+import zmqblocks
+from gnuradio import gr
+from gnuradio import blocks
+from gnuradio import analog
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import numpy
+import signal
+import gui
+from PyQt4 import QtGui
+import sys
+
+
+###############################################################################
+# GNU Radio top_block
+###############################################################################
+class top_block(gr.top_block):
+ def __init__(self, options):
+ gr.top_block.__init__(self)
+
+ self.options = options
+
+ # create a QT application
+ self.qapp = QtGui.QApplication(sys.argv)
+ # give Ctrl+C back to system
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
+
+ # socket addresses
+ rpc_adr_server = "tcp://localhost:6666"
+ rpc_adr_reply = "tcp://*:6666"
+ probe_adr_gui = "tcp://localhost:5556"
+ probe_adr_fg = "tcp://*:5556"
+ sink_adr = "tcp://*:5555"
+ source_adr = "tcp://localhost:5555"
+
+ # create the main window
+ self.ui = gui.gui("Loop",rpc_adr_server,rpc_adr_server,probe_adr_gui)
+ self.ui.show()
+
+ # the strange sampling rate gives a nice movement in the plot :P
+ self.samp_rate = samp_rate = 48200
+
+ # blocks
+ self.gr_sig_source = analog.sig_source_f(samp_rate, analog.GR_SIN_WAVE , 1000, 1, 0)
+ self.null_source = blocks.null_source(gr.sizeof_float)
+ self.throttle = blocks.throttle(gr.sizeof_float, samp_rate)
+ self.zmq_source = zmqblocks.source_pushpull_feedback(gr.sizeof_float,source_adr)
+ self.mult_a = blocks.multiply_const_ff(1)
+ self.mult_b = blocks.multiply_const_ff(0.5)
+ self.add = blocks.add_ff(1)
+ #self.zmq_sink = zmqblocks.sink_reqrep_nopoll(gr.sizeof_float, sink_adr)
+ #self.zmq_sink = zmqblocks.sink_reqrep(gr.sizeof_float, sink_adr)
+ self.zmq_sink = zmqblocks.sink_pushpull(gr.sizeof_float, sink_adr)
+ self.zmq_probe = zmqblocks.sink_pushpull(gr.sizeof_float, probe_adr_fg)
+ #self.null_sink = blocks.null_sink(gr.sizeof_float)
+
+ # connects
+ self.connect(self.gr_sig_source, self.mult_a)
+ self.connect(self.zmq_source, self.mult_b, (self.add,1))
+# self.connect(self.null_source, (self.add,1))
+ self.connect(self.mult_a, (self.add, 0), self.throttle, self.zmq_sink)
+ self.connect(self.throttle, self.zmq_probe)
+
+ # ZeroMQ
+ self.rpc_manager = zmqblocks.rpc_manager()
+ self.rpc_manager.set_reply_socket(rpc_adr_reply)
+ self.rpc_manager.add_interface("start_fg",self.start_fg)
+ self.rpc_manager.add_interface("stop_fg",self.stop_fg)
+ self.rpc_manager.add_interface("set_waveform",self.set_waveform)
+ self.rpc_manager.add_interface("set_k",self.mult_a.set_k)
+ self.rpc_manager.add_interface("get_sample_rate",self.throttle.sample_rate)
+ self.rpc_manager.start_watcher()
+
+ def start_fg(self):
+ print "Start Flowgraph"
+ try:
+ self.start()
+ except RuntimeError:
+ print "Can't start, flowgraph already running!"
+
+ def stop_fg(self):
+ print "Stop Flowgraph"
+ self.stop()
+ self.wait()
+
+ def set_waveform(self, waveform_str):
+ waveform = {'Constant' : analog.GR_CONST_WAVE,
+ 'Sine' : analog.GR_SIN_WAVE,
+ 'Cosine' : analog.GR_COS_WAVE,
+ 'Square' : analog.GR_SQR_WAVE,
+ 'Triangle' : analog.GR_TRI_WAVE,
+ 'Saw Tooth' : analog.GR_SAW_WAVE}[waveform_str]
+ self.gr_sig_source.set_waveform(waveform)
+
+
+###############################################################################
+# Options Parser
+###############################################################################
+def parse_options():
+ """ Options parser. """
+ parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
+ (options, args) = parser.parse_args()
+ return options
+
+
+###############################################################################
+# Main
+###############################################################################
+if __name__ == "__main__":
+ options = parse_options()
+ tb = top_block(options)
+ tb.qapp.exec_()
+ tb.stop()
+ tb = None
diff --git a/gr-zeromq/examples/main_window.ui b/gr-zeromq/examples/main_window.ui
new file mode 100644
index 0000000000..14f810e67d
--- /dev/null
+++ b/gr-zeromq/examples/main_window.ui
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ControlPort_Example</class>
+ <widget class="QMainWindow" name="ControlPort_Example">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1000</width>
+ <height>600</height>
+ </rect>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>ControlPort Example</string>
+ </property>
+ <widget class="QWidget" name="centralwidget">
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="2">
+ <widget class="QGroupBox" name="groupBox_2">
+ <property name="title">
+ <string>Client</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="1" column="0">
+ <widget class="QPushButton" name="pushButtonRunClient">
+ <property name="text">
+ <string>Run</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="2">
+ <widget class="QwtPlot" name="qwtPlotClient">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QPushButton" name="pushButtonStopClient">
+ <property name="text">
+ <string>Stop</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="1" rowspan="4">
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Waveform:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="comboBox">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>Constant</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Sine</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Cosine</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Square</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Triangle</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Saw Tooth</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Gain:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QSpinBox" name="spinBox">
+ <property name="value">
+ <number>1</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="0" column="0">
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Server</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="1" column="0">
+ <widget class="QPushButton" name="pushButtonRunServer">
+ <property name="text">
+ <string>Run</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QPushButton" name="pushButtonStopServer">
+ <property name="text">
+ <string>Stop</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" colspan="2">
+ <widget class="QwtPlot" name="qwtPlotServer">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="Line" name="line_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="Line" name="line_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menubar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1000</width>
+ <height>25</height>
+ </rect>
+ </property>
+ </widget>
+ <widget class="QStatusBar" name="statusbar"/>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QwtPlot</class>
+ <extends>QFrame</extends>
+ <header>PyQt4.Qwt5.Qwt</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/gr-zeromq/examples/run_app.sh b/gr-zeromq/examples/run_app.sh
new file mode 100755
index 0000000000..a18ff14ee2
--- /dev/null
+++ b/gr-zeromq/examples/run_app.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+export LD_LIBRARY_PATH="$PWD/../build/lib"
+export PYTHONPATH="$PWD/../build/swig:$PWD/../python"
+/usr/bin/python $1 $2 $3 $4 $5 $6 $7 $8 $9
diff --git a/gr-zeromq/examples/server.py b/gr-zeromq/examples/server.py
new file mode 100755
index 0000000000..46bfa591eb
--- /dev/null
+++ b/gr-zeromq/examples/server.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 Institute for Theoretical Information Technology,
+# RWTH Aachen University
+#
+# Authors: Johannes Schmitz <schmitz@ti.rwth-aachen.de>
+#
+# This is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# This software is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this software; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+###############################################################################
+# Imports
+###############################################################################
+import zmqblocks
+from gnuradio import gr
+from gnuradio import blocks
+from gnuradio import analog
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+import numpy
+import sys
+from threading import Thread
+import time
+
+
+###############################################################################
+# GNU Radio top_block
+###############################################################################
+class top_block(gr.top_block):
+ def __init__(self, options):
+ gr.top_block.__init__(self)
+
+ self.options = options
+
+ # socket addresses
+ rpc_adr = "tcp://*:6666"
+ probe_adr = "tcp://*:5556"
+ sink_adr = "tcp://*:5555"
+
+ # the strange sampling rate gives a nice movement in the plot :P
+ self.samp_rate = samp_rate = 48200
+
+ # blocks
+ self.gr_sig_source = analog.sig_source_f(samp_rate, analog.GR_SIN_WAVE , 1000, 1, 0)
+ self.throttle = blocks.throttle(gr.sizeof_float, samp_rate)
+ self.mult = blocks.multiply_const_ff(1)
+ #self.zmq_sink = zmqblocks.sink_reqrep_nopoll(gr.sizeof_float, sink_adr)
+ self.zmq_sink = zmqblocks.sink_reqrep(gr.sizeof_float, sink_adr)
+ #self.zmq_sink = zmqblocks.sink_pushpull(gr.sizeof_float, sink_adr)
+ #self.zmq_probe = zmqblocks.sink_pushpull(gr.sizeof_float, probe_adr)
+ self.zmq_probe = zmqblocks.sink_pubsub(gr.sizeof_float, probe_adr)
+ #self.null_sink = blocks.null_sink(gr.sizeof_float)
+
+ # connects
+ self.connect(self.gr_sig_source, self.mult, self.throttle, self.zmq_sink)
+ self.connect(self.throttle, self.zmq_probe)
+
+ # ZeroMQ
+ self.rpc_manager = zmqblocks.rpc_manager()
+ self.rpc_manager.set_reply_socket(rpc_adr)
+ self.rpc_manager.add_interface("start_fg",self.start_fg)
+ self.rpc_manager.add_interface("stop_fg",self.stop_fg)
+ self.rpc_manager.add_interface("set_waveform",self.set_waveform)
+ self.rpc_manager.add_interface("set_k",self.mult.set_k)
+ self.rpc_manager.add_interface("get_sample_rate",self.throttle.sample_rate)
+ self.rpc_manager.start_watcher()
+
+ def start_fg(self):
+ print "Start Flowgraph"
+ try:
+ self.start()
+ except RuntimeError:
+ print "Can't start, flowgraph already running!"
+
+ def stop_fg(self):
+ print "Stop Flowgraph"
+ self.stop()
+ self.wait()
+
+ def set_waveform(self, waveform_str):
+ waveform = {'Constant' : analog.GR_CONST_WAVE,
+ 'Sine' : analog.GR_SIN_WAVE,
+ 'Cosine' : analog.GR_COS_WAVE,
+ 'Square' : analog.GR_SQR_WAVE,
+ 'Triangle' : analog.GR_TRI_WAVE,
+ 'Saw Tooth' : analog.GR_SAW_WAVE}[waveform_str]
+ self.gr_sig_source.set_waveform(waveform)
+
+###############################################################################
+# Options Parser
+###############################################################################
+def parse_options():
+ """ Options parser. """
+ parser = OptionParser(option_class=eng_option, usage="%prog: [options]")
+ (options, args) = parser.parse_args()
+ return options
+
+###############################################################################
+# Main
+###############################################################################
+if __name__ == "__main__":
+ options = parse_options()
+ tb = top_block(options)
+ try:
+ # keep the program running when flowgraph is stopped
+ while True:
+ time.sleep(1)
+ except KeyboardInterrupt:
+ pass
+ print "Shutting down flowgraph."
+ tb.rpc_manager.stop_watcher()
+ tb.stop()
+ tb.wait()
+ tb = None