More hue implementation
This commit is contained in:
parent
db5e826aea
commit
c78546ffcf
9 changed files with 1422 additions and 29 deletions
|
@ -5,7 +5,7 @@ import os
|
|||
from statistics import median
|
||||
from typing import Optional
|
||||
import requests as r
|
||||
from ...endpoints.hue import hue
|
||||
from ...endpoints.hue import hue_bridge
|
||||
import logging
|
||||
|
||||
file_path: str = "bettwaage.csv"
|
||||
|
@ -126,9 +126,9 @@ def check_for_change():
|
|||
# Make room sexy
|
||||
if sexy_mode_detection:
|
||||
if number_of_people >= 2 and weight_increased:
|
||||
hue.in_room_activate_scene("Max Zimmer", "Sexy")
|
||||
hue_bridge.in_room_activate_scene("Max Zimmer", "Sexy")
|
||||
elif number_of_people == 1 and not weight_increased:
|
||||
hue.in_room_activate_scene("Max Zimmer", "Tageslicht")
|
||||
hue_bridge.in_room_activate_scene("Max Zimmer", "Tageslicht")
|
||||
|
||||
|
||||
def add_line_to_bed_history(line: str) -> None:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import json
|
||||
import logging
|
||||
from core import Bridge
|
||||
from core import Bridge, Group
|
||||
from phue import Bridge as phueBridge
|
||||
from time import sleep
|
||||
|
||||
|
@ -9,15 +10,15 @@ class HueBridge(Bridge):
|
|||
def __init__(
|
||||
self,
|
||||
*,
|
||||
ip_address: str,
|
||||
id: str,
|
||||
ip: str,
|
||||
retry_limit: int = 10,
|
||||
retry_timeout_seconds: int = 5,
|
||||
) -> None:
|
||||
super().__init__(id=id, type="hue")
|
||||
self._retry_limit = retry_limit
|
||||
self._retry_timeout_seconds = retry_timeout_seconds
|
||||
self._hue: phueBridge = phueBridge(ip)
|
||||
self._hue: phueBridge = phueBridge(ip_address)
|
||||
|
||||
def disconnect(self) -> None:
|
||||
self._hue = None
|
||||
|
@ -47,6 +48,10 @@ class HueBridge(Bridge):
|
|||
def list_api(self) -> dict:
|
||||
return self._hue.get_api()
|
||||
|
||||
def get_all_lights(self) -> Group:
|
||||
light_states = await self.list_api()
|
||||
# TODO
|
||||
|
||||
def list_scenes(self) -> dict:
|
||||
return self._hue.get_scene()
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from core import Entity
|
||||
from core import Entity, Color
|
||||
from bridges.hue import HueBridge
|
||||
|
||||
|
||||
|
@ -8,6 +8,7 @@ class HueLight(Entity):
|
|||
self,
|
||||
*,
|
||||
bridge: HueBridge,
|
||||
initial_state: dict,
|
||||
id: str,
|
||||
name: str,
|
||||
room: str,
|
||||
|
@ -15,8 +16,24 @@ class HueLight(Entity):
|
|||
) -> None:
|
||||
super().__init__(id=id, name=name, room=room, groups=groups)
|
||||
self._bridge: HueBridge = bridge
|
||||
self._color: Color = Color()
|
||||
self._on: bool = False
|
||||
self._transition_duration_sec = 0
|
||||
|
||||
def poll_state(self):
|
||||
self.__parse_state__(initial_state)
|
||||
|
||||
def __parse_state__(self, state: dict):
|
||||
max_int_value = 255
|
||||
self._on = state["state"]["on"]
|
||||
|
||||
h = state["state"]["hue"] / max_int_value
|
||||
s = state["state"]["sat"] / max_int_value
|
||||
v = state["state"]["bri"] / max_int_value
|
||||
|
||||
# TODO: Update color instead of overwriting it, to better keep track of change?
|
||||
self._color = Color(hue=h, saturation=s, brightness=v)
|
||||
|
||||
def update(self):
|
||||
# TODO
|
||||
pass
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class Color:
|
||||
def __init__(self, *, hue: float, saturation: float, brightness: float):
|
||||
self.hue = hue
|
||||
self.saturation = saturation
|
||||
self.brightness = brightness
|
||||
self.hue: float = hue
|
||||
self.saturation: float = saturation
|
||||
self.brightness: float = brightness
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from core import Color
|
||||
from .color import Color
|
||||
|
||||
|
||||
class EntityOpNotSupportedError(Exception):
|
||||
|
@ -48,9 +48,9 @@ class Entity:
|
|||
def __str__(self) -> str:
|
||||
return f"{self.name} [{self.id}, type {self.device_type}, room {self.room}, in {len(self.groups)} groups]"
|
||||
|
||||
async def poll_state(self):
|
||||
"""Implements an entity specific poll operation to get the latest state."""
|
||||
raise EntityOpNotSupportedError("poll_state")
|
||||
async def update(self):
|
||||
"""Implements an entity specific update operation to get the latest state."""
|
||||
raise EntityOpNotSupportedError("update")
|
||||
|
||||
async def toggle_state(self):
|
||||
"""Turns entity on, if off, and vice versa, if supported."""
|
||||
|
|
|
@ -1,6 +1,43 @@
|
|||
from core import Entity
|
||||
from .entity import Entity, EntityOpNotSupportedError
|
||||
|
||||
|
||||
class Group(Entity):
|
||||
def __init__(self, *, id: str, name: str):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
entities: list[Entity] = ...,
|
||||
id: str = "group",
|
||||
name: str = "Empty Group"
|
||||
):
|
||||
super().__init__(id=id, name=name, room=None, device_type="group")
|
||||
self._entities: list[Entity] = entities
|
||||
|
||||
# List of method names to dynamically create
|
||||
methods_to_create = [
|
||||
"set_brightness",
|
||||
"set_hue",
|
||||
"set_saturation",
|
||||
"set_color",
|
||||
"set_transition_duration",
|
||||
"turn_on",
|
||||
"turn_off",
|
||||
]
|
||||
|
||||
for method_name in methods_to_create:
|
||||
setattr(self, method_name, self._create_group_method(method_name))
|
||||
|
||||
async def __call_method__(self, method_name: str, *args, **kwargs):
|
||||
for entity in self._entities:
|
||||
try:
|
||||
func = getattr(entity, method_name)
|
||||
await func(*args, **kwargs)
|
||||
except EntityOpNotSupportedError:
|
||||
pass
|
||||
|
||||
def _create_group_method(self, method_name: str):
|
||||
# Create a method that calls __call_method__ for the given method name
|
||||
async def group_method(*args, **kwargs):
|
||||
await self.__call_method__(method_name, *args, **kwargs)
|
||||
|
||||
return group_method
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from core import Group
|
||||
from .group import Group
|
||||
|
||||
|
||||
class Room(Group):
|
||||
|
|
|
@ -5,22 +5,23 @@ from bridges.hue import HueBridge, HueLight
|
|||
from fastapi import APIRouter
|
||||
from fastapi.responses import HTMLResponse
|
||||
|
||||
from core import Group
|
||||
|
||||
router = APIRouter(tags=["hue"])
|
||||
hue = HueBridge("192.168.178.85")
|
||||
lights: dict[int, HueLight] = {}
|
||||
hue_bridge = HueBridge(ip_address="192.168.178.85", id="hue-bridge")
|
||||
hue_lights: Group = Group()
|
||||
|
||||
poll_delay_sec = 5
|
||||
|
||||
|
||||
async def hue_service():
|
||||
global lights
|
||||
global hue_lights
|
||||
|
||||
hue_lights = await hue_bridge.get_all_lights()
|
||||
|
||||
while True:
|
||||
try:
|
||||
for light in lights:
|
||||
light.poll_state()
|
||||
|
||||
# TODO: Get all new lights
|
||||
await hue_lights.update()
|
||||
|
||||
await asyncio.sleep(poll_delay_sec)
|
||||
except:
|
||||
|
@ -29,7 +30,7 @@ async def hue_service():
|
|||
|
||||
@router.get("/scenes", tags=["scene"])
|
||||
async def get_scenes():
|
||||
return hue.list_scenes()
|
||||
return hue_bridge.list_scenes()
|
||||
|
||||
|
||||
@router.post(
|
||||
|
@ -38,7 +39,7 @@ async def get_scenes():
|
|||
)
|
||||
async def activate_scene(room_name: str, scene_name: str):
|
||||
try:
|
||||
hue.in_room_activate_scene(room_name, scene_name)
|
||||
hue_bridge.in_room_activate_scene(room_name, scene_name)
|
||||
except Exception as e:
|
||||
return HTMLResponse(status_code=400, content=str(e))
|
||||
|
||||
|
@ -49,7 +50,7 @@ async def activate_scene(room_name: str, scene_name: str):
|
|||
)
|
||||
async def deactivate_room(room_name: str):
|
||||
try:
|
||||
hue.in_room_deactivate_lights(room_name)
|
||||
hue_bridge.in_room_deactivate_lights(room_name)
|
||||
except Exception as e:
|
||||
return HTMLResponse(status_code=400, content=str(e))
|
||||
|
||||
|
@ -60,6 +61,6 @@ async def deactivate_room(room_name: str):
|
|||
)
|
||||
async def activate_room(room_name: str):
|
||||
try:
|
||||
hue.in_room_activate_lights(room_name)
|
||||
hue_bridge.in_room_activate_lights(room_name)
|
||||
except Exception as e:
|
||||
return HTMLResponse(status_code=400, content=str(e))
|
||||
|
|
1333
src/hue_api.json
Normal file
1333
src/hue_api.json
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue