Beispiel #1
0
    async def async_validate_input(self, user_input: dict[str,
                                                          Any]) -> FlowResult:
        """Validate user credentials."""
        username = user_input.get(CONF_USERNAME)
        password = user_input.get(CONF_PASSWORD)

        server = SUPPORTED_SERVERS[user_input.get(CONF_HUB, DEFAULT_HUB)]

        async with TahomaClient(username, password,
                                api_url=server.endpoint) as client:
            await client.login()

            # Set first gateway as unique id
            gateways = await client.get_gateways()
            if gateways:
                gateway_id = gateways[0].id
                await self.async_set_unique_id(gateway_id)

            # Create new config entry
            if (self._reauth_entry is None
                    or self._reauth_entry.unique_id != self.unique_id):
                self._abort_if_unique_id_configured()
                return self.async_create_entry(title=username, data=user_input)

            # Modify existing entry in reauth scenario
            self.hass.config_entries.async_update_entry(self._reauth_entry,
                                                        data=user_input)

            await self.hass.config_entries.async_reload(
                self._reauth_entry.entry_id)

            return self.async_abort(reason="reauth_successful")
Beispiel #2
0
    async def async_validate_input(self, user_input):
        """Validate user credentials."""
        username = user_input.get(CONF_USERNAME)
        password = user_input.get(CONF_PASSWORD)

        async with TahomaClient(username, password) as client:
            await client.login()
            return self.async_create_entry(title=username, data=user_input)
Beispiel #3
0
    async def async_validate_input(self, user_input):
        """Validate user credentials."""
        username = user_input.get(CONF_USERNAME)
        password = user_input.get(CONF_PASSWORD)

        hub = user_input.get(CONF_HUB, DEFAULT_HUB)
        endpoint = SUPPORTED_ENDPOINTS[hub]

        async with TahomaClient(username, password,
                                api_url=endpoint) as client:
            await client.login()
            return self.async_create_entry(
                title=username,
                data=user_input,
            )
Beispiel #4
0
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
    """Set up TaHoma from a config entry."""
    hass.data.setdefault(DOMAIN, {})

    username = entry.data.get(CONF_USERNAME)
    password = entry.data.get(CONF_PASSWORD)

    session = aiohttp_client.async_create_clientsession(
        hass, cookie_jar=CookieJar(unsafe=True))

    client = TahomaClient(username, password, session=session)

    try:
        await client.login()
    except TooManyRequestsException:
        _LOGGER.error("too_many_requests")
        return False
    except BadCredentialsException:
        _LOGGER.error("invalid_auth")
        return False
    except Exception as exception:  # pylint: disable=broad-except
        _LOGGER.exception(exception)
        return False

    update_interval = entry.options.get(CONF_UPDATE_INTERVAL,
                                        DEFAULT_UPDATE_INTERVAL)

    tahoma_coordinator = TahomaDataUpdateCoordinator(
        hass,
        _LOGGER,
        name="TaHoma Event Fetcher",
        client=client,
        devices=await client.get_devices(),
        update_interval=timedelta(seconds=update_interval),
    )

    await tahoma_coordinator.async_refresh()

    entities = defaultdict(list)
    entities[SCENE] = await client.get_scenarios()

    hass.data[DOMAIN][entry.entry_id] = {
        "entities": entities,
        "coordinator": tahoma_coordinator,
        "update_listener": entry.add_update_listener(update_listener),
    }

    for device in tahoma_coordinator.data.values():
        platform = TAHOMA_TYPES.get(device.widget) or TAHOMA_TYPES.get(
            device.ui_class)
        if platform:
            entities[platform].append(device)
        elif (device.widget not in IGNORED_TAHOMA_TYPES
              and device.ui_class not in IGNORED_TAHOMA_TYPES):
            _LOGGER.debug(
                "Unsupported TaHoma device detected (%s - %s - %s)",
                device.controllable_name,
                device.ui_class,
                device.widget,
            )

    for platform in entities:
        hass.async_create_task(
            hass.config_entries.async_forward_entry_setup(entry, platform))

    return True
Beispiel #5
0
 def api(self):
     return TahomaClient("username", "password")
