From e5ac14e38b3f34412ace66f7185bdfb113825a09 Mon Sep 17 00:00:00 2001 From: Mathieu Moran Date: Thu, 13 Aug 2026 15:41:30 -0400 Subject: [PATCH] fix: persist car-connected flag so trip building works across reboots (BUG-16) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit connect_obd() set _car_ever_connected without a global declaration, so the module-level flag was never set and was_car_ever_connected() always returned False — local trip building has been silently blocked since BUG-10 landed. Also persist the flag to the settings table so a drive followed by a reboot still builds trips, and clean up dead code in was_car_ever_connected(). --- modules/app_obd.py | 29 ++++++++++++++++++++++------- tests/test_app_obd.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 7 deletions(-) create mode 100644 tests/test_app_obd.py diff --git a/modules/app_obd.py b/modules/app_obd.py index bb4e3e2..1301e2b 100644 --- a/modules/app_obd.py +++ b/modules/app_obd.py @@ -165,6 +165,7 @@ def _log_connection_diagnostics(candidate): def connect_obd(): """Connect to the adapter and ECU, with actionable failure diagnostics.""" global connection + global _car_ever_connected with _connect_lock: if _is_car_connected(): return connection @@ -232,6 +233,7 @@ def connect_obd(): connection = candidate if candidate is not None: _car_ever_connected = True + _persist_car_connected() if candidate is None: _emit_disconnected() @@ -274,15 +276,28 @@ def obd_connection(): start_obd() +def _persist_car_connected(): + """Record that the car ECU has been reached, so trip building keeps working + across reboots (the in-memory flag resets every process start).""" + try: + from modules import app_sql + app_sql.set_setting("car_ever_connected", "1") + except Exception as error: + print("Failed to persist car-connected flag:", error) + + def was_car_ever_connected(): - """True if the car ECU has been reached at least once this session.""" + """True if the car ECU has ever been reached (persisted across restarts).""" + global _car_ever_connected + if _car_ever_connected: + return True + try: + from modules import app_sql + if app_sql.get_setting("car_ever_connected", "0") == "1": + _car_ever_connected = True + except Exception: + pass return _car_ever_connected - if _is_car_connected(): - app_events.socketio.emit("obd_status", obd_status[1]) - app_events.socketio.emit("obd_speed", get_speedtime()) - app_events.socketio.emit("obd_rpm", rpm if rpm is not None else "-") - else: - _emit_disconnected() def get_fresh_mil(max_age=SENSOR_POLL_INTERVAL * 3): diff --git a/tests/test_app_obd.py b/tests/test_app_obd.py new file mode 100644 index 0000000..c9b3c59 --- /dev/null +++ b/tests/test_app_obd.py @@ -0,0 +1,30 @@ +import unittest +from unittest.mock import patch + +from modules import app_obd + + +class CarConnectedFlagTest(unittest.TestCase): + def setUp(self): + app_obd._car_ever_connected = False + + def tearDown(self): + app_obd._car_ever_connected = False + + def test_was_ever_connected_reads_persisted_flag(self): + with patch("modules.app_sql.get_setting", return_value="1"): + self.assertTrue(app_obd.was_car_ever_connected()) + self.assertTrue(app_obd._car_ever_connected) + + def test_was_ever_connected_defaults_false(self): + with patch("modules.app_sql.get_setting", return_value="0"): + self.assertFalse(app_obd.was_car_ever_connected()) + + def test_persist_car_connected_writes_setting(self): + with patch("modules.app_sql.set_setting") as mock_set: + app_obd._persist_car_connected() + mock_set.assert_called_once_with("car_ever_connected", "1") + + +if __name__ == "__main__": + unittest.main()