Remove deprecated binary sensor in Husqvarna Automower (#144064)

* Remove deprecated binary sensor in Husqvarna Automower

* snapshot
This commit is contained in:
Thomas55555 2025-05-01 18:35:48 +02:00 committed by GitHub
parent bab699eb0c
commit 361d93eb96
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 10 additions and 205 deletions

View File

@ -3,29 +3,18 @@
from collections.abc import Callable
from dataclasses import dataclass
import logging
from typing import TYPE_CHECKING
from aioautomower.model import MowerActivities, MowerAttributes
from homeassistant.components.automation import automations_with_entity
from homeassistant.components.binary_sensor import (
DOMAIN as BINARY_SENSOR_DOMAIN,
BinarySensorDeviceClass,
BinarySensorEntity,
BinarySensorEntityDescription,
)
from homeassistant.components.script import scripts_with_entity
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.issue_registry import (
IssueSeverity,
async_create_issue,
async_delete_issue,
)
from . import AutomowerConfigEntry
from .const import DOMAIN
from .coordinator import AutomowerDataUpdateCoordinator
from .entity import AutomowerBaseEntity
@ -34,13 +23,6 @@ _LOGGER = logging.getLogger(__name__)
PARALLEL_UPDATES = 0
def entity_used_in(hass: HomeAssistant, entity_id: str) -> list[str]:
"""Get list of related automations and scripts."""
used_in = automations_with_entity(hass, entity_id)
used_in += scripts_with_entity(hass, entity_id)
return used_in
@dataclass(frozen=True, kw_only=True)
class AutomowerBinarySensorEntityDescription(BinarySensorEntityDescription):
"""Describes Automower binary sensor entity."""
@ -59,12 +41,6 @@ MOWER_BINARY_SENSOR_TYPES: tuple[AutomowerBinarySensorEntityDescription, ...] =
translation_key="leaving_dock",
value_fn=lambda data: data.mower.activity == MowerActivities.LEAVING,
),
AutomowerBinarySensorEntityDescription(
key="returning_to_dock",
translation_key="returning_to_dock",
value_fn=lambda data: data.mower.activity == MowerActivities.GOING_HOME,
entity_registry_enabled_default=False,
),
)
@ -107,39 +83,3 @@ class AutomowerBinarySensorEntity(AutomowerBaseEntity, BinarySensorEntity):
def is_on(self) -> bool:
"""Return the state of the binary sensor."""
return self.entity_description.value_fn(self.mower_attributes)
async def async_added_to_hass(self) -> None:
"""Raise issue when entity is registered and was not disabled."""
if TYPE_CHECKING:
assert self.unique_id
if not (
entity_id := er.async_get(self.hass).async_get_entity_id(
BINARY_SENSOR_DOMAIN, DOMAIN, self.unique_id
)
):
return
if (
self.enabled
and self.entity_description.key == "returning_to_dock"
and entity_used_in(self.hass, entity_id)
):
async_create_issue(
self.hass,
DOMAIN,
f"deprecated_entity_{self.entity_description.key}",
breaks_in_ha_version="2025.6.0",
is_fixable=False,
severity=IssueSeverity.WARNING,
translation_key="deprecated_entity",
translation_placeholders={
"entity_name": str(self.name),
"entity": entity_id,
},
)
else:
async_delete_issue(
self.hass,
DOMAIN,
f"deprecated_task_entity_{self.entity_description.key}",
)
await super().async_added_to_hass()

View File

@ -67,7 +67,9 @@ rules:
reconfiguration-flow:
status: exempt
comment: no configuration possible
repair-issues: done
repair-issues:
status: exempt
comment: no issues available
stale-devices: done
# Platinum

View File

