Skip to content

Instantly share code, notes, and snippets.

@error454
Last active February 24, 2022 21:07
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save error454/1eed2db4cce45716c8c5 to your computer and use it in GitHub Desktop.
Save error454/1eed2db4cce45716c8c5 to your computer and use it in GitHub Desktop.
UE4 Compile Alerts using Philips Hue
#!/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')
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)
#!/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)
@Nathan-Tran
Copy link

Love it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment