Ejemplo n.º 1
0
    async def async_step_ssdp(self,
                              discovery_info: DiscoveryInfoType) -> FlowResult:
        """Handle SSDP initiated config flow."""
        await self.async_set_unique_id(discovery_info[ssdp.ATTR_UPNP_UDN])
        self._abort_if_unique_id_configured()

        # Attempt to distinguish from other non-LTE Huawei router devices, at least
        # some ones we are interested in have "Mobile Wi-Fi" friendlyName.
        if "mobile" not in discovery_info.get(ssdp.ATTR_UPNP_FRIENDLY_NAME,
                                              "").lower():
            return self.async_abort(reason="not_huawei_lte")

        url = self.context[CONF_URL] = url_normalize(
            discovery_info.get(
                ssdp.ATTR_UPNP_PRESENTATION_URL,
                f"http://{urlparse(discovery_info[ssdp.ATTR_SSDP_LOCATION]).hostname}/",
            ))

        if any(url == flow["context"].get(CONF_URL)
               for flow in self._async_in_progress()):
            return self.async_abort(reason="already_in_progress")

        user_input = {CONF_URL: url}
        if self._already_configured(user_input):
            return self.async_abort(reason="already_configured")

        self.context["title_placeholders"] = {
            CONF_NAME: discovery_info.get(ssdp.ATTR_UPNP_FRIENDLY_NAME)
        }
        return await self._async_show_user_form(user_input)
Ejemplo n.º 2
0
    async def async_step_ssdp(self,
                              discovery_info: DiscoveryInfoType) -> FlowResult:
        """Handle a flow initialized by discovery."""
        host = urlparse(discovery_info[ATTR_SSDP_LOCATION]).hostname
        assert isinstance(host, str)
        self.context[CONF_HOST] = host

        uuid = discovery_info.get(ATTR_UPNP_UDN)
        if uuid:
            if uuid.startswith("uuid:"):
                uuid = uuid[5:]
            await self.async_set_unique_id(uuid)
            self._abort_if_unique_id_configured({CONF_HOST: host})

        for progress in self._async_in_progress():
            if progress.get("context", {}).get(CONF_HOST) == host:
                return self.async_abort(reason="already_in_progress")

        # update old and user-configured config entries
        for entry in self._async_current_entries():
            if entry.data[CONF_HOST] == host:
                if uuid and not entry.unique_id:
                    self.hass.config_entries.async_update_entry(entry,
                                                                unique_id=uuid)
                return self.async_abort(reason="already_configured")

        self._host = host
        self._name = str(discovery_info.get(ATTR_UPNP_FRIENDLY_NAME) or host)

        self.context["title_placeholders"] = {"name": self._name}
        return await self.async_step_confirm()
    async def _async_set_info(self, discovery_info: DiscoveryInfoType) -> None:
        self._discovery_info = discovery_info
        self._descriptor = MerossDeviceDescriptor(
            discovery_info.get(CONF_PAYLOAD, {}))
        self._device_id = self._descriptor.uuid
        await self.async_set_unique_id(self._device_id)
        self._abort_if_unique_id_configured()

        if CONF_DEVICE_ID not in discovery_info:  #this is coming from manual user entry or dhcp discovery
            discovery_info[CONF_DEVICE_ID] = self._device_id

        if (self._cloud_key is not None) and (self._cloud_key == self._key):
            # save (only if good) so we can later automatically retrieve for new devices
            discovery_info[CONF_CLOUD_KEY] = self._cloud_key
        else:
            discovery_info.pop(CONF_CLOUD_KEY, None)

        self._placeholders = {
            CONF_DEVICE_TYPE: get_productnametype(self._descriptor.type),
            CONF_DEVICE_ID: self._device_id,
            CONF_PAYLOAD: ""  #json.dumps(data.get(CONF_PAYLOAD, {}))
        }

        self.context["title_placeholders"] = self._placeholders
        return
Ejemplo n.º 4
0
async def async_setup_platform(
    hass: HomeAssistant,
    _: ConfigType,
    async_add_entities: AddEntitiesCallback,
    discovery_info: DiscoveryInfoType = None,
) -> None:
    """Create the Climate entities for CH/DHW (heat) & HVAC."""
    def entity_factory(entity_class, broker, device):
        migrate_to_ramses_rf(hass, PLATFORM, f"{device.id}")
        return entity_class(broker, device)

    if discovery_info is None:
        return

    broker = hass.data[DOMAIN][BROKER]
    new_entities = []

    if tcs := discovery_info.get("tcs"):
        new_entities.append(entity_factory(EvohomeController, broker, tcs))

        if not broker._services.get(PLATFORM):
            broker._services[PLATFORM] = True

            register_svc = current_platform.get().async_register_entity_service
            [
                register_svc(k, v, f"svc_{k}")
                for k, v in SVCS_CLIMATE_EVOHOME.items()
            ]
Ejemplo n.º 5
0
    async def async_step_ssdp(self,
                              discovery_info: DiscoveryInfoType) -> FlowResult:
        """Handle a discovered device."""
        friendly_name = discovery_info.get(ssdp.ATTR_UPNP_FRIENDLY_NAME, "")

        # Filter out items not having "keenetic" in their name
        if "keenetic" not in friendly_name.lower():
            return self.async_abort(reason="not_keenetic_ndms2")

        # Filters out items having no/empty UDN
        if not discovery_info.get(ssdp.ATTR_UPNP_UDN):
            return self.async_abort(reason="no_udn")

        host = urlparse(discovery_info[ssdp.ATTR_SSDP_LOCATION]).hostname
        await self.async_set_unique_id(discovery_info[ssdp.ATTR_UPNP_UDN])

        self._async_abort_entries_match({CONF_HOST: host})

        self.context[CONF_HOST] = host
        self.context["title_placeholders"] = {
            "name": friendly_name,
            "host": host,
        }

        return await self.async_step_user()
    async def async_step_dhcp(self, discovery_info: DiscoveryInfoType):
        """Handle a flow initialized by DHCP discovery."""
        LOGGER.debug("received dhcp discovery: %s", json.dumps(discovery_info))

        self._host = discovery_info.get('ip')
        self._macaddress = discovery_info.get('macaddress')
        """
        we'll update the unique_id for the flow when we'll have the device_id
        macaddress would have been a better choice since the beginning (...)
        but I don't want to mess with ConfigEntry versioning right now
        Here this is needed in case we cannot correctly identify the device
        via our api and the dhcp integration keeps pushing us discoveries for
        the same device
        """
        await self.async_set_unique_id(self._macaddress,
                                       raise_on_progress=True)
        """
        Check we already dont have the device registered.
        This is probably overkill since the ConfigFlow will recognize
        the duplicated unique_id sooner or later
        """
        api = self.hass.data.get(DOMAIN)
        if api is not None:
            if api.has_device(self._host, self._macaddress):
                return self.async_abort(reason='already_configured')

        try:
            # try device identification so the user/UI has a good context to start with
            _discovery_info = None
            if api is not None:
                """
                we'll see if any previous device already used a 'cloud_key' retrieved
                from meross api for cloud-paired devices and try it
                """
                if api.cloud_key is not None:
                    self._key = api.cloud_key
                    try:
                        _discovery_info = await self._http_discovery()
                        self._cloud_key = self._key  # pass along so we'll save it in this entry too
                    except MerossKeyError:
                        pass
                if (_discovery_info is None) and (api.key is not None):
                    self._key = api.key
                    try:
                        _discovery_info = await self._http_discovery()
                    except MerossKeyError:
                        pass
            if _discovery_info is None:
                self._key = None  # no other options: try empty key (which will eventually use the reply-hack)
                _discovery_info = await self._http_discovery()
            await self._async_set_info(_discovery_info)
            # now just let the user edit/accept the host address even if identification was fine
        except Exception as e:
            LOGGER.debug("Error (%s) identifying meross device (host:%s)",
                         str(e), self._host)
            # forgive and continue if we cant discover the device...let the user work it out

        return await self.async_step_user()
