Add timers to xiaomi_miio vacuum (#35417)

* Add timers to xiaomi_miio vacuum

* Add timezone

* Add cron and next_schedule

* Use next_schedule from backend library

* Use as_utc from utils
This commit is contained in:
MarBra 2020-06-12 06:39:19 +02:00 committed by GitHub
parent 8e44d797a3
commit 44708ed8bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 76 additions and 4 deletions

View File

@ -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.1"],
"codeowners": ["@rytilahti", "@syssi"],
"zeroconf": ["_miio._udp.local."]
}

View File

@ -28,6 +28,7 @@ from homeassistant.components.vacuum import (
)
from homeassistant.const import CONF_HOST, CONF_NAME, CONF_TOKEN, STATE_OFF, STATE_ON
from homeassistant.helpers import config_validation as cv, entity_platform
from homeassistant.util.dt import as_utc
from .const import (
SERVICE_CLEAN_ZONE,
@ -72,6 +73,7 @@ ATTR_RC_VELOCITY = "velocity"
ATTR_STATUS = "status"
ATTR_ZONE_ARRAY = "zone"
ATTR_ZONE_REPEATER = "repeats"
ATTR_TIMERS = "timers"
SUPPORT_XIAOMI = (
SUPPORT_STATE
@ -216,6 +218,8 @@ class MiroboVacuum(StateVacuumEntity):
self._fan_speeds = None
self._fan_speeds_reverse = None
self._timers = None
@property
def name(self):
"""Return the name of the device."""
@ -262,6 +266,18 @@ class MiroboVacuum(StateVacuumEntity):
"""Get the list of available fan speed steps of the vacuum cleaner."""
return list(self._fan_speeds) if self._fan_speeds else []
@property
def timers(self):
"""Get the list of added timers of the vacuum cleaner."""
return [
{
"enabled": timer.enabled,
"cron": timer.cron,
"next_schedule": as_utc(timer.next_schedule),
}
for timer in self._timers
]
@property
def device_state_attributes(self):
"""Return the specific state attributes of this vacuum cleaner."""
@ -307,6 +323,9 @@ class MiroboVacuum(StateVacuumEntity):
if self.vacuum_state.got_error:
attrs[ATTR_ERROR] = self.vacuum_state.error
if self.timers:
attrs[ATTR_TIMERS] = self.timers
return attrs
@property
@ -442,6 +461,8 @@ class MiroboVacuum(StateVacuumEntity):
self.last_clean = self._vacuum.last_clean_details()
self.dnd_state = self._vacuum.dnd_status()
self._timers = self._vacuum.timer()
self._available = True
except OSError as exc:
_LOGGER.error("Got OSError while fetching the state: %s", exc)

View File

@ -1702,7 +1702,7 @@ python-juicenet==1.0.1
# python-lirc==1.2.3
# homeassistant.components.xiaomi_miio
python-miio==0.5.0.1
python-miio==0.5.1
# homeassistant.components.mpd
python-mpd2==1.0.0

View File

@ -717,7 +717,7 @@ python-izone==1.1.2
python-juicenet==1.0.1
# homeassistant.components.xiaomi_miio
python-miio==0.5.0.1
python-miio==0.5.1
# homeassistant.components.nest
python-nest==4.1.0

View File

@ -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,
@ -33,6 +34,7 @@ from homeassistant.components.xiaomi_miio.vacuum import (
ATTR_FILTER_LEFT,
ATTR_MAIN_BRUSH_LEFT,
ATTR_SIDE_BRUSH_LEFT,
ATTR_TIMERS,
CONF_HOST,
CONF_NAME,
CONF_TOKEN,
@ -60,6 +62,7 @@ STATUS_CALLS = [
mock.call.consumable_status(),
mock.call.clean_history(),
mock.call.dnd_status(),
mock.call.timer(),
]
@ -94,6 +97,18 @@ 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_timer_1 = mock.MagicMock()
mock_timer_1.enabled = True
mock_timer_1.cron = "5 5 1 8 1"
mock_timer_1.next_schedule = datetime(2020, 5, 23, 13, 21, 10, tzinfo=utc)
mock_timer_2 = mock.MagicMock()
mock_timer_2.enabled = False
mock_timer_2.cron = "5 5 1 8 2"
mock_timer_2.next_schedule = datetime(2020, 5, 23, 13, 21, 10, tzinfo=utc)
mock_vacuum.timer.return_value = [mock_timer_1, mock_timer_2]
with mock.patch(
"homeassistant.components.xiaomi_miio.vacuum.Vacuum"
) as mock_vaccum_cls:
@ -160,6 +175,18 @@ def mirobo_is_on_fixture():
mock_vacuum.status().state_code = 5
mock_vacuum.dnd_status().enabled = False
mock_timer_1 = mock.MagicMock()
mock_timer_1.enabled = True
mock_timer_1.cron = "5 5 1 8 1"
mock_timer_1.next_schedule = datetime(2020, 5, 23, 13, 21, 10, tzinfo=utc)
mock_timer_2 = mock.MagicMock()
mock_timer_2.enabled = False
mock_timer_2.cron = "5 5 1 8 2"
mock_timer_2.next_schedule = datetime(2020, 5, 23, 13, 21, 10, tzinfo=utc)
mock_vacuum.timer.return_value = [mock_timer_1, mock_timer_2]
with mock.patch(
"homeassistant.components.xiaomi_miio.vacuum.Vacuum"
) as mock_vaccum_cls:
@ -241,6 +268,18 @@ 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_TIMERS) == [
{
"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),
},
]
# Call services
await hass.services.async_call(
@ -341,6 +380,18 @@ 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_TIMERS) == [
{
"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),
},
]
# Xiaomi vacuum specific services:
await hass.services.async_call(