Skip to content

Commit c97c1e5

Browse files
authored
Set zhimi.fan.za4 countdown timer to minutes (#1787)
1 parent 35a8773 commit c97c1e5

2 files changed

Lines changed: 84 additions & 0 deletions

File tree

miio/integrations/zhimi/fan/fan.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,18 @@ def button_pressed(self) -> Optional[str]:
226226
return None
227227

228228

229+
class FanStatusZA4(FanStatus):
230+
"""Container for status reports from the Xiaomi Mi Smart Pedestal Fan Zhimi ZA4."""
231+
232+
def __init__(self, data: Dict[str, Any]) -> None:
233+
self.data = data
234+
235+
@property
236+
def delay_off_countdown(self) -> int:
237+
"""Countdown until turning off in minutes."""
238+
return self.data["poweroff_time"] / 60
239+
240+
229241
class Fan(Device):
230242
"""Main class representing the Xiaomi Mi Smart Pedestal Fan."""
231243

@@ -246,6 +258,10 @@ def status(self) -> FanStatus:
246258

247259
values = self.get_properties(properties, max_properties=_props_per_request)
248260

261+
# The ZA4 has a countdown timer in minutes
262+
if self.model in [MODEL_FAN_ZA4]:
263+
return FanStatusZA4(dict(zip(properties, values)))
264+
249265
return FanStatus(dict(zip(properties, values)))
250266

251267
@command(default_output=format_output("Powering on"))
@@ -390,4 +406,8 @@ def delay_off(self, seconds: int):
390406
if seconds < 0:
391407
raise ValueError("Invalid value for a delayed turn off: %s" % seconds)
392408

409+
# Set delay countdown in minutes for model ZA4
410+
if self.model in [MODEL_FAN_ZA4]:
411+
return self.send("set_poweroff_time", [seconds * 60])
412+
393413
return self.send("set_poweroff_time", [seconds])

miio/integrations/zhimi/fan/test_fan.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
MODEL_FAN_SA1,
99
MODEL_FAN_V2,
1010
MODEL_FAN_V3,
11+
MODEL_FAN_ZA4,
1112
Fan,
1213
FanStatus,
1314
LedBrightness,
@@ -737,3 +738,66 @@ def delay_off_countdown():
737738

738739
with pytest.raises(ValueError):
739740
self.device.delay_off(-1)
741+
742+
743+
class DummyFanZA4(DummyDevice, Fan):
744+
def __init__(self, *args, **kwargs):
745+
self._model = MODEL_FAN_ZA4
746+
self.state = {
747+
"angle": 120,
748+
"speed": 277,
749+
"poweroff_time": 0,
750+
"power": "on",
751+
"ac_power": "on",
752+
"angle_enable": "off",
753+
"speed_level": 1,
754+
"natural_level": 2,
755+
"child_lock": "off",
756+
"buzzer": 0,
757+
"led_b": 0,
758+
"use_time": 2318,
759+
}
760+
761+
self.return_values = {
762+
"get_prop": self._get_state,
763+
"set_power": lambda x: self._set_state("power", x),
764+
"set_speed_level": lambda x: self._set_state("speed_level", x),
765+
"set_natural_level": lambda x: self._set_state("natural_level", x),
766+
"set_move": lambda x: True,
767+
"set_angle": lambda x: self._set_state("angle", x),
768+
"set_angle_enable": lambda x: self._set_state("angle_enable", x),
769+
"set_led_b": lambda x: self._set_state("led_b", x),
770+
"set_buzzer": lambda x: self._set_state("buzzer", x),
771+
"set_child_lock": lambda x: self._set_state("child_lock", x),
772+
"set_poweroff_time": lambda x: self._set_state("poweroff_time", x),
773+
}
774+
super().__init__(args, kwargs)
775+
776+
777+
@pytest.fixture(scope="class")
778+
def fanza4(request):
779+
request.cls.device = DummyFanZA4()
780+
# TODO add ability to test on a real device
781+
782+
783+
@pytest.mark.usefixtures("fanza4")
784+
class TestFanZA4(TestCase):
785+
def is_on(self):
786+
return self.device.status().is_on
787+
788+
def state(self):
789+
return self.device.status()
790+
791+
def test_delay_off(self):
792+
def delay_off_countdown():
793+
return self.device.status().delay_off_countdown
794+
795+
self.device.delay_off(100)
796+
assert delay_off_countdown() == 100
797+
self.device.delay_off(200)
798+
assert delay_off_countdown() == 200
799+
self.device.delay_off(0)
800+
assert delay_off_countdown() == 0
801+
802+
with pytest.raises(ValueError):
803+
self.device.delay_off(-1)

0 commit comments

Comments
 (0)