Skip to content

Commit

Permalink
Merge pull request #18 from dzader/add-foot-warming
Browse files Browse the repository at this point in the history
add foot warming
  • Loading branch information
kbickar committed Dec 13, 2023
2 parents b7efb8c + 8358d91 commit ae852dc
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 0 deletions.
1 change: 1 addition & 0 deletions asyncsleepiq/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
SleepIQLoginException,
SleepIQTimeoutException,
)
from .foot_warmer import SleepIQFootWarmer
from .foundation import SleepIQFoundation
from .light import SleepIQLight
from .preset import SleepIQPreset
Expand Down
6 changes: 6 additions & 0 deletions asyncsleepiq/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@

BED_LIGHTS = [RIGHT_NIGHT_STAND, LEFT_NIGHT_STAND, RIGHT_NIGHT_LIGHT, LEFT_NIGHT_LIGHT]

class FootWarmingTemps(int, enum.Enum):
OFF = 0
LOW = 31
MEDIUM = 57
HIGH = 72

FAVORITE = 1
READ = 2
WATCH_TV = 3
Expand Down
53 changes: 53 additions & 0 deletions asyncsleepiq/foot_warmer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"""Foot warmer representation for SleepIQ API."""
from __future__ import annotations

from .api import SleepIQAPI
from .consts import (Side, FootWarmingTemps, SIDES_FULL)

class SleepIQFootWarmer:
"""Foot warmer representation for SleepIQ API."""

def __init__(self, api: SleepIQAPI, bed_id: str, side: Side, timer: int, temperature: int) -> None:
"""Initialize foot warmer object."""
self._api = api
self.bed_id = bed_id
self.side = side
self.is_on = (temperature > 0)
self.timer = timer
self.temperature = temperature

def __str__(self) -> str:
"""Return string representation."""
return f"SleepIQFootWarmer[{self.side}]: {'On' if self.is_on else 'Off'}, {self.timer}, {FootWarmingTemps(self.temperature).name}"
__repr__ = __str__

async def turn_on(self, temperature: FootWarmingTemps, time: int) -> None:
"""Turn on foot warmer through API."""
await self.set_foot_warming(temperature, time)

async def turn_off(self) -> None:
"""Turn off foot warmer through API."""
# The API requires a valid time value even if we're turning the warmer off
await self.set_foot_warming(FootWarmingTemps.OFF, 1)

async def set_foot_warming(self, temperature: FootWarmingTemps, time: int) -> None:
"""Set foot warmer state through API."""
if time <= 0 or time > 360:
raise ValueError("Invalid Time, must be between 0 and 360")

data = { self.time_key(): time, self.temp_key(): temperature.value}
await self._api.put(f"bed/{self.bed_id}/foundation/footwarming", data)
await self.update(data)

async def update(self, data) -> None:
# when reading the values the key is footWarmingStatus and when writing the values the key is footWarmingTemp so lookup both
self.temperature = data.get(self.temp_key(True), data.get(self.temp_key()))
self.is_on = self.temperature > 0
self.timer = data.get(self.time_key(), self.timer) if self.is_on else 0

def time_key(self):
return 'footWarmingTimer' + SIDES_FULL[self.side]

def temp_key(self, read = False):
key = 'Status' if read else 'Temp'
return f'footWarming{key}' + SIDES_FULL[self.side]
19 changes: 19 additions & 0 deletions asyncsleepiq/foundation.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
Speed,
)
from .light import SleepIQLight
from .foot_warmer import SleepIQFootWarmer
from .preset import SleepIQPreset


Expand All @@ -25,6 +26,7 @@ def __init__(self, api: SleepIQAPI, bed_id: str) -> None:
self._api = api
self.bed_id = bed_id
self.lights: list[SleepIQLight] = []
self.foot_warmers: list[SleepIQFootWarmer] = []
self.features: dict[str, Any] = {}
self.type = ""
self.actuators: list[SleepIQActuator] = []
Expand All @@ -41,6 +43,7 @@ def __repr__(self) -> str:
async def init_features(self) -> None:
"""Initialize all foundation features."""
await self.init_lights()
await self.init_foot_warmers()

if not self.type:
return
Expand All @@ -52,6 +55,7 @@ async def init_features(self) -> None:
async def update_foundation_status(self) -> None:
"""Update all foundation data from API."""
await self.update_lights()
await self.update_foot_warmers()

if not self.type:
return
Expand All @@ -61,6 +65,21 @@ async def update_foundation_status(self) -> None:
await self.update_actuators(data)
await self.update_presets(data)

async def init_foot_warmers(self) -> None:
if not self.features["hasFootWarming"]:
return

for side in [Side.LEFT, Side.RIGHT]:
self.foot_warmers.append(SleepIQFootWarmer(self._api, self.bed_id, side, 0, 0))

async def update_foot_warmers(self) -> None:
if not self.features["hasFootWarming"]:
return

data = await self._api.get(f"bed/{self.bed_id}/foundation/footwarming")
for foot_warmer in self.foot_warmers:
await foot_warmer.update(data)

async def init_lights(self) -> None:
"""Initialize list of lights available on foundation."""
for light in BED_LIGHTS:
Expand Down

0 comments on commit ae852dc

Please sign in to comment.