From 5c294550e8c96d636ff22f4206c23de05b13bdb2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 21 Sep 2022 11:03:50 -1000 Subject: [PATCH] Handle default RSSI values from bleak in bluetooth (#78908) --- homeassistant/components/bluetooth/manager.py | 3 +- tests/components/bluetooth/test_manager.py | 56 +++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/bluetooth/manager.py b/homeassistant/components/bluetooth/manager.py index 014da818e12..9f6b0bbe3ed 100644 --- a/homeassistant/components/bluetooth/manager.py +++ b/homeassistant/components/bluetooth/manager.py @@ -60,6 +60,7 @@ APPLE_DEVICE_ID_START_BYTE: Final = 0x10 # bluetooth_le_tracker APPLE_START_BYTES_WANTED: Final = {APPLE_DEVICE_ID_START_BYTE, APPLE_HOMEKIT_START_BYTE} RSSI_SWITCH_THRESHOLD = 6 +NO_RSSI_VALUE = -1000 _LOGGER = logging.getLogger(__name__) @@ -83,7 +84,7 @@ def _prefer_previous_adv( STALE_ADVERTISEMENT_SECONDS, ) return False - if new.device.rssi - RSSI_SWITCH_THRESHOLD > old.device.rssi: + if new.device.rssi - RSSI_SWITCH_THRESHOLD > (old.device.rssi or NO_RSSI_VALUE): # If new advertisement is RSSI_SWITCH_THRESHOLD more, the new one is preferred if new.source != old.source: _LOGGER.debug( diff --git a/tests/components/bluetooth/test_manager.py b/tests/components/bluetooth/test_manager.py index 9ce5985318b..28f870e3a35 100644 --- a/tests/components/bluetooth/test_manager.py +++ b/tests/components/bluetooth/test_manager.py @@ -116,6 +116,62 @@ async def test_switching_adapters_based_on_rssi(hass, enable_bluetooth): ) +async def test_switching_adapters_based_on_zero_rssi(hass, enable_bluetooth): + """Test switching adapters based on zero rssi.""" + + address = "44:44:33:11:23:45" + + switchbot_device_no_rssi = BLEDevice(address, "wohand_poor_signal", rssi=0) + switchbot_adv_no_rssi = AdvertisementData( + local_name="wohand_no_rssi", service_uuids=[] + ) + inject_advertisement_with_source( + hass, switchbot_device_no_rssi, switchbot_adv_no_rssi, "hci0" + ) + + assert ( + bluetooth.async_ble_device_from_address(hass, address) + is switchbot_device_no_rssi + ) + + switchbot_device_good_signal = BLEDevice(address, "wohand_good_signal", rssi=-60) + switchbot_adv_good_signal = AdvertisementData( + local_name="wohand_good_signal", service_uuids=[] + ) + inject_advertisement_with_source( + hass, switchbot_device_good_signal, switchbot_adv_good_signal, "hci1" + ) + + assert ( + bluetooth.async_ble_device_from_address(hass, address) + is switchbot_device_good_signal + ) + + inject_advertisement_with_source( + hass, switchbot_device_good_signal, switchbot_adv_no_rssi, "hci0" + ) + assert ( + bluetooth.async_ble_device_from_address(hass, address) + is switchbot_device_good_signal + ) + + # We should not switch adapters unless the signal hits the threshold + switchbot_device_similar_signal = BLEDevice( + address, "wohand_similar_signal", rssi=-62 + ) + switchbot_adv_similar_signal = AdvertisementData( + local_name="wohand_similar_signal", service_uuids=[] + ) + + inject_advertisement_with_source( + hass, switchbot_device_similar_signal, switchbot_adv_similar_signal, "hci0" + ) + assert ( + bluetooth.async_ble_device_from_address(hass, address) + is switchbot_device_good_signal + ) + + async def test_switching_adapters_based_on_stale(hass, enable_bluetooth): """Test switching adapters based on the previous advertisement being stale."""