From 5115dfada2df8a4277c39b213ff1ca5eb761bd00 Mon Sep 17 00:00:00 2001 From: Marco Gazzola Date: Wed, 20 Feb 2019 15:44:04 +0100 Subject: [PATCH] Add zone and reps for Xiaomi vacuum (#19777) * xiaomi vacuum with zone and reps * tail whitespace * tail whitespaces * new version * fix params typs * fix param type * line length * rytilahti tips * houndci-bot * fix trevis * rytilahti tips * service description * syssi fix * MartinHjelmare tips * MartinHjelmare * data_template schema * line lenght * line lenght * line lenght * data_template schema * fix * Update homeassistant/components/vacuum/xiaomi_miio.py Co-Authored-By: marcogazzola * Update homeassistant/components/vacuum/xiaomi_miio.py Co-Authored-By: marcogazzola * xiaomi vacuum with zone and reps * tail whitespace * new version * fix param type * rytilahti tips * rytilahti tips * MartinHjelmare * data_template schema * line lenght * line lenght * data_template schema * fix * Merge branch 'dev' of https://github.com/marcogazzola/home-assistant into dev * Revert "Merge branch 'dev' of https://github.com/marcogazzola/home-assistant into dev" This reverts commit e1f370b3b45d2541c8117146b0940d7c2b5bc8b0. * log fixed * Revert "log fixed" This reverts commit 1f0e7b35e81154af476a0bf1ae00773180cadb98. * Revert "Revert "Merge branch 'dev' of https://github.com/marcogazzola/home-assistant into dev"" This reverts commit 1cf9e5ae1f5c1c0504fbf59763b39c6a5656cb91. * Revert "Merge branch 'dev' of https://github.com/marcogazzola/home-assistant into dev" This reverts commit 0e8d53449a98fd33756397f31a891dd0d4d206ce. * log fixed --- homeassistant/components/vacuum/services.yaml | 13 ++++++ .../components/xiaomi_miio/vacuum.py | 41 +++++++++++++++++++ tests/components/xiaomi_miio/test_vacuum.py | 13 +++++- 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/vacuum/services.yaml b/homeassistant/components/vacuum/services.yaml index 6e40b3d67fc8eb..792658bbdfd074 100644 --- a/homeassistant/components/vacuum/services.yaml +++ b/homeassistant/components/vacuum/services.yaml @@ -131,3 +131,16 @@ xiaomi_remote_control_move_step: duration: description: Duration of the movement. example: '1500' + +xiaomi_clean_zone: + description: Start the cleaning operation in the selected areas for the number of repeats indicated. + fields: + entity_id: + description: Name of the vacuum entity. + example: 'vacuum.xiaomi_vacuum_cleaner' + zone: + description: Array of zones. Each zone is an array of 4 integer values. + example: '[[23510,25311,25110,26362]]' + repeats: + description: Number of cleaning repeats for each zone between 1 and 3. + example: '1' diff --git a/homeassistant/components/xiaomi_miio/vacuum.py b/homeassistant/components/xiaomi_miio/vacuum.py index 82a92dd317cc85..361961586008b3 100644 --- a/homeassistant/components/xiaomi_miio/vacuum.py +++ b/homeassistant/components/xiaomi_miio/vacuum.py @@ -33,6 +33,7 @@ SERVICE_MOVE_REMOTE_CONTROL_STEP = 'xiaomi_remote_control_move_step' SERVICE_START_REMOTE_CONTROL = 'xiaomi_remote_control_start' SERVICE_STOP_REMOTE_CONTROL = 'xiaomi_remote_control_stop' +SERVICE_CLEAN_ZONE = 'xiaomi_clean_zone' FAN_SPEEDS = { 'Quiet': 38, @@ -58,6 +59,8 @@ ATTR_RC_ROTATION = 'rotation' ATTR_RC_VELOCITY = 'velocity' ATTR_STATUS = 'status' +ATTR_ZONE_ARRAY = 'zone' +ATTR_ZONE_REPEATER = 'repeats' SERVICE_SCHEMA_REMOTE_CONTROL = VACUUM_SERVICE_SCHEMA.extend({ vol.Optional(ATTR_RC_VELOCITY): @@ -67,6 +70,24 @@ vol.Optional(ATTR_RC_DURATION): cv.positive_int, }) +SERVICE_SCHEMA_CLEAN_ZONE = VACUUM_SERVICE_SCHEMA.extend({ + vol.Required(ATTR_ZONE_ARRAY): + vol.All(list, [vol.ExactSequence( + [vol.Coerce(int), vol.Coerce(int), + vol.Coerce(int), vol.Coerce(int)])]), + vol.Required(ATTR_ZONE_REPEATER): + vol.All(vol.Coerce(int), vol.Clamp(min=1, max=3)), +}) + +SERVICE_SCHEMA_CLEAN_ZONE = VACUUM_SERVICE_SCHEMA.extend({ + vol.Required(ATTR_ZONE_ARRAY): + vol.All(list, [vol.ExactSequence( + [vol.Coerce(int), vol.Coerce(int), + vol.Coerce(int), vol.Coerce(int)])]), + vol.Required(ATTR_ZONE_REPEATER): + vol.All(vol.Coerce(int), vol.Clamp(min=1, max=3)), +}) + SERVICE_TO_METHOD = { SERVICE_START_REMOTE_CONTROL: {'method': 'async_remote_control_start'}, SERVICE_STOP_REMOTE_CONTROL: {'method': 'async_remote_control_stop'}, @@ -76,6 +97,9 @@ SERVICE_MOVE_REMOTE_CONTROL_STEP: { 'method': 'async_remote_control_move_step', 'schema': SERVICE_SCHEMA_REMOTE_CONTROL}, + SERVICE_CLEAN_ZONE: { + 'method': 'async_clean_zone', + 'schema': SERVICE_SCHEMA_CLEAN_ZONE}, } SUPPORT_XIAOMI = SUPPORT_STATE | SUPPORT_PAUSE | \ @@ -127,6 +151,7 @@ async def async_service_handler(service): params = {key: value for key, value in service.data.items() if key != ATTR_ENTITY_ID} entity_ids = service.data.get(ATTR_ENTITY_ID) + if entity_ids: target_vacuums = [vac for vac in hass.data[DATA_KEY].values() if vac.entity_id in entity_ids] @@ -377,3 +402,19 @@ def update(self): _LOGGER.error("Got OSError while fetching the state: %s", exc) except DeviceException as exc: _LOGGER.warning("Got exception while fetching the state: %s", exc) + + async def async_clean_zone(self, + zone, + repeats=1): + """Clean selected area for the number of repeats indicated.""" + from miio import DeviceException + for _zone in zone: + _zone.append(repeats) + _LOGGER.debug("Zone with repeats: %s", zone) + try: + await self.hass.async_add_executor_job( + self._vacuum.zoned_clean, zone) + except (OSError, DeviceException) as exc: + _LOGGER.error( + "Unable to send zoned_clean command to the vacuum: %s", + exc) diff --git a/tests/components/xiaomi_miio/test_vacuum.py b/tests/components/xiaomi_miio/test_vacuum.py index a1e937cb244e03..0bb557b1488234 100644 --- a/tests/components/xiaomi_miio/test_vacuum.py +++ b/tests/components/xiaomi_miio/test_vacuum.py @@ -18,7 +18,8 @@ ATTR_CLEANING_COUNT, ATTR_CLEANED_TOTAL_AREA, ATTR_CLEANING_TOTAL_TIME, CONF_HOST, CONF_NAME, CONF_TOKEN, SERVICE_MOVE_REMOTE_CONTROL, SERVICE_MOVE_REMOTE_CONTROL_STEP, - SERVICE_START_REMOTE_CONTROL, SERVICE_STOP_REMOTE_CONTROL) + SERVICE_START_REMOTE_CONTROL, SERVICE_STOP_REMOTE_CONTROL, + SERVICE_CLEAN_ZONE) from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, CONF_PLATFORM, STATE_OFF, STATE_ON) @@ -330,3 +331,13 @@ def test_xiaomi_specific_services(hass, caplog, mock_mirobo_is_on): [mock.call.Vacuum().manual_control_once(control_once)], any_order=True) mock_mirobo_is_on.assert_has_calls(status_calls, any_order=True) mock_mirobo_is_on.reset_mock() + + control = {"zone": [[123, 123, 123, 123]], "repeats": 2} + yield from hass.services.async_call( + DOMAIN, SERVICE_CLEAN_ZONE, + control, blocking=True) + mock_mirobo_is_off.assert_has_calls( + [mock.call.Vacuum().zoned_clean( + [[123, 123, 123, 123, 2]])], any_order=True) + mock_mirobo_is_off.assert_has_calls(status_calls, any_order=True) + mock_mirobo_is_off.reset_mock()