Add a repair issue for Yale Home users using the August integration (#124895)
The Yale Home brand will stop working with the August integration very soon. Users must migrate to the Yale integration to avoid an interruption in service.pull/124880/head
parent
ee9e3fe27b
commit
8ab8f7a740
|
@ -6,15 +6,16 @@ from pathlib import Path
|
||||||
from typing import cast
|
from typing import cast
|
||||||
|
|
||||||
from aiohttp import ClientResponseError
|
from aiohttp import ClientResponseError
|
||||||
|
from yalexs.const import Brand
|
||||||
from yalexs.exceptions import AugustApiAIOHTTPError
|
from yalexs.exceptions import AugustApiAIOHTTPError
|
||||||
from yalexs.manager.exceptions import CannotConnect, InvalidAuth, RequireValidation
|
from yalexs.manager.exceptions import CannotConnect, InvalidAuth, RequireValidation
|
||||||
from yalexs.manager.gateway import Config as YaleXSConfig
|
from yalexs.manager.gateway import Config as YaleXSConfig
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
||||||
from homeassistant.helpers import device_registry as dr
|
from homeassistant.helpers import device_registry as dr, issue_registry as ir
|
||||||
|
|
||||||
from .const import DOMAIN, PLATFORMS
|
from .const import DOMAIN, PLATFORMS
|
||||||
from .data import AugustData
|
from .data import AugustData
|
||||||
|
@ -24,6 +25,26 @@ from .util import async_create_august_clientsession
|
||||||
type AugustConfigEntry = ConfigEntry[AugustData]
|
type AugustConfigEntry = ConfigEntry[AugustData]
|
||||||
|
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _async_create_yale_brand_migration_issue(
|
||||||
|
hass: HomeAssistant, entry: AugustConfigEntry
|
||||||
|
) -> None:
|
||||||
|
"""Create an issue for a brand migration."""
|
||||||
|
ir.async_create_issue(
|
||||||
|
hass,
|
||||||
|
DOMAIN,
|
||||||
|
"yale_brand_migration",
|
||||||
|
breaks_in_ha_version="2024.9",
|
||||||
|
learn_more_url="https://www.home-assistant.io/integrations/yale",
|
||||||
|
translation_key="yale_brand_migration",
|
||||||
|
is_fixable=False,
|
||||||
|
severity=ir.IssueSeverity.CRITICAL,
|
||||||
|
translation_placeholders={
|
||||||
|
"migrate_url": "https://my.home-assistant.io/redirect/config_flow_start?domain=yale"
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: AugustConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: AugustConfigEntry) -> bool:
|
||||||
"""Set up August from a config entry."""
|
"""Set up August from a config entry."""
|
||||||
session = async_create_august_clientsession(hass)
|
session = async_create_august_clientsession(hass)
|
||||||
|
@ -40,6 +61,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: AugustConfigEntry) -> bo
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
async def async_remove_entry(hass: HomeAssistant, entry: AugustConfigEntry) -> None:
|
||||||
|
"""Remove an August config entry."""
|
||||||
|
ir.async_delete_issue(hass, DOMAIN, "yale_brand_migration")
|
||||||
|
|
||||||
|
|
||||||
async def async_unload_entry(hass: HomeAssistant, entry: AugustConfigEntry) -> bool:
|
async def async_unload_entry(hass: HomeAssistant, entry: AugustConfigEntry) -> bool:
|
||||||
"""Unload a config entry."""
|
"""Unload a config entry."""
|
||||||
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||||
|
@ -51,6 +77,8 @@ async def async_setup_august(
|
||||||
"""Set up the August component."""
|
"""Set up the August component."""
|
||||||
config = cast(YaleXSConfig, entry.data)
|
config = cast(YaleXSConfig, entry.data)
|
||||||
await august_gateway.async_setup(config)
|
await august_gateway.async_setup(config)
|
||||||
|
if august_gateway.api.brand == Brand.YALE_HOME:
|
||||||
|
_async_create_yale_brand_migration_issue(hass, entry)
|
||||||
await august_gateway.async_authenticate()
|
await august_gateway.async_authenticate()
|
||||||
await august_gateway.async_refresh_access_token_if_needed()
|
await august_gateway.async_refresh_access_token_if_needed()
|
||||||
data = entry.runtime_data = AugustData(hass, august_gateway)
|
data = entry.runtime_data = AugustData(hass, august_gateway)
|
||||||
|
|
|
@ -9,7 +9,7 @@ from typing import Any
|
||||||
import aiohttp
|
import aiohttp
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
from yalexs.authenticator_common import ValidationResult
|
from yalexs.authenticator_common import ValidationResult
|
||||||
from yalexs.const import BRANDS_WITHOUT_OAUTH, DEFAULT_BRAND
|
from yalexs.const import BRANDS_WITHOUT_OAUTH, DEFAULT_BRAND, Brand
|
||||||
from yalexs.manager.exceptions import CannotConnect, InvalidAuth, RequireValidation
|
from yalexs.manager.exceptions import CannotConnect, InvalidAuth, RequireValidation
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
||||||
|
@ -28,6 +28,12 @@ from .const import (
|
||||||
from .gateway import AugustGateway
|
from .gateway import AugustGateway
|
||||||
from .util import async_create_august_clientsession
|
from .util import async_create_august_clientsession
|
||||||
|
|
||||||
|
# The Yale Home Brand is not supported by the August integration
|
||||||
|
# anymore and should migrate to the Yale integration
|
||||||
|
AVAILABLE_BRANDS = BRANDS_WITHOUT_OAUTH.copy()
|
||||||
|
del AVAILABLE_BRANDS[Brand.YALE_HOME]
|
||||||
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -118,7 +124,7 @@ class AugustConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||||
vol.Required(
|
vol.Required(
|
||||||
CONF_BRAND,
|
CONF_BRAND,
|
||||||
default=self._user_auth_details.get(CONF_BRAND, DEFAULT_BRAND),
|
default=self._user_auth_details.get(CONF_BRAND, DEFAULT_BRAND),
|
||||||
): vol.In(BRANDS_WITHOUT_OAUTH),
|
): vol.In(AVAILABLE_BRANDS),
|
||||||
vol.Required(
|
vol.Required(
|
||||||
CONF_LOGIN_METHOD,
|
CONF_LOGIN_METHOD,
|
||||||
default=self._user_auth_details.get(
|
default=self._user_auth_details.get(
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
{
|
{
|
||||||
|
"issues": {
|
||||||
|
"yale_brand_migration": {
|
||||||
|
"title": "Yale Home has a new integration",
|
||||||
|
"description": "Add the [Yale integration]({migrate_url}), and remove the August integration as soon as possible to avoid an interruption in service. The Yale Home brand will stop working with the August integration soon and will be removed in a future release."
|
||||||
|
}
|
||||||
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"error": {
|
"error": {
|
||||||
"unhandled": "Unhandled error: {error}",
|
"unhandled": "Unhandled error: {error}",
|
||||||
|
|
|
@ -385,7 +385,7 @@ async def test_switching_brands(hass: HomeAssistant) -> None:
|
||||||
result2 = await hass.config_entries.flow.async_configure(
|
result2 = await hass.config_entries.flow.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
{
|
{
|
||||||
CONF_BRAND: "yale_home",
|
CONF_BRAND: "yale_access",
|
||||||
CONF_LOGIN_METHOD: "email",
|
CONF_LOGIN_METHOD: "email",
|
||||||
CONF_USERNAME: "my@email.tld",
|
CONF_USERNAME: "my@email.tld",
|
||||||
CONF_PASSWORD: "test-password",
|
CONF_PASSWORD: "test-password",
|
||||||
|
@ -396,4 +396,4 @@ async def test_switching_brands(hass: HomeAssistant) -> None:
|
||||||
assert result2["type"] is FlowResultType.ABORT
|
assert result2["type"] is FlowResultType.ABORT
|
||||||
assert result2["reason"] == "reauth_successful"
|
assert result2["reason"] == "reauth_successful"
|
||||||
assert len(mock_setup_entry.mock_calls) == 1
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
assert entry.data[CONF_BRAND] == "yale_home"
|
assert entry.data[CONF_BRAND] == "yale_access"
|
||||||
|
|
|
@ -5,6 +5,7 @@ from unittest.mock import Mock, patch
|
||||||
from aiohttp import ClientResponseError
|
from aiohttp import ClientResponseError
|
||||||
import pytest
|
import pytest
|
||||||
from yalexs.authenticator_common import AuthenticationState
|
from yalexs.authenticator_common import AuthenticationState
|
||||||
|
from yalexs.const import Brand
|
||||||
from yalexs.exceptions import AugustApiAIOHTTPError
|
from yalexs.exceptions import AugustApiAIOHTTPError
|
||||||
|
|
||||||
from homeassistant.components.august.const import DOMAIN
|
from homeassistant.components.august.const import DOMAIN
|
||||||
|
@ -20,7 +21,11 @@ from homeassistant.const import (
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
from homeassistant.helpers import (
|
||||||
|
device_registry as dr,
|
||||||
|
entity_registry as er,
|
||||||
|
issue_registry as ir,
|
||||||
|
)
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from .mocks import (
|
from .mocks import (
|
||||||
|
@ -420,3 +425,24 @@ async def test_device_remove_devices(
|
||||||
)
|
)
|
||||||
response = await client.remove_device(dead_device_entry.id, config_entry.entry_id)
|
response = await client.remove_device(dead_device_entry.id, config_entry.entry_id)
|
||||||
assert response["success"]
|
assert response["success"]
|
||||||
|
|
||||||
|
|
||||||
|
async def test_brand_migration_issue(hass: HomeAssistant) -> None:
|
||||||
|
"""Test creating and removing the brand migration issue."""
|
||||||
|
august_operative_lock = await _mock_operative_august_lock_detail(hass)
|
||||||
|
config_entry = await _create_august_with_devices(
|
||||||
|
hass, [august_operative_lock], brand=Brand.YALE_HOME
|
||||||
|
)
|
||||||
|
|
||||||
|
assert config_entry.state is ConfigEntryState.LOADED
|
||||||
|
|
||||||
|
issue_reg = ir.async_get(hass)
|
||||||
|
issue_entry = issue_reg.async_get_issue(DOMAIN, "yale_brand_migration")
|
||||||
|
assert issue_entry
|
||||||
|
assert issue_entry.severity == ir.IssueSeverity.CRITICAL
|
||||||
|
assert issue_entry.translation_placeholders == {
|
||||||
|
"migrate_url": "https://my.home-assistant.io/redirect/config_flow_start?domain=yale"
|
||||||
|
}
|
||||||
|
|
||||||
|
await hass.config_entries.async_remove(config_entry.entry_id)
|
||||||
|
assert not issue_reg.async_get_issue(DOMAIN, "yale_brand_migration")
|
||||||
|
|
Loading…
Reference in New Issue