1
0
mirror of https://github.com/home-assistant/core.git synced 2026-04-17 23:53:49 +01:00

Add fan speed to SmartThings vacuum (#164452)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Joost Lekkerkerker
2026-02-28 20:09:43 +01:00
committed by GitHub
parent 6cc56b76f9
commit 53da5612e9
6 changed files with 151 additions and 17 deletions

View File

@@ -919,6 +919,20 @@
"wrinkle_prevent": {
"name": "Wrinkle prevent"
}
},
"vacuum": {
"vacuum": {
"state_attributes": {
"fan_speed": {
"state": {
"maximum": "Maximum",
"normal": "Normal",
"quiet": "Quiet",
"smart": "Smart"
}
}
}
}
}
},
"exceptions": {

View File

@@ -22,6 +22,15 @@ from .entity import SmartThingsEntity
_LOGGER = logging.getLogger(__name__)
TURBO_MODE_TO_FAN_SPEED = {
"silence": "normal",
"on": "maximum",
"off": "smart",
"extraSilence": "quiet",
}
FAN_SPEED_TO_TURBO_MODE = {v: k for k, v in TURBO_MODE_TO_FAN_SPEED.items()}
async def async_setup_entry(
hass: HomeAssistant,
@@ -41,20 +50,26 @@ class SamsungJetBotVacuum(SmartThingsEntity, StateVacuumEntity):
"""Representation of a Vacuum."""
_attr_name = None
_attr_supported_features = (
VacuumEntityFeature.START
| VacuumEntityFeature.RETURN_HOME
| VacuumEntityFeature.PAUSE
| VacuumEntityFeature.STATE
)
_attr_translation_key = "vacuum"
def __init__(self, client: SmartThings, device: FullDevice) -> None:
"""Initialize the Samsung robot cleaner vacuum entity."""
super().__init__(
client,
device,
{Capability.SAMSUNG_CE_ROBOT_CLEANER_OPERATING_STATE},
{
Capability.SAMSUNG_CE_ROBOT_CLEANER_OPERATING_STATE,
Capability.ROBOT_CLEANER_TURBO_MODE,
},
)
self._attr_supported_features = (
VacuumEntityFeature.START
| VacuumEntityFeature.RETURN_HOME
| VacuumEntityFeature.PAUSE
| VacuumEntityFeature.STATE
)
if self.supports_capability(Capability.ROBOT_CLEANER_TURBO_MODE):
self._attr_supported_features |= VacuumEntityFeature.FAN_SPEED
@property
def activity(self) -> VacuumActivity | None:
@@ -74,6 +89,23 @@ class SamsungJetBotVacuum(SmartThingsEntity, StateVacuumEntity):
"charging": VacuumActivity.DOCKED,
}.get(status)
@property
def fan_speed_list(self) -> list[str]:
"""Return the list of available fan speeds."""
if not self.supports_capability(Capability.ROBOT_CLEANER_TURBO_MODE):
return []
return list(TURBO_MODE_TO_FAN_SPEED.values())
@property
def fan_speed(self) -> str | None:
"""Return the current fan speed."""
if not self.supports_capability(Capability.ROBOT_CLEANER_TURBO_MODE):
return None
turbo_mode = self.get_attribute_value(
Capability.ROBOT_CLEANER_TURBO_MODE, Attribute.ROBOT_CLEANER_TURBO_MODE
)
return TURBO_MODE_TO_FAN_SPEED.get(turbo_mode)
async def async_start(self) -> None:
"""Start the vacuum's operation."""
await self.execute_device_command(
@@ -93,3 +125,12 @@ class SamsungJetBotVacuum(SmartThingsEntity, StateVacuumEntity):
Capability.SAMSUNG_CE_ROBOT_CLEANER_OPERATING_STATE,
Command.RETURN_TO_HOME,
)
async def async_set_fan_speed(self, fan_speed: str, **kwargs: Any) -> None:
"""Set the fan speed."""
turbo_mode = FAN_SPEED_TO_TURBO_MODE[fan_speed]
await self.execute_device_command(
Capability.ROBOT_CLEANER_TURBO_MODE,
Command.SET_ROBOT_CLEANER_TURBO_MODE,
turbo_mode,
)

View File

@@ -100,7 +100,7 @@
},
"robotCleanerTurboMode": {
"robotCleanerTurboMode": {
"value": "off",
"value": "on",
"timestamp": "2026-02-27T10:49:04.309Z"
}
},

View File

