Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add features for newer vacuums (eg Roborock S7) #1039

Merged
merged 14 commits into from
May 11, 2021
40 changes: 40 additions & 0 deletions miio/vacuum.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ class FanspeedE2(enum.Enum):
Turbo = 100


class FanspeedS7(enum.Enum):
Quiet = 101
Balanced = 102
Turbo = 103
Max = 104
fettlaus marked this conversation as resolved.
Show resolved Hide resolved


class WaterFlow(enum.Enum):
"""Water flow strength on s5 max."""

Expand All @@ -93,10 +100,18 @@ class WaterFlow(enum.Enum):
Maximum = 203


class MopMode(enum.Enum):
"""Mop routing on S7."""

Standard = 300
Deep = 301
fettlaus marked this conversation as resolved.
Show resolved Hide resolved


ROCKROBO_V1 = "rockrobo.vacuum.v1"
ROCKROBO_S5 = "roborock.vacuum.s5"
ROCKROBO_S6 = "roborock.vacuum.s6"
ROCKROBO_S6_MAXV = "roborock.vacuum.a10"
ROCKROBO_S7 = "roborock.vacuum.a15"


class Vacuum(Device):
Expand Down Expand Up @@ -546,6 +561,8 @@ def _autodetect_model(self):
self._fanspeeds = FanspeedV1
elif self.model == "roborock.vacuum.e2":
self._fanspeeds = FanspeedE2
elif self.model == ROCKROBO_S7:
self._fanspeeds = FanspeedS7
else:
self._fanspeeds = FanspeedV2

Expand Down Expand Up @@ -747,6 +764,29 @@ def set_waterflow(self, waterflow: WaterFlow):
"""Set water flow setting."""
return self.send("set_water_box_custom_mode", [waterflow.value])

@command()
def mop_mode(self) -> Optional[MopMode]:
"""Get mop mode setting."""
try:
return MopMode(self.send("get_mop_mode")[0])
except ValueError:
return None
fettlaus marked this conversation as resolved.
Show resolved Hide resolved

@command(click.argument("mop_mode", type=EnumType(MopMode)))
def set_mop_mode(self, mop_mode: MopMode):
"""Set mop mode setting."""
return self.send("set_mop_mode", [mop_mode.value])

@command()
def child_lock(self) -> bool:
"""Get child lock setting."""
return self.send("get_child_lock_status")["lock_status"] == 1

@command(click.argument("lock", type=bool))
def set_child_lock(self, lock: bool) -> bool:
"""Set child lock setting."""
return self.send("set_child_lock_status", {"lock_status": int(lock)})[0] == "ok"

@classmethod
def get_device_group(cls):
@click.pass_context
Expand Down
4 changes: 4 additions & 0 deletions miio/vacuum_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ def status(vac: miio.Vacuum):

if res.error_code:
click.echo(click.style("Error: %s !" % res.error, bold=True, fg="red"))
if res.is_water_shortage:
click.echo(click.style("Water is running low!", bold=True, fg="blue"))
click.echo(click.style("State: %s" % res.state, bold=True))
click.echo("Battery: %s %%" % res.battery)
click.echo("Fanspeed: %s %%" % res.fanspeed)
Expand All @@ -124,6 +126,8 @@ def status(vac: miio.Vacuum):
# click.echo("Map present: %s" % res.map)
# click.echo("in_cleaning: %s" % res.in_cleaning)
click.echo("Water box attached: %s" % res.is_water_box_attached)
if res.is_water_box_carriage_attached is not None:
click.echo("Mop attached: %s" % res.is_water_box_carriage_attached)


@cli.command()
Expand Down
37 changes: 37 additions & 0 deletions miio/vacuumcontainers.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,21 @@ def __init__(self, data: Dict[str, Any]) -> None:
# 'map_present': 1, 'in_cleaning': 3, 'in_returning': 0,
# 'in_fresh_state': 0, 'lab_status': 1, 'water_box_status': 0,
# 'fan_power': 102, 'dnd_enabled': 0, 'map_status': 3, 'lock_status': 0}]

# Example of S7 in charging mode
# new items: is_locating, water_box_mode, water_box_carriage_status,
# mop_forbidden_enable, adbumper_status, water_shortage_status,
# dock_type, dust_collection_status, auto_dust_collection, mop_mode, debug_mode
#
# [{'msg_ver': 2, 'msg_seq': 1839, 'state': 8, 'battery': 100,
# 'clean_time': 2311, 'clean_area': 35545000, 'error_code': 0,
# 'map_present': 1, 'in_cleaning': 0, 'in_returning': 0,
# 'in_fresh_state': 1, 'lab_status': 3, 'water_box_status': 1,
# 'fan_power': 102, 'dnd_enabled': 0, 'map_status': 3, 'is_locating': 0,
# 'lock_status': 0, 'water_box_mode': 202, 'water_box_carriage_status': 0,
# 'mop_forbidden_enable': 0, 'adbumper_status': [0, 0, 0],
# 'water_shortage_status': 0, 'dock_type': 0, 'dust_collection_status': 0,
# 'auto_dust_collection': 1, 'mop_mode': 300, 'debug_mode': 0}]
self.data = data

@property
Expand Down Expand Up @@ -175,6 +190,28 @@ def is_water_box_attached(self) -> bool:
"""Return True is water box is installed."""
return "water_box_status" in self.data and self.data["water_box_status"] == 1

@property
def is_water_box_carriage_attached(self) -> Optional[bool]:
"""Return True if water box carriage (mop) is installed, None if sensor not
present."""
if "water_box_carriage_status" in self.data:
return self.data["water_box_carriage_status"] == 1
else:
fettlaus marked this conversation as resolved.
Show resolved Hide resolved
return None

@property
def is_water_shortage(self) -> Optional[bool]:
"""Returns True if water is low in the tank, None if sensor not present."""
if "water_shortage_status" in self.data:
return self.data["water_shortage_status"] == 1
else:
fettlaus marked this conversation as resolved.
Show resolved Hide resolved
return None

@property
def is_child_lock(self) -> bool:
"""Returns True if the child lock is active."""
return self.data["lock_status"] == 1
fettlaus marked this conversation as resolved.
Show resolved Hide resolved

@property
def got_error(self) -> bool:
"""True if an error has occured."""
Expand Down