Skip to content

Add Specialized Turbo e-bike BLE integration#165565

Open
JamieMagee wants to merge 11 commits intohome-assistant:devfrom
JamieMagee:add-specialized-turbo-integration
Open

Add Specialized Turbo e-bike BLE integration#165565
JamieMagee wants to merge 11 commits intohome-assistant:devfrom
JamieMagee:add-specialized-turbo-integration

Conversation

@JamieMagee
Copy link
Copy Markdown
Contributor

@JamieMagee JamieMagee commented Mar 14, 2026

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 ActiveBluetoothDataUpdateCoordinator that maintains a persistent GATT connection and pushes parsed telemetry to entities via call_soon_threadsafe.

BLE protocol parsing is handled by the specialized-turbo library12, which implements the Gen 2 "TURBOHMI2017" protocol3 reverse-engineered from Sepp62/LevoEsp32Ble.

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Deprecation (breaking change to happen in the future)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

Checklist

  • I understand the code I am submitting and can explain how it works.
  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • I have followed the perfect PR recommendations
  • The code has been formatted using Ruff (ruff format homeassistant tests)
  • Tests have been added to verify that the new code works.
  • Any generated code has been carefully reviewed for correctness and compliance with project standards.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • For the updated dependencies a diff between library versions and ideally a link to the changelog/release notes is added to the PR description.

To help with the load of incoming pull requests:

Footnotes

  1. https://github.com/JamieMagee/specialized-turbo

  2. https://pypi.org/project/specialized-turbo/

  3. https://github.com/JamieMagee/specialized-turbo/blob/main/docs/protocol.md

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_turbo integration (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 using format_mac(...)), but the loop compares info.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

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_turbo integration (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

Copilot AI review requested due to automatic review settings March 14, 2026 23:09
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.1 dependency.

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.

@home-assistant home-assistant bot marked this pull request as draft March 15, 2026 19:35
@home-assistant
Copy link
Copy Markdown

Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍

Learn more about our pull request process.

Copilot AI review requested due to automatic review settings March 23, 2026 00:08
@JamieMagee JamieMagee force-pushed the add-specialized-turbo-integration branch from 1f23b99 to 1e18ea9 Compare March 23, 2026 00:08
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_turbo integration (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.

Copilot AI review requested due to automatic review settings March 23, 2026 00:31
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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) for pin will 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 pin to int, 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),
                }
            ),

@JamieMagee JamieMagee requested a review from joostlek March 23, 2026 00:38
@JamieMagee JamieMagee marked this pull request as ready for review March 23, 2026 00:38
@JamieMagee JamieMagee force-pushed the add-specialized-turbo-integration branch from b6b354f to 65825bf Compare April 3, 2026 18:17
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
Copilot AI review requested due to automatic review settings April 3, 2026 21:42
@JamieMagee JamieMagee force-pushed the add-specialized-turbo-integration branch from 65825bf to f30978f Compare April 3, 2026 21:42
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_turbo integration (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).
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_turbo integration 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-turbo library (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

Comment on lines +132 to +135
self.snapshot.update_from_message(msg)

if msg.field_name:
_LOGGER.debug("%s = %s %s", msg.field_name, msg.converted_value, msg.unit)
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +146 to +156
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)

Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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)

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants