mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 10:47:10 +00:00
Cleanup eight_sleep (#69171)
* Cleanup eight_sleep * Only set data after checking for users
This commit is contained in:
parent
d01666f3a2
commit
0360613ddd
@ -3,20 +3,12 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
from typing import Union
|
|
||||||
|
|
||||||
from pyeight.eight import EightSleep
|
from pyeight.eight import EightSleep
|
||||||
from pyeight.user import EightUser
|
from pyeight.user import EightUser
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import ATTR_ENTITY_ID, CONF_PASSWORD, CONF_USERNAME, Platform
|
||||||
ATTR_ENTITY_ID,
|
|
||||||
CONF_BINARY_SENSORS,
|
|
||||||
CONF_PASSWORD,
|
|
||||||
CONF_SENSORS,
|
|
||||||
CONF_USERNAME,
|
|
||||||
Platform,
|
|
||||||
)
|
|
||||||
from homeassistant.core import HomeAssistant, ServiceCall
|
from homeassistant.core import HomeAssistant, ServiceCall
|
||||||
from homeassistant.helpers import discovery
|
from homeassistant.helpers import discovery
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
@ -27,44 +19,24 @@ from homeassistant.helpers.update_coordinator import (
|
|||||||
DataUpdateCoordinator,
|
DataUpdateCoordinator,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from .const import (
|
||||||
|
ATTR_HEAT_DURATION,
|
||||||
|
ATTR_TARGET_HEAT,
|
||||||
|
DATA_API,
|
||||||
|
DATA_HEAT,
|
||||||
|
DATA_USER,
|
||||||
|
DOMAIN,
|
||||||
|
NAME_MAP,
|
||||||
|
SERVICE_HEAT_SET,
|
||||||
|
)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DATA_EIGHT = "eight_sleep"
|
PLATFORMS = [Platform.BINARY_SENSOR, Platform.SENSOR]
|
||||||
DATA_HEAT = "heat"
|
|
||||||
DATA_USER = "user"
|
|
||||||
DATA_API = "api"
|
|
||||||
DOMAIN = "eight_sleep"
|
|
||||||
|
|
||||||
HEAT_ENTITY = "heat"
|
|
||||||
USER_ENTITY = "user"
|
|
||||||
|
|
||||||
|
|
||||||
HEAT_SCAN_INTERVAL = timedelta(seconds=60)
|
HEAT_SCAN_INTERVAL = timedelta(seconds=60)
|
||||||
USER_SCAN_INTERVAL = timedelta(seconds=300)
|
USER_SCAN_INTERVAL = timedelta(seconds=300)
|
||||||
|
|
||||||
NAME_MAP = {
|
|
||||||
"left_current_sleep": "Left Sleep Session",
|
|
||||||
"left_current_sleep_fitness": "Left Sleep Fitness",
|
|
||||||
"left_last_sleep": "Left Previous Sleep Session",
|
|
||||||
"right_current_sleep": "Right Sleep Session",
|
|
||||||
"right_current_sleep_fitness": "Right Sleep Fitness",
|
|
||||||
"right_last_sleep": "Right Previous Sleep Session",
|
|
||||||
}
|
|
||||||
|
|
||||||
SENSORS = [
|
|
||||||
"current_sleep",
|
|
||||||
"current_sleep_fitness",
|
|
||||||
"last_sleep",
|
|
||||||
"bed_state",
|
|
||||||
"bed_temperature",
|
|
||||||
"sleep_stage",
|
|
||||||
]
|
|
||||||
|
|
||||||
SERVICE_HEAT_SET = "heat_set"
|
|
||||||
|
|
||||||
ATTR_TARGET_HEAT = "target"
|
|
||||||
ATTR_HEAT_DURATION = "duration"
|
|
||||||
|
|
||||||
VALID_TARGET_HEAT = vol.All(vol.Coerce(int), vol.Clamp(min=-100, max=100))
|
VALID_TARGET_HEAT = vol.All(vol.Coerce(int), vol.Clamp(min=-100, max=100))
|
||||||
VALID_DURATION = vol.All(vol.Coerce(int), vol.Clamp(min=0, max=28800))
|
VALID_DURATION = vol.All(vol.Coerce(int), vol.Clamp(min=0, max=28800))
|
||||||
|
|
||||||
@ -107,15 +79,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
user = conf[CONF_USERNAME]
|
user = conf[CONF_USERNAME]
|
||||||
password = conf[CONF_PASSWORD]
|
password = conf[CONF_PASSWORD]
|
||||||
|
|
||||||
if hass.config.time_zone is None:
|
eight = EightSleep(
|
||||||
_LOGGER.error("Timezone is not set in Home Assistant")
|
user, password, hass.config.time_zone, async_get_clientsession(hass)
|
||||||
return False
|
)
|
||||||
|
|
||||||
timezone = str(hass.config.time_zone)
|
hass.data.setdefault(DOMAIN, {})
|
||||||
|
|
||||||
eight = EightSleep(user, password, timezone, async_get_clientsession(hass))
|
|
||||||
|
|
||||||
hass.data.setdefault(DATA_EIGHT, {})[DATA_API] = eight
|
|
||||||
|
|
||||||
# Authenticate, build sensors
|
# Authenticate, build sensors
|
||||||
success = await eight.start()
|
success = await eight.start()
|
||||||
@ -123,43 +91,37 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
# Authentication failed, cannot continue
|
# Authentication failed, cannot continue
|
||||||
return False
|
return False
|
||||||
|
|
||||||
heat_coordinator = hass.data[DOMAIN][DATA_HEAT] = EightSleepHeatDataCoordinator(
|
heat_coordinator: DataUpdateCoordinator = DataUpdateCoordinator(
|
||||||
hass, eight
|
hass,
|
||||||
|
_LOGGER,
|
||||||
|
name=f"{DOMAIN}_heat",
|
||||||
|
update_interval=HEAT_SCAN_INTERVAL,
|
||||||
|
update_method=eight.update_device_data,
|
||||||
)
|
)
|
||||||
user_coordinator = hass.data[DOMAIN][DATA_USER] = EightSleepUserDataCoordinator(
|
user_coordinator: DataUpdateCoordinator = DataUpdateCoordinator(
|
||||||
hass, eight
|
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 heat_coordinator.async_config_entry_first_refresh()
|
||||||
await user_coordinator.async_config_entry_first_refresh()
|
await user_coordinator.async_config_entry_first_refresh()
|
||||||
|
|
||||||
# Load sub components
|
if not eight.users:
|
||||||
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
|
# No users, cannot continue
|
||||||
return False
|
return False
|
||||||
|
|
||||||
hass.async_create_task(
|
hass.data[DOMAIN] = {
|
||||||
discovery.async_load_platform(
|
DATA_API: eight,
|
||||||
hass, Platform.SENSOR, DOMAIN, {CONF_SENSORS: sensors}, config
|
DATA_HEAT: heat_coordinator,
|
||||||
)
|
DATA_USER: user_coordinator,
|
||||||
)
|
}
|
||||||
|
|
||||||
hass.async_create_task(
|
for platform in PLATFORMS:
|
||||||
discovery.async_load_platform(
|
hass.async_create_task(
|
||||||
hass,
|
discovery.async_load_platform(hass, platform, DOMAIN, {}, config)
|
||||||
Platform.BINARY_SENSOR,
|
|
||||||
DOMAIN,
|
|
||||||
{CONF_BINARY_SENSORS: binary_sensors},
|
|
||||||
config,
|
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
async def async_service_handler(service: ServiceCall) -> None:
|
async def async_service_handler(service: ServiceCall) -> None:
|
||||||
"""Handle eight sleep service calls."""
|
"""Handle eight sleep service calls."""
|
||||||
@ -185,88 +147,32 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class EightSleepHeatDataCoordinator(DataUpdateCoordinator):
|
class EightSleepBaseEntity(CoordinatorEntity[DataUpdateCoordinator]):
|
||||||
"""Class to retrieve heat data from Eight Sleep."""
|
|
||||||
|
|
||||||
def __init__(self, hass: HomeAssistant, api: EightSleep) -> None:
|
|
||||||
"""Initialize coordinator."""
|
|
||||||
self.api = api
|
|
||||||
super().__init__(
|
|
||||||
hass,
|
|
||||||
_LOGGER,
|
|
||||||
name=f"{DOMAIN}_heat",
|
|
||||||
update_interval=HEAT_SCAN_INTERVAL,
|
|
||||||
)
|
|
||||||
|
|
||||||
async def _async_update_data(self) -> None:
|
|
||||||
await self.api.update_device_data()
|
|
||||||
|
|
||||||
|
|
||||||
class EightSleepUserDataCoordinator(DataUpdateCoordinator):
|
|
||||||
"""Class to retrieve user data from Eight Sleep."""
|
|
||||||
|
|
||||||
def __init__(self, hass: HomeAssistant, api: EightSleep) -> None:
|
|
||||||
"""Initialize coordinator."""
|
|
||||||
self.api = api
|
|
||||||
super().__init__(
|
|
||||||
hass,
|
|
||||||
_LOGGER,
|
|
||||||
name=f"{DOMAIN}_user",
|
|
||||||
update_interval=USER_SCAN_INTERVAL,
|
|
||||||
)
|
|
||||||
|
|
||||||
async def _async_update_data(self) -> None:
|
|
||||||
await self.api.update_user_data()
|
|
||||||
|
|
||||||
|
|
||||||
class EightSleepBaseEntity(
|
|
||||||
CoordinatorEntity[
|
|
||||||
Union[EightSleepUserDataCoordinator, EightSleepHeatDataCoordinator]
|
|
||||||
]
|
|
||||||
):
|
|
||||||
"""The base Eight Sleep entity class."""
|
"""The base Eight Sleep entity class."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
name: str,
|
coordinator: DataUpdateCoordinator,
|
||||||
coordinator: EightSleepUserDataCoordinator | EightSleepHeatDataCoordinator,
|
|
||||||
eight: EightSleep,
|
eight: EightSleep,
|
||||||
side: str | None,
|
user_id: str | None,
|
||||||
sensor: str,
|
sensor: str,
|
||||||
|
units: str | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the data object."""
|
"""Initialize the data object."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
self._eight = eight
|
self._eight = eight
|
||||||
self._side = side
|
self._user_id = user_id
|
||||||
self._sensor = sensor
|
self._sensor = sensor
|
||||||
self._usrobj: EightUser | None = None
|
|
||||||
if self._side:
|
|
||||||
self._usrobj = self._eight.users[self._eight.fetch_userid(self._side)]
|
|
||||||
full_sensor_name = self._sensor
|
|
||||||
if self._side is not None:
|
|
||||||
full_sensor_name = f"{self._side}_{full_sensor_name}"
|
|
||||||
mapped_name = NAME_MAP.get(
|
|
||||||
full_sensor_name, full_sensor_name.replace("_", " ").title()
|
|
||||||
)
|
|
||||||
|
|
||||||
self._attr_name = f"{name} {mapped_name}"
|
|
||||||
self._attr_unique_id = (
|
|
||||||
f"{_get_device_unique_id(eight, self._usrobj)}.{self._sensor}"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class EightSleepUserEntity(EightSleepBaseEntity):
|
|
||||||
"""The Eight Sleep user entity."""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
name: str,
|
|
||||||
coordinator: EightSleepUserDataCoordinator,
|
|
||||||
eight: EightSleep,
|
|
||||||
side: str | None,
|
|
||||||
sensor: str,
|
|
||||||
units: str,
|
|
||||||
) -> None:
|
|
||||||
"""Initialize the data object."""
|
|
||||||
super().__init__(name, coordinator, eight, side, sensor)
|
|
||||||
self._units = units
|
self._units = units
|
||||||
|
self._user_obj: EightUser | None = None
|
||||||
|
if self._user_id:
|
||||||
|
self._user_obj = self._eight.users[user_id]
|
||||||
|
|
||||||
|
mapped_name = NAME_MAP.get(sensor, sensor.replace("_", " ").title())
|
||||||
|
if self._user_obj is not None:
|
||||||
|
mapped_name = f"{self._user_obj.side.title()} {mapped_name}"
|
||||||
|
|
||||||
|
self._attr_name = f"Eight {mapped_name}"
|
||||||
|
self._attr_unique_id = (
|
||||||
|
f"{_get_device_unique_id(eight, self._user_obj)}.{sensor}"
|
||||||
|
)
|
||||||
|
@ -12,15 +12,10 @@ from homeassistant.components.binary_sensor import (
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||||
|
|
||||||
from . import (
|
from . import EightSleepBaseEntity
|
||||||
CONF_BINARY_SENSORS,
|
from .const import DATA_API, DATA_HEAT, DOMAIN
|
||||||
DATA_API,
|
|
||||||
DATA_EIGHT,
|
|
||||||
DATA_HEAT,
|
|
||||||
EightSleepBaseEntity,
|
|
||||||
EightSleepHeatDataCoordinator,
|
|
||||||
)
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -35,17 +30,16 @@ async def async_setup_platform(
|
|||||||
if discovery_info is None:
|
if discovery_info is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
name = "Eight"
|
eight: EightSleep = hass.data[DOMAIN][DATA_API]
|
||||||
sensors = discovery_info[CONF_BINARY_SENSORS]
|
heat_coordinator: DataUpdateCoordinator = hass.data[DOMAIN][DATA_HEAT]
|
||||||
eight: EightSleep = hass.data[DATA_EIGHT][DATA_API]
|
|
||||||
heat_coordinator: EightSleepHeatDataCoordinator = hass.data[DATA_EIGHT][DATA_HEAT]
|
|
||||||
|
|
||||||
all_sensors = [
|
entities = []
|
||||||
EightHeatSensor(name, heat_coordinator, eight, side, sensor)
|
for user in eight.users.values():
|
||||||
for side, sensor in sensors
|
entities.append(
|
||||||
]
|
EightHeatSensor(heat_coordinator, eight, user.userid, "bed_presence")
|
||||||
|
)
|
||||||
|
|
||||||
async_add_entities(all_sensors)
|
async_add_entities(entities)
|
||||||
|
|
||||||
|
|
||||||
class EightHeatSensor(EightSleepBaseEntity, BinarySensorEntity):
|
class EightHeatSensor(EightSleepBaseEntity, BinarySensorEntity):
|
||||||
@ -53,25 +47,24 @@ class EightHeatSensor(EightSleepBaseEntity, BinarySensorEntity):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
name: str,
|
coordinator: DataUpdateCoordinator,
|
||||||
coordinator: EightSleepHeatDataCoordinator,
|
|
||||||
eight: EightSleep,
|
eight: EightSleep,
|
||||||
side: str | None,
|
user_id: str | None,
|
||||||
sensor: str,
|
sensor: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the sensor."""
|
"""Initialize the sensor."""
|
||||||
super().__init__(name, coordinator, eight, side, sensor)
|
super().__init__(coordinator, eight, user_id, sensor)
|
||||||
self._attr_device_class = BinarySensorDeviceClass.OCCUPANCY
|
self._attr_device_class = BinarySensorDeviceClass.OCCUPANCY
|
||||||
assert self._usrobj
|
assert self._user_obj
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Presence Sensor: %s, Side: %s, User: %s",
|
"Presence Sensor: %s, Side: %s, User: %s",
|
||||||
self._sensor,
|
sensor,
|
||||||
self._side,
|
self._user_obj.side,
|
||||||
self._usrobj.userid,
|
user_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self) -> bool:
|
def is_on(self) -> bool:
|
||||||
"""Return true if the binary sensor is on."""
|
"""Return true if the binary sensor is on."""
|
||||||
assert self._usrobj
|
assert self._user_obj
|
||||||
return bool(self._usrobj.bed_presence)
|
return bool(self._user_obj.bed_presence)
|
||||||
|
19
homeassistant/components/eight_sleep/const.py
Normal file
19
homeassistant/components/eight_sleep/const.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
"""Eight Sleep constants."""
|
||||||
|
DATA_HEAT = "heat"
|
||||||
|
DATA_USER = "user"
|
||||||
|
DATA_API = "api"
|
||||||
|
DOMAIN = "eight_sleep"
|
||||||
|
|
||||||
|
HEAT_ENTITY = "heat"
|
||||||
|
USER_ENTITY = "user"
|
||||||
|
|
||||||
|
NAME_MAP = {
|
||||||
|
"current_sleep": "Sleep Session",
|
||||||
|
"current_sleep_fitness": "Sleep Fitness",
|
||||||
|
"last_sleep": "Previous Sleep Session",
|
||||||
|
}
|
||||||
|
|
||||||
|
SERVICE_HEAT_SET = "heat_set"
|
||||||
|
|
||||||
|
ATTR_TARGET_HEAT = "target"
|
||||||
|
ATTR_HEAT_DURATION = "duration"
|
@ -11,18 +11,10 @@ from homeassistant.const import PERCENTAGE, TEMP_CELSIUS, TEMP_FAHRENHEIT
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||||
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||||
|
|
||||||
from . import (
|
from . import EightSleepBaseEntity
|
||||||
CONF_SENSORS,
|
from .const import DATA_API, DATA_HEAT, DATA_USER, DOMAIN
|
||||||
DATA_API,
|
|
||||||
DATA_EIGHT,
|
|
||||||
DATA_HEAT,
|
|
||||||
DATA_USER,
|
|
||||||
EightSleepBaseEntity,
|
|
||||||
EightSleepHeatDataCoordinator,
|
|
||||||
EightSleepUserDataCoordinator,
|
|
||||||
EightSleepUserEntity,
|
|
||||||
)
|
|
||||||
|
|
||||||
ATTR_ROOM_TEMP = "Room Temperature"
|
ATTR_ROOM_TEMP = "Room Temperature"
|
||||||
ATTR_AVG_ROOM_TEMP = "Average Room Temperature"
|
ATTR_AVG_ROOM_TEMP = "Average Room Temperature"
|
||||||
@ -51,6 +43,16 @@ ATTR_FIT_WAKEUP_SCORE = "Fitness Wakeup Score"
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
EIGHT_USER_SENSORS = [
|
||||||
|
"current_sleep",
|
||||||
|
"current_sleep_fitness",
|
||||||
|
"last_sleep",
|
||||||
|
"bed_temperature",
|
||||||
|
"sleep_stage",
|
||||||
|
]
|
||||||
|
EIGHT_HEAT_SENSORS = ["bed_state"]
|
||||||
|
EIGHT_ROOM_SENSORS = ["room_temperature"]
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(
|
async def async_setup_platform(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
@ -62,11 +64,9 @@ async def async_setup_platform(
|
|||||||
if discovery_info is None:
|
if discovery_info is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
name = "Eight"
|
eight: EightSleep = hass.data[DOMAIN][DATA_API]
|
||||||
sensors = discovery_info[CONF_SENSORS]
|
heat_coordinator: DataUpdateCoordinator = hass.data[DOMAIN][DATA_HEAT]
|
||||||
eight: EightSleep = hass.data[DATA_EIGHT][DATA_API]
|
user_coordinator: DataUpdateCoordinator = hass.data[DOMAIN][DATA_USER]
|
||||||
heat_coordinator: EightSleepHeatDataCoordinator = hass.data[DATA_EIGHT][DATA_HEAT]
|
|
||||||
user_coordinator: EightSleepUserDataCoordinator = hass.data[DATA_EIGHT][DATA_USER]
|
|
||||||
|
|
||||||
if hass.config.units.is_metric:
|
if hass.config.units.is_metric:
|
||||||
units = "si"
|
units = "si"
|
||||||
@ -75,19 +75,17 @@ async def async_setup_platform(
|
|||||||
|
|
||||||
all_sensors: list[SensorEntity] = []
|
all_sensors: list[SensorEntity] = []
|
||||||
|
|
||||||
for side, sensor in sensors:
|
for obj in eight.users.values():
|
||||||
if sensor == "bed_state":
|
for sensor in EIGHT_USER_SENSORS:
|
||||||
all_sensors.append(
|
all_sensors.append(
|
||||||
EightHeatSensor(name, heat_coordinator, eight, side, sensor)
|
EightUserSensor(user_coordinator, eight, obj.userid, sensor, units)
|
||||||
)
|
)
|
||||||
elif sensor == "room_temperature":
|
for sensor in EIGHT_HEAT_SENSORS:
|
||||||
all_sensors.append(
|
all_sensors.append(
|
||||||
EightRoomSensor(name, user_coordinator, eight, side, sensor, units)
|
EightHeatSensor(heat_coordinator, eight, obj.userid, sensor)
|
||||||
)
|
|
||||||
else:
|
|
||||||
all_sensors.append(
|
|
||||||
EightUserSensor(name, user_coordinator, eight, side, sensor, units)
|
|
||||||
)
|
)
|
||||||
|
for sensor in EIGHT_ROOM_SENSORS:
|
||||||
|
all_sensors.append(EightRoomSensor(user_coordinator, eight, sensor, units))
|
||||||
|
|
||||||
async_add_entities(all_sensors)
|
async_add_entities(all_sensors)
|
||||||
|
|
||||||
@ -97,38 +95,37 @@ class EightHeatSensor(EightSleepBaseEntity, SensorEntity):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
name: str,
|
coordinator: DataUpdateCoordinator,
|
||||||
coordinator: EightSleepHeatDataCoordinator,
|
|
||||||
eight: EightSleep,
|
eight: EightSleep,
|
||||||
side: str | None,
|
user_id: str,
|
||||||
sensor: str,
|
sensor: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the sensor."""
|
"""Initialize the sensor."""
|
||||||
super().__init__(name, coordinator, eight, side, sensor)
|
super().__init__(coordinator, eight, user_id, sensor)
|
||||||
self._attr_native_unit_of_measurement = PERCENTAGE
|
self._attr_native_unit_of_measurement = PERCENTAGE
|
||||||
assert self._usrobj
|
assert self._user_obj
|
||||||
|
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"Heat Sensor: %s, Side: %s, User: %s",
|
"Heat Sensor: %s, Side: %s, User: %s",
|
||||||
self._sensor,
|
self._sensor,
|
||||||
self._side,
|
self._user_obj.side,
|
||||||
self._usrobj.userid,
|
self._user_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def native_value(self) -> int:
|
def native_value(self) -> int:
|
||||||
"""Return the state of the sensor."""
|
"""Return the state of the sensor."""
|
||||||
assert self._usrobj
|
assert self._user_obj
|
||||||
return self._usrobj.heating_level
|
return self._user_obj.heating_level
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> dict[str, Any]:
|
def extra_state_attributes(self) -> dict[str, Any]:
|
||||||
"""Return device state attributes."""
|
"""Return device state attributes."""
|
||||||
assert self._usrobj
|
assert self._user_obj
|
||||||
return {
|
return {
|
||||||
ATTR_TARGET_HEAT: self._usrobj.target_heating_level,
|
ATTR_TARGET_HEAT: self._user_obj.target_heating_level,
|
||||||
ATTR_ACTIVE_HEAT: self._usrobj.now_heating,
|
ATTR_ACTIVE_HEAT: self._user_obj.now_heating,
|
||||||
ATTR_DURATION_HEAT: self._usrobj.heating_remaining,
|
ATTR_DURATION_HEAT: self._user_obj.heating_remaining,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -142,20 +139,20 @@ def _get_breakdown_percent(
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
class EightUserSensor(EightSleepUserEntity, SensorEntity):
|
class EightUserSensor(EightSleepBaseEntity, SensorEntity):
|
||||||
"""Representation of an eight sleep user-based sensor."""
|
"""Representation of an eight sleep user-based sensor."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
name: str,
|
coordinator: DataUpdateCoordinator,
|
||||||
coordinator: EightSleepUserDataCoordinator,
|
|
||||||
eight: EightSleep,
|
eight: EightSleep,
|
||||||
side: str | None,
|
user_id: str,
|
||||||
sensor: str,
|
sensor: str,
|
||||||
units: str,
|
units: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the sensor."""
|
"""Initialize the sensor."""
|
||||||
super().__init__(name, coordinator, eight, side, sensor, units)
|
super().__init__(coordinator, eight, user_id, sensor, units)
|
||||||
|
assert self._user_obj
|
||||||
|
|
||||||
if self._sensor == "bed_temperature":
|
if self._sensor == "bed_temperature":
|
||||||
self._attr_icon = "mdi:thermometer"
|
self._attr_icon = "mdi:thermometer"
|
||||||
@ -163,26 +160,26 @@ class EightUserSensor(EightSleepUserEntity, SensorEntity):
|
|||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"User Sensor: %s, Side: %s, User: %s",
|
"User Sensor: %s, Side: %s, User: %s",
|
||||||
self._sensor,
|
self._sensor,
|
||||||
self._side,
|
self._user_obj.side,
|
||||||
self._usrobj.userid if self._usrobj else None,
|
self._user_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def native_value(self) -> str | int | float | None:
|
def native_value(self) -> str | int | float | None:
|
||||||
"""Return the state of the sensor."""
|
"""Return the state of the sensor."""
|
||||||
if not self._usrobj:
|
if not self._user_obj:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if "current" in self._sensor:
|
if "current" in self._sensor:
|
||||||
if "fitness" in self._sensor:
|
if "fitness" in self._sensor:
|
||||||
return self._usrobj.current_sleep_fitness_score
|
return self._user_obj.current_sleep_fitness_score
|
||||||
return self._usrobj.current_sleep_score
|
return self._user_obj.current_sleep_score
|
||||||
|
|
||||||
if "last" in self._sensor:
|
if "last" in self._sensor:
|
||||||
return self._usrobj.last_sleep_score
|
return self._user_obj.last_sleep_score
|
||||||
|
|
||||||
if self._sensor == "bed_temperature":
|
if self._sensor == "bed_temperature":
|
||||||
temp = self._usrobj.current_values["bed_temp"]
|
temp = self._user_obj.current_values["bed_temp"]
|
||||||
try:
|
try:
|
||||||
if self._units == "si":
|
if self._units == "si":
|
||||||
return round(temp, 2)
|
return round(temp, 2)
|
||||||
@ -191,7 +188,7 @@ class EightUserSensor(EightSleepUserEntity, SensorEntity):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
if self._sensor == "sleep_stage":
|
if self._sensor == "sleep_stage":
|
||||||
return self._usrobj.current_values["stage"]
|
return self._user_obj.current_values["stage"]
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -221,13 +218,13 @@ class EightUserSensor(EightSleepUserEntity, SensorEntity):
|
|||||||
def extra_state_attributes(self) -> dict[str, Any] | None:
|
def extra_state_attributes(self) -> dict[str, Any] | None:
|
||||||
"""Return device state attributes."""
|
"""Return device state attributes."""
|
||||||
attr = None
|
attr = None
|
||||||
if "current" in self._sensor and self._usrobj:
|
if "current" in self._sensor and self._user_obj:
|
||||||
if "fitness" in self._sensor:
|
if "fitness" in self._sensor:
|
||||||
attr = self._usrobj.current_fitness_values
|
attr = self._user_obj.current_fitness_values
|
||||||
else:
|
else:
|
||||||
attr = self._usrobj.current_values
|
attr = self._user_obj.current_values
|
||||||
elif "last" in self._sensor and self._usrobj:
|
elif "last" in self._sensor and self._user_obj:
|
||||||
attr = self._usrobj.last_values
|
attr = self._user_obj.last_values
|
||||||
|
|
||||||
if attr is None:
|
if attr is None:
|
||||||
# Skip attributes if sensor type doesn't support
|
# Skip attributes if sensor type doesn't support
|
||||||
@ -284,20 +281,18 @@ class EightUserSensor(EightSleepUserEntity, SensorEntity):
|
|||||||
return state_attr
|
return state_attr
|
||||||
|
|
||||||
|
|
||||||
class EightRoomSensor(EightSleepUserEntity, SensorEntity):
|
class EightRoomSensor(EightSleepBaseEntity, SensorEntity):
|
||||||
"""Representation of an eight sleep room sensor."""
|
"""Representation of an eight sleep room sensor."""
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
name: str,
|
coordinator: DataUpdateCoordinator,
|
||||||
coordinator: EightSleepUserDataCoordinator,
|
|
||||||
eight: EightSleep,
|
eight: EightSleep,
|
||||||
side: str | None,
|
|
||||||
sensor: str,
|
sensor: str,
|
||||||
units: str,
|
units: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the sensor."""
|
"""Initialize the sensor."""
|
||||||
super().__init__(name, coordinator, eight, side, sensor, units)
|
super().__init__(coordinator, eight, None, sensor, units)
|
||||||
|
|
||||||
self._attr_icon = "mdi:thermometer"
|
self._attr_icon = "mdi:thermometer"
|
||||||
self._attr_native_unit_of_measurement: str = (
|
self._attr_native_unit_of_measurement: str = (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user