@@ -11016,7 +11016,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
'state': 'on',
})
# ---
# name: test_all_entities[da_rvc_normal_000001][sensor.robot_vacuum_battery-entry]

View File

@@ -4,7 +4,14 @@
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'capabilities': dict({
'fan_speed_list': list([
'normal',
'maximum',
'smart',
'quiet',
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
@@ -29,8 +36,8 @@
'platform': 'smartthings',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': <VacuumEntityFeature: 12308>,
'translation_key': None,
'supported_features': <VacuumEntityFeature: 12340>,
'translation_key': 'vacuum',
'unique_id': '01b28624-5907-c8bc-0325-8ad23f03a637_main',
'unit_of_measurement': None,
})
@@ -38,8 +45,15 @@
# name: test_all_entities[da_rvc_map_01011][vacuum.robot_vacuum-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'fan_speed': 'maximum',
'fan_speed_list': list([
'normal',
'maximum',
'smart',
'quiet',
]),
'friendly_name': 'Robot Vacuum',
'supported_features': <VacuumEntityFeature: 12308>,
'supported_features': <VacuumEntityFeature: 12340>,
}),
'context': <ANY>,
'entity_id': 'vacuum.robot_vacuum',
@@ -54,7 +68,14 @@
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'capabilities': dict({
'fan_speed_list': list([
'normal',
'maximum',
'smart',
'quiet',
]),
}),
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
@@ -79,8 +100,8 @@
'platform': 'smartthings',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': <VacuumEntityFeature: 12308>,
'translation_key': None,
'supported_features': <VacuumEntityFeature: 12340>,
'translation_key': 'vacuum',
'unique_id': '3442dfc6-17c0-a65f-dae0-4c6e01786f44_main',
'unit_of_measurement': None,
})
@@ -88,8 +109,15 @@
# name: test_all_entities[da_rvc_normal_000001][vacuum.robot_vacuum-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'fan_speed': 'smart',
'fan_speed_list': list([
'normal',
'maximum',
'smart',
'quiet',
]),
'friendly_name': 'Robot vacuum',
'supported_features': <VacuumEntityFeature: 12308>,
'supported_features': <VacuumEntityFeature: 12340>,
}),
'context': <ANY>,
'entity_id': 'vacuum.robot_vacuum',

View File

@@ -9,9 +9,11 @@ from syrupy.assertion import SnapshotAssertion
from homeassistant.components.smartthings import MAIN
from homeassistant.components.vacuum import (
ATTR_FAN_SPEED,
DOMAIN as VACUUM_DOMAIN,
SERVICE_PAUSE,
SERVICE_RETURN_TO_BASE,
SERVICE_SET_FAN_SPEED,
SERVICE_START,
VacuumActivity,
)
@@ -131,3 +133,52 @@ async def test_availability_at_start(
"""Test unavailable at boot."""
await setup_integration(hass, mock_config_entry)
assert hass.states.get("vacuum.robot_vacuum").state == STATE_UNAVAILABLE
@pytest.mark.parametrize("device_fixture", ["da_rvc_map_01011"])
async def test_fan_speed_update(
hass: HomeAssistant,
devices: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test fan speed state update."""
await setup_integration(hass, mock_config_entry)
assert (
hass.states.get("vacuum.robot_vacuum").attributes[ATTR_FAN_SPEED] == "maximum"
)
await trigger_update(
hass,
devices,
"01b28624-5907-c8bc-0325-8ad23f03a637",
Capability.ROBOT_CLEANER_TURBO_MODE,
Attribute.ROBOT_CLEANER_TURBO_MODE,
"extraSilence",
)
assert hass.states.get("vacuum.robot_vacuum").attributes[ATTR_FAN_SPEED] == "quiet"
@pytest.mark.parametrize("device_fixture", ["da_rvc_map_01011"])
async def test_vacuum_set_fan_speed(
hass: HomeAssistant,
devices: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test setting fan speed."""
await setup_integration(hass, mock_config_entry)
await hass.services.async_call(
VACUUM_DOMAIN,
SERVICE_SET_FAN_SPEED,
{ATTR_ENTITY_ID: "vacuum.robot_vacuum", ATTR_FAN_SPEED: "normal"},
blocking=True,
)
devices.execute_device_command.assert_called_once_with(
"01b28624-5907-c8bc-0325-8ad23f03a637",
Capability.ROBOT_CLEANER_TURBO_MODE,
Command.SET_ROBOT_CLEANER_TURBO_MODE,
MAIN,
"silence",
)