Disable sky connect config entry if USB stick is not plugged in (#84975)

* Disable sky connect config entry if USB stick is not plugged in

* Remove debug stuff
This commit is contained in:
Erik Montnemery 2023-01-02 22:24:59 +01:00 committed by GitHub
parent 1724fcc150
commit 472c23d35f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 8 deletions

View file

@ -15,7 +15,7 @@ from homeassistant.components.homeassistant_hardware.silabs_multiprotocol_addon
get_addon_manager,
get_zigbee_socket,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.config_entries import ConfigEntry, ConfigEntryDisabler
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
@ -75,7 +75,12 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
if not usb.async_is_plugged_in(hass, matcher):
# The USB dongle is not plugged in
raise ConfigEntryNotReady
hass.async_create_task(
hass.config_entries.async_set_disabled_by(
entry.entry_id, ConfigEntryDisabler.INTEGRATION
)
)
return False
addon_info = await _multi_pan_addon_info(hass, entry)

View file

@ -5,7 +5,7 @@ from typing import Any
from homeassistant.components import usb
from homeassistant.components.homeassistant_hardware import silabs_multiprotocol_addon
from homeassistant.config_entries import ConfigEntry, ConfigFlow
from homeassistant.config_entries import ConfigEntry, ConfigEntryDisabler, ConfigFlow
from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult
@ -35,7 +35,12 @@ class HomeAssistantSkyConnectConfigFlow(ConfigFlow, domain=DOMAIN):
manufacturer = discovery_info.manufacturer
description = discovery_info.description
unique_id = f"{vid}:{pid}_{serial_number}_{manufacturer}_{description}"
if await self.async_set_unique_id(unique_id):
if existing_entry := await self.async_set_unique_id(unique_id):
# Re-enable existing config entry which was disabled by USB unplug
if existing_entry.disabled_by == ConfigEntryDisabler.INTEGRATION:
await self.hass.config_entries.async_set_disabled_by(
existing_entry.entry_id, None
)
self._abort_if_unique_id_configured(updates={"device": device})
return self.async_create_entry(
title="Home Assistant Sky Connect",

View file

@ -163,6 +163,7 @@ class ConfigEntryChange(StrEnum):
class ConfigEntryDisabler(StrEnum):
"""What disabled a config entry."""
INTEGRATION = "integration"
USER = "user"

View file

@ -5,11 +5,12 @@ from unittest.mock import MagicMock, Mock, patch
import pytest
from homeassistant.components import zha
from homeassistant.components import usb, zha
from homeassistant.components.hassio.handler import HassioAPIError
from homeassistant.components.homeassistant_sky_connect.const import DOMAIN
from homeassistant.config_entries import ConfigEntryState
from homeassistant.config_entries import ConfigEntryDisabler, ConfigEntryState
from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType
from tests.common import MockConfigEntry
@ -244,14 +245,22 @@ async def test_setup_zha_multipan_other_device(
assert config_entry.title == CONFIG_ENTRY_DATA["description"]
async def test_setup_entry_wait_usb(hass: HomeAssistant) -> None:
async def test_setup_entry_wait_usb(
mock_zha_config_flow_setup, hass: HomeAssistant
) -> None:
"""Test setup of a config entry when the dongle is not plugged in."""
# Setup the config entry
vid = CONFIG_ENTRY_DATA["vid"]
pid = CONFIG_ENTRY_DATA["device"]
serial_number = CONFIG_ENTRY_DATA["serial_number"]
manufacturer = CONFIG_ENTRY_DATA["manufacturer"]
description = CONFIG_ENTRY_DATA["description"]
config_entry = MockConfigEntry(
data=CONFIG_ENTRY_DATA,
domain=DOMAIN,
options={},
title="Home Assistant Sky Connect",
unique_id=f"{vid}:{pid}_{serial_number}_{manufacturer}_{description}",
)
config_entry.add_to_hass(hass)
with patch(
@ -261,7 +270,31 @@ async def test_setup_entry_wait_usb(hass: HomeAssistant) -> None:
assert not await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
assert len(mock_is_plugged_in.mock_calls) == 1
assert config_entry.state == ConfigEntryState.SETUP_RETRY
assert config_entry.disabled_by == ConfigEntryDisabler.INTEGRATION
assert config_entry.state == ConfigEntryState.NOT_LOADED
# USB dongle plugged in
usb_data = usb.UsbServiceInfo(
device=CONFIG_ENTRY_DATA["device"],
vid=CONFIG_ENTRY_DATA["vid"],
pid=CONFIG_ENTRY_DATA["device"],
serial_number=CONFIG_ENTRY_DATA["serial_number"],
manufacturer=CONFIG_ENTRY_DATA["manufacturer"],
description=CONFIG_ENTRY_DATA["description"],
)
with patch(
"homeassistant.components.homeassistant_sky_connect.usb.async_is_plugged_in",
return_value=True,
) as mock_is_plugged_in, patch(
"homeassistant.components.onboarding.async_is_onboarded", return_value=True
):
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": "usb"}, data=usb_data
)
assert result["type"] == FlowResultType.ABORT
assert config_entry.disabled_by is None
assert config_entry.state == ConfigEntryState.LOADED
async def test_setup_entry_addon_info_fails(