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
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
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
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
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
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
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