Update README to match codebase

This commit is contained in:
Jimmy Allen
2026-04-01 20:20:37 -04:00
parent db723b6741
commit ab2efb3d8b

159
README.md
View File

@ -1,53 +1,77 @@
# OBD2 Terminal Dashboard # OBD2 Terminal Dashboard
This repository contains a Textual-based terminal dashboard for querying an OBD-II adapter and presenting live vehicle telemetry alongside raw command output. This repository contains a Textual-based terminal dashboard for querying an OBD-II adapter and rendering live telemetry, per-command values, editable cache TTLs, and application logs in one terminal UI.
`scanbus.py` is intentionally excluded from this README. ## Overview
## What It Does The application combines:
- Displays live dashboard metrics for speed, RPM, fuel level, oil temperature, and coolant temperature. - A Textual dashboard for live vehicle data
- Renders a command table for OBD modes `01`, `02`, `03`, `04`, `06`, `07`, and `09`. - An async OBD interface built on `python-OBD`
- Polls commands asynchronously with a global queries-per-second limit. - A per-command TTL cache with hot-reloaded overrides from `command_ttl.conf`
- Deduplicates concurrent reads of the same OBD command. - A simulated adapter path for development and tests
- Caches command results using a default TTL plus per-command overrides from `command_ttl.conf`.
- Supports a simulated mode for UI development without a physical adapter. The primary entry point is [`obd2_tui.py`](/Users/jallen/workspace/obd2/obd2_tui.py).
- Streams application logs inside the terminal UI.
## Features
- Displays live metrics for speed, RPM, fuel level, coolant temperature, and oil temperature
- Shows command data for OBD modes `01`, `02`, `03`, `04`, `06`, `07`, and `09`
- Polls core telemetry continuously while only querying table rows visible in the current viewport
- Deduplicates concurrent reads of the same OBD command through a shared pending-query map
- Enforces a global query-per-second limit across all outbound adapter requests
- Caches command results with a default TTL plus command-specific overrides
- Reloads TTL overrides automatically when `command_ttl.conf` changes
- Lets the user edit a selected command TTL directly from the UI
- Supports simulated telemetry for local development without hardware
- Streams logs into the application log panel
## Repository Layout ## Repository Layout
- `obd2_tui.py`: main Textual app, CLI entry point, keyboard bindings, command polling, and inline TTL editing. - [`obd2_tui.py`](/Users/jallen/workspace/obd2/obd2_tui.py): Textual application, CLI parsing, mode switching, viewport-aware polling, and TTL editing
- `obd2_interface.py`: async OBD abstraction, connection lifecycle, rate limiting, caching, TTL config reloads, and simulation support. - [`obd2_interface.py`](/Users/jallen/workspace/obd2/obd2_interface.py): adapter connection lifecycle, rate limiting, caching, TTL config reloads, and simulated interface support
- `models.py`: Pydantic models for the live telemetry report and scan definitions. - [`models.py`](/Users/jallen/workspace/obd2/models.py): Pydantic models for shared telemetry state and scan definitions
- `ui.css`: Textual stylesheet for the dashboard, command table, and log panel. - [`ui.css`](/Users/jallen/workspace/obd2/ui.css): Textual styling for the dashboard, data table, TTL editor, and log panel
- `command_ttl.conf`: command-specific cache TTL overrides in milliseconds. - [`command_ttl.conf`](/Users/jallen/workspace/obd2/command_ttl.conf): command-specific cache TTL overrides in milliseconds
- `test.py`: unit tests for report normalization, interface behavior, caching, TTL updates, simulation, and UI helpers. - [`test.py`](/Users/jallen/workspace/obd2/test.py): unit tests covering report normalization, interface behavior, simulation, caching, and UI helpers
- `requirements.txt`: Python dependencies. - [`requirements.txt`](/Users/jallen/workspace/obd2/requirements.txt): Python dependencies
## Architecture ## How It Works
The application has two main layers: ### UI layer
1. `OBD2App` in `obd2_tui.py` `OBD2App` builds a dashboard with:
- Builds the terminal UI with Textual.
- Polls a small set of key telemetry commands continuously for the metric cards.
- Polls the currently visible rows in the selected OBD mode table.
- Lets the user edit a selected command's cache TTL from the UI.
2. `OBD2Interface` in `obd2_interface.py` - Five metric cards
- Connects to the adapter through `python-OBD`. - A command table for the selected OBD mode
- Serializes outbound queries through a worker queue. - A TTL editor bound to the highlighted command
- Enforces a global rate limit. - An in-app log panel
- Maintains a TTL cache keyed by command name.
- Watches `command_ttl.conf` and hot-reloads TTL overrides.
`SimulatedOBD2Interface` swaps in a fake connection that generates dynamic values for development and testing. The app refresh loop does two things on each pass:
1. Queries the five telemetry commands needed for the metric cards
2. Queries only the currently visible command rows for the selected mode
Results are then applied back into the metric displays and table cells.
### Interface layer
`OBD2Interface` is responsible for:
- Connecting to the OBD adapter
- Serializing outbound queries through a worker queue
- Enforcing the global QPS limit
- Caching query results by command name
- Deduplicating in-flight requests for the same command
- Loading and reloading TTL overrides from disk
If a live adapter is unavailable, `SimulatedOBD2Interface` uses a synthetic connection that generates changing telemetry values and a few representative string responses such as VIN and DTC output.
## Requirements ## Requirements
- Python 3.11+ recommended - Python 3.11 or newer recommended
- An ELM327-compatible OBD-II adapter for real vehicle data - An ELM327-compatible OBD-II adapter for real vehicle data
- Terminal support suitable for a Textual application - A terminal environment that supports Textual applications
Install dependencies: Install dependencies:
@ -59,7 +83,7 @@ pip install -r requirements.txt
## Running ## Running
Run against a real OBD adapter: Run against a real adapter:
```bash ```bash
python3 obd2_tui.py python3 obd2_tui.py
@ -71,10 +95,11 @@ Run in simulated mode:
python3 obd2_tui.py --simulated python3 obd2_tui.py --simulated
``` ```
Optional flags: Available flags:
- `--qps`: maximum OBD queries per second across the app. Default: `10.0` - `--simulated`: use generated telemetry instead of a hardware adapter
- `--ttl-config`: path to the TTL override file. Default: `command_ttl.conf` - `--qps`: maximum OBD queries per second across the app, default `10.0`
- `--ttl-config`: path to the TTL override file, default `command_ttl.conf`
Example: Example:
@ -82,40 +107,25 @@ Example:
python3 obd2_tui.py --simulated --qps 25 --ttl-config command_ttl.conf python3 obd2_tui.py --simulated --qps 25 --ttl-config command_ttl.conf
``` ```
## UI Behavior
The dashboard is composed of:
- Metric cards for the five primary telemetry values
- A command table for the selected OBD mode
- A TTL editor bound to the currently highlighted command
- An in-app log panel
The polling strategy is selective:
- Core telemetry commands are always queried so the metric cards stay current.
- The mode table queries only commands that are currently visible in the viewport.
- Duplicate requests for the same command are coalesced through the interface queue and cache.
## Keyboard Controls ## Keyboard Controls
- `q`: quit - `q`: quit
- `b`: toggle metric card border style - `b`: toggle metric card border style
- `e`: focus the TTL editor - `e`: focus the TTL editor
- `escape`: return focus to the command table - `escape`: return focus to the command table
- `left` / `right`: previous or next OBD mode - `left` / `right`: switch to the previous or next OBD mode
- `shift+up` / `shift+down`: jump to top or bottom of the table - `shift+up` / `shift+down`: jump to the top or bottom of the table
- `1`, `2`, `3`, `4`, `6`, `7`, `9`: switch directly to that OBD mode - `1`, `2`, `3`, `4`, `6`, `7`, `9`: jump directly to a supported OBD mode
## TTL Configuration ## TTL Configuration
`command_ttl.conf` uses the format: `command_ttl.conf` uses:
```text ```text
COMMAND_NAME,ttl_ms COMMAND_NAME,ttl_ms
``` ```
Examples: Example:
```text ```text
SPEED,10 SPEED,10
@ -126,35 +136,26 @@ GET_DTC,86400000
Notes: Notes:
- TTL values are stored in milliseconds. - TTL values are stored in milliseconds
- A value of `0` effectively disables caching for that command. - `0` disables caching for that command
- The app reloads the file automatically while running. - Blank lines and comment lines beginning with `#` are ignored
- Editing a TTL in the UI writes the updated value back to the configured TTL file. - Editing a value in the UI writes the updated TTL back to the configured file
- The interface reloads TTL overrides automatically while the app is running
The TTL editor accepts plain millisecond values as well as duration suffixes such as `10ms`, `30s`, `1m`, and `1h`.
## Testing ## Testing
Run the unit tests with: Run the test suite with:
```bash ```bash
python3 -m unittest -v test.py python3 -m unittest -v test.py
``` ```
The tests cover: The current workspace environment has the required dependencies installed, and this command passes.
- Report value normalization ## Notes
- Query rate limiting
- Cache hit and cache expiry behavior
- TTL override parsing and persistence
- Simulated connection behavior
- Display formatting and duration parsing helpers
## Current Environment Note - The terminal dashboard is the main supported runtime path
- [`obd2_interface.py`](/Users/jallen/workspace/obd2/obd2_interface.py) also includes a standalone `__main__` path that logs report snapshots outside the TUI
In the current workspace environment, `python3 -m unittest -v test.py` fails immediately because `pydantic` is not installed. After installing dependencies from `requirements.txt`, the test command should be rerun. - Logging is routed into the UI through a custom `logging.Handler`
## Development Notes
- Logging is routed into the Textual `RichLog` panel through a custom logging handler.
- The codebase uses `Report` as the shared mutable telemetry state for the UI.
- `command_ttl.conf` is large because it predefines cache behavior for many standard OBD commands.
- `obd2_interface.py` also contains a non-TUI `__main__` path that continuously logs report snapshots, but the primary entry point for normal use is `obd2_tui.py`.