|
|
|
@@ -22,7 +22,6 @@ from homeassistant.setup import async_setup_component
|
|
|
|
|
from homeassistant.util import dt as dt_util
|
|
|
|
|
|
|
|
|
|
from . import (
|
|
|
|
|
_get_manager,
|
|
|
|
|
async_setup_with_one_adapter,
|
|
|
|
|
generate_advertisement_data,
|
|
|
|
|
generate_ble_device,
|
|
|
|
@@ -183,7 +182,7 @@ async def test_adapter_needs_reset_at_start(
|
|
|
|
|
with (
|
|
|
|
|
patch(
|
|
|
|
|
"habluetooth.scanner.OriginalBleakScanner.start",
|
|
|
|
|
side_effect=[BleakError(error), None],
|
|
|
|
|
side_effect=[BleakError(error), BleakError(error), None],
|
|
|
|
|
),
|
|
|
|
|
patch(
|
|
|
|
|
"habluetooth.util.recover_adapter", return_value=True
|
|
|
|
@@ -239,46 +238,47 @@ async def test_recovery_from_dbus_restart(
|
|
|
|
|
|
|
|
|
|
assert called_start == 1
|
|
|
|
|
|
|
|
|
|
start_time_monotonic = time.monotonic()
|
|
|
|
|
mock_discovered = [MagicMock()]
|
|
|
|
|
start_time_monotonic = time.monotonic()
|
|
|
|
|
mock_discovered = [MagicMock()]
|
|
|
|
|
|
|
|
|
|
# Ensure we don't restart the scanner if we don't need to
|
|
|
|
|
with patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic + 10,
|
|
|
|
|
):
|
|
|
|
|
async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL)
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
# Ensure we don't restart the scanner if we don't need to
|
|
|
|
|
with patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic + 10,
|
|
|
|
|
):
|
|
|
|
|
async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL)
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
|
|
|
|
assert called_start == 1
|
|
|
|
|
assert called_start == 1
|
|
|
|
|
|
|
|
|
|
# Fire a callback to reset the timer
|
|
|
|
|
with patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic,
|
|
|
|
|
):
|
|
|
|
|
_callback(
|
|
|
|
|
generate_ble_device("44:44:33:11:23:42", "any_name"),
|
|
|
|
|
generate_advertisement_data(local_name="any_name"),
|
|
|
|
|
)
|
|
|
|
|
# Fire a callback to reset the timer
|
|
|
|
|
with patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic,
|
|
|
|
|
):
|
|
|
|
|
_callback(
|
|
|
|
|
generate_ble_device("44:44:33:11:23:42", "any_name"),
|
|
|
|
|
generate_advertisement_data(local_name="any_name"),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Ensure we don't restart the scanner if we don't need to
|
|
|
|
|
with patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic + 20,
|
|
|
|
|
):
|
|
|
|
|
async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL)
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
# Ensure we don't restart the scanner if we don't need to
|
|
|
|
|
with patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic + 20,
|
|
|
|
|
):
|
|
|
|
|
async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL)
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
|
|
|
|
assert called_start == 1
|
|
|
|
|
assert called_start == 1
|
|
|
|
|
|
|
|
|
|
# We hit the timer, so we restart the scanner
|
|
|
|
|
with patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic + SCANNER_WATCHDOG_TIMEOUT + 20,
|
|
|
|
|
):
|
|
|
|
|
async_fire_time_changed(
|
|
|
|
|
hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL + timedelta(seconds=20)
|
|
|
|
|
)
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
# We hit the timer, so we restart the scanner
|
|
|
|
|
with patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic + SCANNER_WATCHDOG_TIMEOUT + 20,
|
|
|
|
|
):
|
|
|
|
|
async_fire_time_changed(
|
|
|
|
|
hass,
|
|
|
|
|
dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL + timedelta(seconds=20),
|
|
|
|
|
)
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
|
|
|
|
assert called_start == 2
|
|
|
|
|
assert called_start == 2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def test_adapter_recovery(hass: HomeAssistant, one_adapter: None) -> None:
|
|
|
|
@@ -327,43 +327,42 @@ async def test_adapter_recovery(hass: HomeAssistant, one_adapter: None) -> None:
|
|
|
|
|
|
|
|
|
|
assert called_start == 1
|
|
|
|
|
|
|
|
|
|
scanner = _get_manager()
|
|
|
|
|
mock_discovered = [MagicMock()]
|
|
|
|
|
mock_discovered = [MagicMock()]
|
|
|
|
|
|
|
|
|
|
# Ensure we don't restart the scanner if we don't need to
|
|
|
|
|
with patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic + 10,
|
|
|
|
|
):
|
|
|
|
|
async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL)
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
# Ensure we don't restart the scanner if we don't need to
|
|
|
|
|
with patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic + 10,
|
|
|
|
|
):
|
|
|
|
|
async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL)
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
|
|
|
|
assert called_start == 1
|
|
|
|
|
assert called_start == 1
|
|
|
|
|
|
|
|
|
|
# Ensure we don't restart the scanner if we don't need to
|
|
|
|
|
with patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic + 20,
|
|
|
|
|
):
|
|
|
|
|
async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL)
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
# Ensure we don't restart the scanner if we don't need to
|
|
|
|
|
with patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic + 20,
|
|
|
|
|
):
|
|
|
|
|
async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL)
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
|
|
|
|
assert called_start == 1
|
|
|
|
|
assert called_start == 1
|
|
|
|
|
|
|
|
|
|
# We hit the timer with no detections, so we reset the adapter and restart the scanner
|
|
|
|
|
with (
|
|
|
|
|
patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic
|
|
|
|
|
+ SCANNER_WATCHDOG_TIMEOUT
|
|
|
|
|
+ SCANNER_WATCHDOG_INTERVAL.total_seconds(),
|
|
|
|
|
),
|
|
|
|
|
patch(
|
|
|
|
|
"habluetooth.util.recover_adapter", return_value=True
|
|
|
|
|
) as mock_recover_adapter,
|
|
|
|
|
):
|
|
|
|
|
async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL)
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
# We hit the timer with no detections, so we reset the adapter and restart the scanner
|
|
|
|
|
with (
|
|
|
|
|
patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic
|
|
|
|
|
+ SCANNER_WATCHDOG_TIMEOUT
|
|
|
|
|
+ SCANNER_WATCHDOG_INTERVAL.total_seconds(),
|
|
|
|
|
),
|
|
|
|
|
patch(
|
|
|
|
|
"habluetooth.util.recover_adapter", return_value=True
|
|
|
|
|
) as mock_recover_adapter,
|
|
|
|
|
):
|
|
|
|
|
async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL)
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
|
|
|
|
assert len(mock_recover_adapter.mock_calls) == 1
|
|
|
|
|
assert called_start == 2
|
|
|
|
|
assert len(mock_recover_adapter.mock_calls) == 1
|
|
|
|
|
assert called_start == 2
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def test_adapter_scanner_fails_to_start_first_time(
|
|
|
|
@@ -418,61 +417,61 @@ async def test_adapter_scanner_fails_to_start_first_time(
|
|
|
|
|
|
|
|
|
|
assert called_start == 1
|
|
|
|
|
|
|
|
|
|
scanner = _get_manager()
|
|
|
|
|
mock_discovered = [MagicMock()]
|
|
|
|
|
mock_discovered = [MagicMock()]
|
|
|
|
|
|
|
|
|
|
# Ensure we don't restart the scanner if we don't need to
|
|
|
|
|
with patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic + 10,
|
|
|
|
|
):
|
|
|
|
|
async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL)
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
# Ensure we don't restart the scanner if we don't need to
|
|
|
|
|
with patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic + 10,
|
|
|
|
|
):
|
|
|
|
|
async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL)
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
|
|
|
|
assert called_start == 1
|
|
|
|
|
assert called_start == 1
|
|
|
|
|
|
|
|
|
|
# Ensure we don't restart the scanner if we don't need to
|
|
|
|
|
with patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic + 20,
|
|
|
|
|
):
|
|
|
|
|
async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL)
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
# Ensure we don't restart the scanner if we don't need to
|
|
|
|
|
with patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic + 20,
|
|
|
|
|
):
|
|
|
|
|
async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL)
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
|
|
|
|
assert called_start == 1
|
|
|
|
|
assert called_start == 1
|
|
|
|
|
|
|
|
|
|
# We hit the timer with no detections, so we reset the adapter and restart the scanner
|
|
|
|
|
with (
|
|
|
|
|
patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic
|
|
|
|
|
+ SCANNER_WATCHDOG_TIMEOUT
|
|
|
|
|
+ SCANNER_WATCHDOG_INTERVAL.total_seconds(),
|
|
|
|
|
),
|
|
|
|
|
patch(
|
|
|
|
|
"habluetooth.util.recover_adapter", return_value=True
|
|
|
|
|
) as mock_recover_adapter,
|
|
|
|
|
):
|
|
|
|
|
async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL)
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
# We hit the timer with no detections, so we reset the adapter and restart the scanner
|
|
|
|
|
with (
|
|
|
|
|
patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic
|
|
|
|
|
+ SCANNER_WATCHDOG_TIMEOUT
|
|
|
|
|
+ SCANNER_WATCHDOG_INTERVAL.total_seconds(),
|
|
|
|
|
),
|
|
|
|
|
patch(
|
|
|
|
|
"habluetooth.util.recover_adapter", return_value=True
|
|
|
|
|
) as mock_recover_adapter,
|
|
|
|
|
):
|
|
|
|
|
async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL)
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
|
|
|
|
assert len(mock_recover_adapter.mock_calls) == 1
|
|
|
|
|
assert called_start == 3
|
|
|
|
|
assert len(mock_recover_adapter.mock_calls) == 1
|
|
|
|
|
assert called_start == 4
|
|
|
|
|
|
|
|
|
|
# We hit the timer again the previous start call failed, make sure
|
|
|
|
|
# we try again
|
|
|
|
|
with (
|
|
|
|
|
patch_bluetooth_time(
|
|
|
|
|
start_time_monotonic
|
|
|
|
|
+ SCANNER_WATCHDOG_TIMEOUT
|
|
|
|
|
+ SCANNER_WATCHDOG_INTERVAL.total_seconds(),
|
|
|
|
|
),
|
|
|
|
|
patch(
|
|
|
|
|
"habluetooth.util.recover_adapter", return_value=True
|
|
|
|
|
) as mock_recover_adapter,
|
|
|
|
|
):
|
|
|
|
|
async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL)
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
now_monotonic = time.monotonic()
|
|
|
|
|
# We hit the timer again the previous start call failed, make sure
|
|
|
|
|
# we try again
|
|
|
|
|
with (
|
|
|
|
|
patch_bluetooth_time(
|
|
|
|
|
now_monotonic
|
|
|
|
|
+ SCANNER_WATCHDOG_TIMEOUT * 2
|
|
|
|
|
+ SCANNER_WATCHDOG_INTERVAL.total_seconds(),
|
|
|
|
|
),
|
|
|
|
|
patch(
|
|
|
|
|
"habluetooth.util.recover_adapter", return_value=True
|
|
|
|
|
) as mock_recover_adapter,
|
|
|
|
|
):
|
|
|
|
|
async_fire_time_changed(hass, dt_util.utcnow() + SCANNER_WATCHDOG_INTERVAL)
|
|
|
|
|
await hass.async_block_till_done()
|
|
|
|
|
|
|
|
|
|
assert len(mock_recover_adapter.mock_calls) == 1
|
|
|
|
|
assert called_start == 4
|
|
|
|
|
assert len(mock_recover_adapter.mock_calls) == 1
|
|
|
|
|
assert called_start == 5
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def test_adapter_fails_to_start_and_takes_a_bit_to_init(
|
|
|
|
@@ -497,9 +496,11 @@ async def test_adapter_fails_to_start_and_takes_a_bit_to_init(
|
|
|
|
|
nonlocal called_start
|
|
|
|
|
called_start += 1
|
|
|
|
|
if called_start == 1:
|
|
|
|
|
raise BleakError("org.bluez.Error.InProgress")
|
|
|
|
|
if called_start == 2:
|
|
|
|
|
raise BleakError("org.freedesktop.DBus.Error.UnknownObject")
|
|
|
|
|
if called_start == 2:
|
|
|
|
|
raise BleakError("org.bluez.Error.InProgress")
|
|
|
|
|
if called_start == 3:
|
|
|
|
|
raise BleakError("org.bluez.Error.InProgress")
|
|
|
|
|
|
|
|
|
|
async def stop(self, *args, **kwargs):
|
|
|
|
|
"""Mock Start."""
|
|
|
|
@@ -538,7 +539,7 @@ async def test_adapter_fails_to_start_and_takes_a_bit_to_init(
|
|
|
|
|
):
|
|
|
|
|
await async_setup_with_one_adapter(hass)
|
|
|
|
|
|
|
|
|
|
assert called_start == 3
|
|
|
|
|
assert called_start == 4
|
|
|
|
|
|
|
|
|
|
assert len(mock_recover_adapter.mock_calls) == 1
|
|
|
|
|
assert "Waiting for adapter to initialize" in caplog.text
|
|
|
|
|