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
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.
- Renders a command table for OBD modes `01`, `02`, `03`, `04`, `06`, `07`, and `09`.
- Polls commands asynchronously with a global queries-per-second limit.
- Deduplicates concurrent reads of the same OBD command.
- 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.
- Streams application logs inside the terminal UI.
- A Textual dashboard for live vehicle data
- An async OBD interface built on `python-OBD`
- A per-command TTL cache with hot-reloaded overrides from `command_ttl.conf`
- A simulated adapter path for development and tests
The primary entry point is [`obd2_tui.py`](/Users/jallen/workspace/obd2/obd2_tui.py).
## 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
- `obd2_tui.py`: main Textual app, CLI entry point, keyboard bindings, command polling, and inline TTL editing.
- `obd2_interface.py`: async OBD abstraction, connection lifecycle, rate limiting, caching, TTL config reloads, and simulation support.
- `models.py`: Pydantic models for the live telemetry report and scan definitions.
- `ui.css`: Textual stylesheet for the dashboard, command table, and log panel.
- `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.
- `requirements.txt`: Python dependencies.
- [`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`](/Users/jallen/workspace/obd2/obd2_interface.py): adapter connection lifecycle, rate limiting, caching, TTL config reloads, and simulated interface support
- [`models.py`](/Users/jallen/workspace/obd2/models.py): Pydantic models for shared telemetry state and scan definitions
- [`ui.css`](/Users/jallen/workspace/obd2/ui.css): Textual styling for the dashboard, data table, TTL editor, and log panel
- [`command_ttl.conf`](/Users/jallen/workspace/obd2/command_ttl.conf): command-specific cache TTL overrides in milliseconds
- [`test.py`](/Users/jallen/workspace/obd2/test.py): unit tests covering report normalization, interface behavior, simulation, caching, and UI helpers
- [`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`
- 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.
`OBD2App` builds a dashboard with:
2. `OBD2Interface` in `obd2_interface.py`
- Connects to the adapter through `python-OBD`.
- Serializes outbound queries through a worker queue.
- Enforces a global rate limit.
- Maintains a TTL cache keyed by command name.
- Watches `command_ttl.conf` and hot-reloads TTL overrides.
- Five metric cards
- A command table for the selected OBD mode
- A TTL editor bound to the highlighted command
- An in-app log panel
`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
- Python 3.11+ recommended
- Python 3.11 or newer recommended
- 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:
@ -59,7 +83,7 @@ pip install -r requirements.txt
## Running
Run against a real OBD adapter:
Run against a real adapter:
```bash
python3 obd2_tui.py
@ -71,10 +95,11 @@ Run in simulated mode:
python3 obd2_tui.py --simulated
```
Optional flags:
Available flags:
- `--qps`: maximum OBD queries per second across the app. Default: `10.0`
- `--ttl-config`: path to the TTL override file. Default: `command_ttl.conf`
- `--simulated`: use generated telemetry instead of a hardware adapter
- `--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:
@ -82,40 +107,25 @@ Example:
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
- `q`: quit
- `b`: toggle metric card border style
- `e`: focus the TTL editor
- `escape`: return focus to the command table
- `left` / `right`: previous or next OBD mode
- `shift+up` / `shift+down`: jump to top or bottom of the table
- `1`, `2`, `3`, `4`, `6`, `7`, `9`: switch directly to that OBD mode
- `left` / `right`: switch to the previous or next OBD mode
- `shift+up` / `shift+down`: jump to the top or bottom of the table
- `1`, `2`, `3`, `4`, `6`, `7`, `9`: jump directly to a supported OBD mode
## TTL Configuration
`command_ttl.conf` uses the format:
`command_ttl.conf` uses:
```text
COMMAND_NAME,ttl_ms
```
Examples:
Example:
```text
SPEED,10
@ -126,35 +136,26 @@ GET_DTC,86400000
Notes:
- TTL values are stored in milliseconds.
- A value of `0` effectively disables caching for that command.
- The app reloads the file automatically while running.
- Editing a TTL in the UI writes the updated value back to the configured TTL file.
- TTL values are stored in milliseconds
- `0` disables caching for that command
- Blank lines and comment lines beginning with `#` are ignored
- 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
Run the unit tests with:
Run the test suite with:
```bash
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
- Query rate limiting
- Cache hit and cache expiry behavior
- TTL override parsing and persistence
- Simulated connection behavior
- Display formatting and duration parsing helpers
## Notes
## Current Environment Note
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.
## 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`.
- 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
- Logging is routed into the UI through a custom `logging.Handler`