async def async_setup_entry(opp: OpenPeerPower, config_entry: ConfigEntry): """Set up AEMET OpenData as config entry.""" name = config_entry.data[CONF_NAME] api_key = config_entry.data[CONF_API_KEY] latitude = config_entry.data[CONF_LATITUDE] longitude = config_entry.data[CONF_LONGITUDE] station_updates = config_entry.options.get(CONF_STATION_UPDATES, True) aemet = AEMET(api_key) weather_coordinator = WeatherUpdateCoordinator(opp, aemet, latitude, longitude, station_updates) await weather_coordinator.async_config_entry_first_refresh() opp.data.setdefault(DOMAIN, {}) opp.data[DOMAIN][config_entry.entry_id] = { ENTRY_NAME: name, ENTRY_WEATHER_COORDINATOR: weather_coordinator, } opp.config_entries.async_setup_platforms(config_entry, PLATFORMS) config_entry.async_on_unload( config_entry.add_update_listener(async_update_options)) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry) -> bool: """Set up NZBGet from a config entry.""" if not entry.options: options = { CONF_SCAN_INTERVAL: entry.data.get( CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL ), } opp.config_entries.async_update_entry(entry, options=options) coordinator = NZBGetDataUpdateCoordinator( opp, config=entry.data, options=entry.options, ) await coordinator.async_config_entry_first_refresh() undo_listener = entry.add_update_listener(_async_update_listener) opp.data[DOMAIN][entry.entry_id] = { DATA_COORDINATOR: coordinator, DATA_UNDO_UPDATE_LISTENER: undo_listener, } opp.config_entries.async_setup_platforms(entry, PLATFORMS) _async_register_services(opp, coordinator) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry): """Set up AsusWrt platform.""" # import options from yaml if empty yaml_options = opp.data.get(DOMAIN, {}).pop("yaml_options", {}) if not entry.options and yaml_options: opp.config_entries.async_update_entry(entry, options=yaml_options) router = AsusWrtRouter(opp, entry) await router.setup() router.async_on_close(entry.add_update_listener(update_listener)) opp.config_entries.async_setup_platforms(entry, PLATFORMS) async def async_close_connection(event): """Close AsusWrt connection on OPP Stop.""" await router.close() stop_listener = opp.bus.async_listen_once( EVENT_OPENPEERPOWER_STOP, async_close_connection ) opp.data.setdefault(DOMAIN, {})[entry.entry_id] = { DATA_ASUSWRT: router, "stop_listener": stop_listener, } return True
async def _async_initialize( opp: OpenPeerPower, entry: ConfigEntry, host: str, device: YeelightDevice | None = None, ) -> None: entry_data = opp.data[DOMAIN][DATA_CONFIG_ENTRIES][entry.entry_id] = { DATA_PLATFORMS_LOADED: False } entry.async_on_unload(entry.add_update_listener(_async_update_listener)) @callback def _async_load_platforms(): if entry_data[DATA_PLATFORMS_LOADED]: return entry_data[DATA_PLATFORMS_LOADED] = True opp.config_entries.async_setup_platforms(entry, PLATFORMS) if not device: device = await _async_get_device(opp, host, entry) entry_data[DATA_DEVICE] = device entry.async_on_unload( async_dispatcher_connect( opp, DEVICE_INITIALIZED.format(host), _async_load_platforms, )) entry.async_on_unload(device.async_unload) await device.async_setup()
async def async_setup_entry(opp: OpenPeerPower, 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), } opp.config_entries.async_update_entry(entry, options=options) try: canary_api = await opp.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(opp, api=canary_api) await coordinator.async_config_entry_first_refresh() undo_listener = entry.add_update_listener(_async_update_listener) opp.data[DOMAIN][entry.entry_id] = { DATA_COORDINATOR: coordinator, DATA_UNDO_UPDATE_LISTENER: undo_listener, } opp.config_entries.async_setup_platforms(entry, PLATFORMS) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry) -> bool: """Set up AccuWeather as config entry.""" api_key: str = entry.data[CONF_API_KEY] assert entry.unique_id is not None location_key = entry.unique_id forecast: bool = entry.options.get(CONF_FORECAST, False) _LOGGER.debug("Using location_key: %s, get forecast: %s", location_key, forecast) websession = async_get_clientsession(opp) coordinator = AccuWeatherDataUpdateCoordinator(opp, websession, api_key, location_key, forecast) await coordinator.async_config_entry_first_refresh() undo_listener = entry.add_update_listener(update_listener) opp.data.setdefault(DOMAIN, {})[entry.entry_id] = { COORDINATOR: coordinator, UNDO_UPDATE_LISTENER: undo_listener, } opp.config_entries.async_setup_platforms(entry, PLATFORMS) return True
async def async_setup_entry(opp: core.OpenPeerPower, entry: config_entries.ConfigEntry): """Set up the denonavr components from a config entry.""" opp.data.setdefault(DOMAIN, {}) # Connect to receiver connect_denonavr = ConnectDenonAVR( entry.data[CONF_HOST], DEFAULT_TIMEOUT, entry.options.get(CONF_SHOW_ALL_SOURCES, DEFAULT_SHOW_SOURCES), entry.options.get(CONF_ZONE2, DEFAULT_ZONE2), entry.options.get(CONF_ZONE3, DEFAULT_ZONE3), lambda: get_async_client(opp), ) try: await connect_denonavr.async_connect_receiver() except (AvrNetworkError, AvrTimoutError) as ex: raise ConfigEntryNotReady from ex receiver = connect_denonavr.receiver undo_listener = entry.add_update_listener(update_listener) opp.data[DOMAIN][entry.entry_id] = { CONF_RECEIVER: receiver, UNDO_UPDATE_LISTENER: undo_listener, } opp.config_entries.async_setup_platforms(entry, PLATFORMS) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry): """Set up Monoprice 6-Zone Amplifier from a config entry.""" port = entry.data[CONF_PORT] try: monoprice = await opp.async_add_executor_job(get_monoprice, port) except SerialException as err: _LOGGER.error("Error connecting to Monoprice controller at %s", port) raise ConfigEntryNotReady from err # double negative to handle absence of value first_run = not bool(entry.data.get(CONF_NOT_FIRST_RUN)) if first_run: opp.config_entries.async_update_entry( entry, data={**entry.data, CONF_NOT_FIRST_RUN: True} ) undo_listener = entry.add_update_listener(_update_listener) opp.data.setdefault(DOMAIN, {})[entry.entry_id] = { MONOPRICE_OBJECT: monoprice, UNDO_UPDATE_LISTENER: undo_listener, FIRST_RUN: first_run, } opp.config_entries.async_setup_platforms(entry, PLATFORMS) return True
async def async_setup_entry(opp: OpenPeerPower, config_entry: ConfigEntry): """Set up OpenWeatherMap as config entry.""" name = config_entry.data[CONF_NAME] api_key = config_entry.data[CONF_API_KEY] latitude = config_entry.data.get(CONF_LATITUDE, opp.config.latitude) longitude = config_entry.data.get(CONF_LONGITUDE, opp.config.longitude) forecast_mode = _get_config_value(config_entry, CONF_MODE) language = _get_config_value(config_entry, CONF_LANGUAGE) config_dict = _get_owm_config(language) owm = OWM(api_key, config_dict).weather_manager() weather_coordinator = WeatherUpdateCoordinator(owm, latitude, longitude, forecast_mode, opp) await weather_coordinator.async_config_entry_first_refresh() opp.data.setdefault(DOMAIN, {}) opp.data[DOMAIN][config_entry.entry_id] = { ENTRY_NAME: name, ENTRY_WEATHER_COORDINATOR: weather_coordinator, } opp.config_entries.async_setup_platforms(config_entry, PLATFORMS) update_listener = config_entry.add_update_listener(async_update_options) opp.data[DOMAIN][config_entry.entry_id][UPDATE_LISTENER] = update_listener return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry): """Set up DoorBird from a config entry.""" _async_import_options_from_data_if_missing(opp, entry) doorstation_config = entry.data doorstation_options = entry.options config_entry_id = entry.entry_id device_ip = doorstation_config[CONF_HOST] username = doorstation_config[CONF_USERNAME] password = doorstation_config[CONF_PASSWORD] device = DoorBird(device_ip, username, password) try: status, info = await opp.async_add_executor_job( _init_doorbird_device, device) except requests.exceptions.HTTPError as err: if err.response.status_code == HTTP_UNAUTHORIZED: _LOGGER.error("Authorization rejected by DoorBird for %s@%s", username, device_ip) return False raise ConfigEntryNotReady from err except OSError as oserr: _LOGGER.error("Failed to setup doorbird at %s: %s", device_ip, oserr) raise ConfigEntryNotReady from oserr if not status[0]: _LOGGER.error( "Could not connect to DoorBird as %s@%s: Error %s", username, device_ip, str(status[1]), ) raise ConfigEntryNotReady token = doorstation_config.get(CONF_TOKEN, config_entry_id) custom_url = doorstation_config.get(CONF_CUSTOM_URL) name = doorstation_config.get(CONF_NAME) events = doorstation_options.get(CONF_EVENTS, []) doorstation = ConfiguredDoorBird(device, name, custom_url, token) doorstation.update_events(events) # Subscribe to doorbell or motion events if not await _async_register_events(opp, doorstation): raise ConfigEntryNotReady undo_listener = entry.add_update_listener(_update_listener) opp.data[DOMAIN][config_entry_id] = { DOOR_STATION: doorstation, DOOR_STATION_INFO: info, UNDO_UPDATE_LISTENER: undo_listener, } opp.config_entries.async_setup_platforms(entry, PLATFORMS) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry): """Set up HomeKit from a config entry.""" _async_import_options_from_data_if_missing(opp, entry) conf = entry.data options = entry.options name = conf[CONF_NAME] port = conf[CONF_PORT] _LOGGER.debug("Begin setup HomeKit for %s", name) # ip_address and advertise_ip are yaml only ip_address = conf.get(CONF_IP_ADDRESS) advertise_ip = conf.get(CONF_ADVERTISE_IP) # exclude_accessory_mode is only used for config flow # to indicate that the config entry was setup after # we started creating config entries for entities that # to run in accessory mode and that we should never include # these entities on the bridge. For backwards compatibility # with users who have not migrated yet we do not do exclude # these entities by default as we cannot migrate automatically # since it requires a re-pairing. exclude_accessory_mode = conf.get(CONF_EXCLUDE_ACCESSORY_MODE, DEFAULT_EXCLUDE_ACCESSORY_MODE) homekit_mode = options.get(CONF_HOMEKIT_MODE, DEFAULT_HOMEKIT_MODE) entity_config = options.get(CONF_ENTITY_CONFIG, {}).copy() auto_start = options.get(CONF_AUTO_START, DEFAULT_AUTO_START) entity_filter = FILTER_SCHEMA(options.get(CONF_FILTER, {})) homekit = HomeKit( opp, name, port, ip_address, entity_filter, exclude_accessory_mode, entity_config, homekit_mode, advertise_ip, entry.entry_id, entry.title, ) entry.async_on_unload(entry.add_update_listener(_async_update_listener)) entry.async_on_unload( opp.bus.async_listen_once(EVENT_OPENPEERPOWER_STOP, homekit.async_stop)) opp.data[DOMAIN][entry.entry_id] = {HOMEKIT: homekit} if opp.state == CoreState.running: await homekit.async_start() elif auto_start: opp.bus.async_listen_once(EVENT_OPENPEERPOWER_STARTED, homekit.async_start) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry): """Set up DSMR from a config entry.""" opp.data.setdefault(DOMAIN, {}) opp.data[DOMAIN][entry.entry_id] = {} opp.config_entries.async_setup_platforms(entry, PLATFORMS) listener = entry.add_update_listener(async_update_options) opp.data[DOMAIN][entry.entry_id][DATA_LISTENER] = listener return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry): """Set up BMW Connected Drive from a config entry.""" opp.data.setdefault(DOMAIN, {}) opp.data[DOMAIN].setdefault(DATA_ENTRIES, {}) _async_migrate_options_from_data_if_missing(opp, entry) try: account = await opp.async_add_executor_job(setup_account, entry, opp, entry.data[CONF_USERNAME]) except OSError as ex: raise ConfigEntryNotReady from ex async def _async_update_all(service_call=None): """Update all BMW accounts.""" await opp.async_add_executor_job(_update_all) def _update_all() -> None: """Update all BMW accounts.""" for entry in opp.data[DOMAIN][DATA_ENTRIES].copy().values(): entry[CONF_ACCOUNT].update() # Add update listener for config entry changes (options) undo_listener = entry.add_update_listener(update_listener) opp.data[DOMAIN][DATA_ENTRIES][entry.entry_id] = { CONF_ACCOUNT: account, UNDO_UPDATE_LISTENER: undo_listener, } # Service to manually trigger updates for all accounts. opp.services.async_register(DOMAIN, SERVICE_UPDATE_STATE, _async_update_all) await _async_update_all() opp.config_entries.async_setup_platforms( entry, [platform for platform in PLATFORMS if platform != NOTIFY_DOMAIN]) # set up notify platform, no entry support for notify platform yet, # have to use discovery to load platform. opp.async_create_task( discovery.async_load_platform( opp, NOTIFY_DOMAIN, DOMAIN, {CONF_NAME: DOMAIN}, opp.data[DOMAIN][DATA_OPP_CONFIG], )) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry): """Set up Tado from a config entry.""" _async_import_options_from_data_if_missing(opp, entry) username = entry.data[CONF_USERNAME] password = entry.data[CONF_PASSWORD] fallback = entry.options.get(CONF_FALLBACK, True) tadoconnector = TadoConnector(opp, username, password, fallback) try: await opp.async_add_executor_job(tadoconnector.setup) except KeyError: _LOGGER.error("Failed to login to tado") return False except RuntimeError as exc: _LOGGER.error("Failed to setup tado: %s", exc) return ConfigEntryNotReady except requests.exceptions.Timeout as ex: raise ConfigEntryNotReady from ex except requests.exceptions.HTTPError as ex: if ex.response.status_code > 400 and ex.response.status_code < 500: _LOGGER.error("Failed to login to tado: %s", ex) return False raise ConfigEntryNotReady from ex # Do first update await opp.async_add_executor_job(tadoconnector.update) # Poll for updates in the background update_track = async_track_time_interval( opp, lambda now: tadoconnector.update(), SCAN_INTERVAL, ) update_listener = entry.add_update_listener(_async_update_listener) opp.data.setdefault(DOMAIN, {}) opp.data[DOMAIN][entry.entry_id] = { DATA: tadoconnector, UPDATE_TRACK: update_track, UPDATE_LISTENER: update_listener, } opp.config_entries.async_setup_platforms(entry, PLATFORMS) return True
async def async_setup_entry(opp: OpenPeerPower, config_entry: ConfigEntry): """Set up wiffi from a config entry, config_entry contains data from config entry database.""" if not config_entry.update_listeners: config_entry.add_update_listener(async_update_options) # create api object api = WiffiIntegrationApi(opp) api.async_setup(config_entry) # store api object opp.data.setdefault(DOMAIN, {})[config_entry.entry_id] = api try: await api.server.start_server() except OSError as exc: if exc.errno != errno.EADDRINUSE: _LOGGER.error("Start_server failed, errno: %d", exc.errno) return False _LOGGER.error("Port %s already in use", config_entry.data[CONF_PORT]) raise ConfigEntryNotReady from exc opp.config_entries.async_setup_platforms(config_entry, PLATFORMS) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry) -> bool: """Set up a bridge from a config entry.""" LOGGER.debug("Setting up entry %s", entry.data) bridge = DynaliteBridge(opp, entry.data) # need to do it before the listener opp.data[DOMAIN][entry.entry_id] = bridge entry.async_on_unload(entry.add_update_listener(async_entry_changed)) if not await bridge.async_setup(): LOGGER.error("Could not set up bridge for entry %s", entry.data) opp.data[DOMAIN][entry.entry_id] = None raise ConfigEntryNotReady opp.config_entries.async_setup_platforms(entry, PLATFORMS) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry): """Set up panel from a config entry.""" client = AlarmPanel(opp, entry) # creates a panel data store in opp.data[DOMAIN][CONF_DEVICES] await client.async_save_data() # if the cfg entry was created we know we could connect to the panel at some point # async_connect will handle retries until it establishes a connection await client.async_connect() opp.config_entries.async_setup_platforms(entry, PLATFORMS) # config entry specific data to enable unload opp.data[DOMAIN][entry.entry_id] = { UNDO_UPDATE_LISTENER: entry.add_update_listener(async_entry_updated) } return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry): """Set up Dexcom from a config entry.""" try: dexcom = await opp.async_add_executor_job( Dexcom, entry.data[CONF_USERNAME], entry.data[CONF_PASSWORD], entry.data[CONF_SERVER] == SERVER_OUS, ) except AccountError: return False except SessionError as error: raise ConfigEntryNotReady from error if not entry.options: opp.config_entries.async_update_entry( entry, options={CONF_UNIT_OF_MEASUREMENT: MG_DL}) async def async_update_data(): try: return await opp.async_add_executor_job( dexcom.get_current_glucose_reading) except SessionError as error: raise UpdateFailed(error) from error opp.data.setdefault(DOMAIN, {}) opp.data[DOMAIN][entry.entry_id] = { COORDINATOR: DataUpdateCoordinator( opp, _LOGGER, name=DOMAIN, update_method=async_update_data, update_interval=SCAN_INTERVAL, ), UNDO_UPDATE_LISTENER: entry.add_update_listener(update_listener), } await opp.data[DOMAIN][entry.entry_id ][COORDINATOR].async_config_entry_first_refresh() opp.config_entries.async_setup_platforms(entry, PLATFORMS) return True
async def async_setup_entry(opp: OpenPeerPower, config_entry: ConfigEntry) -> bool: """Set up the component.""" opp.data.setdefault(DOMAIN, {}) async_add_defaults(opp, config_entry) router = KeeneticRouter(opp, config_entry) await router.async_setup() undo_listener = config_entry.add_update_listener(update_listener) opp.data[DOMAIN][config_entry.entry_id] = { ROUTER: router, UNDO_UPDATE_LISTENER: undo_listener, } opp.config_entries.async_setup_platforms(config_entry, PLATFORMS) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry): """Set up kmtronic from a config entry.""" session = aiohttp_client.async_get_clientsession(opp) auth = Auth( session, f"http://{entry.data[CONF_HOST]}", entry.data[CONF_USERNAME], entry.data[CONF_PASSWORD], ) hub = KMTronicHubAPI(auth) async def async_update_data(): try: async with async_timeout.timeout(10): await hub.async_update_relays() except aiohttp.client_exceptions.ClientResponseError as err: raise UpdateFailed(f"Wrong credentials: {err}") from err except aiohttp.client_exceptions.ClientConnectorError as err: raise UpdateFailed(f"Error communicating with API: {err}") from err coordinator = DataUpdateCoordinator( opp, _LOGGER, name=f"{MANUFACTURER} {hub.name}", update_method=async_update_data, update_interval=timedelta(seconds=30), ) await coordinator.async_config_entry_first_refresh() opp.data.setdefault(DOMAIN, {}) opp.data[DOMAIN][entry.entry_id] = { DATA_HUB: hub, DATA_COORDINATOR: coordinator, } opp.config_entries.async_setup_platforms(entry, PLATFORMS) update_listener = entry.add_update_listener(async_update_options) opp.data[DOMAIN][entry.entry_id][UPDATE_LISTENER] = update_listener return True
async def async_setup_entry(opp: OpenPeerPower, 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), } opp.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(opp), tls=entry.data[CONF_SSL], verify_ssl=entry.data[CONF_VERIFY_SSL], ) try: await sonarr.update() except SonarrAccessRestricted as err: raise ConfigEntryAuthFailed( "API Key is no longer valid. Please reauthenticate") from err except SonarrError as err: raise ConfigEntryNotReady from err undo_listener = entry.add_update_listener(_async_update_listener) opp.data.setdefault(DOMAIN, {}) opp.data[DOMAIN][entry.entry_id] = { DATA_SONARR: sonarr, DATA_UNDO_UPDATE_LISTENER: undo_listener, } opp.config_entries.async_setup_platforms(entry, PLATFORMS) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry) -> bool: """Set up fritzboxtools from config entry.""" _LOGGER.debug("Setting up FRITZ!Box Tools component") fritz_tools = FritzBoxTools( opp=opp, host=entry.data[CONF_HOST], port=entry.data[CONF_PORT], username=entry.data[CONF_USERNAME], password=entry.data[CONF_PASSWORD], ) try: await fritz_tools.async_setup() await fritz_tools.async_start(entry.options) except FritzSecurityError as ex: raise ConfigEntryAuthFailed from ex except FritzConnectionException as ex: raise ConfigEntryNotReady from ex opp.data.setdefault(DOMAIN, {}) opp.data[DOMAIN][entry.entry_id] = fritz_tools if DATA_FRITZ not in opp.data: opp.data[DATA_FRITZ] = FritzData() @callback def _async_unload(event): fritz_tools.async_unload() entry.async_on_unload( opp.bus.async_listen_once(EVENT_OPENPEERPOWER_STOP, _async_unload) ) entry.async_on_unload(entry.add_update_listener(update_listener)) # Load the other platforms like switch opp.config_entries.async_setup_platforms(entry, PLATFORMS) await async_setup_services(opp) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry): """Set up Risco from a config entry.""" data = entry.data risco = RiscoAPI(data[CONF_USERNAME], data[CONF_PASSWORD], data[CONF_PIN]) try: await risco.login(async_get_clientsession(opp)) except CannotConnectError as error: raise ConfigEntryNotReady() from error except UnauthorizedError: _LOGGER.exception("Failed to login to Risco cloud") return False scan_interval = entry.options.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) coordinator = RiscoDataUpdateCoordinator(opp, risco, scan_interval) await coordinator.async_config_entry_first_refresh() events_coordinator = RiscoEventsDataUpdateCoordinator( opp, risco, entry.entry_id, 60 ) undo_listener = entry.add_update_listener(_update_listener) opp.data.setdefault(DOMAIN, {}) opp.data[DOMAIN][entry.entry_id] = { DATA_COORDINATOR: coordinator, UNDO_UPDATE_LISTENER: undo_listener, EVENTS_COORDINATOR: events_coordinator, } async def start_platforms(): await asyncio.gather( *[ opp.config_entries.async_forward_entry_setup(entry, platform) for platform in PLATFORMS ] ) await events_coordinator.async_refresh() opp.async_create_task(start_platforms()) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry): """Set up Somfy MyLink from a config entry.""" opp.data.setdefault(DOMAIN, {}) config = entry.data somfy_mylink = SomfyMyLinkSynergy(config[CONF_SYSTEM_ID], config[CONF_HOST], config[CONF_PORT]) try: mylink_status = await somfy_mylink.status_info() except asyncio.TimeoutError as ex: raise ConfigEntryNotReady( "Unable to connect to the Somfy MyLink device, please check your settings" ) from ex if not mylink_status or "error" in mylink_status: _LOGGER.error( "Somfy Mylink failed to setup because of an error: %s", mylink_status.get("error", {}).get("message", "Empty response from mylink device"), ) return False if "result" not in mylink_status: raise ConfigEntryNotReady( "The Somfy MyLink device returned an empty result") undo_listener = entry.add_update_listener(_async_update_listener) opp.data[DOMAIN][entry.entry_id] = { DATA_SOMFY_MYLINK: somfy_mylink, MYLINK_STATUS: mylink_status, UNDO_UPDATE_LISTENER: undo_listener, } opp.config_entries.async_setup_platforms(entry, PLATFORMS) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry): """Set up Logitech Harmony Hub from a config entry.""" # As there currently is no way to import options from yaml # when setting up a config entry, we fallback to adding # the options to the config entry and pull them out here if # they are missing from the options _async_import_options_from_data_if_missing(opp, entry) address = entry.data[CONF_HOST] name = entry.data[CONF_NAME] data = HarmonyData(opp, address, name, entry.unique_id) try: connected_ok = await data.connect() except (asyncio.TimeoutError, ValueError, AttributeError) as err: raise ConfigEntryNotReady from err if not connected_ok: raise ConfigEntryNotReady await _migrate_old_unique_ids(opp, entry.entry_id, data) cancel_listener = entry.add_update_listener(_update_listener) async def _async_on_stop(event): await data.shutdown() cancel_stop = opp.bus.async_listen(EVENT_OPENPEERPOWER_STOP, _async_on_stop) opp.data.setdefault(DOMAIN, {}) opp.data[DOMAIN][entry.entry_id] = { HARMONY_DATA: data, CANCEL_LISTENER: cancel_listener, CANCEL_STOP: cancel_stop, } opp.config_entries.async_setup_platforms(entry, PLATFORMS) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry) -> bool: """Set up RainMachine as config entry.""" session = aiohttp_client.async_get_clientsession(opp) client = Client(entry.data[CONF_PLACE_ID], entry.data[CONF_SERVICE_ID], session=session) async def async_get_pickup_events() -> list[PickupEvent]: """Get the next pickup.""" try: return await client.async_get_pickup_events( start_date=date.today(), end_date=date.today() + timedelta(weeks=4)) except RecollectError as err: raise UpdateFailed( f"Error while requesting data from ReCollect: {err}") from err coordinator = DataUpdateCoordinator( opp, LOGGER, name= f"Place {entry.data[CONF_PLACE_ID]}, Service {entry.data[CONF_SERVICE_ID]}", update_interval=DEFAULT_UPDATE_INTERVAL, update_method=async_get_pickup_events, ) await coordinator.async_config_entry_first_refresh() opp.data[DOMAIN][DATA_COORDINATOR][entry.entry_id] = coordinator opp.config_entries.async_setup_platforms(entry, PLATFORMS) opp.data[DOMAIN][DATA_LISTENER][ entry.entry_id] = entry.add_update_listener(async_reload_entry) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry) -> bool: """Set up RainMachine as config entry.""" opp.data.setdefault(DOMAIN, {DATA_CONTROLLER: {}, DATA_COORDINATOR: {}}) opp.data[DOMAIN][DATA_COORDINATOR][entry.entry_id] = {} websession = aiohttp_client.async_get_clientsession(opp) client = Client(session=websession) try: await client.load_local( entry.data[CONF_IP_ADDRESS], entry.data[CONF_PASSWORD], port=entry.data[CONF_PORT], ssl=entry.data.get(CONF_SSL, DEFAULT_SSL), ) except RainMachineError as err: raise ConfigEntryNotReady from err # regenmaschine can load multiple controllers at once, but we only grab the one # we loaded above: controller = opp.data[DOMAIN][DATA_CONTROLLER][ entry.entry_id] = get_client_controller(client) entry_updates = {} if not entry.unique_id or is_ip_address(entry.unique_id): # If the config entry doesn't already have a unique ID, set one: entry_updates["unique_id"] = controller.mac if CONF_ZONE_RUN_TIME in entry.data: # If a zone run time exists in the config entry's data, pop it and move it to # options: data = {**entry.data} entry_updates["data"] = data entry_updates["options"] = { **entry.options, CONF_ZONE_RUN_TIME: data.pop(CONF_ZONE_RUN_TIME), } if entry_updates: opp.config_entries.async_update_entry(entry, **entry_updates) async def async_update(api_category: str) -> dict: """Update the appropriate API data based on a category.""" try: if api_category == DATA_PROGRAMS: return await controller.programs.all(include_inactive=True) if api_category == DATA_PROVISION_SETTINGS: return await controller.provisioning.settings() if api_category == DATA_RESTRICTIONS_CURRENT: return await controller.restrictions.current() if api_category == DATA_RESTRICTIONS_UNIVERSAL: return await controller.restrictions.universal() return await controller.zones.all(details=True, include_inactive=True) except RainMachineError as err: raise UpdateFailed(err) from err controller_init_tasks = [] for api_category in [ DATA_PROGRAMS, DATA_PROVISION_SETTINGS, DATA_RESTRICTIONS_CURRENT, DATA_RESTRICTIONS_UNIVERSAL, DATA_ZONES, ]: coordinator = opp.data[DOMAIN][DATA_COORDINATOR][ entry.entry_id][api_category] = DataUpdateCoordinator( opp, LOGGER, name=f'{controller.name} ("{api_category}")', update_interval=DEFAULT_UPDATE_INTERVAL, update_method=partial(async_update, api_category), ) controller_init_tasks.append(coordinator.async_refresh()) await asyncio.gather(*controller_init_tasks) opp.config_entries.async_setup_platforms(entry, PLATFORMS) entry.async_on_unload(entry.add_update_listener(async_reload_entry)) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry): """Set up Netatmo from a config entry.""" implementation = ( await config_entry_oauth2_flow.async_get_config_entry_implementation( opp, entry)) # Set unique id if non was set (migration) if not entry.unique_id: opp.config_entries.async_update_entry(entry, unique_id=DOMAIN) session = config_entry_oauth2_flow.OAuth2Session(opp, entry, implementation) opp.data[DOMAIN][entry.entry_id] = { AUTH: api.AsyncConfigEntryNetatmoAuth( aiohttp_client.async_get_clientsession(opp), session) } data_handler = NetatmoDataHandler(opp, entry) await data_handler.async_setup() opp.data[DOMAIN][entry.entry_id][DATA_HANDLER] = data_handler opp.config_entries.async_setup_platforms(entry, PLATFORMS) async def unregister_webhook(_): if CONF_WEBHOOK_ID not in entry.data: return _LOGGER.debug("Unregister Netatmo webhook (%s)", entry.data[CONF_WEBHOOK_ID]) async_dispatcher_send( opp, f"signal-{DOMAIN}-webhook-None", { "type": "None", "data": { WEBHOOK_PUSH_TYPE: WEBHOOK_DEACTIVATION } }, ) webhook_unregister(opp, entry.data[CONF_WEBHOOK_ID]) await opp.data[DOMAIN][entry.entry_id][AUTH].async_dropwebhook() async def register_webhook(event): if CONF_WEBHOOK_ID not in entry.data: data = {**entry.data, CONF_WEBHOOK_ID: secrets.token_hex()} opp.config_entries.async_update_entry(entry, data=data) if opp.components.cloud.async_active_subscription(): if CONF_CLOUDHOOK_URL not in entry.data: webhook_url = await opp.components.cloud.async_create_cloudhook( entry.data[CONF_WEBHOOK_ID]) data = {**entry.data, CONF_CLOUDHOOK_URL: webhook_url} opp.config_entries.async_update_entry(entry, data=data) else: webhook_url = entry.data[CONF_CLOUDHOOK_URL] else: webhook_url = opp.components.webhook.async_generate_url( entry.data[CONF_WEBHOOK_ID]) if entry.data[ "auth_implementation"] == cloud.DOMAIN and not webhook_url.startswith( "https://"): _LOGGER.warning( "Webhook not registered - " "https and port 443 is required to register the webhook") return try: webhook_register( opp, DOMAIN, "Netatmo", entry.data[CONF_WEBHOOK_ID], async_handle_webhook, ) async def handle_event(event): """Handle webhook events.""" if event["data"][WEBHOOK_PUSH_TYPE] == WEBHOOK_ACTIVATION: if activation_listener is not None: activation_listener() if activation_timeout is not None: activation_timeout() activation_listener = async_dispatcher_connect( opp, f"signal-{DOMAIN}-webhook-None", handle_event, ) activation_timeout = async_call_later(opp, 30, unregister_webhook) await opp.data[DOMAIN][entry.entry_id ][AUTH].async_addwebhook(webhook_url) _LOGGER.info("Register Netatmo webhook: %s", webhook_url) except pyatmo.ApiError as err: _LOGGER.error("Error during webhook registration - %s", err) entry.async_on_unload( opp.bus.async_listen_once(EVENT_OPENPEERPOWER_STOP, unregister_webhook)) if opp.state == CoreState.running: await register_webhook(None) else: opp.bus.async_listen_once(EVENT_OPENPEERPOWER_START, register_webhook) opp.services.async_register(DOMAIN, "register_webhook", register_webhook) opp.services.async_register(DOMAIN, "unregister_webhook", unregister_webhook) entry.add_update_listener(async_config_entry_updated) return True
async def async_setup_entry( # noqa: C901 opp: OpenPeerPower, entry: ConfigEntry) -> bool: """Set up Synology DSM sensors.""" # Migrate old unique_id @callback def _async_migrator( entity_entry: entity_registry.RegistryEntry, ) -> dict[str, str] | None: """Migrate away from ID using label.""" # Reject if new unique_id if "SYNO." in entity_entry.unique_id: return None entries = { **STORAGE_DISK_BINARY_SENSORS, **STORAGE_DISK_SENSORS, **STORAGE_VOL_SENSORS, **UTILISATION_SENSORS, } infos = entity_entry.unique_id.split("_") serial = infos.pop(0) label = infos.pop(0) device_id = "_".join(infos) # Removed entity if ("Type" in entity_entry.unique_id or "Device" in entity_entry.unique_id or "Name" in entity_entry.unique_id): return None entity_type: str | None = None for entity_key, entity_attrs in entries.items(): if (device_id and entity_attrs[ENTITY_NAME] == "Status" and "Status" in entity_entry.unique_id and "(Smart)" not in entity_entry.unique_id): if "sd" in device_id and "disk" in entity_key: entity_type = entity_key continue if "volume" in device_id and "volume" in entity_key: entity_type = entity_key continue if entity_attrs[ENTITY_NAME] == label: entity_type = entity_key if entity_type is None: return None new_unique_id = "_".join([serial, entity_type]) if device_id: new_unique_id += f"_{device_id}" _LOGGER.info( "Migrating unique_id from [%s] to [%s]", entity_entry.unique_id, new_unique_id, ) return {"new_unique_id": new_unique_id} await entity_registry.async_migrate_entries(opp, entry.entry_id, _async_migrator) # migrate device indetifiers dev_reg = await get_dev_reg(opp) devices: list[ DeviceEntry] = device_registry.async_entries_for_config_entry( dev_reg, entry.entry_id) for device in devices: old_identifier = list(next(iter(device.identifiers))) if len(old_identifier) > 2: new_identifier = {(old_identifier.pop(0), "_".join([str(x) for x in old_identifier]))} _LOGGER.debug("migrate identifier '%s' to '%s'", device.identifiers, new_identifier) dev_reg.async_update_device(device.id, new_identifiers=new_identifier) # Migrate existing entry configuration if entry.data.get(CONF_VERIFY_SSL) is None: opp.config_entries.async_update_entry( entry, data={ **entry.data, CONF_VERIFY_SSL: DEFAULT_VERIFY_SSL }) # Continue setup api = SynoApi(opp, entry) try: await api.async_setup() except (SynologyDSMLoginFailedException, SynologyDSMRequestException) as err: _LOGGER.debug("Unable to connect to DSM '%s' during setup: %s", entry.unique_id, err) raise ConfigEntryNotReady from err opp.data.setdefault(DOMAIN, {}) opp.data[DOMAIN][entry.unique_id] = { UNDO_UPDATE_LISTENER: entry.add_update_listener(_async_update_listener), SYNO_API: api, SYSTEM_LOADED: True, } # Services await _async_setup_services(opp) # For SSDP compat if not entry.data.get(CONF_MAC): network = await opp.async_add_executor_job(getattr, api.dsm, "network") opp.config_entries.async_update_entry(entry, data={ **entry.data, CONF_MAC: network.macs }) async def async_coordinator_update_data_cameras( ) -> dict[str, dict[str, SynoCamera]] | None: """Fetch all camera data from api.""" if not opp.data[DOMAIN][entry.unique_id][SYSTEM_LOADED]: raise UpdateFailed("System not fully loaded") if SynoSurveillanceStation.CAMERA_API_KEY not in api.dsm.apis: return None surveillance_station = api.surveillance_station try: async with async_timeout.timeout(10): await opp.async_add_executor_job(surveillance_station.update) except SynologyDSMAPIErrorException as err: raise UpdateFailed(f"Error communicating with API: {err}") from err return { "cameras": { camera.id: camera for camera in surveillance_station.get_all_cameras() } } async def async_coordinator_update_data_central() -> None: """Fetch all device and sensor data from api.""" try: await api.async_update() except Exception as err: raise UpdateFailed(f"Error communicating with API: {err}") from err return None async def async_coordinator_update_data_switches( ) -> dict[str, dict[str, Any]] | None: """Fetch all switch data from api.""" if not opp.data[DOMAIN][entry.unique_id][SYSTEM_LOADED]: raise UpdateFailed("System not fully loaded") if SynoSurveillanceStation.HOME_MODE_API_KEY not in api.dsm.apis: return None surveillance_station = api.surveillance_station return { "switches": { "home_mode": await opp.async_add_executor_job( surveillance_station.get_home_mode_status) } } opp.data[DOMAIN][ entry.unique_id][COORDINATOR_CAMERAS] = DataUpdateCoordinator( opp, _LOGGER, name=f"{entry.unique_id}_cameras", update_method=async_coordinator_update_data_cameras, update_interval=timedelta(seconds=30), ) opp.data[DOMAIN][ entry.unique_id][COORDINATOR_CENTRAL] = DataUpdateCoordinator( opp, _LOGGER, name=f"{entry.unique_id}_central", update_method=async_coordinator_update_data_central, update_interval=timedelta(minutes=entry.options.get( CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)), ) opp.data[DOMAIN][ entry.unique_id][COORDINATOR_SWITCHES] = DataUpdateCoordinator( opp, _LOGGER, name=f"{entry.unique_id}_switches", update_method=async_coordinator_update_data_switches, update_interval=timedelta(seconds=30), ) opp.config_entries.async_setup_platforms(entry, PLATFORMS) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry): """Set up Tuya platform.""" tuya = TuyaApi() username = entry.data[CONF_USERNAME] password = entry.data[CONF_PASSWORD] country_code = entry.data[CONF_COUNTRYCODE] platform = entry.data[CONF_PLATFORM] try: await opp.async_add_executor_job(tuya.init, username, password, country_code, platform) except ( TuyaNetException, TuyaServerException, TuyaFrequentlyInvokeException, ) as exc: raise ConfigEntryNotReady() from exc except TuyaAPIRateLimitException as exc: raise ConfigEntryNotReady("Tuya login rate limited") from exc except TuyaAPIException as exc: _LOGGER.error( "Connection error during integration setup. Error: %s", exc, ) return False domain_data = opp.data[DOMAIN] = { TUYA_DATA: tuya, TUYA_DEVICES_CONF: entry.options.copy(), TUYA_TRACKER: None, ENTRY_IS_SETUP: set(), "entities": {}, "pending": {}, "listener": entry.add_update_listener(update_listener), } _update_discovery_interval( opp, entry.options.get(CONF_DISCOVERY_INTERVAL, DEFAULT_DISCOVERY_INTERVAL)) _update_query_interval( opp, entry.options.get(CONF_QUERY_INTERVAL, DEFAULT_QUERY_INTERVAL)) async def async_load_devices(device_list): """Load new devices by device_list.""" device_type_list = {} for device in device_list: dev_type = device.device_type() if (dev_type in TUYA_TYPE_TO_HA and device.object_id() not in domain_data["entities"]): ha_type = TUYA_TYPE_TO_HA[dev_type] if ha_type not in device_type_list: device_type_list[ha_type] = [] device_type_list[ha_type].append(device.object_id()) domain_data["entities"][device.object_id()] = None for ha_type, dev_ids in device_type_list.items(): config_entries_key = f"{ha_type}.tuya" if config_entries_key not in domain_data[ENTRY_IS_SETUP]: domain_data["pending"][ha_type] = dev_ids opp.async_create_task( opp.config_entries.async_forward_entry_setup( entry, ha_type)) domain_data[ENTRY_IS_SETUP].add(config_entries_key) else: async_dispatcher_send(opp, TUYA_DISCOVERY_NEW.format(ha_type), dev_ids) await async_load_devices(tuya.get_all_devices()) def _get_updated_devices(): try: tuya.poll_devices_update() except TuyaFrequentlyInvokeException as exc: _LOGGER.error(exc) return tuya.get_all_devices() async def async_poll_devices_update(event_time): """Check if accesstoken is expired and pull device list from server.""" _LOGGER.debug("Pull devices from Tuya") # Add new discover device. device_list = await opp.async_add_executor_job(_get_updated_devices) await async_load_devices(device_list) # Delete not exist device. newlist_ids = [] for device in device_list: newlist_ids.append(device.object_id()) for dev_id in list(domain_data["entities"]): if dev_id not in newlist_ids: async_dispatcher_send(opp, SIGNAL_DELETE_ENTITY, dev_id) domain_data["entities"].pop(dev_id) domain_data[TUYA_TRACKER] = async_track_time_interval( opp, async_poll_devices_update, timedelta(minutes=2)) @callback def _async_cancel_tuya_tracker(event): domain_data[TUYA_TRACKER]() domain_data[STOP_CANCEL] = opp.bus.async_listen_once( EVENT_OPENPEERPOWER_STOP, _async_cancel_tuya_tracker) opp.services.async_register(DOMAIN, SERVICE_PULL_DEVICES, async_poll_devices_update) async def async_force_update(call): """Force all devices to pull data.""" async_dispatcher_send(opp, SIGNAL_UPDATE_ENTITY) opp.services.async_register(DOMAIN, SERVICE_FORCE_UPDATE, async_force_update) return True