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", "name": "Xiaomi Miio",
"config_flow": true, "config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/xiaomi_miio", "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"], "codeowners": ["@rytilahti", "@syssi"],
"zeroconf": ["_miio._udp.local."] "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.const import CONF_HOST, CONF_NAME, CONF_TOKEN, STATE_OFF, STATE_ON
from homeassistant.helpers import config_validation as cv, entity_platform from homeassistant.helpers import config_validation as cv, entity_platform
from homeassistant.util.dt import as_utc
from .const import ( from .const import (
SERVICE_CLEAN_ZONE, SERVICE_CLEAN_ZONE,
@ -72,6 +73,7 @@ ATTR_RC_VELOCITY = "velocity"
ATTR_STATUS = "status" ATTR_STATUS = "status"
ATTR_ZONE_ARRAY = "zone" ATTR_ZONE_ARRAY = "zone"
ATTR_ZONE_REPEATER = "repeats" ATTR_ZONE_REPEATER = "repeats"
ATTR_TIMERS = "timers"
SUPPORT_XIAOMI = ( SUPPORT_XIAOMI = (
SUPPORT_STATE SUPPORT_STATE
@ -216,6 +218,8 @@ class MiroboVacuum(StateVacuumEntity):
self._fan_speeds = None self._fan_speeds = None
self._fan_speeds_reverse = None self._fan_speeds_reverse = None
self._timers = None
@property @property
def name(self): def name(self):
"""Return the name of the device.""" """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.""" """Get the list of available fan speed steps of the vacuum cleaner."""
return list(self._fan_speeds) if self._fan_speeds else [] 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 @property
def device_state_attributes(self): def device_state_attributes(self):
"""Return the specific state attributes of this vacuum cleaner.""" """Return the specific state attributes of this vacuum cleaner."""
@ -307,6 +323,9 @@ class MiroboVacuum(StateVacuumEntity):
if self.vacuum_state.got_error: if self.vacuum_state.got_error:
attrs[ATTR_ERROR] = self.vacuum_state.error attrs[ATTR_ERROR] = self.vacuum_state.error
if self.timers:
attrs[ATTR_TIMERS] = self.timers
return attrs return attrs
@property @property
@ -442,6 +461,8 @@ class MiroboVacuum(StateVacuumEntity):
self.last_clean = self._vacuum.last_clean_details() self.last_clean = self._vacuum.last_clean_details()
self.dnd_state = self._vacuum.dnd_status() self.dnd_state = self._vacuum.dnd_status()
self._timers = self._vacuum.timer()
self._available = True self._available = True
except OSError as exc: except OSError as exc:
_LOGGER.error("Got OSError while fetching the state: %s", 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 # python-lirc==1.2.3
# homeassistant.components.xiaomi_miio # homeassistant.components.xiaomi_miio
python-miio==0.5.0.1 python-miio==0.5.1
# homeassistant.components.mpd # homeassistant.components.mpd
python-mpd2==1.0.0 python-mpd2==1.0.0

View File

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

View File

@ -1,8 +1,9 @@
"""The tests for the Xiaomi vacuum platform.""" """The tests for the Xiaomi vacuum platform."""
from datetime import time, timedelta from datetime import datetime, time, timedelta
from unittest import mock from unittest import mock
import pytest import pytest
from pytz import utc
from homeassistant.components.vacuum import ( from homeassistant.components.vacuum import (
ATTR_BATTERY_ICON, ATTR_BATTERY_ICON,
@ -33,6 +34,7 @@ from homeassistant.components.xiaomi_miio.vacuum import (
ATTR_FILTER_LEFT, ATTR_FILTER_LEFT,
ATTR_MAIN_BRUSH_LEFT, ATTR_MAIN_BRUSH_LEFT,
ATTR_SIDE_BRUSH_LEFT, ATTR_SIDE_BRUSH_LEFT,
ATTR_TIMERS,
CONF_HOST, CONF_HOST,
CONF_NAME, CONF_NAME,
CONF_TOKEN, CONF_TOKEN,
@ -60,6 +62,7 @@ STATUS_CALLS = [
mock.call.consumable_status(), mock.call.consumable_status(),
mock.call.clean_history(), mock.call.clean_history(),
mock.call.dnd_status(), 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().start = time(hour=22, minute=0)
mock_vacuum.dnd_status().end = time(hour=6, 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( with mock.patch(
"homeassistant.components.xiaomi_miio.vacuum.Vacuum" "homeassistant.components.xiaomi_miio.vacuum.Vacuum"
) as mock_vaccum_cls: ) as mock_vaccum_cls:
@ -160,6 +175,18 @@ def mirobo_is_on_fixture():
mock_vacuum.status().state_code = 5 mock_vacuum.status().state_code = 5
mock_vacuum.dnd_status().enabled = False 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( with mock.patch(
"homeassistant.components.xiaomi_miio.vacuum.Vacuum" "homeassistant.components.xiaomi_miio.vacuum.Vacuum"
) as mock_vaccum_cls: ) 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_CLEANING_COUNT) == 35
assert state.attributes.get(ATTR_CLEANED_TOTAL_AREA) == 123 assert state.attributes.get(ATTR_CLEANED_TOTAL_AREA) == 123
assert state.attributes.get(ATTR_CLEANING_TOTAL_TIME) == 695 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 # Call services
await hass.services.async_call( 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_CLEANING_COUNT) == 41
assert state.attributes.get(ATTR_CLEANED_TOTAL_AREA) == 323 assert state.attributes.get(ATTR_CLEANED_TOTAL_AREA) == 323
assert state.attributes.get(ATTR_CLEANING_TOTAL_TIME) == 675 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: # Xiaomi vacuum specific services:
await hass.services.async_call( await hass.services.async_call(