# OBD2 Terminal Dashboard 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. ## Overview The application combines: - 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`](/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 ## How It Works ### UI layer `OBD2App` builds a dashboard with: - Five metric cards - A command table for the selected OBD mode - A TTL editor bound to the highlighted command - An in-app log panel 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 or newer recommended - An ELM327-compatible OBD-II adapter for real vehicle data - A terminal environment that supports Textual applications Install dependencies: ```bash python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt ``` ## Running Run against a real adapter: ```bash python3 obd2_tui.py ``` Run in simulated mode: ```bash python3 obd2_tui.py --simulated ``` Available flags: - `--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: ```bash python3 obd2_tui.py --simulated --qps 25 --ttl-config command_ttl.conf ``` ## Keyboard Controls - `q`: quit - `b`: toggle metric card border style - `e`: focus the TTL editor - `escape`: return focus to the command table - `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: ```text COMMAND_NAME,ttl_ms ``` Example: ```text SPEED,10 RPM,10 FUEL_LEVEL,5000 GET_DTC,86400000 ``` Notes: - 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 test suite with: ```bash python3 -m unittest -v test.py ``` The current workspace environment has the required dependencies installed, and this command passes. ## Notes - 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`