Remove deprecated horizontal vane select from Sensibo (#150108)

This commit is contained in:
G Johansson
2025-08-09 00:24:38 +02:00
committed by GitHub
parent f9e1c07c04
commit e9d39a826e
3 changed files with 33 additions and 200 deletions

View File

@@ -8,24 +8,11 @@ from typing import TYPE_CHECKING, Any
from pysensibo.model import SensiboDevice from pysensibo.model import SensiboDevice
from homeassistant.components.automation import automations_with_entity from homeassistant.components.select import SelectEntity, SelectEntityDescription
from homeassistant.components.script import scripts_with_entity
from homeassistant.components.select import (
DOMAIN as SELECT_DOMAIN,
SelectEntity,
SelectEntityDescription,
)
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.issue_registry import (
IssueSeverity,
async_create_issue,
async_delete_issue,
)
from . import SensiboConfigEntry from . import SensiboConfigEntry
from .const import DOMAIN
from .coordinator import SensiboDataUpdateCoordinator from .coordinator import SensiboDataUpdateCoordinator
from .entity import SensiboDeviceBaseEntity, async_handle_api_call from .entity import SensiboDeviceBaseEntity, async_handle_api_call
@@ -42,16 +29,6 @@ class SensiboSelectEntityDescription(SelectEntityDescription):
transformation: Callable[[SensiboDevice], dict | None] transformation: Callable[[SensiboDevice], dict | None]
HORIZONTAL_SWING_MODE_TYPE = SensiboSelectEntityDescription(
key="horizontalSwing",
data_key="horizontal_swing_mode",
value_fn=lambda data: data.horizontal_swing_mode,
options_fn=lambda data: data.horizontal_swing_modes,
translation_key="horizontalswing",
transformation=lambda data: data.horizontal_swing_modes_translated,
entity_registry_enabled_default=False,
)
DEVICE_SELECT_TYPES = ( DEVICE_SELECT_TYPES = (
SensiboSelectEntityDescription( SensiboSelectEntityDescription(
key="light", key="light",
@@ -73,43 +50,6 @@ async def async_setup_entry(
coordinator = entry.runtime_data coordinator = entry.runtime_data
entities: list[SensiboSelect] = []
entity_registry = er.async_get(hass)
for device_id, device_data in coordinator.data.parsed.items():
if entity_id := entity_registry.async_get_entity_id(
SELECT_DOMAIN, DOMAIN, f"{device_id}-horizontalSwing"
):
entity = entity_registry.async_get(entity_id)
if entity and entity.disabled:
entity_registry.async_remove(entity_id)
async_delete_issue(
hass,
DOMAIN,
"deprecated_entity_horizontalswing",
)
elif entity and HORIZONTAL_SWING_MODE_TYPE.key in device_data.full_features:
entities.append(
SensiboSelect(coordinator, device_id, HORIZONTAL_SWING_MODE_TYPE)
)
if automations_with_entity(hass, entity_id) or scripts_with_entity(
hass, entity_id
):
async_create_issue(
hass,
DOMAIN,
"deprecated_entity_horizontalswing",
breaks_in_ha_version="2025.8.0",
is_fixable=False,
severity=IssueSeverity.WARNING,
translation_key="deprecated_entity_horizontalswing",
translation_placeholders={
"name": str(entity.name or entity.original_name),
"entity": entity_id,
},
)
async_add_entities(entities)
added_devices: set[str] = set() added_devices: set[str] = set()
def _add_remove_devices() -> None: def _add_remove_devices() -> None:

View File

@@ -77,22 +77,6 @@
} }
}, },
"select": { "select": {
"horizontalswing": {
"name": "Horizontal swing",
"state": {
"stopped": "[%key:common::state::off%]",
"fixedleft": "Fixed left",
"fixedcenterleft": "Fixed center left",
"fixedcenter": "Fixed center",
"fixedcenterright": "Fixed center right",
"fixedright": "Fixed right",
"fixedleftright": "Fixed left right",
"rangecenter": "Range center",
"rangefull": "Range full",
"rangeleft": "Range left",
"rangeright": "Range right"
}
},
"light": { "light": {
"name": "[%key:component::light::title%]", "name": "[%key:component::light::title%]",
"state": { "state": {
@@ -153,14 +137,16 @@
"name": "Horizontal swing", "name": "Horizontal swing",
"state": { "state": {
"stopped": "[%key:common::state::off%]", "stopped": "[%key:common::state::off%]",
"fixedleft": "[%key:component::sensibo::entity::select::horizontalswing::state::fixedleft%]", "fixedleft": "Fixed left",
"fixedcenterleft": "[%key:component::sensibo::entity::select::horizontalswing::state::fixedcenterleft%]", "fixedcenterleft": "Fixed center left",
"fixedcenter": "[%key:component::sensibo::entity::select::horizontalswing::state::fixedcenter%]", "fixedcenter": "Fixed center",
"fixedcenterright": "[%key:component::sensibo::entity::select::horizontalswing::state::fixedcenterright%]", "fixedcenterright": "Fixed center right",
"fixedright": "[%key:component::sensibo::entity::select::horizontalswing::state::fixedright%]", "fixedright": "Fixed right",
"fixedleftright": "[%key:component::sensibo::entity::select::horizontalswing::state::fixedleftright%]", "fixedleftright": "Fixed left right",
"rangecenter": "[%key:component::sensibo::entity::select::horizontalswing::state::rangecenter%]", "rangecenter": "Range center",
"rangefull": "[%key:component::sensibo::entity::select::horizontalswing::state::rangefull%]" "rangefull": "Range full",
"rangeleft": "Range left",
"rangeright": "Range right"
} }
}, },
"light": { "light": {
@@ -239,14 +225,14 @@
"name": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::name%]", "name": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::name%]",
"state": { "state": {
"stopped": "[%key:common::state::off%]", "stopped": "[%key:common::state::off%]",
"fixedleft": "[%key:component::sensibo::entity::select::horizontalswing::state::fixedleft%]", "fixedleft": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::state::fixedleft%]",
"fixedcenterleft": "[%key:component::sensibo::entity::select::horizontalswing::state::fixedcenterleft%]", "fixedcenterleft": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::state::fixedcenterleft%]",
"fixedcenter": "[%key:component::sensibo::entity::select::horizontalswing::state::fixedcenter%]", "fixedcenter": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::state::fixedcenter%]",
"fixedcenterright": "[%key:component::sensibo::entity::select::horizontalswing::state::fixedcenterright%]", "fixedcenterright": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::state::fixedcenterright%]",
"fixedright": "[%key:component::sensibo::entity::select::horizontalswing::state::fixedright%]", "fixedright": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::state::fixedright%]",
"fixedleftright": "[%key:component::sensibo::entity::select::horizontalswing::state::fixedleftright%]", "fixedleftright": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::state::fixedleftright%]",
"rangecenter": "[%key:component::sensibo::entity::select::horizontalswing::state::rangecenter%]", "rangecenter": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::state::rangecenter%]",
"rangefull": "[%key:component::sensibo::entity::select::horizontalswing::state::rangefull%]" "rangefull": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::state::rangefull%]"
} }
}, },
"light": { "light": {
@@ -383,7 +369,7 @@
"rangetop": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::swing::state::rangetop%]", "rangetop": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::swing::state::rangetop%]",
"rangemiddle": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::swing::state::rangemiddle%]", "rangemiddle": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::swing::state::rangemiddle%]",
"rangebottom": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::swing::state::rangebottom%]", "rangebottom": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::swing::state::rangebottom%]",
"rangefull": "[%key:component::sensibo::entity::select::horizontalswing::state::rangefull%]", "rangefull": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::state::rangefull%]",
"horizontal": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::swing::state::horizontal%]", "horizontal": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::swing::state::horizontal%]",
"both": "[%key:component::climate::entity_component::_::state_attributes::swing_mode::state::both%]" "both": "[%key:component::climate::entity_component::_::state_attributes::swing_mode::state::both%]"
} }
@@ -391,16 +377,16 @@
"swing_horizontal_mode": { "swing_horizontal_mode": {
"state": { "state": {
"stopped": "[%key:common::state::off%]", "stopped": "[%key:common::state::off%]",
"fixedleft": "[%key:component::sensibo::entity::select::horizontalswing::state::fixedleft%]", "fixedleft": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::state::fixedleft%]",
"fixedcenterleft": "[%key:component::sensibo::entity::select::horizontalswing::state::fixedcenterleft%]", "fixedcenterleft": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::state::fixedcenterleft%]",
"fixedcenter": "[%key:component::sensibo::entity::select::horizontalswing::state::fixedcenter%]", "fixedcenter": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::state::fixedcenter%]",
"fixedcenterright": "[%key:component::sensibo::entity::select::horizontalswing::state::fixedcenterright%]", "fixedcenterright": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::state::fixedcenterright%]",
"fixedright": "[%key:component::sensibo::entity::select::horizontalswing::state::fixedright%]", "fixedright": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::state::fixedright%]",
"fixedleftright": "[%key:component::sensibo::entity::select::horizontalswing::state::fixedleftright%]", "fixedleftright": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::state::fixedleftright%]",
"rangecenter": "[%key:component::sensibo::entity::select::horizontalswing::state::rangecenter%]", "rangecenter": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::state::rangecenter%]",
"rangefull": "[%key:component::sensibo::entity::select::horizontalswing::state::rangefull%]", "rangefull": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::state::rangefull%]",
"rangeleft": "[%key:component::sensibo::entity::select::horizontalswing::state::rangeleft%]", "rangeleft": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::state::rangeleft%]",
"rangeright": "[%key:component::sensibo::entity::select::horizontalswing::state::rangeright%]" "rangeright": "[%key:component::sensibo::entity::sensor::climate_react_low::state_attributes::horizontalswing::state::rangeright%]"
} }
} }
} }
@@ -590,11 +576,5 @@
"mode_not_exist": { "mode_not_exist": {
"message": "The entity does not support the chosen mode" "message": "The entity does not support the chosen mode"
} }
},
"issues": {
"deprecated_entity_horizontalswing": {
"title": "The Sensibo {name} entity is deprecated",
"description": "The Sensibo entity `{entity}` is deprecated and will be removed in a future release.\nPlease update your automations and scripts to use the `horizontal_swing` attribute part of the `climate` entity instead.\nDisable `{entity}` and reload the config entry or restart Home Assistant to fix this issue."
}
} }
} }

