188 lines
6.1 KiB
Python
188 lines
6.1 KiB
Python
"""Support for Ecovacs Ecovacs Vaccums."""
|
|
import logging
|
|
|
|
from homeassistant.components.vacuum import (
|
|
SUPPORT_BATTERY, SUPPORT_CLEAN_SPOT, SUPPORT_FAN_SPEED, SUPPORT_LOCATE,
|
|
SUPPORT_RETURN_HOME, SUPPORT_SEND_COMMAND, SUPPORT_STATUS, SUPPORT_STOP,
|
|
SUPPORT_TURN_OFF, SUPPORT_TURN_ON, VacuumDevice)
|
|
from homeassistant.helpers.icon import icon_for_battery_level
|
|
|
|
from . import ECOVACS_DEVICES
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
SUPPORT_ECOVACS = (
|
|
SUPPORT_BATTERY | SUPPORT_RETURN_HOME | SUPPORT_CLEAN_SPOT |
|
|
SUPPORT_STOP | SUPPORT_TURN_OFF | SUPPORT_TURN_ON | SUPPORT_LOCATE |
|
|
SUPPORT_STATUS | SUPPORT_SEND_COMMAND | SUPPORT_FAN_SPEED)
|
|
|
|
ATTR_ERROR = 'error'
|
|
ATTR_COMPONENT_PREFIX = 'component_'
|
|
|
|
|
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
|
"""Set up the Ecovacs vacuums."""
|
|
vacuums = []
|
|
for device in hass.data[ECOVACS_DEVICES]:
|
|
vacuums.append(EcovacsVacuum(device))
|
|
_LOGGER.debug("Adding Ecovacs Vacuums to Hass: %s", vacuums)
|
|
add_entities(vacuums, True)
|
|
|
|
|
|
class EcovacsVacuum(VacuumDevice):
|
|
"""Ecovacs Vacuums such as Deebot."""
|
|
|
|
def __init__(self, device):
|
|
"""Initialize the Ecovacs Vacuum."""
|
|
self.device = device
|
|
self.device.connect_and_wait_until_ready()
|
|
if self.device.vacuum.get('nick', None) is not None:
|
|
self._name = '{}'.format(self.device.vacuum['nick'])
|
|
else:
|
|
# In case there is no nickname defined, use the device id
|
|
self._name = '{}'.format(self.device.vacuum['did'])
|
|
|
|
self._fan_speed = None
|
|
self._error = None
|
|
_LOGGER.debug("Vacuum initialized: %s", self.name)
|
|
|
|
async def async_added_to_hass(self) -> None:
|
|
"""Set up the event listeners now that hass is ready."""
|
|
self.device.statusEvents.subscribe(lambda _:
|
|
self.schedule_update_ha_state())
|
|
self.device.batteryEvents.subscribe(lambda _:
|
|
self.schedule_update_ha_state())
|
|
self.device.lifespanEvents.subscribe(lambda _:
|
|
self.schedule_update_ha_state())
|
|
self.device.errorEvents.subscribe(self.on_error)
|
|
|
|
def on_error(self, error):
|
|
"""Handle an error event from the robot.
|
|
|
|
This will not change the entity's state. If the error caused the state
|
|
to change, that will come through as a separate on_status event
|
|
"""
|
|
if error == 'no_error':
|
|
self._error = None
|
|
else:
|
|
self._error = error
|
|
|
|
self.hass.bus.fire('ecovacs_error', {
|
|
'entity_id': self.entity_id,
|
|
'error': error
|
|
})
|
|
self.schedule_update_ha_state()
|
|
|
|
@property
|
|
def should_poll(self) -> bool:
|
|
"""Return True if entity has to be polled for state."""
|
|
return False
|
|
|
|
@property
|
|
def unique_id(self) -> str:
|
|
"""Return an unique ID."""
|
|
return self.device.vacuum.get('did', None)
|
|
|
|
@property
|
|
def is_on(self):
|
|
"""Return true if vacuum is currently cleaning."""
|
|
return self.device.is_cleaning
|
|
|
|
@property
|
|
def is_charging(self):
|
|
"""Return true if vacuum is currently charging."""
|
|
return self.device.is_charging
|
|
|
|
@property
|
|
def name(self):
|
|
"""Return the name of the device."""
|
|
return self._name
|
|
|
|
@property
|
|
def supported_features(self):
|
|
"""Flag vacuum cleaner robot features that are supported."""
|
|
return SUPPORT_ECOVACS
|
|
|
|
@property
|
|
def status(self):
|
|
"""Return the status of the vacuum cleaner."""
|
|
return self.device.vacuum_status
|
|
|
|
def return_to_base(self, **kwargs):
|
|
"""Set the vacuum cleaner to return to the dock."""
|
|
from sucks import Charge
|
|
self.device.run(Charge())
|
|
|
|
@property
|
|
def battery_icon(self):
|
|
"""Return the battery icon for the vacuum cleaner."""
|
|
return icon_for_battery_level(
|
|
battery_level=self.battery_level, charging=self.is_charging)
|
|
|
|
@property
|
|
def battery_level(self):
|
|
"""Return the battery level of the vacuum cleaner."""
|
|
if self.device.battery_status is not None:
|
|
return self.device.battery_status * 100
|
|
|
|
return super().battery_level
|
|
|
|
@property
|
|
def fan_speed(self):
|
|
"""Return the fan speed of the vacuum cleaner."""
|
|
return self.device.fan_speed
|
|
|
|
@property
|
|
def fan_speed_list(self):
|
|
"""Get the list of available fan speed steps of the vacuum cleaner."""
|
|
from sucks import FAN_SPEED_NORMAL, FAN_SPEED_HIGH
|
|
return [FAN_SPEED_NORMAL, FAN_SPEED_HIGH]
|
|
|
|
def turn_on(self, **kwargs):
|
|
"""Turn the vacuum on and start cleaning."""
|
|
from sucks import Clean
|
|
self.device.run(Clean())
|
|
|
|
def turn_off(self, **kwargs):
|
|
"""Turn the vacuum off stopping the cleaning and returning home."""
|
|
self.return_to_base()
|
|
|
|
def stop(self, **kwargs):
|
|
"""Stop the vacuum cleaner."""
|
|
from sucks import Stop
|
|
self.device.run(Stop())
|
|
|
|
def clean_spot(self, **kwargs):
|
|
"""Perform a spot clean-up."""
|
|
from sucks import Spot
|
|
self.device.run(Spot())
|
|
|
|
def locate(self, **kwargs):
|
|
"""Locate the vacuum cleaner."""
|
|
from sucks import PlaySound
|
|
self.device.run(PlaySound())
|
|
|
|
def set_fan_speed(self, fan_speed, **kwargs):
|
|
"""Set fan speed."""
|
|
if self.is_on:
|
|
from sucks import Clean
|
|
self.device.run(Clean(
|
|
mode=self.device.clean_status, speed=fan_speed))
|
|
|
|
def send_command(self, command, params=None, **kwargs):
|
|
"""Send a command to a vacuum cleaner."""
|
|
from sucks import VacBotCommand
|
|
self.device.run(VacBotCommand(command, params))
|
|
|
|
@property
|
|
def device_state_attributes(self):
|
|
"""Return the device-specific state attributes of this vacuum."""
|
|
data = {}
|
|
data[ATTR_ERROR] = self._error
|
|
|
|
for key, val in self.device.components.items():
|
|
attr_name = ATTR_COMPONENT_PREFIX + key
|
|
data[attr_name] = int(val * 100)
|
|
|
|
return data
|