Deprecate media player sensors for SmartThings (#141469)

* Deprecate media player sensors for SmartThings

* Deprecate media player sensors
This commit is contained in:
Joost Lekkerkerker 2025-03-26 18:21:49 +01:00 committed by GitHub
parent c8ab5bc796
commit fe99c39e25
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 51 additions and 25 deletions

View File

@ -7,7 +7,7 @@ from dataclasses import dataclass
from datetime import datetime
from typing import Any, cast
from pysmartthings import Attribute, Capability, SmartThings, Status
from pysmartthings import Attribute, Capability, ComponentStatus, SmartThings, Status
from homeassistant.components.automation import automations_with_entity
from homeassistant.components.script import scripts_with_entity
@ -140,6 +140,7 @@ class SmartThingsSensorEntityDescription(SensorEntityDescription):
options_attribute: Attribute | None = None
exists_fn: Callable[[Status], bool] | None = None
use_temperature_unit: bool = False
deprecated: Callable[[ComponentStatus], str | None] | None = None
CAPABILITY_TO_SENSORS: dict[
@ -196,6 +197,17 @@ CAPABILITY_TO_SENSORS: dict[
key=Attribute.VOLUME,
translation_key="audio_volume",
native_unit_of_measurement=PERCENTAGE,
deprecated=(
lambda status: "media_player"
if all(
capability in status
for capability in (
Capability.AUDIO_MUTE,
Capability.MEDIA_PLAYBACK,
)
)
else None
),
)
]
},
@ -319,6 +331,7 @@ CAPABILITY_TO_SENSORS: dict[
translation_key="dryer_machine_state",
options=WASHER_OPTIONS,
device_class=SensorDeviceClass.ENUM,
deprecated=lambda _: "machine_state",
)
],
Attribute.DRYER_JOB_STATE: [
@ -470,6 +483,7 @@ CAPABILITY_TO_SENSORS: dict[
device_class=SensorDeviceClass.ENUM,
options_attribute=Attribute.SUPPORTED_INPUT_SOURCES,
value_fn=lambda value: value.lower() if value else None,
deprecated=lambda _: "media_player",
)
]
},
@ -478,6 +492,7 @@ CAPABILITY_TO_SENSORS: dict[
SmartThingsSensorEntityDescription(
key=Attribute.PLAYBACK_REPEAT_MODE,
translation_key="media_playback_repeat",
deprecated=lambda _: "media_player",
)
]
},
@ -486,6 +501,7 @@ CAPABILITY_TO_SENSORS: dict[
SmartThingsSensorEntityDescription(
key=Attribute.PLAYBACK_SHUFFLE,
translation_key="media_playback_shuffle",
deprecated=lambda _: "media_player",
)
]
},
@ -504,6 +520,7 @@ CAPABILITY_TO_SENSORS: dict[
],
device_class=SensorDeviceClass.ENUM,
value_fn=lambda value: MEDIA_PLAYBACK_STATE_MAP.get(value, value),
deprecated=lambda _: "media_player",
)
]
},
@ -949,6 +966,7 @@ CAPABILITY_TO_SENSORS: dict[
translation_key="washer_machine_state",
options=WASHER_OPTIONS,
device_class=SensorDeviceClass.ENUM,
deprecated=lambda _: "machine_state",
)
],
Attribute.WASHER_JOB_STATE: [
@ -1102,13 +1120,9 @@ class SmartThingsSensor(SmartThingsEntity, SensorEntity):
"""Call when entity is added to hass."""
await super().async_added_to_hass()
if (
self.capability
not in {
Capability.DISHWASHER_OPERATING_STATE,
Capability.DRYER_OPERATING_STATE,
Capability.WASHER_OPERATING_STATE,
}
or self._attribute is not Attribute.MACHINE_STATE
not self.entity_description.deprecated
or (reason := self.entity_description.deprecated(self.device.status[MAIN]))
is None
):
return
automations = automations_with_entity(self.hass, self.entity_id)
@ -1130,11 +1144,11 @@ class SmartThingsSensor(SmartThingsEntity, SensorEntity):
async_create_issue(
self.hass,
DOMAIN,
f"deprecated_machine_state_{self.entity_id}",
f"deprecated_{reason}_{self.entity_id}",
breaks_in_ha_version="2025.10.0",
is_fixable=False,
severity=IssueSeverity.WARNING,
translation_key="deprecated_machine_state",
translation_key=f"deprecated_{reason}",
translation_placeholders={
"entity": self.entity_id,
"items": "\n".join(items_list),
@ -1145,15 +1159,9 @@ class SmartThingsSensor(SmartThingsEntity, SensorEntity):
"""Call when entity will be removed from hass."""
await super().async_will_remove_from_hass()
if (
self.capability
not in {
Capability.DISHWASHER_OPERATING_STATE,
Capability.DRYER_OPERATING_STATE,
Capability.WASHER_OPERATING_STATE,
}
or self._attribute is not Attribute.MACHINE_STATE
not self.entity_description.deprecated
or (reason := self.entity_description.deprecated(self.device.status[MAIN]))
is None
):
return
async_delete_issue(
self.hass, DOMAIN, f"deprecated_machine_state_{self.entity_id}"
)
async_delete_issue(self.hass, DOMAIN, f"deprecated_{reason}_{self.entity_id}")

View File

@ -494,6 +494,10 @@
"deprecated_switch_appliance": {
"title": "Deprecated switch detected in some automations or scripts",
"description": "The switch `{entity}` is deprecated because the actions did not work, so it has been replaced with a binary sensor instead.\n\nThe switch was used in the following automations or scripts:\n{items}\n\nPlease use them in the above automations or scripts to fix this issue."
},
"deprecated_media_player": {
"title": "Deprecated sensor detected in some automations or scripts",
"description": "The sensor `{entity}` is deprecated because it has been replaced with a media player entity.\n\nThe sensor was used in the following automations or scripts:\n{items}\n\nPlease use the media player entity in the above automations or scripts to fix this issue."
}
}
}

View File

@ -58,10 +58,23 @@ async def test_state_update(
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
@pytest.mark.parametrize(
("device_fixture", "entity_id"),
("device_fixture", "entity_id", "translation_key"),
[
("da_wm_wm_000001", "sensor.washer_machine_state"),
("da_wm_wd_000001", "sensor.dryer_machine_state"),
("da_wm_wm_000001", "sensor.washer_machine_state", "machine_state"),
("da_wm_wd_000001", "sensor.dryer_machine_state", "machine_state"),
("hw_q80r_soundbar", "sensor.soundbar_volume", "media_player"),
("hw_q80r_soundbar", "sensor.soundbar_media_playback_status", "media_player"),
("hw_q80r_soundbar", "sensor.soundbar_media_input_source", "media_player"),
(
"im_speaker_ai_0001",
"sensor.galaxy_home_mini_media_playback_shuffle",
"media_player",
),
(
"im_speaker_ai_0001",
"sensor.galaxy_home_mini_media_playback_repeat",
"media_player",
),
],
)
async def test_create_issue(
@ -70,9 +83,10 @@ async def test_create_issue(
mock_config_entry: MockConfigEntry,
issue_registry: ir.IssueRegistry,
entity_id: str,
translation_key: str,
) -> None:
"""Test we create an issue when an automation or script is using a deprecated entity."""
issue_id = f"deprecated_machine_state_{entity_id}"
issue_id = f"deprecated_{translation_key}_{entity_id}"
assert await async_setup_component(
hass,
@ -117,7 +131,7 @@ async def test_create_issue(
assert len(issue_registry.issues) == 1
issue = issue_registry.async_get_issue(DOMAIN, issue_id)
assert issue is not None
assert issue.translation_key == "deprecated_machine_state"
assert issue.translation_key == f"deprecated_{translation_key}"
assert issue.translation_placeholders == {
"entity": entity_id,
"items": "- [test](/config/automation/edit/test)\n- [test](/config/script/edit/test)",