mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 12:17:07 +00:00
Fix operational state and vacuum state for matter vacuum (#147466)
This commit is contained in:
parent
c54ce7eabd
commit
977e8adbfb
@ -2,7 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from typing import TYPE_CHECKING, cast
|
||||
|
||||
@ -74,6 +74,11 @@ OPERATIONAL_STATE_MAP = {
|
||||
clusters.OperationalState.Enums.OperationalStateEnum.kRunning: "running",
|
||||
clusters.OperationalState.Enums.OperationalStateEnum.kPaused: "paused",
|
||||
clusters.OperationalState.Enums.OperationalStateEnum.kError: "error",
|
||||
}
|
||||
|
||||
RVC_OPERATIONAL_STATE_MAP = {
|
||||
# enum with known Operation state values which we can translate
|
||||
**OPERATIONAL_STATE_MAP,
|
||||
clusters.RvcOperationalState.Enums.OperationalStateEnum.kSeekingCharger: "seeking_charger",
|
||||
clusters.RvcOperationalState.Enums.OperationalStateEnum.kCharging: "charging",
|
||||
clusters.RvcOperationalState.Enums.OperationalStateEnum.kDocked: "docked",
|
||||
@ -171,6 +176,10 @@ class MatterOperationalStateSensorEntityDescription(MatterSensorEntityDescriptio
|
||||
state_list_attribute: type[ClusterAttributeDescriptor] = (
|
||||
clusters.OperationalState.Attributes.OperationalStateList
|
||||
)
|
||||
state_attribute: type[ClusterAttributeDescriptor] = (
|
||||
clusters.OperationalState.Attributes.OperationalState
|
||||
)
|
||||
state_map: dict[int, str] = field(default_factory=lambda: OPERATIONAL_STATE_MAP)
|
||||
|
||||
|
||||
class MatterSensor(MatterEntity, SensorEntity):
|
||||
@ -245,15 +254,15 @@ class MatterOperationalStateSensor(MatterSensor):
|
||||
for state in operational_state_list:
|
||||
# prefer translateable (known) state from mapping,
|
||||
# fallback to the raw state label as given by the device/manufacturer
|
||||
states_map[state.operationalStateID] = OPERATIONAL_STATE_MAP.get(
|
||||
state.operationalStateID, slugify(state.operationalStateLabel)
|
||||
states_map[state.operationalStateID] = (
|
||||
self.entity_description.state_map.get(
|
||||
state.operationalStateID, slugify(state.operationalStateLabel)
|
||||
)
|
||||
)
|
||||
self.states_map = states_map
|
||||
self._attr_options = list(states_map.values())
|
||||
self._attr_native_value = states_map.get(
|
||||
self.get_matter_attribute_value(
|
||||
clusters.OperationalState.Attributes.OperationalState
|
||||
)
|
||||
self.get_matter_attribute_value(self.entity_description.state_attribute)
|
||||
)
|
||||
|
||||
|
||||
@ -999,6 +1008,8 @@ DISCOVERY_SCHEMAS = [
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
translation_key="operational_state",
|
||||
state_list_attribute=clusters.RvcOperationalState.Attributes.OperationalStateList,
|
||||
state_attribute=clusters.RvcOperationalState.Attributes.OperationalState,
|
||||
state_map=RVC_OPERATIONAL_STATE_MAP,
|
||||
),
|
||||
entity_class=MatterOperationalStateSensor,
|
||||
required_attributes=(
|
||||
@ -1016,6 +1027,7 @@ DISCOVERY_SCHEMAS = [
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
translation_key="operational_state",
|
||||
state_list_attribute=clusters.OvenCavityOperationalState.Attributes.OperationalStateList,
|
||||
state_attribute=clusters.OvenCavityOperationalState.Attributes.OperationalState,
|
||||
),
|
||||
entity_class=MatterOperationalStateSensor,
|
||||
required_attributes=(
|
||||
|
@ -30,10 +30,10 @@ class OperationalState(IntEnum):
|
||||
Combination of generic OperationalState and RvcOperationalState.
|
||||
"""
|
||||
|
||||
NO_ERROR = 0x00
|
||||
UNABLE_TO_START_OR_RESUME = 0x01
|
||||
UNABLE_TO_COMPLETE_OPERATION = 0x02
|
||||
COMMAND_INVALID_IN_STATE = 0x03
|
||||
STOPPED = 0x00
|
||||
RUNNING = 0x01
|
||||
PAUSED = 0x02
|
||||
ERROR = 0x03
|
||||
SEEKING_CHARGER = 0x40
|
||||
CHARGING = 0x41
|
||||
DOCKED = 0x42
|
||||
@ -95,7 +95,7 @@ class MatterVacuum(MatterEntity, StateVacuumEntity):
|
||||
|
||||
async def async_pause(self) -> None:
|
||||
"""Pause the cleaning task."""
|
||||
await self.send_device_command(clusters.OperationalState.Commands.Pause())
|
||||
await self.send_device_command(clusters.RvcOperationalState.Commands.Pause())
|
||||
|
||||
@callback
|
||||
def _update_from_device(self) -> None:
|
||||
@ -120,11 +120,10 @@ class MatterVacuum(MatterEntity, StateVacuumEntity):
|
||||
state = VacuumActivity.DOCKED
|
||||
elif operational_state == OperationalState.SEEKING_CHARGER:
|
||||
state = VacuumActivity.RETURNING
|
||||
elif operational_state in (
|
||||
OperationalState.UNABLE_TO_COMPLETE_OPERATION,
|
||||
OperationalState.UNABLE_TO_START_OR_RESUME,
|
||||
):
|
||||
elif operational_state == OperationalState.ERROR:
|
||||
state = VacuumActivity.ERROR
|
||||
elif operational_state == OperationalState.PAUSED:
|
||||
state = VacuumActivity.PAUSED
|
||||
elif (run_mode := self._supported_run_modes.get(run_mode_raw)) is not None:
|
||||
tags = {x.value for x in run_mode.modeTags}
|
||||
if ModeTag.CLEANING in tags:
|
||||
@ -201,7 +200,7 @@ DISCOVERY_SCHEMAS = [
|
||||
entity_class=MatterVacuum,
|
||||
required_attributes=(
|
||||
clusters.RvcRunMode.Attributes.CurrentMode,
|
||||
clusters.RvcOperationalState.Attributes.CurrentPhase,
|
||||
clusters.RvcOperationalState.Attributes.OperationalState,
|
||||
),
|
||||
optional_attributes=(
|
||||
clusters.RvcCleanMode.Attributes.CurrentMode,
|
||||
|
@ -3775,7 +3775,7 @@
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unknown',
|
||||
'state': 'running',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[oven][sensor.mock_oven_temperature_2-entry]
|
||||
@ -6433,7 +6433,7 @@
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unknown',
|
||||
'state': 'stopped',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensors[window_covering_full][sensor.mock_full_window_covering_target_opening_position-entry]
|
||||
|
@ -93,7 +93,7 @@ async def test_vacuum_actions(
|
||||
assert matter_client.send_device_command.call_args == call(
|
||||
node_id=matter_node.node_id,
|
||||
endpoint_id=1,
|
||||
command=clusters.OperationalState.Commands.Pause(),
|
||||
command=clusters.RvcOperationalState.Commands.Pause(),
|
||||
)
|
||||
matter_client.send_device_command.reset_mock()
|
||||
|
||||
@ -168,19 +168,26 @@ async def test_vacuum_updates(
|
||||
assert state
|
||||
assert state.state == "returning"
|
||||
|
||||
# confirm state is 'error' by setting the operational state to 0x01
|
||||
# confirm state is 'idle' by setting the operational state to 0x01 (running) but mode is idle
|
||||
set_node_attribute(matter_node, 1, 97, 4, 0x01)
|
||||
await trigger_subscription_callback(hass, matter_client)
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
assert state.state == "error"
|
||||
assert state.state == "idle"
|
||||
|
||||
# confirm state is 'error' by setting the operational state to 0x02
|
||||
# confirm state is 'idle' by setting the operational state to 0x01 (running) but mode is cleaning
|
||||
set_node_attribute(matter_node, 1, 97, 4, 0x01)
|
||||
await trigger_subscription_callback(hass, matter_client)
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
assert state.state == "idle"
|
||||
|
||||
# confirm state is 'paused' by setting the operational state to 0x02
|
||||
set_node_attribute(matter_node, 1, 97, 4, 0x02)
|
||||
await trigger_subscription_callback(hass, matter_client)
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
assert state.state == "error"
|
||||
assert state.state == "paused"
|
||||
|
||||
# confirm state is 'cleaning' by setting;
|
||||
# - the operational state to 0x00
|
||||
@ -211,3 +218,11 @@ async def test_vacuum_updates(
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
assert state.state == "unknown"
|
||||
|
||||
# confirm state is 'error' by setting;
|
||||
# - the operational state to 0x03
|
||||
set_node_attribute(matter_node, 1, 97, 4, 3)
|
||||
await trigger_subscription_callback(hass, matter_client)
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
assert state.state == "error"
|
||||
|
Loading…
x
Reference in New Issue
Block a user