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)
Esempio n. 2
0
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)
Esempio n. 3
0
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)
Esempio n. 4
0
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
Esempio n. 5
0
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
Esempio n. 6
0
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