README: rewrite as cross-platform multi-vehicle GUI app; add release checksums
- README now leads with the vehicle-agnostic GUI (download binaries, run from source, connect, vehicle profiles), with the Ford 6.0 CLI as a secondary section. Documents the unsigned-binary SmartScreen/Gatekeeper bypass. - CI: each release binary now ships a .sha256 so downloads can be verified (free integrity check in lieu of code signing). - Validated on real vehicles (Jeep 4.0, Mustang Cobra 4.6). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016yT89n4zR4qbrySoSiEyZs
This commit is contained in:
@@ -42,11 +42,14 @@ jobs:
|
||||
& $py -m pip install --no-cache-dir -r requirements-gui.txt pyinstaller
|
||||
& $py -m PyInstaller --noconfirm --onefile --windowed --name OBDash --add-data "profiles;profiles" run_gui.py
|
||||
Copy-Item dist/OBDash.exe OBDash-windows.exe
|
||||
(Get-FileHash OBDash-windows.exe -Algorithm SHA256).Hash.ToLower() + " OBDash-windows.exe" | Out-File -Encoding ascii OBDash-windows.exe.sha256
|
||||
- name: Publish to release
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: OBDash-windows.exe
|
||||
files: |
|
||||
OBDash-windows.exe
|
||||
OBDash-windows.exe.sha256
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
|
||||
@@ -63,11 +66,14 @@ jobs:
|
||||
pip install -r requirements-gui.txt pyinstaller
|
||||
pyinstaller --noconfirm --windowed --name OBDash --add-data "profiles:profiles" run_gui.py
|
||||
ditto -c -k --keepParent dist/OBDash.app OBDash-macos.zip
|
||||
shasum -a 256 OBDash-macos.zip > OBDash-macos.zip.sha256
|
||||
- name: Publish to release
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: OBDash-macos.zip
|
||||
files: |
|
||||
OBDash-macos.zip
|
||||
OBDash-macos.zip.sha256
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
|
||||
@@ -84,11 +90,14 @@ jobs:
|
||||
pip install -r requirements-gui.txt pyinstaller
|
||||
pyinstaller --noconfirm --onefile --name OBDash --add-data "profiles:profiles" run_gui.py
|
||||
cp dist/OBDash OBDash-linux-x86_64
|
||||
sha256sum OBDash-linux-x86_64 > OBDash-linux-x86_64.sha256
|
||||
- name: Publish to release
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: OBDash-linux-x86_64
|
||||
files: |
|
||||
OBDash-linux-x86_64
|
||||
OBDash-linux-x86_64.sha256
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
|
||||
@@ -105,10 +114,13 @@ jobs:
|
||||
pip install -r requirements-gui.txt pyinstaller
|
||||
pyinstaller --noconfirm --onefile --name OBDash --add-data "profiles:profiles" run_gui.py
|
||||
cp dist/OBDash OBDash-linux-aarch64
|
||||
sha256sum OBDash-linux-aarch64 > OBDash-linux-aarch64.sha256
|
||||
- name: Publish to release
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: OBDash-linux-aarch64
|
||||
files: |
|
||||
OBDash-linux-aarch64
|
||||
OBDash-linux-aarch64.sha256
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
|
||||
@@ -1,139 +1,134 @@
|
||||
# OBDash
|
||||
|
||||
Minimal **ELM327 OBD-II code reader** with a **Ford 6.0L Power Stroke no-start triage**,
|
||||
built for a cheap CH340 ELM327 USB adapter. Works on any OBD-II vehicle for generic
|
||||
codes/PIDs; the triage notes are 6.0-specific.
|
||||
**Open-source, vehicle-agnostic OBD-II scanner — Python/Qt, cross-platform.**
|
||||
|
||||
Created as a stopgap while [forscan.org](https://forscan.org) was offline — it covers
|
||||
reading/clearing codes and the basics, not Ford-enhanced diesel PIDs (see Scope below).
|
||||
|
||||
## Features
|
||||
|
||||
- Read **stored** (mode 03), **pending** (mode 07), **permanent** (mode 0A) DTCs
|
||||
- Decode P/C/B/U codes, with common **6.0 codes** described and **no-start suspects flagged**
|
||||
- **Clear** codes (mode 04) — guarded behind `--clear` + a typed `CLEAR` confirmation,
|
||||
then re-reads to show any code that returns immediately (active fault)
|
||||
- Key **live values** (coolant, IAT, MAP, module voltage, RPM, load, throttle) + battery voltage
|
||||
- 6.0 Power Stroke **no-start triage** checklist (FICM, ICP, cam/crank, batteries, fuel)
|
||||
|
||||
## Setup
|
||||
|
||||
Runs on **Windows, macOS, and Linux** (Python + pyserial). The only per-OS
|
||||
difference is the CH340 USB driver:
|
||||
|
||||
- **Windows** — install WCH `CH341SER`; adapter shows as `USB-SERIAL CH340 (COMx)`
|
||||
in Device Manager → Ports. Install Python from <https://www.python.org/downloads/>
|
||||
(tick **Add Python to PATH**), or just double-click `RUN_OBD.bat`.
|
||||
- **macOS** — install WCH `CH34xVCPDriver` (Mac App Store or wch.cn). Port appears
|
||||
as `/dev/cu.wchusbserial*`. `pip install pyserial`.
|
||||
- **Linux** — `ch341` driver is built into the kernel (no install). Port is
|
||||
`/dev/ttyUSB0`; add yourself to the `dialout` group for access
|
||||
(`sudo usermod -aG dialout $USER`, then re-login). `pip install pyserial`.
|
||||
|
||||
The tool auto-detects the port on all three; pass it explicitly if needed
|
||||
(`COM5`, `/dev/cu.usbserial-1420`, `/dev/ttyUSB0`).
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
python obd_reader.py # auto-detect the COM port
|
||||
python obd_reader.py COM5 # force a port
|
||||
python obd_reader.py COM5 9600 # force port + baud (default 38400)
|
||||
python obd_reader.py COM5 --clear # read, then optionally clear (asks to confirm)
|
||||
python obd_reader.py COM5 -v # verbose: show raw ELM327 traffic
|
||||
```
|
||||
|
||||
### Crank monitor (dedicated no-start view) — `--crank`
|
||||
|
||||
The one to use for a crank-but-won't-start. Big ICP readout with a wide bar
|
||||
(the `|` marks the 500-psi firing threshold), a **rolling ASCII trace** of the
|
||||
ICP build-up, **peak-hold**, FICM/battery/RPM with sag tracking, and a pass/fail
|
||||
verdict. Start it, then crank.
|
||||
|
||||
```
|
||||
python obd_reader.py COM5 --crank # crank monitor
|
||||
python obd_reader.py COM5 --crank --dash-log crank.csv # + record a CSV
|
||||
```
|
||||
|
||||
```
|
||||
ICP [#################################|##----] 539.8 psi
|
||||
PEAK 540 psi FIRING PRESSURE REACHED
|
||||
FICM Main 47.5V (min 47.5) [DOC] Batt 12.6V (min 10.7) RPM 200
|
||||
|
||||
ICP trace (psi vs time, last 16 samples)
|
||||
600 |
|
||||
500 |----------------------------------------------#### <- firing line
|
||||
| ######
|
||||
| ########
|
||||
+--------------------------------------------------
|
||||
```
|
||||
|
||||
**Read it:** ICP should climb **past 500 psi within 1–2 s** of cranking
|
||||
(`FIRING PRESSURE REACHED`, green). If it **stalls below 500** (red, trace flat
|
||||
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)
|
||||
|
||||
A cross-platform desktop GUI (PySide6 + pyqtgraph). Vehicle-agnostic — all PIDs,
|
||||
scaling, DTCs, and presets come from the JSON profiles in `profiles/`.
|
||||
|
||||
```
|
||||
pip install -r requirements-gui.txt
|
||||
python run_gui.py # tick "Mock" + Connect to explore with no adapter
|
||||
```
|
||||
|
||||
Features so far:
|
||||
- **PID browser** (left) grouped by system, live values, confidence badges
|
||||
- **Graph view** with **true multi-axis** overlay — one Y scale per unit (psi/V/rpm/…),
|
||||
or a Normalize (% of range) mode
|
||||
- **Gauge view** — arc gauges with peak-hold, one per signal
|
||||
- **Table view** — value + min/max + confidence
|
||||
- **Diagnostics** — read/clear DTCs (guarded), no-start codes flagged
|
||||
- **Profile menu** — switch/import/edit vehicles; **File menu** — record/replay/export captures
|
||||
A desktop app that turns a cheap ELM327 adapter into a real diagnostic tool:
|
||||
live multi-axis graphs, automotive-style gauges, a sortable data table, and
|
||||
DTC read/clear — for **any OBD-II vehicle**. What it can read for each car is
|
||||
defined by a **JSON vehicle profile** (PIDs, scaling, codes, gauges), so adding
|
||||
a new vehicle is data, not code. Runs on **Windows, macOS, and Linux**.
|
||||
|
||||

|
||||

|
||||
|
||||
The whole app runs against simulated data (`MockLink`), so it can be developed
|
||||
on any machine and only needs the vehicle for real captures. See
|
||||
[ARCHITECTURE.md](ARCHITECTURE.md) for the roadmap.
|
||||
> Validated on real vehicles (1997 Jeep Wrangler 4.0 I6, 1996 Mustang Cobra 4.6
|
||||
> DOHC, Ford 6.0L Power Stroke, …) using a QinHeng CH340 ELM327 clone.
|
||||
|
||||
---
|
||||
## Features
|
||||
|
||||
### Live dashboard (real-time gauges)
|
||||
- **Live graphs** with **true multi-axis** overlay — each metric gets its own
|
||||
Y axis, colored to match its line; click a line to move its axis to the left.
|
||||
Optional Normalize (% of range) mode.
|
||||
- **Gauge view** — round, tach-style gauges with tick scales, needles, **redline
|
||||
zones** (configurable per metric), and peak-hold.
|
||||
- **Table view** — value, min/max, and confidence per signal.
|
||||
- **Diagnostics** — read stored/pending/permanent trouble codes and clear them
|
||||
(guarded), with descriptions and **no-start codes flagged**.
|
||||
- **Vehicle profiles** — switch/import/edit vehicles from the Profile menu.
|
||||
- **Units** — °C/°F toggle (US/metric).
|
||||
- **Captures** — record a session to CSV and replay it.
|
||||
- **Mock mode** — explore the whole app with simulated data, no adapter needed.
|
||||
|
||||
Updates in place as you crank or run the engine — color-coded, with live
|
||||
min/max so a crank's **peak ICP** is captured. No extra dependencies (ANSI;
|
||||
works on any Windows 10+ terminal). `q` quits, `r` resets min/max.
|
||||
## Download
|
||||
|
||||
Grab a prebuilt binary from the [**latest release**](https://git.jpaul.io/justin/obdash/releases/latest):
|
||||
|
||||
| Platform | File |
|
||||
|---|---|
|
||||
| Windows | `OBDash-windows.exe` |
|
||||
| macOS | `OBDash-macos.zip` (unzip → `OBDash.app`) |
|
||||
| Linux x86_64 | `OBDash-linux-x86_64` |
|
||||
| Linux ARM64 (Raspberry Pi) | `OBDash-linux-aarch64` |
|
||||
|
||||
Each binary ships with a `.sha256` so you can verify the download:
|
||||
|
||||
```bash
|
||||
# macOS / Linux
|
||||
shasum -a 256 -c OBDash-macos.zip.sha256 # macOS
|
||||
sha256sum -c OBDash-linux-x86_64.sha256 # Linux
|
||||
```
|
||||
python obd_reader.py COM5 --dash # vitals preset (ICP, FICM, IPR, batt, RPM, temps)
|
||||
python obd_reader.py COM5 --dash crank # cranking preset: ICP / FICM main / batt / RPM (fastest)
|
||||
python obd_reader.py COM5 --dash full # every PID
|
||||
python obd_reader.py COM5 --dash crank --dash-log crank.csv # + write a CSV while you watch
|
||||
```powershell
|
||||
# Windows
|
||||
(Get-FileHash OBDash-windows.exe -Algorithm SHA256).Hash.ToLower()
|
||||
Get-Content OBDash-windows.exe.sha256 # compare the two
|
||||
```
|
||||
|
||||
**No-start use:** run `--dash crank`, then crank. A healthy 6.0 builds
|
||||
**~500+ psi ICP within 1–2 s**; if ICP stalls below 500 (red), that confirms
|
||||
the high-pressure oil bleed-off. FICM Main should hold ~48V. The `--dash-log`
|
||||
CSV is your streaming log — paste it back for analysis.
|
||||
### Unsigned-binary warnings (expected for open source)
|
||||
|
||||
Note: the FICM PIDs (`09xx`) are `[DOC]` (not yet confirmed on this truck); if
|
||||
they read `--`, they auto-drop after a few frames so the refresh rate stays up.
|
||||
The binaries aren't code-signed, so the OS will warn on first launch. They're safe
|
||||
— verify the checksum above, then:
|
||||
|
||||
Or just double-click **`RUN_OBD.bat`** on Windows (auto-installs `pyserial`).
|
||||
- **Windows (SmartScreen):** "Windows protected your PC" → **More info** → **Run anyway**.
|
||||
- **macOS (Gatekeeper):** right-click the app → **Open** (then **Open** again), or
|
||||
clear the quarantine flag: `xattr -dr com.apple.quarantine OBDash.app`.
|
||||
- **Linux:** `chmod +x OBDash-linux-x86_64 && ./OBDash-linux-x86_64`.
|
||||
|
||||
On the truck: plug into the OBD port under the dash, key to **RUN** (engine off is fine
|
||||
for codes), then run the tool.
|
||||
(Code signing removes these warnings but costs money / a hardware token; see the
|
||||
project notes. Checksums give you the same integrity guarantee for free.)
|
||||
|
||||
## Scope / honesty
|
||||
## Run from source
|
||||
|
||||
A generic ELM327 reads standard OBD-II only: codes, generic PIDs, port voltage. It does
|
||||
**not** read Ford-enhanced diesel PIDs (ICP, FICM main/sync voltage, IPR%) — those need
|
||||
FORScan. For FICM/ICP numbers, measure at the FICM with a meter, or use FORScan when it's
|
||||
available. Default baud is 38400 (measured on the CH340 adapter); try 9600 if you get garbage.
|
||||
```bash
|
||||
pip install -r requirements-gui.txt
|
||||
python run_gui.py # tick "Mock" + Connect to explore with no adapter
|
||||
```
|
||||
|
||||
## Requirements
|
||||
Needs Python 3.10+. The GUI deps (`PySide6`, `pyqtgraph`, `numpy`, `pyserial`)
|
||||
all ship wheels for Windows / macOS (incl. Apple Silicon) / Linux.
|
||||
|
||||
`pyserial` (`pip install pyserial`). Tested against a QinHeng CH340 ELM327 v1.5 clone.
|
||||
## Connecting to a vehicle
|
||||
|
||||
Plug an **ELM327 (USB or Bluetooth)** into the OBD-II port, turn the key to RUN,
|
||||
then pick the port and **Connect**. The CH340 USB adapters need a one-time driver:
|
||||
|
||||
- **Windows** — WCH `CH341SER`; shows as `USB-SERIAL CH340 (COMx)` in Device Manager.
|
||||
- **macOS** — WCH `CH34xVCPDriver` (Mac App Store / wch.cn); port `/dev/cu.wchusbserial*`.
|
||||
- **Linux** — `ch341` is in the kernel (no install); port `/dev/ttyUSB0` (add yourself
|
||||
to the `dialout` group: `sudo usermod -aG dialout $USER`).
|
||||
|
||||
Default baud is 38400; the ELM327 auto-negotiates the vehicle's protocol.
|
||||
|
||||
## Vehicle profiles
|
||||
|
||||
Each `profiles/*.json` teaches OBDash how to read one vehicle. Bundled profiles:
|
||||
|
||||
| Profile | Vehicle |
|
||||
|---|---|
|
||||
| `generic-obd2.json` | Any OBD-II vehicle (standard SAE PIDs) — a base to fork |
|
||||
| `ford-6.0-powerstroke.json` | Ford 6.0L Power Stroke (2003–2007) — incl. enhanced ICP/FICM/EBP PIDs |
|
||||
| `jeep-wrangler-4.0-1997.json` | 1997 Jeep Wrangler TJ 4.0 I6 |
|
||||
| `ford-mustang-cobra-4.6-1996.json` | 1996 Mustang SVT Cobra 4.6 DOHC |
|
||||
| `ford-mustang-gt-4.6-1996.json` | 1996 Mustang GT 4.6 SOHC |
|
||||
| `mercury-mountaineer-4.6-2006.json` | 2006 Mercury Mountaineer 4.6 V8 |
|
||||
|
||||
**Add your vehicle:** the format is documented in
|
||||
[`profiles/PROFILE_SPEC.md`](profiles/PROFILE_SPEC.md) — it's written to be handed
|
||||
straight to an AI agent (*"research <year make model> and produce an OBDash
|
||||
profile per this spec"*). Drop the `.json` in `profiles/`, load it from the
|
||||
**Profile** menu, and open a PR. Profiles are pure data — they can't run code
|
||||
(formulas go through a sandboxed evaluator).
|
||||
|
||||
## Terminal tool (Ford 6.0 no-start)
|
||||
|
||||
The repo also includes `obd_reader.py`, a self-contained **CLI** focused on
|
||||
diagnosing a **6.0 Power Stroke that won't start** — a big live **ICP-during-crank**
|
||||
monitor (`--crank`), code read/clear, and CSV logging. It needs only `pyserial`.
|
||||
See `handoff.md` and `diagnostics/` for the worked no-start investigation that
|
||||
seeded this project. (The GUI above is the general-purpose, multi-vehicle tool;
|
||||
the CLI is the diesel-specific workflow it grew out of.)
|
||||
|
||||
```bash
|
||||
python obd_reader.py COM5 --crank # big ICP cranking monitor
|
||||
python obd_reader.py COM5 --clear # read, then clear codes (guarded)
|
||||
```
|
||||
|
||||
## Project
|
||||
|
||||
- [`ARCHITECTURE.md`](ARCHITECTURE.md) — design, the acquisition engine, roadmap.
|
||||
- Built on a headless `obdcore` package (link / registry / scheduler / store)
|
||||
shared by the GUI and the CLI; tested without hardware via a mock adapter.
|
||||
- CI builds the cross-platform binaries on tag (`.gitea/workflows/release.yml`).
|
||||
|
||||
## License
|
||||
|
||||
MIT — see [`LICENSE`](LICENSE).
|
||||
|
||||
Reference in New Issue
Block a user