async def async_migrate_entry(hass: HomeAssistantType, entry: ConfigEntry): """Handle migration of a previous version config entry. A config entry created under a previous version must go through the integration setup again so we can properly retrieve the needed data elements. Force this by removing the entry and triggering a new flow. """ from pysmartthings import SmartThings # Remove the installed_app, which if already removed raises a 403 error. api = SmartThings(async_get_clientsession(hass), entry.data[CONF_ACCESS_TOKEN]) installed_app_id = entry.data[CONF_INSTALLED_APP_ID] try: await api.delete_installed_app(installed_app_id) except ClientResponseError as ex: if ex.status == 403: _LOGGER.exception("Installed app %s has already been removed", installed_app_id) else: raise _LOGGER.debug("Removed installed app %s", installed_app_id) # Delete the entry hass.async_create_task( hass.config_entries.async_remove(entry.entry_id)) # only create new flow if there isn't a pending one for SmartThings. flows = hass.config_entries.flow.async_progress() if not [flow for flow in flows if flow['handler'] == DOMAIN]: hass.async_create_task( hass.config_entries.flow.async_init( DOMAIN, context={'source': 'import'})) # Return False because it could not be migrated. return False
def async_publish(hass: HomeAssistantType, topic: Any, payload, qos=None, retain=None) -> None: """Publish message to an MQTT topic.""" data = _build_publish_data(topic, qos, retain) data[ATTR_PAYLOAD] = payload hass.async_create_task( hass.services.async_call(DOMAIN, SERVICE_PUBLISH, data))
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigType) -> bool: """Set up Toon from a config entry.""" from toonapilib import Toon conf = hass.data.get(DATA_TOON_CONFIG) toon = await hass.async_add_executor_job(partial( Toon, entry.data[CONF_USERNAME], entry.data[CONF_PASSWORD], conf[CONF_CLIENT_ID], conf[CONF_CLIENT_SECRET], tenant_id=entry.data[CONF_TENANT], display_common_name=entry.data[CONF_DISPLAY])) hass.data.setdefault(DATA_TOON_CLIENT, {})[entry.entry_id] = toon # Register device for the Meter Adapter, since it will have no entities. device_registry = await dr.async_get_registry(hass) device_registry.async_get_or_create( config_entry_id=entry.entry_id, identifiers={ (DOMAIN, toon.agreement.id, 'meter_adapter'), }, manufacturer='Eneco', name="Meter Adapter", via_hub=(DOMAIN, toon.agreement.id) ) for component in 'binary_sensor', 'climate', 'sensor': hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, component)) return True
def async_setup_scanner_platform(hass: HomeAssistantType, config: ConfigType, scanner: Any, async_see_device: Callable, platform: str): """Set up the connect scanner-based platform to device tracker. This method must be run in the event loop. """ interval = config.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) update_lock = asyncio.Lock(loop=hass.loop) scanner.hass = hass # Initial scan of each mac we also tell about host name for config seen = set() # type: Any async def async_device_tracker_scan(now: dt_util.dt.datetime): """Handle interval matches.""" if update_lock.locked(): _LOGGER.warning( "Updating device list from %s took longer than the scheduled " "scan interval %s", platform, interval) return async with update_lock: found_devices = await scanner.async_scan_devices() for mac in found_devices: if mac in seen: host_name = None else: host_name = await scanner.async_get_device_name(mac) seen.add(mac) try: extra_attributes = \ await scanner.async_get_extra_attributes(mac) except NotImplementedError: extra_attributes = dict() kwargs = { 'mac': mac, 'host_name': host_name, 'source_type': SOURCE_TYPE_ROUTER, 'attributes': { 'scanner': scanner.__class__.__name__, **extra_attributes } } zone_home = hass.states.get(zone.ENTITY_ID_HOME) if zone_home: kwargs['gps'] = [zone_home.attributes[ATTR_LATITUDE], zone_home.attributes[ATTR_LONGITUDE]] kwargs['gps_accuracy'] = 0 hass.async_create_task(async_see_device(**kwargs)) async_track_time_interval(hass, async_device_tracker_scan, interval) hass.async_create_task(async_device_tracker_scan(None))
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry): """Initialize config entry which represents the HEOS controller.""" from pyheos import Heos, CommandError host = entry.data[CONF_HOST] # Setting all_progress_events=False ensures that we only receive a # media position update upon start of playback or when media changes controller = Heos(host, all_progress_events=False) try: await controller.connect(auto_reconnect=True) # Auto reconnect only operates if initial connection was successful. except (asyncio.TimeoutError, ConnectionError, CommandError) as error: await controller.disconnect() _LOGGER.debug("Unable to connect to controller %s: %s", host, error) raise ConfigEntryNotReady # Disconnect when shutting down async def disconnect_controller(event): await controller.disconnect() hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, disconnect_controller) # Get players and sources try: players = await controller.get_players() favorites = {} if controller.is_signed_in: favorites = await controller.get_favorites() else: _LOGGER.warning( "%s is not logged in to a HEOS account and will be unable " "to retrieve HEOS favorites: Use the 'heos.sign_in' service " "to sign-in to a HEOS account", host) inputs = await controller.get_input_sources() except (asyncio.TimeoutError, ConnectionError, CommandError) as error: await controller.disconnect() _LOGGER.debug("Unable to retrieve players and sources: %s", error, exc_info=isinstance(error, CommandError)) raise ConfigEntryNotReady controller_manager = ControllerManager(hass, controller) await controller_manager.connect_listeners() source_manager = SourceManager(favorites, inputs) source_manager.connect_update(hass, controller) hass.data[DOMAIN] = { DATA_CONTROLLER_MANAGER: controller_manager, DATA_SOURCE_MANAGER: source_manager, MEDIA_PLAYER_DOMAIN: players } services.register(hass, controller) hass.async_create_task(hass.config_entries.async_forward_entry_setup( entry, MEDIA_PLAYER_DOMAIN)) return True
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool: """Start the MQTT protocol service.""" conf = config.get(DOMAIN) # type: Optional[ConfigType] # We need this because discovery can cause components to be set up and # otherwise it will not load the users config. # This needs a better solution. hass.data[DATA_MQTT_HASS_CONFIG] = config if conf is None: # If we have a config entry, setup is done by that config entry. # If there is no config entry, this should fail. return bool(hass.config_entries.async_entries(DOMAIN)) conf = dict(conf) if CONF_EMBEDDED in conf or CONF_BROKER not in conf: if (conf.get(CONF_PASSWORD) is None and config.get('http', {}).get('api_password') is not None): _LOGGER.error( "Starting from release 0.76, the embedded MQTT broker does not" " use api_password as default password anymore. Please set" " password configuration. See https://home-assistant.io/docs/" "mqtt/broker#embedded-broker for details") return False broker_config = await _async_setup_server(hass, config) if broker_config is None: _LOGGER.error("Unable to start embedded MQTT broker") return False conf.update({ CONF_BROKER: broker_config[0], CONF_PORT: broker_config[1], CONF_USERNAME: broker_config[2], CONF_PASSWORD: broker_config[3], CONF_CERTIFICATE: broker_config[4], CONF_PROTOCOL: broker_config[5], CONF_CLIENT_KEY: None, CONF_CLIENT_CERT: None, CONF_TLS_INSECURE: None, }) hass.data[DATA_MQTT_CONFIG] = conf # Only import if we haven't before. if not hass.config_entries.async_entries(DOMAIN): hass.async_create_task(hass.config_entries.flow.async_init( DOMAIN, context={'source': config_entries.SOURCE_IMPORT}, data={} )) return True
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry): """Establish connection with Daikin.""" conf = entry.data daikin_api = await daikin_api_setup(hass, conf[CONF_HOST]) if not daikin_api: return False hass.data.setdefault(DOMAIN, {}).update({entry.entry_id: daikin_api}) for component in COMPONENT_TYPES: hass.async_create_task( hass.config_entries.async_forward_entry_setup( entry, component)) return True
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool: """Start the MQTT protocol service.""" conf = config.get(DOMAIN) # type: Optional[ConfigType] # We need this because discovery can cause components to be set up and # otherwise it will not load the users config. # This needs a better solution. hass.data[DATA_MQTT_HASS_CONFIG] = config websocket_api.async_register_command(hass, websocket_subscribe) if conf is None: # If we have a config entry, setup is done by that config entry. # If there is no config entry, this should fail. return bool(hass.config_entries.async_entries(DOMAIN)) conf = dict(conf) if CONF_EMBEDDED in conf or CONF_BROKER not in conf: broker_config = await _async_setup_server(hass, config) if broker_config is None: _LOGGER.error("Unable to start embedded MQTT broker") return False conf.update({ CONF_BROKER: broker_config[0], CONF_PORT: broker_config[1], CONF_USERNAME: broker_config[2], CONF_PASSWORD: broker_config[3], CONF_CERTIFICATE: broker_config[4], CONF_PROTOCOL: broker_config[5], CONF_CLIENT_KEY: None, CONF_CLIENT_CERT: None, CONF_TLS_INSECURE: None, }) hass.data[DATA_MQTT_CONFIG] = conf # Only import if we haven't before. if not hass.config_entries.async_entries(DOMAIN): hass.async_create_task(hass.config_entries.flow.async_init( DOMAIN, context={'source': config_entries.SOURCE_IMPORT}, data={} )) return True
async def async_setup(hass: HomeAssistantType, config: ConfigType): """Set up UPnP component.""" conf_default = CONFIG_SCHEMA({DOMAIN: {}})[DOMAIN] conf = config.get(DOMAIN, conf_default) local_ip = await hass.async_add_executor_job(get_local_ip) hass.data[DOMAIN] = { 'config': conf, 'devices': {}, 'local_ip': config.get(CONF_LOCAL_IP, local_ip), 'ports': conf.get('ports', {}), } if conf is not None: hass.async_create_task(hass.config_entries.flow.async_init( DOMAIN, context={'source': config_entries.SOURCE_IMPORT})) return True
async def async_setup_entry(hass: HomeAssistantType, config_entry: ConfigEntry): """Set up UPnP/IGD-device from a config entry.""" await async_ensure_domain_data(hass) data = config_entry.data # build UPnP/IGD device ssdp_description = data[CONF_SSDP_DESCRIPTION] try: device = await Device.async_create_device(hass, ssdp_description) except (asyncio.TimeoutError, aiohttp.ClientError): _LOGGER.error('Unable to create upnp-device') return False hass.data[DOMAIN]['devices'][device.udn] = device # port mapping if data.get(CONF_ENABLE_PORT_MAPPING): local_ip = hass.data[DOMAIN]['local_ip'] ports = hass.data[DOMAIN]['auto_config']['ports'] _LOGGER.debug('Enabling port mappings: %s', ports) hass_port = None if hasattr(hass, 'http'): hass_port = hass.http.server_port ports = _substitute_hass_ports(ports, hass_port=hass_port) await device.async_add_port_mappings(ports, local_ip) # sensors if data.get(CONF_ENABLE_SENSORS): _LOGGER.debug('Enabling sensors') # register sensor setup handlers hass.async_create_task(hass.config_entries.async_forward_entry_setup( config_entry, 'sensor')) async def delete_port_mapping(event): """Delete port mapping on quit.""" if data.get(CONF_ENABLE_PORT_MAPPING): _LOGGER.debug('Deleting port mappings') await device.async_delete_port_mappings() hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, delete_port_mapping) return True
async def async_setup(hass: HomeAssistantType, config: ConfigType): """Set up the HEOS component.""" if DOMAIN not in config: return True host = config[DOMAIN][CONF_HOST] entries = hass.config_entries.async_entries(DOMAIN) if not entries: # Create new entry based on config hass.async_create_task( hass.config_entries.flow.async_init( DOMAIN, context={'source': 'import'}, data={CONF_HOST: host})) else: # Check if host needs to be updated entry = entries[0] if entry.data[CONF_HOST] != host: entry.data[CONF_HOST] = host entry.title = format_title(host) hass.config_entries.async_update_entry(entry) return True
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool: """Set up the esphome component.""" hass.data.setdefault(DATA_COMPENSATION, {}) if entry.unique_id == CONF_MQTT_PREFIX: _LOGGER.warning("Skipping %s.", CONF_MQTT_PREFIX) return False datapoints = entry.options.get(CONF_DATAPOINTS, [(1,1), (2,2)]) hass_data = calculate_poly(entry.data, datapoints) ## Registers update listener to update config entry when options are updated. ## Store a reference to the unsubscribe function to cleanup if an entry is unloaded. unsub_options_update_listener = entry.add_update_listener(options_update_listener) hass.data[DATA_COMPENSATION][entry.unique_id] = hass_data hass.data[DATA_COMPENSATION][entry.unique_id]["unsub_options_update_listener"] = unsub_options_update_listener hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, "sensor") ) return True
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry): """Load the saved entities.""" host = entry.data[CONF_HOST] port = entry.data[CONF_PORT] coordinator = CertExpiryDataUpdateCoordinator(hass, entry) await coordinator.async_set_options() await coordinator.async_refresh() if not coordinator.last_update_success: raise ConfigEntryNotReady hass.data.setdefault(DOMAIN, {}) hass.data[DOMAIN][entry.entry_id] = coordinator if entry.unique_id is None: hass.config_entries.async_update_entry(entry, unique_id=f"{host}:{port}") hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, "sensor") ) return True
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry): """Set up Somfy from a config entry.""" # Backwards compat if "auth_implementation" not in entry.data: hass.config_entries.async_update_entry( entry, data={ **entry.data, "auth_implementation": DOMAIN }) implementation = await config_entry_oauth2_flow.async_get_config_entry_implementation( hass, entry) hass.data[DOMAIN][API] = api.ConfigEntrySomfyApi(hass, entry, implementation) await update_all_devices(hass) for component in SOMFY_COMPONENTS: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, component)) return True
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry): """Set up Synology DSM sensors.""" host = entry.data[CONF_HOST] port = entry.data[CONF_PORT] username = entry.data[CONF_USERNAME] password = entry.data[CONF_PASSWORD] unit = hass.config.units.temperature_unit use_ssl = entry.data[CONF_SSL] device_token = entry.data.get("device_token") api = SynoApi(hass, host, port, username, password, unit, use_ssl, device_token) await api.async_setup() hass.data.setdefault(DOMAIN, {}) hass.data[DOMAIN][entry.unique_id] = api hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, "sensor")) return True
async def async_setup(hass: HomeAssistantType, config: ConfigType): """Set up the component.""" hass.data[DOMAIN_DATA_ENTRIES] = {} hass.data[DOMAIN_DATA_CONFIG] = {} for device in config[DOMAIN]: hass.data[DOMAIN_DATA_CONFIG][ (device[CONF_HOST], device[CONF_PORT]) ] = device hass.async_create_task( hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data={ CONF_HOST: device[CONF_HOST], CONF_PORT: device[CONF_PORT], }, ) ) return True
async def platform_async_setup_entry( hass: HomeAssistantType, config_entry: ConfigEntry, async_add_entities, *, component_key: str, info_type, entity_type, state_type, ) -> bool: """Set up this integration using UI.""" if config_entry.source == config_entries.SOURCE_IMPORT: # We get here if the integration is set up using YAML hass.async_create_task( hass.config_entries.async_remove(config_entry.entry_id)) return False # Print startup message config_entry.options = config_entry.data config_entry.add_update_listener(update_listener) # Add sensor return await hass.config_entries.async_forward_entry_setup( config_entry, PLATFORM)
async def async_setup(hass: HomeAssistantType, config: ConfigType): """Set up UPnP component.""" _LOGGER.debug("async_setup, config: %s", config) conf_default = CONFIG_SCHEMA({DOMAIN: {}})[DOMAIN] conf = config.get(DOMAIN, conf_default) local_ip = await hass.async_add_executor_job(get_local_ip) hass.data[DOMAIN] = { DOMAIN_CONFIG: conf, DOMAIN_COORDINATORS: {}, DOMAIN_DEVICES: {}, DOMAIN_LOCAL_IP: conf.get(CONF_LOCAL_IP, local_ip), } # Only start if set up via configuration.yaml. if DOMAIN in config: hass.async_create_task( hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_IMPORT} ) ) return True
async def async_setup(hass: HomeAssistantType, config: ConfigEntry): """Set up the Samsung TV integration.""" if DOMAIN in config: hass.data[DOMAIN] = {} for entry_config in config[DOMAIN]: ip_address = await hass.async_add_executor_job( socket.gethostbyname, entry_config[CONF_HOST] ) for key in SAMSMART_SCHEMA: hass.data[DOMAIN].setdefault(ip_address, {})[key] = entry_config.get( key ) if not entry_config.get(CONF_NAME): entry_config[CONF_NAME] = DEFAULT_NAME entry_config[SOURCE_IMPORT] = True hass.async_create_task( hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_IMPORT}, data=entry_config ) ) return True
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool: """Set up Sonarr from a config entry.""" if not entry.options: options = { CONF_UPCOMING_DAYS: entry.data.get(CONF_UPCOMING_DAYS, DEFAULT_UPCOMING_DAYS), CONF_WANTED_MAX_ITEMS: entry.data.get(CONF_WANTED_MAX_ITEMS, DEFAULT_WANTED_MAX_ITEMS), } hass.config_entries.async_update_entry(entry, options=options) sonarr = Sonarr( host=entry.data[CONF_HOST], port=entry.data[CONF_PORT], api_key=entry.data[CONF_API_KEY], base_path=entry.data[CONF_BASE_PATH], session=async_get_clientsession(hass), tls=entry.data[CONF_SSL], verify_ssl=entry.data[CONF_VERIFY_SSL], ) try: await sonarr.update() except SonarrError as err: raise ConfigEntryNotReady from err undo_listener = entry.add_update_listener(_async_update_listener) hass.data[DOMAIN][entry.entry_id] = { DATA_SONARR: sonarr, DATA_UNDO_UPDATE_LISTENER: undo_listener, } for component in PLATFORMS: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, component)) return True
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry): """Establish connection with Daikin.""" conf = entry.data # For backwards compat, set unique ID if entry.unique_id is None: hass.config_entries.async_update_entry(entry, unique_id=conf[KEY_MAC]) elif ".local" in entry.unique_id: hass.config_entries.async_update_entry(entry, unique_id=conf[KEY_MAC]) daikin_api = await daikin_api_setup( hass, conf[CONF_HOST], conf.get(CONF_API_KEY), conf.get(CONF_UUID), conf.get(CONF_PASSWORD), ) if not daikin_api: return False hass.data.setdefault(DOMAIN, {}).update({entry.entry_id: daikin_api}) for component in COMPONENT_TYPES: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, component)) return True
async def async_setup_entry(hass: HomeAssistantType, config_entry: ConfigEntry) -> bool: """Set up ClimaCell API from a config entry.""" hass.data.setdefault(DOMAIN, {}) # If config entry options not set up, set them up if not config_entry.options: hass.config_entries.async_update_entry( config_entry, options={ CONF_TIMESTEP: DEFAULT_TIMESTEP, }, ) coordinator = ClimaCellDataUpdateCoordinator( hass, config_entry, ClimaCell( config_entry.data[CONF_API_KEY], config_entry.data.get(CONF_LATITUDE, hass.config.latitude), config_entry.data.get(CONF_LONGITUDE, hass.config.longitude), session=async_get_clientsession(hass), ), _set_update_interval(hass, config_entry), ) await coordinator.async_refresh() if not coordinator.last_update_success: raise ConfigEntryNotReady hass.data[DOMAIN][config_entry.entry_id] = coordinator for platform in PLATFORMS: hass.async_create_task( hass.config_entries.async_forward_entry_setup( config_entry, platform)) return True
def get_remove_tasks(hass: HomeAssistantType, entities: Iterable[Entity]) -> List[asyncio.Task]: tasks = [] for entity in entities: if entity.hass is None: entity.hass = hass tasks.append( hass.async_create_task( entity.async_remove() ) ) return tasks
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry): """Set up Somfy from a config entry.""" def token_saver(token): _LOGGER.debug('Saving updated token') entry.data[CONF_TOKEN] = token hass.config_entries.async_update_entry(entry, data={**entry.data}) # Force token update. from pymfy.api.somfy_api import SomfyApi hass.data[DOMAIN][API] = SomfyApi( entry.data['refresh_args']['client_id'], entry.data['refresh_args']['client_secret'], token=entry.data[CONF_TOKEN], token_updater=token_saver) await update_all_devices(hass) for component in SOMFY_COMPONENTS: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, component)) return True
async def async_setup(hass: HomeAssistantType, config: ConfigType): """Set up the HEOS component.""" if DOMAIN not in config: return True host = config[DOMAIN][CONF_HOST] entries = hass.config_entries.async_entries(DOMAIN) if not entries: # Create new entry based on config hass.async_create_task( hass.config_entries.flow.async_init( DOMAIN, context={"source": "import"}, data={CONF_HOST: host} ) ) else: # Check if host needs to be updated entry = entries[0] if entry.data[CONF_HOST] != host: entry.data[CONF_HOST] = host entry.title = format_title(host) hass.config_entries.async_update_entry(entry) return True
async def async_get_registry(hass: HomeAssistantType) -> ZhaDeviceStorage: """Return zha device storage instance.""" task = hass.data.get(DATA_REGISTRY) if task is None: async def _load_reg() -> ZhaDeviceStorage: registry = ZhaDeviceStorage(hass) await registry.async_load() return registry task = hass.data[DATA_REGISTRY] = hass.async_create_task(_load_reg()) return cast(ZhaDeviceStorage, await task)
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool: hass.data.setdefault(DOMAIN, {}) conf = config.get(DOMAIN) # type: ConfigType if conf is None: # If we have a config entry, setup is done by that config entry. # If there is no config entry, this should fail. return bool(hass.config_entries.async_entries(DOMAIN)) hass.data[DOMAIN][DATA_HAVCS_CONFIG] = conf if not [ entry for entry in hass.config_entries.async_entries(DOMAIN) if entry.source == config_entries.SOURCE_IMPORT ]: hass.async_create_task( hass.config_entries.flow.async_init( DOMAIN, context={'source': config_entries.SOURCE_IMPORT}, data={'platform': conf.get(CONF_PLATFORM)})) return True
async def async_setup(hass: HomeAssistantType, config: dict) -> bool: """Set up the Ezviz integration.""" hass.data.setdefault(DOMAIN, {}) conf = config.get(DOMAIN, EZVIZ_SCHEMA({})) hass.data[DOMAIN] = {"config": conf} if hass.config_entries.async_entries(DOMAIN): return True if ACC_USERNAME or ACC_PASSWORD or CONF_REGION not in conf: return True if ACC_USERNAME or ACC_PASSWORD or CONF_REGION in conf: hass.async_create_task( hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_IMPORT}, data=config[DOMAIN], ) ) return True
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry): """Set up Somfy from a config entry.""" # Backwards compat if "auth_implementation" not in entry.data: hass.config_entries.async_update_entry( entry, data={ **entry.data, "auth_implementation": DOMAIN }) implementation = ( await config_entry_oauth2_flow.async_get_config_entry_implementation( hass, entry)) hass.data[DOMAIN][API] = api.ConfigEntrySomfyApi(hass, entry, implementation) await update_all_devices(hass) device_registry = await dr.async_get_registry(hass) devices = hass.data[DOMAIN][DEVICES] hubs = [ device for device in devices if Category.HUB.value in device.categories ] for hub in hubs: device_registry.async_get_or_create( config_entry_id=entry.entry_id, identifiers={(DOMAIN, hub.id)}, manufacturer="Somfy", name=hub.name, model=hub.type, ) for component in SOMFY_COMPONENTS: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, component)) return True
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool: hass.data[DOMAIN] = {} myconfig = { "mindst": config[DOMAIN][CONF_MIN_DST], "numofd": config[DOMAIN][CONF_NUMBER_OF_DAYS], "tz": config[DOMAIN][CONF_TIME_ZONE], "token": config[DOMAIN][CONF_TOKEN], "devs": config[DOMAIN][CONF_DEVICES], "haddr": config["http"]["base_url"], } sensors_gps = hass.data[DOMAIN]["sensors_gps"] = SensorsGps(hass,myconfig) try: await sensors_gps.update() except: _LOGGER.warning("Error creating sensors") return False async_track_time_interval(hass, sensors_gps.async_update, timedelta(seconds=60)) for platform in SUPPORTED_DOMAINS: hass.async_create_task(async_load_platform(hass, platform, DOMAIN, {}, config)) try: hass.http.register_view(Route(hass, myconfig)) hass.components.frontend.async_register_built_in_panel( "iframe", "Routes", "mdi:routes", "myroute", {"url": "/route/route.html"}, require_admin=False, ) except: _LOGGER.error("Error creating panel") return False return True
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool: """Set up the UniFi Protect components.""" conf = config.get(DOMAIN, None) if not conf: return True configured_controllers = { entry.data.get(CONF_HOST) for entry in hass.config_entries.async_entries(DOMAIN) } hass.data.setdefault(DOMAIN, {}) for controller_config in conf: if controller_config[CONF_HOST] not in configured_controllers: hass.async_create_task( hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_USER}, data=controller_config)) return True
async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool: """Set up the MySensors component.""" hass.data[DOMAIN] = {DATA_HASS_CONFIG: config} if DOMAIN not in config or bool(hass.config_entries.async_entries(DOMAIN)): return True config = config[DOMAIN] user_inputs = [ { CONF_DEVICE: gw[CONF_DEVICE], CONF_BAUD_RATE: gw[CONF_BAUD_RATE], CONF_TCP_PORT: gw[CONF_TCP_PORT], CONF_TOPIC_OUT_PREFIX: gw.get(CONF_TOPIC_OUT_PREFIX, ""), CONF_TOPIC_IN_PREFIX: gw.get(CONF_TOPIC_IN_PREFIX, ""), CONF_RETAIN: config[CONF_RETAIN], CONF_VERSION: config[CONF_VERSION], CONF_PERSISTENCE_FILE: gw.get(CONF_PERSISTENCE_FILE) # nodes config ignored at this time. renaming nodes can now be done from the frontend. } for gw in config[CONF_GATEWAYS] ] user_inputs = [ {k: v for k, v in userinput.items() if v is not None} for userinput in user_inputs ] # there is an actual configuration in configuration.yaml, so we have to process it for user_input in user_inputs: hass.async_create_task( hass.config_entries.flow.async_init( DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data=user_input, ) ) return True
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry): """Establish connection with Comfort Cloud.""" from . import pcomfortcloud conf = entry.data if PANASONIC_DEVICES not in hass.data: hass.data[PANASONIC_DEVICES] = [] username = conf[CONF_USERNAME] password = conf[CONF_PASSWORD] force_outside_sensor = entry.options.get(CONF_FORCE_OUTSIDE_SENSOR, DEFAULT_FORCE_OUTSIDE_SENSOR) if CONF_FORCE_OUTSIDE_SENSOR in conf: force_outside_sensor = conf[CONF_FORCE_OUTSIDE_SENSOR] enable_daily_energy_sensor = entry.options.get( CONF_ENABLE_DAILY_ENERGY_SENSOR, DEFAULT_ENABLE_DAILY_ENERGY_SENSOR) api = pcomfortcloud.Session(username, password, verifySsl=False) devices = await hass.async_add_executor_job(api.get_devices) for device in devices: try: api_device = PanasonicApiDevice(hass, api, device, force_outside_sensor, enable_daily_energy_sensor) await api_device.update() if enable_daily_energy_sensor: await api_device.update_energy() hass.data[PANASONIC_DEVICES].append(api_device) except Exception as e: _LOGGER.warning(f"Failed to setup device: {device['name']} ({e})") if hass.data[PANASONIC_DEVICES]: for component in COMPONENT_TYPES: hass.async_create_task( hass.config_entries.async_forward_entry_setup( entry, component)) return True
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry): """Set up Ketra platforms from config entry.""" installation_id = entry.data.get("installation_id") oauth_token = entry.data.get(CONF_ACCESS_TOKEN) hub = await N4Hub.get_hub(installation_id, oauth_token, loop=hass.loop) _LOGGER.info( "Discovered N4 Hub at endpoint '%s' for installation '%s'", hub.url_base, installation_id, ) hass.data.setdefault(DOMAIN, {}) hass.data[DOMAIN][entry.unique_id] = { "common_platform": KetraPlatformCommon(hass, hub, _LOGGER) } for platform in KETRA_PLATFORMS: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, platform)) return True
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool: """Set up Lyric from a config entry.""" conf = hass.data[DATA_LYRIC_CONFIG] client_id = conf[CONF_CLIENT_ID] client_secret = conf[CONF_CLIENT_SECRET] token = entry.data[CONF_TOKEN] token_cache_file = hass.config.path(CONF_LYRIC_CONFIG_FILE) lyric = Lyric(app_name='Home Assistant', client_id=client_id, client_secret=client_secret, token=token, token_cache_file=token_cache_file) hass.data.setdefault(DOMAIN, {})[DATA_LYRIC_CLIENT] = LyricClient(lyric) for component in 'climate', 'sensor': hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, component)) return True
async def async_setup(hass: HomeAssistantType, config: ConfigType): """Set up the Withings component.""" conf = config.get(DOMAIN) if not conf: return True hass.data[DOMAIN] = {const.CONFIG: conf} base_url = conf.get(const.BASE_URL, hass.config.api.base_url).rstrip('/') # We don't pull default values from conf because the config # schema would have validated it for us. for profile in conf.get(const.PROFILES): config_flow.register_flow_implementation(hass, conf.get(const.CLIENT_ID), conf.get(const.CLIENT_SECRET), base_url, profile) hass.async_create_task( hass.config_entries.flow.async_init( DOMAIN, context={'source': const.SOURCE_USER}, data={})) return True
async def async_get_registry(hass: HomeAssistantType) -> ZhaStorage: """Return zha device storage instance.""" task = hass.data.get(DATA_REGISTRY) if task is None: async def _load_reg() -> ZhaStorage: registry = ZhaStorage(hass) await registry.async_load() return registry task = hass.data[DATA_REGISTRY] = hass.async_create_task(_load_reg()) return cast(ZhaStorage, await task)
async def async_setup_platform( hass: HomeAssistantType, config: ConfigType, async_add_entities: Callable[[List[Entity], bool], None], discovery_info: Any = None, ) -> None: """Import the platform into a config entry.""" if len(hass.config_entries.async_entries(DOMAIN)) > 0: return True config[CONF_BASE_PATH] = f"{config[CONF_URLBASE]}{DEFAULT_BASE_PATH}" config[CONF_UPCOMING_DAYS] = int(config[CONF_DAYS]) config[CONF_VERIFY_SSL] = False del config[CONF_DAYS] del config[CONF_INCLUDED] del config[CONF_MONITORED_CONDITIONS] del config[CONF_URLBASE] hass.async_create_task( hass.config_entries.flow.async_init(DOMAIN, context={"source": SOURCE_IMPORT}, data=config))
async def async_setup_entry(hass: HomeAssistantType, config_entry: ConfigEntry) -> bool: """Set up Minecraft Server from a config entry.""" domain_data = hass.data.setdefault(DOMAIN, {}) # Create and store server instance. unique_id = config_entry.unique_id _LOGGER.debug( "Creating server instance for '%s' (%s)", config_entry.data[CONF_NAME], config_entry.data[CONF_HOST], ) server = MinecraftServer(hass, unique_id, config_entry.data) domain_data[unique_id] = server await server.async_update() server.start_periodic_update() # Set up platforms. for platform in PLATFORMS: hass.async_create_task( hass.config_entries.async_forward_entry_setup(config_entry, platform) ) return True
async def async_setup_entry(hass: HomeAssistantType, entry: config_entries.ConfigEntry): """Set up an access point from a config entry.""" client = Client(entry.data[CONF_HOST], entry.data[CONF_PORT]) config = hass.data[DOMAIN_DATA_CONFIG].get( (entry.data[CONF_HOST], entry.data[CONF_PORT]), DEVICE_SCHEMA( {CONF_HOST: entry.data[CONF_HOST], CONF_PORT: entry.data[CONF_PORT]} ), ) hass.data[DOMAIN_DATA_ENTRIES][entry.entry_id] = { "client": client, "config": config, } asyncio.ensure_future(_run_client(hass, client, config[CONF_SCAN_INTERVAL])) hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, "media_player") ) return True
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool: """Set up Canary from a config entry.""" if not entry.options: options = { CONF_FFMPEG_ARGUMENTS: entry.data.get(CONF_FFMPEG_ARGUMENTS, DEFAULT_FFMPEG_ARGUMENTS), CONF_TIMEOUT: entry.data.get(CONF_TIMEOUT, DEFAULT_TIMEOUT), } hass.config_entries.async_update_entry(entry, options=options) try: canary_api = await hass.async_add_executor_job( _get_canary_api_instance, entry) except (ConnectTimeout, HTTPError) as error: _LOGGER.error("Unable to connect to Canary service: %s", str(error)) raise ConfigEntryNotReady from error coordinator = CanaryDataUpdateCoordinator(hass, api=canary_api) await coordinator.async_refresh() if not coordinator.last_update_success: raise ConfigEntryNotReady undo_listener = entry.add_update_listener(_async_update_listener) hass.data[DOMAIN][entry.entry_id] = { DATA_COORDINATOR: coordinator, DATA_UNDO_UPDATE_LISTENER: undo_listener, } for platform in PLATFORMS: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, platform)) return True
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry): """Establish connection with Neohub""" conf = entry.data hub = await neohub_api_setup(hass, conf[CONF_HOST]) hass.data.setdefault(DOMAIN, {}).update({entry.entry_id: hub}) # determining mac address is only possible on local subnet # not if running in a non-bridged docker container, for example. mac = get_mac_from_host(conf[CONF_HOST]) _LOGGER.info("neohub host: %s mac: %s" % (conf[CONF_HOST], mac)) if mac is None: conns = {('hub_ip', conf[CONF_HOST])} idents = {(DOMAIN, conf[CONF_HOST])} else: conns = {(CONNECTION_NETWORK_MAC, mac)} idents = {(DOMAIN, mac)} _LOGGER.info("Adding neohub to device registry, entry_id: %s" % entry.entry_id) # add to device registry dev_reg = await dr.async_get_registry(hass) dev_reg.async_get_or_create( config_entry_id=entry.entry_id, connections=conns, identifiers=idents, manufacturer='Heatmiser', name='NeoHub', model=hub.dcb.get('DEVICE_ID'), sw_version=hub.dcb.get('Firmware version'), ) # set up devices for: climate. switch, sensor? for component in COMPONENT_TYPES: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, component)) return True
async def async_setup(hass: HomeAssistantType, config: ConfigType): """Set up the mobile app component.""" store = hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY) app_config = await store.async_load() if app_config is None: app_config = { DATA_BINARY_SENSOR: {}, DATA_CONFIG_ENTRIES: {}, DATA_DELETED_IDS: [], DATA_DEVICES: {}, DATA_SENSOR: {} } hass.data[DOMAIN] = { DATA_BINARY_SENSOR: app_config.get(DATA_BINARY_SENSOR, {}), DATA_CONFIG_ENTRIES: {}, DATA_DELETED_IDS: app_config.get(DATA_DELETED_IDS, []), DATA_DEVICES: {}, DATA_SENSOR: app_config.get(DATA_SENSOR, {}), DATA_STORE: store, } hass.http.register_view(RegistrationsView()) register_websocket_handlers(hass) for deleted_id in hass.data[DOMAIN][DATA_DELETED_IDS]: try: webhook_register(hass, DOMAIN, "Deleted Webhook", deleted_id, handle_webhook) except ValueError: pass hass.async_create_task(discovery.async_load_platform( hass, 'notify', DOMAIN, {}, config)) return True
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry): """Initialize config entry which represents an installed SmartApp.""" from pysmartthings import SmartThings if not hass.config.api.base_url.lower().startswith('https://'): _LOGGER.warning("The 'base_url' of the 'http' component must be " "configured and start with 'https://'") return False api = SmartThings(async_get_clientsession(hass), entry.data[CONF_ACCESS_TOKEN]) remove_entry = False try: # See if the app is already setup. This occurs when there are # installs in multiple SmartThings locations (valid use-case) manager = hass.data[DOMAIN][DATA_MANAGER] smart_app = manager.smartapps.get(entry.data[CONF_APP_ID]) if not smart_app: # Validate and setup the app. app = await api.app(entry.data[CONF_APP_ID]) smart_app = setup_smartapp(hass, app) # Validate and retrieve the installed app. installed_app = await validate_installed_app( api, entry.data[CONF_INSTALLED_APP_ID]) # Get devices and their current status devices = await api.devices( location_ids=[installed_app.location_id]) async def retrieve_device_status(device): try: await device.status.refresh() except ClientResponseError: _LOGGER.debug("Unable to update status for device: %s (%s), " "the device will be ignored", device.label, device.device_id, exc_info=True) devices.remove(device) await asyncio.gather(*[retrieve_device_status(d) for d in devices.copy()]) # Setup device broker broker = DeviceBroker(hass, devices, installed_app.installed_app_id) broker.event_handler_disconnect = \ smart_app.connect_event(broker.event_handler) hass.data[DOMAIN][DATA_BROKERS][entry.entry_id] = broker except ClientResponseError as ex: if ex.status in (401, 403): _LOGGER.exception("Unable to setup config entry '%s' - please " "reconfigure the integration", entry.title) remove_entry = True else: _LOGGER.debug(ex, exc_info=True) raise ConfigEntryNotReady except (ClientConnectionError, RuntimeWarning) as ex: _LOGGER.debug(ex, exc_info=True) raise ConfigEntryNotReady if remove_entry: hass.async_create_task( hass.config_entries.async_remove(entry.entry_id)) # only create new flow if there isn't a pending one for SmartThings. flows = hass.config_entries.flow.async_progress() if not [flow for flow in flows if flow['handler'] == DOMAIN]: hass.async_create_task( hass.config_entries.flow.async_init( DOMAIN, context={'source': 'import'})) return False for component in SUPPORTED_PLATFORMS: hass.async_create_task(hass.config_entries.async_forward_entry_setup( entry, component)) return True
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool: """Set up the esphome component.""" # pylint: disable=redefined-outer-name from aioesphomeapi import APIClient, APIConnectionError hass.data.setdefault(DOMAIN, {}) host = entry.data[CONF_HOST] port = entry.data[CONF_PORT] password = entry.data[CONF_PASSWORD] cli = APIClient(hass.loop, host, port, password, client_info="Home Assistant {}".format(const.__version__)) # Store client in per-config-entry hass.data store = Store(hass, STORAGE_VERSION, STORAGE_KEY.format(entry.entry_id), encoder=JSONEncoder) entry_data = hass.data[DOMAIN][entry.entry_id] = RuntimeEntryData( client=cli, entry_id=entry.entry_id, store=store, ) async def on_stop(event: Event) -> None: """Cleanup the socket client on HA stop.""" await _cleanup_instance(hass, entry) entry_data.cleanup_callbacks.append( hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, on_stop) ) @callback def async_on_state(state: 'EntityState') -> None: """Send dispatcher updates when a new state is received.""" entry_data.async_update_state(hass, state) @callback def async_on_service_call(service: 'ServiceCall') -> None: """Call service when user automation in ESPHome config is triggered.""" domain, service_name = service.service.split('.', 1) service_data = service.data if service.data_template: try: data_template = {key: Template(value) for key, value in service.data_template.items()} template.attach(hass, data_template) service_data.update(template.render_complex( data_template, service.variables)) except TemplateError as ex: _LOGGER.error('Error rendering data template: %s', ex) return hass.async_create_task(hass.services.async_call( domain, service_name, service_data, blocking=True)) async def send_home_assistant_state(entity_id: str, _, new_state: Optional[State]) -> None: """Forward Home Assistant states to ESPHome.""" if new_state is None: return await cli.send_home_assistant_state(entity_id, new_state.state) @callback def async_on_state_subscription(entity_id: str) -> None: """Subscribe and forward states for requested entities.""" unsub = async_track_state_change( hass, entity_id, send_home_assistant_state) entry_data.disconnect_callbacks.append(unsub) # Send initial state hass.async_create_task(send_home_assistant_state( entity_id, None, hass.states.get(entity_id))) async def on_login() -> None: """Subscribe to states and list entities on successful API login.""" try: entry_data.device_info = await cli.device_info() entry_data.available = True await _async_setup_device_registry(hass, entry, entry_data.device_info) entry_data.async_update_device_state(hass) entity_infos = await cli.list_entities() entry_data.async_update_static_infos(hass, entity_infos) await cli.subscribe_states(async_on_state) await cli.subscribe_service_calls(async_on_service_call) await cli.subscribe_home_assistant_states( async_on_state_subscription) hass.async_create_task(entry_data.async_save_to_store()) except APIConnectionError as err: _LOGGER.warning("Error getting initial data: %s", err) # Re-connection logic will trigger after this await cli.disconnect() try_connect = await _setup_auto_reconnect_logic(hass, cli, entry, host, on_login) # This is a bit of a hack: We schedule complete_setup into the # event loop and return immediately (return True) # # Usually, we should avoid that so that HA can track which components # have been started successfully and which failed to be set up. # That doesn't work here for two reasons: # - We have our own re-connect logic # - Before we do the first try_connect() call, we need to make sure # all dispatcher event listeners have been connected, so # async_forward_entry_setup needs to be awaited. However, if we # would await async_forward_entry_setup() in async_setup_entry(), # we would end up with a deadlock. # # Solution is: complete the setup outside of the async_setup_entry() # function. HA will wait until the first connection attempt is made # before starting up (as it should), but if the first connection attempt # fails we will schedule all next re-connect attempts outside of the # tracked tasks (hass.loop.create_task). This way HA won't stall startup # forever until a connection is successful. async def complete_setup() -> None: """Complete the config entry setup.""" tasks = [] for component in HA_COMPONENTS: tasks.append(hass.config_entries.async_forward_entry_setup( entry, component)) await asyncio.wait(tasks) infos = await entry_data.async_load_from_store() entry_data.async_update_static_infos(hass, infos) # If first connect fails, the next re-connect will be scheduled # outside of _pending_task, in order not to delay HA startup # indefinitely await try_connect(is_disconnect=False) hass.async_create_task(complete_setup()) return True
async def async_setup_entry(hass: HomeAssistantType, config_entry: ConfigEntry): """Set up UPnP/IGD device from a config entry.""" domain_data = hass.data[DOMAIN] conf = domain_data['config'] # discover and construct device = await async_discover_and_construct(hass, config_entry.data.get('udn')) if not device: _LOGGER.info('Unable to create UPnP/IGD, aborting') return False # 'register'/save UDN config_entry.data['udn'] = device.udn hass.data[DOMAIN]['devices'][device.udn] = device hass.config_entries.async_update_entry(entry=config_entry, data=config_entry.data) # create device registry entry device_registry = await dr.async_get_registry(hass) device_registry.async_get_or_create( config_entry_id=config_entry.entry_id, connections={ (dr.CONNECTION_UPNP, device.udn) }, identifiers={ (DOMAIN, device.udn) }, name=device.name, manufacturer=device.manufacturer, ) # set up sensors if conf.get(CONF_ENABLE_SENSORS): _LOGGER.debug('Enabling sensors') # register sensor setup handlers hass.async_create_task(hass.config_entries.async_forward_entry_setup( config_entry, 'sensor')) # set up port mapping if conf.get(CONF_ENABLE_PORT_MAPPING): _LOGGER.debug('Enabling port mapping') local_ip = domain_data['local_ip'] ports = conf.get('ports', {}) hass_port = None if hasattr(hass, 'http'): hass_port = hass.http.server_port ports = _substitute_hass_ports(ports, hass_port=hass_port) await device.async_add_port_mappings(ports, local_ip) # set up port mapping deletion on stop-hook async def delete_port_mapping(event): """Delete port mapping on quit.""" _LOGGER.debug('Deleting port mappings') await device.async_delete_port_mappings() hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, delete_port_mapping) return True