Ejemplo n.º 7
0
    async def async_step_ssdp(self, discovery_info: DiscoveryInfoType) -> FlowResult:
        """Handle a flow initialized by discovery."""
        host = urlparse(discovery_info[ATTR_SSDP_LOCATION]).hostname
        assert isinstance(host, str)
        self.context[CONF_HOST] = host

        if uuid := discovery_info.get(ATTR_UPNP_UDN):
            if uuid.startswith("uuid:"):
                uuid = uuid[5:]
            await self.async_set_unique_id(uuid)
            self._abort_if_unique_id_configured({CONF_HOST: host})
Ejemplo n.º 8
0
    async def async_step_ssdp(self, discovery_info: DiscoveryInfoType) -> FlowResult:
        """Handle a flow initialized by SSDP discovery."""
        LOGGER.debug("async_step_ssdp: discovery_info %s", pformat(discovery_info))

        self._discoveries = [discovery_info]

        udn = discovery_info[ssdp.ATTR_SSDP_UDN]
        location = discovery_info[ssdp.ATTR_SSDP_LOCATION]

        # Abort if already configured, but update the last-known location
        await self.async_set_unique_id(udn)
        self._abort_if_unique_id_configured(
            updates={CONF_URL: location}, reload_on_update=False
        )

        # If the device needs migration because it wasn't turned on when HA
        # started, silently migrate it now.
        import_data = get_domain_data(self.hass).unmigrated_config.get(location)
        if import_data is not None:
            return await self.async_step_import(import_data)

        parsed_url = urlparse(location)
        name = discovery_info.get(ssdp.ATTR_UPNP_FRIENDLY_NAME) or parsed_url.hostname
        self.context["title_placeholders"] = {"name": name}

        return await self.async_step_confirm()
Ejemplo n.º 9
0
async def async_setup_platform(
    hass: HomeAssistant,
    _: ConfigType,
    async_add_entities: AddEntitiesCallback,
    discovery_info: DiscoveryInfoType = None,
) -> None:
    """Create a DHW controller."""
    def entity_factory(entity_class, broker, device):
        migrate_to_ramses_rf(hass, "water_heater", f"{device.id}")
        return entity_class(broker, device)

    if discovery_info is None:
        return

    broker = hass.data[DOMAIN][BROKER]

    if not discovery_info.get("dhw"):
        return

    async_add_entities(
        [entity_factory(EvohomeDHW, broker, discovery_info["dhw"])])

    if broker._services.get(PLATFORM):
        return
    broker._services[PLATFORM] = True
Ejemplo n.º 10
0
async def async_setup_platform(
    hass: HomeAssistant,
    _: ConfigType,
    async_add_entities: AddEntitiesCallback,
    discovery_info: DiscoveryInfoType = None,
) -> None:
    """Set up the binary sensor entities.

    discovery_info keys:
      gateway: is the ramses_rf protocol stack (gateway/protocol/transport/serial)
      devices: heat (e.g. CTL, OTB, BDR, TRV) or hvac (e.g. FAN, CO2, SWI)
      domains: TCS, DHW and Zones
    """

    def entity_factory(broker, device, attr, *, entity_class=None, **kwargs):
        migrate_to_ramses_rf(hass, "binary_sensor", f"{device.id}-{attr}")
        return (entity_class or RamsesBinarySensor)(broker, device, attr, **kwargs)

    if discovery_info is None:
        return

    broker = hass.data[DOMAIN][BROKER]

    new_sensors = [
        entity_factory(broker, dev, k, **v)
        for k, v in BINARY_SENSOR_ATTRS["gateway"].items()
        if (dev := discovery_info.get("gateway"))
    ]  # 18:xxxxxx - status
