Ejemplo n.º 1
0
def test_is_ipv4_address():
    """Test if strings are IPv4 addresses."""
    assert network_util.is_ipv4_address("192.168.0.1") is True
    assert network_util.is_ipv4_address("8.8.8.8") is True
    assert network_util.is_ipv4_address("192.168.0.999") is False
    assert network_util.is_ipv4_address("192.168.0.0/24") is False
    assert network_util.is_ipv4_address("example.com") is False
Ejemplo n.º 2
0
    async def async_step_zeroconf(
        self, discovery_info: zeroconf.ZeroconfServiceInfo
    ) -> FlowResult:
        """Handle a flow initialized by zeroconf discovery."""
        if not is_ipv4_address(discovery_info.host):
            return self.async_abort(reason="not_ipv4_address")
        serial = discovery_info.properties["serialnum"]
        await self.async_set_unique_id(serial)
        self.ip_address = discovery_info.host
        self._abort_if_unique_id_configured({CONF_HOST: self.ip_address})
        for entry in self._async_current_entries(include_ignore=False):
            if (
                entry.unique_id is None
                and CONF_HOST in entry.data
                and entry.data[CONF_HOST] == self.ip_address
            ):
                title = f"{ENVOY} {serial}" if entry.title == ENVOY else ENVOY
                self.hass.config_entries.async_update_entry(
                    entry, title=title, unique_id=serial
                )
                self.hass.async_create_task(
                    self.hass.config_entries.async_reload(entry.entry_id)
                )
                return self.async_abort(reason="already_configured")

        return await self.async_step_user()
Ejemplo n.º 3
0
    async def async_step_zeroconf(
            self, discovery_info: zeroconf.ZeroconfServiceInfo) -> FlowResult:
        """Prepare configuration for a discovered doorbird device."""
        macaddress = discovery_info.properties["macaddress"]
        host = discovery_info.host

        if macaddress[:6] != DOORBIRD_OUI:
            return self.async_abort(reason="not_doorbird_device")
        if is_link_local(ip_address(host)):
            return self.async_abort(reason="link_local_address")
        if not is_ipv4_address(host):
            return self.async_abort(reason="not_ipv4_address")

        await self.async_set_unique_id(macaddress)
        self._abort_if_unique_id_configured(updates={CONF_HOST: host})

        self._async_abort_entries_match({CONF_HOST: host})

        if not await async_verify_supported_device(self.hass, host):
            return self.async_abort(reason="not_doorbird_device")

        chop_ending = "._axis-video._tcp.local."
        friendly_hostname = discovery_info.name
        if friendly_hostname.endswith(chop_ending):
            friendly_hostname = friendly_hostname[:-len(chop_ending)]

        self.context["title_placeholders"] = {
            CONF_NAME: friendly_hostname,
            CONF_HOST: host,
        }
        self.discovery_schema = _schema_with_defaults(host=host,
                                                      name=friendly_hostname)

        return await self.async_step_user()
Ejemplo n.º 4
0
class NetgearFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
    """Handle a config flow."""

    VERSION = 1

    def __init__(self):
        """Initialize the netgear config flow."""
        self.placeholders = {
            CONF_HOST: DEFAULT_HOST,
            CONF_PORT: DEFAULT_PORT,
            CONF_USERNAME: DEFAULT_USER,
            CONF_SSL: False,
        }
        self.discovered = False

    @staticmethod
    @callback
    def async_get_options_flow(
        config_entry: config_entries.ConfigEntry, ) -> OptionsFlowHandler:
        """Get the options flow."""
        return OptionsFlowHandler(config_entry)

    async def _show_setup_form(self, user_input=None, errors=None):
        """Show the setup form to the user."""
        if not user_input:
            user_input = {}

        if self.discovered:
            data_schema = _discovery_schema_with_defaults(user_input)
        else:
            data_schema = _user_schema_with_defaults(user_input)

        return self.async_show_form(
            step_id="user",
            data_schema=data_schema,
            errors=errors or {},
            description_placeholders=self.placeholders,
        )

    async def async_step_ssdp(
            self, discovery_info: ssdp.SsdpServiceInfo) -> FlowResult:
        """Initialize flow from ssdp."""
        updated_data: dict[str, str | int | bool] = {}

        device_url = urlparse(discovery_info.ssdp_location)
        if hostname := device_url.hostname:
            hostname = cast(str, hostname)
            updated_data[CONF_HOST] = hostname

        if not is_ipv4_address(str(hostname)):
            return self.async_abort(reason="not_ipv4_address")

        _LOGGER.debug("Netgear ssdp discovery info: %s", discovery_info)

        await self.async_set_unique_id(
            discovery_info.upnp[ssdp.ATTR_UPNP_SERIAL])
        self._abort_if_unique_id_configured(updates=updated_data)

        if device_url.scheme == "https":
            updated_data[CONF_SSL] = True
        else:
            updated_data[CONF_SSL] = False

        updated_data[CONF_PORT] = DEFAULT_PORT
        for model in MODELS_PORT_80:
            if discovery_info.upnp.get(
                    ssdp.ATTR_UPNP_MODEL_NUMBER,
                    "").startswith(model) or discovery_info.upnp.get(
                        ssdp.ATTR_UPNP_MODEL_NAME, "").startswith(model):
                updated_data[CONF_PORT] = PORT_80
        for model in MODELS_PORT_5555:
            if discovery_info.upnp.get(
                    ssdp.ATTR_UPNP_MODEL_NUMBER,
                    "").startswith(model) or discovery_info.upnp.get(
                        ssdp.ATTR_UPNP_MODEL_NAME, "").startswith(model):
                updated_data[CONF_PORT] = PORT_5555
                updated_data[CONF_SSL] = True

        self.placeholders.update(updated_data)
        self.discovered = True

        return await self.async_step_user()