Skip to content
New issue

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

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

Already on GitHub? # to your account

Air Humidifier: Strong mode property added and docstrings updated #300

Merged
merged 7 commits into from
Aug 21, 2018
Merged
Show file tree
Hide file tree
Changes from all 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
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'},

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

continuation line under-indented for visual indent

'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])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (105 > 100 characters)

assert self.state().strong_mode_enabled is False

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