Ejemplo n.º 11
0
    async def async_step_ssdp(self,
                              discovery_info: DiscoveryInfoType) -> FlowResult:
        """Handle a flow initialized by discovery."""
        ssdp_location: ParseResult = urlparse(
            discovery_info[ATTR_SSDP_LOCATION])
        self._host = ssdp_location.hostname
        self._port = ssdp_location.port
        self._name = (discovery_info.get(ATTR_UPNP_FRIENDLY_NAME)
                      or self.fritz_tools.model)
        self.context[CONF_HOST] = self._host

        if uuid := discovery_info.get(ATTR_UPNP_UDN):
            if uuid.startswith("uuid:"):
                uuid = uuid[5:]
            await self.async_set_unique_id(uuid)
            self._abort_if_unique_id_configured({CONF_HOST: self._host})
Ejemplo n.º 12
0
    async def async_step_zeroconf(
        self, discovery_info: DiscoveryInfoType
    ) -> FlowResult:
        """Handle zeroconf discovery."""
        try:
            self.info = info = await self._async_get_info(discovery_info["host"])
        except HTTP_CONNECT_ERRORS:
            return self.async_abort(reason="cannot_connect")
        except aioshelly.FirmwareUnsupported:
            return self.async_abort(reason="unsupported_firmware")

        await self.async_set_unique_id(info["mac"])
        self._abort_if_unique_id_configured({CONF_HOST: discovery_info["host"]})
        self.host = discovery_info["host"]

        self.context["title_placeholders"] = {
            "name": discovery_info.get("name", "").split(".")[0]
        }

        if info["auth"]:
            return await self.async_step_credentials()

        try:
            self.device_info = await validate_input(self.hass, self.host, {})
        except HTTP_CONNECT_ERRORS:
            return self.async_abort(reason="cannot_connect")

        return await self.async_step_confirm_discovery()
Ejemplo n.º 13
0
    async def async_step_zeroconf(
        self, discovery_info: DiscoveryInfoType
    ) -> FlowResult:
        """Handle zeroconf discovery."""
        # Hostname is format: brother.local.
        self.host = discovery_info["hostname"].rstrip(".")

        # Do not probe the device if the host is already configured
        self._async_abort_entries_match({CONF_HOST: self.host})

        snmp_engine = get_snmp_engine(self.hass)
        model = discovery_info.get("properties", {}).get("product")

        try:
            self.brother = Brother(self.host, snmp_engine=snmp_engine, model=model)
            await self.brother.async_update()
        except UnsupportedModel:
            return self.async_abort(reason="unsupported_model")
        except (ConnectionError, SnmpError):
            return self.async_abort(reason="cannot_connect")

        # Check if already configured
        await self.async_set_unique_id(self.brother.serial.lower())
        self._abort_if_unique_id_configured()

        self.context.update(
            {
                "title_placeholders": {
                    "serial_number": self.brother.serial,
                    "model": self.brother.model,
                }
            }
        )
        return await self.async_step_zeroconf_confirm()
Ejemplo n.º 14
0
 async def async_step_zeroconf(self, discovery_info: DiscoveryInfoType):
     """Handle zeroconf discovery."""
     # Check if it is a gateway
     if discovery_info.get("properties", {}).get("MT") in SUPPORTED_MODEL_TYPES:
         await self._async_handle_discovery_without_unique_id()
         return await self.async_step_zeroconf_confirm()
     return self.async_abort(reason="Not a devolo Home Control gateway.")
