From f400b778371f032e26e3192870830719f16d96a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Sun, 5 Jan 2020 23:13:54 +0200 Subject: [PATCH] Preserve new BLE tracker item name if seen before adding discovery (#30318) * Preserve new BLE device name if one seen before the last scan but not on it * Save an indented else block * Use async_fire_time_changed and mock_device_tracker_conf in tests --- .coveragerc | 1 - .../bluetooth_le_tracker/device_tracker.py | 31 +++++----- requirements_test_all.txt | 4 ++ .../bluetooth_le_tracker/__init__.py | 1 + .../test_device_tracker.py | 56 +++++++++++++++++++ 5 files changed, 78 insertions(+), 15 deletions(-) create mode 100644 tests/components/bluetooth_le_tracker/__init__.py create mode 100644 tests/components/bluetooth_le_tracker/test_device_tracker.py diff --git a/.coveragerc b/.coveragerc index b0b9cc92fc4..71989964c6d 100644 --- a/.coveragerc +++ b/.coveragerc @@ -84,7 +84,6 @@ omit = homeassistant/components/blockchain/sensor.py homeassistant/components/bloomsky/* homeassistant/components/bluesound/* - homeassistant/components/bluetooth_le_tracker/device_tracker.py homeassistant/components/bluetooth_tracker/* homeassistant/components/bme280/sensor.py homeassistant/components/bme680/sensor.py diff --git a/homeassistant/components/bluetooth_le_tracker/device_tracker.py b/homeassistant/components/bluetooth_le_tracker/device_tracker.py index 523c40c8cfe..4957356d26a 100644 --- a/homeassistant/components/bluetooth_le_tracker/device_tracker.py +++ b/homeassistant/components/bluetooth_le_tracker/device_tracker.py @@ -44,23 +44,26 @@ def setup_scanner(hass, config, see, discovery_info=None): def see_device(address, name, new_device=False): """Mark a device as seen.""" - if new_device: - if address in new_devices: - new_devices[address] += 1 - _LOGGER.debug("Seen %s %s times", address, new_devices[address]) - if new_devices[address] >= MIN_SEEN_NEW: - _LOGGER.debug("Adding %s to tracked devices", address) - devs_to_track.append(address) - else: - return - else: - _LOGGER.debug("Seen %s for the first time", address) - new_devices[address] = 1 - return - if name is not None: name = name.strip("\x00") + if new_device: + if address in new_devices: + new_devices[address]["seen"] += 1 + if name: + new_devices[address]["name"] = name + else: + name = new_devices[address]["name"] + _LOGGER.debug("Seen %s %s times", address, new_devices[address]["seen"]) + if new_devices[address]["seen"] < MIN_SEEN_NEW: + return + _LOGGER.debug("Adding %s to tracked devices", address) + devs_to_track.append(address) + else: + _LOGGER.debug("Seen %s for the first time", address) + new_devices[address] = {"seen": 1, "name": name} + return + see( mac=BLE_PREFIX + address, host_name=name, diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 89feb7a7823..7c682b2bcda 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -428,6 +428,10 @@ pyfritzhome==0.4.0 # homeassistant.components.ifttt pyfttt==0.3 +# homeassistant.components.bluetooth_le_tracker +# homeassistant.components.skybeacon +pygatt[GATTTOOL]==4.0.5 + # homeassistant.components.version pyhaversion==3.1.0 diff --git a/tests/components/bluetooth_le_tracker/__init__.py b/tests/components/bluetooth_le_tracker/__init__.py new file mode 100644 index 00000000000..b071000936b --- /dev/null +++ b/tests/components/bluetooth_le_tracker/__init__.py @@ -0,0 +1 @@ +"""Tests for the Bluetooth LE tracker component.""" diff --git a/tests/components/bluetooth_le_tracker/test_device_tracker.py b/tests/components/bluetooth_le_tracker/test_device_tracker.py new file mode 100644 index 00000000000..308371c9aaa --- /dev/null +++ b/tests/components/bluetooth_le_tracker/test_device_tracker.py @@ -0,0 +1,56 @@ +"""Test Bluetooth LE device tracker.""" + +from datetime import timedelta +from unittest.mock import patch + +from homeassistant.components.bluetooth_le_tracker import device_tracker +from homeassistant.components.device_tracker.const import ( + CONF_SCAN_INTERVAL, + CONF_TRACK_NEW, + DOMAIN, +) +from homeassistant.const import CONF_PLATFORM +from homeassistant.setup import async_setup_component +from homeassistant.util import dt as dt_util, slugify + +from tests.common import async_fire_time_changed + + +async def test_preserve_new_tracked_device_name(hass, mock_device_tracker_conf): + """Test preserving tracked device name across new seens.""" + + address = "DE:AD:BE:EF:13:37" + name = "Mock device name" + entity_id = f"{DOMAIN}.{slugify(name)}" + + with patch( + "homeassistant.components." + "bluetooth_le_tracker.device_tracker.pygatt.GATTToolBackend" + ) as mock_backend, patch.object(device_tracker, "MIN_SEEN_NEW", 3): + + # Return with name when seen first time + device = {"address": address, "name": name} + mock_backend.return_value.scan.return_value = [device] + + config = { + CONF_PLATFORM: "bluetooth_le_tracker", + CONF_SCAN_INTERVAL: timedelta(minutes=1), + CONF_TRACK_NEW: True, + } + result = await async_setup_component(hass, DOMAIN, {DOMAIN: config}) + assert result + + # Seen once here; return without name when seen subsequent times + device["name"] = None + + # Tick until device seen enough times for to be registered for tracking + for _ in range(device_tracker.MIN_SEEN_NEW - 1): + async_fire_time_changed( + hass, + dt_util.utcnow() + config[CONF_SCAN_INTERVAL] + timedelta(seconds=1), + ) + await hass.async_block_till_done() + + state = hass.states.get(entity_id) + assert state + assert state.name == name