@ -39,9 +39,6 @@
"binary_sensor": {
"leaving_dock": {
"name": "Leaving dock"
},
"returning_to_dock": {
"name": "Returning to dock"
}
},
"button": {
@ -323,12 +320,6 @@
}
}
},
"issues": {
"deprecated_entity": {
"title": "The Husqvarna Automower {entity_name} sensor is deprecated",
"description": "The Husqvarna Automower entity `{entity}` is deprecated and will be removed in a future release.\nYou can use the new returning state of the lawn mower entity instead.\nPlease update your automations and scripts to replace the sensor entity with the newly added lawn mower entity.\nWhen you are done migrating you can disable `{entity}`."
}
},
"services": {
"override_schedule": {
"name": "Override schedule",

View File

@ -94,53 +94,6 @@
'state': 'off',
})
# ---
# name: test_binary_sensor_snapshot[binary_sensor.test_mower_1_returning_to_dock-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': None,
'entity_id': 'binary_sensor.test_mower_1_returning_to_dock',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Returning to dock',
'platform': 'husqvarna_automower',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'returning_to_dock',
'unique_id': 'c7233734-b219-4287-a173-08e3643f89f0_returning_to_dock',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensor_snapshot[binary_sensor.test_mower_1_returning_to_dock-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Mower 1 Returning to dock',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.test_mower_1_returning_to_dock',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_binary_sensor_snapshot[binary_sensor.test_mower_2_charging-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
@ -236,50 +189,3 @@
'state': 'off',
})
# ---
# name: test_binary_sensor_snapshot[binary_sensor.test_mower_2_returning_to_dock-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': None,
'entity_id': 'binary_sensor.test_mower_2_returning_to_dock',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Returning to dock',
'platform': 'husqvarna_automower',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'returning_to_dock',
'unique_id': '1234_returning_to_dock',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensor_snapshot[binary_sensor.test_mower_2_returning_to_dock-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Test Mower 2 Returning to dock',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.test_mower_2_returning_to_dock',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---

View File

@ -2,54 +2,16 @@
from unittest.mock import AsyncMock, patch
from aioautomower.model import MowerActivities, MowerAttributes
from freezegun.api import FrozenDateTimeFactory
import pytest
from syrupy import SnapshotAssertion
from homeassistant.components.husqvarna_automower.coordinator import SCAN_INTERVAL
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from . import setup_integration
from .const import TEST_MOWER_ID
from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_binary_sensor_states(
hass: HomeAssistant,
mock_automower_client: AsyncMock,
mock_config_entry: MockConfigEntry,
freezer: FrozenDateTimeFactory,
values: dict[str, MowerAttributes],
) -> None:
"""Test binary sensor states."""
await setup_integration(hass, mock_config_entry)
state = hass.states.get("binary_sensor.test_mower_1_charging")
assert state is not None
assert state.state == "off"
state = hass.states.get("binary_sensor.test_mower_1_leaving_dock")
assert state is not None
assert state.state == "off"
state = hass.states.get("binary_sensor.test_mower_1_returning_to_dock")
assert state is not None
assert state.state == "off"
for activity, entity in (
(MowerActivities.CHARGING, "test_mower_1_charging"),
(MowerActivities.LEAVING, "test_mower_1_leaving_dock"),
(MowerActivities.GOING_HOME, "test_mower_1_returning_to_dock"),
):
values[TEST_MOWER_ID].mower.activity = activity
mock_automower_client.get_status.return_value = values
freezer.tick(SCAN_INTERVAL)
async_fire_time_changed(hass)
await hass.async_block_till_done()
state = hass.states.get(f"binary_sensor.{entity}")
assert state.state == "on"
from tests.common import MockConfigEntry, snapshot_platform
@pytest.mark.usefixtures("entity_registry_enabled_by_default")

View File

@ -33,6 +33,7 @@ from tests.test_util.aiohttp import AiohttpClientMocker
ADDITIONAL_NUMBER_ENTITIES = 1
ADDITIONAL_SENSOR_ENTITIES = 2
ADDITIONAL_SWITCH_ENTITIES = 1
NUMBER_OF_ENTITIES_MOWER_2 = 11
async def test_load_unload_entry(
@ -250,7 +251,7 @@ async def test_coordinator_automatic_registry_cleanup(
assert (
len(er.async_entries_for_config_entry(entity_registry, entry.entry_id))
== current_entites - 12
== current_entites - NUMBER_OF_ENTITIES_MOWER_2
)
assert (
len(dr.async_entries_for_config_entry(device_registry, entry.entry_id))
@ -278,7 +279,10 @@ async def test_coordinator_automatic_registry_cleanup(
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert len(er.async_entries_for_config_entry(entity_registry, entry.entry_id)) == 12
assert (
len(er.async_entries_for_config_entry(entity_registry, entry.entry_id))
== NUMBER_OF_ENTITIES_MOWER_2
)
assert (
len(dr.async_entries_for_config_entry(device_registry, entry.entry_id))
== current_devices - 1