View File

@@ -3,7 +3,7 @@
from __future__ import annotations from __future__ import annotations
from datetime import timedelta from datetime import timedelta
from unittest.mock import MagicMock, patch from unittest.mock import MagicMock
from freezegun.api import FrozenDateTimeFactory from freezegun.api import FrozenDateTimeFactory
import pytest import pytest
@@ -14,16 +14,13 @@ from homeassistant.components.select import (
DOMAIN as SELECT_DOMAIN, DOMAIN as SELECT_DOMAIN,
SERVICE_SELECT_OPTION, SERVICE_SELECT_OPTION,
) )
from homeassistant.components.sensibo.const import DOMAIN
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_ENTITY_ID, STATE_UNAVAILABLE, Platform from homeassistant.const import ATTR_ENTITY_ID, STATE_UNAVAILABLE, Platform
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import entity_registry as er, issue_registry as ir from homeassistant.helpers import entity_registry as er
from . import ENTRY_CONFIG from tests.common import async_fire_time_changed, snapshot_platform
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
@pytest.mark.parametrize( @pytest.mark.parametrize(
@@ -154,87 +151,3 @@ async def test_select_set_option(
state = hass.states.get("select.kitchen_light") state = hass.states.get("select.kitchen_light")
assert state.state == STATE_UNAVAILABLE assert state.state == STATE_UNAVAILABLE
@pytest.mark.parametrize(
"load_platforms",
[[Platform.SELECT]],
)
async def test_deprecated_horizontal_swing_select(
hass: HomeAssistant,
load_platforms: list[Platform],
mock_client: MagicMock,
entity_registry: er.EntityRegistry,
issue_registry: ir.IssueRegistry,
) -> None:
"""Test the deprecated horizontal swing select entity."""
config_entry = MockConfigEntry(
domain=DOMAIN,
data=ENTRY_CONFIG,
entry_id="1",
unique_id="firstnamelastname",
version=2,
)
config_entry.add_to_hass(hass)
entity_registry.async_get_or_create(
SELECT_DOMAIN,
DOMAIN,
"ABC999111-horizontalSwing",
config_entry=config_entry,
disabled_by=None,
has_entity_name=True,
suggested_object_id="hallway_horizontal_swing",
)
with patch("homeassistant.components.sensibo.PLATFORMS", load_platforms):
await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
state = hass.states.get("select.hallway_horizontal_swing")
assert state.state == "stopped"
# No issue created without automation or script
assert issue_registry.issues == {}
with (
patch("homeassistant.components.sensibo.PLATFORMS", load_platforms),
patch(
# Patch check for automation, that one exist
"homeassistant.components.sensibo.select.automations_with_entity",
return_value=["automation.test"],
),
):
await hass.config_entries.async_reload(config_entry.entry_id)
await hass.async_block_till_done(True)
# Issue is created when entity is enabled and automation/script exist
issue = issue_registry.async_get_issue(DOMAIN, "deprecated_entity_horizontalswing")
assert issue
assert issue.translation_key == "deprecated_entity_horizontalswing"
assert hass.states.get("select.hallway_horizontal_swing")
assert entity_registry.async_is_registered("select.hallway_horizontal_swing")
# Disabling the entity should remove the entity and remove the issue
# once the integration is reloaded
entity_registry.async_update_entity(
state.entity_id, disabled_by=er.RegistryEntryDisabler.USER
)
with (
patch("homeassistant.components.sensibo.PLATFORMS", load_platforms),
patch(
"homeassistant.components.sensibo.select.automations_with_entity",
return_value=["automation.test"],
),
):
await hass.config_entries.async_reload(config_entry.entry_id)
await hass.async_block_till_done(True)
# Disabling the entity and reloading has removed the entity and issue
assert not hass.states.get("select.hallway_horizontal_swing")
assert not entity_registry.async_is_registered("select.hallway_horizontal_swing")
issue = issue_registry.async_get_issue(DOMAIN, "deprecated_entity_horizontalswing")
assert not issue