# 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. `scanbus.py` is intentionally excluded from this README. ## What It Does - 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. ## 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. ## Architecture The application has two main layers: 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. 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. `SimulatedOBD2Interface` swaps in a fake connection that generates dynamic values for development and testing. ## Requirements - Python 3.11+ recommended - An ELM327-compatible OBD-II adapter for real vehicle data - Terminal support suitable for a Textual application Install dependencies: ```bash python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt ``` ## Running Run against a real OBD adapter: ```bash python3 obd2_tui.py ``` Run in simulated mode: ```bash python3 obd2_tui.py --simulated ``` Optional 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` Example: ```bash 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 ## TTL Configuration `command_ttl.conf` uses the format: ```text COMMAND_NAME,ttl_ms ``` Examples: ```text SPEED,10 RPM,10 FUEL_LEVEL,5000 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. ## Testing Run the unit tests with: ```bash python3 -m unittest -v test.py ``` The tests cover: - 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 ## 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`.