Beispiel #6
0
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
    """Set up TaHoma from a config entry."""
    hass.data.setdefault(DOMAIN, {})

    username = entry.data.get(CONF_USERNAME)
    password = entry.data.get(CONF_PASSWORD)

    session = aiohttp_client.async_create_clientsession(hass)
    client = TahomaClient(username, password, session=session)

    try:
        await client.login()
        devices = await client.get_devices()
        scenarios = await client.get_scenarios()
    except BadCredentialsException:
        _LOGGER.error("invalid_auth")
        return False
    except TooManyRequestsException as exception:
        _LOGGER.error("too_many_requests")
        raise ConfigEntryNotReady from exception
    except (TimeoutError, ClientError, ServerDisconnectedError) as exception:
        _LOGGER.error("cannot_connect")
        raise ConfigEntryNotReady from exception
    except MaintenanceException as exception:
        _LOGGER.error("server_in_maintenance")
        raise ConfigEntryNotReady from exception
    except Exception as exception:  # pylint: disable=broad-except
        _LOGGER.exception(exception)
        return False

    update_interval = entry.options.get(CONF_UPDATE_INTERVAL,
                                        DEFAULT_UPDATE_INTERVAL)

    tahoma_coordinator = TahomaDataUpdateCoordinator(
        hass,
        _LOGGER,
        name="TaHoma Event Fetcher",
        client=client,
        devices=devices,
        update_interval=timedelta(seconds=update_interval),
    )

    await tahoma_coordinator.async_refresh()

    entities = defaultdict(list)
    entities[SCENE] = scenarios

    hass.data[DOMAIN][entry.entry_id] = {
        "entities": entities,
        "coordinator": tahoma_coordinator,
        "update_listener": entry.add_update_listener(update_listener),
    }

    for device in tahoma_coordinator.data.values():
        platform = TAHOMA_TYPES.get(device.widget) or TAHOMA_TYPES.get(
            device.ui_class)
        if platform:
            entities[platform].append(device)
        elif (device.widget not in IGNORED_TAHOMA_TYPES
              and device.ui_class not in IGNORED_TAHOMA_TYPES):
            _LOGGER.debug(
                "Unsupported TaHoma device detected (%s - %s - %s)",
                device.controllable_name,
                device.ui_class,
                device.widget,
            )

    for platform in entities:
        hass.async_create_task(
            hass.config_entries.async_forward_entry_setup(entry, platform))

    async def handle_execute_command(call):
        """Handle execute command service."""
        entity_registry = await hass.helpers.entity_registry.async_get_registry(
        )
        entity = entity_registry.entities.get(call.data.get("entity_id"))
        await tahoma_coordinator.client.execute_command(
            entity.unique_id,
            Command(call.data.get("command"), call.data.get("args")),
            "Home Assistant Service",
        )

    hass.services.async_register(
        DOMAIN,
        SERVICE_EXECUTE_COMMAND,
        handle_execute_command,
        vol.Schema({
            vol.Required("entity_id"):
            cv.string,
            vol.Required("command"):
            cv.string,
            vol.Optional("args", default=[]):
            vol.All(cv.ensure_list, [vol.Any(str, int)]),
        }),
    )

    return True
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    """Set up TaHoma from a config entry."""
    hass.data.setdefault(DOMAIN, {})

    username = entry.data.get(CONF_USERNAME)
    password = entry.data.get(CONF_PASSWORD)
    server = SUPPORTED_SERVERS[entry.data.get(CONF_HUB, DEFAULT_HUB)]

    session = async_get_clientsession(hass)
    client = TahomaClient(
        username,
        password,
        session=session,
        api_url=server.endpoint,
    )

    try:
        await client.login()

        tasks = [
            client.get_devices(),
            client.get_scenarios(),
            client.get_gateways(),
            client.get_places(),
        ]
        devices, scenarios, gateways, places = await asyncio.gather(*tasks)
    except BadCredentialsException as exception:
        raise ConfigEntryAuthFailed from exception
    except TooManyRequestsException as exception:
        raise ConfigEntryNotReady(
            "Too many requests, try again later") from exception
    except (TimeoutError, ClientError, ServerDisconnectedError) as exception:
        raise ConfigEntryNotReady("Failed to connect") from exception
    except MaintenanceException as exception:
        raise ConfigEntryNotReady(
            "Server is down for maintenance") from exception
    except Exception as exception:  # pylint: disable=broad-except
        _LOGGER.exception(exception)
        return False

    update_interval = timedelta(seconds=entry.options.get(
        CONF_UPDATE_INTERVAL, DEFAULT_UPDATE_INTERVAL))

    coordinator = OverkizDataUpdateCoordinator(
        hass,
        _LOGGER,
        name="device events",
        client=client,
        devices=devices,
        places=places,
        update_interval=update_interval,
        config_entry_id=entry.entry_id,
    )

    _LOGGER.debug("Initialized DataUpdateCoordinator with %s interval.",
                  str(update_interval))

    await coordinator.async_refresh()

    platforms = defaultdict(list)
    platforms[SCENE] = scenarios

    hass.data[DOMAIN][entry.entry_id] = {
        "platforms": platforms,
        "coordinator": coordinator,
        "update_listener": entry.add_update_listener(update_listener),
    }

    # Map Overkiz device to Home Assistant platform
    for device in coordinator.data.values():
        platform = OVERKIZ_DEVICE_TO_PLATFORM.get(
            device.widget) or OVERKIZ_DEVICE_TO_PLATFORM.get(device.ui_class)
        if platform:
            platforms[platform].append(device)
            log_device("Added device", device)
        elif (device.widget not in IGNORED_OVERKIZ_DEVICES
              and device.ui_class not in IGNORED_OVERKIZ_DEVICES):
            log_device("Unsupported device detected", device)

        if device.widget == HOMEKIT_STACK:
            print_homekit_setup_code(device)

    supported_platforms = set(platforms.keys())

    # Sensor and Binary Sensor will be added dynamically, based on the device states
    # Switch will be added dynamically, based on device features (e.g. low speed cover switch)
    supported_platforms.update((BINARY_SENSOR, SENSOR, SWITCH))
    for platform in supported_platforms:
        hass.async_create_task(
            hass.config_entries.async_forward_entry_setup(entry, platform))

    device_registry = await dr.async_get_registry(hass)

    for gateway in gateways:
        _LOGGER.debug(
            "Added gateway (%s - %s - %s)",
            gateway.id,
            gateway.type,
            gateway.sub_type,
        )

        gateway_model = (beautify_name(gateway.sub_type.name) if isinstance(
            gateway.sub_type, Enum) else None)

        gateway_name = (f"{beautify_name(gateway.type.name)} hub"
                        if isinstance(gateway.type, Enum) else gateway.type)

        device_registry.async_get_or_create(
            config_entry_id=entry.entry_id,
            identifiers={(DOMAIN, gateway.id)},
            model=gateway_model,
            manufacturer=server.manufacturer,
            name=gateway_name,
            sw_version=gateway.connectivity.protocol_version,
        )

    async def handle_execute_command(call: ServiceCall):
        """Handle execute command service."""
        entity_registry = await hass.helpers.entity_registry.async_get_registry(
        )

        for entity_id in call.data.get("entity_id"):
            entity = entity_registry.entities.get(entity_id)

            try:
                await coordinator.client.execute_command(
                    entity.unique_id,
                    Command(call.data.get("command"), call.data.get("args")),
                    "Home Assistant Service",
                )
            except InvalidCommandException as exception:
                _LOGGER.error(exception)

    service.async_register_admin_service(
        hass,
        DOMAIN,
        SERVICE_EXECUTE_COMMAND,
        handle_execute_command,
        vol.Schema(
            {
                vol.Required("entity_id"): [cv.entity_id],
                vol.Required("command"):
                cv.string,
                vol.Optional("args", default=[]):
                vol.All(cv.ensure_list, [vol.Any(str, int)]),
            }, ),
    )

    async def handle_get_execution_history(call):
        """Handle get execution history service."""
        await write_execution_history_to_log(coordinator.client)

    service.async_register_admin_service(
        hass,
        DOMAIN,
        "get_execution_history",
        handle_get_execution_history,
    )

    return True