ADR 0003: Live data as a long job in the single worker thread¶
Status: accepted (2026-10-08)
Context¶
Live data (v0.2) queries mode 01 values continuously until the user stops. The user interface runs all adapter actions in a thread pool with exactly one thread, so that two actions never use the same port. A live run blocks this thread for minutes.
Decision¶
Live data runs as one job in the same thread (
backend.live_port). Intermediate values reach the GUI thread via a Qt signal (queued) with a run number; values of an old run are discarded. Stopping goes through athreading.Eventthatrun_livechecks before every round and while waiting in steps of at most 0.1 s.Live data and diagnosis lock each other: while live data runs, scan, clearing and export are locked (
DiagnosisViewModel.blocked), otherwise they would pile up in the one thread. Live data does not start while the diagnosis is busy. On exit,app.pystops live data before waiting for the pool.Only
01xxandATRVare sent. An unreadable value givesNonefor that round; connection errors abort, as do three consecutive rounds in which every value fails with an adapter error (CAN ERROR,UNABLE TO CONNECT…: ignition off, bus gone). Below 11.8 V battery voltage values are only queried every 5 s to protect the battery; an unreadable voltage does not lift the throttling. The voltage is measured every tenth round, every round while throttled (since the second car test: otherwise the throttling stayed for up to 50 s after starting the engine).The PID table (
protocol/pids.py) has one entry (PidSpec) per value; several entries can share one PID (oxygen sensors, secondary trim, torque points, status byte PIDs66/67).decodegets the firstsizedata bytes and may returnNone(status bit not set). Each PID is queried once per round. PIDs whose structure is not unambiguous in the free sources (68–7F, among them boost pressure70and particulate filter7A–7C) stay out.Curves scale to the values shown, with a minimum span; the full range of the standard (e.g. engine speed up to 16384 rpm) would make them look flat.
Consequences¶
No second thread, no synchronisation on the port; the lock is visible (greyed-out buttons) instead of a silent wait.
The timing is testable with an injectable clock; a Hypothesis test checks that rounds never come faster than allowed.