Skip to content

Commit

Permalink
New properties of the Xiaomi Air Humidifier added (#173)
Browse files Browse the repository at this point in the history
* New properties added: child_lock, limit_hum, trans_level
  trans_level is a read-only property and depends on the operation mode.
* Tests extended.
  • Loading branch information
syssi committed Jan 25, 2018
1 parent 047704a commit 79c2904
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 10 deletions.
63 changes: 56 additions & 7 deletions miio/airhumidifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@
import enum
from typing import Any, Dict, Optional
from collections import defaultdict
from .device import Device
from .device import Device, DeviceException

_LOGGER = logging.getLogger(__name__)


class AirHumidifierException(DeviceException):
pass


class OperationMode(enum.Enum):
Silent = 'silent'
Medium = 'medium'
Expand All @@ -27,7 +31,8 @@ def __init__(self, data: Dict[str, Any]) -> None:
Response of a Air Humidifier (zhimi.humidifier.v1):
{'power': 'off', 'mode': 'high', 'temp_dec': 294,
'humidity': 33, 'buzzer': 'on', 'led_b': 0}
'humidity': 33, 'buzzer': 'on', 'led_b': 0,
'child_lock': 'on', 'limit_hum': 40, 'trans_level': 85}
"""

self.data = data
Expand Down Expand Up @@ -71,11 +76,40 @@ def led_brightness(self) -> Optional[LedBrightness]:
return LedBrightness(self.data["led_b"])
return None

@property
def child_lock(self) -> bool:
"""Return True if child lock is on."""
return self.data["child_lock"] == "on"

@property
def target_humidity(self) -> int:
"""Target humiditiy. Can be either 30, 40, 50, 60, 70, 80 percent."""
return self.data["limit_hum"]

@property
def trans_level(self) -> int:
"""The meaning of the property is unknown."""
return self.data["trans_level"]

def __str__(self) -> str:
s = "<AirHumidiferStatus power=%s, mode=%s, temperature=%s, " \
"humidity=%s%%, led_brightness=%s, buzzer=%s>" % \
(self.power, self.mode, self.temperature,
self.humidity, self.led_brightness, self.buzzer)
s = "<AirHumidiferStatus power=%s, " \
"mode=%s, " \
"temperature=%s, " \
"humidity=%s%%, " \
"led_brightness=%s, " \
"buzzer=%s, " \
"child_lock=%s, " \
"target_humidity=%s%%, " \
"trans_level=%s>" % \
(self.power,
self.mode,
self.temperature,
self.humidity,
self.led_brightness,
self.buzzer,
self.child_lock,
self.target_humidity,
self.trans_level)
return s


Expand All @@ -86,7 +120,7 @@ def status(self) -> AirHumidifierStatus:
"""Retrieve properties."""

properties = ['power', 'mode', 'temp_dec', 'humidity', 'buzzer',
'led_b', ]
'led_b', 'child_lock', 'limit_hum', 'trans_level', ]

values = self.send(
"get_prop",
Expand Down Expand Up @@ -126,3 +160,18 @@ def set_buzzer(self, buzzer: bool):
return self.send("set_buzzer", ["on"])
else:
return self.send("set_buzzer", ["off"])

def set_child_lock(self, lock: bool):
"""Set child lock on/off."""
if lock:
return self.send("set_child_lock", ["on"])
else:
return self.send("set_child_lock", ["off"])

def set_target_humidity(self, humidity: int):
"""Set the target humidity."""
if humidity not in [30, 40, 50, 60, 70, 80]:
raise AirHumidifierException(
"Invalid target humidity: %s" % humidity)

return self.send("set_limit_hum", [humidity])
47 changes: 44 additions & 3 deletions miio/tests/test_airhumidifier.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from unittest import TestCase
from miio import AirHumidifier
from miio.airhumidifier import OperationMode, LedBrightness
from miio.airhumidifier import OperationMode, LedBrightness, AirHumidifierException
from .dummies import DummyDevice
import pytest

Expand All @@ -10,17 +10,22 @@ def __init__(self, *args, **kwargs):
self.state = {
'power': 'on',
'mode': 'medium',
'temp_dec': 186,
'humidity': 62,
'temp_dec': 294,
'humidity': 33,
'buzzer': 'off',
'led_b': 2,
'child_lock': 'on',
'limit_hum': 40,
'trans_level': 85,
}
self.return_values = {
'get_prop': self._get_state,
'set_power': lambda x: self._set_state("power", x),
'set_mode': lambda x: self._set_state("mode", x),
'set_led_b': lambda x: self._set_state("led_b", x),
'set_buzzer': lambda x: self._set_state("buzzer", x),
'set_child_lock': lambda x: self._set_state("child_lock", x),
'set_limit_hum': lambda x: self._set_state("limit_hum", x),
}
super().__init__(args, kwargs)

Expand Down Expand Up @@ -64,6 +69,9 @@ def test_status(self):
assert self.state().mode == OperationMode(self.device.start_state["mode"])
assert self.state().led_brightness == LedBrightness(self.device.start_state["led_b"])
assert self.state().buzzer == (self.device.start_state["buzzer"] == 'on')
assert self.state().child_lock == (self.device.start_state["child_lock"] == 'on')
assert self.state().target_humidity == self.device.start_state["limit_hum"]
assert self.state().trans_level == self.device.start_state["trans_level"]

def test_set_mode(self):
def mode():
Expand Down Expand Up @@ -112,3 +120,36 @@ def test_status_without_led_brightness(self):
self.device.state["led_b"] = None

assert self.state().led_brightness is None

def test_set_target_humidity(self):
def target_humidity():
return self.device.status().target_humidity

self.device.set_target_humidity(30)
assert target_humidity() == 30
self.device.set_target_humidity(60)
assert target_humidity() == 60
self.device.set_target_humidity(80)
assert target_humidity() == 80

with pytest.raises(AirHumidifierException):
self.device.set_target_humidity(-1)

with pytest.raises(AirHumidifierException):
self.device.set_target_humidity(20)

with pytest.raises(AirHumidifierException):
self.device.set_target_humidity(90)

with pytest.raises(AirHumidifierException):
self.device.set_target_humidity(110)

def test_set_child_lock(self):
def child_lock():
return self.device.status().child_lock

self.device.set_child_lock(True)
assert child_lock() is True

self.device.set_child_lock(False)
assert child_lock() is False

0 comments on commit 79c2904

Please sign in to comment.