mirror of
https://github.com/home-assistant/core.git
synced 2025-08-06 06:05:10 +02:00
Deprecate MQTT vacuum battery feature and remove it as default feature
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
{
|
{
|
||||||
"issues": {
|
"issues": {
|
||||||
|
"deprecated_vacuum_battery_feature": {
|
||||||
|
"title": "Deprecated battery feature used",
|
||||||
|
"description": "Vacuum entity {entity_id} implements the battery feature which is deprecated. This will stop working in Home Assistant 2026.3. Implement a separate entity for the battery status instead. To fix the issue `battery` feature should be removed from the configured supported features, and Home Assistant should be restarted to fix this issue."
|
||||||
|
},
|
||||||
"invalid_platform_config": {
|
"invalid_platform_config": {
|
||||||
"title": "Invalid config found for MQTT {domain} item",
|
"title": "Invalid config found for MQTT {domain} item",
|
||||||
"description": "Home Assistant detected an invalid config for a manually configured item.\n\nPlatform domain: **{domain}**\nConfiguration file: **{config_file}**\nNear line: **{line}**\nConfiguration found:\n```yaml\n{config}\n```\nError: **{error}**.\n\nMake sure the configuration is valid and [reload](/developer-tools/yaml) the manually configured MQTT items or restart Home Assistant to fix this issue."
|
"description": "Home Assistant detected an invalid config for a manually configured item.\n\nPlatform domain: **{domain}**\nConfiguration file: **{config_file}**\nNear line: **{line}**\nConfiguration found:\n```yaml\n{config}\n```\nError: **{error}**.\n\nMake sure the configuration is valid and [reload](/developer-tools/yaml) the manually configured MQTT items or restart Home Assistant to fix this issue."
|
||||||
|
@@ -17,7 +17,7 @@ from homeassistant.components.vacuum import (
|
|||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import ATTR_SUPPORTED_FEATURES, CONF_NAME
|
from homeassistant.const import ATTR_SUPPORTED_FEATURES, CONF_NAME
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv, issue_registry as ir
|
||||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||||
from homeassistant.helpers.json import json_dumps
|
from homeassistant.helpers.json import json_dumps
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType, VolSchemaType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType, VolSchemaType
|
||||||
@@ -25,11 +25,11 @@ from homeassistant.util.json import json_loads_object
|
|||||||
|
|
||||||
from . import subscription
|
from . import subscription
|
||||||
from .config import MQTT_BASE_SCHEMA
|
from .config import MQTT_BASE_SCHEMA
|
||||||
from .const import CONF_COMMAND_TOPIC, CONF_RETAIN, CONF_STATE_TOPIC
|
from .const import CONF_COMMAND_TOPIC, CONF_RETAIN, CONF_STATE_TOPIC, DOMAIN
|
||||||
from .entity import MqttEntity, async_setup_entity_entry_helper
|
from .entity import IssueSeverity, MqttEntity, async_setup_entity_entry_helper
|
||||||
from .models import ReceiveMessage
|
from .models import ReceiveMessage
|
||||||
from .schemas import MQTT_ENTITY_COMMON_SCHEMA
|
from .schemas import MQTT_ENTITY_COMMON_SCHEMA
|
||||||
from .util import valid_publish_topic
|
from .util import learn_more_url, valid_publish_topic
|
||||||
|
|
||||||
PARALLEL_UPDATES = 0
|
PARALLEL_UPDATES = 0
|
||||||
|
|
||||||
@@ -84,6 +84,8 @@ SERVICE_TO_STRING: dict[VacuumEntityFeature, str] = {
|
|||||||
VacuumEntityFeature.STOP: "stop",
|
VacuumEntityFeature.STOP: "stop",
|
||||||
VacuumEntityFeature.RETURN_HOME: "return_home",
|
VacuumEntityFeature.RETURN_HOME: "return_home",
|
||||||
VacuumEntityFeature.FAN_SPEED: "fan_speed",
|
VacuumEntityFeature.FAN_SPEED: "fan_speed",
|
||||||
|
# Use of the battery feature was deprecated in HA Core 2025.9
|
||||||
|
# and will removed with HA Core 2026.3
|
||||||
VacuumEntityFeature.BATTERY: "battery",
|
VacuumEntityFeature.BATTERY: "battery",
|
||||||
VacuumEntityFeature.STATUS: "status",
|
VacuumEntityFeature.STATUS: "status",
|
||||||
VacuumEntityFeature.SEND_COMMAND: "send_command",
|
VacuumEntityFeature.SEND_COMMAND: "send_command",
|
||||||
@@ -96,7 +98,6 @@ DEFAULT_SERVICES = (
|
|||||||
VacuumEntityFeature.START
|
VacuumEntityFeature.START
|
||||||
| VacuumEntityFeature.STOP
|
| VacuumEntityFeature.STOP
|
||||||
| VacuumEntityFeature.RETURN_HOME
|
| VacuumEntityFeature.RETURN_HOME
|
||||||
| VacuumEntityFeature.BATTERY
|
|
||||||
| VacuumEntityFeature.CLEAN_SPOT
|
| VacuumEntityFeature.CLEAN_SPOT
|
||||||
)
|
)
|
||||||
ALL_SERVICES = (
|
ALL_SERVICES = (
|
||||||
@@ -106,6 +107,7 @@ ALL_SERVICES = (
|
|||||||
| VacuumEntityFeature.FAN_SPEED
|
| VacuumEntityFeature.FAN_SPEED
|
||||||
| VacuumEntityFeature.SEND_COMMAND
|
| VacuumEntityFeature.SEND_COMMAND
|
||||||
)
|
)
|
||||||
|
DEPRECATED_SERVICES = VacuumEntityFeature.BATTERY
|
||||||
|
|
||||||
|
|
||||||
def services_to_strings(
|
def services_to_strings(
|
||||||
@@ -251,10 +253,35 @@ class MqttStateVacuum(MqttEntity, StateVacuumEntity):
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async def mqtt_async_added_to_hass(self) -> None:
|
||||||
|
"""Check for use of deprecated battery features."""
|
||||||
|
if self.supported_features & VacuumEntityFeature.BATTERY:
|
||||||
|
ir.async_create_issue(
|
||||||
|
self.hass,
|
||||||
|
DOMAIN,
|
||||||
|
f"deprecated_vacuum_battery_feature_{self.entity_id}",
|
||||||
|
issue_domain=vacuum.DOMAIN,
|
||||||
|
breaks_in_ha_version="2026.3",
|
||||||
|
is_fixable=False,
|
||||||
|
severity=IssueSeverity.WARNING,
|
||||||
|
learn_more_url=learn_more_url(vacuum.DOMAIN),
|
||||||
|
translation_placeholders={"entity_id": self.entity_id},
|
||||||
|
translation_key="deprecated_vacuum_battery_feature",
|
||||||
|
)
|
||||||
|
_LOGGER.warning(
|
||||||
|
"MQTT vacuum entity %s implements the battery feature "
|
||||||
|
"which is deprecated. This will stop working "
|
||||||
|
"in Home Assistant 2026.3. Implement a separate entity "
|
||||||
|
"for the battery status instead",
|
||||||
|
self.entity_id,
|
||||||
|
)
|
||||||
|
|
||||||
def _update_state_attributes(self, payload: dict[str, Any]) -> None:
|
def _update_state_attributes(self, payload: dict[str, Any]) -> None:
|
||||||
"""Update the entity state attributes."""
|
"""Update the entity state attributes."""
|
||||||
self._state_attrs.update(payload)
|
self._state_attrs.update(payload)
|
||||||
self._attr_fan_speed = self._state_attrs.get(FAN_SPEED, 0)
|
self._attr_fan_speed = self._state_attrs.get(FAN_SPEED, 0)
|
||||||
|
# Use of the battery feature was deprecated in HA Core 2025.9
|
||||||
|
# and will removed with HA Core 2026.3
|
||||||
self._attr_battery_level = max(0, min(100, self._state_attrs.get(BATTERY, 0)))
|
self._attr_battery_level = max(0, min(100, self._state_attrs.get(BATTERY, 0)))
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
|
@@ -32,6 +32,7 @@ from homeassistant.components.vacuum import (
|
|||||||
from homeassistant.const import CONF_NAME, ENTITY_MATCH_ALL, STATE_UNKNOWN
|
from homeassistant.const import CONF_NAME, ENTITY_MATCH_ALL, STATE_UNKNOWN
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
from homeassistant.helpers import issue_registry as ir
|
||||||
|
|
||||||
from .common import (
|
from .common import (
|
||||||
help_custom_config,
|
help_custom_config,
|
||||||
@@ -63,7 +64,7 @@ from .common import (
|
|||||||
help_test_update_with_json_attrs_not_dict,
|
help_test_update_with_json_attrs_not_dict,
|
||||||
)
|
)
|
||||||
|
|
||||||
from tests.common import async_fire_mqtt_message
|
from tests.common import async_capture_events, async_fire_mqtt_message
|
||||||
from tests.components.vacuum import common
|
from tests.components.vacuum import common
|
||||||
from tests.typing import MqttMockHAClientGenerator, MqttMockPahoClient
|
from tests.typing import MqttMockHAClientGenerator, MqttMockPahoClient
|
||||||
|
|
||||||
@@ -108,7 +109,7 @@ async def test_default_supported_features(
|
|||||||
entity = hass.states.get("vacuum.mqtttest")
|
entity = hass.states.get("vacuum.mqtttest")
|
||||||
entity_features = entity.attributes.get(mqttvacuum.CONF_SUPPORTED_FEATURES, 0)
|
entity_features = entity.attributes.get(mqttvacuum.CONF_SUPPORTED_FEATURES, 0)
|
||||||
assert sorted(services_to_strings(entity_features, SERVICE_TO_STRING)) == sorted(
|
assert sorted(services_to_strings(entity_features, SERVICE_TO_STRING)) == sorted(
|
||||||
["start", "stop", "return_home", "battery", "clean_spot"]
|
["start", "stop", "return_home", "clean_spot"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -313,8 +314,6 @@ async def test_status(
|
|||||||
async_fire_mqtt_message(hass, "vacuum/state", message)
|
async_fire_mqtt_message(hass, "vacuum/state", message)
|
||||||
state = hass.states.get("vacuum.mqtttest")
|
state = hass.states.get("vacuum.mqtttest")
|
||||||
assert state.state == VacuumActivity.CLEANING
|
assert state.state == VacuumActivity.CLEANING
|
||||||
assert state.attributes.get(ATTR_BATTERY_LEVEL) == 54
|
|
||||||
assert state.attributes.get(ATTR_BATTERY_ICON) == "mdi:battery-50"
|
|
||||||
assert state.attributes.get(ATTR_FAN_SPEED) == "max"
|
assert state.attributes.get(ATTR_FAN_SPEED) == "max"
|
||||||
|
|
||||||
message = """{
|
message = """{
|
||||||
@@ -326,8 +325,6 @@ async def test_status(
|
|||||||
async_fire_mqtt_message(hass, "vacuum/state", message)
|
async_fire_mqtt_message(hass, "vacuum/state", message)
|
||||||
state = hass.states.get("vacuum.mqtttest")
|
state = hass.states.get("vacuum.mqtttest")
|
||||||
assert state.state == VacuumActivity.DOCKED
|
assert state.state == VacuumActivity.DOCKED
|
||||||
assert state.attributes.get(ATTR_BATTERY_ICON) == "mdi:battery-charging-60"
|
|
||||||
assert state.attributes.get(ATTR_BATTERY_LEVEL) == 61
|
|
||||||
assert state.attributes.get(ATTR_FAN_SPEED) == "min"
|
assert state.attributes.get(ATTR_FAN_SPEED) == "min"
|
||||||
assert state.attributes.get(ATTR_FAN_SPEED_LIST) == ["min", "medium", "high", "max"]
|
assert state.attributes.get(ATTR_FAN_SPEED_LIST) == ["min", "medium", "high", "max"]
|
||||||
|
|
||||||
@@ -337,6 +334,61 @@ async def test_status(
|
|||||||
assert state.state == STATE_UNKNOWN
|
assert state.state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
|
||||||
|
# Use of the battery feature was deprecated in HA Core 2025.9
|
||||||
|
# and will removed with HA Core 2026.3
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"hass_config",
|
||||||
|
[
|
||||||
|
help_custom_config(
|
||||||
|
vacuum.DOMAIN,
|
||||||
|
DEFAULT_CONFIG,
|
||||||
|
({mqttvacuum.CONF_SUPPORTED_FEATURES: ["battery"]},),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_status_with_deprecated_battery_feature(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mqtt_mock_entry: MqttMockHAClientGenerator,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
) -> None:
|
||||||
|
"""Test status updates from the vacuum with deprecated battery feature."""
|
||||||
|
events = async_capture_events(hass, ir.EVENT_REPAIRS_ISSUE_REGISTRY_UPDATED)
|
||||||
|
await mqtt_mock_entry()
|
||||||
|
state = hass.states.get("vacuum.mqtttest")
|
||||||
|
assert state.state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
message = """{
|
||||||
|
"battery_level": 54,
|
||||||
|
"state": "cleaning"
|
||||||
|
}"""
|
||||||
|
async_fire_mqtt_message(hass, "vacuum/state", message)
|
||||||
|
state = hass.states.get("vacuum.mqtttest")
|
||||||
|
assert state.state == VacuumActivity.CLEANING
|
||||||
|
assert state.attributes.get(ATTR_BATTERY_LEVEL) == 54
|
||||||
|
assert state.attributes.get(ATTR_BATTERY_ICON) == "mdi:battery-50"
|
||||||
|
|
||||||
|
message = """{
|
||||||
|
"battery_level": 61,
|
||||||
|
"state": "docked"
|
||||||
|
}"""
|
||||||
|
|
||||||
|
async_fire_mqtt_message(hass, "vacuum/state", message)
|
||||||
|
state = hass.states.get("vacuum.mqtttest")
|
||||||
|
assert state.state == VacuumActivity.DOCKED
|
||||||
|
assert state.attributes.get(ATTR_BATTERY_ICON) == "mdi:battery-charging-60"
|
||||||
|
assert state.attributes.get(ATTR_BATTERY_LEVEL) == 61
|
||||||
|
|
||||||
|
message = '{"state":null}'
|
||||||
|
async_fire_mqtt_message(hass, "vacuum/state", message)
|
||||||
|
state = hass.states.get("vacuum.mqtttest")
|
||||||
|
assert state.state == STATE_UNKNOWN
|
||||||
|
assert (
|
||||||
|
"MQTT vacuum entity vacuum.mqtttest implements "
|
||||||
|
"the battery feature which is deprecated." in caplog.text
|
||||||
|
)
|
||||||
|
assert len(events) == 1
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"hass_config",
|
"hass_config",
|
||||||
[
|
[
|
||||||
@@ -346,7 +398,9 @@ async def test_status(
|
|||||||
(
|
(
|
||||||
{
|
{
|
||||||
mqttvacuum.CONF_SUPPORTED_FEATURES: services_to_strings(
|
mqttvacuum.CONF_SUPPORTED_FEATURES: services_to_strings(
|
||||||
mqttvacuum.DEFAULT_SERVICES, SERVICE_TO_STRING
|
mqttvacuum.DEFAULT_SERVICES
|
||||||
|
| vacuum.VacuumEntityFeature.BATTERY,
|
||||||
|
SERVICE_TO_STRING,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
Reference in New Issue
Block a user