示例#1
0
    async def async_step_user(self,
                              user_input: dict[str, Any] | None = None
                              ) -> FlowResult:
        """Handle the user step to pick discovered device."""
        if user_input is not None:
            address = user_input[CONF_ADDRESS]
            await self.async_set_unique_id(address, raise_on_progress=False)
            self._abort_if_unique_id_configured()
            return self.async_create_entry(
                title=self._discovered_devices[address], data={})

        current_addresses = self._async_current_ids()
        for discovery_info in async_discovered_service_info(self.hass, False):
            address = discovery_info.address
            if address in current_addresses or address in self._discovered_devices:
                continue
            device = DeviceData()
            if device.supported(discovery_info):
                self._discovered_devices[address] = (device.title or
                                                     device.get_device_name()
                                                     or discovery_info.name)

        if not self._discovered_devices:
            return self.async_abort(reason="no_devices_found")

        return self.async_show_form(
            step_id="user",
            data_schema=vol.Schema(
                {vol.Required(CONF_ADDRESS):
                 vol.In(self._discovered_devices)}),
        )
示例#2
0
def async_find_existing_service_info(
        hass: HomeAssistant, local_name: str,
        address: str) -> BluetoothServiceInfoBleak | None:
    """Return the service info for the given local_name and address."""
    for service_info in async_discovered_service_info(hass):
        device = service_info.device
        if device.address == address:
            return service_info
    return None
示例#3
0
    async def async_step_user(self,
                              user_input: dict[str, Any] | None = None
                              ) -> FlowResult:
        """Handle the user step to pick discovered device."""
        if user_input is not None:
            address = user_input[CONF_ADDRESS]
            await self.async_set_unique_id(address, raise_on_progress=False)
            self._abort_if_unique_id_configured()
            discovery = self._discovered_devices[address]

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

            # Wait until we have received enough information about this device to detect its encryption type
            try:
                self._discovery_info = await self._async_wait_for_full_advertisement(
                    discovery.discovery_info, discovery.device)
            except asyncio.TimeoutError:
                # This device might have a really long advertising interval
                # So create a config entry for it, and if we discover it has encryption later
                # We can do a reauth
                return await self.async_step_confirm_slow()

            self._discovered_device = discovery.device

            if discovery.device.encryption_scheme == EncryptionScheme.MIBEACON_LEGACY:
                return await self.async_step_get_encryption_key_legacy()

            if discovery.device.encryption_scheme == EncryptionScheme.MIBEACON_4_5:
                return await self.async_step_get_encryption_key_4_5()

            return self._async_get_or_create_entry()

        current_addresses = self._async_current_ids()
        for discovery_info in async_discovered_service_info(self.hass, False):
            address = discovery_info.address
            if address in current_addresses or address in self._discovered_devices:
                continue
            device = DeviceData()
            if device.supported(discovery_info):
                self._discovered_devices[address] = Discovery(
                    title=_title(discovery_info, device),
                    discovery_info=discovery_info,
                    device=device,
                )

        if not self._discovered_devices:
            return self.async_abort(reason="no_devices_found")

        titles = {
            address: discovery.title
            for (address, discovery) in self._discovered_devices.items()
        }
        return self.async_show_form(
            step_id="user",
            data_schema=vol.Schema(
                {vol.Required(CONF_ADDRESS): vol.In(titles)}),
        )
示例#4
0
async def _async_has_devices(hass: HomeAssistant) -> bool:
    """Return if there are devices that can be discovered."""

    service_infos = async_discovered_service_info(hass)

    for service_info in service_infos:
        if device_filter(service_info.device, service_info.advertisement):
            return True

    return False
示例#5
0
 def _async_refresh_ble(now: datetime) -> None:
     """Refresh BLE devices from the discovered service info."""
     # Make sure devices are seen again at the scheduled
     # interval so they do not get set to not_home when
     # there have been no callbacks because the RSSI or
     # other properties have not changed.
     for service_info in bluetooth.async_discovered_service_info(
             hass, False):
         _async_update_ble(service_info,
                           bluetooth.BluetoothChange.ADVERTISEMENT)
示例#6
0
    async def async_step_user(
        self, user_input: dict[str, Any] | None = None
    ) -> FlowResult:
        """Handle the user step to pick discovered device."""
        if user_input is not None:
            address = user_input[CONF_ADDRESS]
            await self.async_set_unique_id(address, raise_on_progress=False)
            self._abort_if_unique_id_configured()
            discovery = self._discovered_devices[address]

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

            self._discovery_info = discovery.discovery_info
            self._discovered_device = discovery.device

            if discovery.device.encryption_scheme == EncryptionScheme.BTHOME_BINDKEY:
                return await self.async_step_get_encryption_key()

            return self._async_get_or_create_entry()

        current_addresses = self._async_current_ids()
        for discovery_info in async_discovered_service_info(self.hass, False):
            address = discovery_info.address
            if address in current_addresses or address in self._discovered_devices:
                continue
            device = DeviceData()
            if device.supported(discovery_info):
                self._discovered_devices[address] = Discovery(
                    title=_title(discovery_info, device),
                    discovery_info=discovery_info,
                    device=device,
                )

        if not self._discovered_devices:
            return self.async_abort(reason="no_devices_found")

        titles = {
            address: discovery.title
            for (address, discovery) in self._discovered_devices.items()
        }
        return self.async_show_form(
            step_id="user",
            data_schema=vol.Schema({vol.Required(CONF_ADDRESS): vol.In(titles)}),
        )
示例#7
0
    def _async_discover_devices(self) -> None:
        current_addresses = self._async_current_ids()
        for connectable in (True, False):
            for discovery_info in async_discovered_service_info(self.hass, connectable):
                address = discovery_info.address
                if (
                    format_unique_id(address) in current_addresses
                    or address in self._discovered_advs
                ):
                    continue
                parsed = parse_advertisement_data(
                    discovery_info.device, discovery_info.advertisement
                )
                if not parsed:
                    continue
                model_name = parsed.data.get("modelName")
                if (
                    discovery_info.connectable
                    and model_name in CONNECTABLE_SUPPORTED_MODEL_TYPES
                ) or model_name in NON_CONNECTABLE_SUPPORTED_MODEL_TYPES:
                    self._discovered_advs[address] = parsed

        if not self._discovered_advs:
            raise AbortFlow("no_unconfigured_devices")
示例#8
0
                _LOGGER.exception("Unexpected error")
                errors["base"] = "unknown"
            else:
                await led_ble.stop()
                return self.async_create_entry(
                    title=local_name,
                    data={
                        CONF_ADDRESS: discovery_info.address,
                    },
                )

        if discovery := self._discovery_info:
            self._discovered_devices[discovery.address] = discovery
        else:
            current_addresses = self._async_current_ids()
            for discovery in async_discovered_service_info(self.hass):
                if (discovery.address in current_addresses
                        or discovery.address in self._discovered_devices
                        or not any(
                            discovery.name.startswith(local_name)
                            and not discovery.name.startswith(
                                UNSUPPORTED_SUB_MODEL)
                            for local_name in LOCAL_NAMES)):
                    continue
                self._discovered_devices[discovery.address] = discovery

        if not self._discovered_devices:
            return self.async_abort(reason="no_unconfigured_devices")

        data_schema = vol.Schema({
            vol.Required(CONF_ADDRESS):