mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Eight Sleep add REM type, Update async syntax, Catch API quirks (#14937)
This commit is contained in:
parent
8a777f6e78
commit
9efa31ef9f
@ -5,7 +5,6 @@ For more details about this platform, please refer to the documentation at
|
|||||||
https://home-assistant.io/components/binary_sensor.eight_sleep/
|
https://home-assistant.io/components/binary_sensor.eight_sleep/
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
import asyncio
|
|
||||||
|
|
||||||
from homeassistant.components.binary_sensor import BinarySensorDevice
|
from homeassistant.components.binary_sensor import BinarySensorDevice
|
||||||
from homeassistant.components.eight_sleep import (
|
from homeassistant.components.eight_sleep import (
|
||||||
@ -16,8 +15,8 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
DEPENDENCIES = ['eight_sleep']
|
DEPENDENCIES = ['eight_sleep']
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_setup_platform(hass, config, async_add_devices,
|
||||||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
discovery_info=None):
|
||||||
"""Set up the eight sleep binary sensor."""
|
"""Set up the eight sleep binary sensor."""
|
||||||
if discovery_info is None:
|
if discovery_info is None:
|
||||||
return
|
return
|
||||||
@ -63,7 +62,6 @@ class EightHeatSensor(EightSleepHeatEntity, BinarySensorDevice):
|
|||||||
"""Return true if the binary sensor is on."""
|
"""Return true if the binary sensor is on."""
|
||||||
return self._state
|
return self._state
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_update(self):
|
||||||
def async_update(self):
|
|
||||||
"""Retrieve latest state."""
|
"""Retrieve latest state."""
|
||||||
self._state = self._usrobj.bed_presence
|
self._state = self._usrobj.bed_presence
|
||||||
|
@ -4,7 +4,6 @@ Support for Eight smart mattress covers and mattresses.
|
|||||||
For more details about this component, please refer to the documentation at
|
For more details about this component, please refer to the documentation at
|
||||||
https://home-assistant.io/components/eight_sleep/
|
https://home-assistant.io/components/eight_sleep/
|
||||||
"""
|
"""
|
||||||
import asyncio
|
|
||||||
import logging
|
import logging
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
@ -22,7 +21,7 @@ from homeassistant.helpers.entity import Entity
|
|||||||
from homeassistant.helpers.event import async_track_point_in_utc_time
|
from homeassistant.helpers.event import async_track_point_in_utc_time
|
||||||
from homeassistant.util.dt import utcnow
|
from homeassistant.util.dt import utcnow
|
||||||
|
|
||||||
REQUIREMENTS = ['pyeight==0.0.8']
|
REQUIREMENTS = ['pyeight==0.0.9']
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -86,8 +85,7 @@ CONFIG_SCHEMA = vol.Schema({
|
|||||||
}, extra=vol.ALLOW_EXTRA)
|
}, extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_setup(hass, config):
|
||||||
def async_setup(hass, config):
|
|
||||||
"""Set up the Eight Sleep component."""
|
"""Set up the Eight Sleep component."""
|
||||||
from pyeight.eight import EightSleep
|
from pyeight.eight import EightSleep
|
||||||
|
|
||||||
@ -107,31 +105,29 @@ def async_setup(hass, config):
|
|||||||
hass.data[DATA_EIGHT] = eight
|
hass.data[DATA_EIGHT] = eight
|
||||||
|
|
||||||
# Authenticate, build sensors
|
# Authenticate, build sensors
|
||||||
success = yield from eight.start()
|
success = await eight.start()
|
||||||
if not success:
|
if not success:
|
||||||
# Authentication failed, cannot continue
|
# Authentication failed, cannot continue
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_update_heat_data(now):
|
||||||
def async_update_heat_data(now):
|
|
||||||
"""Update heat data from eight in HEAT_SCAN_INTERVAL."""
|
"""Update heat data from eight in HEAT_SCAN_INTERVAL."""
|
||||||
yield from eight.update_device_data()
|
await eight.update_device_data()
|
||||||
async_dispatcher_send(hass, SIGNAL_UPDATE_HEAT)
|
async_dispatcher_send(hass, SIGNAL_UPDATE_HEAT)
|
||||||
|
|
||||||
async_track_point_in_utc_time(
|
async_track_point_in_utc_time(
|
||||||
hass, async_update_heat_data, utcnow() + HEAT_SCAN_INTERVAL)
|
hass, async_update_heat_data, utcnow() + HEAT_SCAN_INTERVAL)
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_update_user_data(now):
|
||||||
def async_update_user_data(now):
|
|
||||||
"""Update user data from eight in USER_SCAN_INTERVAL."""
|
"""Update user data from eight in USER_SCAN_INTERVAL."""
|
||||||
yield from eight.update_user_data()
|
await eight.update_user_data()
|
||||||
async_dispatcher_send(hass, SIGNAL_UPDATE_USER)
|
async_dispatcher_send(hass, SIGNAL_UPDATE_USER)
|
||||||
|
|
||||||
async_track_point_in_utc_time(
|
async_track_point_in_utc_time(
|
||||||
hass, async_update_user_data, utcnow() + USER_SCAN_INTERVAL)
|
hass, async_update_user_data, utcnow() + USER_SCAN_INTERVAL)
|
||||||
|
|
||||||
yield from async_update_heat_data(None)
|
await async_update_heat_data(None)
|
||||||
yield from async_update_user_data(None)
|
await async_update_user_data(None)
|
||||||
|
|
||||||
# Load sub components
|
# Load sub components
|
||||||
sensors = []
|
sensors = []
|
||||||
@ -157,8 +153,7 @@ def async_setup(hass, config):
|
|||||||
CONF_BINARY_SENSORS: binary_sensors,
|
CONF_BINARY_SENSORS: binary_sensors,
|
||||||
}, config))
|
}, config))
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_service_handler(service):
|
||||||
def async_service_handler(service):
|
|
||||||
"""Handle eight sleep service calls."""
|
"""Handle eight sleep service calls."""
|
||||||
params = service.data.copy()
|
params = service.data.copy()
|
||||||
|
|
||||||
@ -170,7 +165,7 @@ def async_setup(hass, config):
|
|||||||
side = sens.split('_')[1]
|
side = sens.split('_')[1]
|
||||||
userid = eight.fetch_userid(side)
|
userid = eight.fetch_userid(side)
|
||||||
usrobj = eight.users[userid]
|
usrobj = eight.users[userid]
|
||||||
yield from usrobj.set_heating_level(target, duration)
|
await usrobj.set_heating_level(target, duration)
|
||||||
|
|
||||||
async_dispatcher_send(hass, SIGNAL_UPDATE_HEAT)
|
async_dispatcher_send(hass, SIGNAL_UPDATE_HEAT)
|
||||||
|
|
||||||
@ -179,10 +174,9 @@ def async_setup(hass, config):
|
|||||||
DOMAIN, SERVICE_HEAT_SET, async_service_handler,
|
DOMAIN, SERVICE_HEAT_SET, async_service_handler,
|
||||||
schema=SERVICE_EIGHT_SCHEMA)
|
schema=SERVICE_EIGHT_SCHEMA)
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def stop_eight(event):
|
||||||
def stop_eight(event):
|
|
||||||
"""Handle stopping eight api session."""
|
"""Handle stopping eight api session."""
|
||||||
yield from eight.stop()
|
await eight.stop()
|
||||||
|
|
||||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_eight)
|
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_eight)
|
||||||
|
|
||||||
@ -196,8 +190,7 @@ class EightSleepUserEntity(Entity):
|
|||||||
"""Initialize the data object."""
|
"""Initialize the data object."""
|
||||||
self._eight = eight
|
self._eight = eight
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_added_to_hass(self):
|
||||||
def async_added_to_hass(self):
|
|
||||||
"""Register update dispatcher."""
|
"""Register update dispatcher."""
|
||||||
@callback
|
@callback
|
||||||
def async_eight_user_update():
|
def async_eight_user_update():
|
||||||
@ -220,8 +213,7 @@ class EightSleepHeatEntity(Entity):
|
|||||||
"""Initialize the data object."""
|
"""Initialize the data object."""
|
||||||
self._eight = eight
|
self._eight = eight
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_added_to_hass(self):
|
||||||
def async_added_to_hass(self):
|
|
||||||
"""Register update dispatcher."""
|
"""Register update dispatcher."""
|
||||||
@callback
|
@callback
|
||||||
def async_eight_heat_update():
|
def async_eight_heat_update():
|
||||||
|
@ -5,7 +5,6 @@ For more details about this platform, please refer to the documentation at
|
|||||||
https://home-assistant.io/components/sensor.eight_sleep/
|
https://home-assistant.io/components/sensor.eight_sleep/
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
import asyncio
|
|
||||||
|
|
||||||
from homeassistant.components.eight_sleep import (
|
from homeassistant.components.eight_sleep import (
|
||||||
DATA_EIGHT, EightSleepHeatEntity, EightSleepUserEntity,
|
DATA_EIGHT, EightSleepHeatEntity, EightSleepUserEntity,
|
||||||
@ -24,20 +23,20 @@ ATTR_AVG_HEART_RATE = 'Average Heart Rate'
|
|||||||
ATTR_SLEEP_DUR = 'Time Slept'
|
ATTR_SLEEP_DUR = 'Time Slept'
|
||||||
ATTR_LIGHT_PERC = 'Light Sleep %'
|
ATTR_LIGHT_PERC = 'Light Sleep %'
|
||||||
ATTR_DEEP_PERC = 'Deep Sleep %'
|
ATTR_DEEP_PERC = 'Deep Sleep %'
|
||||||
|
ATTR_REM_PERC = 'REM Sleep %'
|
||||||
ATTR_TNT = 'Tosses & Turns'
|
ATTR_TNT = 'Tosses & Turns'
|
||||||
ATTR_SLEEP_STAGE = 'Sleep Stage'
|
ATTR_SLEEP_STAGE = 'Sleep Stage'
|
||||||
ATTR_TARGET_HEAT = 'Target Heating Level'
|
ATTR_TARGET_HEAT = 'Target Heating Level'
|
||||||
ATTR_ACTIVE_HEAT = 'Heating Active'
|
ATTR_ACTIVE_HEAT = 'Heating Active'
|
||||||
ATTR_DURATION_HEAT = 'Heating Time Remaining'
|
ATTR_DURATION_HEAT = 'Heating Time Remaining'
|
||||||
ATTR_LAST_SEEN = 'Last In Bed'
|
|
||||||
ATTR_PROCESSING = 'Processing'
|
ATTR_PROCESSING = 'Processing'
|
||||||
ATTR_SESSION_START = 'Session Start'
|
ATTR_SESSION_START = 'Session Start'
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_setup_platform(hass, config, async_add_devices,
|
||||||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
discovery_info=None):
|
||||||
"""Set up the eight sleep sensors."""
|
"""Set up the eight sleep sensors."""
|
||||||
if discovery_info is None:
|
if discovery_info is None:
|
||||||
return
|
return
|
||||||
@ -98,8 +97,7 @@ class EightHeatSensor(EightSleepHeatEntity):
|
|||||||
"""Return the unit the value is expressed in."""
|
"""Return the unit the value is expressed in."""
|
||||||
return '%'
|
return '%'
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_update(self):
|
||||||
def async_update(self):
|
|
||||||
"""Retrieve latest state."""
|
"""Retrieve latest state."""
|
||||||
_LOGGER.debug("Updating Heat sensor: %s", self._sensor)
|
_LOGGER.debug("Updating Heat sensor: %s", self._sensor)
|
||||||
self._state = self._usrobj.heating_level
|
self._state = self._usrobj.heating_level
|
||||||
@ -110,7 +108,6 @@ class EightHeatSensor(EightSleepHeatEntity):
|
|||||||
state_attr = {ATTR_TARGET_HEAT: self._usrobj.target_heating_level}
|
state_attr = {ATTR_TARGET_HEAT: self._usrobj.target_heating_level}
|
||||||
state_attr[ATTR_ACTIVE_HEAT] = self._usrobj.now_heating
|
state_attr[ATTR_ACTIVE_HEAT] = self._usrobj.now_heating
|
||||||
state_attr[ATTR_DURATION_HEAT] = self._usrobj.heating_remaining
|
state_attr[ATTR_DURATION_HEAT] = self._usrobj.heating_remaining
|
||||||
state_attr[ATTR_LAST_SEEN] = self._usrobj.last_seen
|
|
||||||
|
|
||||||
return state_attr
|
return state_attr
|
||||||
|
|
||||||
@ -164,8 +161,7 @@ class EightUserSensor(EightSleepUserEntity):
|
|||||||
if 'bed_temp' in self._sensor:
|
if 'bed_temp' in self._sensor:
|
||||||
return 'mdi:thermometer'
|
return 'mdi:thermometer'
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_update(self):
|
||||||
def async_update(self):
|
|
||||||
"""Retrieve latest state."""
|
"""Retrieve latest state."""
|
||||||
_LOGGER.debug("Updating User sensor: %s", self._sensor)
|
_LOGGER.debug("Updating User sensor: %s", self._sensor)
|
||||||
if 'current' in self._sensor:
|
if 'current' in self._sensor:
|
||||||
@ -176,10 +172,13 @@ class EightUserSensor(EightSleepUserEntity):
|
|||||||
self._attr = self._usrobj.last_values
|
self._attr = self._usrobj.last_values
|
||||||
elif 'bed_temp' in self._sensor:
|
elif 'bed_temp' in self._sensor:
|
||||||
temp = self._usrobj.current_values['bed_temp']
|
temp = self._usrobj.current_values['bed_temp']
|
||||||
|
try:
|
||||||
if self._units == 'si':
|
if self._units == 'si':
|
||||||
self._state = round(temp, 2)
|
self._state = round(temp, 2)
|
||||||
else:
|
else:
|
||||||
self._state = round((temp*1.8)+32, 2)
|
self._state = round((temp*1.8)+32, 2)
|
||||||
|
except TypeError:
|
||||||
|
self._state = None
|
||||||
elif 'sleep_stage' in self._sensor:
|
elif 'sleep_stage' in self._sensor:
|
||||||
self._state = self._usrobj.current_values['stage']
|
self._state = self._usrobj.current_values['stage']
|
||||||
|
|
||||||
@ -208,12 +207,27 @@ class EightUserSensor(EightSleepUserEntity):
|
|||||||
except ZeroDivisionError:
|
except ZeroDivisionError:
|
||||||
state_attr[ATTR_DEEP_PERC] = 0
|
state_attr[ATTR_DEEP_PERC] = 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
state_attr[ATTR_REM_PERC] = round((
|
||||||
|
self._attr['breakdown']['rem'] / sleep_time) * 100, 2)
|
||||||
|
except ZeroDivisionError:
|
||||||
|
state_attr[ATTR_REM_PERC] = 0
|
||||||
|
|
||||||
|
try:
|
||||||
if self._units == 'si':
|
if self._units == 'si':
|
||||||
room_temp = round(self._attr['room_temp'], 2)
|
room_temp = round(self._attr['room_temp'], 2)
|
||||||
bed_temp = round(self._attr['bed_temp'], 2)
|
|
||||||
else:
|
else:
|
||||||
room_temp = round((self._attr['room_temp']*1.8)+32, 2)
|
room_temp = round((self._attr['room_temp']*1.8)+32, 2)
|
||||||
|
except TypeError:
|
||||||
|
room_temp = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
if self._units == 'si':
|
||||||
|
bed_temp = round(self._attr['bed_temp'], 2)
|
||||||
|
else:
|
||||||
bed_temp = round((self._attr['bed_temp']*1.8)+32, 2)
|
bed_temp = round((self._attr['bed_temp']*1.8)+32, 2)
|
||||||
|
except TypeError:
|
||||||
|
bed_temp = None
|
||||||
|
|
||||||
if 'current' in self._sensor_root:
|
if 'current' in self._sensor_root:
|
||||||
state_attr[ATTR_RESP_RATE] = round(self._attr['resp_rate'], 2)
|
state_attr[ATTR_RESP_RATE] = round(self._attr['resp_rate'], 2)
|
||||||
@ -255,15 +269,17 @@ class EightRoomSensor(EightSleepUserEntity):
|
|||||||
"""Return the state of the sensor."""
|
"""Return the state of the sensor."""
|
||||||
return self._state
|
return self._state
|
||||||
|
|
||||||
@asyncio.coroutine
|
async def async_update(self):
|
||||||
def async_update(self):
|
|
||||||
"""Retrieve latest state."""
|
"""Retrieve latest state."""
|
||||||
_LOGGER.debug("Updating Room sensor: %s", self._sensor)
|
_LOGGER.debug("Updating Room sensor: %s", self._sensor)
|
||||||
temp = self._eight.room_temperature()
|
temp = self._eight.room_temperature()
|
||||||
|
try:
|
||||||
if self._units == 'si':
|
if self._units == 'si':
|
||||||
self._state = round(temp, 2)
|
self._state = round(temp, 2)
|
||||||
else:
|
else:
|
||||||
self._state = round((temp*1.8)+32, 2)
|
self._state = round((temp*1.8)+32, 2)
|
||||||
|
except TypeError:
|
||||||
|
self._state = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unit_of_measurement(self):
|
def unit_of_measurement(self):
|
||||||
|
@ -811,7 +811,7 @@ pyeconet==0.0.5
|
|||||||
pyedimax==0.1
|
pyedimax==0.1
|
||||||
|
|
||||||
# homeassistant.components.eight_sleep
|
# homeassistant.components.eight_sleep
|
||||||
pyeight==0.0.8
|
pyeight==0.0.9
|
||||||
|
|
||||||
# homeassistant.components.media_player.emby
|
# homeassistant.components.media_player.emby
|
||||||
pyemby==1.5
|
pyemby==1.5
|
||||||
|
Loading…
x
Reference in New Issue
Block a user