Fix weather satellite mode returning false success on SatDump startup failure

Add synchronous startup verification after Popen() — sleep 0.5s and poll
the process before returning to the caller. If SatDump exits immediately
(missing device, bad args), raise RuntimeError with the actual error
message instead of returning status: 'started'. Keep a shorter (2s) async
backup check for slower failures.

Also fix --source_id handling: omit the flag entirely when no serial number
is found instead of passing "0" which SatDump may reject. Change start()
and start_from_file() to return (bool, str|None) tuples so error messages
propagate through to the HTTP response.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Smittix
2026-02-25 21:49:16 +00:00
parent a50f77629c
commit 935b7a4d9d
7 changed files with 197 additions and 147 deletions

View File

@@ -26,48 +26,48 @@ logger = get_logger('intercept.weather_sat')
weather_sat_bp = Blueprint('weather_sat', __name__, url_prefix='/weather-sat')
# Queue for SSE progress streaming
_weather_sat_queue: queue.Queue = queue.Queue(maxsize=100)
_weather_sat_queue: queue.Queue = queue.Queue(maxsize=100)
def _progress_callback(progress: CaptureProgress) -> None:
"""Callback to queue progress updates for SSE stream."""
try:
_weather_sat_queue.put_nowait(progress.to_dict())
def _progress_callback(progress: CaptureProgress) -> None:
"""Callback to queue progress updates for SSE stream."""
try:
_weather_sat_queue.put_nowait(progress.to_dict())
except queue.Full:
try:
_weather_sat_queue.get_nowait()
_weather_sat_queue.put_nowait(progress.to_dict())
except queue.Empty:
pass
def _release_weather_sat_device(device_index: int) -> None:
"""Release an SDR device only if weather-sat currently owns it."""
if device_index < 0:
return
try:
import app as app_module
except ImportError:
return
owner = None
get_status = getattr(app_module, 'get_sdr_device_status', None)
if callable(get_status):
try:
owner = get_status().get(device_index)
except Exception:
owner = None
if owner and owner != 'weather_sat':
logger.debug(
'Skipping SDR release for device %s owned by %s',
device_index,
owner,
)
return
app_module.release_sdr_device(device_index)
except queue.Empty:
pass
def _release_weather_sat_device(device_index: int) -> None:
"""Release an SDR device only if weather-sat currently owns it."""
if device_index < 0:
return
try:
import app as app_module
except ImportError:
return
owner = None
get_status = getattr(app_module, 'get_sdr_device_status', None)
if callable(get_status):
try:
owner = get_status().get(device_index)
except Exception:
owner = None
if owner and owner != 'weather_sat':
logger.debug(
'Skipping SDR release for device %s owned by %s',
device_index,
owner,
)
return
app_module.release_sdr_device(device_index)
@weather_sat_bp.route('/status')
@@ -178,15 +178,15 @@ def start_capture():
except queue.Empty:
break
# Set callback and on-complete handler for SDR release
decoder.set_callback(_progress_callback)
def _release_device():
_release_weather_sat_device(device_index)
# Set callback and on-complete handler for SDR release
decoder.set_callback(_progress_callback)
def _release_device():
_release_weather_sat_device(device_index)
decoder.set_on_complete(_release_device)
success = decoder.start(
success, error_msg = decoder.start(
satellite=satellite,
device_index=device_index,
gain=gain,
@@ -208,7 +208,7 @@ def start_capture():
_release_device()
return jsonify({
'status': 'error',
'message': 'Failed to start capture'
'message': error_msg or 'Failed to start capture'
}), 500
@@ -310,7 +310,7 @@ def test_decode():
decoder.set_callback(_progress_callback)
decoder.set_on_complete(None)
success = decoder.start_from_file(
success, error_msg = decoder.start_from_file(
satellite=satellite,
input_file=input_file,
sample_rate=sample_rate,
@@ -329,7 +329,7 @@ def test_decode():
else:
return jsonify({
'status': 'error',
'message': 'Failed to start file decode'
'message': error_msg or 'Failed to start file decode'
}), 500
@@ -343,9 +343,9 @@ def stop_capture():
decoder = get_weather_sat_decoder()
device_index = decoder.device_index
decoder.stop()
_release_weather_sat_device(device_index)
decoder.stop()
_release_weather_sat_device(device_index)
return jsonify({'status': 'stopped'})