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.
tinge/tinge/HueGroup/__init__.py

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)