|
| 1 | +--- |
| 2 | +title: Specialized Turbo |
| 3 | +description: Read telemetry from Specialized Turbo e-bikes over Bluetooth Low Energy in Home Assistant. |
| 4 | +ha_category: |
| 5 | + - Sensor |
| 6 | +ha_release: "2026.4" |
| 7 | +ha_iot_class: Local Push |
| 8 | +ha_config_flow: true |
| 9 | +ha_codeowners: |
| 10 | + - '@JamieMagee' |
| 11 | +ha_domain: specialized_turbo |
| 12 | +ha_integration_type: device |
| 13 | +ha_quality_scale: bronze |
| 14 | +ha_platforms: |
| 15 | + - sensor |
| 16 | +ha_bluetooth: true |
| 17 | +related: |
| 18 | + - docs: /docs/configuration/troubleshooting/#debug-logs-and-diagnostics |
| 19 | + title: Debug logs and diagnostics |
| 20 | + - docs: /integrations/bluetooth/ |
| 21 | + title: Bluetooth |
| 22 | +--- |
| 23 | + |
| 24 | +The **Specialized Turbo** {% term integration %} connects Home Assistant to [Specialized](https://www.specialized.com/) Turbo e-bikes over {% term Bluetooth %} Low Energy. It reads real-time telemetry straight from the bike — battery level, speed, power output, cadence, motor temperature, odometer, and more — giving you the same data the Specialized Mission Control app sees. |
| 25 | + |
| 26 | +If you ride a Specialized Turbo Vado, Levo, Creo, Como, or Tero, you can track battery health over time, log rides through Home Assistant's history, or build automations that fire when your bike finishes charging. |
| 27 | + |
| 28 | +## Supported devices |
| 29 | + |
| 30 | +This integration works with Specialized Turbo e-bikes that have the Gen 2 BLE module (the "TURBOHMI2017" protocol), which includes most 2017 and newer models with a <abbr title="Turbo Connect Unit">TCU</abbr> display: |
| 31 | + |
| 32 | +- Turbo Vado (all SL and full-power variants) |
| 33 | +- Turbo Levo (all SL and full-power variants) |
| 34 | +- Turbo Creo (all SL and full-power variants) |
| 35 | +- Turbo Como (SL and full-power) |
| 36 | +- Turbo Tero |
| 37 | + |
| 38 | +If your bike broadcasts a "TURBOHMI" Bluetooth advertisement when powered on, it should work. |
| 39 | + |
| 40 | +## Unsupported devices |
| 41 | + |
| 42 | +- Older Specialized bikes without a TCU display |
| 43 | +- Non-Turbo Specialized bikes (road, mountain, gravel without a motor) |
| 44 | +- Third-party e-bikes |
| 45 | + |
| 46 | +## Prerequisites |
| 47 | + |
| 48 | +Before setting up this integration, make sure: |
| 49 | + |
| 50 | +1. Your bike is powered on and awake (pedal or press the power button — the TCU screen should be lit). |
| 51 | +2. Home Assistant has access to a [Bluetooth adapter](/integrations/bluetooth/). If the bike is out of range, you can use an [ESPHome Bluetooth proxy](https://esphome.io/projects/?type=bluetooth) placed in your garage or shed. |
| 52 | +3. No other app (like Specialized Mission Control) is actively connected to the bike over Bluetooth. Only one BLE client can connect at a time. |
| 53 | + |
| 54 | +{% include integrations/config_flow.md %} |
| 55 | + |
| 56 | +The bike is usually discovered automatically. If it doesn't appear, make sure it's powered on and within Bluetooth range, then try adding it manually through {% my integrations title="**Settings** > **Devices & services**" %}. |
| 57 | + |
| 58 | +{% configuration_basic %} |
| 59 | +Pairing PIN: |
| 60 | + description: "The PIN displayed on the bike's TCU screen during Bluetooth pairing. Leave empty if your bike does not require a PIN." |
| 61 | +{% endconfiguration_basic %} |
| 62 | + |
| 63 | +## Supported functionality |
| 64 | + |
| 65 | +### Entities |
| 66 | + |
| 67 | +The **Specialized Turbo** integration provides the following sensor entities. |
| 68 | + |
| 69 | +#### Sensors |
| 70 | + |
| 71 | +- **Battery** |
| 72 | + - **Description**: Current battery charge level, in percent. |
| 73 | + |
| 74 | +- **Battery capacity** |
| 75 | + - **Description**: Total battery capacity in watt-hours. |
| 76 | + |
| 77 | +- **Battery remaining** |
| 78 | + - **Description**: Remaining battery energy in watt-hours. |
| 79 | + |
| 80 | +- **Battery health** |
| 81 | + - **Description**: Battery health percentage. Useful for tracking degradation over time. |
| 82 | + - **Category**: Diagnostic |
| 83 | + |
| 84 | +- **Battery temperature** |
| 85 | + - **Description**: Battery temperature in °C. |
| 86 | + - **Category**: Diagnostic |
| 87 | + |
| 88 | +- **Charge cycles** |
| 89 | + - **Description**: Total number of charge cycles the battery has completed. |
| 90 | + - **Category**: Diagnostic |
| 91 | + |
| 92 | +- **Battery voltage** |
| 93 | + - **Description**: Current battery voltage. |
| 94 | + - **Category**: Diagnostic |
| 95 | + |
| 96 | +- **Battery current** |
| 97 | + - **Description**: Current draw from the battery in amps. |
| 98 | + - **Category**: Diagnostic |
| 99 | + |
| 100 | +- **Speed** |
| 101 | + - **Description**: Current speed in km/h. |
| 102 | + |
| 103 | +- **Rider power** |
| 104 | + - **Description**: Power you're putting through the pedals, in watts. |
| 105 | + |
| 106 | +- **Motor power** |
| 107 | + - **Description**: Power the electric motor is adding, in watts. |
| 108 | + |
| 109 | +- **Cadence** |
| 110 | + - **Description**: Pedaling cadence in RPM. |
| 111 | + |
| 112 | +- **Odometer** |
| 113 | + - **Description**: Total distance the bike has traveled, in kilometers. |
| 114 | + |
| 115 | +- **Motor temperature** |
| 116 | + - **Description**: Motor temperature in °C. |
| 117 | + - **Category**: Diagnostic |
| 118 | + |
| 119 | +- **Assist level** |
| 120 | + - **Description**: Current assist mode — Off, Eco, Trail, or Turbo. |
| 121 | + |
| 122 | +- **ECO assist** |
| 123 | + - **Description**: Assist percentage configured for ECO mode. |
| 124 | + - **Category**: Diagnostic |
| 125 | + - **Remarks**: Disabled by default. |
| 126 | + |
| 127 | +- **Trail assist** |
| 128 | + - **Description**: Assist percentage configured for Trail mode. |
| 129 | + - **Category**: Diagnostic |
| 130 | + - **Remarks**: Disabled by default. |
| 131 | + |
| 132 | +- **Turbo assist** |
| 133 | + - **Description**: Assist percentage configured for Turbo mode. |
| 134 | + - **Category**: Diagnostic |
| 135 | + - **Remarks**: Disabled by default. |
| 136 | + |
| 137 | +## Examples |
| 138 | + |
| 139 | +### Notify when the battery is fully charged |
| 140 | + |
| 141 | +```yaml |
| 142 | +- alias: "Bike battery full" |
| 143 | + triggers: |
| 144 | + - trigger: numeric_state |
| 145 | + entity_id: sensor.specialized_turbo_battery |
| 146 | + above: 99 |
| 147 | + actions: |
| 148 | + - action: notify.mobile_app |
| 149 | + data: |
| 150 | + message: "Your bike is fully charged!" |
| 151 | +``` |
| 152 | +
|
| 153 | +### Warn when battery health drops |
| 154 | +
|
| 155 | +```yaml |
| 156 | +- alias: "Bike battery health warning" |
| 157 | + triggers: |
| 158 | + - trigger: numeric_state |
| 159 | + entity_id: sensor.specialized_turbo_battery_health |
| 160 | + below: 80 |
| 161 | + actions: |
| 162 | + - action: notify.mobile_app |
| 163 | + data: |
| 164 | + message: > |
| 165 | + Bike battery health is at |
| 166 | + {{ states( |
| 167 | + 'sensor.specialized_turbo_battery_health' |
| 168 | + ) }}%. |
| 169 | + Consider scheduling a service. |
| 170 | +``` |
| 171 | +
|
| 172 | +## Data updates |
| 173 | +
|
| 174 | +The integration uses a push-based approach. It connects to the bike over Bluetooth, subscribes to GATT notifications on the telemetry characteristic, and receives updates whenever the bike broadcasts new data. No polling is performed. If the Bluetooth connection drops, the integration reconnects automatically the next time it sees the bike's advertisement. |
| 175 | +
|
| 176 | +## Known limitations |
| 177 | +
|
| 178 | +- **Bluetooth range**: The bike needs to be within about 5–10 meters of a Bluetooth adapter. For a garage or shed, an [ESPHome Bluetooth proxy](https://esphome.io/projects/?type=bluetooth) works well. |
| 179 | +- **One connection at a time**: Only one BLE client can connect to the bike simultaneously. If the Specialized Mission Control app is connected, Home Assistant can't connect, and vice versa. |
| 180 | +- **Read-only**: The integration reads telemetry only. It cannot change assist levels, adjust settings, or send commands to the bike. |
| 181 | +- **Sleep mode**: When the bike enters sleep mode, Bluetooth advertisements stop and the connection drops. Data resumes when you wake the bike up. |
| 182 | +- **Secondary battery**: Range-extender battery data is parsed internally but not exposed as sensor entities. |
| 183 | +
|
| 184 | +## Troubleshooting |
| 185 | +
|
| 186 | +### Bike not discovered |
| 187 | +
|
| 188 | +If your bike doesn't appear during setup: |
| 189 | +
|
| 190 | +1. Make sure the bike is powered on and awake — pedal briefly or press the power button so the TCU screen lights up. |
| 191 | +2. Check that your Bluetooth adapter is working under {% my integrations title="**Settings** > **Devices & services**" %} > **Bluetooth**. |
| 192 | +3. If you're using an ESPHome Bluetooth proxy, confirm that `active: true` is set in the proxy's configuration. |
| 193 | +4. Move the bike closer to the Bluetooth adapter. BLE range is typically 5–10 meters, less through walls. |
| 194 | + |
| 195 | +### Sensors show "Unavailable" |
| 196 | + |
| 197 | +This usually means the bike is out of range or asleep: |
| 198 | + |
| 199 | +1. Wake the bike by pedaling or pressing the power button. |
| 200 | +2. Check whether the Specialized Mission Control app (or another BLE client) has an active connection — only one client can connect at a time. |
| 201 | +3. Try restarting the integration from {% my integrations title="**Settings** > **Devices & services**" %}. |
| 202 | + |
| 203 | +### Pairing PIN not accepted |
| 204 | + |
| 205 | +The PIN is displayed on the bike's TCU screen when it enters pairing mode. If you don't see a PIN prompt on the bike, it may already be paired with another device. Reset the BLE pairing on the bike and try again. |
| 206 | + |
| 207 | +Some Bluetooth backends don't support programmatic PIN entry. If that happens, pair the bike through your operating system's Bluetooth settings first, then set up the integration without entering a PIN. |
| 208 | + |
| 209 | +## Removing the integration |
| 210 | + |
| 211 | +This integration follows standard integration removal. |
| 212 | + |
| 213 | +{% include integrations/remove_device_service.md %} |
0 commit comments