fix: BUG-21 GPS-speed fallback in server route replay
This commit is contained in:
@@ -35,11 +35,13 @@ When CLOSED, move the entire entry to Resolved — don't duplicate.
|
|||||||
(`insert_tracking(gps_x, gps_y, speed=None, …)`) — there is no GPS-derived speed fallback, so
|
(`insert_tracking(gps_x, gps_y, speed=None, …)`) — there is no GPS-derived speed fallback, so
|
||||||
the SPEED column stays NULL and the replay shows 0.0 km/h (`speed_source="gps"`).
|
the SPEED column stays NULL and the replay shows 0.0 km/h (`speed_source="gps"`).
|
||||||
- **Data**: trip #9 has 723 points — 570 with OBD speed, 25 with speed=0, 128 with NULL speed.
|
- **Data**: trip #9 has 723 points — 570 with OBD speed, 25 with speed=0, 128 with NULL speed.
|
||||||
- **Fix (proposed)**:
|
- **Fix**: mirror the Pi's `route_points` GPS-speed fallback in the server's `get_trip_route()`
|
||||||
1. GPS-speed fallback in `_log_loop()` — when OBD speed is None/0 but GPS coords exist,
|
(`server/modules/db.py`) — when OBD speed is missing, derive speed from the previous point's
|
||||||
compute speed from the previous position (haversine / elapsed time) and log that as SPEED,
|
movement (haversine / elapsed time, ≥8 m, ≤220 km/h) so the replay shows the real speed
|
||||||
so the replay shows the real speed (sourced "gps").
|
instead of flatlining at 0 km/h. (The Pi's own replay already did this; only the portal was
|
||||||
2. Investigate why the OBD adapter didn't recover for ~20 min (reconnect on stalled reads).
|
missing it.)
|
||||||
|
- **Follow-up**: investigate why the OBD adapter didn't recover for ~20 min (reconnect on
|
||||||
|
stalled reads).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -2282,10 +2282,10 @@ logged as `BUG-XX` entries in [BUGS.md](./BUGS.md) (BUG-16 onward) and fixed + v
|
|||||||
- **BUG-20 (server trip IDs inflate) — ✅ FIXED**: `trips.id BIGSERIAL` burned sequence values
|
- **BUG-20 (server trip IDs inflate) — ✅ FIXED**: `trips.id BIGSERIAL` burned sequence values
|
||||||
on every upsert (recompute after each upload batch). Fixed: sequence clamped to `MAX(id)`
|
on every upsert (recompute after each upload batch). Fixed: sequence clamped to `MAX(id)`
|
||||||
after each recompute + one-time renumber migration — trips now 1..10, sequence at 10.
|
after each recompute + one-time renumber migration — trips now 1..10, sequence at 10.
|
||||||
- **BUG-21 (OBD speed dropout mid-drive) — OPEN**: ELM327 stopped returning speed for ~20 min
|
- **BUG-21 (OBD speed dropout mid-drive) — 🚧 IN PROGRESS**: ELM327 stopped returning speed for
|
||||||
on 2026-08-13 (22:23:50→22:43:41 UTC); Pi logged NULL speed (no GPS-speed fallback), so the
|
~20 min on 2026-08-13 (22:23:50→22:43:41 UTC). Fix: server `get_trip_route()` now mirrors the
|
||||||
replay shows 0 km/h for that stretch. Proposed: GPS-speed fallback in `_log_loop()` + OBD
|
Pi's GPS-speed fallback (derive speed from consecutive GPS points when OBD speed is missing),
|
||||||
reconnect on stalled reads.
|
so the portal replay no longer flatlines at 0 km/h. Follow-up: OBD reconnect on stalled reads.
|
||||||
|
|
||||||
Open items from the drive — fill in as reported:
|
Open items from the drive — fill in as reported:
|
||||||
- (none clock-related — BUG-17/BUG-18 closed 2026-08-14).
|
- (none clock-related — BUG-17/BUG-18 closed 2026-08-14).
|
||||||
|
|||||||
+14
-3
@@ -617,9 +617,20 @@ def get_trip_route(device_id, trip_id):
|
|||||||
lon = float(p[2])
|
lon = float(p[2])
|
||||||
speed = p[3] or 0
|
speed = p[3] or 0
|
||||||
raw_odo = p[4]
|
raw_odo = p[4]
|
||||||
|
speed_source = "obd" if speed > 0 else "gps"
|
||||||
|
# Mirror the Pi's route_points GPS-speed fallback: when OBD speed is
|
||||||
|
# missing (adapter dropout), derive speed from the previous point's
|
||||||
|
# movement so the replay doesn't flatline at 0 km/h while the car moves.
|
||||||
|
if speed <= 0 and prev is not None:
|
||||||
|
seconds = (p[0] - prev[2]).total_seconds()
|
||||||
|
if seconds > 0:
|
||||||
|
dist_km = hav(prev[0], prev[1], lat, lon)
|
||||||
|
seg_speed = dist_km / seconds * 3600
|
||||||
|
if seg_speed <= 220 and dist_km * 1000 >= 8:
|
||||||
|
speed = seg_speed
|
||||||
if prev is not None:
|
if prev is not None:
|
||||||
cumulative += hav(prev[0], prev[1], lat, lon)
|
cumulative += hav(prev[0], prev[1], lat, lon)
|
||||||
prev = (lat, lon)
|
prev = (lat, lon, p[0])
|
||||||
if raw_odo is not None and float(raw_odo) > 0:
|
if raw_odo is not None and float(raw_odo) > 0:
|
||||||
odometer = float(raw_odo)
|
odometer = float(raw_odo)
|
||||||
else:
|
else:
|
||||||
@@ -628,10 +639,10 @@ def get_trip_route(device_id, trip_id):
|
|||||||
"datetime": p[0].isoformat(),
|
"datetime": p[0].isoformat(),
|
||||||
"latitude": lat,
|
"latitude": lat,
|
||||||
"longitude": lon,
|
"longitude": lon,
|
||||||
"speed": speed,
|
"speed": round(speed, 1),
|
||||||
# Mirror the Pi's route_points: OBD speed when we have it,
|
# Mirror the Pi's route_points: OBD speed when we have it,
|
||||||
# otherwise the point is sourced from GPS.
|
# otherwise the point is sourced from GPS.
|
||||||
"speed_source": "obd" if speed > 0 else "gps",
|
"speed_source": speed_source,
|
||||||
"odometer": round(odometer, 1),
|
"odometer": round(odometer, 1),
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user