Retry later if bluetooth fails to start (#75647)

This commit is contained in:
J. Nick Koston 2022-07-23 12:00:34 -05:00 committed by GitHub
parent 2951a941b6
commit 240bbfa080
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 6 deletions

View File

@ -23,6 +23,7 @@ from homeassistant.core import (
HomeAssistant, HomeAssistant,
callback as hass_callback, callback as hass_callback,
) )
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import discovery_flow from homeassistant.helpers import discovery_flow
from homeassistant.helpers.event import async_track_time_interval from homeassistant.helpers.event import async_track_time_interval
from homeassistant.helpers.service_info.bluetooth import BluetoothServiceInfo from homeassistant.helpers.service_info.bluetooth import BluetoothServiceInfo
@ -338,7 +339,6 @@ class BluetoothManager:
except (FileNotFoundError, BleakError) as ex: except (FileNotFoundError, BleakError) as ex:
raise RuntimeError(f"Failed to initialize Bluetooth: {ex}") from ex raise RuntimeError(f"Failed to initialize Bluetooth: {ex}") from ex
install_multiple_bleak_catcher() install_multiple_bleak_catcher()
self.async_setup_unavailable_tracking()
# We have to start it right away as some integrations might # We have to start it right away as some integrations might
# need it straight away. # need it straight away.
_LOGGER.debug("Starting bluetooth scanner") _LOGGER.debug("Starting bluetooth scanner")
@ -349,7 +349,9 @@ class BluetoothManager:
try: try:
await self.scanner.start() await self.scanner.start()
except (FileNotFoundError, BleakError) as ex: except (FileNotFoundError, BleakError) as ex:
raise RuntimeError(f"Failed to start Bluetooth: {ex}") from ex self._cancel_device_detected()
raise ConfigEntryNotReady(f"Failed to start Bluetooth: {ex}") from ex
self.async_setup_unavailable_tracking()
self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, self.async_stop) self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, self.async_stop)
@hass_callback @hass_callback

View File

@ -15,6 +15,7 @@ from homeassistant.components.bluetooth import (
async_track_unavailable, async_track_unavailable,
models, models,
) )
from homeassistant.config_entries import ConfigEntryState
from homeassistant.const import EVENT_HOMEASSISTANT_STARTED, EVENT_HOMEASSISTANT_STOP from homeassistant.const import EVENT_HOMEASSISTANT_STARTED, EVENT_HOMEASSISTANT_STOP
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
@ -70,10 +71,7 @@ async def test_setup_and_stop_no_bluetooth(hass, caplog):
async def test_setup_and_stop_broken_bluetooth(hass, caplog): async def test_setup_and_stop_broken_bluetooth(hass, caplog):
"""Test we fail gracefully when bluetooth/dbus is broken.""" """Test we fail gracefully when bluetooth/dbus is broken."""
mock_bt = [ mock_bt = []
{"domain": "switchbot", "service_uuid": "cba20d00-224d-11e6-9fb8-0002a5d5c51b"}
]
with patch("homeassistant.components.bluetooth.HaBleakScanner.async_setup"), patch( with patch("homeassistant.components.bluetooth.HaBleakScanner.async_setup"), patch(
"homeassistant.components.bluetooth.HaBleakScanner.start", "homeassistant.components.bluetooth.HaBleakScanner.start",
side_effect=BleakError, side_effect=BleakError,
@ -93,6 +91,42 @@ async def test_setup_and_stop_broken_bluetooth(hass, caplog):
assert len(bluetooth.async_discovered_service_info(hass)) == 0 assert len(bluetooth.async_discovered_service_info(hass)) == 0
async def test_setup_and_retry_adapter_not_yet_available(hass, caplog):
"""Test we retry if the adapter is not yet available."""
mock_bt = []
with patch("homeassistant.components.bluetooth.HaBleakScanner.async_setup"), patch(
"homeassistant.components.bluetooth.HaBleakScanner.start",
side_effect=BleakError,
), patch(
"homeassistant.components.bluetooth.async_get_bluetooth", return_value=mock_bt
):
assert await async_setup_component(
hass, bluetooth.DOMAIN, {bluetooth.DOMAIN: {}}
)
await hass.async_block_till_done()
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
await hass.async_block_till_done()
entry = hass.config_entries.async_entries(bluetooth.DOMAIN)[0]
assert "Failed to start Bluetooth" in caplog.text
assert len(bluetooth.async_discovered_service_info(hass)) == 0
assert entry.state == ConfigEntryState.SETUP_RETRY
with patch(
"homeassistant.components.bluetooth.HaBleakScanner.start",
):
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(minutes=10))
await hass.async_block_till_done()
assert entry.state == ConfigEntryState.LOADED
with patch(
"homeassistant.components.bluetooth.HaBleakScanner.stop",
):
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
await hass.async_block_till_done()
async def test_calling_async_discovered_devices_no_bluetooth(hass, caplog): async def test_calling_async_discovered_devices_no_bluetooth(hass, caplog):
"""Test we fail gracefully when asking for discovered devices and there is no blueooth.""" """Test we fail gracefully when asking for discovered devices and there is no blueooth."""
mock_bt = [] mock_bt = []