mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 20:27:08 +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.config_entries import ConfigEntry
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import Platform
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||||
|
|
||||||
from .entity import MatterEntity
|
from .entity import MatterEntity
|
||||||
@ -67,20 +68,31 @@ class MatterVacuum(MatterEntity, StateVacuumEntity):
|
|||||||
entity_description: StateVacuumEntityDescription
|
entity_description: StateVacuumEntityDescription
|
||||||
_platform_translation_key = "vacuum"
|
_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:
|
async def async_stop(self, **kwargs: Any) -> None:
|
||||||
"""Stop the vacuum cleaner."""
|
"""Stop the vacuum cleaner."""
|
||||||
# We simply set the RvcRunMode to the first runmode
|
# We simply set the RvcRunMode to the first runmode
|
||||||
# that has the idle tag to stop the vacuum cleaner.
|
# that has the idle tag to stop the vacuum cleaner.
|
||||||
# this is compatible with both Matter 1.2 and 1.3+ devices.
|
# this is compatible with both Matter 1.2 and 1.3+ devices.
|
||||||
supported_run_modes = self._supported_run_modes or {}
|
mode = self._get_run_mode_by_tag(ModeTag.IDLE)
|
||||||
for mode in supported_run_modes.values():
|
if mode is None:
|
||||||
for tag in mode.modeTags:
|
raise HomeAssistantError(
|
||||||
if tag.value == ModeTag.IDLE:
|
"No supported run mode found to stop the vacuum cleaner."
|
||||||
# stop the vacuum by changing the run mode to idle
|
)
|
||||||
await self.send_device_command(
|
|
||||||
clusters.RvcRunMode.Commands.ChangeToMode(newMode=mode.mode)
|
await self.send_device_command(
|
||||||
)
|
clusters.RvcRunMode.Commands.ChangeToMode(newMode=mode.mode)
|
||||||
return
|
)
|
||||||
|
|
||||||
async def async_return_to_base(self, **kwargs: Any) -> None:
|
async def async_return_to_base(self, **kwargs: Any) -> None:
|
||||||
"""Set the vacuum cleaner to return to the dock."""
|
"""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
|
# We simply set the RvcRunMode to the first runmode
|
||||||
# that has the cleaning tag to start the vacuum cleaner.
|
# that has the cleaning tag to start the vacuum cleaner.
|
||||||
# this is compatible with both Matter 1.2 and 1.3+ devices.
|
# this is compatible with both Matter 1.2 and 1.3+ devices.
|
||||||
supported_run_modes = self._supported_run_modes or {}
|
mode = self._get_run_mode_by_tag(ModeTag.CLEANING)
|
||||||
for mode in supported_run_modes.values():
|
if mode is None:
|
||||||
for tag in mode.modeTags:
|
raise HomeAssistantError(
|
||||||
if tag.value == ModeTag.CLEANING:
|
"No supported run mode found to start the vacuum cleaner."
|
||||||
await self.send_device_command(
|
)
|
||||||
clusters.RvcRunMode.Commands.ChangeToMode(newMode=mode.mode)
|
|
||||||
)
|
await self.send_device_command(
|
||||||
return
|
clusters.RvcRunMode.Commands.ChangeToMode(newMode=mode.mode)
|
||||||
|
)
|
||||||
|
|
||||||
async def async_pause(self) -> None:
|
async def async_pause(self) -> None:
|
||||||
"""Pause the cleaning task."""
|
"""Pause the cleaning task."""
|
||||||
|
@ -9,6 +9,7 @@ from syrupy.assertion import SnapshotAssertion
|
|||||||
|
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
@ -238,3 +239,55 @@ async def test_vacuum_updates(
|
|||||||
state = hass.states.get(entity_id)
|
state = hass.states.get(entity_id)
|
||||||
assert state
|
assert state
|
||||||
assert state.state == "error"
|
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