async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry): """Set up Freebox entry.""" router = FreeboxRouter(opp, entry) await router.setup() opp.data.setdefault(DOMAIN, {}) opp.data[DOMAIN][entry.unique_id] = router opp.config_entries.async_setup_platforms(entry, PLATFORMS) # Services async def async_reboot(call): """Handle reboot service call.""" await router.reboot() opp.services.async_register(DOMAIN, SERVICE_REBOOT, async_reboot) async def async_close_connection(event): """Close Freebox connection on OPP Stop.""" await router.close() entry.async_on_unload( opp.bus.async_listen_once(EVENT_OPENPEERPOWER_STOP, async_close_connection)) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry): """Set up a wemo config entry.""" config = opp.data[DOMAIN].pop("config") # Keep track of WeMo device subscriptions for push updates registry = opp.data[DOMAIN]["registry"] = pywemo.SubscriptionRegistry() await opp.async_add_executor_job(registry.start) static_conf = config.get(CONF_STATIC, []) wemo_dispatcher = WemoDispatcher(entry) wemo_discovery = WemoDiscovery(opp, wemo_dispatcher, static_conf) async def async_stop_wemo(event): """Shutdown Wemo subscriptions and subscription thread on exit.""" _LOGGER.debug("Shutting down WeMo event subscriptions") await opp.async_add_executor_job(registry.stop) wemo_discovery.async_stop_discovery() entry.async_on_unload( opp.bus.async_listen_once(EVENT_OPENPEERPOWER_STOP, async_stop_wemo)) # Need to do this at least once in case statics are defined and discovery is disabled await wemo_discovery.discover_statics() if config.get(CONF_DISCOVERY, DEFAULT_DISCOVERY): await wemo_discovery.async_discover_and_schedule() return True
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): """Set up Plum Lightpad from a config entry.""" _LOGGER.debug("Setting up config entry with ID = %s", entry.unique_id) username = entry.data.get(CONF_USERNAME) password = entry.data.get(CONF_PASSWORD) try: plum = await load_plum(username, password, opp) except ContentTypeError as ex: _LOGGER.error("Unable to authenticate to Plum cloud: %s", ex) return False except (ConnectTimeout, HTTPError) as ex: _LOGGER.error("Unable to connect to Plum cloud: %s", ex) raise ConfigEntryNotReady from ex opp.data.setdefault(DOMAIN, {}) opp.data[DOMAIN][entry.entry_id] = plum for platform in PLATFORMS: opp.async_create_task( opp.config_entries.async_forward_entry_setup(entry, platform)) def cleanup(event): """Clean up resources.""" plum.cleanup() entry.async_on_unload( opp.bus.async_listen_once(EVENT_OPENPEERPOWER_STOP, cleanup)) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry): """Set up ONVIF from a config entry.""" if DOMAIN not in opp.data: opp.data[DOMAIN] = {} if not entry.options: await async_populate_options(opp, entry) device = ONVIFDevice(opp, entry) if not await device.async_setup(): await device.device.close() return False if not device.available: raise ConfigEntryNotReady() if not entry.data.get(CONF_SNAPSHOT_AUTH): await async_populate_snapshot_auth(opp, device, entry) opp.data[DOMAIN][entry.unique_id] = device platforms = ["camera"] if device.capabilities.events: platforms += ["binary_sensor", "sensor"] opp.config_entries.async_setup_platforms(entry, platforms) entry.async_on_unload( opp.bus.async_listen_once(EVENT_OPENPEERPOWER_STOP, device.async_stop) ) 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) -> 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, async_add_entities) -> None: """Set up device tracker for FRITZ!Box component.""" _LOGGER.debug("Starting FRITZ!Box device tracker") router = opp.data[DOMAIN][entry.entry_id] data_fritz = opp.data[DATA_FRITZ] @callback def update_router(): """Update the values of the router.""" _async_add_entities(router, async_add_entities, data_fritz) entry.async_on_unload( async_dispatcher_connect(opp, router.signal_device_new, update_router)) update_router()
async def async_setup_entry( opp: OpenPeerPower, config_entry: config_entries.ConfigEntry ) -> bool: """Set up a Firmata board for a config entry.""" if DOMAIN not in opp.data: opp.data[DOMAIN] = {} _LOGGER.debug( "Setting up Firmata id %s, name %s, config %s", config_entry.entry_id, config_entry.data[CONF_NAME], config_entry.data, ) board = FirmataBoard(config_entry.data) if not await board.async_setup(): return False opp.data[DOMAIN][config_entry.entry_id] = board async def handle_shutdown(event) -> None: """Handle shutdown of board when Open Peer Power shuts down.""" # Ensure board was not already removed previously before shutdown if config_entry.entry_id in opp.data[DOMAIN]: await board.async_reset() config_entry.async_on_unload( opp.bus.async_listen_once(EVENT_OPENPEERPOWER_STOP, handle_shutdown) ) device_registry = await dr.async_get_registry(opp) device_registry.async_get_or_create( config_entry_id=config_entry.entry_id, connections={}, identifiers={(DOMAIN, board.name)}, manufacturer=FIRMATA_MANUFACTURER, name=board.name, sw_version=board.firmware_version, ) for (conf, platform) in CONF_PLATFORM_MAP.items(): if conf in config_entry.data: opp.async_create_task( opp.config_entries.async_forward_entry_setup(config_entry, platform) ) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry) -> bool: """Set up Verisure from a config entry.""" coordinator = VerisureDataUpdateCoordinator(opp, entry=entry) if not await coordinator.async_login(): raise ConfigEntryAuthFailed entry.async_on_unload( opp.bus.async_listen_once(EVENT_OPENPEERPOWER_STOP, coordinator.async_logout)) await coordinator.async_config_entry_first_refresh() opp.data.setdefault(DOMAIN, {}) opp.data[DOMAIN][entry.entry_id] = coordinator # Set up all platforms for this device/entry. 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_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 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, config_entry: ConfigEntry) -> bool: """Do setup of vera.""" # Use options entered during initial config flow or provided from configuration.yml if config_entry.data.get(CONF_LIGHTS) or config_entry.data.get(CONF_EXCLUDE): opp.config_entries.async_update_entry( entry=config_entry, data=config_entry.data, options=new_options( config_entry.data.get(CONF_LIGHTS, []), config_entry.data.get(CONF_EXCLUDE, []), ), ) saved_light_ids = config_entry.options.get(CONF_LIGHTS, []) saved_exclude_ids = config_entry.options.get(CONF_EXCLUDE, []) base_url = config_entry.data[CONF_CONTROLLER] light_ids = fix_device_id_list(saved_light_ids) exclude_ids = fix_device_id_list(saved_exclude_ids) # If the ids were corrected. Update the config entry. if light_ids != saved_light_ids or exclude_ids != saved_exclude_ids: opp.config_entries.async_update_entry( entry=config_entry, options=new_options(light_ids, exclude_ids) ) # Initialize the Vera controller. subscription_registry = SubscriptionRegistry(opp) controller = veraApi.VeraController(base_url, subscription_registry) try: all_devices = await opp.async_add_executor_job(controller.get_devices) all_scenes = await opp.async_add_executor_job(controller.get_scenes) except RequestException as exception: # There was a network related error connecting to the Vera controller. _LOGGER.exception("Error communicating with Vera API") raise ConfigEntryNotReady from exception # Exclude devices unwanted by user. devices = [device for device in all_devices if device.device_id not in exclude_ids] vera_devices = defaultdict(list) for device in devices: device_type = map_vera_device(device, light_ids) if device_type is not None: vera_devices[device_type].append(device) vera_scenes = [] for scene in all_scenes: vera_scenes.append(scene) controller_data = ControllerData( controller=controller, devices=vera_devices, scenes=vera_scenes, config_entry=config_entry, ) set_controller_data(opp, config_entry, controller_data) # Forward the config data to the necessary platforms. for platform in get_configured_platforms(controller_data): opp.async_create_task( opp.config_entries.async_forward_entry_setup(config_entry, platform) ) def stop_subscription(event): """Stop SubscriptionRegistry updates.""" controller.stop() await opp.async_add_executor_job(controller.start) config_entry.async_on_unload( opp.bus.async_listen_once(EVENT_OPENPEERPOWER_STOP, stop_subscription) ) config_entry.async_on_unload( config_entry.add_update_listener(_async_update_listener) ) return True
async def async_setup_entry(opp: OpenPeerPower, config_entry: ConfigEntry) -> bool: """Set up the UpCloud config entry.""" manager = upcloud_api.CloudManager( config_entry.data[CONF_USERNAME], config_entry.data[CONF_PASSWORD] ) try: await opp.async_add_executor_job(manager.authenticate) except upcloud_api.UpCloudAPIError: _LOGGER.error("Authentication failed", exc_info=True) return False except requests.exceptions.RequestException as err: _LOGGER.error("Failed to connect", exc_info=True) raise ConfigEntryNotReady from err upcloud_data = opp.data.setdefault(DATA_UPCLOUD, UpCloudHassData()) # Handle pre config entry (0.117) scan interval migration to options migrated_scan_interval = upcloud_data.scan_interval_migrations.pop( config_entry.data[CONF_USERNAME], None ) if migrated_scan_interval and ( not config_entry.options.get(CONF_SCAN_INTERVAL) or config_entry.options[CONF_SCAN_INTERVAL] == DEFAULT_SCAN_INTERVAL.total_seconds() ): update_interval = migrated_scan_interval opp.config_entries.async_update_entry( config_entry, options={CONF_SCAN_INTERVAL: update_interval.total_seconds()}, ) elif config_entry.options.get(CONF_SCAN_INTERVAL): update_interval = timedelta(seconds=config_entry.options[CONF_SCAN_INTERVAL]) else: update_interval = DEFAULT_SCAN_INTERVAL coordinator = UpCloudDataUpdateCoordinator( opp, update_interval=update_interval, cloud_manager=manager, username=config_entry.data[CONF_USERNAME], ) # Call the UpCloud API to refresh data await coordinator.async_config_entry_first_refresh() # Listen to config entry updates config_entry.async_on_unload( config_entry.add_update_listener(_async_signal_options_update) ) config_entry.async_on_unload( async_dispatcher_connect( opp, _config_entry_update_signal_name(config_entry), coordinator.async_update_config, ) ) upcloud_data.coordinators[config_entry.data[CONF_USERNAME]] = coordinator # Forward entry setup opp.config_entries.async_setup_platforms(config_entry, CONFIG_ENTRY_DOMAINS) return True
async def async_setup_entry(opp: OpenPeerPower, entry: config_entries.ConfigEntry) -> bool: """Set up the ISY 994 integration.""" # 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) opp.data[DOMAIN][entry.entry_id] = {} opp_isy_data = opp.data[DOMAIN][entry.entry_id] opp_isy_data[ISY994_NODES] = {} for platform in PLATFORMS: opp_isy_data[ISY994_NODES][platform] = [] opp_isy_data[ISY994_PROGRAMS] = {} for platform in PROGRAM_PLATFORMS: opp_isy_data[ISY994_PROGRAMS][platform] = [] opp_isy_data[ISY994_VARIABLES] = [] isy_config = entry.data isy_options = entry.options # Required user = isy_config[CONF_USERNAME] password = isy_config[CONF_PASSWORD] host = urlparse(isy_config[CONF_HOST]) # Optional tls_version = isy_config.get(CONF_TLS_VER) ignore_identifier = isy_options.get(CONF_IGNORE_STRING, DEFAULT_IGNORE_STRING) sensor_identifier = isy_options.get(CONF_SENSOR_STRING, DEFAULT_SENSOR_STRING) variable_identifier = isy_options.get(CONF_VAR_SENSOR_STRING, DEFAULT_VAR_SENSOR_STRING) if host.scheme == "http": https = False port = host.port or 80 session = aiohttp_client.async_create_clientsession( opp, verify_ssl=None, cookie_jar=CookieJar(unsafe=True)) elif host.scheme == "https": https = True port = host.port or 443 session = aiohttp_client.async_get_clientsession(opp) else: _LOGGER.error("The isy994 host value in configuration is invalid") return False # Connect to ISY controller. isy = ISY( host.hostname, port, username=user, password=password, use_https=https, tls_ver=tls_version, webroot=host.path, websession=session, use_websocket=True, ) try: async with async_timeout.timeout(60): await isy.initialize() except asyncio.TimeoutError as err: raise ConfigEntryNotReady( f"Timed out initializing the ISY; device may be busy, trying again later: {err}" ) from err except ISYInvalidAuthError as err: _LOGGER.error( "Invalid credentials for the ISY, please adjust settings and try again: %s", err, ) return False except ISYConnectionError as err: raise ConfigEntryNotReady( f"Failed to connect to the ISY, please adjust settings and try again: {err}" ) from err except ISYResponseParseError as err: raise ConfigEntryNotReady( f"Invalid XML response from ISY; Ensure the ISY is running the latest firmware: {err}" ) from err _categorize_nodes(opp_isy_data, isy.nodes, ignore_identifier, sensor_identifier) _categorize_programs(opp_isy_data, isy.programs) _categorize_variables(opp_isy_data, isy.variables, variable_identifier) # Dump ISY Clock Information. Future: Add ISY as sensor to Opp with attrs _LOGGER.info(repr(isy.clock)) opp_isy_data[ISY994_ISY] = isy await _async_get_or_create_isy_device_in_registry(opp, entry, isy) # Load platforms for the devices in the ISY controller that we support. opp.config_entries.async_setup_platforms(entry, PLATFORMS) def _start_auto_update() -> None: """Start isy auto update.""" _LOGGER.debug("ISY Starting Event Stream and automatic updates") isy.websocket.start() def _stop_auto_update(event) -> None: """Stop the isy auto update on Open Peer Power Shutdown.""" _LOGGER.debug("ISY Stopping Event Stream and automatic updates") isy.websocket.stop() await opp.async_add_executor_job(_start_auto_update) undo_listener = entry.add_update_listener(_async_update_listener) opp_isy_data[UNDO_UPDATE_LISTENER] = undo_listener entry.async_on_unload( opp.bus.async_listen_once(EVENT_OPENPEERPOWER_STOP, _stop_auto_update)) # Register Integration-wide Services: async_setup_services(opp) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry) -> bool: """Set up buienradar from a config entry.""" opp.config_entries.async_setup_platforms(entry, PLATFORMS) entry.async_on_unload(entry.add_update_listener(async_update_options)) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry): """Set up Sense from a config entry.""" entry_data = entry.data email = entry_data[CONF_EMAIL] password = entry_data[CONF_PASSWORD] timeout = entry_data[CONF_TIMEOUT] client_session = async_get_clientsession(opp) gateway = ASyncSenseable( api_timeout=timeout, wss_timeout=timeout, client_session=client_session ) gateway.rate_limit = ACTIVE_UPDATE_RATE try: await gateway.authenticate(email, password) except SenseAuthenticationException: _LOGGER.error("Could not authenticate with sense server") return False except SENSE_TIMEOUT_EXCEPTIONS as err: raise ConfigEntryNotReady from err sense_devices_data = SenseDevicesData() try: sense_discovered_devices = await gateway.get_discovered_device_data() await gateway.update_realtime() except SENSE_TIMEOUT_EXCEPTIONS as err: raise ConfigEntryNotReady from err trends_coordinator = DataUpdateCoordinator( opp, _LOGGER, name=f"Sense Trends {email}", update_method=gateway.update_trend_data, update_interval=timedelta(seconds=300), ) # This can take longer than 60s and we already know # sense is online since get_discovered_device_data was # successful so we do it later. asyncio.create_task(trends_coordinator.async_request_refresh()) opp.data.setdefault(DOMAIN, {})[entry.entry_id] = { SENSE_DATA: gateway, SENSE_DEVICES_DATA: sense_devices_data, SENSE_TRENDS_COORDINATOR: trends_coordinator, SENSE_DISCOVERED_DEVICES_DATA: sense_discovered_devices, } opp.config_entries.async_setup_platforms(entry, PLATFORMS) async def async_sense_update(_): """Retrieve latest state.""" try: await gateway.update_realtime() except SenseAPITimeoutException: _LOGGER.error("Timeout retrieving data") data = gateway.get_realtime() if "devices" in data: sense_devices_data.set_devices_data(data["devices"]) async_dispatcher_send(opp, f"{SENSE_DEVICE_UPDATE}-{gateway.sense_monitor_id}") remove_update_callback = async_track_time_interval( opp, async_sense_update, timedelta(seconds=ACTIVE_UPDATE_RATE) ) @callback def _remove_update_callback_at_stop(event): remove_update_callback() entry.async_on_unload(remove_update_callback) entry.async_on_unload( opp.bus.async_listen_once( EVENT_OPENPEERPOWER_STOP, _remove_update_callback_at_stop ) ) return True
async def async_setup_entry( opp: OpenPeerPower, config_entry: ConfigEntry, async_add_entities: AddEntitiesCallback, ) -> None: """Set up Sonos from a config entry.""" platform = entity_platform.async_get_current_platform() @callback def async_create_entities(speaker: SonosSpeaker) -> None: """Handle device discovery and create entities.""" async_add_entities([SonosMediaPlayerEntity(speaker)]) @service.verify_domain_control(opp, SONOS_DOMAIN) async def async_service_handle(service_call: ServiceCall) -> None: """Handle dispatched services.""" assert platform is not None entities = await platform.async_extract_from_service(service_call) if not entities: return speakers = [] for entity in entities: assert isinstance(entity, SonosMediaPlayerEntity) speakers.append(entity.speaker) if service_call.service == SERVICE_JOIN: master = platform.entities.get(service_call.data[ATTR_MASTER]) if master: await SonosSpeaker.join_multi(opp, master.speaker, speakers ) # type: ignore[arg-type] else: _LOGGER.error( "Invalid master specified for join service: %s", service_call.data[ATTR_MASTER], ) elif service_call.service == SERVICE_UNJOIN: await SonosSpeaker.unjoin_multi(opp, speakers) # type: ignore[arg-type] elif service_call.service == SERVICE_SNAPSHOT: await SonosSpeaker.snapshot_multi( opp, speakers, service_call.data[ATTR_WITH_GROUP] # type: ignore[arg-type] ) elif service_call.service == SERVICE_RESTORE: await SonosSpeaker.restore_multi( opp, speakers, service_call.data[ATTR_WITH_GROUP] # type: ignore[arg-type] ) config_entry.async_on_unload( async_dispatcher_connect(opp, SONOS_CREATE_MEDIA_PLAYER, async_create_entities)) opp.services.async_register( SONOS_DOMAIN, SERVICE_JOIN, async_service_handle, cv.make_entity_service_schema( {vol.Required(ATTR_MASTER): cv.entity_id}), ) opp.services.async_register( SONOS_DOMAIN, SERVICE_UNJOIN, async_service_handle, cv.make_entity_service_schema({}), ) join_unjoin_schema = cv.make_entity_service_schema( {vol.Optional(ATTR_WITH_GROUP, default=True): cv.boolean}) opp.services.async_register(SONOS_DOMAIN, SERVICE_SNAPSHOT, async_service_handle, join_unjoin_schema) opp.services.async_register(SONOS_DOMAIN, SERVICE_RESTORE, async_service_handle, join_unjoin_schema) platform.async_register_entity_service( # type: ignore SERVICE_SET_TIMER, { vol.Required(ATTR_SLEEP_TIME): vol.All( vol.Coerce(int), vol.Range(min=0, max=86399) ) }, "set_sleep_timer", ) platform.async_register_entity_service(SERVICE_CLEAR_TIMER, {}, "clear_sleep_timer") # type: ignore platform.async_register_entity_service( # type: ignore SERVICE_UPDATE_ALARM, { vol.Required(ATTR_ALARM_ID): cv.positive_int, vol.Optional(ATTR_TIME): cv.time, vol.Optional(ATTR_VOLUME): cv.small_float, vol.Optional(ATTR_ENABLED): cv.boolean, vol.Optional(ATTR_INCLUDE_LINKED_ZONES): cv.boolean, }, "set_alarm", ) platform.async_register_entity_service( # type: ignore SERVICE_SET_OPTION, { vol.Optional(ATTR_BUTTONS_ENABLED): cv.boolean, vol.Optional(ATTR_NIGHT_SOUND): cv.boolean, vol.Optional(ATTR_SPEECH_ENHANCE): cv.boolean, vol.Optional(ATTR_STATUS_LIGHT): cv.boolean, }, "set_option", ) platform.async_register_entity_service( # type: ignore SERVICE_PLAY_QUEUE, {vol.Optional(ATTR_QUEUE_POSITION): cv.positive_int}, "play_queue", ) platform.async_register_entity_service( # type: ignore SERVICE_REMOVE_FROM_QUEUE, {vol.Optional(ATTR_QUEUE_POSITION): cv.positive_int}, "remove_from_queue", )
async def async_setup_entry(opp: OpenPeerPower, config_entry: ConfigEntry) -> bool: """Set up Huawei LTE component from config entry.""" url = config_entry.data[CONF_URL] # Override settings from YAML config, but only if they're changed in it # Old values are stored as *_from_yaml in the config entry yaml_config = opp.data[DOMAIN].config.get(url) if yaml_config: # Config values new_data = {} for key in CONF_USERNAME, CONF_PASSWORD: if key in yaml_config: value = yaml_config[key] if value != config_entry.data.get(f"{key}_from_yaml"): new_data[f"{key}_from_yaml"] = value new_data[key] = value # Options new_options = {} yaml_recipient = yaml_config.get(NOTIFY_DOMAIN, {}).get(CONF_RECIPIENT) if yaml_recipient is not None and yaml_recipient != config_entry.options.get( f"{CONF_RECIPIENT}_from_yaml" ): new_options[f"{CONF_RECIPIENT}_from_yaml"] = yaml_recipient new_options[CONF_RECIPIENT] = yaml_recipient yaml_notify_name = yaml_config.get(NOTIFY_DOMAIN, {}).get(CONF_NAME) if ( yaml_notify_name is not None and yaml_notify_name != config_entry.options.get(f"{CONF_NAME}_from_yaml") ): new_options[f"{CONF_NAME}_from_yaml"] = yaml_notify_name new_options[CONF_NAME] = yaml_notify_name # Update entry if overrides were found if new_data or new_options: opp.config_entries.async_update_entry( config_entry, data={**config_entry.data, **new_data}, options={**config_entry.options, **new_options}, ) # Get MAC address for use in unique ids. Being able to use something # from the API would be nice, but all of that seems to be available only # through authenticated calls (e.g. device_information.SerialNumber), and # we want this available and the same when unauthenticated too. host = urlparse(url).hostname try: if ipaddress.ip_address(host).version == 6: mode = "ip6" else: mode = "ip" except ValueError: mode = "hostname" mac = await opp.async_add_executor_job(partial(get_mac_address, **{mode: host})) def get_connection() -> Connection: """ Set up a connection. Authorized one if username/pass specified (even if empty), unauthorized one otherwise. """ username = config_entry.data.get(CONF_USERNAME) password = config_entry.data.get(CONF_PASSWORD) if username or password: connection: Connection = AuthorizedConnection( url, username=username, password=password, timeout=CONNECTION_TIMEOUT ) else: connection = Connection(url, timeout=CONNECTION_TIMEOUT) return connection def signal_update() -> None: """Signal updates to data.""" dispatcher_send(opp, UPDATE_SIGNAL, url) try: connection = await opp.async_add_executor_job(get_connection) except Timeout as ex: raise ConfigEntryNotReady from ex # Set up router and store reference to it router = Router(config_entry, connection, url, mac, signal_update) opp.data[DOMAIN].routers[url] = router # Do initial data update await opp.async_add_executor_job(router.update) # Clear all subscriptions, enabled entities will push back theirs router.subscriptions.clear() # Set up device registry if router.device_identifiers or router.device_connections: device_data = {} sw_version = None if router.data.get(KEY_DEVICE_INFORMATION): device_info = router.data[KEY_DEVICE_INFORMATION] sw_version = device_info.get("SoftwareVersion") if device_info.get("DeviceName"): device_data["model"] = device_info["DeviceName"] if not sw_version and router.data.get(KEY_DEVICE_BASIC_INFORMATION): sw_version = router.data[KEY_DEVICE_BASIC_INFORMATION].get( "SoftwareVersion" ) if sw_version: device_data["sw_version"] = sw_version device_registry = await dr.async_get_registry(opp) device_registry.async_get_or_create( config_entry_id=config_entry.entry_id, connections=router.device_connections, identifiers=router.device_identifiers, name=router.device_name, manufacturer="Huawei", **device_data, ) # Forward config entry setup to platforms opp.config_entries.async_setup_platforms(config_entry, CONFIG_ENTRY_PLATFORMS) # Notify doesn't support config entry setup yet, load with discovery for now await discovery.async_load_platform( opp, NOTIFY_DOMAIN, DOMAIN, { CONF_URL: url, CONF_NAME: config_entry.options.get(CONF_NAME, DEFAULT_NOTIFY_SERVICE_NAME), CONF_RECIPIENT: config_entry.options.get(CONF_RECIPIENT), }, opp.data[DOMAIN].opp_config, ) def _update_router(*_: Any) -> None: """ Update router data. Separate passthrough function because lambdas don't work with track_time_interval. """ router.update() # Set up periodic update config_entry.async_on_unload( async_track_time_interval(opp, _update_router, SCAN_INTERVAL) ) # Clean up at end config_entry.async_on_unload( opp.bus.async_listen_once(EVENT_OPENPEERPOWER_STOP, router.cleanup) ) return True
async def async_setup_entry(opp: OpenPeerPower, entry: ConfigEntry) -> bool: """Set up the AVM FRITZ!SmartHome platforms.""" fritz = Fritzhome( host=entry.data[CONF_HOST], user=entry.data[CONF_USERNAME], password=entry.data[CONF_PASSWORD], ) try: await opp.async_add_executor_job(fritz.login) except LoginError as err: raise ConfigEntryAuthFailed from err opp.data.setdefault(DOMAIN, {}) opp.data[DOMAIN][entry.entry_id] = { CONF_CONNECTIONS: fritz, } def _update_fritz_devices() -> dict[str, FritzhomeDevice]: """Update all fritzbox device data.""" try: devices = fritz.get_devices() except requests.exceptions.HTTPError: # If the device rebooted, login again try: fritz.login() except requests.exceptions.HTTPError as ex: raise ConfigEntryAuthFailed from ex devices = fritz.get_devices() data = {} for device in devices: device.update() data[device.ain] = device return data async def async_update_coordinator() -> dict[str, FritzhomeDevice]: """Fetch all device data.""" return await opp.async_add_executor_job(_update_fritz_devices) opp.data[DOMAIN][entry.entry_id][ CONF_COORDINATOR] = coordinator = DataUpdateCoordinator( opp, LOGGER, name=f"{entry.entry_id}", update_method=async_update_coordinator, update_interval=timedelta(seconds=30), ) await coordinator.async_config_entry_first_refresh() opp.config_entries.async_setup_platforms(entry, PLATFORMS) def logout_fritzbox(event: Event) -> None: """Close connections to this fritzbox.""" fritz.logout() entry.async_on_unload( opp.bus.async_listen_once(EVENT_OPENPEERPOWER_STOP, logout_fritzbox)) return True