#!/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)