From d240ae06e3cbfce25614143aa08e5b78739b1ee6 Mon Sep 17 00:00:00 2001 From: James Smith Date: Thu, 19 Mar 2026 21:48:33 +0000 Subject: [PATCH] fix(satellite): populate currentPos with full telemetry in pass predictions Previously currentPos only had lat/lon, so the updateTelemetry fallback (used before first live position arrives) always showed '---' for altitude/elevation/azimuth/distance. currentPos now includes all fields computed from the request observer location. updateTelemetry simplified to delegate to applyTelemetryPosition. --- routes/satellite.py | 12 ++++++++++++ templates/satellite_dashboard.html | 18 +++--------------- tests/test_satellite.py | 19 +++++++++++++++++++ 3 files changed, 34 insertions(+), 15 deletions(-) diff --git a/routes/satellite.py b/routes/satellite.py index 78640fe..217fe4d 100644 --- a/routes/satellite.py +++ b/routes/satellite.py @@ -513,7 +513,19 @@ def predict_passes(): current_pos = { 'lat': float(sp.latitude.degrees), 'lon': float(sp.longitude.degrees), + 'altitude': float(sp.elevation.km), } + # Add observer-relative data using the request's observer location + try: + diff = satellite - observer + topo = diff.at(t0) + alt_deg, az_deg, dist_km = topo.altaz() + current_pos['elevation'] = round(float(alt_deg.degrees), 1) + current_pos['azimuth'] = round(float(az_deg.degrees), 1) + current_pos['distance'] = round(float(dist_km.km), 1) + current_pos['visible'] = bool(alt_deg.degrees > 0) + except Exception: + pass except Exception: pass diff --git a/templates/satellite_dashboard.html b/templates/satellite_dashboard.html index fe09413..9dc0be8 100644 --- a/templates/satellite_dashboard.html +++ b/templates/satellite_dashboard.html @@ -2404,21 +2404,9 @@ clearTelemetry(); return; } - - const pos = pass.currentPos; - const telLat = document.getElementById('telLat'); - const telLon = document.getElementById('telLon'); - const telAlt = document.getElementById('telAlt'); - const telEl = document.getElementById('telEl'); - const telAz = document.getElementById('telAz'); - const telDist = document.getElementById('telDist'); - - if (telLat) telLat.textContent = Number.isFinite(pos.lat) ? pos.lat.toFixed(4) + '°' : '---.----'; - if (telLon) telLon.textContent = Number.isFinite(pos.lon) ? pos.lon.toFixed(4) + '°' : '---.----'; - if (telAlt && Number.isFinite(pos.alt)) telAlt.textContent = pos.alt.toFixed(0) + ' km'; - if (telEl && Number.isFinite(pos.el)) telEl.textContent = pos.el.toFixed(1) + '°'; - if (telAz && Number.isFinite(pos.az)) telAz.textContent = pos.az.toFixed(1) + '°'; - if (telDist && Number.isFinite(pos.dist)) telDist.textContent = pos.dist.toFixed(0) + ' km'; + // currentPos now contains full position data (lat, lon, altitude, + // elevation, azimuth, distance, visible) from the predict endpoint. + applyTelemetryPosition(pass.currentPos); } function updateCountdown() { diff --git a/tests/test_satellite.py b/tests/test_satellite.py index 7d62a9f..cc86e1f 100644 --- a/tests/test_satellite.py +++ b/tests/test_satellite.py @@ -121,6 +121,25 @@ def test_tracker_position_has_no_observer_fields(): assert required in pos, f"SSE tracker must emit '{required}'" +def test_predict_passes_currentpos_has_full_fields(client): + """currentPos in pass results must include altitude, elevation, azimuth, distance.""" + payload = { + 'latitude': 51.5074, + 'longitude': -0.1278, + 'hours': 48, + 'minEl': 5, + 'satellites': ['ISS'], + } + response = client.post('/satellite/predict', json=payload) + assert response.status_code == 200 + data = response.json + assert data['status'] == 'success' + if data['passes']: + cp = data['passes'][0].get('currentPos', {}) + for field in ('lat', 'lon', 'altitude', 'elevation', 'azimuth', 'distance'): + assert field in cp, f"currentPos missing field: {field}" + + @patch('routes.satellite.refresh_tle_data', return_value=['ISS']) @patch('routes.satellite._load_db_satellites_into_cache') def test_tle_auto_refresh_schedules_daily_repeat(mock_load_db, mock_refresh):