Skip to content

Commit

Permalink
Set zhimi.fan.za4 countdown timer to minutes (#1787)
Browse files Browse the repository at this point in the history
  • Loading branch information
alex3305 authored Mar 13, 2024
1 parent 35a8773 commit c97c1e5
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
20 changes: 20 additions & 0 deletions miio/integrations/zhimi/fan/fan.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,18 @@ def button_pressed(self) -> Optional[str]:
return None


class FanStatusZA4(FanStatus):
"""Container for status reports from the Xiaomi Mi Smart Pedestal Fan Zhimi ZA4."""

def __init__(self, data: Dict[str, Any]) -> None:
self.data = data

@property
def delay_off_countdown(self) -> int:
"""Countdown until turning off in minutes."""
return self.data["poweroff_time"] / 60


class Fan(Device):
"""Main class representing the Xiaomi Mi Smart Pedestal Fan."""

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

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

# The ZA4 has a countdown timer in minutes
if self.model in [MODEL_FAN_ZA4]:
return FanStatusZA4(dict(zip(properties, values)))

return FanStatus(dict(zip(properties, values)))

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

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

return self.send("set_poweroff_time", [seconds])
64 changes: 64 additions & 0 deletions miio/integrations/zhimi/fan/test_fan.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
MODEL_FAN_SA1,
MODEL_FAN_V2,
MODEL_FAN_V3,
MODEL_FAN_ZA4,
Fan,
FanStatus,
LedBrightness,
Expand Down Expand Up @@ -737,3 +738,66 @@ def delay_off_countdown():

with pytest.raises(ValueError):
self.device.delay_off(-1)


class DummyFanZA4(DummyDevice, Fan):
def __init__(self, *args, **kwargs):
self._model = MODEL_FAN_ZA4
self.state = {
"angle": 120,
"speed": 277,
"poweroff_time": 0,
"power": "on",
"ac_power": "on",
"angle_enable": "off",
"speed_level": 1,
"natural_level": 2,
"child_lock": "off",
"buzzer": 0,
"led_b": 0,
"use_time": 2318,
}

self.return_values = {
"get_prop": self._get_state,
"set_power": lambda x: self._set_state("power", x),
"set_speed_level": lambda x: self._set_state("speed_level", x),
"set_natural_level": lambda x: self._set_state("natural_level", x),
"set_move": lambda x: True,
"set_angle": lambda x: self._set_state("angle", x),
"set_angle_enable": lambda x: self._set_state("angle_enable", 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_poweroff_time": lambda x: self._set_state("poweroff_time", x),
}
super().__init__(args, kwargs)


@pytest.fixture(scope="class")
def fanza4(request):
request.cls.device = DummyFanZA4()
# TODO add ability to test on a real device


@pytest.mark.usefixtures("fanza4")
class TestFanZA4(TestCase):
def is_on(self):
return self.device.status().is_on

def state(self):
return self.device.status()

def test_delay_off(self):
def delay_off_countdown():
return self.device.status().delay_off_countdown

self.device.delay_off(100)
assert delay_off_countdown() == 100
self.device.delay_off(200)
assert delay_off_countdown() == 200
self.device.delay_off(0)
assert delay_off_countdown() == 0

with pytest.raises(ValueError):
self.device.delay_off(-1)

0 comments on commit c97c1e5

Please sign in to comment.