From 0bfd4c44bb8e4902ed92f7afd5ac736836dc5761 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 1 Jun 2026 14:11:09 -0500 Subject: [PATCH] Explain why a LED BLE device could not be found (#172764) --- homeassistant/components/led_ble/__init__.py | 14 ++++++- homeassistant/components/led_ble/strings.json | 5 +++ tests/components/led_ble/test_init.py | 41 +++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 tests/components/led_ble/test_init.py diff --git a/homeassistant/components/led_ble/__init__.py b/homeassistant/components/led_ble/__init__.py index 14a41952b44d..a6f8bf56efd4 100644 --- a/homeassistant/components/led_ble/__init__.py +++ b/homeassistant/components/led_ble/__init__.py @@ -5,12 +5,13 @@ import asyncio from led_ble import LEDBLE from homeassistant.components import bluetooth +from homeassistant.components.bluetooth import BluetoothReachabilityIntent from homeassistant.components.bluetooth.match import ADDRESS, BluetoothCallbackMatcher from homeassistant.const import CONF_ADDRESS, EVENT_HOMEASSISTANT_STOP, Platform from homeassistant.core import Event, HomeAssistant, callback from homeassistant.exceptions import ConfigEntryNotReady -from .const import DEVICE_TIMEOUT +from .const import DEVICE_TIMEOUT, DOMAIN from .coordinator import LEDBLEConfigEntry, LEDBLECoordinator, LEDBLEData PLATFORMS: list[Platform] = [Platform.LIGHT] @@ -22,7 +23,16 @@ async def async_setup_entry(hass: HomeAssistant, entry: LEDBLEConfigEntry) -> bo ble_device = bluetooth.async_ble_device_from_address(hass, address.upper(), True) if not ble_device: raise ConfigEntryNotReady( - f"Could not find LED BLE device with address {address}" + translation_domain=DOMAIN, + translation_key="device_not_found", + translation_placeholders={ + "address": address, + "reason": bluetooth.async_address_reachability_diagnostics( + hass, + address.upper(), + BluetoothReachabilityIntent.CONNECTION, + ), + }, ) led_ble = LEDBLE(ble_device) diff --git a/homeassistant/components/led_ble/strings.json b/homeassistant/components/led_ble/strings.json index 7d777781ab11..0cc44653ce2f 100644 --- a/homeassistant/components/led_ble/strings.json +++ b/homeassistant/components/led_ble/strings.json @@ -18,5 +18,10 @@ } } } + }, + "exceptions": { + "device_not_found": { + "message": "Could not find LED BLE device with address {address}: {reason}" + } } } diff --git a/tests/components/led_ble/test_init.py b/tests/components/led_ble/test_init.py new file mode 100644 index 000000000000..f5b1bdf3d5d7 --- /dev/null +++ b/tests/components/led_ble/test_init.py @@ -0,0 +1,41 @@ +"""Test the LED BLE integration init.""" + +from unittest.mock import patch + +import pytest + +from homeassistant.components.led_ble.const import DOMAIN +from homeassistant.config_entries import ConfigEntryState +from homeassistant.const import CONF_ADDRESS +from homeassistant.core import HomeAssistant + +from . import LED_BLE_DISCOVERY_INFO + +from tests.common import MockConfigEntry + + +async def test_setup_retries_when_device_not_found( + hass: HomeAssistant, + caplog: pytest.LogCaptureFixture, +) -> None: + """Test setup is retried with a diagnostic reason when the device is missing.""" + entry = MockConfigEntry( + domain=DOMAIN, + unique_id=LED_BLE_DISCOVERY_INFO.address, + data={CONF_ADDRESS: LED_BLE_DISCOVERY_INFO.address}, + ) + entry.add_to_hass(hass) + + with patch( + "homeassistant.components.led_ble.bluetooth." + "async_address_reachability_diagnostics", + return_value="mock reachability reason", + ): + await hass.config_entries.async_setup(entry.entry_id) + await hass.async_block_till_done() + + assert entry.state is ConfigEntryState.SETUP_RETRY + assert ( + "Could not find LED BLE device with address " + f"{LED_BLE_DISCOVERY_INFO.address}: mock reachability reason" in caplog.text + )