Ejemplo n.º 15
0
    async def async_step_ssdp(self,
                              discovery_info: DiscoveryInfoType) -> FlowResult:
        """Handle SSDP discovery."""
        host = urlparse(discovery_info[ATTR_SSDP_LOCATION]).hostname
        receiver_id = None

        if discovery_info.get(ATTR_UPNP_SERIAL):
            receiver_id = discovery_info[ATTR_UPNP_SERIAL][
                4:]  # strips off RID-

        self.context.update({"title_placeholders": {"name": host}})

        self.discovery_info.update({
            CONF_HOST: host,
            CONF_NAME: host,
            CONF_RECEIVER_ID: receiver_id
        })

        try:
            info = await validate_input(self.hass, self.discovery_info)
        except DIRECTVError:
            return self.async_abort(reason=ERROR_CANNOT_CONNECT)
        except Exception:  # pylint: disable=broad-except
            _LOGGER.exception("Unexpected exception")
            return self.async_abort(reason=ERROR_UNKNOWN)

        self.discovery_info[CONF_RECEIVER_ID] = info[CONF_RECEIVER_ID]

        await self.async_set_unique_id(self.discovery_info[CONF_RECEIVER_ID])
        self._abort_if_unique_id_configured(
            updates={CONF_HOST: self.discovery_info[CONF_HOST]})

        return await self.async_step_ssdp_confirm()
Ejemplo n.º 16
0
async def async_setup_platform(
    hass: HomeAssistant,
    _: ConfigType,
    async_add_entities: AddEntitiesCallback,
    discovery_info: DiscoveryInfoType = None,
) -> None:
    """Set up the sensor entities.

    discovery_info keys:
      gateway: is the ramses_rf protocol stack (gateway/protocol/transport/serial)
      devices: heat (e.g. CTL, OTB, BDR, TRV) or hvac (e.g. FAN, CO2, SWI)
      domains: TCS, DHW and Zones
    """
    def entity_factory(broker, device, attr, *, entity_class=None, **kwargs):
        migrate_to_ramses_rf(hass, "sensor", f"{device.id}-{attr}")
        return (entity_class or RamsesSensor)(broker, device, attr, **kwargs)

    if discovery_info is None:
        return

    broker = hass.data[DOMAIN][BROKER]

    new_sensors = [
        entity_factory(broker, device, k, **v)
        for device in discovery_info.get("devices", [])
        for k, v in SENSOR_ATTRS.items() if hasattr(device, k)
    ]  # and (not device._is_faked or device["fakable"])
    new_sensors += [
        entity_factory(broker, device, f"{k}_ot", **v)
        for device in discovery_info.get("devices", [])
        for k, v in SENSOR_ATTRS_HEAT.items()
        if device._SLUG == "OTB" and hasattr(device, f"{k}_ot")
    ]
    new_sensors += [
        entity_factory(broker, domain, k, **v)
        for domain in discovery_info.get("domains", [])
        for k, v in SENSOR_ATTRS_HEAT.items()
        if k == "heat_demand" and hasattr(domain, k)
    ]

    async_add_entities(new_sensors)

    if not broker._services.get(PLATFORM) and new_sensors:
        broker._services[PLATFORM] = True

        register_svc = current_platform.get().async_register_entity_service
        [register_svc(k, v, f"svc_{k}") for k, v in SVCS_SENSOR.items()]
Ejemplo n.º 17
0
 async def async_step_ssdp(
         self,
         discovery_info: DiscoveryInfoType) -> data_entry_flow.FlowResult:
     """Handle a flow initialized by ssdp discovery."""
     LOGGER.debug("Samsung device found via SSDP: %s", discovery_info)
     model_name: str = discovery_info.get(ATTR_UPNP_MODEL_NAME) or ""
     self._udn = _strip_uuid(discovery_info[ATTR_UPNP_UDN])
     if hostname := urlparse(discovery_info[ATTR_SSDP_LOCATION]).hostname:
         self._host = hostname
