I am currently working on a GNU Radio project to generate analog signal from an USRP. I have to create a local html page to control this.
So in my php script (first_php.php), I have :
<?php
//echo exec('python testpython.py'); // Test python script : works !
echo shell_exec("./testscript.sh"); // Echo to see the output
echo '<br/>Current script owner: ' . get_current_user();
?>
In testscript.sh, I have
python top_block.py &
My Python script is quite extensive, but basically, in the main function, I am calling "Qt.QApplication(sys.argv)" and it doesn't work.
The python code is the following :
# -*- coding: utf-8 -*-
##################################################
# GNU Radio Python Flow Graph
# Title: Top Block
# Generated: Mon Jul 3 14:59:12 2017
##################################################
print "Starting Top Block Execution <br/>"
if __name__ == '__main__':
import ctypes
import sys
if sys.platform.startswith('linux'):
try:
x11 = ctypes.cdll.LoadLibrary('libX11.so')
x11.XInitThreads()
except:
print "Warning: failed to XInitThreads()"
print "Step 1 : Imports <br/>"
import os
print " - Step 1.1 : Importing [os] <br/>"
import sys
print " - Step 1.2 : Importing [sys] <br/>"
print " - - Step 1.2.1 : Adding correct PATH to [sys.path] <br/>"
sys.path.append(os.environ.get('GRC_HIER_PATH', os.path.expanduser('~/.grc_gnuradio')))
print " - - "
print sys.path
print "<br/>"
print " - - Step 1.2.1 : Adding DME_station PATH to [sys.path] <br/>"
sys.path.append('/home/myusername/.grc_gnuradio')
print " - - "
print sys.path
print "<br/>"
print " - Step 1.3 : Importing [DME_station] <br/>"
from DME_station import DME_station # grc-generated hier_block
print " - Step 1.4 : Importing [PyQt4] from [Qt] <br/>"
from PyQt4 import Qt
print " - Step 1.5 : Importing [blocks] from [gnuradio]<br/>"
from gnuradio import blocks
print " - Step 1.6 : Importing [eng_notation] from [gnuradio]<br/>"
from gnuradio import eng_notation
print " - Step 1.7 : Importing [gr] from [gnuradio]<br/>"
from gnuradio import gr
print " - Step 1.8 : Importing [qtgui] from [gnuradio]<br/>"
from gnuradio import qtgui
print " - Step 1.9 : Importing [eng_option] from [gnuradio.eng_option]<br/>"
from gnuradio.eng_option import eng_option
print " - Step 1.10 : Importing [firdes] from [gnuradio.filter]<br/>"
from gnuradio.filter import firdes
print " - Step 1.11 : Importing [OptionParser] from [optparse]<br/>"
from optparse import OptionParser
print " - Step 1.12 : Importing [DME]<br/>"
import DME
print " - Step 1.13 : Importing [sip]<br/>"
import sip
print " - Step 1.14 : Importing [threading]<br/>"
import threading
print " - Step 1.15 : Importing [time]<br/>"
import time
print "Step 2 : class top_block <br/>"
class top_block(gr.top_block, Qt.QWidget):
def __init__(self):
gr.top_block.__init__(self, "Top Block")
Qt.QWidget.__init__(self)
self.setWindowTitle("Top Block")
try:
self.setWindowIcon(Qt.QIcon.fromTheme('gnuradio-grc'))
except:
pass
self.top_scroll_layout = Qt.QVBoxLayout()
self.setLayout(self.top_scroll_layout)
self.top_scroll = Qt.QScrollArea()
self.top_scroll.setFrameStyle(Qt.QFrame.NoFrame)
self.top_scroll_layout.addWidget(self.top_scroll)
self.top_scroll.setWidgetResizable(True)
self.top_widget = Qt.QWidget()
self.top_scroll.setWidget(self.top_widget)
self.top_layout = Qt.QVBoxLayout(self.top_widget)
self.top_grid_layout = Qt.QGridLayout()
self.top_layout.addLayout(self.top_grid_layout)
self.settings = Qt.QSettings("GNU Radio", "top_block")
self.restoreGeometry(self.settings.value("geometry").toByteArray())
##################################################
# Variables
##################################################
self.d_nm = d_nm = 10
self.DMEOutputFreq_0 = DMEOutputFreq_0 = 0
self.DMEInputFreq_0 = DMEInputFreq_0 = 0
self.variable_qtgui_label_0_1 = variable_qtgui_label_0_1 = DMEInputFreq_0
self.variable_qtgui_label_0_0_0 = variable_qtgui_label_0_0_0 = DMEOutputFreq_0
self.samp_rate = samp_rate = 10000000
self.k = k = 0.0
self.d_m = d_m = float((d_nm*1852))
self.c = c = 299792458.0
self.NAV = NAV = 108000000
##################################################
# Blocks
##################################################
self.widget = Qt.QTabWidget()
self.widget_widget_0 = Qt.QWidget()
self.widget_layout_0 = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom, self.widget_widget_0)
self.widget_grid_layout_0 = Qt.QGridLayout()
self.widget_layout_0.addLayout(self.widget_grid_layout_0)
self.widget.addTab(self.widget_widget_0, "DME_Generator/Detector Test")
self.widget_widget_1 = Qt.QWidget()
self.widget_layout_1 = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom, self.widget_widget_1)
self.widget_grid_layout_1 = Qt.QGridLayout()
self.widget_layout_1.addLayout(self.widget_grid_layout_1)
self.widget.addTab(self.widget_widget_1, "DME_Response Test")
self.widget_widget_2 = Qt.QWidget()
self.widget_layout_2 = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom, self.widget_widget_2)
self.widget_grid_layout_2 = Qt.QGridLayout()
self.widget_layout_2.addLayout(self.widget_grid_layout_2)
self.widget.addTab(self.widget_widget_2, "Final Simulation")
self.widget_widget_3 = Qt.QWidget()
self.widget_layout_3 = Qt.QBoxLayout(Qt.QBoxLayout.TopToBottom, self.widget_widget_3)
self.widget_grid_layout_3 = Qt.QGridLayout()
self.widget_layout_3.addLayout(self.widget_grid_layout_3)
self.widget.addTab(self.widget_widget_3, "Station Block Simulation")
self.top_layout.addWidget(self.widget)
self._d_nm_tool_bar = Qt.QToolBar(self)
self._d_nm_tool_bar.addWidget(Qt.QLabel("d_nm"+": "))
self._d_nm_line_edit = Qt.QLineEdit(str(self.d_nm))
self._d_nm_tool_bar.addWidget(self._d_nm_line_edit)
self._d_nm_line_edit.returnPressed.connect(
lambda: self.set_d_nm(int(str(self._d_nm_line_edit.text().toAscii()))))
self.widget_layout_3.addWidget(self._d_nm_tool_bar)
self._NAV_tool_bar = Qt.QToolBar(self)
self._NAV_tool_bar.addWidget(Qt.QLabel("NAV"+": "))
self._NAV_line_edit = Qt.QLineEdit(str(self.NAV))
self._NAV_tool_bar.addWidget(self._NAV_line_edit)
self._NAV_line_edit.returnPressed.connect(
lambda: self.set_NAV(int(str(self._NAV_line_edit.text().toAscii()))))
self.widget_layout_3.addWidget(self._NAV_tool_bar)
self.DME_station_0 = DME_station(
NAV_freq=NAV,
d_nm=10,
)
self._variable_qtgui_label_0_1_tool_bar = Qt.QToolBar(self)
if None:
self._variable_qtgui_label_0_1_formatter = None
else:
self._variable_qtgui_label_0_1_formatter = lambda x: x
self._variable_qtgui_label_0_1_tool_bar.addWidget(Qt.QLabel("DME Input Frequency"+": "))
self._variable_qtgui_label_0_1_label = Qt.QLabel(str(self._variable_qtgui_label_0_1_formatter(self.variable_qtgui_label_0_1)))
self._variable_qtgui_label_0_1_tool_bar.addWidget(self._variable_qtgui_label_0_1_label)
self.widget_layout_3.addWidget(self._variable_qtgui_label_0_1_tool_bar)
self._variable_qtgui_label_0_0_0_tool_bar = Qt.QToolBar(self)
if None:
self._variable_qtgui_label_0_0_0_formatter = None
else:
self._variable_qtgui_label_0_0_0_formatter = lambda x: x
self._variable_qtgui_label_0_0_0_tool_bar.addWidget(Qt.QLabel("DME Output Frequency"+": "))
self._variable_qtgui_label_0_0_0_label = Qt.QLabel(str(self._variable_qtgui_label_0_0_0_formatter(self.variable_qtgui_label_0_0_0)))
self._variable_qtgui_label_0_0_0_tool_bar.addWidget(self._variable_qtgui_label_0_0_0_label)
self.widget_layout_3.addWidget(self._variable_qtgui_label_0_0_0_tool_bar)
self.qtgui_time_sink_x_0_0_1_0_0_0 = qtgui.time_sink_f(
2048, #size
samp_rate, #samp_rate
"Response Generator", #name
2 #number of inputs
)
self.qtgui_time_sink_x_0_0_1_0_0_0.set_update_time(0.05)
self.qtgui_time_sink_x_0_0_1_0_0_0.set_y_axis(-1, 1)
self.qtgui_time_sink_x_0_0_1_0_0_0.set_y_label("Amplitude", "")
self.qtgui_time_sink_x_0_0_1_0_0_0.enable_tags(-1, True)
self.qtgui_time_sink_x_0_0_1_0_0_0.set_trigger_mode(qtgui.TRIG_MODE_FREE, qtgui.TRIG_SLOPE_POS, 0.0, 0, 0, "")
self.qtgui_time_sink_x_0_0_1_0_0_0.enable_autoscale(False)
self.qtgui_time_sink_x_0_0_1_0_0_0.enable_grid(False)
self.qtgui_time_sink_x_0_0_1_0_0_0.enable_control_panel(True)
if not True:
self.qtgui_time_sink_x_0_0_1_0_0_0.disable_legend()
labels = ["", "", "", "", "",
"", "", "", "", ""]
widths = [1, 1, 1, 1, 1,
1, 1, 1, 1, 1]
colors = ["blue", "red", "green", "black", "cyan",
"magenta", "yellow", "dark red", "dark green", "blue"]
styles = [1, 1, 1, 1, 1,
1, 1, 1, 1, 1]
markers = [-1, -1, -1, -1, -1,
-1, -1, -1, -1, -1]
alphas = [1.0, 1.0, 1.0, 1.0, 1.0,
1.0, 1.0, 1.0, 1.0, 1.0]
for i in xrange(2):
if len(labels[i]) == 0:
self.qtgui_time_sink_x_0_0_1_0_0_0.set_line_label(i, "Data {0}".format(i))
else:
self.qtgui_time_sink_x_0_0_1_0_0_0.set_line_label(i, labels[i])
self.qtgui_time_sink_x_0_0_1_0_0_0.set_line_width(i, widths[i])
self.qtgui_time_sink_x_0_0_1_0_0_0.set_line_color(i, colors[i])
self.qtgui_time_sink_x_0_0_1_0_0_0.set_line_style(i, styles[i])
self.qtgui_time_sink_x_0_0_1_0_0_0.set_line_marker(i, markers[i])
self.qtgui_time_sink_x_0_0_1_0_0_0.set_line_alpha(i, alphas[i])
self._qtgui_time_sink_x_0_0_1_0_0_0_win = sip.wrapinstance(self.qtgui_time_sink_x_0_0_1_0_0_0.pyqwidget(), Qt.QWidget)
self.widget_layout_3.addWidget(self._qtgui_time_sink_x_0_0_1_0_0_0_win)
self.blocks_throttle_0_0 = blocks.throttle(gr.sizeof_float*1, samp_rate/10,True)
self.DME_Pulse_Generator_0_0 = DME.Pulse_Generator(samp_rate)
def _DMEOutputFreq_0_probe():
while True:
val = self.DME_station_0.DME_Pairing_VOR_DME_0.getDMEOutputFreq()
try:
self.set_DMEOutputFreq_0(val)
except AttributeError:
pass
time.sleep(1.0 / (10))
_DMEOutputFreq_0_thread = threading.Thread(target=_DMEOutputFreq_0_probe)
_DMEOutputFreq_0_thread.daemon = True
_DMEOutputFreq_0_thread.start()
def _DMEInputFreq_0_probe():
while True:
val = self.DME_station_0.DME_Pairing_VOR_DME_0.getDMEInputFreq()
try:
self.set_DMEInputFreq_0(val)
except AttributeError:
pass
time.sleep(1.0 / (10))
_DMEInputFreq_0_thread = threading.Thread(target=_DMEInputFreq_0_probe)
_DMEInputFreq_0_thread.daemon = True
_DMEInputFreq_0_thread.start()
##################################################
# Connections
##################################################
self.connect((self.DME_Pulse_Generator_0_0, 0), (self.blocks_throttle_0_0, 0))
self.connect((self.DME_station_0, 0), (self.qtgui_time_sink_x_0_0_1_0_0_0, 1))
self.connect((self.blocks_throttle_0_0, 0), (self.DME_station_0, 0))
self.connect((self.blocks_throttle_0_0, 0), (self.qtgui_time_sink_x_0_0_1_0_0_0, 0))
def closeEvent(self, event):
self.settings = Qt.QSettings("GNU Radio", "top_block")
self.settings.setValue("geometry", self.saveGeometry())
event.accept()
def get_d_nm(self):
return self.d_nm
def set_d_nm(self, d_nm):
self.d_nm = d_nm
self.set_d_m(float((self.d_nm*1852)))
Qt.QMetaObject.invokeMethod(self._d_nm_line_edit, "setText", Qt.Q_ARG("QString", str(self.d_nm)))
def get_DMEOutputFreq_0(self):
return self.DMEOutputFreq_0
def set_DMEOutputFreq_0(self, DMEOutputFreq_0):
self.DMEOutputFreq_0 = DMEOutputFreq_0
self.set_variable_qtgui_label_0_0_0(self._variable_qtgui_label_0_0_0_formatter(self.DMEOutputFreq_0))
def get_DMEInputFreq_0(self):
return self.DMEInputFreq_0
def set_DMEInputFreq_0(self, DMEInputFreq_0):
self.DMEInputFreq_0 = DMEInputFreq_0
self.set_variable_qtgui_label_0_1(self._variable_qtgui_label_0_1_formatter(self.DMEInputFreq_0))
def get_variable_qtgui_label_0_1(self):
return self.variable_qtgui_label_0_1
def set_variable_qtgui_label_0_1(self, variable_qtgui_label_0_1):
self.variable_qtgui_label_0_1 = variable_qtgui_label_0_1
Qt.QMetaObject.invokeMethod(self._variable_qtgui_label_0_1_label, "setText", Qt.Q_ARG("QString", str(self.variable_qtgui_label_0_1)))
def get_variable_qtgui_label_0_0_0(self):
return self.variable_qtgui_label_0_0_0
def set_variable_qtgui_label_0_0_0(self, variable_qtgui_label_0_0_0):
self.variable_qtgui_label_0_0_0 = variable_qtgui_label_0_0_0
Qt.QMetaObject.invokeMethod(self._variable_qtgui_label_0_0_0_label, "setText", Qt.Q_ARG("QString", str(self.variable_qtgui_label_0_0_0)))
def get_samp_rate(self):
return self.samp_rate
def set_samp_rate(self, samp_rate):
self.samp_rate = samp_rate
self.qtgui_time_sink_x_0_0_1_0_0_0.set_samp_rate(self.samp_rate)
self.blocks_throttle_0_0.set_sample_rate(self.samp_rate/10)
def get_k(self):
return self.k
def set_k(self, k):
self.k = k
def get_d_m(self):
return self.d_m
def set_d_m(self, d_m):
self.d_m = d_m
def get_c(self):
return self.c
def set_c(self, c):
self.c = c
def get_NAV(self):
return self.NAV
def set_NAV(self, NAV):
self.NAV = NAV
Qt.QMetaObject.invokeMethod(self._NAV_line_edit, "setText", Qt.Q_ARG("QString", str(self.NAV)))
self.DME_station_0.set_NAV_freq(self.NAV)
print "Step 3 : main function definition <br/>"
def main(top_block_cls=top_block, options=None):
from distutils.version import StrictVersion
print " - Step 3.1 : Setting Qt version, style"
if StrictVersion(Qt.qVersion()) >= StrictVersion("4.5.0"):
print " - - Step 3.1.1 : Setting Qt style"
style = gr.prefs().get_string('qtgui', 'style', 'raster')
Qt.QApplication.setGraphicsSystem(style)
print " - - Step 3.1.1 : Setting Qt app"
qapp = Qt.QApplication(sys.argv)
print " - Step 3.2 : Initializing, starting and showing tob block"
tb = top_block_cls()
tb.start()
tb.show()
def quitting():
tb.stop()
tb.wait()
qapp.connect(qapp, Qt.SIGNAL("aboutToQuit()"), quitting)
qapp.exec_()
if __name__ == '__main__':
main()
print "Top Block Output
"
I am using Ubuntu 16.04.1 on a Parallels Desktop VM,aAnd I am trying to accomplish this either from Safari browser (macOS Sierra) or Chrome (Ubuntu on the VM). The script's behavior is the same in either case (including "localhost" instead of IP dress in Chrome)
I have added prints to the Python code to analyse where the code stops running. The output in the html page is :
Starting Top Block Execution
Step 1 : Imports
- Step 1.1 : Importing [os]
- Step 1.2 : Importing [sys]
- - Step 1.2.1 : Adding correct PATH to [sys.path]
- - ['/var/www/html', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PILcompat', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/python2.7/dist-packages/wx-3.0-gtk2', '/var/www/.grc_gnuradio']
- - Step 1.2.1 : Adding DME_station PATH to [sys.path]
- - ['/var/www/html', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PILcompat', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/python2.7/dist-packages/wx-3.0-gtk2', '/var/www/.grc_gnuradio', '/home/clovel/.grc_gnuradio']
- Step 1.3 : Importing [DME_station]
- Step 1.4 : Importing [PyQt4] from [Qt]
- Step 1.5 : Importing [blocks] from [gnuradio]
- Step 1.6 : Importing [eng_notation] from [gnuradio]
- Step 1.7 : Importing [gr] from [gnuradio]
- Step 1.8 : Importing [qtgui] from [gnuradio]
- Step 1.9 : Importing [eng_option] from [gnuradio.eng_option]
- Step 1.10 : Importing [firdes] from [gnuradio.filter]
- Step 1.11 : Importing [OptionParser] from [optparse]
- Step 1.12 : Importing [DME]
- Step 1.13 : Importing [sip]
- Step 1.14 : Importing [threading]
- Step 1.15 : Importing [time]
Step 2 : class top_block
Step 3 : main function definition
- Step 3.1 : Setting Qt version, style - - Step 3.1.1 : Setting Qt style - - Step 3.1.1 : Setting Qt app
Current script owner: www-data
If I use "exec" instead of "shell_exec", the output is only :
- - Step 3.1.1 : Setting Qt app
Current script owner: www-data
I am new to HTML/PHP coding. This is my first question on StackOverflow. Don't hesitate to tell me if info is missing.
Thanks a lot for your time, Clovel
EDIT 1 : It works seamlessly with the "php first_php.php" command in the terminal