diff --git a/htdocs/index.wrx b/htdocs/index.wrx
index 2cd64da..885e3ef 100644
--- a/htdocs/index.wrx
+++ b/htdocs/index.wrx
@@ -22,23 +22,16 @@
OpenWebRX | Open Source SDR Web App for Everyone!
-
+ -->
diff --git a/htdocs/openwebrx.js b/htdocs/openwebrx.js
index c7fd7c0..6efc93d 100644
--- a/htdocs/openwebrx.js
+++ b/htdocs/openwebrx.js
@@ -79,7 +79,8 @@ is_chrome = /Chrome/.test(navigator.userAgent);
function init_rx_photo()
{
- e("webrx-top-photo-clip").style.maxHeight=rx_photo_height.toString()+"px";
+ var clip = e("webrx-top-photo-clip");
+ clip.style.maxHeight=clip.clientHeight+"px";
window.setTimeout(function() { animate(e("webrx-rx-photo-title"),"opacity","",1,0,1,500,30); },1000);
window.setTimeout(function() { animate(e("webrx-rx-photo-desc"),"opacity","",1,0,1,500,30); },1500);
window.setTimeout(function() { close_rx_photo() },2500);
@@ -1145,6 +1146,46 @@ var COMPRESS_FFT_PAD_N=10; //should be the same as in csdr.c
function on_ws_recv(evt)
{
+ if (typeof evt.data == 'string') {
+ // text messages
+ if (evt.data.substr(0, 16) == "CLIENT DE SERVER") {
+ divlog("Server acknowledged WebSocket connection.");
+ } else {
+ try {
+ json = JSON.parse(evt.data)
+ switch (json.type) {
+ case "config":
+ config = json.value;
+ window.waterfall_colors = config.waterfall_colors;
+ window.waterfall_min_level_default = config.waterfall_min_level;
+ window.waterfall_max_level_default = config.waterfall_max_level;
+ window.waterfall_auto_level_margin = config.waterfall_auto_level_margin;
+ waterfallColorsDefault();
+
+ bandwidth = config.samp_rate;
+ center_freq = config.shown_center_freq;
+ fft_size = config.fft_size;
+ fft_fps = config.fft_fps;
+ audio_compression = config.audio_compression;
+ divlog( "Audio stream is "+ ((audio_compression=="adpcm")?"compressed":"uncompressed")+"." )
+ fft_compression = config.fft_compression;
+ divlog( "FFT stream is "+ ((fft_compression=="adpcm")?"compressed":"uncompressed")+"." )
+ max_clients_num = config.max_clients;
+ waterfall_init();
+ audio_preinit();
+ break;
+ default:
+ console.warn('received message of unknown type', json);
+ }
+ } catch (e) {
+ // don't lose exception
+ console.error(e)
+ }
+ }
+ } else if (evt.data instanceof ArrayBuffer) {
+ // binary messages
+ }
+ return
if(!(evt.data instanceof ArrayBuffer)) { divlog("on_ws_recv(): Not ArrayBuffer received...",1); return; }
//
debug_ws_data_received+=evt.data.byteLength/1000;
@@ -1152,8 +1193,6 @@ function on_ws_recv(evt)
first3Chars=first4Chars.slice(0,3);
if(first3Chars=="CLI")
{
- var stringData=arrayBufferToString(evt.data);
- if(stringData.substring(0,16)=="CLIENT DE SERVER") divlog("Server acknowledged WebSocket connection.");
}
if(first3Chars=="AUD")
@@ -1574,7 +1613,7 @@ function parsehash()
if(harr[0]=="mute") toggleMute();
else if(harr[0]=="mod") starting_mod = harr[1];
else if(harr[0]=="sql")
- {
+ { config
e("openwebrx-panel-squelch").value=harr[1];
updateSquelch();
}
@@ -1692,14 +1731,10 @@ String.prototype.startswith=function(str){ return this.indexOf(str) == 0; }; //h
function open_websocket()
{
- //if(ws_url.startswith("ws://localhost:")&&window.location.hostname!="127.0.0.1"&&window.location.hostname!="localhost")
- //{
- //divlog("Server administrator should set server_hostname correctly, because it is left as \"localhost\". Now guessing hostname from page URL.",1);
- ws_url="ws://"+(window.location.origin.split("://")[1])+"/ws/"; //guess automatically -> now default behaviour
- //}
+ ws_url="ws://"+(window.location.origin.split("://")[1])+"/ws/"; //guess automatically -> now default behaviour
if (!("WebSocket" in window))
divlog("Your browser does not support WebSocket, which is required for WebRX to run. Please upgrade to a HTML5 compatible browser.");
- ws = new WebSocket(ws_url+client_id);
+ ws = new WebSocket(ws_url);
ws.onopen = on_ws_opened;
ws.onmessage = on_ws_recv;
ws.onclose = on_ws_closed;
@@ -2196,7 +2231,7 @@ function openwebrx_init()
//Synchronise volume with slider
updateVolume();
- waterfallColorsDefault();
+
}
function iosPlayButtonClick()
diff --git a/owrx/config.py b/owrx/config.py
new file mode 100644
index 0000000..7e4e7e5
--- /dev/null
+++ b/owrx/config.py
@@ -0,0 +1,23 @@
+class Property(object):
+ def __init__(self, value = None):
+ self.value = value
+ def getValue(self):
+ return self.value
+ def setValue(self, value):
+ self.value = value
+
+class PropertyManager(object):
+ sharedInstance = None
+ @staticmethod
+ def getSharedInstance():
+ if PropertyManager.sharedInstance is None:
+ PropertyManager.sharedInstance = PropertyManager()
+ return PropertyManager.sharedInstance
+
+ def __init__(self):
+ self.properties = {}
+
+ def getProperty(self, name):
+ if not name in self.properties:
+ self.properties[name] = Property()
+ return self.properties[name]
diff --git a/owrx/controllers.py b/owrx/controllers.py
index c7989c1..12a4aa2 100644
--- a/owrx/controllers.py
+++ b/owrx/controllers.py
@@ -1,4 +1,6 @@
import mimetypes
+from owrx.websocket import WebSocketConnection
+from owrx.config import PropertyManager
class Controller(object):
def __init__(self, handler, matches):
@@ -12,16 +14,6 @@ class Controller(object):
if (type(content) == str):
content = content.encode()
self.handler.wfile.write(content)
- def serve_file(self, file):
- try:
- f = open('htdocs/' + file, 'rb')
- data = f.read()
- f.close()
-
- (content_type, encoding) = mimetypes.MimeTypes().guess_type(file)
- self.send_response(data, content_type = content_type)
- except FileNotFoundError:
- self.send_response("file not found", code = 404)
def render_template(self, template, **variables):
f = open('htdocs/' + template)
data = f.read()
@@ -38,6 +30,33 @@ class IndexController(Controller):
self.render_template("index.wrx")
class AssetsController(Controller):
+ def serve_file(self, file):
+ try:
+ f = open('htdocs/' + file, 'rb')
+ data = f.read()
+ f.close()
+
+ (content_type, encoding) = mimetypes.MimeTypes().guess_type(file)
+ self.send_response(data, content_type = content_type)
+ except FileNotFoundError:
+ self.send_response("file not found", code = 404)
def handle_request(self):
filename = self.matches.group(1)
- self.serve_file(filename)
\ No newline at end of file
+ self.serve_file(filename)
+
+
+class WebSocketController(Controller):
+ def handle_request(self):
+ conn = WebSocketConnection(self.handler)
+ conn.send("CLIENT DE SERVER openwebrx.py")
+
+ config = {}
+ pm = PropertyManager.getSharedInstance()
+
+ for key in ["waterfall_colors", "waterfall_min_level", "waterfall_max_level", "waterfall_auto_level_margin",
+ "shown_center_freq", "samp_rate", "fft_size", "fft_fps", "audio_compression", "fft_compression",
+ "max_clients"]:
+
+ config[key] = pm.getProperty(key).getValue()
+
+ conn.send({"type":"config","value":config})
diff --git a/owrx/http.py b/owrx/http.py
index b5ac0ae..ab4399b 100644
--- a/owrx/http.py
+++ b/owrx/http.py
@@ -1,4 +1,4 @@
-from owrx.controllers import StatusController, IndexController, AssetsController
+from owrx.controllers import StatusController, IndexController, AssetsController, WebSocketController
from http.server import BaseHTTPRequestHandler
import re
@@ -13,7 +13,8 @@ class Router(object):
mappings = [
{"route": "/", "controller": IndexController},
{"route": "/status", "controller": StatusController},
- {"regex": "/static/(.+)", "controller": AssetsController}
+ {"regex": "/static/(.+)", "controller": AssetsController},
+ {"route": "/ws/", "controller": WebSocketController}
]
def find_controller(self, path):
for m in Router.mappings:
diff --git a/owrx/websocket.py b/owrx/websocket.py
new file mode 100644
index 0000000..8bd305e
--- /dev/null
+++ b/owrx/websocket.py
@@ -0,0 +1,47 @@
+import base64
+import hashlib
+import json
+
+class WebSocketConnection(object):
+ def __init__(self, handler):
+ self.handler = handler
+ my_headers = self.handler.headers.items()
+ my_header_keys = list(map(lambda x:x[0],my_headers))
+ h_key_exists = lambda x:my_header_keys.count(x)
+ h_value = lambda x:my_headers[my_header_keys.index(x)][1]
+ if (not h_key_exists("Upgrade")) or not (h_value("Upgrade")=="websocket") or (not h_key_exists("Sec-WebSocket-Key")):
+ raise WebSocketException
+ ws_key = h_value("Sec-WebSocket-Key")
+ shakey = hashlib.sha1()
+ shakey.update("{ws_key}258EAFA5-E914-47DA-95CA-C5AB0DC85B11".format(ws_key = ws_key).encode())
+ ws_key_toreturn = base64.b64encode(shakey.digest())
+ self.handler.wfile.write("HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: {0}\r\nCQ-CQ-de: HA5KFU\r\n\r\n".format(ws_key_toreturn.decode()).encode())
+
+ def get_header(self, size, opcode):
+ ws_first_byte = 0b10000000 | (opcode & 0x0F)
+ if(size>125):
+ return bytes([ws_first_byte, 126, (size>>8) & 0xff, size & 0xff])
+ else:
+ # 256 bytes binary message in a single unmasked frame
+ return bytes([ws_first_byte, size])
+
+ def send(self, data):
+ # convenience
+ if (type(data) == dict):
+ data = json.dumps(data)
+
+ # string-type messages are sent as text frames
+ if (type(data) == str):
+ header = self.get_header(len(data), 1)
+ self.handler.wfile.write(header)
+ self.handler.wfile.write(data.encode('utf-8'))
+ self.handler.wfile.flush()
+ # anything else as binary
+ else:
+ header = self.get_header(len(data), 2)
+ self.handler.wfile.write(header)
+ self.handler.wfile.write(data.encode())
+ self.handler.wfile.flush()
+
+class WebSocketException(Exception):
+ pass
diff --git a/server.py b/server.py
index 2b14a52..32850a5 100644
--- a/server.py
+++ b/server.py
@@ -1,5 +1,12 @@
from http.server import HTTPServer
from owrx.http import RequestHandler
+from owrx.config import PropertyManager
+
+cfg=__import__("config_webrx")
+pm = PropertyManager.getSharedInstance()
+for name, value in cfg.__dict__.items():
+ if (name.startswith("__")): continue
+ pm.getProperty(name).setValue(value)
server = HTTPServer(('0.0.0.0', 3000), RequestHandler)
server.serve_forever()