Hide bluetooth passive option if its not available on the host system (#77421)

* Hide bluetooth passive option if its not available

- We now have a way to determine in advance if passive
  scanning is supported by BlueZ

* drop string
This commit is contained in:
J. Nick Koston 2022-08-27 18:18:54 -05:00 committed by GitHub
parent d25a76d3d6
commit a28aeeeca7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 87 additions and 28 deletions

View File

@ -1,7 +1,6 @@
"""Config flow to configure the Bluetooth integration."""
from __future__ import annotations
import platform
from typing import TYPE_CHECKING, Any, cast
import voluptuous as vol
@ -11,6 +10,7 @@ from homeassistant.config_entries import ConfigEntry, ConfigFlow, OptionsFlow
from homeassistant.core import callback
from homeassistant.helpers.typing import DiscoveryInfoType
from . import models
from .const import (
ADAPTER_ADDRESS,
CONF_ADAPTER,
@ -134,7 +134,7 @@ class BluetoothConfigFlow(ConfigFlow, domain=DOMAIN):
@callback
def async_supports_options_flow(cls, config_entry: ConfigEntry) -> bool:
"""Return options flow support for this handler."""
return platform.system() == "Linux"
return bool(models.MANAGER and models.MANAGER.supports_passive_scan)
class OptionsFlowHandler(OptionsFlow):

View File

@ -59,8 +59,10 @@ class AdapterDetails(TypedDict, total=False):
address: str
sw_version: str
hw_version: str
passive_scan: bool
ADAPTER_ADDRESS: Final = "address"
ADAPTER_SW_VERSION: Final = "sw_version"
ADAPTER_HW_VERSION: Final = "hw_version"
ADAPTER_PASSIVE_SCAN: Final = "passive_scan"

View File

@ -23,6 +23,7 @@ from homeassistant.helpers.event import async_track_time_interval
from .const import (
ADAPTER_ADDRESS,
ADAPTER_PASSIVE_SCAN,
STALE_ADVERTISEMENT_SECONDS,
UNAVAILABLE_TRACK_SECONDS,
AdapterDetails,
@ -147,6 +148,11 @@ class BluetoothManager:
self._connectable_scanners: list[BaseHaScanner] = []
self._adapters: dict[str, AdapterDetails] = {}
@property
def supports_passive_scan(self) -> bool:
"""Return if passive scan is supported."""
return any(adapter[ADAPTER_PASSIVE_SCAN] for adapter in self._adapters.values())
async def async_diagnostics(self) -> dict[str, Any]:
"""Diagnostics for the manager."""
scanner_diagnostics = await asyncio.gather(

View File

@ -29,9 +29,8 @@
"options": {
"step": {
"init": {
"description": "Passive listening requires BlueZ 5.63 or later with experimental features enabled.",
"data": {
"passive": "Passive listening"
"passive": "Passive scanning"
}
}
}

View File

@ -9,9 +9,6 @@
"bluetooth_confirm": {
"description": "Do you want to setup {name}?"
},
"enable_bluetooth": {
"description": "Do you want to setup Bluetooth?"
},
"multiple_adapters": {
"data": {
"adapter": "Adapter"
@ -33,10 +30,8 @@
"step": {
"init": {
"data": {
"adapter": "The Bluetooth Adapter to use for scanning",
"passive": "Passive listening"
},
"description": "Passive listening requires BlueZ 5.63 or later with experimental features enabled."
"passive": "Passive scanning"
}
}
}
}

View File

@ -24,6 +24,7 @@ async def async_get_bluetooth_adapters() -> dict[str, AdapterDetails]:
WINDOWS_DEFAULT_BLUETOOTH_ADAPTER: AdapterDetails(
address=DEFAULT_ADDRESS,
sw_version=platform.release(),
passive_scan=False,
)
}
if platform.system() == "Darwin":
@ -31,6 +32,7 @@ async def async_get_bluetooth_adapters() -> dict[str, AdapterDetails]:
MACOS_DEFAULT_BLUETOOTH_ADAPTER: AdapterDetails(
address=DEFAULT_ADDRESS,
sw_version=platform.release(),
passive_scan=False,
)
}
from bluetooth_adapters import ( # pylint: disable=import-outside-toplevel
@ -45,6 +47,7 @@ async def async_get_bluetooth_adapters() -> dict[str, AdapterDetails]:
address=adapter1["Address"],
sw_version=adapter1["Name"], # This is actually the BlueZ version
hw_version=adapter1["Modalias"],
passive_scan="org.bluez.AdvertisementMonitorManager1" in details,
)
return adapters

View File

@ -42,7 +42,11 @@ def one_adapter_fixture():
"Address": "00:00:00:00:00:01",
"Name": "BlueZ 4.63",
"Modalias": "usbid:1234",
}
},
"org.bluez.AdvertisementMonitorManager1": {
"SupportedMonitorTypes": ["or_patterns"],
"SupportedFeatures": [],
},
},
},
):
@ -74,7 +78,11 @@ def two_adapters_fixture():
"Address": "00:00:00:00:00:02",
"Name": "BlueZ 4.63",
"Modalias": "usbid:1234",
}
},
"org.bluez.AdvertisementMonitorManager1": {
"SupportedMonitorTypes": ["or_patterns"],
"SupportedFeatures": [],
},
},
},
):