Ejemplo n.º 18
0
 def __init__(self, config: ConfigType,
              discovery_info: DiscoveryInfoType) -> None:
     """Initialize the Configuration Info for Yamaha Receiver."""
     self.name = config.get(CONF_NAME)
     self.host = config.get(CONF_HOST)
     self.ctrl_url: str | None = f"http://{self.host}:80/YamahaRemoteControl/ctrl"
     self.source_ignore = config.get(CONF_SOURCE_IGNORE)
     self.source_names = config.get(CONF_SOURCE_NAMES)
     self.zone_ignore = config.get(CONF_ZONE_IGNORE)
     self.zone_names = config.get(CONF_ZONE_NAMES)
     self.from_discovery = False
     if discovery_info is not None:
         self.name = discovery_info.get("name")
         self.model = discovery_info.get("model_name")
         self.ctrl_url = discovery_info.get("control_url")
         self.desc_url = discovery_info.get("description_url")
         self.zone_ignore = []
         self.from_discovery = True
Ejemplo n.º 19
0
    async def async_step_ssdp(self,
                              discovery_info: DiscoveryInfoType) -> FlowResult:
        """Handle SSDP initiated config flow."""
        await self.async_set_unique_id(discovery_info[ssdp.ATTR_UPNP_UDN])
        self._abort_if_unique_id_configured()

        # Attempt to distinguish from other non-LTE Huawei router devices, at least
        # some ones we are interested in have "Mobile Wi-Fi" friendlyName.
        if "mobile" not in discovery_info.get(ssdp.ATTR_UPNP_FRIENDLY_NAME,
                                              "").lower():
            return self.async_abort(reason="not_huawei_lte")

        url = url_normalize(
            discovery_info.get(
                ssdp.ATTR_UPNP_PRESENTATION_URL,
                f"http://{urlparse(discovery_info[ssdp.ATTR_SSDP_LOCATION]).hostname}/",
            ))

        if serial_number := discovery_info.get(ssdp.ATTR_UPNP_SERIAL):
            await self.async_set_unique_id(serial_number)
            self._abort_if_unique_id_configured()
Ejemplo n.º 20
0
 async def async_step_ssdp(self, discovery_info: DiscoveryInfoType):
     """Handle a flow initialized by ssdp discovery."""
     self._udn = _strip_uuid(discovery_info[ATTR_UPNP_UDN])
     await self._async_set_unique_id_from_udn()
     await self._async_start_discovery_for_host(
         urlparse(discovery_info[ATTR_SSDP_LOCATION]).hostname)
     self._manufacturer = discovery_info[ATTR_UPNP_MANUFACTURER]
     if not self._manufacturer or not self._manufacturer.lower().startswith(
             "samsung"):
         raise data_entry_flow.AbortFlow(RESULT_NOT_SUPPORTED)
     self._name = self._title = self._model = discovery_info.get(
         ATTR_UPNP_MODEL_NAME)
     self.context["title_placeholders"] = {"device": self._title}
     return await self.async_step_confirm()
Ejemplo n.º 21
0
 async def async_step_ssdp(self, discovery_info: DiscoveryInfoType):
     """Handle a flow initialized by ssdp discovery."""
     LOGGER.debug("Samsung device found via SSDP: %s", discovery_info)
     model_name = discovery_info.get(ATTR_UPNP_MODEL_NAME)
     self._udn = _strip_uuid(discovery_info[ATTR_UPNP_UDN])
     self._host = urlparse(discovery_info[ATTR_SSDP_LOCATION]).hostname
     await self._async_set_unique_id_from_udn()
     self._manufacturer = discovery_info[ATTR_UPNP_MANUFACTURER]
     self._abort_if_manufacturer_is_not_samsung()
     if not await self._async_get_and_check_device_info():
         # If we cannot get device info for an SSDP discovery
         # its likely a legacy tv.
         self._name = self._title = self._model = model_name
     self._async_update_and_abort_for_matching_unique_id()
     self._async_abort_if_host_already_in_progress()
     self.context["title_placeholders"] = {"device": self._title}
     return await self.async_step_confirm()
