fix: force OBD reconnect after ~20s of stale null speed (BUG-24)

obd_speed() now counts consecutive null-speed polls. If the ELM327 returns
null for 10 polls (~20s) while still reporting CAR_CONNECTED, it force-closes
the connection so the reconnect loop re-handshakes instead of silently
flatlining until the next ignition cycle.
This commit is contained in:
Mathieu Moran
2026-08-15 17:47:32 -04:00
parent bfc8ddabd9
commit b0ad6fde51
+14
View File
@@ -11,6 +11,9 @@ from modules import app_events, app_gps
RECONNECT_INTERVAL = 10
SENSOR_POLL_INTERVAL = 5
# Speed poll is every 2s; if the adapter returns null for this many consecutive
# polls (~20s) the ELM327 is usually stalled — force a reconnect.
STALE_SPEED_RECONNECT_THRESHOLD = 10
status = None
speed = 0
@@ -357,14 +360,25 @@ def get_fresh_dtc_codes(max_age=SENSOR_POLL_INTERVAL * 3):
def obd_speed():
global speed, speed_updated_at
with obd_speed_lock:
null_streak = 0
while not stop_speed.is_set() and _is_car_connected():
response = _query(obd.commands.SPEED)
if response is None:
break
if response.is_null():
null_streak += 1
print("No speed data received. #" + str(get_speedtime()))
print(app_gps.get_gps())
# A stalled ELM327 keeps the connection "alive" but returns
# null for speed forever. Force a reconnect after ~20s of null
# reads instead of flatlining until the next ignition cycle.
if null_streak >= STALE_SPEED_RECONNECT_THRESHOLD:
with _connection_lock:
candidate = connection
_mark_connection_lost(candidate, "speed", "stale null speed")
break
else:
null_streak = 0
speed = round(response.value.to("kph").magnitude, 1)
speed_updated_at = time.monotonic()
print("Speed:", speed, "kph")