hondavert-dev/docs/FULL_PROJECT_DOCUMENTATION.md
HVBT Dev 763821171c feat: Add ECU Frame Debug Screen and DTC Screen
- Implemented RawFrameDebugScreen for displaying ECU frame data and diagnostics.
- Created DtcScreen to show active Diagnostic Trouble Codes (DTCs) with detailed descriptions.
- Added DtcRow widget for individual DTC representation.
- Introduced GraphScreen for visualizing sensor data over time with customizable time windows.
- Developed SensorListScreen to display available sensors and their current values.
- Enhanced SettingsScreen with options for Bluetooth connection, ECU protocol selection, polling interval, and theme settings.
- Added AppColors and AppTheme for consistent theming across the application.
- Implemented BtStatusChip to show Bluetooth connection status in the app bar.
- Created RecordFab for starting and stopping data recording sessions.
2026-07-26 23:14:58 +05:30

18 KiB

HV BT Dashboard - Full Project Documentation

1. Simple Summary

HV BT Dashboard is a Flutter Android app for car/ECU monitoring over Bluetooth. ̥ In plain terms, the app connects to a paired Bluetooth ECU device, asks the ECU for live data many times per second, checks that the received data is valid, converts the raw bytes into readable vehicle values, and shows those values on dashboards, lists, graphs, fault-code screens, and saved recording screens.

The main use case is for a driver, tuner, mechanic, or performance shop that wants to see Honda ECU data such as RPM, speed, throttle, manifold pressure, coolant temperature, intake temperature, battery voltage, fuel/ignition related readings, warning flags, and diagnostic trouble codes.

2. What The App Is For

This app is not a general car marketplace or booking app. It is an ECU dashboard and datalogging tool.

It helps a user:

  • Connect to a Bluetooth ECU adapter.
  • Choose the ECU protocol: S300 or KPro.
  • Watch live vehicle sensor data.
  • See important values in a large dashboard layout.
  • See all supported sensor values in a list.
  • Graph selected sensors over time.
  • Check active diagnostic trouble codes.
  • Record raw ECU frames into local storage.
  • View saved recording sessions.
  • Start playback controls for saved sessions.
  • Change theme, ECU protocol, and polling speed.

3. Main Benefits

The business/user benefits are:

  • Faster troubleshooting: faults and live readings are visible in one app.
  • Safer tuning support: important values like RPM, MAP, TPS, coolant temperature, intake temperature, AFR, trims, and battery voltage can be watched live.
  • Better diagnosis: diagnostic trouble codes are decoded into readable descriptions instead of only raw bytes.
  • Better review after driving: sessions can be recorded and saved locally.
  • Flexible display: users can choose which sensors appear on dashboard tiles and graph panels.
  • Works without a backend: data is read from Bluetooth and saved on the phone using SQLite.
  • Supports two ECU families: S300 and KPro parser paths are implemented.

4. Technology Stack

The app is built with:

  • Flutter: mobile app framework.
  • Dart: programming language.
  • Riverpod: state management.
  • flutter_bluetooth_serial: Bluetooth Classic serial communication.
  • permission_handler: Android Bluetooth/location permissions.
  • fl_chart: graph display.
  • sqflite: local SQLite database for datalog sessions.
  • path_provider and path: local file/database path handling.
  • intl: date formatting for saved sessions.

The project is currently Android-focused. The Android manifest includes Bluetooth and location permissions required for scanning/connecting on Android.

5. App Startup Flow

The app starts from lib/main.dart.

Startup flow:

  1. main() starts the Flutter app inside a Riverpod ProviderScope.
  2. HvbtApp builds a MaterialApp.
  3. The selected theme is read from themeProvider.
  4. The first screen is BtPickerScreen.

So the first thing a user sees is not the dashboard. The user is first asked to connect to an ECU Bluetooth device.

6. User Journey

The typical user journey is:

  1. User opens the app.
  2. App requests Bluetooth and location permissions.
  3. App checks whether Bluetooth is turned on.
  4. App loads already paired Bluetooth devices.
  5. User taps the ECU Bluetooth device.
  6. App asks whether the ECU protocol is S300 or KPro.
  7. App connects to the selected Bluetooth device.
  8. App starts polling the ECU.
  9. App receives 128-byte data frames.
  10. App validates each frame using NEG8 checksum.
  11. App parses the frame into readable sensor values.
  12. App navigates to the main dashboard.
  13. User can switch between Dashboard, Sensors, Graph, and DTC tabs.
  14. User can record a datalog session using the floating record button.
  15. User can open saved sessions from the folder icon.
  16. User can change protocol/theme/polling settings from the settings icon.

7. Main Screens

7.1 Bluetooth Picker Screen

File: lib/ui/screens/bt_picker/bt_picker_screen.dart

