Skip to content

Commit

Permalink
Air Humidifier: Add strong mode property and update docstrings (#300)
Browse files Browse the repository at this point in the history
  • Loading branch information
syssi authored Aug 21, 2018
1 parent 2c25b3a commit ca9ae67
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 9 deletions.
67 changes: 59 additions & 8 deletions miio/airhumidifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import click

from .click_common import command, format_output, EnumType
from .device import Device, DeviceException
from .device import Device, DeviceInfo, DeviceException

_LOGGER = logging.getLogger(__name__)

Expand All @@ -20,6 +20,7 @@ class OperationMode(enum.Enum):
Medium = 'medium'
High = 'high'
Auto = 'auto'
Strong = 'strong'


class LedBrightness(enum.Enum):
Expand All @@ -31,7 +32,7 @@ class LedBrightness(enum.Enum):
class AirHumidifierStatus:
"""Container for status reports from the air humidifier."""

def __init__(self, data: Dict[str, Any]) -> None:
def __init__(self, data: Dict[str, Any], device_info: DeviceInfo) -> None:
"""
Response of a Air Humidifier (zhimi.humidifier.v1):
Expand All @@ -43,6 +44,7 @@ def __init__(self, data: Dict[str, Any]) -> None:
"""

self.data = data
self.device_info = device_info

@property
def power(self) -> str:
Expand Down Expand Up @@ -95,22 +97,56 @@ def target_humidity(self) -> int:

@property
def trans_level(self) -> int:
"""The meaning of the property is unknown."""
"""
The meaning of the property is unknown.
The property is used to determine the strong mode is enabled on old firmware.
"""
return self.data["trans_level"]

@property
def strong_mode_enabled(self) -> bool:
if self.firmware_version_minor == 25:
if self.trans_level == 90:
return True

elif self.firmware_version_minor > 25:
return self.mode.value == "strong"

return False

@property
def firmware_version(self) -> str:
"""Returns the fw_ver of miIO.info. For example 1.2.9_5033."""
return self.device_info.firmware_version

@property
def firmware_version_major(self) -> str:
major, _ = self.firmware_version.rsplit('_', 1)
return major

@property
def firmware_version_minor(self) -> int:
_, minor = self.firmware_version.rsplit('_', 1)
return int(minor)

@property
def speed(self) -> Optional[int]:
"""Current fan speed."""
return self.data["speed"]

@property
def depth(self) -> Optional[int]:
"""Current depth."""
"""The remaining amount of water in percent."""
return self.data["depth"]

@property
def dry(self) -> Optional[bool]:
"""Return True if dry mode is on if available."""
"""
Dry mode: The amount of water is not enough to continue to work for about 8 hours.
Return True if dry mode is on if available.
"""
if self.data["dry"] is not None:
return self.data["dry"] == "on"
return None
Expand Down Expand Up @@ -145,7 +181,10 @@ def __repr__(self) -> str:
"dry=%s, " \
"use_time=%s, " \
"hardware_version=%s, " \
"button_pressed=%s>" % \
"button_pressed=%s, " \
"strong_mode_enabled=%s, " \
"firmware_version_major=%s, " \
"firmware_version_minor=%s>" % \
(self.power,
self.mode,
self.temperature,
Expand All @@ -160,7 +199,10 @@ def __repr__(self) -> str:
self.dry,
self.use_time,
self.hardware_version,
self.button_pressed)
self.button_pressed,
self.strong_mode_enabled,
self.firmware_version_major,
self.firmware_version_minor)
return s

def __json__(self):
Expand All @@ -170,6 +212,12 @@ def __json__(self):
class AirHumidifier(Device):
"""Implementation of Xiaomi Mi Air Humidifier."""

def __init__(self, ip: str = None, token: str = None, start_id: int = 0,
debug: int = 0, lazy_discover: bool = True) -> None:
super().__init__(ip, token, start_id, debug, lazy_discover)

