Created
August 28, 2019 13:17
-
-
Save Soltroy/b3ae9a48f4030e3d00fda22af52723d8 to your computer and use it in GitHub Desktop.
HomeAssistant - EcoVacs Workaround
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
"""Support for Ecovacs Deebot vacuums.""" | |
import logging | |
import random | |
import string | |
import voluptuous as vol | |
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, EVENT_HOMEASSISTANT_STOP | |
from homeassistant.helpers import discovery | |
import homeassistant.helpers.config_validation as cv | |
_LOGGER = logging.getLogger(__name__) | |
DOMAIN = "deebot" | |
CONF_COUNTRY = "country" | |
CONF_CONTINENT = "continent" | |
CONFIG_SCHEMA = vol.Schema( | |
{ | |
DOMAIN: vol.Schema( | |
{ | |
vol.Required(CONF_USERNAME): cv.string, | |
vol.Required(CONF_PASSWORD): cv.string, | |
vol.Required(CONF_COUNTRY): vol.All(vol.Lower, cv.string), | |
vol.Required(CONF_CONTINENT): vol.All(vol.Lower, cv.string), | |
} | |
) | |
}, | |
extra=vol.ALLOW_EXTRA, | |
) | |
ECOVACS_DEVICES = "ecovacs_devices" | |
# Generate a random device ID on each bootup | |
ECOVACS_API_DEVICEID = "".join( | |
random.choice(string.ascii_uppercase + string.digits) for _ in range(8) | |
) | |
def setup(hass, config): | |
"""Set up the Ecovacs component.""" | |
_LOGGER.debug("Creating new Ecovacs component") | |
hass.data[ECOVACS_DEVICES] = [] | |
from ozmo import EcoVacsAPI, VacBot | |
ecovacs_api = EcoVacsAPI( | |
ECOVACS_API_DEVICEID, | |
config[DOMAIN].get(CONF_USERNAME), | |
EcoVacsAPI.md5(config[DOMAIN].get(CONF_PASSWORD)), | |
config[DOMAIN].get(CONF_COUNTRY), | |
config[DOMAIN].get(CONF_CONTINENT), | |
) | |
devices = ecovacs_api.devices() | |
_LOGGER.debug("Ecobot devices: %s", devices) | |
for device in devices: | |
_LOGGER.info( | |
"Discovered Ecovacs device on account: %s with nickname %s", | |
device["did"], | |
device["nick"], | |
) | |
vacbot = VacBot( | |
ecovacs_api.uid, | |
ecovacs_api.REALM, | |
ecovacs_api.resource, | |
ecovacs_api.user_access_token, | |
device, | |
config[DOMAIN].get(CONF_CONTINENT).lower(), | |
monitor=True, | |
) | |
hass.data[ECOVACS_DEVICES].append(vacbot) | |
def stop(event: object) -> None: | |
"""Shut down open connections to Ecovacs XMPP server.""" | |
for device in hass.data[ECOVACS_DEVICES]: | |
_LOGGER.info( | |
"Shutting down connection to Ecovacs device %s", device.vacuum["did"] | |
) | |
device.disconnect() | |
# Listen for HA stop to disconnect. | |
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop) | |
if hass.data[ECOVACS_DEVICES]: | |
_LOGGER.debug("Starting vacuum components") | |
discovery.load_platform(hass, "vacuum", DOMAIN, {}, config) | |
return True |
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
#ecovacs: | |
deebot: | |
username: !secret Ecovacs_username | |
password: !secret Ecovacs_password | |
country: !secret Ecovacs_coutry | |
continent: !secret Ecovacs_continent |
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
{ | |
"domain": "deebot", | |
"name": "deebot", | |
"documentation": "https://www.home-assistant.io/components/deebot", | |
"requirements": [ | |
"ozmo==1.0" | |
], | |
"dependencies": [], | |
"codeowners": [ | |
"@OverloadUT" | |
] | |
} |
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
"""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 ozmo 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 ozmo 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 ozmo 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 ozmo import Stop | |
self.device.run(Stop()) | |
def clean_spot(self, **kwargs): | |
"""Perform a spot clean-up.""" | |
from ozmo import Spot | |
self.device.run(Spot()) | |
def locate(self, **kwargs): | |
"""Locate the vacuum cleaner.""" | |
from ozmo import PlaySound | |
self.device.run(PlaySound()) | |
def set_fan_speed(self, fan_speed, **kwargs): | |
"""Set fan speed.""" | |
if self.is_on: | |
from ozmo 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 ozmo 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 |
@vannetta, got it. how did u access to that folder?
I've tried to access trough ssh but no luck to find /usr/bin/local/python3.9/size-packages/ozmo/init.py.
in bin folder there is no local folder
@sunsgs I don't rimember the right path; it is shown in the log error. In any case you must access via 22222 port because you need to work on the OS
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@sunsgs go to the path you find in the log. It should be something like
/usr/bin/local/python3.9/size-packages/ozmo/__init__.py
My logs said that the line 700 with isAlive was desprecated and line 800 with getchildren.
You have to change isAlive with is_alive and erase getchildren
You have to enter in HassOS to reach this path