Skip to content

Commit

Permalink
Add fan_speed_presets() for querying available fan speeds (#643)
Browse files Browse the repository at this point in the history
* Add fan_speed_presets() for querying available fan speeds

This returns a dictionary {name, value} of the available fan speeds,
the main driver being the need to simplify homeassistant integrations for different devices.

For viomi vacuums this is currently straightforward and hard-coded, but we do special handling
for rockrobo devices (based on info() responses):

* If the query succeeds, newer firmware versions (3.5.7+) of v1 are handled as a special case,
  otherwise the new-style [100-105] mapping is returned.

* If the query fails, we fall back to rockrobo v1's percentage-based mapping.
  This happens, e.g., when the vacuum has no cloud connectivity.

Related to #523

Related downstream issues
home-assistant/core#32821
home-assistant/core#31268
home-assistant/core#27268

* Fix method naming..

* small pre-merge cleanups
  • Loading branch information
rytilahti authored Mar 27, 2020
1 parent ccd1c42 commit 86de386
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 5 deletions.
68 changes: 63 additions & 5 deletions miio/vacuum.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import os
import pathlib
import time
from typing import List, Optional, Union
from typing import Dict, List, Optional, Union

import click
import pytz
Expand Down Expand Up @@ -46,6 +46,24 @@ class Consumable(enum.Enum):
SensorDirty = "sensor_dirty_time"


class FanspeedV1(enum.Enum):
Silent = 38
Standard = 60
Medium = 77
Turbo = 90


class FanspeedV2(enum.Enum):
Silent = 101
Standard = 102
Medium = 103
Turbo = 104
Gentle = 105


ROCKROBO_V1 = "rockrobo.vacuum.v1"


class Vacuum(Device):
"""Main class representing the vacuum."""

Expand All @@ -54,6 +72,8 @@ def __init__(
) -> None:
super().__init__(ip, token, start_id, debug)
self.manual_seqnum = -1
self.model = None
self._fanspeeds = FanspeedV1

@command()
def start(self):
Expand Down Expand Up @@ -416,6 +436,47 @@ def fan_speed(self):
"""Return fan speed."""
return self.send("get_custom_mode")[0]

def _autodetect_model(self):
"""Detect the model of the vacuum.
For the moment this is used only for the fanspeeds,
but that could be extended to cover other supported features."""
try:
info = self.info()
self.model = info.model
except TypeError:
# cloud-blocked vacuums will not return proper payloads
self._fanspeeds = FanspeedV1
self.model = ROCKROBO_V1
_LOGGER.debug("Unable to query model, falling back to %s", self._fanspeeds)
return

_LOGGER.info("model: %s", self.model)

if info.model == ROCKROBO_V1:
_LOGGER.debug("Got robov1, checking for firmware version")
fw_version = info.firmware_version
version, build = fw_version.split("_")
version = tuple(map(int, version.split(".")))
if version >= (3, 5, 7):
self._fanspeeds = FanspeedV2
else:
self._fanspeeds = FanspeedV1
else:
self._fanspeeds = FanspeedV2

_LOGGER.debug(
"Using new fanspeed mapping %s for %s", self._fanspeeds, info.model
)

@command()
def fan_speed_presets(self) -> Dict[str, int]:
"""Return dictionary containing supported fan speeds."""
if self.model is None:
self._autodetect_model()

return {x.name: x.value for x in list(self._fanspeeds)}

@command()
def sound_info(self):
"""Get voice settings."""
Expand Down Expand Up @@ -619,10 +680,7 @@ def cleanup(vac: Vacuum, *args, **kwargs):
_LOGGER.debug("Writing %s to %s", seqs, id_file)
path_obj = pathlib.Path(id_file)
cache_dir = path_obj.parents[0]
try:
cache_dir.mkdir(parents=True)
except FileExistsError:
pass # after dropping py3.4 support, use exist_ok for mkdir
cache_dir.mkdir(parents=True, exist_ok=True)
with open(id_file, "w") as f:
json.dump(seqs, f)

Expand Down
6 changes: 6 additions & 0 deletions miio/viomivacuum.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from collections import defaultdict
from datetime import timedelta
from enum import Enum
from typing import Dict

import click

Expand Down Expand Up @@ -338,3 +339,8 @@ def led(self, state: ViomiLedState):
def carpet_mode(self, mode: ViomiCarpetTurbo):
"""Set the carpet mode."""
return self.send("set_carpetturbo", [mode.value])

@command()
def fan_speed_presets(self) -> Dict[str, int]:
"""Return dictionary containing supported fanspeeds."""
return {x.name: x.value for x in list(ViomiVacuumSpeed)}

0 comments on commit 86de386

Please sign in to comment.