You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
206 lines
6.4 KiB
206 lines
6.4 KiB
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import requests
|
|
|
|
from ..HueLight import HueLight
|
|
from ..HueUtils import make_request
|
|
|
|
|
|
class HueGroup:
|
|
"""A class for groups
|
|
"""
|
|
|
|
class Action:
|
|
"""The light state of one of the lamps in the group.
|
|
"""
|
|
|
|
def __init__(self, data_slice: dict):
|
|
"""Constructor
|
|
|
|
Args:
|
|
data_slice (dict): The part of the data structure that concerns this Action
|
|
"""
|
|
keys = data_slice.keys()
|
|
self.m_on: bool = data_slice['on']
|
|
self.m_bri: int = data_slice['bri']
|
|
self.m_alert: str = data_slice['alert']
|
|
if 'hue' in keys:
|
|
self.m_hue: int = data_slice['hue']
|
|
else:
|
|
self.m_hue = 0
|
|
if 'sat' in keys:
|
|
self.m_sat: int = data_slice['sat']
|
|
else:
|
|
self.m_sat = 0
|
|
if 'effect' in keys:
|
|
self.m_effect: str = data_slice['effect']
|
|
else:
|
|
self.m_effect = str()
|
|
if 'xy' in keys:
|
|
self.m_xy: list[float] = data_slice['xy']
|
|
else:
|
|
self.m_xy = list()
|
|
if 'ct' in keys:
|
|
self.m_ct: int = data_slice['ct']
|
|
else:
|
|
self.m_ct = 0
|
|
if 'colormode' in keys:
|
|
self.m_colormode: str = data_slice['colormode']
|
|
else:
|
|
self.m_colormode = str()
|
|
|
|
class State:
|
|
"""A hueGroup.State represents the collective state of the group
|
|
|
|
"""
|
|
|
|
def __init__(self, data_slice: dict):
|
|
"""Constructor
|
|
|
|
Args:
|
|
data_slice (dict): The part of the data structure that concerns this State
|
|
"""
|
|
self.m_all_on: bool = data_slice['all_on']
|
|
self.m_any_on: bool = data_slice['any_on']
|
|
|
|
def __init__(self, group_id: int, lights: list[HueLight], data: dict, parent_bridge_ip: str,
|
|
parent_bridge_user: str):
|
|
"""Constructor
|
|
|
|
Args:
|
|
group_id (int): The group id for this group
|
|
lights (list[HueLight]): The lights that is in this group
|
|
data (dict): The Hue API description of the group
|
|
parent_bridge_ip (str): ip address of the parent bridge
|
|
parent_bridge_user (str): username of the parent bridge
|
|
"""
|
|
self.m_id: int = group_id
|
|
self.m_parent_bridge_ip = parent_bridge_ip
|
|
self.m_parent_bridge_user = parent_bridge_user
|
|
self.m_name: str = data['name']
|
|
self.m_lights = lights
|
|
self.m_sensors: list[str] = data['sensors']
|
|
self.m_type: str = data['type']
|
|
# Don't believe the api, it can claim that a light is on even if it is unreachable
|
|
state: dict = {'all_on': self.is_any_on(), 'any_on': self.is_any_on()}
|
|
self.m_state: HueGroup.State = HueGroup.State(state)
|
|
self.m_recycle: bool = data['recycle']
|
|
if 'class' in data.keys():
|
|
self.m_class: str = data['class']
|
|
else:
|
|
self.m_class: str = str()
|
|
self.m_action: HueGroup.Action(data['action'])
|
|
|
|
def __str__(self) -> str:
|
|
"""String representation of the group
|
|
|
|
Returns:
|
|
str: The group name
|
|
"""
|
|
return self.m_name
|
|
|
|
def get_id(self) -> int:
|
|
"""Get the group id
|
|
|
|
Returns:
|
|
int: The group id
|
|
"""
|
|
return self.m_id
|
|
|
|
def get_lights(self) -> list[HueLight]:
|
|
"""Get the lights that belong to this group
|
|
|
|
Returns:
|
|
list[HueLight]: The lights
|
|
"""
|
|
return self.m_lights
|
|
|
|
def is_all_on(self) -> bool:
|
|
"""We really check to make sure
|
|
|
|
Returns:
|
|
bool: True if all lights are on and reachable, otherwise False
|
|
"""
|
|
# Dont believe the API, both on and reachable to be on
|
|
on = True
|
|
for light in self.m_lights:
|
|
if not light.is_on():
|
|
on = False
|
|
return on
|
|
|
|
def is_any_on(self) -> bool:
|
|
"""Check if any of the lights are on and reachable
|
|
|
|
Returns:
|
|
bool: True if any light in the group is on and reachable, otherwise False
|
|
"""
|
|
# Dont believe the API, both on and reachable to be on
|
|
on = False
|
|
for light in self.m_lights:
|
|
if light.is_on():
|
|
on = True
|
|
return on
|
|
|
|
def remove_light(self, light: HueLight):
|
|
"""Remove a light
|
|
"""
|
|
if light in self.m_lights:
|
|
self.m_lights.remove(light)
|
|
|
|
def toggle(self):
|
|
"""Toggle all lights of the group
|
|
"""
|
|
for light in self.m_lights:
|
|
light.toggle()
|
|
self.update_state()
|
|
|
|
def turn_off(self):
|
|
"""turn off all lights in the group
|
|
"""
|
|
state: str = '{"on": false}'
|
|
self.set_state(state)
|
|
|
|
def turn_on(self):
|
|
"""Turn on all lights in the group
|
|
"""
|
|
state: str = '{"on": true}'
|
|
self.set_state(state)
|
|
|
|
def set_state(self, state: str) -> requests.Response:
|
|
"""Helper method to set the state of the group
|
|
|
|
Args:
|
|
state (str): The state of the group
|
|
Possible attributes are:
|
|
* on: True/False
|
|
* bri: 0-254
|
|
* hue: 0-65535
|
|
* sat: 0-254
|
|
* xy: [0.0-1.0,0.0-1.0]
|
|
* ct: 153-500
|
|
* alert: "none"/"select"/"lselect"
|
|
* effect: "none"/"colorloop"
|
|
* transitiontime: 0-65535 (multiple of 100ms, default is 4)
|
|
* bri_inc: -254-254
|
|
* sat_inc: -254-254
|
|
* hue_inc: -65534-65534
|
|
* ct_inc: -65534-65534
|
|
* xy_inc: -0.5-0.5
|
|
* scene: "Scene identifier"
|
|
|
|
Returns:
|
|
requests.Response: The API response
|
|
"""
|
|
path: str = "{}/groups/{}/action".format(self.m_parent_bridge_user, self.m_id)
|
|
method: str = "PUT"
|
|
response = make_request(self.m_parent_bridge_ip, path, method, state)
|
|
self.update_state()
|
|
return response
|
|
|
|
def update_state(self):
|
|
"""Update the state after a possible change
|
|
"""
|
|
state: dict = {'all_on': self.is_any_on(), 'any_on': self.is_any_on()}
|
|
self.m_state = HueGroup.State(state)
|