aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gui/README.md2
-rwxr-xr-xgui/api/__init__.py24
-rwxr-xr-xgui/run.py16
-rw-r--r--gui/static/js/odr-modulator.js52
-rw-r--r--gui/static/js/odr-predistortion.js40
-rw-r--r--gui/static/js/odr-rcvalues.js31
-rw-r--r--gui/static/js/odr.js109
-rw-r--r--gui/templates/modulator.html80
-rw-r--r--gui/templates/predistortion.html38
9 files changed, 209 insertions, 183 deletions
diff --git a/gui/README.md b/gui/README.md
index 0094a8d..ec55bc9 100644
--- a/gui/README.md
+++ b/gui/README.md
@@ -13,7 +13,7 @@ Make it easier to discover the tuning possibilities of the modulator.
Install
-------
-Install dependencies: cherrypy and jinja2 python modules
+Install dependencies: cherrypy, jinja2, scipy, matplotlib, zmq python modules
Run
---
diff --git a/gui/api/__init__.py b/gui/api/__init__.py
index 6c04a64..74f5feb 100755
--- a/gui/api/__init__.py
+++ b/gui/api/__init__.py
@@ -30,6 +30,12 @@ import os
import io
import datetime
+def send_ok(data):
+ return json.dumps({'status' : 'ok', 'data': data}).encode()
+
+def send_error(data, reason=""):
+ return json.dumps({'status' : 'error', 'reason': reason}).encode()
+
class API:
def __init__(self, mod_rc, dpd):
self.mod_rc = mod_rc
@@ -42,7 +48,7 @@ class API:
@cherrypy.expose
def rc_parameters(self):
cherrypy.response.headers["Content-Type"] = "application/json"
- return json.dumps(self.mod_rc.get_modules()).encode()
+ return send_ok(self.mod_rc.get_modules())
@cherrypy.expose
def parameter(self, **kwargs):
@@ -55,24 +61,24 @@ class API:
self.mod_rc.set_param_value(params['controllable'], params['param'], params['value'])
except ValueError as e:
cherrypy.response.status = 400
- return "{}".format(e)
- return json.dumps("ok").encode()
+ return send_error(str(e))
+ return send_ok(None)
else:
cherrypy.response.headers["Content-Type"] = "application/json"
cherrypy.response.status = 400
- return json.dumps("POST only").encode()
+ return send_error("POST only")
@cherrypy.expose
def trigger_capture(self, **kwargs):
if cherrypy.request.method == 'POST':
- cherrypy.response.headers["Content-Type"] = "text/plain"
- return self.dpd.capture_samples()
+ cherrypy.response.headers["Content-Type"] = "application/json"
+ return send_ok(self.dpd.capture_samples())
else:
- cherrypy.response.headers["Content-Type"] = "text/plain"
+ cherrypy.response.headers["Content-Type"] = "application/json"
cherrypy.response.status = 400
- return "POST only"
+ return send_error("POST only")
@cherrypy.expose
def dpd_status(self, **kwargs):
cherrypy.response.headers["Content-Type"] = "application/json"
- return json.dumps(self.dpd.status()).encode()
+ return send_ok(self.dpd.status())
diff --git a/gui/run.py b/gui/run.py
index 94f6def..3646b2c 100755
--- a/gui/run.py
+++ b/gui/run.py
@@ -32,6 +32,8 @@ import dpd
env = Environment(loader=FileSystemLoader('templates'))
+base_js = ["js/odr.js"]
+
class Root:
def __init__(self, config_file):
self.config_file = config_file
@@ -47,31 +49,29 @@ class Root:
@cherrypy.expose
def about(self):
tmpl = env.get_template("about.html")
- js = []
- return tmpl.render(tab='about', js=js, is_login=False)
+ return tmpl.render(tab='about', js=base_js, is_login=False)
@cherrypy.expose
def home(self):
tmpl = env.get_template("home.html")
- js = []
- return tmpl.render(tab='home', js=js, is_login=False)
+ return tmpl.render(tab='home', js=base_js, is_login=False)
@cherrypy.expose
def rcvalues(self):
tmpl = env.get_template("rcvalues.html")
- js = ["js/odr-rcvalues.js"]
+ js = base_js + ["js/odr-rcvalues.js"]
return tmpl.render(tab='rcvalues', js=js, is_login=False)
@cherrypy.expose
def modulator(self):
tmpl = env.get_template("modulator.html")
- js = ["js/odr-modulator.js"]
+ js = base_js + ["js/odr-modulator.js"]
return tmpl.render(tab='modulator', js=js, is_login=False)
@cherrypy.expose
def predistortion(self):
tmpl = env.get_template("predistortion.html")
- js = ["js/odr-predistortion.js"]
+ js = base_js + ["js/odr-predistortion.js"]
return tmpl.render(tab='predistortion', js=js, is_login=False)
if __name__ == '__main__':
@@ -93,10 +93,10 @@ if __name__ == '__main__':
errorlog = os.path.realpath(os.path.join(config.config['global']['logs_directory'], 'error.log'))
cherrypy.config.update({
+ 'engine.autoreload.on': True,
'server.socket_host': config.config['global']['host'],
'server.socket_port': int(config.config['global']['port']),
'request.show_tracebacks' : True,
- 'environment': 'production',
'tools.sessions.on': False,
'tools.encode.on': True,
'tools.encode.encoding': "utf-8",
diff --git a/gui/static/js/odr-modulator.js b/gui/static/js/odr-modulator.js
index 273d9f7..8538645 100644
--- a/gui/static/js/odr-modulator.js
+++ b/gui/static/js/odr-modulator.js
@@ -18,48 +18,6 @@
// You should have received a copy of the GNU General Public License
// along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>.
-function set_rc(controllable, param, value, callback) {
- $.ajax({
- type: "POST",
- url: "/api/parameter",
- contentType: 'application/json',
- dataType: 'json',
- data: JSON.stringify({
- controllable: controllable,
- param: param,
- value: value
- }),
-
- error: function(data) {
- $.gritter.add({
- title: 'RC set',
- text: "ERROR",
- image: '/fonts/warning.png',
- sticky: true,
- });
- },
- success: callback
- });
-}
-
-function getRc(callback) {
- $.ajax({
- type: "GET",
- url: "/api/rc_parameters",
- contentType: 'application/json',
- dataType: 'json',
-
- error: function(data) {
- $.gritter.add({
- title: 'RC info',
- text: "ERROR: ",
- image: '/fonts/warning.png',
- sticky: true,
- });
- },
- success: callback
- });
-}
function requestAllParams(callback) {
getRc(function(data) {
@@ -86,21 +44,21 @@ $(function(){
requestAllParams();
$('#setdigitalgain').click(function() {
- set_rc("gain", "digital", $('#digitalgain').val(),
+ setRc("gain", "digital", $('#digitalgain').val(),
requestAllParams);
});
$('#setwindowlength').click(function() {
- set_rc("guardinterval", "windowlen", $('#windowlength').val(),
+ setRc("guardinterval", "windowlen", $('#windowlength').val(),
requestAllParams);
});
$('#setclip').click(function() {
- set_rc("ofdm", "clip", $('#cfrclip').val(),
+ setRc("ofdm", "clip", $('#cfrclip').val(),
requestAllParams);
- set_rc("ofdm", "errorclip", $('#cfrerrorclip').val(),
+ setRc("ofdm", "errorclip", $('#cfrerrorclip').val(),
requestAllParams);
- set_rc("ofdm", "cfr",
+ setRc("ofdm", "cfr",
($('#cfrenable').prop("checked") ? "1" : "0"),
requestAllParams);
});
diff --git a/gui/static/js/odr-predistortion.js b/gui/static/js/odr-predistortion.js
index dce3922..13dac7a 100644
--- a/gui/static/js/odr-predistortion.js
+++ b/gui/static/js/odr-predistortion.js
@@ -20,46 +20,14 @@
$(function(){
$('#capturebutton').click(function() {
- $.ajax({
- type: "POST",
- url: "/api/trigger_capture",
- contentType: 'text/plain',
- dataType: '',
- data: '',
-
- error: function(data) {
- $.gritter.add({
- title: 'Capture trigger',
- text: "ERROR",
- image: '/fonts/warning.png',
- sticky: true,
- });
- },
- success: function(data) {
- $('#capturestatus').val(data);
- },
+ doApiRequestPOST("/api/trigger_capture", {}, function(data) {
+ $('#capturestatus').val(data);
});
});
$('#dpdstatusbutton').click(function() {
- $.ajax({
- type: "GET",
- url: "/api/dpd_status",
- contentType: 'application/json',
- dataType: '',
- data: '',
-
- error: function(data) {
- $.gritter.add({
- title: 'DPD Status Update',
- text: "ERROR",
- image: '/fonts/warning.png',
- sticky: true,
- });
- },
- success: function(data) {
- $('#dpdstatus').val(data);
- },
+ doApiRequestGET("/api/dpd_status", function(data) {
+ $('#dpdstatus').val(data);
});
});
});
diff --git a/gui/static/js/odr-rcvalues.js b/gui/static/js/odr-rcvalues.js
index 6d53e8d..f40279d 100644
--- a/gui/static/js/odr-rcvalues.js
+++ b/gui/static/js/odr-rcvalues.js
@@ -21,30 +21,15 @@
function requestStatus(callback) {
$('#rctable > tbody').empty();
- $.ajax({
- type: "GET",
- url: "/api/rc_parameters",
- contentType: 'application/json',
- dataType: 'json',
-
- error: function(data) {
- $.gritter.add({
- title: 'RC info',
- text: "ERROR: ",
- image: '/fonts/warning.png',
- sticky: true,
- });
- },
- success: function(data) {
- $.each( data, function( key1, controllable ) {
- $.each( controllable, function( key2, param ) {
- $('#rctable > tbody:last').append(
- '<tr><td>'+key1+'.'+key2+'</td>'+
- '<td>'+param['value']+'</td>'+
- '<td>'+param['help']+'</td></tr>');
- });
+ doApiRequestGET("/api/rc_parameters", function(data) {
+ $.each( data, function( key1, controllable ) {
+ $.each( controllable, function( key2, param ) {
+ $('#rctable > tbody:last').append(
+ '<tr><td>'+key1+'.'+key2+'</td>'+
+ '<td>'+param['value']+'</td>'+
+ '<td>'+param['help']+'</td></tr>');
});
- }
+ });
});
}
diff --git a/gui/static/js/odr.js b/gui/static/js/odr.js
new file mode 100644
index 0000000..ecb02c5
--- /dev/null
+++ b/gui/static/js/odr.js
@@ -0,0 +1,109 @@
+// Copyright (C) 2018
+// Matthias P. Braendli, matthias.braendli@mpb.li
+//
+// http://www.opendigitalradio.org
+//
+// This file is part of ODR-DabMod.
+//
+// ODR-DabMod 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 of the
+// License, or (at your option) any later version.
+//
+// ODR-DabMod 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 ODR-DabMod. If not, see <http://www.gnu.org/licenses/>.
+
+
+function doApiRequestGET(uri, callback) {
+ $.ajax({
+ type: "GET",
+ url: uri,
+ contentType: 'application/json',
+ dataType: 'json',
+
+ error: function(data) {
+ if (data.status == 500) {
+ var errorWindow = window.open("", "_self");
+ errorWindow.document.write(data.responseText);
+ }
+ else {
+ $.gritter.add({ title: 'API',
+ text: "AJAX failed: " + data.statusText,
+ image: '/fonts/warning.png',
+ sticky: true,
+ });
+ }
+ },
+ success: function(data) {
+ if (data.status == 'ok') {
+ callback(data.data);
+ }
+ else {
+ $.gritter.add({
+ title: 'API',
+ text: "API ERROR: " + data.reason,
+ image: '/fonts/warning.png',
+ sticky: true,
+ });
+ }
+ }
+ });
+}
+
+function doApiRequestPOST(uri, data, callback) {
+ $.ajax({
+ type: "POST",
+ url: uri,
+ contentType: 'application/json',
+ dataType: 'json',
+ data: JSON.stringify(data),
+
+ error: function(data) {
+ if (data.status == 500) {
+ var errorWindow = window.open("", "_self");
+ errorWindow.document.write(data.responseText);
+ }
+ else {
+ $.gritter.add({
+ title: 'API',
+ text: "AJAX failed: " + data.statusText,
+ image: '/fonts/warning.png',
+ sticky: true,
+ });
+ }
+ },
+
+ success: function(data_in) {
+ if (data_in.status == 'ok') {
+ callback(data_in.data);
+ }
+ else {
+ $.gritter.add({
+ title: 'API',
+ text: "API ERROR: " + data_in.reason,
+ image: '/fonts/warning.png',
+ sticky: true,
+ });
+ }
+ }
+ });
+}
+
+function setRc(controllable, param, value, callback) {
+ var data = {
+ controllable: controllable,
+ param: param,
+ value: value
+ };
+ doApiRequestPOST("/api/parameter/", data, callback);
+}
+
+function getRc(callback) {
+ doApiRequestGET("/api/rc_parameters", callback);
+}
+
diff --git a/gui/templates/modulator.html b/gui/templates/modulator.html
index 07e7a82..6deffb1 100644
--- a/gui/templates/modulator.html
+++ b/gui/templates/modulator.html
@@ -24,50 +24,50 @@ along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>.
{% include 'head.html' %}
<body>
- {% include 'body-nav.html' %}
+ {% include 'body-nav.html' %}
- <div class="container-fluid">
- <div class="panel-group">
- <div class="panel panel-default">
- <div class="panel-body">
- <h3>Gain</h3>
- <div class="form-group">
- <label for="digitalgain">Digital Gain:</label>
- <input type="text" class="form-control" id="digitalgain">
- <button type="button" class="btn btn-sm btn-info" id="setdigitalgain">Set</button>
- </div>
- </div>
- <div class="panel-body">
- <h3>OFDM Windowing</h3>
- <div class="form-group">
- <label for="windowlength">Window length:</label>
- <input type="text" class="form-control" id="windowlength">
- <button type="button" class="btn btn-sm btn-info" id="setwindowlength">Set</button>
- </div>
- </div>
- <div class="panel-body">
- <h3>CFR</h3>
- <div class="form-group">
- <div class="checkbox">
- <label><input type="checkbox" value="1" id="cfrenable">Enable</label>
- </div>
-
- <label for="cfrclip">clip:</label>
- <input type="text" class="form-control" id="cfrclip">
-
- <label for="errorclip">error clip:</label>
- <input type="text" class="form-control" id="cfrerrorclip">
- <input type="text" readonly class="form-control" id="cfrstats">
- <input type="text" readonly class="form-control" id="paprstats">
- <button type="button" class="btn btn-sm btn-info" id="setclip">
- Set
- </button>
- </div>
- </div>
+ <div class="container-fluid">
+ <div class="panel-group">
+ <div class="panel panel-default">
+ <div class="panel-body">
+ <h3>Gain</h3>
+ <div class="form-group">
+ <label for="digitalgain">Digital Gain:</label>
+ <input type="text" class="form-control" id="digitalgain">
+ <button type="button" class="btn btn-sm btn-info" id="setdigitalgain">Set</button>
+ </div>
+ </div>
+ <div class="panel-body">
+ <h3>OFDM Windowing</h3>
+ <div class="form-group">
+ <label for="windowlength">Window length:</label>
+ <input type="text" class="form-control" id="windowlength">
+ <button type="button" class="btn btn-sm btn-info" id="setwindowlength">Set</button>
+ </div>
+ </div>
+ <div class="panel-body">
+ <h3>CFR</h3>
+ <div class="form-group">
+ <div class="checkbox">
+ <label><input type="checkbox" value="1" id="cfrenable">Enable</label>
</div>
+ <label for="cfrclip">clip:</label>
+ <input type="text" class="form-control" id="cfrclip">
+
+ <label for="errorclip">error clip:</label>
+ <input type="text" class="form-control" id="cfrerrorclip">
+ <input type="text" readonly class="form-control" id="cfrstats">
+ <input type="text" readonly class="form-control" id="paprstats">
+ <button type="button" class="btn btn-sm btn-info" id="setclip">
+ Set
+ </button>
+ </div>
</div>
- <button type="button" class="btn btn-sm btn-info" id="refresh">Refresh</button>
+ </div>
+
</div>
+ <button type="button" class="btn btn-sm btn-info" id="refresh">Refresh</button>
+ </div>
</body>
</html>
diff --git a/gui/templates/predistortion.html b/gui/templates/predistortion.html
index ef20a16..316c43d 100644
--- a/gui/templates/predistortion.html
+++ b/gui/templates/predistortion.html
@@ -24,26 +24,26 @@ along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>.
{% include 'head.html' %}
<body>
- {% include 'body-nav.html' %}
-
- <div class="container-fluid">
- <div class="panel-group">
- <div class="panel panel-default">
- <div class="panel-body">
- <h3>Capture</h3>
- <div class="form-group">
- <label for="capturestatus">Capture status:</label>
- <input type="text" class="form-control" id="capturestatus">
- <button type="button" class="btn btn-sm btn-info" id="capturebutton">Capture</button>
- </div>
+ {% include 'body-nav.html' %}
+
+ <div class="container-fluid">
+ <div class="panel-group">
+ <div class="panel panel-default">
+ <div class="panel-body">
+ <h3>Capture</h3>
+ <div class="form-group">
+ <label for="capturestatus">Capture status:</label>
+ <input type="text" class="form-control" id="capturestatus">
+ <button type="button" class="btn btn-sm btn-info" id="capturebutton">Capture</button>
+ </div>
+ </div>
+ <div class="panel-body">
+ <h3>Status</h3>
+ <button type="button" class="btn btn-sm btn-info" id="dpdstatusbutton">Update</button>
+ <div id="dpdstatus"></div>
+ </div>
+ </div>
</div>
- <div class="panel-body">
- <h3>Status</h3>
- <button type="button" class="btn btn-sm btn-info" id="dpdstatusbutton">Update</button>
- <div id="dpdstatus"></div>
- </div>
- </div>
</div>
- </div>
</body>
</html>