kopia lustrzana https://github.com/projecthorus/radiosonde_auto_rx
				
				
				
			Fix adjacent channel detection, add debug flask endpoints.
							rodzic
							
								
									ef34b6496f
								
							
						
					
					
						commit
						8547c724c6
					
				|  | @ -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. | ||||
|  |  | |||
|  | @ -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() | ||||
|  | @ -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, | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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 | ||||
| # | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 Mark Jessop
						Mark Jessop