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 support for Xiaomi Mijia STYJ02YM (viomi.vacuum.v7) #576

Merged
merged 6 commits into from
Dec 4, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Supported devices
- Xiaomi Mi Air Purifier
- Xiaomi Aqara Camera
- Xiaomi Mijia 360 1080p
- Xiaomi Mijia STYJ02YM (Viomi)
- Xiaomi Mi Smart WiFi Socket
- Xiaomi Chuangmi Plug V1 (1 Socket, 1 USB Port)
- Xiaomi Chuangmi Plug V3 (1 Socket, 2 USB Ports)
Expand Down
1 change: 1 addition & 0 deletions miio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
Timer,
VacuumStatus,
)
from miio.viomivacuum import ViomiVacuum
from miio.waterpurifier import WaterPurifier
from miio.wifirepeater import WifiRepeater
from miio.wifispeaker import WifiSpeaker
Expand Down
2 changes: 2 additions & 0 deletions miio/discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
PowerStrip,
Toiletlid,
Vacuum,
ViomiVacuum,
WaterPurifier,
WifiRepeater,
WifiSpeaker,
Expand Down Expand Up @@ -144,6 +145,7 @@
"lumi-gateway-": lambda x: other_package_info(
x, "https://github.com/Danielhiversen/PyXiaomiGateway"
),
"viomi-vacuum-v7": ViomiVacuum,
} # type: Dict[str, Union[Callable, Device]]


Expand Down
176 changes: 176 additions & 0 deletions miio/viomivacuum.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
import logging
from collections import defaultdict
from datetime import timedelta
from enum import Enum

import click

from .click_common import command, format_output
from .device import Device
from .utils import pretty_seconds

_LOGGER = logging.getLogger(__name__)


class ViomiVacuumSpeed(Enum):
Silent = 0
Standard = 1
Medium = 2
Turbo = 3


class ViomiVacuumState(Enum):
syssi marked this conversation as resolved.
Show resolved Hide resolved
Idle = 1
Idle2 = 2
Cleaning = 3
Returning = 4
Docked = 5


class ViomiVacuumStatus:
def __init__(self, data):
# ["run_state","mode","err_state","battary_life","box_type","mop_type","s_time","s_area",
# [ 5, 0, 2103, 85, 3, 1, 0, 0,
# "suction_grade","water_grade","remember_map","has_map","is_mop","has_newmap"]'
# 1, 11, 1, 1, 1, 0 ]
self.data = data

@property
def state(self):
return ViomiVacuumState(self.data["run_state"])

@property
def is_on(self) -> bool:
"""True if cleaning."""
return self.state == ViomiVacuumState.Cleaning

@property
def mode(self):
"""TODO: unknown values"""
return self.data["mode"]

@property
def error(self):
"""TODO: unknown values"""
return self.data["error_state"]

@property
def battery(self) -> int:
"""Battery in percentage."""
return self.data["battary_life"]

@property
def box_type(self):
"""TODO: unknown values"""
return self.data["box_type"]

@property
def mop_type(self):
"""TODO: unknown values"""
return self.data["mop_type"]

@property
def clean_time(self) -> timedelta:
return pretty_seconds(self.data["s_time"])

@property
def clean_area(self) -> float:
"""TODO: unknown values"""
return self.data["s_area"]

@property
def fanspeed(self):
return ViomiVacuumSpeed(self.data["suction_grade"])

@property
def water_level(self):
"""TODO: unknown values, percentage?"""
return self.data["water_grade"]

@property
def remember_map(self) -> bool:
return bool(self.data["remember_map"])

@property
def has_map(self) -> bool:
return bool(self.data["has_map"])

@property
def has_new_map(self) -> bool:
return bool(self.data["has_newmap"])

@property
def is_mop(self) -> bool:
return bool(self.data["is_mop"])


class ViomiVacuum(Device):
"""Interface for Viomi vacuums (viomi.vacuum.v7)."""

@command(
default_output=format_output(
"",
"State: {result.state}\n"
"Mode: {result.mode}\n"
"Error: {result.error}\n"
"Battery: {result.battery}\n"
"Fan speed: {result.fanspeed}\n"
"Box type: {result.box_type}\n"
"Mop type: {result.mop_type}\n"
"Clean time: {result.clean_time}\n"
"Clean area: {result.clean_area}\n"
"Water level: {result.water_level}\n"
"Remember map: {result.remember_map}\n"
"Has map: {result.has_map}\n"
"Has new map: {result.has_new_map}\n"
"Is mop: {result.is_mop}\n",
)
)
def status(self) -> ViomiVacuumStatus:
"""Retrieve properties."""
properties = [
"run_state",
"mode",
"err_state",
"battary_life",
"box_type",
"mop_type",
"s_time",
"s_area",
"suction_grade",
"water_grade",
"remember_map",
"has_map",
"is_mop",
"has_newmap",
]

values = self.send("get_prop", properties)

return ViomiVacuumStatus(defaultdict(lambda: None, zip(properties, values)))

@command()
def start(self):
"""Start cleaning."""
# TODO figure out the parameters
self.send("set_mode_withroom", [0, 1, 0])

@command()
def stop(self):
"""Stop cleaning."""
self.send("set_mode", [0])

@command()
def pause(self):
"""Pause cleaning."""
self.send("set_mode_withroom", [0, 2, 0])

@command(click.argument("speed", type=str))
def set_fan_speed(self, speed: str):
"""Set fanspeed [silent, standard, medium, turbo]."""
self.send("set_suction", [ViomiVacuumSpeed(speed.capitalize()).value])

@command()
def home(self):
"""Return to home."""
self.send("set_charge", [1])