From 4589904b97baff26031394506bc97a420c4228b9 Mon Sep 17 00:00:00 2001 From: Justin Paul Date: Tue, 30 Jun 2026 14:13:49 -0400 Subject: [PATCH] P1: PySide6 + pyqtgraph GUI shell (PID browser + live overlay plot) First graphical frontend on obdcore. Cross-platform (Win/mac/Linux). - gui/controller.py: owns link/registry/store/scheduler; subscribe == poll == plot; per-PID rates (ICP/FICM/RPM fast); optional CSV recording. - gui/main.py: connection bar (port dropdown via find_ports, baud, Mock, connect), left PID browser grouped by system with live values + confidence badges + checkboxes, central pyqtgraph overlay plot with legend, Normalize (% of range) toggle for mixed-scale PIDs, Crank/Driving/Vitals presets, 10Hz refresh reading the store off the acquisition thread. - run_gui.py launcher; requirements-gui.txt. - store.py: lock Channel push/series (GUI reads while scheduler writes). - docs/gui-p1-preview.png: validated render (mock crank, ICP ramp to 540). Validated headless (offscreen Qt): connect(mock) -> crank preset -> ICP streams past 500 -> normalize -> uncheck removes curve -> clean disconnect. obdcore tests still pass after the locking change. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_016yT89n4zR4qbrySoSiEyZs --- README.md | 18 +++ docs/gui-p1-preview.png | Bin 0 -> 106606 bytes gui/__init__.py | 4 + gui/controller.py | 85 +++++++++++ gui/main.py | 319 ++++++++++++++++++++++++++++++++++++++++ obdcore/store.py | 27 ++-- requirements-gui.txt | 7 + run_gui.py | 12 ++ 8 files changed, 463 insertions(+), 9 deletions(-) create mode 100644 docs/gui-p1-preview.png create mode 100644 gui/__init__.py create mode 100644 gui/controller.py create mode 100644 gui/main.py create mode 100644 requirements-gui.txt create mode 100644 run_gui.py diff --git a/README.md b/README.md index 95119f3..e7c3d94 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,24 @@ python obd_reader.py COM5 --crank --dash-log crank.csv # + record a CSV under the line), that's the high-pressure oil bleed-off — STC fitting / oil-rail O-rings. On exit it prints the peak and a verdict. `q` quits, `r` resets. +## Graphical app (preview — P1) + +A cross-platform desktop GUI (PySide6 + pyqtgraph) is in progress. P1 = PID +browser + live overlay plot; see [ARCHITECTURE.md](ARCHITECTURE.md) for the +roadmap (cranking/driving/diagnostics perspectives, record/playback, etc.). + +``` +pip install -r requirements-gui.txt +python run_gui.py # tick "Mock" + Connect to explore with no adapter +``` + +![P1 GUI](docs/gui-p1-preview.png) + +The whole app runs against simulated data (`MockLink`) so it can be developed +on any machine and only needs the truck for real captures. + +--- + ### Live dashboard (real-time gauges) Updates in place as you crank or run the engine — color-coded, with live diff --git a/docs/gui-p1-preview.png b/docs/gui-p1-preview.png new file mode 100644 index 0000000000000000000000000000000000000000..06de7a29b1132c3757727d171933482fe3de4639 GIT binary patch literal 106606 zcmZ^~WmH^C*EI?;+}$05yK8VKxNGAY+~EY8KyY_=C%DtWoyJ{)ySp@eeR7_6jQi)V z0fSxLo03(sWX}5eRapiFkq{9E1_nh=R#FWH=7S;(%)3(fchFC^EFlumKM3DsbzNa# zQ2YMthj#swGe_fX zD^Jhhu<-BSb%3yxl;lCOp1o_Q9f8E;pNmK-{6u5G+s?d#&snXVYgt)Ky7?U)#IVo? zp(3XLrQ~yY5#YZP3`{nKzQF%I|Dmzo`QP(0w!lEkk`^uwPEtxrN?O{Iz1@c@f`nmn zHhdo+A7&Ex82^_Cc2-taM#hSw_m7Oz)6>YGB#ezg(1OFMsp!nmhO%HK;%AqPSuHeN zn15)c5)%`-!0Gw<`Jcl%czK<&=e`H_Wbis2xIKZqXbn?h$V4fDvvYI$0_db+F)?&< z)4zY`LMuZ#wGy5A<5WVT^%1)j#m*NF2}Vr4fOjSR>gwv`L*tmrPGva&Mpc*O>gp$<7>wf{SSmHBE!B$x-^@r8t7^q@5?nB21NfMWT7zvF-^ ztJ>0GhkTJFI2}I7`Vd{Lmy(ha5fPD4k(QR$(#&ic`I4(t_{56vam6N76IRMG;g1O{ z%!A>$KszB!V^GvD?p}O6Y-}A}UG7v4E-vh@5lgMko`m>#H+T1lhzNbQY}{GYX5oKZ znk~@HNeCtiA!(m6av15X8z}np);8cEc#_{UJ@5Xl*BkE>J#y>pw>Rk(a@9~E@I!ch zOHGF3X=QFm@mjP078k?ixl`~-jG(XXSl|=*)HOYqA>F79Ecd-~$8n5C@ z7NBJ*8Z+N) zYbzd^e>@t3Yw$Yz@UvK(cgZOy0Wl=J?qZ5TL|Y!w4{_kPdo9I=aB!@jF>2ePWZ{GuHa{QWJ5#Hmvirh zEe160T{+K`MS5FBU!9H12%N@dm6Rn|?^{yP@n?>KR1(j{s_n!TT_KT|W|vzhC5@|K zhnY~mbi4HNKsBvPEjfyr-Qm#)-pZ*Z>p1&R2XX^H9GJVz>)3hv0s`gmRG));{(YRzOe%r+J|cb$4-V_{?B;^JZ^XmKBNdM|9B@8Sa@5pYuakADzN zWjGW#MW(mc=|P+|UsyZ_BHkNK6ptXYW5|8<�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�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 literal 0 HcmV?d00001 diff --git a/gui/__init__.py b/gui/__init__.py new file mode 100644 index 0000000..9e76f19 --- /dev/null +++ b/gui/__init__.py @@ -0,0 +1,4 @@ +"""PySide6 + pyqtgraph GUI for ford-obd (P1 shell). + +Run: python run_gui.py (or) python -m gui +""" diff --git a/gui/controller.py b/gui/controller.py new file mode 100644 index 0000000..ad0905a --- /dev/null +++ b/gui/controller.py @@ -0,0 +1,85 @@ +"""Controller -- owns the obdcore link/registry/store/scheduler for the GUI. + +Keeps all acquisition concerns out of the widgets. The GUI subscribes/ +unsubscribes PIDs (== what's polled == what's plotted) and reads the store on +a timer; the scheduler thread does the serial work. +""" +import time + +from obdcore import PidRegistry, TimeSeriesStore, PollScheduler, CsvRecorder +from obdcore.mock import MockLink + +# default poll rates (Hz) -- fast for the no-start metrics, slower for the rest +FAST = {"ICP", "FICM_M", "RPM"} +DEFAULT_HZ = 2 +FAST_HZ = 5 + + +class Controller: + def __init__(self): + self.reg = PidRegistry() + self.store = TimeSeriesStore() + self.link = None + self.sched = None + self.t0 = None + self.connected = False + + def connect(self, port=None, baud=38400, mock=False): + if mock: + self.link = MockLink(clock=time.time) + else: + from obdcore.link import ElmLink # imported lazily (needs pyserial) + self.link = ElmLink(port, baud) + self.link.init() + ok = self.link.connect() + try: + self.link.fast_timing(True) + except Exception: + pass + self.sched = PollScheduler(self.link, self.reg, self.store, clock=time.time) + self.t0 = time.time() + self.connected = True + return ok + + def hz_for(self, key): + return FAST_HZ if key in FAST else DEFAULT_HZ + + def subscribe(self, key): + if self.sched: + self.sched.subscribe(key, self.hz_for(key)) + + def unsubscribe(self, key): + if self.sched: + self.sched.unsubscribe(key) + + def subscribed(self): + return set(self.sched.subscriptions()) if self.sched else set() + + def start(self): + if self.sched: + self.sched.start() + + def record(self, path): + self.store.recorder = CsvRecorder(path) + + def stop_record(self): + if self.store.recorder: + self.store.recorder.close() + self.store.recorder = None + + def now(self): + return (time.time() - self.t0) if self.t0 else 0.0 + + def stop(self): + if self.sched: + self.sched.stop() + self.sched = None + self.stop_record() + if self.link: + try: + self.link.fast_timing(False) + except Exception: + pass + self.link.close() + self.link = None + self.connected = False diff --git a/gui/main.py b/gui/main.py new file mode 100644 index 0000000..2d94d56 --- /dev/null +++ b/gui/main.py @@ -0,0 +1,319 @@ +"""ford-obd GUI -- P1 shell: connection bar, PID browser (side), live overlay plot. + +Checking a PID in the browser subscribes it (polls + plots); unchecking removes +it. Preset buttons bulk-select. 'Normalize' overlays mixed-scale PIDs (ICP vs +FICM) as % of each PID's range so they're all readable on one axis. + +Built to run against MockLink with no hardware -- pick "Mock" and Connect. +""" +import time + +from PySide6 import QtCore, QtGui, QtWidgets +import pyqtgraph as pg + +from obdcore import PRESETS +from .controller import Controller + +PLOT_WINDOW_S = 60.0 # seconds of history shown +REFRESH_MS = 100 # GUI redraw rate (10 Hz) + +CURVE_COLORS = [ + "#e6194B", "#3cb44b", "#4363d8", "#f58231", "#911eb4", + "#42d4f4", "#f032e6", "#bfef45", "#fabed4", "#469990", + "#9A6324", "#ffe119", "#000075", "#a9a9a9", "#800000", +] + +GROUP_ORDER = ["fuel", "ficm", "air", "engine", "driveline", "power", "misc"] +GROUP_LABEL = { + "fuel": "Fuel / Injection", "ficm": "FICM", "air": "Air / Boost", + "engine": "Engine", "driveline": "Driveline", "power": "Power", "misc": "Other", +} +CONF_BADGE = {"verified": "", "doc": " [DOC]", "tentative": " [?]"} + + +class MainWindow(QtWidgets.QMainWindow): + def __init__(self): + super().__init__() + self.setWindowTitle("ford-obd -- 6.0 Power Stroke scanner") + self.resize(1100, 680) + self.ctl = Controller() + self.curves = {} # key -> PlotDataItem + self._color_i = 0 + + self._build_connection_bar() + self._build_pid_browser() + self._build_plot() + self._build_statusbar() + + self.timer = QtCore.QTimer(self) + self.timer.timeout.connect(self._tick) + self.timer.setInterval(REFRESH_MS) + + # ---- UI construction ---- + def _build_connection_bar(self): + tb = QtWidgets.QToolBar("Connection") + tb.setMovable(False) + self.addToolBar(tb) + + tb.addWidget(QtWidgets.QLabel(" Port ")) + self.port_combo = QtWidgets.QComboBox() + self.port_combo.setMinimumWidth(180) + self._refresh_ports() + tb.addWidget(self.port_combo) + + refresh = QtWidgets.QToolButton() + refresh.setText("↻") + refresh.setToolTip("Rescan serial ports") + refresh.clicked.connect(self._refresh_ports) + tb.addWidget(refresh) + + tb.addWidget(QtWidgets.QLabel(" Baud ")) + self.baud_edit = QtWidgets.QLineEdit("38400") + self.baud_edit.setFixedWidth(70) + tb.addWidget(self.baud_edit) + + self.mock_chk = QtWidgets.QCheckBox("Mock") + self.mock_chk.setToolTip("Use simulated data (no adapter needed)") + tb.addWidget(self.mock_chk) + + self.connect_btn = QtWidgets.QPushButton("Connect") + self.connect_btn.clicked.connect(self._toggle_connect) + tb.addWidget(self.connect_btn) + + tb.addSeparator() + for name in ("crank", "driving", "vitals"): + b = QtWidgets.QPushButton(name.capitalize()) + b.setToolTip(f"Select the '{name}' PID set") + b.clicked.connect(lambda _=False, n=name: self._apply_preset(n)) + b.setEnabled(False) + b.setProperty("preset", True) + tb.addWidget(b) + + def _build_pid_browser(self): + dock = QtWidgets.QDockWidget("PIDs", self) + dock.setAllowedAreas(QtCore.Qt.LeftDockWidgetArea | QtCore.Qt.RightDockWidgetArea) + self.tree = QtWidgets.QTreeWidget() + self.tree.setColumnCount(2) + self.tree.setHeaderLabels(["Signal", "Value"]) + self.tree.setRootIsDecorated(True) + self.tree.setUniformRowHeights(True) + self.tree.itemChanged.connect(self._on_item_changed) + dock.setWidget(self.tree) + self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, dock) + self._populate_tree() + + def _populate_tree(self): + self.tree.blockSignals(True) + self.tree.clear() + self._items = {} # key -> QTreeWidgetItem + groups = {} + for p in self.ctl.reg.all(): + g = groups.get(p.group) + if g is None: + g = QtWidgets.QTreeWidgetItem([GROUP_LABEL.get(p.group, p.group), ""]) + g.setFlags(QtCore.Qt.ItemIsEnabled) + f = g.font(0); f.setBold(True); g.setFont(0, f) + groups[p.group] = g + it = QtWidgets.QTreeWidgetItem([f"{p.name}{CONF_BADGE.get(p.confidence,'')}", "--"]) + it.setFlags(QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled) + it.setCheckState(0, QtCore.Qt.Unchecked) + it.setData(0, QtCore.Qt.UserRole, p.key) + it.setToolTip(0, f"{p.key} (mode {p.mode} {p.pid}) {p.unit} {p.notes}") + g.addChild(it) + self._items[p.key] = it + for gk in GROUP_ORDER: + if gk in groups: + self.tree.addTopLevelItem(groups[gk]) + self.tree.expandAll() + self.tree.resizeColumnToContents(0) + self.tree.blockSignals(False) + + def _build_plot(self): + pg.setConfigOptions(antialias=True, background="#111", foreground="#ccc") + central = QtWidgets.QWidget() + lay = QtWidgets.QVBoxLayout(central) + lay.setContentsMargins(4, 4, 4, 4) + + bar = QtWidgets.QHBoxLayout() + self.norm_chk = QtWidgets.QCheckBox("Normalize (% of range)") + self.norm_chk.setToolTip("Scale each curve to its min..max so mixed units " + "(ICP vs FICM) are all readable on one axis") + bar.addWidget(self.norm_chk) + bar.addStretch(1) + self.window_label = QtWidgets.QLabel(f"window: {int(PLOT_WINDOW_S)}s") + bar.addWidget(self.window_label) + lay.addLayout(bar) + + self.plot = pg.PlotWidget() + self.plot.addLegend(offset=(10, 10)) + self.plot.showGrid(x=True, y=True, alpha=0.25) + self.plot.setLabel("bottom", "time", units="s") + self.plot.setLabel("left", "value") + lay.addWidget(self.plot) + self.setCentralWidget(central) + + def _build_statusbar(self): + self.status = self.statusBar() + self.status.showMessage("Not connected. Pick a port (or Mock) and Connect.") + + # ---- connection ---- + def _refresh_ports(self): + self.port_combo.clear() + try: + from obdcore.link import find_ports + ports = find_ports() + except Exception: + ports = [] + for p in ports: + self.port_combo.addItem(f"{p.device} ({p.description})", p.device) + if not ports: + self.port_combo.addItem("(no ports found)", None) + + def _toggle_connect(self): + if self.ctl.connected: + self._disconnect() + return + mock = self.mock_chk.isChecked() + port = self.port_combo.currentData() + try: + baud = int(self.baud_edit.text()) + except ValueError: + baud = 38400 + try: + ok = self.ctl.connect(port=port, baud=baud, mock=mock) + except Exception as e: + QtWidgets.QMessageBox.critical(self, "Connect failed", str(e)) + return + self.ctl.start() + self.timer.start() + self.connect_btn.setText("Disconnect") + self._set_presets_enabled(True) + proto = getattr(self.ctl.link, "protocol", "?") + kind = "MOCK" if mock else "ELM327" + self.status.showMessage(f"Connected ({kind}) protocol {proto} " + f"{'(ECU answered)' if ok else '(no 0100 ack - key to RUN?)'}") + self._apply_preset("crank") + + def _disconnect(self): + self.timer.stop() + for key in list(self.curves): + self._remove_curve(key) + self.ctl.stop() + # uncheck everything + self.tree.blockSignals(True) + for it in self._items.values(): + it.setCheckState(0, QtCore.Qt.Unchecked) + it.setText(1, "--") + self.tree.blockSignals(False) + self.connect_btn.setText("Connect") + self._set_presets_enabled(False) + self.status.showMessage("Disconnected.") + + def _set_presets_enabled(self, on): + for b in self.findChildren(QtWidgets.QPushButton): + if b.property("preset"): + b.setEnabled(on) + + # ---- PID selection ---- + def _apply_preset(self, name): + if not self.ctl.connected: + return + wanted = set(PRESETS.get(name, [])) + self.tree.blockSignals(True) + for key, it in self._items.items(): + want = key in wanted + it.setCheckState(0, QtCore.Qt.Checked if want else QtCore.Qt.Unchecked) + self.tree.blockSignals(False) + # sync subscriptions/curves to the new check state + for key in self._items: + self._sync_key(key) + + def _on_item_changed(self, item, col): + if col != 0: + return + key = item.data(0, QtCore.Qt.UserRole) + if key: + self._sync_key(key) + + def _sync_key(self, key): + it = self._items[key] + checked = it.checkState(0) == QtCore.Qt.Checked + has = key in self.curves + if checked and not has: + if self.ctl.connected: + self.ctl.subscribe(key) + self._add_curve(key) + elif not checked and has: + self.ctl.unsubscribe(key) + self._remove_curve(key) + + def _add_curve(self, key): + p = self.ctl.reg.get(key) + color = CURVE_COLORS[self._color_i % len(CURVE_COLORS)] + self._color_i += 1 + pen = pg.mkPen(color=color, width=2) + curve = self.plot.plot([], [], name=f"{p.name} ({p.unit})", pen=pen) + curve.setData([], []) + self.curves[key] = curve + + def _remove_curve(self, key): + curve = self.curves.pop(key, None) + if curve is not None: + self.plot.removeItem(curve) + legend = self.plot.plotItem.legend + if legend: + try: + legend.removeItem(curve) + except Exception: + pass + + # ---- periodic refresh ---- + def _tick(self): + if not self.ctl.connected: + return + now = self.ctl.now() + since = (self.ctl.t0 or 0) + max(0.0, now - PLOT_WINDOW_S) + normalize = self.norm_chk.isChecked() + + # update browser values + self.tree.blockSignals(True) + for key, it in self._items.items(): + v = self.ctl.store.latest(key) + p = self.ctl.reg.get(key) + it.setText(1, "--" if v is None else f"{v:g} {p.unit}".strip()) + self.tree.blockSignals(False) + + # update plotted curves + for key, curve in self.curves.items(): + p = self.ctl.reg.get(key) + series = self.ctl.store.channel(key).series(since=since) + xs, ys = [], [] + for t, v in series: + if v is None: + continue + xs.append(t - self.ctl.t0) + if normalize and p.vmax != p.vmin: + ys.append((v - p.vmin) / (p.vmax - p.vmin) * 100.0) + else: + ys.append(v) + curve.setData(xs, ys) + self.plot.setLabel("left", "% of range" if normalize else "value") + + def closeEvent(self, ev): + try: + self.timer.stop() + self.ctl.stop() + finally: + super().closeEvent(ev) + + +def run(): + import sys + app = QtWidgets.QApplication(sys.argv) + win = MainWindow() + win.show() + sys.exit(app.exec()) + + +if __name__ == "__main__": + run() diff --git a/obdcore/store.py b/obdcore/store.py index bcb5078..ae19e9a 100644 --- a/obdcore/store.py +++ b/obdcore/store.py @@ -10,7 +10,11 @@ from collections import deque class Channel: - """One PID's rolling history plus session min/max.""" + """One PID's rolling history plus session min/max. + + Lock-guarded so the acquisition thread can push while the GUI thread + reads series()/snapshots without a 'deque mutated during iteration' race. + """ def __init__(self, key, maxlen=3600): self.key = key @@ -19,22 +23,27 @@ class Channel: self.hi = None self.last_t = None self.last_v = None + self._lock = threading.Lock() def push(self, t, v): - self.buf.append((t, v)) - self.last_t, self.last_v = t, v - if v is not None: - self.lo = v if self.lo is None else min(self.lo, v) - self.hi = v if self.hi is None else max(self.hi, v) + with self._lock: + self.buf.append((t, v)) + self.last_t, self.last_v = t, v + if v is not None: + self.lo = v if self.lo is None else min(self.lo, v) + self.hi = v if self.hi is None else max(self.hi, v) def reset_minmax(self): - self.lo = self.hi = self.last_v + with self._lock: + self.lo = self.hi = self.last_v def series(self, since=None): """Return [(t, v), ...]; if since given, only samples with t >= since.""" + with self._lock: + items = list(self.buf) # snapshot under lock if since is None: - return list(self.buf) - return [(t, v) for (t, v) in self.buf if t >= since] + return items + return [(t, v) for (t, v) in items if t >= since] class TimeSeriesStore: diff --git a/requirements-gui.txt b/requirements-gui.txt new file mode 100644 index 0000000..657addd --- /dev/null +++ b/requirements-gui.txt @@ -0,0 +1,7 @@ +# GUI dependencies (cross-platform: Windows / macOS / Linux, incl. Apple Silicon) +# pip install -r requirements-gui.txt +# python run_gui.py +PySide6>=6.6 +pyqtgraph>=0.13 +numpy>=1.24 +pyserial>=3.5 diff --git a/run_gui.py b/run_gui.py new file mode 100644 index 0000000..4647e9b --- /dev/null +++ b/run_gui.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python3 +"""Launcher for the ford-obd GUI. + + pip install PySide6 pyqtgraph numpy pyserial + python run_gui.py + +Tick "Mock" + Connect to explore with simulated data (no adapter needed). +""" +from gui.main import run + +if __name__ == "__main__": + run()