Ensure remote bluetooth adapters are loaded before integrations that need them (#85723)

pull/85976/head
J. Nick Koston 2023-01-15 13:17:17 -10:00 committed by GitHub
parent cd31624768
commit 65ca62c991
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 103 additions and 31 deletions

View File

@ -156,6 +156,8 @@ build.json @home-assistant/supervisor
/homeassistant/components/bluesound/ @thrawnarn
/homeassistant/components/bluetooth/ @bdraco
/tests/components/bluetooth/ @bdraco
/homeassistant/components/bluetooth_adapters/ @bdraco
/tests/components/bluetooth_adapters/ @bdraco
/homeassistant/components/bmw_connected_drive/ @gerard33 @rikroe
/tests/components/bmw_connected_drive/ @gerard33 @rikroe
/homeassistant/components/bond/ @bdraco @prystupa @joshs85 @marciogranzotto

View File

@ -4,7 +4,7 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/airthings_ble",
"requirements": ["airthings-ble==0.5.3"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@vincegio"],
"iot_class": "local_polling",
"bluetooth": [

View File

@ -4,7 +4,7 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/aranet",
"requirements": ["aranet4==2.1.3"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@aschmitz"],
"iot_class": "local_push",
"integration_type": "device",

View File

@ -10,7 +10,7 @@
}
],
"requirements": ["bluemaestro-ble==0.2.1"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@bdraco"],
"iot_class": "local_push"
}

View File

@ -0,0 +1,20 @@
"""The Bluetooth Adapters integration."""
from __future__ import annotations
from homeassistant.core import HomeAssistant
from homeassistant.helpers.typing import ConfigType
DOMAIN = "bluetooth_adapters"
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up Bluetooth Adapters from a config entry.
This integration is only used as a dependency for other integrations
that need Bluetooth Adapters.
All integrations that provide Bluetooth Adapters must be listed
in after_dependencies in the manifest.json file to ensure
they are loaded before this integration.
"""
return True

View File

@ -0,0 +1,11 @@
{
"domain": "bluetooth_adapters",
"name": "Bluetooth Adapters",
"documentation": "https://www.home-assistant.io/integrations/bluetooth_adapters",
"dependencies": ["bluetooth"],
"after_dependencies": ["esphome", "shelly", "ruuvi_gateway"],
"quality_scale": "internal",
"codeowners": ["@bdraco"],
"iot_class": "local_push",
"integration_type": "system"
}

View File

@ -2,7 +2,7 @@
"domain": "bluetooth_le_tracker",
"name": "Bluetooth LE Tracker",
"documentation": "https://www.home-assistant.io/integrations/bluetooth_le_tracker",
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": [],
"iot_class": "local_push",
"loggers": []

View File

@ -18,7 +18,7 @@
}
],
"requirements": ["bthome-ble==2.5.0"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@Ernst79"],
"iot_class": "local_push"
}

View File

@ -3,7 +3,7 @@
"name": "eQ-3 Bluetooth Smart Thermostats",
"documentation": "https://www.home-assistant.io/integrations/eq3btsmart",
"requirements": ["construct==2.10.56", "python-eq3bt==0.2"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@rytilahti"],
"iot_class": "local_polling",
"loggers": ["bleak", "eq3bt"]

View File

@ -7,7 +7,7 @@
"codeowners": ["@elupus"],
"iot_class": "local_polling",
"loggers": ["bleak", "fjaraskupan"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"bluetooth": [
{
"connectable": false,

View File

@ -74,7 +74,7 @@
}
],
"requirements": ["govee-ble==0.21.0"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@bdraco", "@PierreAronnax"],
"iot_class": "local_push"
}

View File

@ -6,7 +6,7 @@
"requirements": ["aiohomekit==2.4.4"],
"zeroconf": ["_hap._tcp.local.", "_hap._udp.local."],
"bluetooth": [{ "manufacturer_id": 76, "manufacturer_data_start": [6] }],
"dependencies": ["bluetooth", "zeroconf"],
"dependencies": ["bluetooth_adapters", "zeroconf"],
"codeowners": ["@Jc2k", "@bdraco"],
"iot_class": "local_push",
"loggers": ["aiohomekit", "commentjson"]

View File

@ -2,7 +2,7 @@
"domain": "ibeacon",
"name": "iBeacon Tracker",
"documentation": "https://www.home-assistant.io/integrations/ibeacon",
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"bluetooth": [{ "manufacturer_id": 76, "manufacturer_data_start": [2, 21] }],
"requirements": ["ibeacon_ble==1.0.1"],
"codeowners": ["@bdraco"],

View File

@ -11,7 +11,7 @@
{ "local_name": "tps", "connectable": false }
],
"requirements": ["inkbird-ble==0.5.5"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@bdraco"],
"iot_class": "local_push"
}

View File

@ -10,7 +10,7 @@
}
],
"requirements": ["kegtron-ble==0.4.0"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@Ernst79"],
"iot_class": "local_push"
}

View File

@ -14,6 +14,6 @@
"codeowners": ["@spycle"],
"requirements": ["PyMicroBot==0.0.8"],
"iot_class": "assumed_state",
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"loggers": ["keymitt_ble"]
}

View File

@ -4,7 +4,7 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/ld2410_ble/",
"requirements": ["bluetooth-data-tools==0.3.1", "ld2410-ble==0.1.1"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@930913"],
"bluetooth": [{ "local_name": "HLK-LD2410B_*" }],
"integration_type": "device",

View File

@ -4,7 +4,7 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/led_ble/",
"requirements": ["bluetooth-data-tools==0.3.1", "led-ble==1.0.0"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@bdraco"],
"bluetooth": [
{ "local_name": "LEDnet*" },

View File

@ -1,11 +1,11 @@
{
"after_dependencies": ["bluetooth"],
"bluetooth": [
{
"manufacturer_data_start": [89],
"manufacturer_id": 13
}
],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@vanstinator"],
"config_flow": true,
"domain": "melnor",

View File

@ -5,7 +5,7 @@
"documentation": "https://www.home-assistant.io/integrations/moat",
"bluetooth": [{ "local_name": "Moat_S*", "connectable": false }],
"requirements": ["moat-ble==0.1.1"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@bdraco"],
"iot_class": "local_push"
}

View File

@ -9,7 +9,7 @@
}
],
"requirements": ["oralb-ble==0.17.1"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@bdraco", "@conway20"],
"iot_class": "local_push"
}

View File

@ -12,7 +12,7 @@
}
],
"requirements": ["qingping-ble==0.8.2"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@bdraco", "@skgsergio"],
"iot_class": "local_push"
}

View File

@ -4,6 +4,7 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/ruuvi_gateway",
"codeowners": ["@akx"],
"dependencies": ["bluetooth"],
"requirements": ["aioruuvigateway==0.0.2"],
"iot_class": "local_polling",
"dhcp": [

View File

@ -14,7 +14,7 @@
}
],
"requirements": ["ruuvitag-ble==0.1.1"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@akx"],
"iot_class": "local_push"
}

View File

@ -14,7 +14,7 @@
}
],
"requirements": ["sensirion-ble==0.0.1"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@akx"],
"iot_class": "local_push"
}

View File

@ -16,7 +16,7 @@
}
],
"requirements": ["sensorpro-ble==0.5.1"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@bdraco"],
"iot_class": "local_push"
}

View File

@ -10,7 +10,7 @@
}
],
"requirements": ["sensorpush-ble==1.5.2"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@bdraco"],
"iot_class": "local_push"
}

View File

@ -4,7 +4,7 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/snooz",
"requirements": ["pysnooz==0.8.3"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@AustinBrunkhorst"],
"bluetooth": [
{

View File

@ -4,7 +4,7 @@
"documentation": "https://www.home-assistant.io/integrations/switchbot",
"requirements": ["PySwitchbot==0.36.4"],
"config_flow": true,
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": [
"@bdraco",
"@danielhiversen",

View File

@ -37,7 +37,7 @@
{ "local_name": "ThermoBeacon", "connectable": false }
],
"requirements": ["thermobeacon-ble==0.6.0"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@bdraco"],
"iot_class": "local_push"
}

View File

@ -7,7 +7,7 @@
{ "local_name": "TP35*", "connectable": false },
{ "local_name": "TP39*", "connectable": false }
],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"requirements": ["thermopro-ble==0.4.3"],
"codeowners": ["@bdraco"],
"iot_class": "local_push"

View File

@ -10,7 +10,7 @@
}
],
"requirements": ["tilt-ble==0.2.3"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@apt-itude"],
"iot_class": "local_push"
}

View File

@ -14,7 +14,7 @@
}
],
"requirements": ["xiaomi-ble==0.14.3"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@Jc2k", "@Ernst79"],
"iot_class": "local_push"
}

View File

@ -4,7 +4,7 @@
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/yalexs_ble",
"requirements": ["yalexs-ble==1.12.5"],
"dependencies": ["bluetooth"],
"dependencies": ["bluetooth_adapters"],
"codeowners": ["@bdraco"],
"bluetooth": [
{

View File

@ -163,6 +163,12 @@ def calc_allowed_references(integration: Integration) -> set[str]:
| set(manifest.get("dependencies", []))
| set(manifest.get("after_dependencies", []))
)
# bluetooth_adapters is a wrapper to ensure
# that all the integrations that provide bluetooth
# adapters are setup before loading integrations
# that use them.
if "bluetooth_adapters" in allowed_references:
allowed_references.add("bluetooth")
# Discovery requirements are ok if referenced in manifest
for check_domain, to_check in DISCOVERY_INTEGRATIONS.items():

View File

@ -0,0 +1 @@
"""Tests for the Bluetooth Adapters integration."""

View File

@ -0,0 +1,8 @@
"""bluetooth_adapters session fixtures."""
import pytest
@pytest.fixture(autouse=True)
def mock_bluetooth(enable_bluetooth):
"""Auto mock bluetooth."""

View File

@ -0,0 +1,10 @@
"""Test the Bluetooth Adapters setup."""
from homeassistant.components.bluetooth_adapters import DOMAIN
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
async def test_setup(hass: HomeAssistant) -> None:
"""Ensure we can setup."""
assert await async_setup_component(hass, DOMAIN, {})

View File

@ -1,11 +1,11 @@
"""Tests for the melnor integration."""
from __future__ import annotations
from unittest.mock import AsyncMock, patch
from bleak.backends.device import BLEDevice
from melnor_bluetooth.device import Device
import pytest
from homeassistant.components.bluetooth.models import BluetoothServiceInfoBleak
from homeassistant.components.melnor.const import DOMAIN
@ -52,6 +52,11 @@ FAKE_SERVICE_INFO_2 = BluetoothServiceInfoBleak(
)
@pytest.fixture(autouse=True)
def mock_bluetooth(enable_bluetooth):
"""Auto mock bluetooth."""
class MockedValve:
"""Mocked class for a Valve."""

View File

@ -0,0 +1,8 @@
"""ruuvi_gateway session fixtures."""
import pytest
@pytest.fixture(autouse=True)
def mock_bluetooth(enable_bluetooth):
"""Auto mock bluetooth."""