async def _async_setup_platform( hass: HomeAssistantType, config: ConfigType, async_add_entities ): """Set up the cast platform.""" # Import CEC IGNORE attributes pychromecast.IGNORE_CEC += config.get(CONF_IGNORE_CEC, []) hass.data.setdefault(ADDED_CAST_DEVICES_KEY, set()) hass.data.setdefault(KNOWN_CHROMECAST_INFO_KEY, {}) info = None if CONF_UUID in config: info = ChromecastInfo(uuid=config[CONF_UUID], services=None) @callback def async_cast_discovered(discover: ChromecastInfo) -> None: """Handle discovery of a new chromecast.""" # If info is set, we're handling a specific cast device identified by UUID if info is not None and (info.uuid is not None and info.uuid != discover.uuid): # UUID not matching, this is not it. return cast_device = _async_create_cast_device(hass, discover) if cast_device is not None: async_add_entities([cast_device]) async_dispatcher_connect(hass, SIGNAL_CAST_DISCOVERED, async_cast_discovered) # Re-play the callback for all past chromecasts, store the objects in # a list to avoid concurrent modification resulting in exception. for chromecast in hass.data[KNOWN_CHROMECAST_INFO_KEY].values(): async_cast_discovered(chromecast) ChromeCastZeroconf.set_zeroconf(await zeroconf.async_get_instance(hass)) hass.async_add_executor_job(setup_internal_discovery, hass)
async def _async_setup_platform( hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info ): """Set up the cast platform.""" # Import CEC IGNORE attributes pychromecast.IGNORE_CEC += config.get(CONF_IGNORE_CEC, []) hass.data.setdefault(ADDED_CAST_DEVICES_KEY, set()) hass.data.setdefault(KNOWN_CHROMECAST_INFO_KEY, set()) info = None if discovery_info is not None: info = ChromecastInfo(host=discovery_info["host"], port=discovery_info["port"]) elif CONF_HOST in config: info = ChromecastInfo(host=config[CONF_HOST], port=DEFAULT_PORT) @callback def async_cast_discovered(discover: ChromecastInfo) -> None: """Handle discovery of a new chromecast.""" if info is not None and info.host_port != discover.host_port: # Waiting for a specific cast device, this is not it. return cast_device = _async_create_cast_device(hass, discover) if cast_device is not None: async_add_entities([cast_device]) async_dispatcher_connect(hass, SIGNAL_CAST_DISCOVERED, async_cast_discovered) # Re-play the callback for all past chromecasts, store the objects in # a list to avoid concurrent modification resulting in exception. for chromecast in list(hass.data[KNOWN_CHROMECAST_INFO_KEY]): async_cast_discovered(chromecast) hass.async_add_executor_job(setup_internal_discovery, hass)
async def _async_setup_platform(hass: HomeAssistantType, config: ConfigType, async_add_entities, discovery_info): """Set up the cast platform.""" # Import CEC IGNORE attributes pychromecast.IGNORE_CEC += config.get(CONF_IGNORE_CEC, []) hass.data.setdefault(ADDED_CAST_DEVICES_KEY, set()) hass.data.setdefault(KNOWN_CHROMECAST_INFO_KEY, set()) info = None if discovery_info is not None: info = ChromecastInfo(host=discovery_info["host"], port=discovery_info["port"]) elif CONF_HOST in config: info = ChromecastInfo(host=config[CONF_HOST], port=DEFAULT_PORT) @callback def async_cast_discovered(discover: ChromecastInfo) -> None: """Handle discovery of a new chromecast.""" if info is not None and info.host_port != discover.host_port: # Not our requested cast device. return cast_device = _async_create_cast_device(hass, discover) if cast_device is not None: async_add_entities([cast_device]) async_dispatcher_connect(hass, SIGNAL_CAST_DISCOVERED, async_cast_discovered) # Re-play the callback for all past chromecasts, store the objects in # a list to avoid concurrent modification resulting in exception. for chromecast in list(hass.data[KNOWN_CHROMECAST_INFO_KEY]): async_cast_discovered(chromecast) if info is None or info.is_audio_group: # If we were a) explicitly told to enable discovery or # b) have an audio group cast device, we need internal discovery. hass.async_add_executor_job(setup_internal_discovery, hass) else: info = await hass.async_add_executor_job( info.fill_out_missing_chromecast_info) if info.friendly_name is None: _LOGGER.debug( "Cannot retrieve detail information for chromecast" " %s, the device may not be online", info, ) hass.async_add_executor_job(discover_chromecast, hass, info)
async def async_unload_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool: """Unload a config entry.""" unload = all(await asyncio.gather(*[ hass.config_entries.async_forward_entry_unload(entry, platform) for platform in PLATFORMS ])) await asyncio.gather(*[ hass.async_add_executor_job(gateway.websocket_disconnect) for gateway in hass.data[DOMAIN][entry.entry_id]["gateways"] ]) hass.data[DOMAIN][entry.entry_id]["listener"]() hass.data[DOMAIN].pop(entry.entry_id) return unload
async def async_setup_entry( hass: HomeAssistantType, entry: ConfigEntry, async_add_entities ) -> None: _LOGGER.debug("Setting up switches") fritzbox_tools = hass.data[DOMAIN][DATA_FRITZ_TOOLS_INSTANCE][entry.entry_id] def _create_deflection_switches(): deflections_response = fritzbox_tools.connection.call_action("X_AVM-DE_OnTel:1", "GetNumberOfDeflections") _LOGGER.debug(deflections_response) _LOGGER.debug(fritzbox_tools.connection.services) if "X_AVM-DE_OnTel1" in fritzbox_tools.connection.services and deflections_response[ "NewNumberOfDeflections"] != 0: try: _LOGGER.debug("Setting up deflection switches") deflections = xmltodict.parse( fritzbox_tools.connection.call_action("X_AVM-DE_OnTel:1", "GetDeflections")["NewDeflectionList"] )["List"]["Item"] if not isinstance(deflections, list): deflections = [deflections] for dict_of_deflection in deflections: hass.add_job( async_add_entities, [ FritzBoxDeflectionSwitch( fritzbox_tools, dict_of_deflection ) ], ) except Exception: _LOGGER.error( f"Call Deflection switches could not be enabled.", exc_info=True, ) def _create_port_switches(): if fritzbox_tools.ha_ip != "127.0.0.1": try: _LOGGER.debug("Setting up port forward switches") connection_type = fritzbox_tools.connection.call_action( "Layer3Forwarding:1", "GetDefaultConnectionService" )["NewDefaultConnectionService"] connection_type = connection_type[2:].replace(".", ":") # Query port forwardings and setup a switch for each forward for the current device port_forwards_count: int = fritzbox_tools.connection.call_action( connection_type, "GetPortMappingNumberOfEntries" )["NewPortMappingNumberOfEntries"] _LOGGER.debug('Number of port forwards response') _LOGGER.debug(port_forwards_count) for i in range(port_forwards_count): portmap = fritzbox_tools.connection.call_action( connection_type, "GetGenericPortMappingEntry", NewPortMappingIndex=i, ) _LOGGER.debug("Specific port forward response") _LOGGER.debug(portmap) _LOGGER.debug(f"Port forwards of the following device are shown: {fritzbox_tools.ha_ip}") # We can only handle port forwards of the given device if portmap["NewInternalClient"] == fritzbox_tools.ha_ip: hass.add_job( async_add_entities, [ FritzBoxPortSwitch( fritzbox_tools, portmap, i, connection_type ) ], ) except Exception: _LOGGER.error( f"Port switches could not be enabled. Check if your fritzbox is able to do port forwardings!", exc_info=True, ) def _create_profile_switches(): if len(fritzbox_tools.profile_switch) > 0: _LOGGER.debug("Setting up profile switches") for profile in fritzbox_tools.profile_switch.keys(): hass.add_job( async_add_entities, [FritzBoxProfileSwitch(fritzbox_tools, profile)], ) def _create_wifi_switches(): if "WLANConfiguration3" not in fritzbox_tools.connection.services: networks = {"1": "Wifi", "2": "Guest Wifi"} else: networks = {"1": "Wifi", "2": "Wifi (5GHz)", "3": "Guest Wifi"} for net in networks: hass.add_job( async_add_entities, [FritzBoxWifiSwitch(fritzbox_tools, net, networks[net])], ) if fritzbox_tools.use_wifi: hass.async_add_executor_job(_create_wifi_switches) if fritzbox_tools.use_port: hass.async_add_executor_job(_create_port_switches) if fritzbox_tools.use_deflections: hass.async_add_executor_job(_create_deflection_switches) if fritzbox_tools.use_profiles: hass.async_add_executor_job(_create_profile_switches) _LOGGER.debug(f"use_wifi: {fritzbox_tools.use_wifi}") _LOGGER.debug(f"use_profiles: {fritzbox_tools.use_profiles}") _LOGGER.debug(f"use_deflections: {fritzbox_tools.use_deflections}") _LOGGER.debug(f"use_port: {fritzbox_tools.use_port}") return True
async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry, async_add_entities) -> None: _LOGGER.debug("Setting up switches") fritzbox_tools = hass.data[DOMAIN][DATA_FRITZ_TOOLS_INSTANCE] def _create_deflection_switches(): number_of_deflections = fritzbox_tools.connection.call_action( "X_AVM-DE_OnTel:1", "GetNumberOfDeflections")["NewNumberOfDeflections"] if "X_AVM-DE_OnTel:1" in fritzbox_tools.connection.services and number_of_deflections != 0: try: _LOGGER.debug("Setting up deflection switches") deflections = xmltodict.parse( fritzbox_tools.connection.call_action( "X_AVM-DE_OnTel:1", "GetDeflections") ["NewDeflectionList"])["List"].items() for item, dict_of_deflection in deflections: hass.add_job( async_add_entities, [ FritzBoxDeflectionSwitch(fritzbox_tools, item, dict_of_deflection) ], ) except Exception: _LOGGER.error( f"Call Deflection switches could not be enabled.", exc_info=True, ) def _create_port_switches(): if fritzbox_tools.ha_ip != "127.0.0.1": try: _LOGGER.debug("Setting up port forward switches") connection_type = fritzbox_tools.connection.call_action( "Layer3Forwarding:1", "GetDefaultConnectionService" )["NewDefaultConnectionService"] connection_type = connection_type[2:].replace(".", ":") # Query port forwardings and setup a switch for each forward for the current deivce port_forwards_count: int = fritzbox_tools.connection.call_action( connection_type, "GetPortMappingNumberOfEntries" )["NewPortMappingNumberOfEntries"] for i in range(port_forwards_count): portmap = fritzbox_tools.connection.call_action( connection_type, "GetGenericPortMappingEntry", NewPortMappingIndex=i, ) # We can only handle port forwards of the given device if portmap["NewInternalClient"] == fritzbox_tools.ha_ip: hass.add_job( async_add_entities, [ FritzBoxPortSwitch(fritzbox_tools, portmap, i, connection_type) ], ) except Exception: _LOGGER.error( f"Port switches could not be enabled. Check if your fritzbox is able to do port forwardings!", exc_info=True, ) def _create_profile_switches(): if len(fritzbox_tools.device_list) > 0: _LOGGER.debug("Setting up profile switches") devices = fritzbox_tools.profile_switch.get_devices() # Identify duplicated host names and log an error message hostname_count = Counter([device["name"] for device in devices]) duplicated_hostnames = [ name for name, occurence in hostname_count.items() if occurence > 1 ] if len(duplicated_hostnames) > 0: errs = ", ".join(duplicated_hostnames) _LOGGER.error( f"You have multiple devices with the hostname {errs} in your network. " "There will be no profile switches created for these.") # add device switches for device in devices: # Check for duplicated host names in the devices list. if device["name"] not in duplicated_hostnames: if device["name"] in fritzbox_tools.device_list: hass.add_job( async_add_entities, [FritzBoxProfileSwitch(fritzbox_tools, device)], ) def _create_wifi_switches(): if "WLANConfiguration:3" not in fritzbox_tools.connection.services: networks = {"1": "Wifi", "2": "Guest Wifi"} else: networks = {"1": "Wifi", "2": "Wifi (5GHz)", "3": "Guest Wifi"} for net in networks: hass.add_job( async_add_entities, [FritzBoxWifiSwitch(fritzbox_tools, net, networks[net])], ) hass.async_add_executor_job(_create_wifi_switches) hass.async_add_executor_job(_create_port_switches) hass.async_add_executor_job(_create_deflection_switches) hass.async_add_executor_job(_create_profile_switches) return True