Skip to content

Commit

Permalink
Add cron and next_schedule
Browse files Browse the repository at this point in the history
  • Loading branch information
MarBra committed May 23, 2020
1 parent 06f83de commit cf95051
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 19 deletions.
2 changes: 1 addition & 1 deletion homeassistant/components/xiaomi_miio/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "Xiaomi Miio",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/xiaomi_miio",
"requirements": ["construct==2.9.45", "python-miio==0.5.0.1"],
"requirements": ["construct==2.9.45", "python-miio==0.5.0.1", "croniter==0.3.31"],
"codeowners": ["@rytilahti", "@syssi"],
"zeroconf": ["_miio._udp.local."]
}
21 changes: 20 additions & 1 deletion homeassistant/components/xiaomi_miio/vacuum.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
"""Support for the Xiaomi vacuum cleaner robot."""
import asyncio
from datetime import datetime
from functools import partial
import logging

from croniter import croniter
from miio import DeviceException, Vacuum # pylint: disable=import-error
from pytz import all_timezones, timezone, utc
import voluptuous as vol

from homeassistant.components.vacuum import (
Expand Down Expand Up @@ -301,7 +304,23 @@ def fan_speed_list(self):
@property
def timers(self):
"""Get the list of added timers of the vacuum cleaner."""
return [{"enabled": timer.enabled, "time": timer.ts} for timer in self._timers]
if self.timezone not in all_timezones:
return []

timers = []
local_tz = timezone(self.timezone)

for timer in self._timers:
cron = croniter(timer.cron, start_time=local_tz.localize(datetime.now()))
next_schedule = cron.get_next(ret_type=datetime)
timers.append(
{
"enabled": timer.enabled,
"cron": timer.cron,
"next_schedule": next_schedule.astimezone(utc),
}
)
return timers

@property
def device_state_attributes(self):
Expand Down
3 changes: 3 additions & 0 deletions requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,9 @@ coronavirus==1.1.0
# homeassistant.components.crimereports
crimereports==1.0.1

# homeassistant.components.xiaomi_miio
croniter==0.3.31

# homeassistant.components.datadog
datadog==0.15.0

Expand Down
3 changes: 3 additions & 0 deletions requirements_test_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ coronavirus==1.1.0
# homeassistant.scripts.credstash
# credstash==1.15.0

# homeassistant.components.xiaomi_miio
croniter==0.3.31

# homeassistant.components.datadog
datadog==0.15.0

Expand Down
58 changes: 41 additions & 17 deletions tests/components/xiaomi_miio/test_vacuum.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""The tests for the Xiaomi vacuum platform."""
from datetime import time, timedelta
from datetime import datetime, time, timedelta
from unittest import mock

import pytest
from pytz import utc

from homeassistant.components.vacuum import (
ATTR_BATTERY_ICON,
Expand Down Expand Up @@ -61,6 +62,7 @@
mock.call.consumable_status(),
mock.call.clean_history(),
mock.call.dnd_status(),
mock.call.timezone(),
mock.call.timer(),
]

Expand Down Expand Up @@ -96,22 +98,25 @@ def mirobo_is_got_error_fixture():
mock_vacuum.dnd_status().start = time(hour=22, minute=0)
mock_vacuum.dnd_status().end = time(hour=6, minute=0)

mock_vacuum.timezone.return_value = "Europe/Berlin"

mock_timer_1 = mock.MagicMock()
mock_timer_1.enabled = True
mock_timer_1.ts = time(hour=9, minute=0)
mock_timer_1.cron = "5 5 1 8 1"

mock_timer_2 = mock.MagicMock()
mock_timer_2.enabled = False
mock_timer_2.ts = time(hour=11, minute=0)
mock_timer_2.cron = "5 5 1 8 2"

mock_vacuum.timer.return_value = [mock_timer_1, mock_timer_2]

mock_vacuum.timezone.return_value = "Europe/Berlin"

with mock.patch(
"homeassistant.components.xiaomi_miio.vacuum.Vacuum"
) as mock_vaccum_cls:
) as mock_vaccum_cls, mock.patch(
"homeassistant.components.xiaomi_miio.vacuum.croniter.get_next"
) as mock_next_schedule:
mock_vaccum_cls.return_value = mock_vacuum
mock_next_schedule.return_value = datetime(2020, 5, 23, 15, 21, 10)
yield mock_vacuum


Expand Down Expand Up @@ -174,22 +179,25 @@ def mirobo_is_on_fixture():
mock_vacuum.status().state_code = 5
mock_vacuum.dnd_status().enabled = False

mock_vacuum.timezone.return_value = "Europe/Berlin"

mock_timer_1 = mock.MagicMock()
mock_timer_1.enabled = True
mock_timer_1.ts = time(hour=9, minute=0)
mock_timer_1.cron = "5 5 1 8 1"

mock_timer_2 = mock.MagicMock()
mock_timer_2.enabled = False
mock_timer_2.ts = time(hour=11, minute=0)
mock_timer_2.cron = "5 5 1 8 2"

mock_vacuum.timer.return_value = [mock_timer_1, mock_timer_2]

mock_vacuum.timezone.return_value = "Europe/Berlin"

with mock.patch(
"homeassistant.components.xiaomi_miio.vacuum.Vacuum"
) as mock_vaccum_cls:
) as mock_vaccum_cls, mock.patch(
"homeassistant.components.xiaomi_miio.vacuum.croniter.get_next"
) as mock_next_schedule:
mock_vaccum_cls.return_value = mock_vacuum
mock_next_schedule.return_value = datetime(2020, 5, 23, 15, 21, 10)
yield mock_vacuum


Expand Down Expand Up @@ -267,11 +275,19 @@ async def test_xiaomi_vacuum_services(hass, caplog, mock_mirobo_is_got_error):
assert state.attributes.get(ATTR_CLEANING_COUNT) == 35
assert state.attributes.get(ATTR_CLEANED_TOTAL_AREA) == 123
assert state.attributes.get(ATTR_CLEANING_TOTAL_TIME) == 695
assert state.attributes.get(ATTR_TIMEZONE) == "Europe/Berlin"
assert state.attributes.get(ATTR_TIMERS) == [
{"enabled": True, "time": time(hour=9, minute=0)},
{"enabled": False, "time": time(hour=11, minute=0)},
{
"enabled": True,
"cron": "5 5 1 8 1",
"next_schedule": datetime(2020, 5, 23, 13, 21, 10, tzinfo=utc),
},
{
"enabled": False,
"cron": "5 5 1 8 2",
"next_schedule": datetime(2020, 5, 23, 13, 21, 10, tzinfo=utc),
},
]
assert state.attributes.get(ATTR_TIMEZONE) == "Europe/Berlin"

# Call services
await hass.services.async_call(
Expand Down Expand Up @@ -372,11 +388,19 @@ async def test_xiaomi_specific_services(hass, caplog, mock_mirobo_is_on):
assert state.attributes.get(ATTR_CLEANING_COUNT) == 41
assert state.attributes.get(ATTR_CLEANED_TOTAL_AREA) == 323
assert state.attributes.get(ATTR_CLEANING_TOTAL_TIME) == 675
assert state.attributes.get(ATTR_TIMEZONE) == "Europe/Berlin"
assert state.attributes.get(ATTR_TIMERS) == [
{"enabled": True, "time": time(hour=9, minute=0)},
{"enabled": False, "time": time(hour=11, minute=0)},
{
"enabled": True,
"cron": "5 5 1 8 1",
"next_schedule": datetime(2020, 5, 23, 13, 21, 10, tzinfo=utc),
},
{
"enabled": False,
"cron": "5 5 1 8 2",
"next_schedule": datetime(2020, 5, 23, 13, 21, 10, tzinfo=utc),
},
]
assert state.attributes.get(ATTR_TIMEZONE) == "Europe/Berlin"

# Xiaomi vacuum specific services:
await hass.services.async_call(
Expand Down

0 comments on commit cf95051

Please sign in to comment.