mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 20:27:08 +00:00
Handle additional bluetooth start exceptions (#76096)
This commit is contained in:
parent
fbf3c1a5d4
commit
bf931f1225
@ -12,6 +12,7 @@ from typing import TYPE_CHECKING, Final
|
||||
|
||||
import async_timeout
|
||||
from bleak import BleakError
|
||||
from dbus_next import InvalidMessageError
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
||||
@ -26,6 +27,7 @@ from homeassistant.helpers import discovery_flow
|
||||
from homeassistant.helpers.event import async_track_time_interval
|
||||
from homeassistant.helpers.service_info.bluetooth import BluetoothServiceInfo
|
||||
from homeassistant.loader import async_get_bluetooth
|
||||
from homeassistant.util.package import is_docker_env
|
||||
|
||||
from . import models
|
||||
from .const import CONF_ADAPTER, DEFAULT_ADAPTERS, DOMAIN
|
||||
@ -341,13 +343,42 @@ class BluetoothManager:
|
||||
try:
|
||||
async with async_timeout.timeout(START_TIMEOUT):
|
||||
await self.scanner.start() # type: ignore[no-untyped-call]
|
||||
except InvalidMessageError as ex:
|
||||
self._cancel_device_detected()
|
||||
_LOGGER.debug("Invalid DBus message received: %s", ex, exc_info=True)
|
||||
raise ConfigEntryNotReady(
|
||||
f"Invalid DBus message received: {ex}; try restarting `dbus`"
|
||||
) from ex
|
||||
except BrokenPipeError as ex:
|
||||
self._cancel_device_detected()
|
||||
_LOGGER.debug("DBus connection broken: %s", ex, exc_info=True)
|
||||
if is_docker_env():
|
||||
raise ConfigEntryNotReady(
|
||||
f"DBus connection broken: {ex}; try restarting `bluetooth`, `dbus`, and finally the docker container"
|
||||
) from ex
|
||||
raise ConfigEntryNotReady(
|
||||
f"DBus connection broken: {ex}; try restarting `bluetooth` and `dbus`"
|
||||
) from ex
|
||||
except FileNotFoundError as ex:
|
||||
self._cancel_device_detected()
|
||||
_LOGGER.debug(
|
||||
"FileNotFoundError while starting bluetooth: %s", ex, exc_info=True
|
||||
)
|
||||
if is_docker_env():
|
||||
raise ConfigEntryNotReady(
|
||||
f"DBus service not found; docker config may be missing `-v /run/dbus:/run/dbus:ro`: {ex}"
|
||||
) from ex
|
||||
raise ConfigEntryNotReady(
|
||||
f"DBus service not found; make sure the DBus socket is available to Home Assistant: {ex}"
|
||||
) from ex
|
||||
except asyncio.TimeoutError as ex:
|
||||
self._cancel_device_detected()
|
||||
raise ConfigEntryNotReady(
|
||||
f"Timed out starting Bluetooth after {START_TIMEOUT} seconds"
|
||||
) from ex
|
||||
except (FileNotFoundError, BleakError) as ex:
|
||||
except BleakError as ex:
|
||||
self._cancel_device_detected()
|
||||
_LOGGER.debug("BleakError while starting bluetooth: %s", ex, exc_info=True)
|
||||
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)
|
||||
|
@ -5,6 +5,7 @@ from unittest.mock import MagicMock, patch
|
||||
|
||||
from bleak import BleakError
|
||||
from bleak.backends.scanner import AdvertisementData, BLEDevice
|
||||
from dbus_next import InvalidMessageError
|
||||
import pytest
|
||||
|
||||
from homeassistant.components import bluetooth
|
||||
@ -1409,3 +1410,112 @@ async def test_changing_the_adapter_at_runtime(hass):
|
||||
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
||||
async def test_dbus_socket_missing_in_container(hass, caplog):
|
||||
"""Test we handle dbus being missing in the container."""
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.bluetooth.is_docker_env", return_value=True
|
||||
), patch("homeassistant.components.bluetooth.HaBleakScanner.async_setup"), patch(
|
||||
"homeassistant.components.bluetooth.HaBleakScanner.start",
|
||||
side_effect=FileNotFoundError,
|
||||
):
|
||||
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()
|
||||
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
|
||||
await hass.async_block_till_done()
|
||||
assert "/run/dbus" in caplog.text
|
||||
assert "docker" in caplog.text
|
||||
|
||||
|
||||
async def test_dbus_socket_missing(hass, caplog):
|
||||
"""Test we handle dbus being missing."""
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.bluetooth.is_docker_env", return_value=False
|
||||
), patch("homeassistant.components.bluetooth.HaBleakScanner.async_setup"), patch(
|
||||
"homeassistant.components.bluetooth.HaBleakScanner.start",
|
||||
side_effect=FileNotFoundError,
|
||||
):
|
||||
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()
|
||||
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
|
||||
await hass.async_block_till_done()
|
||||
assert "DBus" in caplog.text
|
||||
assert "docker" not in caplog.text
|
||||
|
||||
|
||||
async def test_dbus_broken_pipe_in_container(hass, caplog):
|
||||
"""Test we handle dbus broken pipe in the container."""
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.bluetooth.is_docker_env", return_value=True
|
||||
), patch("homeassistant.components.bluetooth.HaBleakScanner.async_setup"), patch(
|
||||
"homeassistant.components.bluetooth.HaBleakScanner.start",
|
||||
side_effect=BrokenPipeError,
|
||||
):
|
||||
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()
|
||||
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
|
||||
await hass.async_block_till_done()
|
||||
assert "dbus" in caplog.text
|
||||
assert "restarting" in caplog.text
|
||||
assert "container" in caplog.text
|
||||
|
||||
|
||||
async def test_dbus_broken_pipe(hass, caplog):
|
||||
"""Test we handle dbus broken pipe."""
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.bluetooth.is_docker_env", return_value=False
|
||||
), patch("homeassistant.components.bluetooth.HaBleakScanner.async_setup"), patch(
|
||||
"homeassistant.components.bluetooth.HaBleakScanner.start",
|
||||
side_effect=BrokenPipeError,
|
||||
):
|
||||
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()
|
||||
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
|
||||
await hass.async_block_till_done()
|
||||
assert "DBus" in caplog.text
|
||||
assert "restarting" in caplog.text
|
||||
assert "container" not in caplog.text
|
||||
|
||||
|
||||
async def test_invalid_dbus_message(hass, caplog):
|
||||
"""Test we handle invalid dbus message."""
|
||||
|
||||
with patch("homeassistant.components.bluetooth.HaBleakScanner.async_setup"), patch(
|
||||
"homeassistant.components.bluetooth.HaBleakScanner.start",
|
||||
side_effect=InvalidMessageError,
|
||||
):
|
||||
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()
|
||||
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP)
|
||||
await hass.async_block_till_done()
|
||||
assert "dbus" in caplog.text
|
||||
|
Loading…
x
Reference in New Issue
Block a user