Add setting to change carpet clean mode (#1458)
Some checks failed
CI / Perform linting checks (3.13) (push) Has been cancelled
CodeQL checks / Analyze (python) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.13) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.11) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.12) (push) Has been cancelled
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.13) (push) Has been cancelled

Add new setting to control carpet clean mode:
```
== Configuration ==
Carpet clean mode (carpet_clean_mode): Normal *Boost*
```
This commit is contained in:
Teemu R. 2025-01-15 20:35:41 +01:00 committed by GitHub
parent d27697c50f
commit 773801cad5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 94 additions and 2 deletions

View File

@ -437,6 +437,7 @@ COMPONENT_REQUESTS = {
"overheat_protection": [],
# Vacuum components
"clean": [
SmartRequest.get_raw_request("getCarpetClean"),
SmartRequest.get_raw_request("getCleanRecords"),
SmartRequest.get_raw_request("getVacStatus"),
SmartRequest.get_raw_request("getAreaUnit"),

View File

@ -4,7 +4,7 @@ from __future__ import annotations
import logging
from datetime import timedelta
from enum import IntEnum
from enum import IntEnum, StrEnum
from typing import Annotated, Literal
from ...feature import Feature
@ -56,6 +56,13 @@ class FanSpeed(IntEnum):
Ultra = 5
class CarpetCleanMode(StrEnum):
"""Carpet clean mode."""
Normal = "normal"
Boost = "boost"
class AreaUnit(IntEnum):
"""Area unit."""
@ -143,7 +150,6 @@ class Clean(SmartModule):
type=Feature.Type.Sensor,
)
)
self._add_feature(
Feature(
self._device,
@ -171,6 +177,20 @@ class Clean(SmartModule):
type=Feature.Type.Number,
)
)
self._add_feature(
Feature(
self._device,
id="carpet_clean_mode",
name="Carpet clean mode",
container=self,
attribute_getter="carpet_clean_mode",
attribute_setter="set_carpet_clean_mode",
icon="mdi:rug",
choices_getter=lambda: list(CarpetCleanMode.__members__),
category=Feature.Category.Config,
type=Feature.Type.Choice,
)
)
self._add_feature(
Feature(
self._device,
@ -234,6 +254,7 @@ class Clean(SmartModule):
return {
"getVacStatus": {},
"getCleanInfo": {},
"getCarpetClean": {},
"getAreaUnit": {},
"getBatteryInfo": {},
"getCleanStatus": {},
@ -342,6 +363,24 @@ class Clean(SmartModule):
_LOGGER.warning("Got unknown status code: %s (%s)", status_code, self.data)
return Status.UnknownInternal
@property
def carpet_clean_mode(self) -> Annotated[str, FeatureAttribute()]:
"""Return carpet clean mode."""
return CarpetCleanMode(self.data["getCarpetClean"]["carpet_clean_prefer"]).name
async def set_carpet_clean_mode(
self, mode: str
) -> Annotated[dict, FeatureAttribute()]:
"""Set carpet clean mode."""
name_to_value = {x.name: x.value for x in CarpetCleanMode}
if mode not in name_to_value:
raise ValueError(
"Invalid carpet clean mode %s, available %s", mode, name_to_value
)
return await self.call(
"setCarpetClean", {"carpet_clean_prefer": name_to_value[mode]}
)
@property
def area_unit(self) -> AreaUnit:
"""Return area unit."""

View File

@ -162,6 +162,9 @@
"getBatteryInfo": {
"battery_percentage": 75
},
"getCarpetClean": {
"carpet_clean_prefer": "boost"
},
"getCleanAttr": {
"cistern": 2,
"clean_number": 1,

View File

@ -21,6 +21,7 @@ clean = parametrize("clean module", component_filter="clean", protocol_filter={"
("vacuum_status", "status", Status),
("vacuum_error", "error", ErrorCode),
("vacuum_fan_speed", "fan_speed_preset", str),
("carpet_clean_mode", "carpet_clean_mode", str),
("battery_level", "battery", int),
],
)
@ -69,6 +70,13 @@ async def test_features(dev: SmartDevice, feature: str, prop_name: str, type: ty
{"suction": 1, "type": "global"},
id="vacuum_fan_speed",
),
pytest.param(
"carpet_clean_mode",
"Boost",
"setCarpetClean",
{"carpet_clean_prefer": "boost"},
id="carpet_clean_mode",
),
pytest.param(
"clean_count",
2,
@ -151,3 +159,44 @@ async def test_unknown_status(
assert clean.status is Status.UnknownInternal
assert "Got unknown status code: 123" in caplog.text
@clean
@pytest.mark.parametrize(
("setting", "value", "exc", "exc_message"),
[
pytest.param(
"vacuum_fan_speed",
"invalid speed",
ValueError,
"Invalid fan speed",
id="vacuum_fan_speed",
),
pytest.param(
"carpet_clean_mode",
"invalid mode",
ValueError,
"Invalid carpet clean mode",
id="carpet_clean_mode",
),
],
)
async def test_invalid_settings(
dev: SmartDevice,
mocker: MockerFixture,
setting: str,
value: str,
exc: type[Exception],
exc_message: str,
):
"""Test invalid settings."""
clean = next(get_parent_and_child_modules(dev, Module.Clean))
# Not using feature.set_value() as it checks for valid values
setter_name = dev.features[setting].attribute_setter
assert isinstance(setter_name, str)
setter = getattr(clean, setter_name)
with pytest.raises(exc, match=exc_message):
await setter(value)