mirror of
https://github.com/smittix/intercept.git
synced 2026-06-12 07:53:30 -07:00
fix: Preserve GPS satellites across DOP-only SKY messages
gpsd sends multiple SKY messages per cycle — some contain only DOP values with an empty satellites array. Previously this would overwrite the satellite list, causing the sky view to flicker empty. Now DOP-only SKY messages preserve the existing satellite list. Also adds a 5-second polling fallback for satellite data since SSE can miss sky updates due to queue contention. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ const GPS = (function() {
|
||||
let connected = false;
|
||||
let lastPosition = null;
|
||||
let lastSky = null;
|
||||
let skyPollTimer = null;
|
||||
|
||||
// Constellation color map
|
||||
const CONST_COLORS = {
|
||||
@@ -41,6 +42,7 @@ const GPS = (function() {
|
||||
updateSkyUI(data.sky);
|
||||
}
|
||||
subscribeToStream();
|
||||
startSkyPolling();
|
||||
// Ensure the global GPS stream is running
|
||||
if (typeof startGpsStream === 'function' && !gpsEventSource) {
|
||||
startGpsStream();
|
||||
@@ -58,6 +60,7 @@ const GPS = (function() {
|
||||
|
||||
function disconnect() {
|
||||
unsubscribeFromStream();
|
||||
stopSkyPolling();
|
||||
fetch('/gps/stop', { method: 'POST' })
|
||||
.then(() => {
|
||||
connected = false;
|
||||
@@ -77,6 +80,34 @@ const GPS = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
function startSkyPolling() {
|
||||
stopSkyPolling();
|
||||
// Poll satellite data every 5 seconds as a reliable fallback
|
||||
// SSE stream may miss sky updates due to queue contention with position messages
|
||||
pollSatellites();
|
||||
skyPollTimer = setInterval(pollSatellites, 5000);
|
||||
}
|
||||
|
||||
function stopSkyPolling() {
|
||||
if (skyPollTimer) {
|
||||
clearInterval(skyPollTimer);
|
||||
skyPollTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
function pollSatellites() {
|
||||
if (!connected) return;
|
||||
fetch('/gps/satellites')
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.status === 'ok' && data.sky) {
|
||||
lastSky = data.sky;
|
||||
updateSkyUI(data.sky);
|
||||
}
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
function subscribeToStream() {
|
||||
// Subscribe to the global GPS stream instead of opening a separate SSE connection
|
||||
if (typeof addGpsStreamSubscriber === 'function') {
|
||||
@@ -395,6 +426,7 @@ const GPS = (function() {
|
||||
|
||||
function destroy() {
|
||||
unsubscribeFromStream();
|
||||
stopSkyPolling();
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
+29
-13
@@ -318,6 +318,8 @@ class GPSDClient:
|
||||
|
||||
except json.JSONDecodeError:
|
||||
logger.debug(f"Invalid JSON from gpsd: {line[:50]}")
|
||||
except Exception as parse_err:
|
||||
logger.error(f"Error handling gpsd {msg_class} message: {parse_err}")
|
||||
|
||||
except socket.timeout:
|
||||
continue
|
||||
@@ -371,19 +373,33 @@ class GPSDClient:
|
||||
self._update_position(position)
|
||||
|
||||
def _handle_sky(self, msg: dict) -> None:
|
||||
"""Handle SKY (satellite sky view) message from gpsd."""
|
||||
sats = []
|
||||
for sat in msg.get('satellites', []):
|
||||
prn = sat.get('PRN', 0)
|
||||
gnssid = sat.get('gnssid')
|
||||
sats.append(GPSSatellite(
|
||||
prn=prn,
|
||||
elevation=sat.get('el'),
|
||||
azimuth=sat.get('az'),
|
||||
snr=sat.get('ss'),
|
||||
used=sat.get('used', False),
|
||||
constellation=_classify_constellation(prn, gnssid),
|
||||
))
|
||||
"""Handle SKY (satellite sky view) message from gpsd.
|
||||
|
||||
gpsd sends multiple SKY messages per cycle: some contain only DOP
|
||||
values while others include the full satellites array. When a
|
||||
DOP-only SKY arrives, preserve the most recent satellite list
|
||||
instead of overwriting it with an empty one.
|
||||
"""
|
||||
raw_sats = msg.get('satellites', [])
|
||||
has_satellites = len(raw_sats) > 0
|
||||
|
||||
if has_satellites:
|
||||
sats = []
|
||||
for sat in raw_sats:
|
||||
prn = sat.get('PRN', 0)
|
||||
gnssid = sat.get('gnssid')
|
||||
sats.append(GPSSatellite(
|
||||
prn=prn,
|
||||
elevation=sat.get('el'),
|
||||
azimuth=sat.get('az'),
|
||||
snr=sat.get('ss'),
|
||||
used=sat.get('used', False),
|
||||
constellation=_classify_constellation(prn, gnssid),
|
||||
))
|
||||
else:
|
||||
# DOP-only SKY message — keep existing satellites
|
||||
with self._lock:
|
||||
sats = list(self._sky.satellites) if self._sky else []
|
||||
|
||||
sky_data = GPSSkyData(
|
||||
satellites=sats,
|
||||
|
||||
Reference in New Issue
Block a user