Пример #1
0
    async def _validate_data(self, config: dict[str, str]) -> str | None:
        """Validate input data and return any error."""
        await self.async_set_unique_id(config[CONF_USERNAME].lower())
        self._abort_if_unique_id_configured()

        eight = EightSleep(
            config[CONF_USERNAME],
            config[CONF_PASSWORD],
            self.hass.config.time_zone,
            client_session=async_get_clientsession(self.hass),
        )

        try:
            await eight.fetch_token()
        except RequestError as err:
            return str(err)

        return None
Пример #2
0
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up the Eight Sleep component."""

    if DOMAIN not in config:
        return True

    conf = config[DOMAIN]
    user = conf[CONF_USERNAME]
    password = conf[CONF_PASSWORD]

    if hass.config.time_zone is None:
        _LOGGER.error("Timezone is not set in Home Assistant")
        return False

    timezone = str(hass.config.time_zone)

    eight = EightSleep(user, password, timezone, async_get_clientsession(hass))

    hass.data.setdefault(DATA_EIGHT, {})[DATA_API] = eight

    # Authenticate, build sensors
    success = await eight.start()
    if not success:
        # Authentication failed, cannot continue
        return False

    heat_coordinator = hass.data[DOMAIN][
        DATA_HEAT] = EightSleepHeatDataCoordinator(hass, eight)
    user_coordinator = hass.data[DOMAIN][
        DATA_USER] = EightSleepUserDataCoordinator(hass, eight)
    await heat_coordinator.async_config_entry_first_refresh()
    await user_coordinator.async_config_entry_first_refresh()

    # Load sub components
    sensors = []
    binary_sensors = []
    if eight.users:
        for user, obj in eight.users.items():
            for sensor in SENSORS:
                sensors.append((obj.side, sensor))
            binary_sensors.append((obj.side, "bed_presence"))
        sensors.append((None, "room_temperature"))
    else:
        # No users, cannot continue
        return False

    hass.async_create_task(
        discovery.async_load_platform(hass, Platform.SENSOR, DOMAIN,
                                      {CONF_SENSORS: sensors}, config))

    hass.async_create_task(
        discovery.async_load_platform(
            hass,
            Platform.BINARY_SENSOR,
            DOMAIN,
            {CONF_BINARY_SENSORS: binary_sensors},
            config,
        ))

    async def async_service_handler(service: ServiceCall) -> None:
        """Handle eight sleep service calls."""
        params = service.data.copy()

        sensor = params.pop(ATTR_ENTITY_ID, None)
        target = params.pop(ATTR_TARGET_HEAT, None)
        duration = params.pop(ATTR_HEAT_DURATION, 0)

        for sens in sensor:
            side = sens.split("_")[1]
            userid = eight.fetch_userid(side)
            usrobj = eight.users[userid]
            await usrobj.set_heating_level(target, duration)

        await heat_coordinator.async_request_refresh()

    # Register services
    hass.services.async_register(DOMAIN,
                                 SERVICE_HEAT_SET,
                                 async_service_handler,
                                 schema=SERVICE_EIGHT_SCHEMA)

    return True
Пример #3
0
def async_setup(hass, config):
    """Set up the Eight Sleep component."""
    from pyeight.eight import EightSleep

    conf = config.get(DOMAIN)
    user = conf.get(CONF_USERNAME)
    password = conf.get(CONF_PASSWORD)
    partner = conf.get(CONF_PARTNER)

    if hass.config.time_zone is None:
        _LOGGER.error('Timezone is not set in Home Assistant.')
        return False

    timezone = hass.config.time_zone

    eight = EightSleep(user, password, timezone, partner, None, hass.loop)

    hass.data[DATA_EIGHT] = eight

    # Authenticate, build sensors
    success = yield from eight.start()
    if not success:
        # Authentication failed, cannot continue
        return False

    @asyncio.coroutine
    def async_update_heat_data(now):
        """Update heat data from eight in HEAT_SCAN_INTERVAL."""
        yield from eight.update_device_data()
        async_dispatcher_send(hass, SIGNAL_UPDATE_HEAT)

        async_track_point_in_utc_time(hass, async_update_heat_data,
                                      utcnow() + HEAT_SCAN_INTERVAL)

    @asyncio.coroutine
    def async_update_user_data(now):
        """Update user data from eight in USER_SCAN_INTERVAL."""
        yield from eight.update_user_data()
        async_dispatcher_send(hass, SIGNAL_UPDATE_USER)

        async_track_point_in_utc_time(hass, async_update_user_data,
                                      utcnow() + USER_SCAN_INTERVAL)

    yield from async_update_heat_data(None)
    yield from async_update_user_data(None)

    # Load sub components
    sensors = []
    binary_sensors = []
    if eight.users:
        for user in eight.users:
            obj = eight.users[user]
            for sensor in SENSORS:
                sensors.append('{}_{}'.format(obj.side, sensor))
            binary_sensors.append('{}_presence'.format(obj.side))
        sensors.append('room_temp')
    else:
        # No users, cannot continue
        return False

    hass.async_add_job(
        discovery.async_load_platform(hass, 'sensor', DOMAIN, {
            CONF_SENSORS: sensors,
        }, config))

    hass.async_add_job(
        discovery.async_load_platform(hass, 'binary_sensor', DOMAIN, {
            CONF_BINARY_SENSORS: binary_sensors,
        }, config))

    @asyncio.coroutine
    def async_service_handler(service):
        """Handle eight sleep service calls."""
        params = service.data.copy()

        sensor = params.pop(ATTR_ENTITY_ID, None)
        target = params.pop(ATTR_TARGET_HEAT, None)
        duration = params.pop(ATTR_HEAT_DURATION, 0)

        for sens in sensor:
            side = sens.split('_')[1]
            userid = eight.fetch_userid(side)
            usrobj = eight.users[userid]
            yield from usrobj.set_heating_level(target, duration)

        async_dispatcher_send(hass, SIGNAL_UPDATE_HEAT)

    # Register services
    hass.services.async_register(DOMAIN,
                                 SERVICE_HEAT_SET,
                                 async_service_handler,
                                 schema=SERVICE_EIGHT_SCHEMA)

    @asyncio.coroutine
    def stop_eight(event):
        """Handle stopping eight api session."""
        yield from eight.stop()

    hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_eight)

    return True
Пример #4
0
def async_setup(hass, config):
    """Set up the Eight Sleep component."""
    from pyeight.eight import EightSleep

    conf = config.get(DOMAIN)
    user = conf.get(CONF_USERNAME)
    password = conf.get(CONF_PASSWORD)
    partner = conf.get(CONF_PARTNER)

    if hass.config.time_zone is None:
        _LOGGER.error('Timezone is not set in Home Assistant.')
        return False

    timezone = hass.config.time_zone

    eight = EightSleep(user, password, timezone, partner, None, hass.loop)

    hass.data[DATA_EIGHT] = eight

    # Authenticate, build sensors
    success = yield from eight.start()
    if not success:
        # Authentication failed, cannot continue
        return False

    @asyncio.coroutine
    def async_update_heat_data(now):
        """Update heat data from eight in HEAT_SCAN_INTERVAL."""
        yield from eight.update_device_data()
        async_dispatcher_send(hass, SIGNAL_UPDATE_HEAT)

        async_track_point_in_utc_time(
            hass, async_update_heat_data, utcnow() + HEAT_SCAN_INTERVAL)

    @asyncio.coroutine
    def async_update_user_data(now):
        """Update user data from eight in USER_SCAN_INTERVAL."""
        yield from eight.update_user_data()
        async_dispatcher_send(hass, SIGNAL_UPDATE_USER)

        async_track_point_in_utc_time(
            hass, async_update_user_data, utcnow() + USER_SCAN_INTERVAL)

    yield from async_update_heat_data(None)
    yield from async_update_user_data(None)

    # Load sub components
    sensors = []
    binary_sensors = []
    if eight.users:
        for user in eight.users:
            obj = eight.users[user]
            for sensor in SENSORS:
                sensors.append('{}_{}'.format(obj.side, sensor))
            binary_sensors.append('{}_presence'.format(obj.side))
        sensors.append('room_temp')
    else:
        # No users, cannot continue
        return False

    hass.async_add_job(discovery.async_load_platform(
        hass, 'sensor', DOMAIN, {
            CONF_SENSORS: sensors,
        }, config))

    hass.async_add_job(discovery.async_load_platform(
        hass, 'binary_sensor', DOMAIN, {
            CONF_BINARY_SENSORS: binary_sensors,
        }, config))

    descriptions = yield from hass.async_add_job(
        load_yaml_config_file,
        os.path.join(os.path.dirname(__file__), 'services.yaml'))

    @asyncio.coroutine
    def async_service_handler(service):
        """Handle eight sleep service calls."""
        params = service.data.copy()

        sensor = params.pop(ATTR_ENTITY_ID, None)
        target = params.pop(ATTR_TARGET_HEAT, None)
        duration = params.pop(ATTR_HEAT_DURATION, 0)

        for sens in sensor:
            side = sens.split('_')[1]
            userid = eight.fetch_userid(side)
            usrobj = eight.users[userid]
            yield from usrobj.set_heating_level(target, duration)

        async_dispatcher_send(hass, SIGNAL_UPDATE_HEAT)

    # Register services
    hass.services.async_register(
        DOMAIN, SERVICE_HEAT_SET, async_service_handler,
        descriptions[DOMAIN].get(SERVICE_HEAT_SET),
        schema=SERVICE_EIGHT_SCHEMA)

    @asyncio.coroutine
    def stop_eight(event):
        """Handle stopping eight api session."""
        yield from eight.stop()

    hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_eight)

    return True
Пример #5
0
async def async_setup(hass, config):
    """Set up the Eight Sleep component."""

    conf = config.get(DOMAIN)
    user = conf.get(CONF_USERNAME)
    password = conf.get(CONF_PASSWORD)

    if hass.config.time_zone is None:
        _LOGGER.error("Timezone is not set in Home Assistant")
        return False

    timezone = str(hass.config.time_zone)

    eight = EightSleep(user, password, timezone, async_get_clientsession(hass))

    hass.data[DATA_EIGHT] = eight

    # Authenticate, build sensors
    success = await eight.start()
    if not success:
        # Authentication failed, cannot continue
        return False

    async def async_update_heat_data(now):
        """Update heat data from eight in HEAT_SCAN_INTERVAL."""
        await eight.update_device_data()
        async_dispatcher_send(hass, SIGNAL_UPDATE_HEAT)

        async_track_point_in_utc_time(hass, async_update_heat_data,
                                      utcnow() + HEAT_SCAN_INTERVAL)

    async def async_update_user_data(now):
        """Update user data from eight in USER_SCAN_INTERVAL."""
        await eight.update_user_data()
        async_dispatcher_send(hass, SIGNAL_UPDATE_USER)

        async_track_point_in_utc_time(hass, async_update_user_data,
                                      utcnow() + USER_SCAN_INTERVAL)

    await async_update_heat_data(None)
    await async_update_user_data(None)

    # Load sub components
    sensors = []
    binary_sensors = []
    if eight.users:
        for obj in eight.users.values():
            for sensor in SENSORS:
                sensors.append(f"{obj.side}_{sensor}")
            binary_sensors.append(f"{obj.side}_presence")
        sensors.append("room_temp")
    else:
        # No users, cannot continue
        return False

    hass.async_create_task(
        discovery.async_load_platform(hass, "sensor", DOMAIN,
                                      {CONF_SENSORS: sensors}, config))

    hass.async_create_task(
        discovery.async_load_platform(hass, "binary_sensor", DOMAIN,
                                      {CONF_BINARY_SENSORS: binary_sensors},
                                      config))

    async def async_service_handler(service):
        """Handle eight sleep service calls."""
        params = service.data.copy()

        sensor = params.pop(ATTR_ENTITY_ID, None)
        target = params.pop(ATTR_TARGET_HEAT, None)
        duration = params.pop(ATTR_HEAT_DURATION, 0)

        for sens in sensor:
            side = sens.split("_")[1]
            userid = eight.fetch_userid(side)
            usrobj = eight.users[userid]
            await usrobj.set_heating_level(target, duration)

        async_dispatcher_send(hass, SIGNAL_UPDATE_HEAT)

    # Register services
    hass.services.async_register(DOMAIN,
                                 SERVICE_HEAT_SET,
                                 async_service_handler,
                                 schema=SERVICE_EIGHT_SCHEMA)

    return True
Пример #6
0
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    """Set up the Eight Sleep config entry."""
    eight = EightSleep(
        entry.data[CONF_USERNAME],
        entry.data[CONF_PASSWORD],
        hass.config.time_zone,
        async_get_clientsession(hass),
    )

    # Authenticate, build sensors
    try:
        success = await eight.start()
    except RequestError as err:
        raise ConfigEntryNotReady from err
    if not success:
        # Authentication failed, cannot continue
        return False

    heat_coordinator: DataUpdateCoordinator = DataUpdateCoordinator(
        hass,
        _LOGGER,
        name=f"{DOMAIN}_heat",
        update_interval=HEAT_SCAN_INTERVAL,
        update_method=eight.update_device_data,
    )
    user_coordinator: DataUpdateCoordinator = DataUpdateCoordinator(
        hass,
        _LOGGER,
        name=f"{DOMAIN}_user",
        update_interval=USER_SCAN_INTERVAL,
        update_method=eight.update_user_data,
    )
    await heat_coordinator.async_config_entry_first_refresh()
    await user_coordinator.async_config_entry_first_refresh()

    if not eight.users:
        # No users, cannot continue
        return False

    dev_reg = async_get(hass)
    assert eight.device_data
    device_data = {
        ATTR_MANUFACTURER:
        "Eight Sleep",
        ATTR_MODEL:
        eight.device_data.get("modelString", UNDEFINED),
        ATTR_HW_VERSION:
        eight.device_data.get("sensorInfo", {}).get("hwRevision", UNDEFINED),
        ATTR_SW_VERSION:
        eight.device_data.get("firmwareVersion", UNDEFINED),
    }
    dev_reg.async_get_or_create(
        config_entry_id=entry.entry_id,
        identifiers={(DOMAIN, _get_device_unique_id(eight))},
        name=f"{entry.data[CONF_USERNAME]}'s Eight Sleep",
        **device_data,
    )
    for user in eight.users.values():
        assert user.user_profile
        dev_reg.async_get_or_create(
            config_entry_id=entry.entry_id,
            identifiers={(DOMAIN, _get_device_unique_id(eight, user))},
            name=f"{user.user_profile['firstName']}'s Eight Sleep Side",
            via_device=(DOMAIN, _get_device_unique_id(eight)),
            **device_data,
        )

    hass.data.setdefault(DOMAIN,
                         {})[entry.entry_id] = EightSleepConfigEntryData(
                             eight, heat_coordinator, user_coordinator)

    hass.config_entries.async_setup_platforms(entry, PLATFORMS)

    return True
Пример #7
0
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
    """Set up the Eight Sleep component."""

    if DOMAIN not in config:
        return True

    conf = config[DOMAIN]
    user = conf[CONF_USERNAME]
    password = conf[CONF_PASSWORD]

    eight = EightSleep(user, password, hass.config.time_zone,
                       async_get_clientsession(hass))

    hass.data.setdefault(DOMAIN, {})

    # Authenticate, build sensors
    success = await eight.start()
    if not success:
        # Authentication failed, cannot continue
        return False

    heat_coordinator: DataUpdateCoordinator = DataUpdateCoordinator(
        hass,
        _LOGGER,
        name=f"{DOMAIN}_heat",
        update_interval=HEAT_SCAN_INTERVAL,
        update_method=eight.update_device_data,
    )
    user_coordinator: DataUpdateCoordinator = DataUpdateCoordinator(
        hass,
        _LOGGER,
        name=f"{DOMAIN}_user",
        update_interval=USER_SCAN_INTERVAL,
        update_method=eight.update_user_data,
    )
    await heat_coordinator.async_config_entry_first_refresh()
    await user_coordinator.async_config_entry_first_refresh()

    if not eight.users:
        # No users, cannot continue
        return False

    hass.data[DOMAIN] = {
        DATA_API: eight,
        DATA_HEAT: heat_coordinator,
        DATA_USER: user_coordinator,
    }

    for platform in PLATFORMS:
        hass.async_create_task(
            discovery.async_load_platform(hass, platform, DOMAIN, {}, config))

    async def async_service_handler(service: ServiceCall) -> None:
        """Handle eight sleep service calls."""
        params = service.data.copy()

        sensor = params.pop(ATTR_ENTITY_ID, None)
        target = params.pop(ATTR_TARGET_HEAT, None)
        duration = params.pop(ATTR_HEAT_DURATION, 0)

        for sens in sensor:
            side = sens.split("_")[1]
            userid = eight.fetch_userid(side)
            usrobj = eight.users[userid]
            await usrobj.set_heating_level(target, duration)

        await heat_coordinator.async_request_refresh()

    # Register services
    hass.services.async_register(DOMAIN,
                                 SERVICE_HEAT_SET,
                                 async_service_handler,
                                 schema=SERVICE_EIGHT_SCHEMA)

    return True