self.device_info = None

@command(
default_output=format_output(
"",
Expand All @@ -193,6 +241,9 @@ class AirHumidifier(Device):
def status(self) -> AirHumidifierStatus:
"""Retrieve properties."""

if self.device_info is None:
self.device_info = self.info()

properties = ['power', 'mode', 'temp_dec', 'humidity', 'buzzer',
'led_b', 'child_lock', 'limit_hum', 'trans_level',
'speed', 'depth', 'dry', 'use_time', 'button_pressed',
Expand All @@ -212,7 +263,7 @@ def status(self) -> AirHumidifierStatus:
properties_count, values_count)

return AirHumidifierStatus(
defaultdict(lambda: None, zip(properties, values)))
defaultdict(lambda: None, zip(properties, values)), self.device_info)

@command(
default_output=format_output("Powering on"),
Expand Down
36 changes: 35 additions & 1 deletion miio/tests/test_airhumidifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,32 @@
from miio.airhumidifier import (OperationMode, LedBrightness,
AirHumidifierStatus, AirHumidifierException, )
from .dummies import DummyDevice
from miio.device import DeviceInfo


class DummyAirHumidifier(DummyDevice, AirHumidifier):
def __init__(self, *args, **kwargs):
self.dummy_device_info = {
'fw_ver': '1.2.9_5033',
'token': '68ffffffffffffffffffffffffffffff',
'otu_stat': [101, 74, 5343, 0, 5327, 407],
'mmfree': 228248,
'netif': {'gw': '192.168.0.1',
'localIp': '192.168.0.25',
'mask': '255.255.255.0'},
'ott_stat': [0, 0, 0, 0],
'model': 'zhimi.humidifier.v1',
'cfg_time': 0,
'life': 575661,
'ap': {'rssi': -35, 'ssid': 'ap',
'bssid': 'FF:FF:FF:FF:FF:FF'},
'wifi_fw_ver': 'SD878x-14.76.36.p84-702.1.0-WM',
'hw_ver': 'MW300',
'ot': 'otu',
'mac': '78:11:FF:FF:FF:FF'
}
self.device_info = None

self.state = {
'power': 'on',
'mode': 'medium',
Expand Down Expand Up @@ -37,9 +59,14 @@ def __init__(self, *args, **kwargs):
'set_child_lock': lambda x: self._set_state("child_lock", x),
'set_limit_hum': lambda x: self._set_state("limit_hum", x),
'set_dry': lambda x: self._set_state("dry", x),
'miIO.info': self._get_device_info,
}
super().__init__(args, kwargs)

def _get_device_info(self, _):
"""Return dummy device info."""
return self.dummy_device_info


@pytest.fixture(scope="class")
def airhumidifier(request):
Expand Down Expand Up @@ -72,7 +99,9 @@ def test_off(self):
def test_status(self):
self.device._reset_state()

assert repr(self.state()) == repr(AirHumidifierStatus(self.device.start_state))
device_info = DeviceInfo(self.device.dummy_device_info)

assert repr(self.state()) == repr(AirHumidifierStatus(self.device.start_state, device_info))

assert self.is_on() is True
assert self.state().temperature == self.device.start_state["temp_dec"] / 10.0
Expand All @@ -90,6 +119,11 @@ def test_status(self):
assert self.state().hardware_version == self.device.start_state["hw_version"]
assert self.state().button_pressed == self.device.start_state["button_pressed"]

assert self.state().firmware_version == device_info.firmware_version
assert self.state().firmware_version_major == device_info.firmware_version.rsplit('_', 1)[0]
assert self.state().firmware_version_minor == int(device_info.firmware_version.rsplit('_', 1)[1])
assert self.state().strong_mode_enabled is False

def test_set_mode(self):
def mode():
return self.device.status().mode
Expand Down

0 comments on commit ca9ae67

Please sign in to comment.