diff --git a/homeassistant/components/roomba/__init__.py b/homeassistant/components/roomba/__init__.py index 28092f964773e6..28307c63f95910 100644 --- a/homeassistant/components/roomba/__init__.py +++ b/homeassistant/components/roomba/__init__.py @@ -23,6 +23,7 @@ DEFAULT_CONTINUOUS, DEFAULT_DELAY, DOMAIN, + LISTENER, ROOMBA_SESSION, ) @@ -104,9 +105,12 @@ async def async_setup_entry(hass, config_entry): except CannotConnect: raise exceptions.ConfigEntryNotReady + listener_options = config_entry.add_update_listener(async_update_options) + hass.data[DOMAIN][config_entry.entry_id] = { ROOMBA_SESSION: roomba, BLID: config_entry.data[CONF_BLID], + LISTENER: listener_options, } for component in COMPONENTS: @@ -114,9 +118,6 @@ async def async_setup_entry(hass, config_entry): hass.config_entries.async_forward_entry_setup(config_entry, component) ) - if not config_entry.update_listeners: - config_entry.add_update_listener(async_update_options) - return True @@ -126,10 +127,10 @@ async def async_connect_or_timeout(hass, roomba): name = None with async_timeout.timeout(10): _LOGGER.debug("Initialize connection to vacuum") - await hass.async_add_job(roomba.connect) + await hass.async_add_executor_job(roomba.connect) while not roomba.roomba_connected or name is None: # Waiting for connection and check datas ready - name = roomba_reported_state(roomba).get("name", None) + name = roomba_reported_state(roomba).get("name") if name: break await asyncio.sleep(1) @@ -147,10 +148,16 @@ async def async_connect_or_timeout(hass, roomba): 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 + try: + with async_timeout.timeout(3): + _LOGGER.debug("Disconnect vacuum") + await hass.async_add_executor_job(roomba.disconnect) + while roomba.roomba_connected: + await asyncio.sleep(1) + break + except asyncio.TimeoutError: + _LOGGER.error("Timeout exceeded when disconnecting the vacuum cleaner") + raise CannotDisconnect async def async_update_options(hass, config_entry): @@ -168,9 +175,19 @@ async def async_unload_entry(hass, config_entry): ] ) ) - if unload_ok: - domain_data = hass.data[DOMAIN][config_entry.entry_id] + + domain_data = hass.data[DOMAIN][config_entry.entry_id] + + # unsubscribe listerner + domain_data[LISTENER]() + + # disconnect cleanly + try: await async_disconnect_or_timeout(hass, roomba=domain_data[ROOMBA_SESSION]) + except CannotDisconnect: + return False + + if unload_ok: hass.data[DOMAIN].pop(config_entry.entry_id) return unload_ok @@ -190,3 +207,7 @@ def _async_find_matching_config_entry(hass, prefix): class CannotConnect(exceptions.HomeAssistantError): """Error to indicate we cannot connect.""" + + +class CannotDisconnect(exceptions.HomeAssistantError): + """Error to indicate we cannot disconnect.""" diff --git a/homeassistant/components/roomba/binary_sensor.py b/homeassistant/components/roomba/binary_sensor.py index fb11a0f9d4caaf..e14aef9a458c84 100644 --- a/homeassistant/components/roomba/binary_sensor.py +++ b/homeassistant/components/roomba/binary_sensor.py @@ -42,6 +42,6 @@ def icon(self): return self.ICON @property - def state(self): + def is_on(self): """Return the state of the sensor.""" return roomba_reported_state(self.vacuum).get("bin", {}).get("full", False) diff --git a/homeassistant/components/roomba/config_flow.py b/homeassistant/components/roomba/config_flow.py index e323150fba3220..5256e05468e7f3 100644 --- a/homeassistant/components/roomba/config_flow.py +++ b/homeassistant/components/roomba/config_flow.py @@ -8,7 +8,12 @@ from homeassistant.const import CONF_HOST, CONF_PASSWORD from homeassistant.core import callback -from . import CannotConnect, async_connect_or_timeout, async_disconnect_or_timeout +from . import ( + CannotConnect, + CannotDisconnect, + async_connect_or_timeout, + async_disconnect_or_timeout, +) from .const import ( CONF_BLID, CONF_CERT, @@ -84,11 +89,16 @@ async def async_step_user(self, user_input=None): self._abort_if_unique_id_configured() try: info = await validate_input(self.hass, user_input) + await async_disconnect_or_timeout(self.hass, info[ROOMBA_SESSION]) except CannotConnect: errors = {"base": "cannot_connect"} + except CannotDisconnect: + errors = {"base": "cannot_disconnect"} + except Exception as error: # pylint: disable=broad-except + _LOGGER.error("An unknown error occurred: %s", error) + errors = {"base": "unknown"} if "base" not in errors: - await async_disconnect_or_timeout(self.hass, info[ROOMBA_SESSION]) return self.async_create_entry(title=info[CONF_NAME], data=user_input) return self.async_show_form( diff --git a/homeassistant/components/roomba/const.py b/homeassistant/components/roomba/const.py index 06684e63bdc238..abd9197d8bcd0b 100644 --- a/homeassistant/components/roomba/const.py +++ b/homeassistant/components/roomba/const.py @@ -11,3 +11,4 @@ DEFAULT_DELAY = 1 ROOMBA_SESSION = "roomba_session" BLID = "blid_key" +LISTENER = "listener_options"