Add Specialized Turbo e-bike BLE integration#165565
Add Specialized Turbo e-bike BLE integration#165565JamieMagee wants to merge 11 commits intohome-assistant:devfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new specialized_turbo Bluetooth (local_push) device integration to Home Assistant, including config flow, BLE coordinator, sensor entities, diagnostics, and a full test suite.
Changes:
- Introduces the
specialized_turbointegration (manifest, config flow, BLE coordinator, sensors, diagnostics, translations/icons, quality scale). - Adds comprehensive tests for config flow, coordinator behavior, sensors, setup/unload, and diagnostics.
- Registers the integration in generated registries and adds the external dependency (
specialized-turbo==0.1.1).
Reviewed changes
Copilot reviewed 20 out of 23 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
homeassistant/components/specialized_turbo/__init__.py |
Integration setup/unload wiring and coordinator creation. |
homeassistant/components/specialized_turbo/config_flow.py |
Bluetooth discovery + user + reconfigure flows and connection validation. |
homeassistant/components/specialized_turbo/coordinator.py |
Active BLE connection management, notification parsing, listener updates. |
homeassistant/components/specialized_turbo/sensor.py |
Sensor entity descriptions and coordinator-backed entities. |
homeassistant/components/specialized_turbo/diagnostics.py |
Redacted config entry diagnostics + snapshot export. |
homeassistant/components/specialized_turbo/const.py |
Domain and PIN constants. |
homeassistant/components/specialized_turbo/manifest.json |
Declares integration metadata, Bluetooth matcher, requirements, etc. |
homeassistant/components/specialized_turbo/strings.json |
Config flow + sensor entity translations. |
homeassistant/components/specialized_turbo/icons.json |
Entity icon translations. |
homeassistant/components/specialized_turbo/quality_scale.yaml |
IQS rule status declarations for the integration. |
homeassistant/generated/integrations.json |
Registers integration metadata. |
homeassistant/generated/config_flows.py |
Registers config flow availability. |
homeassistant/generated/bluetooth.py |
Registers Bluetooth matcher for discovery. |
tests/components/specialized_turbo/conftest.py |
Shared fixtures and BLE connection patch helpers. |
tests/components/specialized_turbo/test_config_flow.py |
Config flow coverage (bluetooth/user/reconfigure paths). |
tests/components/specialized_turbo/test_coordinator.py |
Coordinator unit tests for connection + notifications + shutdown. |
tests/components/specialized_turbo/test_sensor.py |
Sensor description/value function tests. |
tests/components/specialized_turbo/test_init.py |
Entry setup/unload tests. |
tests/components/specialized_turbo/test_diagnostics.py |
Diagnostics structure + redaction tests. |
tests/components/specialized_turbo/__init__.py |
Test package marker. |
requirements_all.txt |
Adds specialized-turbo==0.1.1 to runtime requirements. |
requirements_test_all.txt |
Adds specialized-turbo==0.1.1 to test requirements. |
CODEOWNERS |
Adds code ownership for the new integration + tests. |
Comments suppressed due to low confidence (1)
homeassistant/components/specialized_turbo/config_flow.py:123
current_addresses = self._async_current_ids()returns configured unique_ids (you set them usingformat_mac(...)), but the loop comparesinfo.address(unformatted) against these IDs. This means already-configured devices won't be filtered out of the discovery list. Compare using the same normalization (e.g.,format_mac(info.address)) or track configured addresses separately.
current_addresses = self._async_current_ids()
for info in async_discovered_service_info(self.hass):
if info.address in current_addresses:
continue
There was a problem hiding this comment.
Pull request overview
Adds a new specialized_turbo Home Assistant integration for Specialized Turbo e-bikes using BLE discovery + a connectable coordinator for GATT notifications, along with accompanying tests and generated registry updates.
Changes:
- Introduces the
specialized_turbointegration (config flow, coordinator, sensors, diagnostics, translations/icons, manifest/quality scale). - Adds a full test suite for config flow, coordinator behavior, diagnostics, and sensor descriptions.
- Updates requirements, generated integration registries, Bluetooth matchers, and CODEOWNERS.
Reviewed changes
Copilot reviewed 20 out of 23 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
homeassistant/components/specialized_turbo/__init__.py |
Integration setup/unload and coordinator lifecycle wiring |
homeassistant/components/specialized_turbo/config_flow.py |
BLE discovery + user/reconfigure flows and connection test |
homeassistant/components/specialized_turbo/coordinator.py |
BLE connection handling + notification parsing + listener updates |
homeassistant/components/specialized_turbo/sensor.py |
Sensor entity descriptions + entity implementation over coordinator snapshot |
homeassistant/components/specialized_turbo/diagnostics.py |
Diagnostics output with redaction of sensitive config values |
homeassistant/components/specialized_turbo/const.py |
Domain + PIN constant |
homeassistant/components/specialized_turbo/manifest.json |
Integration metadata, requirements, bluetooth matcher, dependencies |
homeassistant/components/specialized_turbo/strings.json |
Config flow + entity translations |
homeassistant/components/specialized_turbo/icons.json |
Entity icon translations |
homeassistant/components/specialized_turbo/quality_scale.yaml |
Quality scale checklist/status tracking |
tests/components/specialized_turbo/conftest.py |
BLE discovery fixtures + connection patch helpers |
tests/components/specialized_turbo/test_config_flow.py |
Config flow coverage (bluetooth/user/reconfigure/error paths) |
tests/components/specialized_turbo/test_coordinator.py |
Coordinator connection/notification/parsing/shutdown tests |
tests/components/specialized_turbo/test_diagnostics.py |
Diagnostics shape + redaction tests |
tests/components/specialized_turbo/test_init.py |
Entry setup/unload tests |
tests/components/specialized_turbo/test_sensor.py |
Sensor description/value function tests |
tests/components/specialized_turbo/__init__.py |
Test package init |
homeassistant/generated/bluetooth.py |
Generated Bluetooth matcher entry for specialized_turbo |
homeassistant/generated/config_flows.py |
Generated inclusion in config flows list |
homeassistant/generated/integrations.json |
Generated integration registry entry |
requirements_all.txt |
Adds specialized-turbo dependency pin |
requirements_test_all.txt |
Adds specialized-turbo dependency pin for tests |
CODEOWNERS |
Adds ownership for integration + tests |
There was a problem hiding this comment.
Pull request overview
Adds a new specialized_turbo Bluetooth (local_push) integration to Home Assistant, including config flow, BLE coordinator, sensor entities, diagnostics support, and a full test suite.
Changes:
- Introduce the Specialized Turbo integration (manifest, config flow, coordinator, sensors, diagnostics, translations/icons).
- Add comprehensive integration tests for config flow, coordinator behavior, sensors, and diagnostics.
- Register the integration in generated metadata and add the upstream
specialized-turbo==0.1.1dependency.
Reviewed changes
Copilot reviewed 20 out of 23 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
homeassistant/components/specialized_turbo/__init__.py |
Sets up/unloads the config entry and forwards platform setup. |
homeassistant/components/specialized_turbo/config_flow.py |
Implements Bluetooth discovery + user flow + reconfigure flow. |
homeassistant/components/specialized_turbo/const.py |
Defines integration constants (domain, PIN key). |
homeassistant/components/specialized_turbo/coordinator.py |
Active BLE coordinator: connect, pair, subscribe to notifications, parse telemetry. |
homeassistant/components/specialized_turbo/sensor.py |
Defines sensor entities and their value extraction from telemetry snapshots. |
homeassistant/components/specialized_turbo/diagnostics.py |
Adds config entry diagnostics with redaction. |
homeassistant/components/specialized_turbo/manifest.json |
Declares integration metadata, Bluetooth matcher, and requirements. |
homeassistant/components/specialized_turbo/strings.json |
Provides config flow + entity translations. |
homeassistant/components/specialized_turbo/icons.json |
Provides entity icon mappings. |
homeassistant/components/specialized_turbo/quality_scale.yaml |
Documents quality scale rule status/exemptions. |
homeassistant/generated/integrations.json |
Registers integration metadata for HA frontend/tools. |
homeassistant/generated/config_flows.py |
Registers integration as having a config flow. |
homeassistant/generated/bluetooth.py |
Registers Bluetooth matcher (manufacturer ID + prefix). |
requirements_all.txt |
Adds specialized-turbo==0.1.1 to core requirements. |
requirements_test_all.txt |
Adds specialized-turbo==0.1.1 to test requirements. |
tests/components/specialized_turbo/__init__.py |
Test package marker for the integration. |
tests/components/specialized_turbo/conftest.py |
Shared fixtures and BLE connection helper patchers. |
tests/components/specialized_turbo/test_config_flow.py |
Tests discovery/user/reconfigure flows and connection error handling. |
tests/components/specialized_turbo/test_init.py |
Tests setup/unload behavior for the config entry. |
tests/components/specialized_turbo/test_coordinator.py |
Tests coordinator polling, notification parsing, reconnect, and cleanup paths. |
tests/components/specialized_turbo/test_sensor.py |
Tests sensor description value functions and metadata expectations. |
tests/components/specialized_turbo/test_diagnostics.py |
Tests diagnostics structure and redaction. |
CODEOWNERS |
Adds code ownership for the new integration and its tests. |
|
Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍 |
1f23b99 to
1e18ea9
Compare
There was a problem hiding this comment.
Pull request overview
Adds a new Home Assistant BLE integration (specialized_turbo) for Specialized Turbo e-bikes, using an active BLE coordinator to maintain a GATT connection and expose telemetry via sensor entities.
Changes:
- Introduces the
specialized_turbointegration (config flow, coordinator, sensor platform, translations/icons, manifest/quality scale). - Adds a full test suite for config flow, coordinator behavior, integration setup/unload, and sensor description/value functions.
- Registers the integration in generated discovery/config-flow lists and adds the external dependency (
specialized-turbo==0.1.1) to requirements.
Reviewed changes
Copilot reviewed 18 out of 21 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| homeassistant/components/specialized_turbo/init.py | Sets up/unloads the integration, creates and stores the coordinator, forwards platforms. |
| homeassistant/components/specialized_turbo/config_flow.py | Implements Bluetooth discovery/user/reconfigure flows and connection test logic. |
| homeassistant/components/specialized_turbo/const.py | Defines integration constants (domain, PIN key). |
| homeassistant/components/specialized_turbo/coordinator.py | Maintains BLE connection, subscribes to notifications, parses telemetry, and notifies entities. |
| homeassistant/components/specialized_turbo/sensor.py | Defines 18 sensor entity descriptions and the sensor entity implementation. |
| homeassistant/components/specialized_turbo/strings.json | Adds UI strings for config flow and entity translations. |
| homeassistant/components/specialized_turbo/icons.json | Provides default icons for selected sensors. |
| homeassistant/components/specialized_turbo/manifest.json | Declares integration metadata, BLE matcher, and dependency requirement. |
| homeassistant/components/specialized_turbo/quality_scale.yaml | Adds quality scale status declarations for the integration. |
| tests/components/specialized_turbo/init.py | Test package marker for the integration. |
| tests/components/specialized_turbo/conftest.py | Provides BLE discovery/service-info fixtures and connection patch helpers. |
| tests/components/specialized_turbo/test_config_flow.py | Covers discovery/user/reconfigure flows and error cases. |
| tests/components/specialized_turbo/test_coordinator.py | Covers connection logic, notification parsing path, disconnect/shutdown behavior, and error handling. |
| tests/components/specialized_turbo/test_init.py | Covers config entry setup/unload behavior. |
| tests/components/specialized_turbo/test_sensor.py | Covers sensor description metadata and snapshot-to-value mapping helpers. |
| requirements_all.txt | Adds specialized-turbo==0.1.1 to runtime requirements. |
| requirements_test_all.txt | Adds specialized-turbo==0.1.1 to test requirements. |
| homeassistant/generated/bluetooth.py | Registers the integration’s Bluetooth matcher in generated discovery data. |
| homeassistant/generated/config_flows.py | Registers the integration as having a config flow. |
| homeassistant/generated/integrations.json | Registers integration metadata (name/type/config_flow/iot_class). |
| CODEOWNERS | Assigns code ownership for integration and tests. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 18 out of 21 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (2)
homeassistant/components/specialized_turbo/config_flow.py:139
- Same as the bluetooth confirm step:
vol.Coerce(int)forpinwill strip leading zeros. If the PIN is displayed as a fixed-width code on the bike, it’s safer to keep it as a string and validate it as 4 digits, rather than coercing to int.
data_schema=vol.Schema(
{
vol.Required(CONF_ADDRESS): vol.In(address_options),
vol.Optional(CONF_PIN): vol.Coerce(int),
}
),
homeassistant/components/specialized_turbo/config_flow.py:159
- The reconfigure step also coerces
pintoint, which can drop leading zeros and change the stored PIN. Consider using a string schema (digit/length validation) here as well so reconfiguration preserves the exact code the user enters.
return self.async_show_form(
step_id="reconfigure",
data_schema=vol.Schema(
{
vol.Optional(CONF_PIN): vol.Coerce(int),
}
),
b6b354f to
65825bf
Compare
Reads telemetry from Specialized Turbo e-bikes over Bluetooth Low Energy using the specialized-turbo PyPI package. Connects via GATT notifications and exposes 18 sensors: battery, speed, power, cadence, odometer, motor temp, assist level, and assist percentages. Supports auto-discovery via manufacturer data and manual setup with an optional pairing PIN. Includes a reconfigure flow for updating the PIN.
ActiveBluetoothDataUpdateCoordinator does not extend DataUpdateCoordinator, so CoordinatorEntity[T] fails the type-var constraint. Switch to PassiveBluetoothCoordinatorEntity which accepts PassiveBluetoothDataUpdateCoordinator subtypes.
Use AddConfigEntryEntitiesCallback instead of AddEntitiesCallback for async_setup_entry, and return StateType instead of Any from native_value.
- Fix config flow title: use device name instead of service info object - Use REVOLUTIONS_PER_MINUTE constant instead of literal "RPM" - Add CONNECTION_BLUETOOTH to DeviceInfo connections - Call async_shutdown() in async_unload_entry for BLE cleanup - Widen notification handler sender type to accept int | BleakGATTCharacteristic
- Remove logger param from coordinator, use module-level _LOGGER - Fix _on_disconnect thread safety with call_soon_threadsafe - Use service_info.device instead of extra BLE address lookup - Lower pairing/subscription logs to debug - Make assist_level an enum sensor with snake_case values - Drop redundant translation_key on battery (device class handles it) - Remove state_class from static battery_capacity_wh - Narrow value_fn return type to StateType - Simplify DeviceInfo: connections only, no name - Remove unused _LOGGER from config_flow - Deduplicate PIN strings in strings.json with references - Defer diagnostics to follow-up PR
- _assist_level_name returns None for non-AssistLevel values (ENUM sensor requires values from options list or None) - Remove test_setup_entry_device_not_in_range (duplicate of test_setup_entry) - Update test_assist_level_name_unknown_int to expect None
65825bf to
f30978f
Compare
There was a problem hiding this comment.
Pull request overview
Adds a new Bluetooth Low Energy integration for Specialized Turbo e-bikes, using a persistent GATT connection + notifications to expose bike telemetry as Home Assistant sensor entities.
Changes:
- Introduces the
specialized_turbointegration (config flow, BLE coordinator, and 18 sensor entities). - Adds translations/icons and registers Bluetooth discovery + generated integration metadata.
- Adds a full test suite for config flow, coordinator behavior, init/unload, and sensor value functions.
Show a summary per file
| File | Description |
|---|---|
homeassistant/components/specialized_turbo/__init__.py |
Sets up/unloads the config entry and forwards the sensor platform; stores coordinator in runtime data. |
homeassistant/components/specialized_turbo/config_flow.py |
Implements Bluetooth discovery, user setup, and reconfigure flow (optional pairing PIN). |
homeassistant/components/specialized_turbo/const.py |
Defines integration constants (DOMAIN, CONF_PIN). |
homeassistant/components/specialized_turbo/coordinator.py |
Maintains BLE connection, subscribes to notifications, parses telemetry, and pushes updates to entities. |
homeassistant/components/specialized_turbo/sensor.py |
Defines sensor entity descriptions and sensor entities backed by the coordinator snapshot. |
homeassistant/components/specialized_turbo/manifest.json |
Declares integration metadata, BLE discovery matcher, and dependency (specialized-turbo). |
homeassistant/components/specialized_turbo/strings.json |
Provides config flow and sensor translations (including enum states). |
homeassistant/components/specialized_turbo/icons.json |
Provides entity icons for key sensors. |
homeassistant/components/specialized_turbo/quality_scale.yaml |
Declares quality scale status for the new integration. |
homeassistant/generated/bluetooth.py |
Registers Bluetooth discovery matcher for the new domain. |
homeassistant/generated/config_flows.py |
Registers the integration as having a config flow. |
homeassistant/generated/integrations.json |
Registers the integration in generated integrations metadata. |
requirements_all.txt |
Adds specialized-turbo==0.1.1 to runtime requirements. |
requirements_test_all.txt |
Adds specialized-turbo==0.1.1 to test requirements. |
CODEOWNERS |
Adds code ownership for the new integration and its tests. |
tests/components/specialized_turbo/__init__.py |
Initializes the test package. |
tests/components/specialized_turbo/conftest.py |
Adds BLE discovery fixtures and connection mock helpers for tests. |
tests/components/specialized_turbo/test_config_flow.py |
Tests discovery/user/reconfigure flows and error handling. |
tests/components/specialized_turbo/test_coordinator.py |
Tests connection lifecycle, notification parsing, and shutdown behavior. |
tests/components/specialized_turbo/test_init.py |
Tests config entry setup/unload wiring. |
tests/components/specialized_turbo/test_sensor.py |
Tests sensor description/value functions and assist-level mapping. |
Copilot's findings
- Files reviewed: 18/21 changed files
- Comments generated: 2
- Re-raise BleakError after clearing client so the coordinator tracks poll failures correctly - Compare discovered addresses with format_mac() so already-configured devices are filtered in the user step - Update tests accordingly
Specialized TCU PINs are 6 digits and can have leading zeros. Storing as int would drop them (e.g. '012345' -> 12345).
There was a problem hiding this comment.
Pull request overview
Adds a new Home Assistant integration to connect to Specialized Turbo e-bikes over Bluetooth LE and expose bike telemetry as sensor entities.
Changes:
- Introduces the
specialized_turbointegration with BLE discovery, config flow (optional pairing PIN), and a BLE coordinator maintaining a GATT notification subscription. - Adds 18 sensor entities backed by parsed telemetry from the
specialized-turbolibrary (battery, motor/rider metrics, assist settings). - Adds full test coverage for config flow, coordinator behavior, and sensor value mapping; updates requirements, generated bluetooth/config-flow registries, and CODEOWNERS.
Show a summary per file
| File | Description |
|---|---|
| homeassistant/components/specialized_turbo/init.py | Sets up/unloads the integration and forwards to the sensor platform. |
| homeassistant/components/specialized_turbo/config_flow.py | Implements Bluetooth discovery/user flow and reconfigure flow for the optional PIN. |
| homeassistant/components/specialized_turbo/coordinator.py | Manages BLE connection + notification subscription and pushes telemetry updates. |
| homeassistant/components/specialized_turbo/sensor.py | Defines the 18 sensor entity descriptions and entity implementation. |
| homeassistant/components/specialized_turbo/manifest.json | Declares integration metadata, BLE matcher, dependency, and PyPI requirement. |
| homeassistant/components/specialized_turbo/strings.json | Adds config-flow + entity translations (including enum states). |
| homeassistant/components/specialized_turbo/icons.json | Provides icons for key sensor entities. |
| homeassistant/components/specialized_turbo/const.py | Defines integration constants (DOMAIN, CONF_PIN). |
| homeassistant/components/specialized_turbo/quality_scale.yaml | Documents quality-scale rule status/exemptions for the new integration. |
| homeassistant/generated/bluetooth.py | Registers the BLE discovery matcher in generated bluetooth matchers. |
| homeassistant/generated/config_flows.py | Adds the domain to the generated config flow registry. |
| homeassistant/generated/integrations.json | Registers the integration metadata in generated integrations list. |
| requirements_all.txt | Adds specialized-turbo==0.1.1 to the consolidated requirements list. |
| requirements_test_all.txt | Adds specialized-turbo==0.1.1 to the consolidated test requirements list. |
| tests/components/specialized_turbo/conftest.py | Adds BLE service info fixtures and connection mocking helpers. |
| tests/components/specialized_turbo/test_config_flow.py | Validates discovery/user/reconfigure flow behavior and error handling. |
| tests/components/specialized_turbo/test_coordinator.py | Tests reconnection logic, notify parsing path, pairing behavior, and shutdown cleanup. |
| tests/components/specialized_turbo/test_init.py | Tests entry setup/unload wiring and coordinator lifecycle hooks. |
| tests/components/specialized_turbo/test_sensor.py | Tests all sensor value functions and description metadata constraints. |
| tests/components/specialized_turbo/init.py | Marks the test package for the integration. |
| CODEOWNERS | Adds code ownership entries for the new integration and its tests. |
Copilot's findings
- Files reviewed: 18/21 changed files
- Comments generated: 2
| self.snapshot.update_from_message(msg) | ||
|
|
||
| if msg.field_name: | ||
| _LOGGER.debug("%s = %s %s", msg.field_name, msg.converted_value, msg.unit) |
There was a problem hiding this comment.
Move notification parsing/state updates onto the Home Assistant event loop (or guard with a lock) to avoid mutating self.snapshot from a Bleak callback thread.
| def _on_disconnect(self, client: BleakClient) -> None: | ||
| """Handle unexpected disconnection.""" | ||
| if not self._was_unavailable: | ||
| _LOGGER.info("Disconnected from Specialized Turbo at %s", self._address) | ||
| self._was_unavailable = True | ||
| self._client = None | ||
| # Notify listeners so entities mark themselves unavailable. | ||
| # Schedule on the event loop since bleak disconnect callbacks | ||
| # may come from a background thread. | ||
| self.hass.loop.call_soon_threadsafe(self.async_update_listeners) | ||
|
|
There was a problem hiding this comment.
Schedule disconnect state changes on the Home Assistant event loop (or protect them with a lock) so _client/availability flags aren't modified from a Bleak callback thread.
| def _on_disconnect(self, client: BleakClient) -> None: | |
| """Handle unexpected disconnection.""" | |
| if not self._was_unavailable: | |
| _LOGGER.info("Disconnected from Specialized Turbo at %s", self._address) | |
| self._was_unavailable = True | |
| self._client = None | |
| # Notify listeners so entities mark themselves unavailable. | |
| # Schedule on the event loop since bleak disconnect callbacks | |
| # may come from a background thread. | |
| self.hass.loop.call_soon_threadsafe(self.async_update_listeners) | |
| @callback | |
| def _handle_disconnect(self) -> None: | |
| """Handle unexpected disconnection on the HA event loop.""" | |
| if not self._was_unavailable: | |
| _LOGGER.info("Disconnected from Specialized Turbo at %s", self._address) | |
| self._was_unavailable = True | |
| self._client = None | |
| # Notify listeners so entities mark themselves unavailable. | |
| self.async_update_listeners() | |
| def _on_disconnect(self, client: BleakClient) -> None: | |
| """Schedule unexpected disconnection handling on the HA event loop.""" | |
| # bleak disconnect callbacks may come from a background thread. | |
| self.hass.loop.call_soon_threadsafe(self._handle_disconnect) |
Breaking change
Proposed change
Add a new integration for Specialized Turbo e-bikes (Vado, Levo, Creo, Como, Tero). It connects over Bluetooth Low Energy, subscribes to GATT notifications, and exposes 18 sensor entities: battery charge, speed, rider power, motor power, cadence, odometer, motor temperature, assist level, battery health, charge cycles, voltage, current, and the three assist percentages.
The bike is auto-discovered via manufacturer data (Nordic manufacturer ID 89, "TURBOHMI" prefix). Setup collects an optional pairing PIN. The coordinator is an
ActiveBluetoothDataUpdateCoordinatorthat maintains a persistent GATT connection and pushes parsed telemetry to entities viacall_soon_threadsafe.BLE protocol parsing is handled by the
specialized-turbolibrary12, which implements the Gen 2 "TURBOHMI2017" protocol3 reverse-engineered fromSepp62/LevoEsp32Ble.Type of change
Additional information
Checklist
ruff format homeassistant tests)If user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
Updated and included derived files by running:
python3 -m script.hassfest.requirements_all.txt.Updated by running
python3 -m script.gen_requirements_all.To help with the load of incoming pull requests:
Footnotes
https://github.com/JamieMagee/specialized-turbo ↩
https://pypi.org/project/specialized-turbo/ ↩
https://github.com/JamieMagee/specialized-turbo/blob/main/docs/protocol.md ↩