Continued implementing hue bridge and first entities
This commit is contained in:
parent
b9d8c5312c
commit
b3106e8bae
13 changed files with 187 additions and 10 deletions
|
@ -27,7 +27,8 @@ class HueBridge(Bridge):
|
|||
for _ in range(self._retry_limit):
|
||||
try:
|
||||
self._hue.connect()
|
||||
break
|
||||
logging.info(f"Connected to Hue Bridge [{self.id}].")
|
||||
return
|
||||
except Exception as e:
|
||||
logging.exception(
|
||||
f"Failed to connect to Hue bridge [ip {self._hue.ip}]. Retrying in [{self._retry_timeout_seconds}] seconds.",
|
||||
|
@ -35,7 +36,9 @@ class HueBridge(Bridge):
|
|||
)
|
||||
sleep(self._retry_timeout_seconds)
|
||||
|
||||
logging.info(f"Connected to Hue Bridge [{self.id}].")
|
||||
logging.error(
|
||||
f"Unable to connect to Hue bridge [{self.id}]. Retry count exceeded [{self._retry_limit}]."
|
||||
)
|
||||
|
||||
@property
|
||||
def is_connected(self) -> bool | None:
|
||||
|
@ -54,6 +57,18 @@ class HueBridge(Bridge):
|
|||
return scene
|
||||
return None
|
||||
|
||||
def set_light(self, lights, command):
|
||||
return self._hue.set_light(lights, command)
|
||||
|
||||
def get_light(self, id, command=None):
|
||||
return self._hue.get_light(id, command)
|
||||
|
||||
def set_group(self, groups, command):
|
||||
return self._hue.set_group(groups, command)
|
||||
|
||||
def get_group(self, id, command=None):
|
||||
return self._hue.get_group(id, command)
|
||||
|
||||
def in_room_activate_scene(self, room_name: str, scene_name: str):
|
||||
"""Activate a scene in a room.
|
||||
|
||||
|
|
13
src/mash/bridges/hue/hue_light.py
Normal file
13
src/mash/bridges/hue/hue_light.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
from mash.core.entities.light import Light
|
||||
from mash.core.utilities.glow import Glow
|
||||
|
||||
|
||||
class HueLight(Light):
|
||||
def __init__(
|
||||
self, *, id: str, name: str, room: str, groups: list[str] = ...
|
||||
) -> None:
|
||||
super().__init__(id=id, name=name, room=room, groups=groups)
|
||||
|
||||
def __on_change__(self, current_on: bool, current_glow: Glow):
|
||||
pass
|
||||
# TODO: Requires reference to bridge
|
|
@ -1,5 +1,3 @@
|
|||
from .entities import *
|
||||
from .bridge import Bridge, BridgeException
|
||||
from .entity import Entity
|
||||
from .group import Group
|
||||
from .home import Home
|
||||
from .feature import Feature
|
||||
|
|
6
src/mash/core/entities/__init__.py
Normal file
6
src/mash/core/entities/__init__.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from .entity import Entity
|
||||
from .group import Group
|
||||
from .home import Home
|
||||
from .contact_sensor import ContactSensor
|
||||
from .light import Light
|
||||
from .device_type import DeviceTypes
|
21
src/mash/core/entities/contact_sensor.py
Normal file
21
src/mash/core/entities/contact_sensor.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
from mash.core.entities.device_type import DeviceType
|
||||
from mash.core.entities.entity import Entity
|
||||
|
||||
|
||||
class ContactSensor(Entity):
|
||||
def __init__(
|
||||
self, *, id: str, name: str, room: str, groups: list[str] = ...
|
||||
) -> None:
|
||||
super().__init__(
|
||||
id=id,
|
||||
name=name,
|
||||
room=room,
|
||||
device_type=DeviceType.CONTACT_SENSOR,
|
||||
groups=groups,
|
||||
)
|
||||
self._has_contact: bool = False
|
||||
|
||||
def is_closed(self) -> bool:
|
||||
return self._has_contact
|
||||
|
||||
# TODO: Update state
|
6
src/mash/core/entities/device_type.py
Normal file
6
src/mash/core/entities/device_type.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from enum import Enum
|
||||
|
||||
|
||||
class DeviceType(Enum):
|
||||
LIGHT = "light"
|
||||
CONTACT_SENSOR = "contact_sensor"
|
|
@ -1,6 +1,15 @@
|
|||
from mash.core.entities.device_type import DeviceType
|
||||
|
||||
|
||||
class Entity:
|
||||
def __init__(
|
||||
self, *, id: str, name: str, room: str, device_type: str, groups: list[str] = []
|
||||
self,
|
||||
*,
|
||||
id: str,
|
||||
name: str,
|
||||
room: str,
|
||||
device_type: DeviceType,
|
||||
groups: list[str] = [],
|
||||
) -> None:
|
||||
self._id = id
|
||||
self._name = name
|
||||
|
@ -21,7 +30,7 @@ class Entity:
|
|||
return self._room
|
||||
|
||||
@property
|
||||
def device_type(self) -> str:
|
||||
def device_type(self) -> DeviceType:
|
||||
return self._device_type
|
||||
|
||||
@property
|
|
@ -1,4 +1,4 @@
|
|||
from mash.core.entity import Entity
|
||||
from mash.core.entities.entity import Entity
|
||||
from fnmatch import fnmatch
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
from mash.core.entity import Entity
|
||||
from mash.core.group import Group
|
||||
from mash.core.entities.entity import Entity
|
||||
from mash.core.entities.group import Group
|
||||
|
||||
|
||||
class Home(Group):
|
66
src/mash/core/entities/light.py
Normal file
66
src/mash/core/entities/light.py
Normal file
|
@ -0,0 +1,66 @@
|
|||
from mash.core.entities.device_type import DeviceType
|
||||
from mash.core.entities.entity import Entity
|
||||
from mash.core.utilities.glow import Glow
|
||||
from mash.core.utilities.validation import clip_int
|
||||
|
||||
|
||||
class Light(Entity):
|
||||
def __init__(
|
||||
self, *, id: str, name: str, room: str, groups: list[str] = ...
|
||||
) -> None:
|
||||
super().__init__(
|
||||
id=id, name=name, room=room, device_type=DeviceType.LIGHT, groups=groups
|
||||
)
|
||||
self._glow: Glow = Glow()
|
||||
self._on: bool = False
|
||||
|
||||
def __on_change__(self, current_on: bool, current_glow: Glow):
|
||||
pass
|
||||
|
||||
def __check_for_change__(self, obj, prop, new_value):
|
||||
old_value = getattr(obj, prop)
|
||||
if old_value == new_value:
|
||||
return
|
||||
|
||||
setattr(obj, prop, new_value)
|
||||
self.__on_change__(current_on=self.on, current_glow=self._glow)
|
||||
|
||||
@property
|
||||
def on(self) -> bool:
|
||||
"""True, if light is emitting glow. False, if light is off."""
|
||||
return self._on
|
||||
|
||||
@on.setter
|
||||
def on(self, value: bool):
|
||||
"""True, if light is emitting glow. False, if light is off."""
|
||||
self.__check_for_change__(self, "_on", value)
|
||||
|
||||
@property
|
||||
def brightness(self) -> int:
|
||||
"""Brightness in the range [0, 254]."""
|
||||
return self._glow.brightness
|
||||
|
||||
@brightness.setter
|
||||
def brightness(self, value: int):
|
||||
"""Brightness in the range [0, 254]. Value will be clipped."""
|
||||
self.__check_for_change__(self._glow, "brightness", clip_int(value, 0, 254))
|
||||
|
||||
@property
|
||||
def saturation(self) -> int:
|
||||
"""Saturation in the range [0, 254]."""
|
||||
return self._glow.saturation
|
||||
|
||||
@saturation.setter
|
||||
def saturation(self, value: int):
|
||||
"""Saturation in the range [0, 254]. Value will be clipped."""
|
||||
self.__check_for_change__(self._glow, "saturation", clip_int(value, 0, 254))
|
||||
|
||||
@property
|
||||
def hue(self) -> int:
|
||||
"""Hue in the range [0, 65535]."""
|
||||
return self._glow.hue
|
||||
|
||||
@hue.setter
|
||||
def hue(self, value: int):
|
||||
"""Hue in the range [0, 65535]. Value will be clipped."""
|
||||
self.__check_for_change__(self._glow, "hue", clip_int(value, 0, 65535))
|
2
src/mash/core/utilities/__init__.py
Normal file
2
src/mash/core/utilities/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
from .glow import Glow
|
||||
from .validation import clip_int
|
39
src/mash/core/utilities/glow.py
Normal file
39
src/mash/core/utilities/glow.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
class Glow:
|
||||
"""Concept of colored light-rays."""
|
||||
|
||||
def __init__(
|
||||
self, *, brightness: int = 0, saturation: int = 0, hue: int = 0
|
||||
) -> None:
|
||||
self._brightness: int = brightness
|
||||
self._saturation: int = saturation
|
||||
self._hue: int = hue
|
||||
|
||||
@property
|
||||
def brightness(self) -> int:
|
||||
"""Brightness in the range [0, 254]."""
|
||||
return self._brightness
|
||||
|
||||
@brightness.setter
|
||||
def brightness(self, value: int):
|
||||
"""Brightness in the range [0, 254]."""
|
||||
self._brightness = value
|
||||
|
||||
@property
|
||||
def saturation(self) -> int:
|
||||
"""Saturation in the range [0, 254]."""
|
||||
return self._saturation
|
||||
|
||||
@saturation.setter
|
||||
def saturation(self, value: int):
|
||||
"""Saturation in the range [0, 254]."""
|
||||
self._saturation = value
|
||||
|
||||
@property
|
||||
def hue(self) -> int:
|
||||
"""Hue in the range [0, 65535]."""
|
||||
return self._hue
|
||||
|
||||
@hue.setter
|
||||
def hue(self, value: int):
|
||||
"""Hue in the range [0, 65535]."""
|
||||
self._hue = value
|
2
src/mash/core/utilities/validation.py
Normal file
2
src/mash/core/utilities/validation.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
def clip_int(value, min_val: int, max_val: int) -> int:
|
||||
return min([max([int(value), min_val]), max_val])
|
Loading…
Reference in a new issue