Purpose:

  • Ask for required permissions.
  • Turn on Bluetooth if needed.
  • Show paired Bluetooth devices.
  • Let the user pick an ECU device.
  • Ask the user to choose S300 or KPro.
  • Start the Bluetooth connection.

Important behavior:

  • The app only lists paired devices. The user must pair the ECU adapter in Android settings first.
  • The screen requests bluetoothConnect, bluetoothScan, and locationWhenInUse.
  • If permissions are denied, it shows a red error banner.
  • On successful connection, it replaces the screen with MainNav.

7.2 Main Navigation

File: lib/ui/widgets/main_nav.dart

Purpose:

  • Provides the main app shell after Bluetooth connection.
  • Shows the app bar.
  • Shows Bluetooth status.
  • Shows saved session and settings buttons.
  • Shows bottom navigation.
  • Shows the record floating button.

Main tabs:

  • Dashboard
  • Sensors
  • Graph
  • DTC

The app uses an IndexedStack, so tab state is kept while switching tabs.

7.3 Dashboard Screen

Files:

  • lib/ui/screens/dashboard/dashboard_screen.dart
  • lib/ui/screens/dashboard/dashboard_vertical.dart
  • lib/ui/screens/dashboard/dashboard_horizontal.dart
  • lib/ui/screens/dashboard/dashboard_slots_provider.dart

Purpose:

  • Show the live dashboard in a visually useful layout.
  • Show a large RPM gauge.
  • Show quick sensor tiles.
  • Show warning/condition flags.

Portrait layout:

  • Large RPM gauge at the top.
  • Flag row below it.
  • Six sensor tiles in a 2-column grid.

Landscape layout:

  • Sensor tiles on left and right.
  • Large RPM gauge in the middle.
  • Flag row at the bottom.

Default dashboard tile sensors:

  • Speed
  • Manifold pressure
  • Throttle pedal
  • Coolant temperature
  • Intake air temperature
  • Battery voltage

The user can long-press a sensor tile and choose a different sensor for that slot.

7.4 Sensor List Screen

File: lib/ui/screens/sensor_list/sensor_list_screen.dart

Purpose:

  • Show all supported sensor values in a complete list.

This is useful when the dashboard does not show a particular value, but the user still wants to see it.

Supported analog/numeric sensors include:

  • RPM
  • Speed
  • Manifold pressure
  • Throttle pedal
  • Injector duration
  • Timing advance
  • Coolant temperature
  • Intake air temperature
  • Battery voltage
  • O2 sensor
  • Gear
  • Ethanol
  • Barometric pressure
  • AFR
  • Short trim
  • Long trim
  • Analog input 0 through Analog input 7

7.5 Graph Screen

Files:

  • lib/ui/screens/graph/graph_screen.dart
  • lib/ui/screens/graph/widgets/sensor_graph_panel.dart
  • lib/core/providers/sensor_history_provider.dart

Purpose:

  • Show live sensor values over time.
  • Let the user choose which sensors to graph.
  • Let the user choose the visible time window.

Default graph sensors:

  • RPM
  • MAP
  • TPS

The history provider stores up to 18,000 points per sensor in memory. This is live in-memory graph history, not the same thing as saved datalog storage.

7.6 DTC Screen

Files:

  • lib/ui/screens/dtc/dtc_screen.dart
  • lib/core/protocol/dtc_map.dart

Purpose:

  • Decode ECU error bytes into readable diagnostic trouble codes.
  • Show whether there are active faults.

If there are no codes, the screen shows an all-clear state.

If codes are active, the screen lists code and description, for example P0130 - O2 Sensor (front).

S300 supports 4 error bytes in this app. KPro supports 18 error bytes in this app.

7.7 Saved Sessions Screen

Files:

  • lib/ui/screens/datalog/datalog_list_screen.dart
  • lib/ui/screens/datalog/datalog_playback_bar.dart
  • lib/core/datalog/datalog_db.dart
  • lib/core/datalog/datalog_recorder.dart
  • lib/core/datalog/datalog_player.dart

Purpose:

  • Show recorded sessions.
  • Show session date, ECU type, frame count, and duration.
  • Delete old sessions.
  • Load a saved session into playback.
  • Show playback progress, play/pause/stop controls, seek slider, and speed selector.

Important current note:

The player has a stream that can replay saved frames, and the UI has playback controls. However, the current live sensor provider listens to the Bluetooth frame stream, not the datalog player stream. That means the saved-session playback control layer exists, but the dashboard/sensor/graph screens are not currently wired to consume playback frames as a replacement for live Bluetooth frames.

7.8 Settings Screen

File: lib/ui/screens/settings/settings_screen.dart

