Less verbose error logs for bleak connection errors in ActiveBluetoothProcessorCoordinator (#77839)

Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
Jc2k 2022-09-05 15:33:10 +01:00 committed by GitHub
parent 61f4040d56
commit a641bbc352
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 85 additions and 0 deletions

View File

@ -6,6 +6,8 @@ import logging
import time import time
from typing import Any, Generic, TypeVar from typing import Any, Generic, TypeVar
from bleak import BleakError
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.debounce import Debouncer from homeassistant.helpers.debounce import Debouncer
@ -109,6 +111,13 @@ class ActiveBluetoothProcessorCoordinator(
try: try:
update = await self._async_poll_data(self._last_service_info) update = await self._async_poll_data(self._last_service_info)
except BleakError as exc:
if self.last_poll_successful:
self.logger.error(
"%s: Bluetooth error whilst polling: %s", self.address, str(exc)
)
self.last_poll_successful = False
return
except Exception: # pylint: disable=broad-except except Exception: # pylint: disable=broad-except
if self.last_poll_successful: if self.last_poll_successful:
self.logger.exception("%s: Failure while polling", self.address) self.logger.exception("%s: Failure while polling", self.address)

View File

@ -5,6 +5,8 @@ import asyncio
import logging import logging
from unittest.mock import MagicMock, call, patch from unittest.mock import MagicMock, call, patch
from bleak import BleakError
from homeassistant.components.bluetooth import ( from homeassistant.components.bluetooth import (
DOMAIN, DOMAIN,
BluetoothChange, BluetoothChange,
@ -162,6 +164,80 @@ async def test_poll_can_be_skipped(hass: HomeAssistant, mock_bleak_scanner_start
cancel() cancel()
async def test_bleak_error_and_recover(
hass: HomeAssistant, mock_bleak_scanner_start, caplog
):
"""Test bleak error handling and recovery."""
await async_setup_component(hass, DOMAIN, {DOMAIN: {}})
flag = True
def _update_method(service_info: BluetoothServiceInfoBleak):
return {"testdata": None}
def _poll_needed(*args, **kwargs):
return True
async def _poll(*args, **kwargs):
nonlocal flag
if flag:
raise BleakError("Connection was aborted")
return {"testdata": flag}
coordinator = ActiveBluetoothProcessorCoordinator(
hass,
_LOGGER,
address="aa:bb:cc:dd:ee:ff",
mode=BluetoothScanningMode.ACTIVE,
update_method=_update_method,
needs_poll_method=_poll_needed,
poll_method=_poll,
poll_debouncer=Debouncer(
hass,
_LOGGER,
cooldown=0,
immediate=True,
),
)
assert coordinator.available is False # no data yet
saved_callback = None
processor = MagicMock()
coordinator.async_register_processor(processor)
async_handle_update = processor.async_handle_update
def _async_register_callback(_hass, _callback, _matcher, _mode):
nonlocal saved_callback
saved_callback = _callback
return lambda: None
with patch(
"homeassistant.components.bluetooth.update_coordinator.async_register_callback",
_async_register_callback,
):
cancel = coordinator.async_start()
assert saved_callback is not None
# First poll fails
saved_callback(GENERIC_BLUETOOTH_SERVICE_INFO, BluetoothChange.ADVERTISEMENT)
await hass.async_block_till_done()
assert async_handle_update.mock_calls[-1] == call({"testdata": None})
assert (
"aa:bb:cc:dd:ee:ff: Bluetooth error whilst polling: Connection was aborted"
in caplog.text
)
# Second poll works
flag = False
saved_callback(GENERIC_BLUETOOTH_SERVICE_INFO, BluetoothChange.ADVERTISEMENT)
await hass.async_block_till_done()
assert async_handle_update.mock_calls[-1] == call({"testdata": False})
cancel()
async def test_poll_failure_and_recover(hass: HomeAssistant, mock_bleak_scanner_start): async def test_poll_failure_and_recover(hass: HomeAssistant, mock_bleak_scanner_start):
"""Test error handling and recovery.""" """Test error handling and recovery."""
await async_setup_component(hass, DOMAIN, {DOMAIN: {}}) await async_setup_component(hass, DOMAIN, {DOMAIN: {}})