UE4 Compile Alerts using Philips Hue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# -*- coding: utf-8 -*- | |
''' | |
phue by Nathanaël Lécaudé - A Philips Hue Python library | |
Contributions by Marshall Perrin, Justin Lintz | |
https://github.com/studioimaginaire/phue | |
Original protocol hacking by rsmck : http://rsmck.co.uk/hue | |
Published under the GWTFPL - http://www.wtfpl.net | |
"Hue Personal Wireless Lighting" is a trademark owned by Koninklijke Philips Electronics N.V., see www.meethue.com for more information. | |
I am in no way affiliated with the Philips organization. | |
''' | |
import json | |
import os | |
import platform | |
import sys | |
import socket | |
if sys.version_info[0] > 2: | |
PY3K = True | |
else: | |
PY3K = False | |
if PY3K: | |
import http.client as httplib | |
else: | |
import httplib | |
import logging | |
logger = logging.getLogger('phue') | |
if platform.system() == 'Windows': | |
USER_HOME = 'USERPROFILE' | |
else: | |
USER_HOME = 'HOME' | |
__version__ = '0.8' | |
class PhueException(Exception): | |
def __init__(self, id, message): | |
self.id = id | |
self.message = message | |
class PhueRegistrationException(PhueException): | |
pass | |
class PhueRequestTimeout(PhueException): | |
pass | |
class Light(object): | |
""" Hue Light object | |
Light settings can be accessed or set via the properties of this object. | |
""" | |
def __init__(self, bridge, light_id): | |
self.bridge = bridge | |
self.light_id = light_id | |
self._name = None | |
self._on = None | |
self._brightness = None | |
self._colormode = None | |
self._hue = None | |
self._saturation = None | |
self._xy = None | |
self._colortemp = None | |
self._effect = None | |
self._alert = None | |
self.transitiontime = None # default | |
self._reset_bri_after_on = None | |
def __repr__(self): | |
# like default python repr function, but add light name | |
return '<{0}.{1} object "{2}" at {3}>'.format( | |
self.__class__.__module__, | |
self.__class__.__name__, | |
self.name, | |
hex(id(self))) | |
# Wrapper functions for get/set through the bridge, adding support for | |
# remembering the transitiontime parameter if the user has set it | |
def _get(self, *args, **kwargs): | |
return self.bridge.get_light(self.light_id, *args, **kwargs) | |
def _set(self, *args, **kwargs): | |
if self.transitiontime is not None: | |
kwargs['transitiontime'] = self.transitiontime | |
logger.debug("Setting with transitiontime = {0} ds = {1} s".format( | |
self.transitiontime, float(self.transitiontime) / 10)) | |
if args[0] == 'on' and args[1] is False: | |
self._reset_bri_after_on = True | |
return self.bridge.set_light(self.light_id, *args, **kwargs) | |
@property | |
def name(self): | |
'''Get or set the name of the light [string]''' | |
if PY3K: | |
self._name = self._get('name') | |
else: | |
self._name = self._get('name').encode('utf-8') | |
return self._name | |
@name.setter | |
def name(self, value): | |
old_name = self.name | |
self._name = value | |
self._set('name', self._name) | |
logger.debug("Renaming light from '{0}' to '{1}'".format( | |
old_name, value)) | |
self.bridge.lights_by_name[self.name] = self | |
del self.bridge.lights_by_name[old_name] | |
@property | |
def on(self): | |
'''Get or set the state of the light [True|False]''' | |
self._on = self._get('on') | |
return self._on | |
@on.setter | |
def on(self, value): | |
# Some added code here to work around known bug where | |
# turning off with transitiontime set makes it restart on brightness = 1 | |
# see | |
# http://www.everyhue.com/vanilla/discussion/204/bug-with-brightness-when-requesting-ontrue-transitiontime5 | |
# if we're turning off, save whether this bug in the hardware has been | |
# invoked | |
if self._on and value is False: | |
self._reset_bri_after_on = self.transitiontime is not None | |
if self._reset_bri_after_on: | |
logger.warning( | |
'Turned off light with transitiontime specified, brightness will be reset on power on') | |
self._set('on', value) | |
# work around bug by resetting brightness after a power on | |
if self._on is False and value is True: | |
if self._reset_bri_after_on: | |
logger.warning( | |
'Light was turned off with transitiontime specified, brightness needs to be reset now.') | |
self.brightness = self._brightness | |
self._reset_bri_after_on = False | |
self._on = value | |
@property | |
def colormode(self): | |
'''Get the color mode of the light [hs|xy|ct]''' | |
self._colormode = self._get('colormode') | |
return self._colormode | |
@property | |
def brightness(self): | |
'''Get or set the brightness of the light [0-254]. | |
0 is not off''' | |
self._brightness = self._get('bri') | |
return self._brightness | |
@brightness.setter | |
def brightness(self, value): | |
self._brightness = value | |
result = self._set('bri', self._brightness) | |
@property | |
def hue(self): | |
'''Get or set the hue of the light [0-65535]''' | |
self._hue = self._get('hue') | |
return self._hue | |
@hue.setter | |
def hue(self, value): | |
self._hue = int(value) | |
self._set('hue', self._hue) | |
@property | |
def saturation(self): | |
'''Get or set the saturation of the light [0-254] | |
0 = white | |
254 = most saturated | |
''' | |
self._saturation = self._get('sat') | |
return self._saturation | |
@saturation.setter | |
def saturation(self, value): | |
self._saturation = value | |
self._set('sat', self._saturation) | |
@property | |
def xy(self): | |
'''Get or set the color coordinates of the light [ [0.0-1.0, 0.0-1.0] ] | |
This is in a color space similar to CIE 1931 (but not quite identical) | |
''' | |
self._xy = self._get('xy') | |
return self._xy | |
@xy.setter | |
def xy(self, value): | |
self._xy = value | |
self._set('xy', self._xy) | |
@property | |
def colortemp(self): | |
'''Get or set the color temperature of the light, in units of mireds [154-500]''' | |
self._colortemp = self._get('ct') | |
return self._colortemp | |
@colortemp.setter | |
def colortemp(self, value): | |
if value < 154: | |
logger.warn('154 mireds is coolest allowed color temp') | |
elif value > 500: | |
logger.warn('500 mireds is warmest allowed color temp') | |
self._colortemp = value | |
self._set('ct', self._colortemp) | |
@property | |
def colortemp_k(self): | |
'''Get or set the color temperature of the light, in units of Kelvin [2000-6500]''' | |
self._colortemp = self._get('ct') | |
return int(round(1e6 / self._colortemp)) | |
@colortemp_k.setter | |
def colortemp_k(self, value): | |
if value > 6500: | |
logger.warn('6500 K is max allowed color temp') | |
value = 6500 | |
elif value < 2000: | |
logger.warn('2000 K is min allowed color temp') | |
value = 2000 | |
colortemp_mireds = int(round(1e6 / value)) | |
logger.debug("{0:d} K is {1} mireds".format(value, colortemp_mireds)) | |
self.colortemp = colortemp_mireds | |
@property | |
def effect(self): | |
'''Check the effect setting of the light. [none|colorloop]''' | |
self._effect = self._get('effect') | |
return self._effect | |
@effect.setter | |
def effect(self, value): | |
self._effect = value | |
self._set('effect', self._effect) | |
@property | |
def alert(self): | |
'''Get or set the alert state of the light [select|lselect|none]''' | |
self._alert = self._get('alert') | |
return self._alert | |
@alert.setter | |
def alert(self, value): | |
if value is None: | |
value = 'none' | |
self._alert = value | |
self._set('alert', self._alert) | |
class Group(Light): | |
""" A group of Hue lights, tracked as a group on the bridge | |
Example: | |
>>> b = Bridge() | |
>>> g1 = Group(b, 1) | |
>>> g1.hue = 50000 # all lights in that group turn blue | |
>>> g1.on = False # all will turn off | |
>>> g2 = Group(b, 'Kitchen') # you can also look up groups by name | |
>>> # will raise a LookupError if the name doesn't match | |
""" | |
def __init__(self, bridge, group_id): | |
Light.__init__(self, bridge, None) | |
del self.light_id # not relevant for a group | |
try: | |
self.group_id = int(group_id) | |
except: | |
name = group_id | |
groups = bridge.get_group() | |
for idnumber, info in groups.items(): | |
if PY3K: | |
if info['name'] == name: | |
self.group_id = int(idnumber) | |
break | |
else: | |
if info['name'] == unicode(name, encoding='utf-8'): | |
self.group_id = int(idnumber) | |
break | |
else: | |
raise LookupError("Could not find a group by that name.") | |
# Wrapper functions for get/set through the bridge, adding support for | |
# remembering the transitiontime parameter if the user has set it | |
def _get(self, *args, **kwargs): | |
return self.bridge.get_group(self.group_id, *args, **kwargs) | |
def _set(self, *args, **kwargs): | |
# let's get basic group functionality working first before adding | |
# transition time... | |
if self.transitiontime is not None: | |
kwargs['transitiontime'] = self.transitiontime | |
logger.debug("Setting with transitiontime = {0} ds = {1} s".format( | |
self.transitiontime, float(self.transitiontime) / 10)) | |
if args[0] == 'on' and args[1] is False: | |
self._reset_bri_after_on = True | |
return self.bridge.set_group(self.group_id, *args, **kwargs) | |
@property | |
def name(self): | |
'''Get or set the name of the light group [string]''' | |
if PY3K: | |
self._name = self._get('name') | |
else: | |
self._name = self._get('name').encode('utf-8') | |
return self._name | |
@name.setter | |
def name(self, value): | |
old_name = self.name | |
self._name = value | |
logger.debug("Renaming light group from '{0}' to '{1}'".format( | |
old_name, value)) | |
self._set('name', self._name) | |
@property | |
def lights(self): | |
""" Return a list of all lights in this group""" | |
# response = self.bridge.request('GET', '/api/{0}/groups/{1}'.format(self.bridge.username, self.group_id)) | |
# return [Light(self.bridge, int(l)) for l in response['lights']] | |
return [Light(self.bridge, int(l)) for l in self._get('lights')] | |
@lights.setter | |
def lights(self, value): | |
""" Change the lights that are in this group""" | |
logger.debug("Setting lights in group {0} to {1}".format( | |
self.group_id, str(value))) | |
self._set('lights', value) | |
class AllLights(Group): | |
""" All the Hue lights connected to your bridge | |
This makes use of the semi-documented feature that | |
"Group 0" of lights appears to be a group automatically | |
consisting of all lights. This is not returned by | |
listing the groups, but is accessible if you explicitly | |
ask for group 0. | |
""" | |
def __init__(self, bridge=None): | |
if bridge is None: | |
bridge = Bridge() | |
Group.__init__(self, bridge, 0) | |
class Bridge(object): | |
""" Interface to the Hue ZigBee bridge | |
You can obtain Light objects by calling the get_light_objects method: | |
>>> b = Bridge(ip='192.168.1.100') | |
>>> b.get_light_objects() | |
[<phue.Light at 0x10473d750>, | |
<phue.Light at 0x1046ce110>] | |
Or more succinctly just by accessing this Bridge object as a list or dict: | |
>>> b[1] | |
<phue.Light at 0x10473d750> | |
>>> b['Kitchen'] | |
<phue.Light at 0x10473d750> | |
""" | |
def __init__(self, ip=None, username=None, config_file_path=None): | |
""" Initialization function. | |
Parameters: | |
------------ | |
ip : string | |
IP address as dotted quad | |
username : string, optional | |
""" | |
if config_file_path is not None: | |
self.config_file_path = config_file_path | |
elif os.getenv(USER_HOME) is not None and os.access(os.getenv(USER_HOME), os.W_OK): | |
self.config_file_path = os.path.join(os.getenv(USER_HOME), '.python_hue') | |
elif 'iPad' in platform.machine() or 'iPhone' in platform.machine() or 'iPad' in platform.machine(): | |
self.config_file_path = os.path.join(os.getenv(USER_HOME), 'Documents', '.python_hue') | |
else: | |
self.config_file_path = os.path.join(os.getcwd(), '.python_hue') | |
self.ip = ip | |
self.username = username | |
self.lights_by_id = {} | |
self.lights_by_name = {} | |
self._name = None | |
# self.minutes = 600 # these do not seem to be used anywhere? | |
# self.seconds = 10 | |
self.connect() | |
@property | |
def name(self): | |
'''Get or set the name of the bridge [string]''' | |
self._name = self.request( | |
'GET', '/api/' + self.username + '/config')['name'] | |
return self._name | |
@name.setter | |
def name(self, value): | |
self._name = value | |
data = {'name': self._name} | |
self.request( | |
'PUT', '/api/' + self.username + '/config', json.dumps(data)) | |
def request(self, mode='GET', address=None, data=None): | |
""" Utility function for HTTP GET/PUT requests for the API""" | |
connection = httplib.HTTPConnection(self.ip, timeout=10) | |
try: | |
if mode == 'GET' or mode == 'DELETE': | |
connection.request(mode, address) | |
if mode == 'PUT' or mode == 'POST': | |
connection.request(mode, address, data) | |
logger.debug("{0} {1} {2}".format(mode, address, str(data))) | |
except socket.timeout: | |
error = "{} Request to {}{} timed out.".format(mode, self.ip, address) | |
logger.exception(error) | |
raise PhueRequestTimeout(None, error) | |
result = connection.getresponse() | |
connection.close() | |
if PY3K: | |
return json.loads(str(result.read(), encoding='utf-8')) | |
else: | |
result_str = result.read() | |
logger.debug(result_str) | |
return json.loads(result_str) | |
def get_ip_address(self, set_result=False): | |
""" Get the bridge ip address from the meethue.com nupnp api """ | |
connection = httplib.HTTPConnection('www.meethue.com') | |
connection.request('GET', '/api/nupnp') | |
logger.info('Connecting to meethue.com/api/nupnp') | |
result = connection.getresponse() | |
if PY3K: | |
data = json.loads(str(result.read(), encoding='utf-8')) | |
else: | |
result_str = result.read() | |
data = json.loads(result_str) | |
""" close connection after read() is done, to prevent issues with read() """ | |
connection.close() | |
ip = str(data[0]['internalipaddress']) | |
if ip is not '': | |
if set_result: | |
self.ip = ip | |
return ip | |
else: | |
return False | |
def register_app(self): | |
""" Register this computer with the Hue bridge hardware and save the resulting access token """ | |
registration_request = {"devicetype": "python_hue"} | |
data = json.dumps(registration_request) | |
response = self.request('POST', '/api', data) | |
for line in response: | |
for key in line: | |
if 'success' in key: | |
with open(self.config_file_path, 'w') as f: | |
logger.info( | |
'Writing configuration file to ' + self.config_file_path) | |
f.write(json.dumps({self.ip: line['success']})) | |
logger.info('Reconnecting to the bridge') | |
self.connect() | |
if 'error' in key: | |
error_type = line['error']['type'] | |
if error_type == 101: | |
raise PhueRegistrationException(error_type, | |
'The link button has not been pressed in the last 30 seconds.') | |
if error_type == 7: | |
raise PhueException(error_type, | |
'Unknown username') | |
def connect(self): | |
""" Connect to the Hue bridge """ | |
logger.info('Attempting to connect to the bridge...') | |
# If the ip and username were provided at class init | |
if self.ip is not None and self.username is not None: | |
logger.info('Using ip: ' + self.ip) | |
logger.info('Using username: ' + self.username) | |
return | |
if self.ip is None or self.username is None: | |
try: | |
with open(self.config_file_path) as f: | |
config = json.loads(f.read()) | |
if self.ip is None: | |
self.ip = list(config.keys())[0] | |
logger.info('Using ip from config: ' + self.ip) | |
else: | |
logger.info('Using ip: ' + self.ip) | |
if self.username is None: | |
self.username = config[self.ip]['username'] | |
logger.info( | |
'Using username from config: ' + self.username) | |
else: | |
logger.info('Using username: ' + self.username) | |
except Exception as e: | |
logger.info( | |
'Error opening config file, will attempt bridge registration') | |
self.register_app() | |
def get_light_id_by_name(self, name): | |
""" Lookup a light id based on string name. Case-sensitive. """ | |
lights = self.get_light() | |
for light_id in lights: | |
if PY3K: | |
if name == lights[light_id]['name']: | |
return light_id | |
else: | |
if unicode(name, encoding='utf-8') == lights[light_id]['name']: | |
return light_id | |
return False | |
def get_light_objects(self, mode='list'): | |
"""Returns a collection containing the lights, either by name or id (use 'id' or 'name' as the mode) | |
The returned collection can be either a list (default), or a dict. | |
Set mode='id' for a dict by light ID, or mode='name' for a dict by light name. """ | |
if self.lights_by_id == {}: | |
lights = self.request('GET', '/api/' + self.username + '/lights/') | |
for light in lights: | |
self.lights_by_id[int(light)] = Light(self, int(light)) | |
self.lights_by_name[lights[light][ | |
'name']] = self.lights_by_id[int(light)] | |
if mode == 'id': | |
return self.lights_by_id | |
if mode == 'name': | |
return self.lights_by_name | |
if mode == 'list': | |
return [self.lights_by_id[x] for x in range(1, len(self.lights_by_id) + 1)] | |
def __getitem__(self, key): | |
""" Lights are accessibly by indexing the bridge either with | |
an integer index or string name. """ | |
if self.lights_by_id == {}: | |
self.get_light_objects() | |
try: | |
return self.lights_by_id[key] | |
except: | |
try: | |
if PY3K: | |
return self.lights_by_name[key] | |
else: | |
return self.lights_by_name[unicode(key, encoding='utf-8')] | |
except: | |
raise KeyError( | |
'Not a valid key (integer index starting with 1, or light name): ' + str(key)) | |
@property | |
def lights(self): | |
""" Access lights as a list """ | |
return self.get_light_objects() | |
def get_api(self): | |
""" Returns the full api dictionary """ | |
return self.request('GET', '/api/' + self.username) | |
def get_light(self, light_id=None, parameter=None): | |
""" Gets state by light_id and parameter""" | |
if PY3K: | |
if isinstance(light_id, str): | |
light_id = self.get_light_id_by_name(light_id) | |
else: | |
if isinstance(light_id, str) or isinstance(light_id, unicode): | |
light_id = self.get_light_id_by_name(light_id) | |
if light_id is None: | |
return self.request('GET', '/api/' + self.username + '/lights/') | |
state = self.request( | |
'GET', '/api/' + self.username + '/lights/' + str(light_id)) | |
if parameter is None: | |
return state | |
if parameter == 'name': | |
return state[parameter] | |
else: | |
return state['state'][parameter] | |
def set_light(self, light_id, parameter, value=None, transitiontime=None): | |
""" Adjust properties of one or more lights. | |
light_id can be a single lamp or an array of lamps | |
parameters: 'on' : True|False , 'bri' : 0-254, 'sat' : 0-254, 'ct': 154-500 | |
transitiontime : in **deciseconds**, time for this transition to take place | |
Note that transitiontime only applies to *this* light | |
command, it is not saved as a setting for use in the future! | |
Use the Light class' transitiontime attribute if you want | |
persistent time settings. | |
""" | |
if isinstance(parameter, dict): | |
data = parameter | |
else: | |
data = {parameter: value} | |
if transitiontime is not None: | |
data['transitiontime'] = int(round( | |
transitiontime)) # must be int for request format | |
light_id_array = light_id | |
if PY3K: | |
if isinstance(light_id, int) or isinstance(light_id, str): | |
light_id_array = [light_id] | |
else: | |
if isinstance(light_id, int) or isinstance(light_id, str) or isinstance(light_id, unicode): | |
light_id_array = [light_id] | |
result = [] | |
for light in light_id_array: | |
logger.debug(str(data)) | |
if parameter == 'name': | |
result.append(self.request('PUT', '/api/' + self.username + '/lights/' + str( | |
light_id), json.dumps(data))) | |
else: | |
if PY3K: | |
if isinstance(light, str): | |
converted_light = self.get_light_id_by_name(light) | |
else: | |
converted_light = light | |
else: | |
if isinstance(light, str) or isinstance(light, unicode): | |
converted_light = self.get_light_id_by_name(light) | |
else: | |
converted_light = light | |
result.append(self.request('PUT', '/api/' + self.username + '/lights/' + str( | |
converted_light) + '/state', json.dumps(data))) | |
if 'error' in list(result[-1][0].keys()): | |
logger.warn("ERROR: {0} for light {1}".format( | |
result[-1][0]['error']['description'], light)) | |
logger.debug(result) | |
return result | |
# Groups of lights ##### | |
@property | |
def groups(self): | |
""" Access groups as a list """ | |
return [Group(self, int(groupid)) for groupid in self.get_group().keys()] | |
def get_group_id_by_name(self, name): | |
""" Lookup a group id based on string name. Case-sensitive. """ | |
groups = self.get_group() | |
for group_id in groups: | |
if PY3K: | |
if name == groups[group_id]['name']: | |
return group_id | |
else: | |
if unicode(name, encoding='utf-8') == groups[group_id]['name']: | |
return group_id | |
return False | |
def get_group(self, group_id=None, parameter=None): | |
if PY3K: | |
if isinstance(group_id, str): | |
group_id = self.get_group_id_by_name(group_id) | |
else: | |
if isinstance(group_id, str) or isinstance(group_id, unicode): | |
group_id = self.get_group_id_by_name(group_id) | |
if group_id is False: | |
logger.error('Group name does not exit') | |
return | |
if group_id is None: | |
return self.request('GET', '/api/' + self.username + '/groups/') | |
if parameter is None: | |
return self.request('GET', '/api/' + self.username + '/groups/' + str(group_id)) | |
elif parameter == 'name' or parameter == 'lights': | |
return self.request('GET', '/api/' + self.username + '/groups/' + str(group_id))[parameter] | |
else: | |
return self.request('GET', '/api/' + self.username + '/groups/' + str(group_id))['action'][parameter] | |
def set_group(self, group_id, parameter, value=None, transitiontime=None): | |
""" Change light settings for a group | |
group_id : int, id number for group | |
parameter : 'name' or 'lights' | |
value: string, or list of light IDs if you're setting the lights | |
""" | |
if isinstance(parameter, dict): | |
data = parameter | |
elif parameter == 'lights' and (isinstance(value, list) or isinstance(value, int)): | |
if isinstance(value, int): | |
value = [value] | |
data = {parameter: [str(x) for x in value]} | |
else: | |
data = {parameter: value} | |
if transitiontime is not None: | |
data['transitiontime'] = int(round( | |
transitiontime)) # must be int for request format | |
group_id_array = group_id | |
if PY3K: | |
if isinstance(group_id, int) or isinstance(group_id, str): | |
group_id_array = [group_id] | |
else: | |
if isinstance(group_id, int) or isinstance(group_id, str) or isinstance(group_id, unicode): | |
group_id_array = [group_id] | |
result = [] | |
for group in group_id_array: | |
logger.debug(str(data)) | |
if PY3K: | |
if isinstance(group, str): | |
converted_group = self.get_group_id_by_name(group) | |
else: | |
converted_group = group | |
else: | |
if isinstance(group, str) or isinstance(group, unicode): | |
converted_group = self.get_group_id_by_name(group) | |
else: | |
converted_group = group | |
if converted_group is False: | |
logger.error('Group name does not exit') | |
return | |
if parameter == 'name' or parameter == 'lights': | |
result.append(self.request('PUT', '/api/' + self.username + '/groups/' + str(converted_group), json.dumps(data))) | |
else: | |
result.append(self.request('PUT', '/api/' + self.username + '/groups/' + str(converted_group) + '/action', json.dumps(data))) | |
if 'error' in list(result[-1][0].keys()): | |
logger.warn("ERROR: {0} for group {1}".format( | |
result[-1][0]['error']['description'], group)) | |
logger.debug(result) | |
return result | |
def create_group(self, name, lights=None): | |
""" Create a group of lights | |
Parameters | |
------------ | |
name : string | |
Name for this group of lights | |
lights : list | |
List of lights to be in the group. | |
""" | |
data = {'lights': [str(x) for x in lights], 'name': name} | |
return self.request('POST', '/api/' + self.username + '/groups/', json.dumps(data)) | |
def delete_group(self, group_id): | |
return self.request('DELETE', '/api/' + self.username + '/groups/' + str(group_id)) | |
# Schedules ##### | |
def get_schedule(self, schedule_id=None, parameter=None): | |
if schedule_id is None: | |
return self.request('GET', '/api/' + self.username + '/schedules') | |
if parameter is None: | |
return self.request('GET', '/api/' + self.username + '/schedules/' + str(schedule_id)) | |
def create_schedule(self, name, time, light_id, data, description=' '): | |
schedule = { | |
'name': name, | |
'time': time, | |
'description': description, | |
'command': | |
{ | |
'method': 'PUT', | |
'address': '/api/' + self.username + | |
'/lights/' + str(light_id) + '/state', | |
'body': data | |
} | |
} | |
return self.request('POST', '/api/' + self.username + '/schedules', json.dumps(schedule)) | |
def create_group_schedule(self, name, time, group_id, data, description=' '): | |
schedule = { | |
'name': name, | |
'time': time, | |
'description': description, | |
'command': | |
{ | |
'method': 'PUT', | |
'address': '/api/' + self.username + | |
'/groups/' + str(group_id) + '/action', | |
'body': data | |
} | |
} | |
return self.request('POST', '/api/' + self.username + '/schedules', json.dumps(schedule)) | |
def delete_schedule(self, schedule_id): | |
return self.request('DELETE', '/api/' + self.username + '/schedules/' + str(schedule_id)) | |
if __name__ == '__main__': | |
import argparse | |
logging.basicConfig(level=logging.DEBUG) | |
parser = argparse.ArgumentParser() | |
parser.add_argument('--host', required=True) | |
parser.add_argument('--config-file-path', required=False) | |
args = parser.parse_args() | |
while True: | |
try: | |
b = Bridge(args.host, config_file_path=args.config_file_path) | |
break | |
except PhueRegistrationException as e: | |
if PY3K: | |
input('Press button on Bridge then hit Enter to try again') | |
else: | |
raw_input('Press button on Bridge then hit Enter to try again') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from time import sleep | |
import time | |
import datetime | |
import zachhue | |
import os | |
import winsound, sys | |
lastColor = zachhue.office.xy | |
lastBrightness = zachhue.office.brightness | |
bIsBuilding = False | |
startTime = 0 | |
def beep(sound): | |
winsound.PlaySound('%s.wav' % sound, winsound.SND_FILENAME) | |
def showCompilingLight(): | |
lastColor = zachhue.office.xy | |
xy = zachhue.RGBtoXY(250,20,20) | |
zachhue.OnXY(zachhue.office, xy, 250, 3) | |
def restorePreviousColor(): | |
zachhue.OnXY(zachhue.office, lastColor, lastBrightness, 3) | |
def logBuildTime(): | |
with open("d:\Dropbox\UnrealBuildLog.txt", "a") as myfile: | |
date = datetime.datetime.now() | |
elapsed = time.time() - startTime | |
myfile.write("\n%s" % date + "," + str(elapsed)) | |
while 1: | |
PROCNAME = "UnrealBuildTool.exe" | |
output = os.popen('tasklist /FI "IMAGENAME eq ' + PROCNAME + '"').read() | |
if not bIsBuilding and PROCNAME in output: | |
bIsBuilding = True | |
startTime = time.time() | |
showCompilingLight() | |
elif bIsBuilding and not PROCNAME in output: | |
bIsBuilding = False | |
logBuildTime() | |
restorePreviousColor() | |
beep("subtle_confirm_13") | |
sleep(1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# Misc functions for controlling lights and bridge via phue | |
from phue import Bridge | |
from time import sleep | |
import math | |
# Set this to yoru bridge IP | |
b = Bridge('192.168.0.2') | |
lights = b.get_light_objects('name') | |
# Change this array to match your light names | |
office = lights['Lamp'] | |
theater = lights['Theater'] | |
bedroom = lights['Bedroom'] | |
def OnXY(lamp, xy, b, time): | |
lamp.on = True | |
lamp.effect = 'none' | |
lamp.transitiontime = time | |
lamp.xy = xy | |
lamp.brightness = b | |
def OnHue(lamp, hue, saturation, brightness, time): | |
lamp.on = True | |
lamp.effect = 'none' | |
lamp.transitiontime = time | |
lamp.hue = hue | |
lamp.brightness = brightness | |
lamp.saturation = saturation | |
def Cylon(lamp, hue): | |
if not lamp.on: | |
lamp.on = True | |
lamp.transitiontime = 4 | |
lamp.hue = hue | |
lamp.brightness = 254 | |
lamp.saturation = 254 | |
lamp.effect = 'colorloop' | |
timeFlop = False | |
def Blink(lamp, hue, brightnesses): | |
wasOn = lamp.on | |
if not wasOn: | |
lamp.on = True | |
oldEffect = lamp.effect | |
lamp.effect = 'none' | |
oldHue = lamp.hue | |
oldBrightness = lamp.brightness | |
oldSaturation = lamp.saturation | |
lamp.transitiontime = 4 | |
lamp.hue = hue | |
lamp.brightness = 254 | |
lamp.saturation = 254 | |
timeFlop = False | |
for brightness in brightnesses: | |
lamp.transitiontime = 2 | |
lamp.brightness = brightness | |
if timeFlop: | |
sleep(0.45) | |
else: | |
sleep(0.3) | |
timeFlop = not timeFlop | |
lamp.transitiontime = 4 | |
lamp.hue = oldHue | |
lamp.brightness = oldBrightness | |
lamp.saturation = oldSaturation | |
lamp.on = wasOn | |
lamp.effect = oldEffect | |
def EnhanceColor(normalized): | |
if normalized > 0.04045: | |
return math.pow( (normalized + 0.055) / (1.0 + 0.055), 2.4) | |
else: | |
return normalized / 12.92 | |
def RGBtoXY(r, g, b): | |
rNorm = r / 255.0 | |
gNorm = g / 255.0 | |
bNorm = b / 255.0 | |
rFinal = EnhanceColor(rNorm) | |
gFinal = EnhanceColor(gNorm) | |
bFinal = EnhanceColor(bNorm) | |
X = rFinal * 0.649926 + gFinal * 0.103455 + bFinal * 0.197109 | |
Y = rFinal * 0.234327 + gFinal * 0.743075 + bFinal * 0.022598 | |
Z = rFinal * 0.000000 + gFinal * 0.053077 + bFinal * 1.035763 | |
if X + Y + Z == 0: | |
return (0,0) | |
else: | |
xFinal = X / (X + Y + Z) | |
yFinal = Y / (X + Y + Z) | |
return (xFinal, yFinal) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Love it