Hi all,
I have been working on an ESPHome external component that turns a plain ESP32 into a Bluetooth bridge for the Bosch smart system Live Data Interface that Bosch quietly published in May 2026. It surfaces all 13 live data fields (battery SoC, speed, cadence, rider power, odometer, light, lock state, charger connected, and the rest) as ESPHome sensors and binary_sensors. Repo and bilingual docs:
ha-bosch-ebike/esphome at main · Xunil99/ha-bosch-ebike · GitHub
Why this is interesting
Bosch's LDI spec (v1.0, May 2026) is public, Apache-2.0 licensed, with no registration and no keys: Live Data Interface: eBike-Echtzeitdaten via API nutzen. The catch is that smartphone support is explicitly out of scope, so we need a small stationary BLE accessory. An ESP32 in the garage or shed turned out to be the natural fit. Smart system control unit release v19 or newer is required on the bike side.
Easy install (no ESPHome dashboard needed)
For non-technical users I built a browser-based installer using esp-web-tools plus an automated GitHub Actions build:
Bosch eBike LDI Bridge - Web Installer
Plug an ESP32 via USB, open the page in Chrome or Edge, click Install. WiFi setup happens in the same browser session via Improv-Serial. After that, the device shows up in HA's auto-discovery and adopts into the ESPHome dashboard if available. The whole flashing flow takes about a minute, including WiFi.
DIY-style YAML for those who prefer to compile themselves is also in the repo under esphome/example-bridge.yaml. It pulls the component directly from the repo via external_components: source: github://..., so updates flow in automatically on the next compile.
A few technical highlights that may interest the ESPHome crowd
- Inverse GAP / GATT roles: the eBike is GAP Central + GATT Server, the accessory must be GAP Peripheral + GATT Client. The ESP32 advertises with a
Service Solicitation(AD type 0x15) for the LDI service UUID and then acts as GATT client on the resulting connection. This is unusual and not directly representable in NimBLE'sble_hs_adv_fields, so the AD payload is built by hand and passed toble_gap_adv_set_data(). - Mandatory bonding with LE Secure Connections, Just Works, stored persistently in NVS. NimBLE's
ble_store_config_init()handles persistence cleanly across reboots and OTA. - Bosch firmware quirks: the spec acknowledges three known issues in v19. Two of them (DLE and MTU not being initiated by the eBike) are worked around by the bridge actively triggering both itself right after encryption setup.
- Protobuf payload: the live data characteristic is a
com.bosch.ebike.LiveDataproto3 message. Hand-rolled decoder, around 120 lines, no nanopb build setup required. Forward-compatible by design, since unknown tags are skipped per proto3 rules. - Bond-resume race fix: NimBLE sometimes delivers
BLE_GAP_EVENT_ENC_CHANGEto user space beforeBLE_GAP_EVENT_CONNECTon bonded reconnects. The handler readsconn_handlestraight from the event struct rather than from cached state to avoid anENOTCONNfromble_gattc_exchange_mtu.
Pairs with the cloud integration
This bridge complements an existing HACS integration in the same repo that pulls tour history from the Bosch Data Act cloud API. From v1.10.0, the cloud integration can optionally use the live BLE values as the source of truth for tour distance and battery consumption, replacing the snapshot-based cloud estimates.
Status
Tested with a Performance Line CX on smart system v19.54.0. Should work with any v19+ drive unit since the LDI is unit-agnostic, but confirmation from other variants (SX, Cargo, Performance Line) would be very welcome. ESP32-S3, C3 and C6 also untested so far, plain ESP32 dev boards work.
Issues, ideas, drive unit confirmations and PRs all appreciated.
Cheers,
Xunil99