Ejemplo n.º 22
0
    async def async_step_zeroconf(self, discovery_info: DiscoveryInfoType):
        """Prepare configuration for a discovered Plugwise Smile."""
        self.discovery_info = discovery_info
        _properties = self.discovery_info.get("properties")

        unique_id = self.discovery_info.get("hostname").split(".")[0]
        await self.async_set_unique_id(unique_id)
        self._abort_if_unique_id_configured()

        _product = _properties.get("product", None)
        _version = _properties.get("version", "n/a")
        _name = f"{ZEROCONF_MAP.get(_product, _product)} v{_version}"

        self.context["title_placeholders"] = {
            CONF_HOST: discovery_info[CONF_HOST],
            CONF_PORT: discovery_info.get(CONF_PORT, DEFAULT_PORT),
            CONF_NAME: _name,
        }
        return await self.async_step_user()
Ejemplo n.º 23
0
async def async_setup_platform(
    hass: HomeAssistant,
    _: ConfigType,
    async_add_entities: AddEntitiesCallback,
    discovery_info: DiscoveryInfoType = None,
) -> None:
    """Create the Climate entities for CH/DHW (heat) & HVAC."""

    if discovery_info is None:
        return

    broker = hass.data[DOMAIN][BROKER]
    new_entities = []

    for fan in [f for f in discovery_info.get("fans", [])]:
        new_entities.append(RamsesFan(broker, fan))

    if new_entities:
        async_add_entities(new_entities)
Ejemplo n.º 24
0
    async def async_step_ssdp(self,
                              discovery_info: DiscoveryInfoType) -> FlowResult:
        """Handle a flow initialized by SSDP discovery."""
        LOGGER.debug("async_step_ssdp: discovery_info %s",
                     pformat(discovery_info))

        await self._async_set_info_from_discovery(discovery_info)

        if _is_ignored_device(discovery_info):
            return self.async_abort(reason="alternative_integration")

        # Abort if the device doesn't support all services required for a DmrDevice.
        # Use the discovery_info instead of DmrDevice.is_profile_device to avoid
        # contacting the device again.
        discovery_service_list = discovery_info.get(
            ssdp.ATTR_UPNP_SERVICE_LIST)
        if not discovery_service_list:
            return self.async_abort(reason="not_dmr")
        discovery_service_ids = {
            service.get("serviceId")
            for service in discovery_service_list.get("service") or []
        }
        if not DmrDevice.SERVICE_IDS.issubset(discovery_service_ids):
            return self.async_abort(reason="not_dmr")

        # Abort if a migration flow for the device's location is in progress
        for progress in self._async_in_progress(include_uninitialized=True):
            if progress["context"].get("unique_id") == self._location:
                LOGGER.debug(
                    "Aborting SSDP setup because migration for %s is in progress",
                    self._location,
                )
                return self.async_abort(reason="already_in_progress")

        self.context["title_placeholders"] = {"name": self._name}

        return await self.async_step_confirm()