Purpose:

  • Show current Bluetooth connection state.
  • Disconnect Bluetooth.
  • Choose ECU protocol.
  • Choose polling interval.
  • Choose theme.
  • Show app information.

Available ECU protocols:

  • S300
  • KPro

Available polling intervals:

  • 50 ms, about 20 Hz
  • 100 ms, about 10 Hz
  • 200 ms, about 5 Hz

Available themes:

  • Red - Dark
  • Red - Light
  • Green - Dark
  • Green - Light

8. Bluetooth And ECU Data Flow

This is the most important technical flow in the app.

Simple version:

The app asks the ECU for data. The ECU replies with bytes. The app checks the bytes. Then the app converts them into numbers and displays them.

Detailed flow:

  1. BtPickerScreen asks the user to select a paired Bluetooth device.
  2. BtNotifier.connect() calls BtService.connect().
  3. BtService opens a Bluetooth Classic RFCOMM/SPP connection.
  4. BtPoller starts a timer.
  5. On each timer tick, BtPoller sends a request command to the ECU.
  6. The ECU sends back raw bytes.
  7. BtPoller collects those bytes into a buffer.
  8. It looks for a frame starting with 0x1B.
  9. It extracts 128-byte frames.
  10. It validates the frame using validateFrame().
  11. Valid frames are sent to BtNotifier.frameStream.
  12. sensorStateProvider parses each frame.
  13. UI screens read latestSensorProvider and update.

Request bytes:

  • S300 request: [0x1B, 0x00, 0xE5]
  • KPro request: [0x1B, 0x01, 0xE4]

Frame size:

  • 128 bytes

Default polling:

  • 100 ms, roughly 10 updates per second

9. Parsing Logic

The app has two parser files:

  • lib/core/protocol/s300_parser.dart
  • lib/core/protocol/kpro_parser.dart

Both parsers produce the same output model: SensorState.

That is important because the UI does not need to know where the values came from. The UI only reads fields like rpm, vss, map, tps, ect, and bat.

S300 and KPro use different byte offsets and formulas. The parser hides that complexity.

Example:

  • S300 RPM is read from bytes 3 and 4.
  • KPro RPM is read from bytes 2 and 3, then divided by 4.

The result is still exposed to the UI as state.rpm.

10. SensorState Model

File: lib/core/protocol/sensor_state.dart

SensorState is the central live-data model.

It contains:

  • Numeric sensors.
  • Boolean flags.
  • Raw error bytes.
  • Timestamp.

Numeric examples:

  • rpm
  • vss
  • map
  • tps
  • inj
  • ign
  • ect
  • iat
  • bat
  • o2
  • gear
  • eth
  • pa
  • afr
  • strim
  • ltrim
  • ain0 through ain7

Flag examples:

  • MIL
  • Fuel Cut
  • FAN Out
  • VTEC
  • Knock
  • Rev Limit
  • Launch

11. State Management

The app uses Riverpod providers.

Important providers:

  • btProvider: Bluetooth connection status and frame stream.
  • pairedDevicesProvider: paired Bluetooth devices.
  • settingsProvider: ECU type and polling interval.
  • sensorStateProvider: parsed live sensor stream.
  • latestSensorProvider: latest available sensor state for UI.
  • sensorHistoryProvider: graph history.
  • dashboardSlotsProvider: selected dashboard tile sensors.
  • recordingProvider: datalog recording status.
  • sessionListProvider: saved datalog sessions.
  • playbackProvider: saved session playback state.
  • themeProvider: selected theme.

In simple terms, providers are the app's shared memory. Screens watch providers, and when the provider changes, the screen updates.

12. Datalog Recording

The datalog recorder saves raw validated ECU frames, not only final display values.

Recording flow:

  1. User taps the floating record button.
  2. RecordingNotifier.startRecording() starts a new session.
  3. The recorder listens to BtNotifier.frameStream.
  4. Every incoming frame is added to a batch.
  5. Every 500 ms, the batch is written to SQLite.
  6. User taps the record button again to stop.
  7. The app writes the end time and frame count to the session row.
  8. Saved sessions list is refreshed.

Database file:

  • hvbt_datalog.db

Database tables:

  • sessions: one row per recording session.
  • frames: raw frame blobs linked to a session.

This approach is useful because raw frames can later be replayed or re-parsed if parser logic improves.

13. Local Storage

The app uses local phone storage only.

There is no backend API in this project.

Stored locally:

  • Datalog sessions.
  • Raw ECU frames.

Currently in-memory only:

  • Theme selection.
  • ECU protocol selection.
  • Polling interval.
  • Dashboard tile slot choices.
  • Graph sensor choices.

Because these settings are not persisted with shared preferences in the current implementation, they reset when the app restarts.

14. Android Permissions

