# zexry619/votol-esp32-can-bus architecture

> Architecture diagram of the GitHub repository zexry619/votol-esp32-can-bus, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-29). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/zexry619/votol-esp32-can-bus
- Repository: https://github.com/zexry619/votol-esp32-can-bus

## Overview

Votol BLE+WiFi Dashboard monitors a Votol controller and BMS over CAN, presenting live vehicle and battery data in a browser. The main workflow is ESP32 CAN acquisition and compact data output, reception over BLE, WiFi, or USB Serial, normalization by the Go application, and WebSocket delivery to its dashboard. The product also includes CAN-sniffer views, charging/injector features, transport switching, and ESP32 firmware updates over WiFi HTTP or BLE. The architecture follows the README and sampled Go, WiFi, and OTA code; unsampled firmware details are represented only where documented.

Main entry points: [`go_web/main.go`](https://github.com/zexry619/votol-esp32-can-bus/blob/beta/go_web/main.go) (Web + APIs), [`esp32/votol_ble_dualcore/votol_ble_dualcore.ino`](https://github.com/zexry619/votol-esp32-can-bus/blob/beta/esp32/votol_ble_dualcore/votol_ble_dualcore.ino) (CAN Monitoring), [`go_web/dashboard.html`](https://github.com/zexry619/votol-esp32-can-bus/blob/beta/go_web/dashboard.html) (Web Dashboard), [`esp32/votol_ble_dualcore/ota_http.cpp`](https://github.com/zexry619/votol-esp32-can-bus/blob/beta/esp32/votol_ble_dualcore/ota_http.cpp) (HTTP OTA Endpoints)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_firmware["ESP32 Firmware"]
  node_firmware_core["CAN Monitoring"]
  node_injector["Charger Injector"]
  node_wifi_firmware["WiFi AP + WS<br/>[wifi_handler.cpp]"]
end

subgraph group_ingest["Data Ingress"]
  node_ble_ingress["BLE Receiver<br/>[ble.go]"]
  node_serial_ingress["USB Serial<br/>[serial.go]"]
  node_wifi_ingress["WiFi Receiver<br/>[wifi.go]"]
  node_udp_sniffer["UDP Sniffer<br/>[udp.go]"]
end

subgraph group_dashboard["Go Dashboard"]
  node_normalizer["Data Normalizer<br/>[main.go]"]
  node_dashboard_server["Web + APIs<br/>[main.go]"]
  node_browser["Web Dashboard<br/>[dashboard.html]"]
end

subgraph group_updates["Firmware Updates"]
  node_ble_ota["BLE OTA Service<br/>[votol_ota.cpp]"]
  node_http_ota["HTTP OTA Endpoints<br/>[ota_http.cpp]"]
  node_ota_proxy["OTA Proxy<br/>[main.go]"]
  node_flash[("ESP32 Firmware Store")]
end

node_user(("Dashboard User"))
node_vehicle{{"Votol + BMS"}}

node_vehicle -->|"sends CAN data"| node_firmware_core
node_firmware_core -->|"charger detection"| node_injector
node_firmware_core -->|"streams BLE data"| node_ble_ingress
node_firmware_core -->|"streams serial data"| node_serial_ingress
node_firmware_core -->|"provides telemetry"| node_wifi_firmware
node_wifi_firmware -->|"streams WebSocket data"| node_wifi_ingress
node_firmware_core -.->|"sends sniffer data"| node_udp_sniffer
node_user -->|"views dashboard"| node_browser
node_browser -->|"opens dashboard"| node_dashboard_server
node_ble_ingress -->|"passes JSON"| node_normalizer
node_serial_ingress -->|"passes JSON"| node_normalizer
node_wifi_ingress -->|"passes JSON"| node_normalizer
node_udp_sniffer -->|"broadcasts CAN logs"| node_dashboard_server
node_dashboard_server -->|"serves processing"| node_normalizer
node_normalizer -->|"updates live state"| node_dashboard_server
node_dashboard_server -->|"broadcasts dashboard data"| node_browser
node_browser -->|"requests BLE control"| node_dashboard_server
node_dashboard_server -->|"pauses or resumes"| node_ble_ingress
node_browser -->|"uploads firmware"| node_ota_proxy
node_ota_proxy -->|"proxies HTTP update"| node_http_ota
node_http_ota -->|"writes firmware"| node_flash
node_http_ota -->|"returns update status"| node_ota_proxy
node_user -.->|"initiates BLE update"| node_ble_ota
node_ble_ota -.->|"writes firmware"| node_flash
node_browser -->|"sends WiFi commands"| node_wifi_firmware

click node_firmware_core "https://github.com/zexry619/votol-esp32-can-bus/blob/beta/esp32/votol_ble_dualcore/votol_ble_dualcore.ino"
click node_injector "https://github.com/zexry619/votol-esp32-can-bus/blob/beta/esp32/votol_ble_dualcore/votol_ble_dualcore.ino"
click node_wifi_firmware "https://github.com/zexry619/votol-esp32-can-bus/blob/beta/esp32/votol_ble_dualcore/wifi_handler.cpp"
click node_ble_ingress "https://github.com/zexry619/votol-esp32-can-bus/blob/beta/go_web/ble.go"
click node_serial_ingress "https://github.com/zexry619/votol-esp32-can-bus/blob/beta/go_web/serial.go"
click node_wifi_ingress "https://github.com/zexry619/votol-esp32-can-bus/blob/beta/go_web/wifi.go"
click node_udp_sniffer "https://github.com/zexry619/votol-esp32-can-bus/blob/beta/go_web/udp.go"
click node_normalizer "https://github.com/zexry619/votol-esp32-can-bus/blob/beta/go_web/main.go"
click node_dashboard_server "https://github.com/zexry619/votol-esp32-can-bus/blob/beta/go_web/main.go"
click node_browser "https://github.com/zexry619/votol-esp32-can-bus/blob/beta/go_web/dashboard.html"
click node_ble_ota "https://github.com/zexry619/votol-esp32-can-bus/blob/beta/esp32/votol_ble_dualcore/votol_ota.cpp"
click node_http_ota "https://github.com/zexry619/votol-esp32-can-bus/blob/beta/esp32/votol_ble_dualcore/ota_http.cpp"
click node_ota_proxy "https://github.com/zexry619/votol-esp32-can-bus/blob/beta/go_web/main.go"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_firmware_core,node_injector,node_wifi_firmware,node_user toneBlue
class node_ble_ingress,node_serial_ingress,node_wifi_ingress,node_udp_sniffer toneAmber
class node_normalizer,node_dashboard_server,node_browser toneMint
class node_ble_ota,node_http_ota,node_ota_proxy,node_flash toneRose
class node_vehicle toneIndigo
```

## Components

### ESP32 Firmware

- [CAN Monitoring](https://github.com/zexry619/votol-esp32-can-bus/blob/beta/esp32/votol_ble_dualcore/votol_ble_dualcore.ino): `esp32/votol_ble_dualcore/votol_ble_dualcore.ino`
- [Charger Injector](https://github.com/zexry619/votol-esp32-can-bus/blob/beta/esp32/votol_ble_dualcore/votol_ble_dualcore.ino): `esp32/votol_ble_dualcore/votol_ble_dualcore.ino`
- [WiFi AP + WS](https://github.com/zexry619/votol-esp32-can-bus/blob/beta/esp32/votol_ble_dualcore/wifi_handler.cpp): `esp32/votol_ble_dualcore/wifi_handler.cpp`

### Data Ingress

- [BLE Receiver](https://github.com/zexry619/votol-esp32-can-bus/blob/beta/go_web/ble.go): `go_web/ble.go`
- [USB Serial](https://github.com/zexry619/votol-esp32-can-bus/blob/beta/go_web/serial.go): `go_web/serial.go`
- [WiFi Receiver](https://github.com/zexry619/votol-esp32-can-bus/blob/beta/go_web/wifi.go): `go_web/wifi.go`
- [UDP Sniffer](https://github.com/zexry619/votol-esp32-can-bus/blob/beta/go_web/udp.go): `go_web/udp.go`

### Go Dashboard

- [Data Normalizer](https://github.com/zexry619/votol-esp32-can-bus/blob/beta/go_web/main.go): `go_web/main.go`
- [Web + APIs](https://github.com/zexry619/votol-esp32-can-bus/blob/beta/go_web/main.go): `go_web/main.go`
- [Web Dashboard](https://github.com/zexry619/votol-esp32-can-bus/blob/beta/go_web/dashboard.html): `go_web/dashboard.html`

### Firmware Updates

- [BLE OTA Service](https://github.com/zexry619/votol-esp32-can-bus/blob/beta/esp32/votol_ble_dualcore/votol_ota.cpp): `esp32/votol_ble_dualcore/votol_ota.cpp`
- [HTTP OTA Endpoints](https://github.com/zexry619/votol-esp32-can-bus/blob/beta/esp32/votol_ble_dualcore/ota_http.cpp): `esp32/votol_ble_dualcore/ota_http.cpp`
- [OTA Proxy](https://github.com/zexry619/votol-esp32-can-bus/blob/beta/go_web/main.go): `go_web/main.go`
- **ESP32 Firmware Store**

### Other components

- **Dashboard User**
- **Votol + BMS**

## Connections

- Votol + BMS → CAN Monitoring: sends CAN data
- CAN Monitoring → Charger Injector: charger detection
- CAN Monitoring → BLE Receiver: streams BLE data
- CAN Monitoring → USB Serial: streams serial data
- CAN Monitoring → WiFi AP + WS: provides telemetry
- WiFi AP + WS → WiFi Receiver: streams WebSocket data
- CAN Monitoring → UDP Sniffer: sends sniffer data
- Dashboard User → Web Dashboard: views dashboard
- Web Dashboard → Web + APIs: opens dashboard
- BLE Receiver → Data Normalizer: passes JSON
- USB Serial → Data Normalizer: passes JSON
- WiFi Receiver → Data Normalizer: passes JSON
- UDP Sniffer → Web + APIs: broadcasts CAN logs
- Web + APIs → Data Normalizer: serves processing
- Data Normalizer → Web + APIs: updates live state
- Web + APIs → Web Dashboard: broadcasts dashboard data
- Web Dashboard → Web + APIs: requests BLE control
- Web + APIs → BLE Receiver: pauses or resumes
- Web Dashboard → OTA Proxy: uploads firmware
- OTA Proxy → HTTP OTA Endpoints: proxies HTTP update
- HTTP OTA Endpoints → ESP32 Firmware Store: writes firmware
- HTTP OTA Endpoints → OTA Proxy: returns update status
- Dashboard User → BLE OTA Service: initiates BLE update
- BLE OTA Service → ESP32 Firmware Store: writes firmware
- Web Dashboard → WiFi AP + WS: sends WiFi commands