Ejemplo n.º 25
0
    async def async_step_zeroconf(self, discovery_info: DiscoveryInfoType):
        """Handle zeroconf discovery."""
        # Hostname is format: _aqara._tcp.local., _aqara-setup._tcp.local.
        local_name = discovery_info["hostname"][:-1]
        node_name = local_name[:-len(".local")]
        address = discovery_info["properties"].get("address",
                                                   discovery_info["host"])
        model = discovery_info["properties"].get("md", "unknow")
        fwversion = discovery_info["properties"].get("fw", "unknow")
        fwcloud = discovery_info["properties"].get("cl", "unknow")
        self._device_info = (f"Name: {node_name}\n"
                             f"Model: {model}\n"
                             f"Hostname: {local_name}\n"
                             f"IP: {address}\n"
                             f"Version: {fwversion}\n"
                             f"Cloud: {fwcloud}")

        self._host = discovery_info[CONF_HOST]
        self._name = node_name
        self._password = ''
        self._model = Utils.get_device_name(model).split(" ")[-1]

        ret = gateway.is_aqaragateway(address, None, model)
        if "ok" not in ret['status']:
            return await self.async_step_user()

        # Check if already configured
        if node_name:
            await self.async_set_unique_id(node_name)

        self._abort_if_unique_id_configured(
            updates={CONF_HOST: discovery_info[CONF_HOST]})

        for entry in self._async_current_entries():
            already_configured = False
            if CONF_HOST in entry.data and entry.data[CONF_HOST] in [
                    address,
                    discovery_info[CONF_HOST],
            ]:
                # Is this address or IP address already configured?
                already_configured = True
            elif entry.entry_id in self.hass.data.get(DATA_KEY, {}):
                # Does a config entry with this name already exist?
                data: RuntimeEntryData = self.hass.data[DATA_KEY][
                    entry.entry_id]

                # Node names are unique in the network
                if data.device_info is not None:
                    already_configured = data.device_info.name == node_name
            if already_configured:
                # Backwards compat, we update old entries
                if not entry.unique_id:
                    self.hass.config_entries.async_update_entry(
                        entry,
                        data={
                            **entry.data, CONF_HOST: discovery_info[CONF_HOST]
                        },
                        unique_id=node_name,
                    )

                return self.async_abort(reason="already_configured")

        if discovery_info.get('type') == '_aqara-setup._tcp.local.':
            return await self.async_step_user()
        else:
            return await self.async_step_discovery_confirm()
Ejemplo n.º 26
0
    async def async_step_zeroconf(self, discovery_info: DiscoveryInfoType):
        """Handle zeroconf discovery."""
        # Hostname is format: _aqara._tcp.local., _aqara-setup._tcp.local.
        if getattr(discovery_info, "hostname"):
            local_name = discovery_info.hostname[:-1]
            node_name = local_name[:-len(".local")]
            address = discovery_info.properties.get("address",
                                                    discovery_info.host)
            model = discovery_info.properties.get("md", "unknow")
            fwversion = discovery_info.properties.get("fw", "unknow")
            fwcloud = discovery_info.properties.get("cl", "unknow")
        else:
            local_name = discovery_info["hostname"][:-1]
            node_name = local_name[:-len(".local")]
            address = discovery_info["properties"].get(
                "address", discovery_info[CONF_HOST])
            model = discovery_info["properties"].get("md", "unknow")
            fwversion = discovery_info["properties"].get("fw", "unknow")
            fwcloud = discovery_info["properties"].get("cl", "unknow")
        self._device_info = (f"Name: {node_name}\n"
                             f"Model: {model}\n"
                             f"Hostname: {local_name}\n"
                             f"IP: {address}\n"
                             f"Version: {fwversion}\n"
                             f"Cloud: {fwcloud}")

        if getattr(discovery_info, "hostname"):
            self._host = discovery_info.hostname
        else:
            self._host = discovery_info[CONF_HOST]
        self._name = node_name
        self._password = ''
        self._token = ''
        self._model = model

        for entry in self._async_current_entries():
            already_configured = False
            if CONF_HOST in entry.data and entry.data[CONF_HOST] in [
                    address,
                    self._host,
            ]:
                # Is this address or IP address already configured?
                already_configured = True
            elif CONF_HOST in entry.options and entry.options[CONF_HOST] in [
                    address,
                    self._host,
            ]:
                # Is this address or IP address already configured?
                already_configured = True
            if already_configured:
                # Backwards compat, we update old entries

                return self.async_abort(reason="already_configured")

        # Check if already configured
        if node_name:
            await self.async_set_unique_id(node_name)

        self._abort_if_unique_id_configured(updates={CONF_HOST: self._host})

        if model not in SUPPORTED_MODELS:
            return self.async_abort(reason="connection_error")

        if (fwcloud == "miot"
                and discovery_info.get('type') == '_aqara-setup._tcp.local.'):
            return await self.async_step_user()
        return await self.async_step_discovery_confirm()