The Android manifest requests:

  • BLUETOOTH
  • BLUETOOTH_ADMIN
  • BLUETOOTH_CONNECT
  • BLUETOOTH_SCAN
  • ACCESS_FINE_LOCATION
  • ACCESS_COARSE_LOCATION

The app also requests permissions at runtime from the Bluetooth picker screen.

Why location permission appears:

On Android, Bluetooth scanning and device discovery have historically been tied to location permission. Even though the app is not a location app, Android may require this permission for Bluetooth workflows.

15. Project Folder Map

Important folders:

  • lib/main.dart: app entry point.
  • lib/core/bluetooth: Bluetooth connection and polling.
  • lib/core/protocol: ECU parsing, checksum, DTC map, temperature table.
  • lib/core/providers: Riverpod state providers.
  • lib/core/models: sensor definitions and datalog session model.
  • lib/core/datalog: SQLite database, recording, playback.
  • lib/ui/screens: app screens.
  • lib/ui/widgets: shared UI widgets.
  • lib/ui/theme: colors and theme setup.
  • test: parser, checksum, DTC, and utility tests.
  • android: Android build and permission configuration.

16. Testing

The project has Flutter tests for important protocol logic.

Existing tests cover:

  • S300 parser behavior.
  • KPro parser behavior.
  • NEG8 checksum behavior.
  • Temperature table behavior.
  • DTC map decoding.

These tests are valuable because parser bugs can display wrong vehicle data. The parser layer is one of the highest-risk parts of the app.

Run tests with:

flutter test

17. Build And Run Commands

Run the app on a connected device in debug mode:

flutter run

Run the app in release mode:

flutter run --release

Build a release APK:

flutter build apk --release

Build an Android App Bundle:

flutter build appbundle --release

Do not use:

flutter run build --release

That command is wrong because Flutter treats build as a Dart target file.

18. Current Limitations And Honest Notes

These are not complaints. They are useful project facts for future development.

  • Saved playback is not currently wired into sensorStateProvider, so dashboard screens still listen to live Bluetooth frames.
  • Settings are not persisted after restart, even though shared_preferences is included as a dependency.
  • Dashboard tile choices are not persisted after restart.
  • Graph selected sensors and time window are not persisted after restart.
  • The app is Android-focused because it uses flutter_bluetooth_serial and Android Bluetooth permissions.
  • The app lists already paired devices; it does not provide a full in-app Bluetooth pairing flow.
  • Settings screen shows app info as v1.4.0 - Phase 4, while pubspec.yaml version is 1.3.0+4; this should be aligned before release.

19. Plain-English Explanation For Non-Technical People

Think of the ECU as the car's engine computer.

The app works like a translator:

  1. It connects to the ECU through Bluetooth.
  2. It repeatedly asks, "What is happening right now?"
  3. The ECU replies with a block of computer bytes.
  4. The app checks if the reply is valid.
  5. The app translates those bytes into readable values.
  6. The app shows those values as gauges, lists, graphs, and warning codes.

For example, the ECU may send bytes that mean "engine is at 3000 RPM." A normal person cannot read that raw data, so the app converts it into a clean dashboard value.

20. Feature List

Implemented user-facing features:

  • Bluetooth permission request.
  • Paired Bluetooth device listing.
  • Bluetooth connection to ECU adapter.
  • ECU protocol selection.
  • S300 polling command.
  • KPro polling command.
  • 128-byte frame collection.
  • NEG8 checksum validation.
  • S300 parser.
  • KPro parser.
  • Live RPM gauge.
  • Portrait dashboard.
  • Landscape dashboard.
  • Six customizable dashboard sensor slots.
  • Live flag indicators.
  • Full sensor list.
  • Live graph screen.
  • Add/remove graph sensors.
  • Select graph time window.
  • DTC decoding screen.
  • S300 DTC map.
  • KPro DTC map.
  • Local datalog recording.
  • Saved datalog session list.
  • Swipe-to-delete saved sessions.
  • Playback controls for saved sessions.
  • Polling interval settings.
  • Theme settings.
  • Disconnect action.
  • Bluetooth status chip.

21. Suggested Next Improvements

High-value next improvements:

  • Wire datalog playback frames into the same parser/display pipeline used by live Bluetooth.
  • Persist user settings using shared_preferences.
  • Persist dashboard tile selections.
  • Persist graph sensor selections.
  • Add export/share for datalog sessions.
  • Add CSV export for recorded frames or parsed sensor values.
  • Add clearer connection lost handling and auto-reconnect behavior.
  • Align app version in UI and pubspec.yaml.
  • Add user-facing explanation for S300 vs KPro selection.
  • Add tests for datalog database and recorder behavior.

22. One-Line Pitch

HV BT Dashboard turns raw Honda ECU Bluetooth data into a practical live dashboard, diagnostic tool, graphing tool, and local datalog recorder.