Merge remote-tracking branch 'jketterl/develop' into kiwisdr-dev
# Conflicts: # owrx/controllers/status.py
This commit is contained in:
parent
a57b112417
commit
c3b81a754e
BIN
CQWW_CW_2005.fs96k.cf7040.iq.s16.dat
Normal file
BIN
CQWW_CW_2005.fs96k.cf7040.iq.s16.dat
Normal file
Binary file not shown.
@ -43,7 +43,7 @@ web_port = 8073
|
||||
max_clients = 20
|
||||
|
||||
# ==== Web GUI configuration ====
|
||||
receiver_name = "[Callsign]"
|
||||
receiver_name = "OpenWebRX listing test"
|
||||
receiver_location = "Budapest, Hungary"
|
||||
receiver_asl = 200
|
||||
receiver_admin = "example@example.com"
|
||||
@ -65,11 +65,11 @@ Website: <a href="http://localhost" target="_blank">http://localhost</a>
|
||||
# -or-
|
||||
# 1b. Send an email to support@kiwisdr.com and request a new listing key.
|
||||
# Enter the listing key from step 1a or 1b here:
|
||||
listing_key = ""
|
||||
listing_key = "1138"
|
||||
# 2. Use a public domain name or public ip address as the server hostname:
|
||||
server_hostname = "localhost"
|
||||
server_hostname = "openwebrx.kiwisdr.com"
|
||||
# 3. Set this setting to True to enable listing:
|
||||
public_listing = False
|
||||
public_listing = True
|
||||
|
||||
# ==== DSP/RX settings ====
|
||||
fft_fps = 9
|
||||
@ -125,6 +125,36 @@ Note: if you experience audio underruns while CPU usage is 100%, you can:
|
||||
#
|
||||
|
||||
sdrs = {
|
||||
"file": {
|
||||
"name": "file:",
|
||||
"type": "file",
|
||||
"profiles": {
|
||||
"40m": {
|
||||
"name": "40m CQWW-CW 2005 loop",
|
||||
"center_freq": 7040000,
|
||||
"rf_gain": 30,
|
||||
"samp_rate": 96000,
|
||||
"start_freq": 7040000,
|
||||
"start_mod": "lsb",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
'''
|
||||
"kiwisdr": {
|
||||
"name": "KiwiSDR test interface",
|
||||
"type": "KiwiSDR",
|
||||
"profiles": {
|
||||
"MW": {
|
||||
"name": "AM MW",
|
||||
"center_freq": 1440000,
|
||||
"rf_gain": 30,
|
||||
"samp_rate": 12000,
|
||||
"start_freq": 1440000,
|
||||
"start_mod": "am",
|
||||
},
|
||||
},
|
||||
},
|
||||
"rtlsdr": {
|
||||
"name": "RTL-SDR USB Stick",
|
||||
"type": "rtl_sdr",
|
||||
@ -243,6 +273,7 @@ sdrs = {
|
||||
},
|
||||
},
|
||||
}
|
||||
'''
|
||||
|
||||
# ==== Color themes ====
|
||||
|
||||
|
@ -1,11 +1,13 @@
|
||||
from . import Controller
|
||||
from owrx.client import ClientRegistry
|
||||
from owrx.version import openwebrx_version
|
||||
from owrx.sdr import SdrService
|
||||
from owrx.config import Config
|
||||
import os
|
||||
from owrx.receiverid import ReceiverId, KeyException
|
||||
import json
|
||||
import pkg_resources
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class StatusController(Controller):
|
||||
@ -28,6 +30,11 @@ class StatusController(Controller):
|
||||
def indexAction(self):
|
||||
pm = Config.get()
|
||||
avatar_path = pkg_resources.resource_filename("htdocs", "gfx/openwebrx-avatar.png")
|
||||
if "Authorization" in self.request.headers:
|
||||
try:
|
||||
ReceiverId.getResponseHeader(self.request.headers["Authorization"])
|
||||
except KeyException:
|
||||
logger.exception("error processing authorization header")
|
||||
status = {
|
||||
"receiver": {
|
||||
"name": pm["receiver_name"],
|
||||
|
@ -30,6 +30,7 @@ class FeatureDetector(object):
|
||||
"airspyhf": ["soapy_connector", "soapy_airspyhf"],
|
||||
"lime_sdr": ["soapy_connector", "soapy_lime_sdr"],
|
||||
"fifi_sdr": ["alsa", "rockprog"],
|
||||
"file": [],
|
||||
"pluto_sdr": ["soapy_connector", "soapy_pluto_sdr"],
|
||||
"soapy_remote": ["soapy_connector", "soapy_remote"],
|
||||
"uhd": ["soapy_connector", "soapy_uhd"],
|
||||
|
22
owrx/http.py
22
owrx/http.py
@ -35,19 +35,26 @@ class RequestHandler(BaseHTTPRequestHandler):
|
||||
logger.debug("%s - - [%s] %s", self.address_string(), self.log_date_time_string(), format % args)
|
||||
|
||||
def do_GET(self):
|
||||
self.router.route(self, "GET")
|
||||
self.router.route(self, self.get_request("GET"))
|
||||
|
||||
def do_POST(self):
|
||||
self.router.route(self, "POST")
|
||||
self.router.route(self, self.get_request("POST"))
|
||||
|
||||
def get_request(self, method):
|
||||
url = urlparse(self.path)
|
||||
return Request(url, method, self.headers)
|
||||
|
||||
|
||||
class Request(object):
|
||||
def __init__(self, url, method, cookies):
|
||||
def __init__(self, url, method, headers):
|
||||
self.path = url.path
|
||||
self.query = parse_qs(url.query)
|
||||
self.matches = None
|
||||
self.method = method
|
||||
self.cookies = cookies
|
||||
self.headers = headers
|
||||
self.cookies = SimpleCookie()
|
||||
if "Cookie" in headers:
|
||||
self.cookies.load(headers["Cookie"])
|
||||
|
||||
def setMatches(self, matches):
|
||||
self.matches = matches
|
||||
@ -114,12 +121,7 @@ class Router(object):
|
||||
if r.matches(request):
|
||||
return r
|
||||
|
||||
def route(self, handler, method):
|
||||
url = urlparse(handler.path)
|
||||
cookies = SimpleCookie()
|
||||
if "Cookie" in handler.headers:
|
||||
cookies.load(handler.headers["Cookie"])
|
||||
request = Request(url, method, cookies)
|
||||
def route(self, handler, request):
|
||||
route = self.find_route(request)
|
||||
if route is not None:
|
||||
controller = route.controller
|
||||
|
63
owrx/receiverid.py
Normal file
63
owrx/receiverid.py
Normal file
@ -0,0 +1,63 @@
|
||||
import re
|
||||
import logging
|
||||
from owrx.config import Config
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
keyRegex = re.compile("^([a-zA-Z]+)-([0-9a-f]{32})-([0-9a-f]{64})$")
|
||||
keyChallengeRegex = re.compile("^([a-zA-Z]+)-([0-9a-f]{32})-([0-9a-f]{32})$")
|
||||
headerRegex = re.compile("^ReceiverId (.*)$")
|
||||
|
||||
|
||||
class KeyException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class Key(object):
|
||||
def __init__(self, keyString):
|
||||
matches = keyRegex.match(keyString)
|
||||
if not matches:
|
||||
raise KeyException("invalid key format")
|
||||
self.source = matches.group(1)
|
||||
self.id = matches.group(2)
|
||||
self.secret = matches.group(3)
|
||||
|
||||
|
||||
class KeyChallenge(object):
|
||||
def __init__(self, challengeString):
|
||||
matches = keyChallengeRegex.match(challengeString)
|
||||
if not matches:
|
||||
raise KeyException("invalid key challenge format")
|
||||
self.source = matches.group(1)
|
||||
self.id = matches.group(2)
|
||||
self.challenge = matches.group(3)
|
||||
|
||||
|
||||
class KeyResponse(object):
|
||||
def __str__(self):
|
||||
return "TODO"
|
||||
|
||||
|
||||
class ReceiverId(object):
|
||||
@staticmethod
|
||||
def getResponseHeader(requestHeader):
|
||||
matches = headerRegex.match(requestHeader)
|
||||
if not matches:
|
||||
raise KeyException("invalid authorization header")
|
||||
challenge = KeyChallenge(matches.group(1))
|
||||
key = ReceiverId.findKey(challenge)
|
||||
# TODO sign challenge and respond
|
||||
|
||||
@staticmethod
|
||||
def findKey(challenge):
|
||||
def parseKey(keyString):
|
||||
try:
|
||||
return Key(keyString)
|
||||
except KeyError as e:
|
||||
logger.error(e)
|
||||
keys = [key for key in (parseKey(keyString) for keyString in Config.get()['receiver_keys']) if key is not None]
|
||||
matching_keys = [key for key in keys if key.source == challenge.source and key.id == challenge.id]
|
||||
if matching_keys:
|
||||
return matching_keys[0]
|
||||
return None
|
@ -17,10 +17,10 @@ class FifiSdrSource(DirectSource):
|
||||
return super().getEventNames() + ["device"]
|
||||
|
||||
def getFormatConversion(self):
|
||||
return ["csdr convert_s16_f", "csdr gain_ff 30"]
|
||||
return ["csdr convert_s16_f", "csdr gain_ff 5"]
|
||||
|
||||
def sendRockProgFrequency(self, frequency):
|
||||
process = Popen(["rockprog", "--vco", "-w", "--", "freq={}".format(frequency / 1E6)])
|
||||
process = Popen(["rockprog", "--vco", "-w", "--freq={}".format(frequency / 1E6)])
|
||||
process.communicate()
|
||||
rc = process.wait()
|
||||
if rc != 0:
|
||||
|
21
owrx/source/file.py
Normal file
21
owrx/source/file.py
Normal file
@ -0,0 +1,21 @@
|
||||
from owrx.command import Option
|
||||
from .direct import DirectSource
|
||||
from subprocess import Popen
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FileSource(DirectSource):
|
||||
def getCommandMapper(self):
|
||||
file = "CQWW_CW_2005.fs96k.cf7040.iq.s16.dat"
|
||||
bytes_per_sample = 4
|
||||
#sdrProps = getProps()
|
||||
#srate = sdrProps["samp_rate"]
|
||||
srate = 96000
|
||||
cmd = "(while true; do cat {fn}; done) | csdr flowcontrol {sr} 20".format(fn=file,sr=srate*bytes_per_sample*1.05)
|
||||
return super().getCommandMapper().setBase(cmd)
|
||||
|
||||
def getFormatConversion(self):
|
||||
return ["csdr convert_s16_f --bigendian", "csdr iq_swap_ff"]
|
Loading…
x
Reference in New Issue
Block a user