async def async_setup_entry_gw(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up Plugwise Smiles from a config entry.""" await er.async_migrate_entries(hass, entry.entry_id, async_migrate_entity_entry) websession = async_get_clientsession(hass, verify_ssl=False) api = Smile( host=entry.data[CONF_HOST], username=entry.data.get(CONF_USERNAME, DEFAULT_USERNAME), password=entry.data[CONF_PASSWORD], port=entry.data.get(CONF_PORT, DEFAULT_PORT), timeout=30, websession=websession, ) try: connected = await api.connect() except InvalidAuthentication: LOGGER.error("Invalid username or Smile ID") return False except (ClientConnectionError, PlugwiseException) as err: raise ConfigEntryNotReady( f"Error while communicating to device {api.smile_name}") from err except asyncio.TimeoutError as err: raise ConfigEntryNotReady( f"Timeout while connecting to Smile {api.smile_name}") from err if not connected: raise ConfigEntryNotReady("Unable to connect to Smile") api.get_all_devices() if entry.unique_id is None and api.smile_version[0] != "1.8.0": hass.config_entries.async_update_entry(entry, unique_id=api.smile_hostname) coordinator = PlugwiseDataUpdateCoordinator(hass, api) await coordinator.async_config_entry_first_refresh() migrate_sensor_entities(hass, coordinator) hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator device_registry = dr.async_get(hass) device_registry.async_get_or_create( config_entry_id=entry.entry_id, identifiers={(DOMAIN, str(api.gateway_id))}, manufacturer="Plugwise", name=entry.title, model=f"Smile {api.smile_name}", sw_version=api.smile_version[0], ) hass.config_entries.async_setup_platforms(entry, PLATFORMS_GATEWAY) return True
async def validate_gw_input(hass: core.HomeAssistant, data): """ Validate whether the user input allows us to connect to the gateway. Data has the keys from _base_gw_schema() with values provided by the user. """ websession = async_get_clientsession(hass, verify_ssl=False) api = Smile( host=data[CONF_HOST], username=data[CONF_USERNAME], password=data[CONF_PASSWORD], port=data[CONF_PORT], timeout=30, websession=websession, ) try: await api.connect() except InvalidAuthentication as err: raise InvalidAuth from err except PlugwiseException as err: raise CannotConnect from err return api
async def validate_gw_input(hass: HomeAssistant, data: dict[str, Any]) -> Smile: """ Validate whether the user input allows us to connect to the gateway. Data has the keys from _base_gw_schema() with values provided by the user. """ websession = async_get_clientsession(hass, verify_ssl=False) api = Smile( host=data[CONF_HOST], password=data[CONF_PASSWORD], port=data[CONF_PORT], username=data[CONF_USERNAME], timeout=30, websession=websession, ) await api.connect() return api
async def async_setup_entry_gw(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up Plugwise Smiles from a config entry.""" websession = async_get_clientsession(hass, verify_ssl=False) api = Smile( host=entry.data[CONF_HOST], username=entry.data.get(CONF_USERNAME, DEFAULT_USERNAME), password=entry.data[CONF_PASSWORD], port=entry.data.get(CONF_PORT, DEFAULT_PORT), timeout=30, websession=websession, ) try: connected = await api.connect() if not connected: _LOGGER.error("Unable to connect to Smile") raise ConfigEntryNotReady except InvalidAuthentication: _LOGGER.error("Invalid username or Smile ID") return False except PlugwiseException as err: _LOGGER.error("Error while communicating to device %s", api.smile_name) raise ConfigEntryNotReady from err except asyncio.TimeoutError as err: _LOGGER.error("Timeout while connecting to Smile %s", api.smile_name) raise ConfigEntryNotReady from err update_interval = timedelta(seconds=entry.options.get( CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL[api.smile_type])) async def async_update_data(): """Update data via API endpoint.""" try: async with async_timeout.timeout(DEFAULT_TIMEOUT): await api.full_update_device() return True except XMLDataMissingError as err: raise UpdateFailed("Smile update failed") from err coordinator = DataUpdateCoordinator( hass, _LOGGER, name=f"Smile {api.smile_name}", update_method=async_update_data, update_interval=update_interval, ) await coordinator.async_config_entry_first_refresh() api.get_all_devices() if entry.unique_id is None and api.smile_version[0] != "1.8.0": hass.config_entries.async_update_entry(entry, unique_id=api.smile_hostname) undo_listener = entry.add_update_listener(_update_listener) hass.data.setdefault(DOMAIN, {})[entry.entry_id] = { "api": api, COORDINATOR: coordinator, PW_TYPE: GATEWAY, UNDO_UPDATE_LISTENER: undo_listener, } device_registry = dr.async_get(hass) device_registry.async_get_or_create( config_entry_id=entry.entry_id, identifiers={(DOMAIN, api.gateway_id)}, manufacturer="Plugwise", name=entry.title, model=f"Smile {api.smile_name}", sw_version=api.smile_version[0], ) single_master_thermostat = api.single_master_thermostat() platforms = PLATFORMS_GATEWAY if single_master_thermostat is None: platforms = SENSOR_PLATFORMS hass.config_entries.async_setup_platforms(entry, platforms) return True
async def async_setup_entry_gw(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up Plugwise Smiles from a config entry.""" websession = async_get_clientsession(hass, verify_ssl=False) # When migrating from Core to beta, add the username to ConfigEntry entry_updates = {} if CONF_USERNAME not in entry.data: data = {**entry.data} data.update({CONF_USERNAME: DEFAULT_USERNAME}) entry_updates["data"] = data if entry_updates: hass.config_entries.async_update_entry(entry, **entry_updates) api = Smile( host=entry.data[CONF_HOST], username=entry.data[CONF_USERNAME], password=entry.data[CONF_PASSWORD], port=entry.data.get(CONF_PORT, DEFAULT_PORT), timeout=30, websession=websession, ) try: connected = await api.connect() if not connected: _LOGGER.error("Unable to connect to the Smile/Stretch") raise ConfigEntryNotReady except InvalidAuthentication: _LOGGER.error("Invalid username or Smile ID") return False except PlugwiseException as err: _LOGGER.error("Error while communicating to the Smile/Stretch") raise ConfigEntryNotReady from err except asyncio.TimeoutError as err: _LOGGER.error("Timeout while connecting to the Smile/Stretch") raise ConfigEntryNotReady from err # Migrate to a valid unique_id when needed if entry.unique_id is None: if api.smile_version[0] != "1.8.0": hass.config_entries.async_update_entry( entry, unique_id=api.smile_hostname) update_interval = timedelta(seconds=entry.options.get( CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL[api.smile_type])) async def async_update_gw_data(): """Update data via API endpoint.""" _LOGGER.debug("Updating %s", api.smile_name) try: async with async_timeout.timeout(update_interval.seconds): await api.update_gw_devices() _LOGGER.debug("Successfully updated %s", api.smile_name) return True except XMLDataMissingError as err: _LOGGER.debug("Updating Smile failed, expected XML data for %s", api.smile_name) raise UpdateFailed("Smile update failed") from err except PlugwiseException as err: _LOGGER.debug("Updating failed, generic failure for %s", api.smile_name) raise UpdateFailed("Smile update failed") from err coordinator = DataUpdateCoordinator( hass, _LOGGER, name=f"{api.smile_name}", update_method=async_update_gw_data, update_interval=update_interval, ) await coordinator.async_refresh() if not coordinator.last_update_success: raise ConfigEntryNotReady undo_listener = entry.add_update_listener(_update_listener) hass.data.setdefault(DOMAIN, {})[entry.entry_id] = { API: api, COORDINATOR: coordinator, PW_TYPE: GATEWAY, UNDO_UPDATE_LISTENER: undo_listener, } api.get_all_devices() _LOGGER.debug("Gateway is %s", api.gateway_id) _LOGGER.debug("Gateway software version is %s", api.smile_version[0]) _LOGGER.debug("Appliances are %s", api.gw_devices) _LOGGER.debug("Single master thermostat = %s", api.single_master_thermostat()) platforms = GATEWAY_PLATFORMS if api.single_master_thermostat() is None: platforms = SENSOR_PLATFORMS async def delete_notification(self): """Service: delete the Plugwise Notification.""" _LOGGER.debug("Service delete PW Notification called for %s", api.smile_name) try: deleted = await api.delete_notification() _LOGGER.debug("PW Notification deleted: %s", deleted) except PlugwiseException: _LOGGER.debug("Failed to delete the Plugwise Notification for %s", api.smile_name) for component in platforms: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, component)) if component == CLIMATE_DOMAIN: hass.services.async_register(DOMAIN, SERVICE_DELETE, delete_notification, schema=vol.Schema({})) return True