-
-
Notifications
You must be signed in to change notification settings - Fork 37.4k
Add config_flow for Roomba #33302
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Add config_flow for Roomba #33302
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 a333305
Get options to connect
cyr-ius bc6d357
Fix options in config flow
cyr-ius b80cb10
Fix syntax in config_flow
cyr-ius cf737d1
Remove name (not necessary)
cyr-ius 52f901b
Add bin sensor
cyr-ius bd8a95b
Add Battery sensor
cyr-ius 0937fd5
Add async_connect
cyr-ius 2d9e51d
Fix typo
cyr-ius 501e3e2
Add Model and Software version
cyr-ius e2284ba
Update Roombapy 1.5.0
cyr-ius 43616ac
Add validate_input
cyr-ius 82016b7
Add connect and disconnect functions
cyr-ius 098621e
Remove test config flow
cyr-ius a2de1d0
Add variables after loop
cyr-ius 29b51a6
Fix translate
cyr-ius 2ce5b5f
Fix typo
cyr-ius 3d86cbc
Fix state of bin
cyr-ius 32c9d64
Update homeassistant/components/roomba/__init__.py
cyr-ius ad869dc
Update homeassistant/components/roomba/config_flow.py
cyr-ius c14e03b
Update homeassistant/components/roomba/config_flow.py
cyr-ius 4b502a7
Update homeassistant/components/roomba/config_flow.py
cyr-ius 96bffd8
Update homeassistant/components/roomba/config_flow.py
cyr-ius 239864b
Update homeassistant/components/roomba/config_flow.py
cyr-ius 9f0a94a
Update homeassistant/components/roomba/__init__.py
cyr-ius 2e6ad58
Update homeassistant/components/roomba/__init__.py
cyr-ius 2482087
Update homeassistant/components/roomba/__init__.py
cyr-ius eeee967
Update homeassistant/components/roomba/config_flow.py
cyr-ius 96666c8
Remove invalid auth
cyr-ius 432c326
Add call function reported_state
cyr-ius 779948f
Add options reload
cyr-ius 2e9d268
Fix tracelog
cyr-ius 8a437a7
Set entry_id for config_entry
cyr-ius 54d1914
Fix DOMAIN unsed-import
cyr-ius 9e7aed4
Update homeassistant/components/roomba/config_flow.py
cyr-ius 5882a76
Update homeassistant/components/roomba/config_flow.py
cyr-ius fd5bdcd
Add unique_id for entry
cyr-ius c0a8971
Merge branch 'dev' into roomba
cyr-ius 0a9a09d
Fix device info
cyr-ius 48c62d4
Merge branch 'roomba' of https://github.com/cyr-ius/home-assistant int…
cyr-ius d539dff
Add config_flow for roomba
cyr-ius 2dac241
Get options to connect
cyr-ius 54bd240
Fix options in config flow
cyr-ius f1884ce
Fix syntax in config_flow
cyr-ius c1e3e5c
Remove name (not necessary)
cyr-ius 20f2e83
Add bin sensor
cyr-ius 557ac4a
Add Battery sensor
cyr-ius 3978d0a
Add async_connect
cyr-ius a0c9392
Fix typo
cyr-ius 4fdf7cc
Add Model and Software version
cyr-ius 6c32598
Update Roombapy 1.5.0
cyr-ius 5114707
Add validate_input
cyr-ius ff4d19d
Add connect and disconnect functions
cyr-ius 26a8942
Remove test config flow
cyr-ius f85d48a
Add variables after loop
cyr-ius d0a0be2
Fix translate
cyr-ius 0203110
Fix typo
cyr-ius 15f1bd2
Fix state of bin
cyr-ius 4cc82e6
Update homeassistant/components/roomba/__init__.py
cyr-ius 81f071f
Update homeassistant/components/roomba/config_flow.py
cyr-ius 569febe
Update homeassistant/components/roomba/config_flow.py
cyr-ius d998f29
Update homeassistant/components/roomba/config_flow.py
cyr-ius f463606
Update homeassistant/components/roomba/config_flow.py
cyr-ius 7521711
Update homeassistant/components/roomba/config_flow.py
cyr-ius 0c49bd5
Update homeassistant/components/roomba/__init__.py
cyr-ius 331b470
Update homeassistant/components/roomba/__init__.py
cyr-ius 0a535b6
Update homeassistant/components/roomba/__init__.py
cyr-ius 9f34793
Update homeassistant/components/roomba/config_flow.py
cyr-ius 71230a3
Remove invalid auth
cyr-ius 9ea758f
Add call function reported_state
cyr-ius c0e1bae
Add options reload
cyr-ius 3354e26
Fix tracelog
cyr-ius 4eec0e0
Set entry_id for config_entry
cyr-ius abce6fb
Fix DOMAIN unsed-import
cyr-ius 369d5da
Update homeassistant/components/roomba/config_flow.py
cyr-ius fa2e474
Update homeassistant/components/roomba/config_flow.py
cyr-ius 999d66d
Add unique_id for entry
cyr-ius 991a16c
Fix device info
cyr-ius 9e7b153
syntax for mac (pyupgrade)
cyr-ius e2c25e3
syntax for mac (pyupgrade)
cyr-ius 304f601
Change single key to BLID
cyr-ius 6fa5e94
Resolve dict conflict
cyr-ius 9646e16
Update homeassistant/components/roomba/binary_sensor.py
cyr-ius 6aa29e1
Update homeassistant/components/roomba/sensor.py
cyr-ius 3cad764
Update homeassistant/components/roomba/.translations/en.json
cyr-ius 62b15e3
Update homeassistant/components/roomba/strings.json
cyr-ius 35a285b
Add description
cyr-ius 7cd6420
Revert "Remove test config flow"
bdraco 7fc9dd2
Add tests
bdraco 3c89967
Remove check if user none
cyr-ius 82ce71c
Replace CONF_USERNAME to CONF_BLID (breaking change)
cyr-ius 6d690b9
Update test_config_flow.py
cyr-ius 4257793
Add code owners
cyr-ius 6e642bc
Remove CONF_USERNAME (unused)
cyr-ius 9bbd013
Add multiple vacuum
cyr-ius 5262616
Add multiple vacuum
cyr-ius 6a0104e
Update homeassistant/components/roomba/__init__.py
cyr-ius 2d394d4
Update homeassistant/components/roomba/__init__.py
cyr-ius 7bb8164
Update homeassistant/components/roomba/__init__.py
cyr-ius e723d0f
Update homeassistant/components/roomba/__init__.py
cyr-ius a3e266b
Update homeassistant/components/roomba/__init__.py
cyr-ius e74c517
Fix syntax name
cyr-ius 9daeeac
Update homeassistant/components/roomba/__init__.py
cyr-ius d29d3dc
Update homeassistant/components/roomba/__init__.py
cyr-ius f83beb9
Update homeassistant/components/roomba/__init__.py
cyr-ius f2a40c9
Update homeassistant/components/roomba/__init__.py
cyr-ius 017e3e6
Remove CONF_PREFIX (unused)
cyr-ius d1db911
Update homeassistant/components/roomba/sensor.py
cyr-ius 0e798b3
Add import UNIT_PERCENTAGE
cyr-ius c70d2f6
Update homeassistant/components/roomba/__init__.py
cyr-ius 9da03a0
Update homeassistant/components/roomba/__init__.py
cyr-ius File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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,33 @@ | ||
| { | ||
| "config": { | ||
| "title": "iRobot Roomba", | ||
| "step": { | ||
| "user": { | ||
| "title": "Connect to the device", | ||
| "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" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or 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,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" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
This file contains hidden or 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 |
|---|---|---|
| @@ -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], | ||
| }, | ||
| ) | ||
|
|
||
|
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): | ||
|
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: | ||
|
cyr-ius marked this conversation as resolved.
|
||
| config_entry.add_update_listener(async_update_options) | ||
|
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) | ||
|
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) | ||
|
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.""" | ||
This file contains hidden or 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,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" | ||
|
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) | ||
|
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): | ||
|
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) | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.