-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Add Specialized Turbo integration docs #44119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
JamieMagee
wants to merge
5
commits into
home-assistant:next
Choose a base branch
from
JamieMagee:add-specialized-turbo-docs
base: next
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
09156f8
Add Specialized Turbo integration docs
JamieMagee 3f01192
Fix docs review: raw tags, indentation, breadcrumb
JamieMagee bca5c20
Remove invalid Bluetooth glossary term reference
JamieMagee 38b9f4b
PR review comments
JamieMagee 6687387
Address review comments
JamieMagee File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,213 @@ | ||||||
| --- | ||||||
| title: Specialized Turbo | ||||||
| description: Read telemetry from Specialized Turbo e-bikes over Bluetooth Low Energy in Home Assistant. | ||||||
| ha_category: | ||||||
| - Sensor | ||||||
| ha_release: "2026.4" | ||||||
| ha_iot_class: Local Push | ||||||
| ha_config_flow: true | ||||||
| ha_codeowners: | ||||||
| - '@JamieMagee' | ||||||
| ha_domain: specialized_turbo | ||||||
| ha_integration_type: device | ||||||
| ha_quality_scale: bronze | ||||||
| ha_platforms: | ||||||
| - sensor | ||||||
| ha_bluetooth: true | ||||||
| related: | ||||||
| - docs: /docs/configuration/troubleshooting/#debug-logs-and-diagnostics | ||||||
| title: Debug logs and diagnostics | ||||||
| - docs: /integrations/bluetooth/ | ||||||
| title: Bluetooth | ||||||
| --- | ||||||
|
|
||||||
| 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. | ||||||
|
|
||||||
| 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. | ||||||
|
|
||||||
| ## Supported devices | ||||||
|
|
||||||
| 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: | ||||||
|
|
||||||
| - Turbo Vado (all SL and full-power variants) | ||||||
| - Turbo Levo (all SL and full-power variants) | ||||||
| - Turbo Creo (all SL and full-power variants) | ||||||
| - Turbo Como (SL and full-power) | ||||||
| - Turbo Tero | ||||||
|
|
||||||
| If your bike broadcasts a "TURBOHMI" Bluetooth advertisement when powered on, it should work. | ||||||
|
JamieMagee marked this conversation as resolved.
Outdated
|
||||||
|
|
||||||
| ## Unsupported devices | ||||||
|
|
||||||
| - Older Specialized bikes without a TCU display | ||||||
| - Non-Turbo Specialized bikes (road, mountain, gravel without a motor) | ||||||
| - Third-party e-bikes | ||||||
|
|
||||||
| ## Prerequisites | ||||||
|
|
||||||
| Before setting up this integration, make sure: | ||||||
|
|
||||||
| 1. Your bike is powered on and awake (pedal or press the power button — the TCU screen should be lit). | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| 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. | ||||||
| 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. | ||||||
|
|
||||||
| {% include integrations/config_flow.md %} | ||||||
|
|
||||||
| 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**" %}. | ||||||
|
|
||||||
| {% configuration_basic %} | ||||||
| Pairing PIN: | ||||||
| description: "The PIN displayed on the bike's TCU screen during Bluetooth pairing. Leave empty if your bike does not require a PIN." | ||||||
|
JamieMagee marked this conversation as resolved.
Outdated
|
||||||
| {% endconfiguration_basic %} | ||||||
|
|
||||||
| ## Supported functionality | ||||||
|
|
||||||
| ### Entities | ||||||
|
|
||||||
| The **Specialized Turbo** integration provides the following sensor entities. | ||||||
|
|
||||||
| #### Sensors | ||||||
|
|
||||||
| - **Battery** | ||||||
| - **Description**: Current battery charge level, in percent. | ||||||
|
JamieMagee marked this conversation as resolved.
Outdated
|
||||||
|
|
||||||
| - **Battery capacity** | ||||||
| - **Description**: Total battery capacity in watt-hours. | ||||||
|
|
||||||
| - **Battery remaining** | ||||||
| - **Description**: Remaining battery energy in watt-hours. | ||||||
|
|
||||||
| - **Battery health** | ||||||
| - **Description**: Battery health percentage. Useful for tracking degradation over time. | ||||||
| - **Category**: Diagnostic | ||||||
|
|
||||||
| - **Battery temperature** | ||||||
| - **Description**: Battery temperature in °C. | ||||||
| - **Category**: Diagnostic | ||||||
|
|
||||||
| - **Charge cycles** | ||||||
| - **Description**: Total number of charge cycles the battery has completed. | ||||||
| - **Category**: Diagnostic | ||||||
|
|
||||||
| - **Battery voltage** | ||||||
| - **Description**: Current battery voltage. | ||||||
| - **Category**: Diagnostic | ||||||
|
|
||||||
| - **Battery current** | ||||||
| - **Description**: Current draw from the battery in amps. | ||||||
| - **Category**: Diagnostic | ||||||
|
|
||||||
| - **Speed** | ||||||
| - **Description**: Current speed in km/h. | ||||||
|
|
||||||
| - **Rider power** | ||||||
| - **Description**: Power you're putting through the pedals, in watts. | ||||||
|
|
||||||
| - **Motor power** | ||||||
| - **Description**: Power the electric motor is adding, in watts. | ||||||
|
|
||||||
| - **Cadence** | ||||||
| - **Description**: Pedaling cadence in RPM. | ||||||
|
|
||||||
| - **Odometer** | ||||||
| - **Description**: Total distance the bike has traveled, in kilometers. | ||||||
|
|
||||||
| - **Motor temperature** | ||||||
| - **Description**: Motor temperature in °C. | ||||||
| - **Category**: Diagnostic | ||||||
|
|
||||||
| - **Assist level** | ||||||
| - **Description**: Current assist mode — Off, Eco, Trail, or Turbo. | ||||||
|
|
||||||
| - **ECO assist** | ||||||
| - **Description**: Assist percentage configured for ECO mode. | ||||||
| - **Category**: Diagnostic | ||||||
| - **Remarks**: Disabled by default. | ||||||
|
|
||||||
| - **Trail assist** | ||||||
| - **Description**: Assist percentage configured for Trail mode. | ||||||
| - **Category**: Diagnostic | ||||||
| - **Remarks**: Disabled by default. | ||||||
|
|
||||||
| - **Turbo assist** | ||||||
| - **Description**: Assist percentage configured for Turbo mode. | ||||||
| - **Category**: Diagnostic | ||||||
| - **Remarks**: Disabled by default. | ||||||
|
|
||||||
| ## Examples | ||||||
|
|
||||||
| ### Notify when the battery is fully charged | ||||||
|
|
||||||
| ```yaml | ||||||
| - alias: "Bike battery full" | ||||||
| triggers: | ||||||
| - trigger: numeric_state | ||||||
| entity_id: sensor.specialized_turbo_battery | ||||||
| above: 99 | ||||||
| actions: | ||||||
| - action: notify.mobile_app | ||||||
| data: | ||||||
| message: "Your bike is fully charged!" | ||||||
| ``` | ||||||
|
|
||||||
| ### Warn when battery health drops | ||||||
|
|
||||||
| ```yaml | ||||||
| - alias: "Bike battery health warning" | ||||||
| triggers: | ||||||
| - trigger: numeric_state | ||||||
| entity_id: sensor.specialized_turbo_battery_health | ||||||
| below: 80 | ||||||
| actions: | ||||||
| - action: notify.mobile_app | ||||||
| data: | ||||||
| message: > | ||||||
| Bike battery health is at | ||||||
| {{ states( | ||||||
| 'sensor.specialized_turbo_battery_health' | ||||||
| ) }}%. | ||||||
| Consider scheduling a service. | ||||||
| ``` | ||||||
|
JamieMagee marked this conversation as resolved.
|
||||||
|
|
||||||
| ## Data updates | ||||||
|
|
||||||
| 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. | ||||||
|
|
||||||
| ## Known limitations | ||||||
|
|
||||||
| - **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. | ||||||
| - **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. | ||||||
| - **Read-only**: The integration reads telemetry only. It cannot change assist levels, adjust settings, or send commands to the bike. | ||||||
| - **Sleep mode**: When the bike enters sleep mode, Bluetooth advertisements stop and the connection drops. Data resumes when you wake the bike up. | ||||||
| - **Secondary battery**: Range-extender battery data is parsed internally but not exposed as sensor entities. | ||||||
|
|
||||||
| ## Troubleshooting | ||||||
|
|
||||||
| ### Bike not discovered | ||||||
|
|
||||||
| If your bike doesn't appear during setup: | ||||||
|
|
||||||
| 1. Make sure the bike is powered on and awake — pedal briefly or press the power button so the TCU screen lights up. | ||||||
| 2. Check that your Bluetooth adapter is working under {% my integrations title="**Settings** > **Devices & services**" %} > **Bluetooth**. | ||||||
|
JamieMagee marked this conversation as resolved.
Outdated
|
||||||
| 3. If you're using an ESPHome Bluetooth proxy, confirm that `active: true` is set in the proxy's configuration. | ||||||
| 4. Move the bike closer to the Bluetooth adapter. BLE range is typically 5–10 meters, less through walls. | ||||||
|
|
||||||
| ### Sensors show "Unavailable" | ||||||
|
JamieMagee marked this conversation as resolved.
Outdated
|
||||||
|
|
||||||
| This usually means the bike is out of range or asleep: | ||||||
|
|
||||||
| 1. Wake the bike by pedaling or pressing the power button. | ||||||
| 2. Check whether the Specialized Mission Control app (or another BLE client) has an active connection — only one client can connect at a time. | ||||||
| 3. Try restarting the integration from {% my integrations title="**Settings** > **Devices & services**" %}. | ||||||
|
JamieMagee marked this conversation as resolved.
Outdated
|
||||||
|
|
||||||
| ### Pairing PIN not accepted | ||||||
|
|
||||||
| 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. | ||||||
|
|
||||||
| 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. | ||||||
|
JamieMagee marked this conversation as resolved.
Outdated
|
||||||
|
|
||||||
| ## Removing the integration | ||||||
|
|
||||||
| This integration follows standard integration removal. | ||||||
|
|
||||||
| {% include integrations/remove_device_service.md %} | ||||||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.