Fix adjacent channel detection, add debug flask endpoints.

pull/169/head
Mark Jessop 2019-05-04 12:42:24 +09:30
rodzic ef34b6496f
commit 8547c724c6
5 zmienionych plików z 102 dodań i 42 usunięć

Wyświetl plik

@ -68,7 +68,7 @@ temporary_block_list = {}
# Scan Result Queue
# Scan results are processed asynchronously from the main scanner object.
scan_results = Queue()
#scan_results = Queue()
def allocate_sdr(check_only = False, task_description = ""):
@ -100,7 +100,7 @@ def allocate_sdr(check_only = False, task_description = ""):
def start_scanner():
""" Start a scanner thread on the first available SDR """
global config, scan_results, RS_PATH, temporary_block_list
global config, RS_PATH, temporary_block_list
if 'SCAN' in autorx.task_list:
# Already a scanner running! Return.
@ -119,7 +119,7 @@ def start_scanner():
# Init Scanner using settings from the global config.
# TODO: Nicer way of passing in the huge list of args.
autorx.task_list['SCAN']['task'] = SondeScanner(
callback = scan_results.put,
callback = autorx.scan_results.put,
auto_start = True,
min_freq = config['min_freq'],
max_freq = config['max_freq'],
@ -182,36 +182,6 @@ def start_decoder(freq, sonde_type):
"""
global config, RS_PATH, exporter_functions, rs92_ephemeris, temporary_block_list
# Check the frequency is not in our temporary block list
# (This may happen from time-to-time depending on the timing of the scan thread)
if freq in temporary_block_list.keys():
if temporary_block_list[freq] > (time.time()-config['temporary_block_time']*60):
logging.error("Task Manager - Attempted to start a decoder on a temporarily blocked frequency (%.3f MHz)" % (freq/1e6))
return
else:
# This frequency should not be blocked any more, remove it from the block list.
logging.info("Task Manager - Removed %.3f MHz from temporary block list." % (freq/1e6))
temporary_block_list.pop(freq)
# Check that we are not attempting to start a decoder too close to an existing decoder for known 'drifty' radiosonde types.
# 'Too close' is defined by the 'decoder_spacing_limit' advanced coniguration option.
for _key in autorx.task_list.keys():
# Iterate through the task list, and only attempt to compare with those that are a decoder task.
# This is indicated by the task key being an integer (the sonde frequency).
if (type(_key) == int) or (type(_key) == float):
# Extract the currently decoded sonde type from the currently running decoder.
_decoding_sonde_type = autorx.task_list[_key]['task'].sonde_type
# Only check the frequency spacing if we have a known 'drifty' sonde type, *and* the new sonde type is of the same type.
if (_decoding_sonde_type in DRIFTY_SONDE_TYPES) and (_decoding_sonde_type == sonde_type):
if (abs(_key - freq) < config['decoder_spacing_limit']):
# At this point, we can be pretty sure that there is another decoder already decoding this particular sonde ID.
# Without actually starting another decoder and matching IDs, we can't be 100% sure, but it's a good chance.
logging.error("Task Manager - Attempted to start a %s decoder within %d kHz of an already running decoder. (This limit can be set using the 'decoder_spacing_limit' advanced config option.)" % (sonde_type, config['decoder_spacing_limit']/1e3))
return
# Allocate a SDR.
_device_idx = allocate_sdr(task_description="Decoder (%s, %.3f MHz)" % (sonde_type, freq/1e6))
@ -260,11 +230,11 @@ def handle_scan_results():
- If there is a free SDR, allocate it to a decoder.
- If there is no free SDR, but a scanner is running, stop the scanner and start decoding.
"""
global scan_results
global config, temporary_block_list
if scan_results.qsize() > 0:
if autorx.scan_results.qsize() > 0:
# Grab the latest detections from the scan result queue.
_scan_data = scan_results.get()
_scan_data = autorx.scan_results.get()
for _sonde in _scan_data:
# Extract frequency & type info
_freq = _sonde[0]
@ -275,6 +245,44 @@ def handle_scan_results():
continue
else:
# Check that we are not attempting to start a decoder too close to an existing decoder for known 'drifty' radiosonde types.
# 'Too close' is defined by the 'decoder_spacing_limit' advanced coniguration option.
_too_close = False
for _key in autorx.task_list.keys():
# Iterate through the task list, and only attempt to compare with those that are a decoder task.
# This is indicated by the task key being an integer (the sonde frequency).
if (type(_key) == int) or (type(_key) == float):
# Extract the currently decoded sonde type from the currently running decoder.
_decoding_sonde_type = autorx.task_list[_key]['task'].sonde_type
# Only check the frequency spacing if we have a known 'drifty' sonde type, *and* the new sonde type is of the same type.
if (_decoding_sonde_type in DRIFTY_SONDE_TYPES) and (_decoding_sonde_type == _type):
if (abs(_key - _freq) < config['decoder_spacing_limit']):
# At this point, we can be pretty sure that there is another decoder already decoding this particular sonde ID.
# Without actually starting another decoder and matching IDs, we can't be 100% sure, but it's a good chance.
logging.error("Task Manager - Detected %s sonde on %.3f MHz, but this is within %d kHz of an already running decoder. (This limit can be set using the 'decoder_spacing_limit' advanced config option.)" %
(_type,
_freq/1e6,
config['decoder_spacing_limit']/1e3))
_too_close = True
continue
# Continue to the next scan result if this one is too close to a currently running decoder.
if _too_close:
continue
# Check the frequency is not in our temporary block list
# (This may happen from time-to-time depending on the timing of the scan thread)
if _freq in temporary_block_list.keys():
if temporary_block_list[_freq] > (time.time()-config['temporary_block_time']*60):
logging.error("Task Manager - Attempted to start a decoder on a temporarily blocked frequency (%.3f MHz)" % (_freq/1e6))
continue
else:
# This frequency should not be blocked any more, remove it from the block list.
logging.info("Task Manager - Removed %.3f MHz from temporary block list." % (_freq/1e6))
temporary_block_list.pop(_freq)
# Handle an inverted sonde detection.
if _type.startswith('-'):
_inverted = " (Inverted)"
@ -284,11 +292,11 @@ def handle_scan_results():
_inverted = ""
# Note: We don't indicate if it's been detected as inverted here.
logging.info("Detected new %s sonde on %.3f MHz!" % (_check_type, _freq/1e6))
logging.info("Task Manager - Detected new %s sonde on %.3f MHz!" % (_check_type, _freq/1e6))
# Break if we don't support this sonde type.
if (_check_type not in VALID_SONDE_TYPES):
logging.error("Unsupported sonde type: %s" % _check_type)
logging.error("Task Manager - Unsupported sonde type: %s" % _check_type)
# TODO - Potentially add the frequency of the unsupported sonde to the temporary block list?
continue
@ -663,7 +671,7 @@ def main():
# and immediately start a decoder. If decoding fails, then we continue into
# the main scanning loop.
if args.type != None:
scan_results.put([[args.frequency*1e6, args.type]])
autorx.scan_results.put([[args.frequency*1e6, args.type]])
handle_scan_results()
# Loop.

Wyświetl plik

@ -5,6 +5,12 @@
# Copyright (C) 2018 Mark Jessop <vk5qi@rfhead.net>
# Released under GNU GPL v3 or later
#
try:
# Python 2
from Queue import Queue
except ImportError:
# Python 3
from queue import Queue
# Now using Semantic Versioning (https://semver.org/) MAJOR.MINOR.PATCH
# MAJOR - Only updated when something huge changes to the project (new decode chain, etc)
@ -37,3 +43,7 @@ sdr_list = {}
#
task_list = {}
# Scan result queue.
scan_results = Queue()

Wyświetl plik

@ -89,6 +89,7 @@ def read_auto_rx_config(filename):
'web_host' : '0.0.0.0',
'web_port' : 5000,
'web_archive_age': 120,
'web_debug': True,
# Advanced Parameters
'search_step' : 800,
'snr_threshold' : 10,

Wyświetl plik

@ -697,11 +697,13 @@ class SondeScanner(object):
# Run rs_detect on each peak frequency, to determine if there is a sonde there.
for freq in peak_frequencies:
_freq = float(freq)
# Exit opportunity.
if self.sonde_scanner_running == False:
return []
detected = detect_sonde(freq,
detected = detect_sonde(_freq,
sdr_fm=self.sdr_fm,
device_idx=self.device_idx,
ppm=self.ppm,
@ -712,10 +714,10 @@ class SondeScanner(object):
if detected != None:
# Add a detected sonde to the output array
_search_results.append([freq, detected])
_search_results.append([_freq, detected])
# Immediately send this result to the callback.
self.send_to_callback([[freq, detected]])
self.send_to_callback([[_freq, detected]])
# If we only want the first detected sonde, then return now.
if first_only:
return _search_results

Wyświetl plik

@ -17,6 +17,7 @@ import autorx.config
import autorx.scan
from threading import Thread
import flask
from flask import request, abort
from flask_socketio import SocketIO
try:
# Python 2
@ -130,6 +131,44 @@ def shutdown_flask(shutdown_key):
return ""
#
# Debugging endpoints. May eventually be exposed to the client, though authentication will need to be dealt with first.
#
@app.route('/start_decoder', methods=['POST'])
def flask_start_decoder():
""" Inject a scan result, which will cause a decoder to be started if there
are enough resources (SDRs) to do so. """
if request.method == 'POST' and autorx.config.global_config['web_debug']:
_type = str(request.form['type'])
_freq = float(request.form['freq'])
logging.info("Web - Got decoder start request: %s, %f" % (_type, _freq))
autorx.scan_results.put([[_freq, _type]])
return "OK"
else:
abort(403)
@app.route('/stop_decoder', methods=['POST'])
def flask_stop_decoder():
""" Request that a decoder process be halted. """
if request.method == 'POST' and autorx.config.global_config['web_debug']:
_freq = float(request.form['freq'])
logging.info("Web - Got decoder stop request: %f" % (_freq))
if _freq in autorx.task_list:
autorx.task_list[_freq]['task'].stop()
return "OK"
else:
# If we aren't running a decoder, 404.
abort(404)
else:
abort(403)
#
# SocketIO Events
#