mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 12:17:07 +00:00
Deduplicate shared logic in Matter vacuum commands (#147578)
Get the run mode by tag in a single place to avoid code duplication. Also raise an error if the run mode (unexpectedly) is not found.
This commit is contained in:
parent
d55ecd885e
commit
be49296547
@ -17,6 +17,7 @@ from homeassistant.components.vacuum import (
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
|
||||
from .entity import MatterEntity
|
||||
@ -67,20 +68,31 @@ class MatterVacuum(MatterEntity, StateVacuumEntity):
|
||||
entity_description: StateVacuumEntityDescription
|
||||
_platform_translation_key = "vacuum"
|
||||
|
||||
def _get_run_mode_by_tag(
|
||||
self, tag: ModeTag
|
||||
) -> clusters.RvcRunMode.Structs.ModeOptionStruct | None:
|
||||
"""Get the run mode by tag."""
|
||||
supported_run_modes = self._supported_run_modes or {}
|
||||
for mode in supported_run_modes.values():
|
||||
for t in mode.modeTags:
|
||||
if t.value == tag.value:
|
||||
return mode
|
||||
return None
|
||||
|
||||
async def async_stop(self, **kwargs: Any) -> None:
|
||||
"""Stop the vacuum cleaner."""
|
||||
# We simply set the RvcRunMode to the first runmode
|
||||
# that has the idle tag to stop the vacuum cleaner.
|
||||
# this is compatible with both Matter 1.2 and 1.3+ devices.
|
||||
supported_run_modes = self._supported_run_modes or {}
|
||||
for mode in supported_run_modes.values():
|
||||
for tag in mode.modeTags:
|
||||
if tag.value == ModeTag.IDLE:
|
||||
# stop the vacuum by changing the run mode to idle
|
||||
await self.send_device_command(
|
||||
clusters.RvcRunMode.Commands.ChangeToMode(newMode=mode.mode)
|
||||
)
|
||||
return
|
||||
mode = self._get_run_mode_by_tag(ModeTag.IDLE)
|
||||
if mode is None:
|
||||
raise HomeAssistantError(
|
||||
"No supported run mode found to stop the vacuum cleaner."
|
||||
)
|
||||
|
||||
await self.send_device_command(
|
||||
clusters.RvcRunMode.Commands.ChangeToMode(newMode=mode.mode)
|
||||
)
|
||||
|
||||
async def async_return_to_base(self, **kwargs: Any) -> None:
|
||||
"""Set the vacuum cleaner to return to the dock."""
|
||||
@ -110,14 +122,15 @@ class MatterVacuum(MatterEntity, StateVacuumEntity):
|
||||
# We simply set the RvcRunMode to the first runmode
|
||||
# that has the cleaning tag to start the vacuum cleaner.
|
||||
# this is compatible with both Matter 1.2 and 1.3+ devices.
|
||||
supported_run_modes = self._supported_run_modes or {}
|
||||
for mode in supported_run_modes.values():
|
||||
for tag in mode.modeTags:
|
||||
if tag.value == ModeTag.CLEANING:
|
||||
await self.send_device_command(
|
||||
clusters.RvcRunMode.Commands.ChangeToMode(newMode=mode.mode)
|
||||
)
|
||||
return
|
||||
mode = self._get_run_mode_by_tag(ModeTag.CLEANING)
|
||||
if mode is None:
|
||||
raise HomeAssistantError(
|
||||
"No supported run mode found to start the vacuum cleaner."
|
||||
)
|
||||
|
||||
await self.send_device_command(
|
||||
clusters.RvcRunMode.Commands.ChangeToMode(newMode=mode.mode)
|
||||
)
|
||||
|
||||
async def async_pause(self) -> None:
|
||||
"""Pause the cleaning task."""
|
||||
|
@ -9,6 +9,7 @@ from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
@ -238,3 +239,55 @@ async def test_vacuum_updates(
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
assert state.state == "error"
|
||||
|
||||
|
||||
@pytest.mark.parametrize("node_fixture", ["vacuum_cleaner"])
|
||||
async def test_vacuum_actions_no_supported_run_modes(
|
||||
hass: HomeAssistant,
|
||||
matter_client: MagicMock,
|
||||
matter_node: MatterNode,
|
||||
) -> None:
|
||||
"""Test vacuum entity actions when no supported run modes are available."""
|
||||
# Fetch translations
|
||||
await async_setup_component(hass, "homeassistant", {})
|
||||
entity_id = "vacuum.mock_vacuum"
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
|
||||
# Set empty supported modes to simulate no available run modes
|
||||
# RvcRunMode cluster ID is 84, SupportedModes attribute ID is 0
|
||||
set_node_attribute(matter_node, 1, 84, 0, [])
|
||||
# RvcOperationalState cluster ID is 97, AcceptedCommandList attribute ID is 65529
|
||||
set_node_attribute(matter_node, 1, 97, 65529, [])
|
||||
await trigger_subscription_callback(hass, matter_client)
|
||||
|
||||
# test start action fails when no supported run modes
|
||||
with pytest.raises(
|
||||
HomeAssistantError,
|
||||
match="No supported run mode found to start the vacuum cleaner",
|
||||
):
|
||||
await hass.services.async_call(
|
||||
"vacuum",
|
||||
"start",
|
||||
{
|
||||
"entity_id": entity_id,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
# test stop action fails when no supported run modes
|
||||
with pytest.raises(
|
||||
HomeAssistantError,
|
||||
match="No supported run mode found to stop the vacuum cleaner",
|
||||
):
|
||||
await hass.services.async_call(
|
||||
"vacuum",
|
||||
"stop",
|
||||
{
|
||||
"entity_id": entity_id,
|
||||
},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
# Ensure no commands were sent to the device
|
||||
assert matter_client.send_device_command.call_count == 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user