-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support to Dyson 360 Eye robot vacuum using new vacuum platform (#…
…8852) * Add support to Dyson 360 Eye robot vacuum using new vacuum platform * Fix tests with Python 3.5 * Code review * Code review - v2 * Code review - v3
- Loading branch information
1 parent
82a7dff
commit 83afd12
Showing
11 changed files
with
468 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,213 @@ | ||
""" | ||
Support for the Dyson 360 eye vacuum cleaner robot. | ||
For more details about this platform, please refer to the documentation | ||
https://home-assistant.io/components/vacuum.dyson/ | ||
""" | ||
import asyncio | ||
import logging | ||
|
||
from homeassistant.components.dyson import DYSON_DEVICES | ||
from homeassistant.components.vacuum import (SUPPORT_BATTERY, | ||
SUPPORT_FAN_SPEED, SUPPORT_PAUSE, | ||
SUPPORT_RETURN_HOME, | ||
SUPPORT_STATUS, SUPPORT_STOP, | ||
SUPPORT_TURN_OFF, SUPPORT_TURN_ON, | ||
VacuumDevice) | ||
from homeassistant.util.icon import icon_for_battery_level | ||
|
||
ATTR_FULL_CLEAN_TYPE = "full_clean_type" | ||
ATTR_CLEAN_ID = "clean_id" | ||
ATTR_POSITION = "position" | ||
|
||
DEPENDENCIES = ['dyson'] | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
DYSON_360_EYE_DEVICES = "dyson_360_eye_devices" | ||
|
||
ICON = "mdi:roomba" | ||
|
||
SUPPORT_DYSON = SUPPORT_TURN_ON | SUPPORT_TURN_OFF | SUPPORT_PAUSE | \ | ||
SUPPORT_RETURN_HOME | SUPPORT_FAN_SPEED | SUPPORT_STATUS | \ | ||
SUPPORT_BATTERY | SUPPORT_STOP | ||
|
||
|
||
def setup_platform(hass, config, add_devices, discovery_info=None): | ||
"""Set up the Dyson 360 Eye robot vacuum platform.""" | ||
_LOGGER.info("Creating new Dyson 360 Eye robot vacuum") | ||
if DYSON_360_EYE_DEVICES not in hass.data: | ||
hass.data[DYSON_360_EYE_DEVICES] = [] | ||
|
||
# Get Dyson Devices from parent component | ||
from libpurecoollink.dyson_360_eye import Dyson360Eye | ||
for device in [d for d in hass.data[DYSON_DEVICES] if | ||
isinstance(d, Dyson360Eye)]: | ||
dyson_entity = Dyson360EyeDevice(device) | ||
hass.data[DYSON_360_EYE_DEVICES].append(dyson_entity) | ||
|
||
add_devices(hass.data[DYSON_360_EYE_DEVICES]) | ||
return True | ||
|
||
|
||
class Dyson360EyeDevice(VacuumDevice): | ||
"""Dyson 360 Eye robot vacuum device.""" | ||
|
||
def __init__(self, device): | ||
"""Dyson 360 Eye robot vacuum device.""" | ||
_LOGGER.info("Creating device %s", device.name) | ||
self._device = device | ||
self._icon = ICON | ||
|
||
@asyncio.coroutine | ||
def async_added_to_hass(self): | ||
"""Callback when entity is added to hass.""" | ||
self.hass.async_add_job( | ||
self._device.add_message_listener, self.on_message) | ||
|
||
def on_message(self, message): | ||
"""Called when new messages received from the vacuum.""" | ||
_LOGGER.debug("Message received for %s device: %s", self.name, message) | ||
self.schedule_update_ha_state() | ||
|
||
@property | ||
def should_poll(self) -> bool: | ||
"""Return True if entity has to be polled for state. | ||
False if entity pushes its state to HA. | ||
""" | ||
return False | ||
|
||
@property | ||
def name(self): | ||
"""Return the name of the device.""" | ||
return self._device.name | ||
|
||
@property | ||
def icon(self): | ||
"""Return the icon to use for device.""" | ||
return self._icon | ||
|
||
@property | ||
def status(self): | ||
"""Return the status of the vacuum cleaner.""" | ||
from libpurecoollink.const import Dyson360EyeMode | ||
dyson_labels = { | ||
Dyson360EyeMode.INACTIVE_CHARGING: "Stopped - Charging", | ||
Dyson360EyeMode.INACTIVE_CHARGED: "Stopped - Charged", | ||
Dyson360EyeMode.FULL_CLEAN_PAUSED: "Paused", | ||
Dyson360EyeMode.FULL_CLEAN_RUNNING: "Cleaning", | ||
Dyson360EyeMode.FULL_CLEAN_ABORTED: "Returning home", | ||
Dyson360EyeMode.FULL_CLEAN_INITIATED: "Start cleaning", | ||
Dyson360EyeMode.FAULT_USER_RECOVERABLE: "Error - device blocked", | ||
Dyson360EyeMode.FAULT_REPLACE_ON_DOCK: | ||
"Error - Replace device on dock", | ||
Dyson360EyeMode.FULL_CLEAN_FINISHED: "Finished", | ||
Dyson360EyeMode.FULL_CLEAN_NEEDS_CHARGE: "Need charging" | ||
} | ||
return dyson_labels.get(self._device.state.state, | ||
self._device.state.state) | ||
|
||
@property | ||
def battery_level(self): | ||
"""Return the battery level of the vacuum cleaner.""" | ||
return self._device.state.battery_level | ||
|
||
@property | ||
def fan_speed(self): | ||
"""Return the fan speed of the vacuum cleaner.""" | ||
from libpurecoollink.const import PowerMode | ||
speed_labels = { | ||
PowerMode.MAX: "Max", | ||
PowerMode.QUIET: "Quiet" | ||
} | ||
return speed_labels[self._device.state.power_mode] | ||
|
||
@property | ||
def fan_speed_list(self): | ||
"""Get the list of available fan speed steps of the vacuum cleaner.""" | ||
return ["Quiet", "Max"] | ||
|
||
@property | ||
def device_state_attributes(self): | ||
"""Return the specific state attributes of this vacuum cleaner.""" | ||
return { | ||
ATTR_POSITION: str(self._device.state.position) | ||
} | ||
|
||
@property | ||
def is_on(self) -> bool: | ||
"""Return True if entity is on.""" | ||
from libpurecoollink.const import Dyson360EyeMode | ||
return self._device.state.state in [ | ||
Dyson360EyeMode.FULL_CLEAN_INITIATED, | ||
Dyson360EyeMode.FULL_CLEAN_ABORTED, | ||
Dyson360EyeMode.FULL_CLEAN_RUNNING | ||
] | ||
|
||
@property | ||
def available(self) -> bool: | ||
"""Return True if entity is available.""" | ||
return True | ||
|
||
@property | ||
def supported_features(self): | ||
"""Flag vacuum cleaner robot features that are supported.""" | ||
return SUPPORT_DYSON | ||
|
||
@property | ||
def battery_icon(self): | ||
"""Return the battery icon for the vacuum cleaner.""" | ||
from libpurecoollink.const import Dyson360EyeMode | ||
charging = self._device.state.state in [ | ||
Dyson360EyeMode.INACTIVE_CHARGING] | ||
return icon_for_battery_level( | ||
battery_level=self.battery_level, charging=charging) | ||
|
||
def turn_on(self, **kwargs): | ||
"""Turn the vacuum on.""" | ||
_LOGGER.debug("Turn on device %s", self.name) | ||
from libpurecoollink.const import Dyson360EyeMode | ||
if self._device.state.state in [Dyson360EyeMode.FULL_CLEAN_PAUSED]: | ||
self._device.resume() | ||
else: | ||
self._device.start() | ||
|
||
def turn_off(self, **kwargs): | ||
"""Turn the vacuum off and return to home.""" | ||
_LOGGER.debug("Turn off device %s", self.name) | ||
self._device.pause() | ||
|
||
def stop(self, **kwargs): | ||
"""Stop the vacuum cleaner.""" | ||
_LOGGER.debug("Stop device %s", self.name) | ||
self._device.pause() | ||
|
||
def set_fan_speed(self, fan_speed, **kwargs): | ||
"""Set fan speed.""" | ||
_LOGGER.debug("Set fan speed %s on device %s", fan_speed, self.name) | ||
from libpurecoollink.const import PowerMode | ||
power_modes = { | ||
"Quiet": PowerMode.QUIET, | ||
"Max": PowerMode.MAX | ||
} | ||
self._device.set_power_mode(power_modes[fan_speed]) | ||
|
||
def start_pause(self, **kwargs): | ||
"""Start, pause or resume the cleaning task.""" | ||
from libpurecoollink.const import Dyson360EyeMode | ||
if self._device.state.state in [Dyson360EyeMode.FULL_CLEAN_PAUSED]: | ||
_LOGGER.debug("Resume device %s", self.name) | ||
self._device.resume() | ||
elif self._device.state.state in [Dyson360EyeMode.INACTIVE_CHARGED, | ||
Dyson360EyeMode.INACTIVE_CHARGING]: | ||
_LOGGER.debug("Start device %s", self.name) | ||
self._device.start() | ||
else: | ||
_LOGGER.debug("Pause device %s", self.name) | ||
self._device.pause() | ||
|
||
def return_to_base(self, **kwargs): | ||
"""Set the vacuum cleaner to return to the dock.""" | ||
_LOGGER.debug("Return to base device %s", self.name) | ||
self._device.abort() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.