Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
111 commits
Select commit Hold shift + click to select a range
670e9ca
Add config_flow for roomba
cyr-ius Mar 25, 2020
a333305
Get options to connect
cyr-ius Mar 27, 2020
bc6d357
Fix options in config flow
cyr-ius Mar 27, 2020
b80cb10
Fix syntax in config_flow
cyr-ius Mar 27, 2020
cf737d1
Remove name (not necessary)
cyr-ius Mar 28, 2020
52f901b
Add bin sensor
cyr-ius Mar 28, 2020
bd8a95b
Add Battery sensor
cyr-ius Mar 28, 2020
0937fd5
Add async_connect
cyr-ius Mar 28, 2020
2d9e51d
Fix typo
cyr-ius Mar 28, 2020
501e3e2
Add Model and Software version
cyr-ius Mar 28, 2020
e2284ba
Update Roombapy 1.5.0
cyr-ius Mar 28, 2020
43616ac
Add validate_input
cyr-ius Mar 28, 2020
82016b7
Add connect and disconnect functions
cyr-ius Mar 29, 2020
098621e
Remove test config flow
cyr-ius Mar 29, 2020
a2de1d0
Add variables after loop
cyr-ius Mar 29, 2020
29b51a6
Fix translate
cyr-ius Mar 29, 2020
2ce5b5f
Fix typo
cyr-ius Mar 29, 2020
3d86cbc
Fix state of bin
cyr-ius Mar 29, 2020
32c9d64
Update homeassistant/components/roomba/__init__.py
cyr-ius Apr 2, 2020
ad869dc
Update homeassistant/components/roomba/config_flow.py
cyr-ius Apr 2, 2020
c14e03b
Update homeassistant/components/roomba/config_flow.py
cyr-ius Apr 2, 2020
4b502a7
Update homeassistant/components/roomba/config_flow.py
cyr-ius Apr 2, 2020
96bffd8
Update homeassistant/components/roomba/config_flow.py
cyr-ius Apr 2, 2020
239864b
Update homeassistant/components/roomba/config_flow.py
cyr-ius Apr 2, 2020
9f0a94a
Update homeassistant/components/roomba/__init__.py
cyr-ius Apr 2, 2020
2e6ad58
Update homeassistant/components/roomba/__init__.py
cyr-ius Apr 2, 2020
2482087
Update homeassistant/components/roomba/__init__.py
cyr-ius Apr 2, 2020
eeee967
Update homeassistant/components/roomba/config_flow.py
cyr-ius Apr 2, 2020
96666c8
Remove invalid auth
cyr-ius Apr 3, 2020
432c326
Add call function reported_state
cyr-ius Apr 3, 2020
779948f
Add options reload
cyr-ius Apr 4, 2020
2e9d268
Fix tracelog
cyr-ius Apr 4, 2020
8a437a7
Set entry_id for config_entry
cyr-ius Apr 4, 2020
54d1914
Fix DOMAIN unsed-import
cyr-ius Apr 4, 2020
9e7aed4
Update homeassistant/components/roomba/config_flow.py
cyr-ius Apr 5, 2020
5882a76
Update homeassistant/components/roomba/config_flow.py
cyr-ius Apr 5, 2020
fd5bdcd
Add unique_id for entry
cyr-ius Apr 5, 2020
c0a8971
Merge branch 'dev' into roomba
cyr-ius Apr 5, 2020
0a9a09d
Fix device info
cyr-ius Apr 5, 2020
48c62d4
Merge branch 'roomba' of https://github.com/cyr-ius/home-assistant int…
cyr-ius Apr 5, 2020
d539dff
Add config_flow for roomba
cyr-ius Mar 25, 2020
2dac241
Get options to connect
cyr-ius Mar 27, 2020
54bd240
Fix options in config flow
cyr-ius Mar 27, 2020
f1884ce
Fix syntax in config_flow
cyr-ius Mar 27, 2020
c1e3e5c
Remove name (not necessary)
cyr-ius Mar 28, 2020
20f2e83
Add bin sensor
cyr-ius Mar 28, 2020
557ac4a
Add Battery sensor
cyr-ius Mar 28, 2020
3978d0a
Add async_connect
cyr-ius Mar 28, 2020
a0c9392
Fix typo
cyr-ius Mar 28, 2020
4fdf7cc
Add Model and Software version
cyr-ius Mar 28, 2020
6c32598
Update Roombapy 1.5.0
cyr-ius Mar 28, 2020
5114707
Add validate_input
cyr-ius Mar 28, 2020
ff4d19d
Add connect and disconnect functions
cyr-ius Mar 29, 2020
26a8942
Remove test config flow
cyr-ius Mar 29, 2020
f85d48a
Add variables after loop
cyr-ius Mar 29, 2020
d0a0be2
Fix translate
cyr-ius Mar 29, 2020
0203110
Fix typo
cyr-ius Mar 29, 2020
15f1bd2
Fix state of bin
cyr-ius Mar 29, 2020
4cc82e6
Update homeassistant/components/roomba/__init__.py
cyr-ius Apr 2, 2020
81f071f
Update homeassistant/components/roomba/config_flow.py
cyr-ius Apr 2, 2020
569febe
Update homeassistant/components/roomba/config_flow.py
cyr-ius Apr 2, 2020
d998f29
Update homeassistant/components/roomba/config_flow.py
cyr-ius Apr 2, 2020
f463606
Update homeassistant/components/roomba/config_flow.py
cyr-ius Apr 2, 2020
7521711
Update homeassistant/components/roomba/config_flow.py
cyr-ius Apr 2, 2020
0c49bd5
Update homeassistant/components/roomba/__init__.py
cyr-ius Apr 2, 2020
331b470
Update homeassistant/components/roomba/__init__.py
cyr-ius Apr 2, 2020
0a535b6
Update homeassistant/components/roomba/__init__.py
cyr-ius Apr 2, 2020
9f34793
Update homeassistant/components/roomba/config_flow.py
cyr-ius Apr 2, 2020
71230a3
Remove invalid auth
cyr-ius Apr 3, 2020
9ea758f
Add call function reported_state
cyr-ius Apr 3, 2020
c0e1bae
Add options reload
cyr-ius Apr 4, 2020
3354e26
Fix tracelog
cyr-ius Apr 4, 2020
4eec0e0
Set entry_id for config_entry
cyr-ius Apr 4, 2020
abce6fb
Fix DOMAIN unsed-import
cyr-ius Apr 4, 2020
369d5da
Update homeassistant/components/roomba/config_flow.py
cyr-ius Apr 5, 2020
fa2e474
Update homeassistant/components/roomba/config_flow.py
cyr-ius Apr 5, 2020
999d66d
Add unique_id for entry
cyr-ius Apr 5, 2020
991a16c
Fix device info
cyr-ius Apr 5, 2020
9e7b153
syntax for mac (pyupgrade)
cyr-ius Apr 5, 2020
e2c25e3
syntax for mac (pyupgrade)
cyr-ius Apr 5, 2020
304f601
Change single key to BLID
cyr-ius Apr 5, 2020
6fa5e94
Resolve dict conflict
cyr-ius Apr 6, 2020
9646e16
Update homeassistant/components/roomba/binary_sensor.py
cyr-ius Apr 8, 2020
6aa29e1
Update homeassistant/components/roomba/sensor.py
cyr-ius Apr 8, 2020
3cad764
Update homeassistant/components/roomba/.translations/en.json
cyr-ius Apr 8, 2020
62b15e3
Update homeassistant/components/roomba/strings.json
cyr-ius Apr 8, 2020
35a285b
Add description
cyr-ius Apr 8, 2020
7cd6420
Revert "Remove test config flow"
bdraco Apr 8, 2020
7fc9dd2
Add tests
bdraco Apr 8, 2020
3c89967
Remove check if user none
cyr-ius Apr 9, 2020
82ce71c
Replace CONF_USERNAME to CONF_BLID (breaking change)
cyr-ius Apr 9, 2020
6d690b9
Update test_config_flow.py
cyr-ius Apr 9, 2020
4257793
Add code owners
cyr-ius Apr 10, 2020
6e642bc
Remove CONF_USERNAME (unused)
cyr-ius Apr 10, 2020
9bbd013
Add multiple vacuum
cyr-ius Apr 10, 2020
5262616
Add multiple vacuum
cyr-ius Apr 10, 2020
6a0104e
Update homeassistant/components/roomba/__init__.py
cyr-ius Apr 10, 2020
2d394d4
Update homeassistant/components/roomba/__init__.py
cyr-ius Apr 10, 2020
7bb8164
Update homeassistant/components/roomba/__init__.py
cyr-ius Apr 10, 2020
e723d0f
Update homeassistant/components/roomba/__init__.py
cyr-ius Apr 10, 2020
a3e266b
Update homeassistant/components/roomba/__init__.py
cyr-ius Apr 10, 2020
e74c517
Fix syntax name
cyr-ius Apr 10, 2020
9daeeac
Update homeassistant/components/roomba/__init__.py
cyr-ius Apr 11, 2020
d29d3dc
Update homeassistant/components/roomba/__init__.py
cyr-ius Apr 11, 2020
f83beb9
Update homeassistant/components/roomba/__init__.py
cyr-ius Apr 11, 2020
f2a40c9
Update homeassistant/components/roomba/__init__.py
cyr-ius Apr 11, 2020
017e3e6
Remove CONF_PREFIX (unused)
cyr-ius Apr 11, 2020
d1db911
Update homeassistant/components/roomba/sensor.py
cyr-ius Apr 11, 2020
0e798b3
Add import UNIT_PERCENTAGE
cyr-ius Apr 11, 2020
c70d2f6
Update homeassistant/components/roomba/__init__.py
cyr-ius Apr 11, 2020
9da03a0
Update homeassistant/components/roomba/__init__.py
cyr-ius Apr 11, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ homeassistant/components/rfxtrx/* @danielhiversen
homeassistant/components/ring/* @balloob
homeassistant/components/rmvtransport/* @cgtobi
homeassistant/components/roku/* @ctalkington
homeassistant/components/roomba/* @pschmitt
homeassistant/components/roomba/* @pschmitt @cyr-ius
homeassistant/components/safe_mode/* @home-assistant/core
homeassistant/components/saj/* @fredericvl
homeassistant/components/salt/* @bjornorri
Expand Down
33 changes: 33 additions & 0 deletions homeassistant/components/roomba/.translations/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"config": {
"title": "iRobot Roomba",
"step": {
"user": {
"title": "Connect to the device",
Comment thread
cyr-ius marked this conversation as resolved.
"description": "Currently retrieving the BLID and password is a manual process. Please follow the steps outlined in the documentation at: https://www.home-assistant.io/integrations/roomba/#retrieving-your-credentials",
"data": {
"host": "Hostname or IP Address",
"blid": "BLID",
"password": "Password",
"certificate": "Certificate",
"continuous": "Continuous",
"delay": "Delay"
}
}
},
"error": {
"unknown" : "Unexpected error",
"cannot_connect": "Failed to connect, please try again"
}
},
"options": {
"step": {
"init": {
"data": {
"continuous": "Continuous",
"delay": "Delay"
}
}
}
}
}
33 changes: 33 additions & 0 deletions homeassistant/components/roomba/.translations/fr.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"config": {
"title": "iRobot Roomba",
"step": {
"user": {
"title": "Connexion au périphérique",
"description": "Actuellement la récupération du BLID et du mot de passe nécessite une procédure manuelle. Veuillez suivre les étapes décrites dans la documentation sur: https://www.home-assistant.io/integrations/roomba/#retrieving-your-credentials",
"data": {
"host": "Nom ou Addresse IP",
"blid": "BLID",
"password": "Mot de passe",
"certificate": "Certificat",
"continuous": "Continue",
"delay": "Delais"
}
}
},
"error": {
"unknown" : "Erreur imprévu",
"cannot_connect": "Impossible de se connecter"
}
},
"options": {
"step": {
"init": {
"data": {
"continuous": "Continue",
"delay": "Delais"
}
}
}
}
}
190 changes: 190 additions & 0 deletions homeassistant/components/roomba/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,191 @@
"""The roomba component."""
import asyncio
import logging

import async_timeout
from roomba import Roomba, RoombaConnectionError
import voluptuous as vol

from homeassistant import config_entries, exceptions
from homeassistant.const import CONF_HOST, CONF_PASSWORD
from homeassistant.core import callback
from homeassistant.helpers import config_validation as cv

from .const import (
BLID,
COMPONENTS,
CONF_BLID,
CONF_CERT,
CONF_CONTINUOUS,
CONF_DELAY,
CONF_NAME,
DEFAULT_CERT,
DEFAULT_CONTINUOUS,
DEFAULT_DELAY,
DOMAIN,
ROOMBA_SESSION,
)

_LOGGER = logging.getLogger(__name__)


def _has_all_unique_bilds(value):
"""Validate that each vacuum configured has a unique bild.

Uniqueness is determined case-independently.
"""
bilds = [device[CONF_BLID] for device in value]
schema = vol.Schema(vol.Unique())
schema(bilds)
return value


DEVICE_SCHEMA = vol.Schema(
{
vol.Required(CONF_HOST): str,
vol.Required(CONF_BLID): str,
vol.Required(CONF_PASSWORD): str,
vol.Optional(CONF_CERT, default=DEFAULT_CERT): str,
vol.Optional(CONF_CONTINUOUS, default=DEFAULT_CONTINUOUS): bool,
vol.Optional(CONF_DELAY, default=DEFAULT_DELAY): int,
},
)


CONFIG_SCHEMA = vol.Schema(
{DOMAIN: vol.All(cv.ensure_list, [DEVICE_SCHEMA], _has_all_unique_bilds)},
extra=vol.ALLOW_EXTRA,
)


async def async_setup(hass, config):
"""Set up the roomba environment."""
hass.data.setdefault(DOMAIN, {})

if DOMAIN not in config:
return True
for index, conf in enumerate(config[DOMAIN]):
_LOGGER.debug("Importing Roomba #%d - %s", index, conf[CONF_HOST])
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data=conf,
)
)

return True


async def async_setup_entry(hass, config_entry):
"""Set the config entry up."""
# Set up roomba platforms with config entry

if not config_entry.options:
hass.config_entries.async_update_entry(
config_entry,
options={
"continuous": config_entry.data[CONF_CONTINUOUS],
"delay": config_entry.data[CONF_DELAY],
},
)

Comment thread
cyr-ius marked this conversation as resolved.
roomba = Roomba(
address=config_entry.data[CONF_HOST],
blid=config_entry.data[CONF_BLID],
password=config_entry.data[CONF_PASSWORD],
cert_name=config_entry.data[CONF_CERT],
continuous=config_entry.options[CONF_CONTINUOUS],
delay=config_entry.options[CONF_DELAY],
)

try:
if not await async_connect_or_timeout(hass, roomba):
Comment thread
cyr-ius marked this conversation as resolved.
return False
except CannotConnect:
raise exceptions.ConfigEntryNotReady

hass.data[DOMAIN][config_entry.entry_id] = {
ROOMBA_SESSION: roomba,
BLID: config_entry.data[CONF_BLID],
}

for component in COMPONENTS:
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(config_entry, component)
)

if not config_entry.update_listeners:
Comment thread
cyr-ius marked this conversation as resolved.
config_entry.add_update_listener(async_update_options)
Comment thread
cyr-ius marked this conversation as resolved.

return True


async def async_connect_or_timeout(hass, roomba):
"""Connect to vacuum."""
try:
name = None
with async_timeout.timeout(10):
_LOGGER.debug("Initialize connection to vacuum")
await hass.async_add_job(roomba.connect)
Comment thread
cyr-ius marked this conversation as resolved.
while not roomba.roomba_connected or name is None:
# Waiting for connection and check datas ready
name = roomba_reported_state(roomba).get("name", None)
Comment thread
cyr-ius marked this conversation as resolved.
if name:
break
await asyncio.sleep(1)
except RoombaConnectionError:
_LOGGER.error("Error to connect to vacuum")
raise CannotConnect
except asyncio.TimeoutError:
# api looping if user or password incorrect and roomba exist
await async_disconnect_or_timeout(hass, roomba)
_LOGGER.error("Timeout expired")
raise CannotConnect

return {ROOMBA_SESSION: roomba, CONF_NAME: name}


async def async_disconnect_or_timeout(hass, roomba):
"""Disconnect to vacuum."""
_LOGGER.debug("Disconnect vacuum")
with async_timeout.timeout(3):
await hass.async_add_job(roomba.disconnect)
return True


async def async_update_options(hass, config_entry):
"""Update options."""
await hass.config_entries.async_reload(config_entry.entry_id)


async def async_unload_entry(hass, config_entry):
"""Unload a config entry."""
unload_ok = all(
await asyncio.gather(
*[
hass.config_entries.async_forward_entry_unload(config_entry, component)
for component in COMPONENTS
]
)
)
if unload_ok:
domain_data = hass.data[DOMAIN][config_entry.entry_id]
await async_disconnect_or_timeout(hass, roomba=domain_data[ROOMBA_SESSION])
hass.data[DOMAIN].pop(config_entry.entry_id)

return unload_ok


def roomba_reported_state(roomba):
"""Roomba report."""
return roomba.master_state.get("state", {}).get("reported", {})


@callback
def _async_find_matching_config_entry(hass, prefix):
for entry in hass.config_entries.async_entries(DOMAIN):
if entry.unique_id == prefix:
return entry


class CannotConnect(exceptions.HomeAssistantError):
"""Error to indicate we cannot connect."""
74 changes: 74 additions & 0 deletions homeassistant/components/roomba/binary_sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""Roomba binary sensor entities."""
import logging

from homeassistant.components.binary_sensor import BinarySensorDevice

from . import roomba_reported_state
from .const import BLID, DOMAIN, ROOMBA_SESSION

_LOGGER = logging.getLogger(__name__)


async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up the iRobot Roomba vacuum cleaner."""
domain_data = hass.data[DOMAIN][config_entry.entry_id]
roomba = domain_data[ROOMBA_SESSION]
blid = domain_data[BLID]
status = roomba_reported_state(roomba).get("bin", {})
if "full" in status:
roomba_vac = RoombaBinStatus(roomba, blid)
async_add_entities([roomba_vac], True)


class RoombaBinStatus(BinarySensorDevice):
"""Class to hold Roomba Sensor basic info."""

ICON = "mdi:delete-variant"
Comment thread
cyr-ius marked this conversation as resolved.

def __init__(self, roomba, blid):
"""Initialize the sensor object."""
self.vacuum = roomba
self.vacuum_state = roomba_reported_state(roomba)
Comment thread
cyr-ius marked this conversation as resolved.
self._blid = blid
self._name = self.vacuum_state.get("name")
self._identifier = f"roomba_{self._blid}"
self._bin_status = None

@property
def name(self):
"""Return the name of the sensor."""
return f"{self._name} Bin Full"

@property
def unique_id(self):
"""Return the ID of this sensor."""
return f"bin_{self._blid}"

@property
def icon(self):
"""Return the icon of this sensor."""
return self.ICON

@property
def state(self):
Comment thread
cyr-ius marked this conversation as resolved.
"""Return the state of the sensor."""
return self._bin_status

@property
def device_info(self):
"""Return the device info of the vacuum cleaner."""
return {
"identifiers": {(DOMAIN, self._identifier)},
"name": str(self._name),
}

async def async_update(self):
"""Return the update info of the vacuum cleaner."""
# No data, no update
if not self.vacuum.master_state:
_LOGGER.debug("Roomba %s has no data yet. Skip update", self.name)
return
self._bin_status = (
roomba_reported_state(self.vacuum).get("bin", {}).get("full", False)
)
_LOGGER.debug("Update Full Bin status from the vacuum: %s", self._bin_status)
Loading