View File

@ -17,6 +17,29 @@ from homeassistant.setup import async_setup_component
from tests.common import MockConfigEntry
async def test_options_flow_disabled_not_setup(
hass, hass_ws_client, mock_bleak_scanner_start, macos_adapter
):
"""Test options are disabled if the integration has not been setup."""
await async_setup_component(hass, "config", {})
entry = MockConfigEntry(
domain=DOMAIN, data={}, options={}, unique_id=DEFAULT_ADDRESS
)
entry.add_to_hass(hass)
ws_client = await hass_ws_client(hass)
await ws_client.send_json(
{
"id": 5,
"type": "config_entries/get",
"domain": "bluetooth",
"type_filter": "integration",
}
)
response = await ws_client.receive_json()
assert response["result"][0]["supports_options"] is False
async def test_async_step_user_macos(hass, macos_adapter):
"""Test setting up manually with one adapter on MacOS."""
result = await hass.config_entries.flow.async_init(
@ -287,19 +310,18 @@ async def test_options_flow_linux(hass, mock_bleak_scanner_start, one_adapter):
assert result["data"][CONF_PASSIVE] is False
@patch(
"homeassistant.components.bluetooth.config_flow.platform.system",
return_value="Darwin",
)
async def test_options_flow_disabled_macos(mock_system, hass, hass_ws_client):
async def test_options_flow_disabled_macos(
hass, hass_ws_client, mock_bleak_scanner_start, macos_adapter
):
"""Test options are disabled on MacOS."""
await async_setup_component(hass, "config", {})
entry = MockConfigEntry(
domain=DOMAIN,
data={},
options={},
domain=DOMAIN, data={}, options={}, unique_id=DEFAULT_ADDRESS
)
entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
ws_client = await hass_ws_client(hass)
await ws_client.send_json(
@ -314,19 +336,21 @@ async def test_options_flow_disabled_macos(mock_system, hass, hass_ws_client):
assert response["result"][0]["supports_options"] is False
@patch(
"homeassistant.components.bluetooth.config_flow.platform.system",
return_value="Linux",
)
async def test_options_flow_enabled_linux(mock_system, hass, hass_ws_client):
async def test_options_flow_enabled_linux(
hass, hass_ws_client, mock_bleak_scanner_start, one_adapter
):
"""Test options are enabled on Linux."""
await async_setup_component(hass, "config", {})
entry = MockConfigEntry(
domain=DOMAIN,
data={},
options={},
unique_id="00:00:00:00:00:01",
)
entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
ws_client = await hass_ws_client(hass)
await ws_client.send_json(

View File

@ -31,7 +31,16 @@ async def test_diagnostics(
return_value={
"org.bluez": {
"/org/bluez/hci0": {
"Interfaces": {"org.bluez.Adapter1": {"Discovering": False}}
"org.bluez.Adapter1": {
"Name": "BlueZ 5.63",
"Alias": "BlueZ 5.63",
"Modalias": "usb:v1D6Bp0246d0540",
"Discovering": False,
},
"org.bluez.AdvertisementMonitorManager1": {
"SupportedMonitorTypes": ["or_patterns"],
"SupportedFeatures": [],
},
}
}
},
@ -57,18 +66,29 @@ async def test_diagnostics(
"hci0": {
"address": "00:00:00:00:00:01",
"hw_version": "usbid:1234",
"passive_scan": False,
"sw_version": "BlueZ 4.63",
},
"hci1": {
"address": "00:00:00:00:00:02",
"hw_version": "usbid:1234",
"passive_scan": True,
"sw_version": "BlueZ 4.63",
},
},
"dbus": {
"org.bluez": {
"/org/bluez/hci0": {
"Interfaces": {"org.bluez.Adapter1": {"Discovering": False}}
"org.bluez.Adapter1": {
"Alias": "BlueZ " "5.63",
"Discovering": False,
"Modalias": "usb:v1D6Bp0246d0540",
"Name": "BlueZ " "5.63",
},
"org.bluez.AdvertisementMonitorManager1": {
"SupportedFeatures": [],
"SupportedMonitorTypes": ["or_patterns"],
},
}
}
},
@ -77,11 +97,13 @@ async def test_diagnostics(
"hci0": {
"address": "00:00:00:00:00:01",
"hw_version": "usbid:1234",
"passive_scan": False,
"sw_version": "BlueZ 4.63",
},
"hci1": {
"address": "00:00:00:00:00:02",
"hw_version": "usbid:1234",
"passive_scan": True,
"sw_version": "BlueZ 4.63",
},
},