phue.py
Go to the documentation of this file.
00001 #!/usr/bin/python
00002 # -*- coding: utf-8 -*-
00003 
00004 '''
00005 phue by Nathanaël Lécaudé - A Philips Hue Python library
00006 Contributions by Marshall Perrin, Justin Lintz
00007 https://github.com/studioimaginaire/phue
00008 Original protocol hacking by rsmck : http://rsmck.co.uk/hue
00009 
00010 Published under the GWTFPL - http://www.wtfpl.net
00011 
00012 "Hue Personal Wireless Lighting" is a trademark owned by Koninklijke Philips Electronics N.V., see www.meethue.com for more information.
00013 I am in no way affiliated with the Philips organization.
00014 
00015 Modification by dwlee
00016 - Delete config file writer
00017 - Create the exception.py and move the exception class
00018 - Add the "reachable" flag.
00019     Possible to get the each bulb validation.
00020 - Connection method change.
00021     No more use the user name. The user name is pre-define to "newdeveloper". It has the all permission of hue restapi.
00022 '''
00023 
00024 import json
00025 import platform
00026 import sys
00027 import socket
00028 from exceptions import * 
00029 if sys.version_info[0] > 2:
00030     PY3K = True
00031 else:
00032     PY3K = False
00033 
00034 if PY3K:
00035     import http.client as httplib
00036 else:
00037     import httplib
00038 
00039 import logging
00040 logger = logging.getLogger('phue')
00041 
00042 
00043 if platform.system() == 'Windows':
00044     USER_HOME = 'USERPROFILE'
00045 else:
00046     USER_HOME = 'HOME'
00047 
00048 __version__ = '0.8'
00049 
00050 
00051 class Light(object):
00052 
00053     """ Hue Light object
00054 
00055     Light settings can be accessed or set via the properties of this object.
00056 
00057     """
00058     def __init__(self, bridge, light_id):
00059         self.bridge = bridge
00060         self.light_id = light_id
00061 
00062         self._name = None
00063         self._on = None
00064         self._brightness = None
00065         self._colormode = None
00066         self._hue = None
00067         self._saturation = None
00068         self._xy = None
00069         self._colortemp = None
00070         self._effect = None
00071         self._alert = None
00072         self.transitiontime = None  # default
00073         self._reset_bri_after_on = None
00074         self._reachable = False  # default
00075 
00076     def __repr__(self):
00077         # like default python repr function, but add light name
00078         return '<{0}.{1} object "{2}" at {3}>'.format(
00079             self.__class__.__module__,
00080             self.__class__.__name__,
00081             self.name,
00082             hex(id(self)))
00083 
00084     # Wrapper functions for get/set through the bridge, adding support for
00085     # remembering the transitiontime parameter if the user has set it
00086     def _get(self, *args, **kwargs):
00087         return self.bridge.get_light(self.light_id, *args, **kwargs)
00088 
00089     def _set(self, *args, **kwargs):
00090 
00091         if self.transitiontime is not None:
00092             kwargs['transitiontime'] = self.transitiontime
00093             logger.debug("Setting with transitiontime = {0} ds = {1} s".format(
00094                 self.transitiontime, float(self.transitiontime) / 10))
00095 
00096             if args[0] == 'on' and args[1] is False:
00097                 self._reset_bri_after_on = True
00098         return self.bridge.set_light(self.light_id, *args, **kwargs)
00099 
00100     @property
00101     def name(self):
00102         '''Get or set the name of the light [string]'''
00103         if PY3K:
00104             self._name = self._get('name')
00105         else:
00106             self._name = self._get('name').encode('utf-8')
00107         return self._name
00108 
00109     @name.setter
00110     def name(self, value):
00111         old_name = self.name
00112         self._name = value
00113         self._set('name', self._name)
00114 
00115         logger.debug("Renaming light from '{0}' to '{1}'".format(
00116             old_name, value))
00117 
00118         self.bridge.lights_by_name[self.name] = self
00119         del self.bridge.lights_by_name[old_name]
00120 
00121     @property
00122     def on(self):
00123         '''Get or set the state of the light [True|False]'''
00124         self._on = self._get('on')
00125         return self._on
00126 
00127     @on.setter
00128     def on(self, value):
00129 
00130         # Some added code here to work around known bug where
00131         # turning off with transitiontime set makes it restart on brightness = 1
00132         # see
00133         # http://www.everyhue.com/vanilla/discussion/204/bug-with-brightness-when-requesting-ontrue-transitiontime5
00134 
00135         # if we're turning off, save whether this bug in the hardware has been
00136         # invoked
00137         if self._on and value is False:
00138             self._reset_bri_after_on = self.transitiontime is not None
00139             if self._reset_bri_after_on:
00140                 logger.warning(
00141                     'Turned off light with transitiontime specified, brightness will be reset on power on')
00142 
00143         self._set('on', value)
00144 
00145         # work around bug by resetting brightness after a power on
00146         if self._on is False and value is True:
00147             if self._reset_bri_after_on:
00148                 logger.warning(
00149                     'Light was turned off with transitiontime specified, brightness needs to be reset now.')
00150                 self.brightness = self._brightness
00151                 self._reset_bri_after_on = False
00152 
00153         self._on = value
00154 
00155     @property
00156     def colormode(self):
00157         '''Get the color mode of the light [hs|xy|ct]'''
00158         self._colormode = self._get('colormode')
00159         return self._colormode
00160 
00161     @property
00162     def brightness(self):
00163         '''Get or set the brightness of the light [0-254].
00164 
00165         0 is not off'''
00166 
00167         self._brightness = self._get('bri')
00168         return self._brightness
00169 
00170     @brightness.setter
00171     def brightness(self, value):
00172         self._brightness = value
00173         result = self._set('bri', self._brightness)
00174 
00175     @property
00176     def hue(self):
00177         '''Get or set the hue of the light [0-65535]'''
00178         self._hue = self._get('hue')
00179         return self._hue
00180 
00181     @hue.setter
00182     def hue(self, value):
00183         self._hue = int(value)
00184         self._set('hue', self._hue)
00185 
00186     @property
00187     def saturation(self):
00188         '''Get or set the saturation of the light [0-254]
00189 
00190         0 = white
00191         254 = most saturated
00192         '''
00193         self._saturation = self._get('sat')
00194         return self._saturation
00195 
00196     @saturation.setter
00197     def saturation(self, value):
00198         self._saturation = value
00199         self._set('sat', self._saturation)
00200 
00201     @property
00202     def xy(self):
00203         '''Get or set the color coordinates of the light [ [0.0-1.0, 0.0-1.0] ]
00204 
00205         This is in a color space similar to CIE 1931 (but not quite identical)
00206         '''
00207         self._xy = self._get('xy')
00208         return self._xy
00209 
00210     @xy.setter
00211     def xy(self, value):
00212         self._xy = value
00213         self._set('xy', self._xy)
00214 
00215     @property
00216     def colortemp(self):
00217         '''Get or set the color temperature of the light, in units of mireds [154-500]'''
00218         self._colortemp = self._get('ct')
00219         return self._colortemp
00220 
00221     @colortemp.setter
00222     def colortemp(self, value):
00223         if value < 154:
00224             logger.warn('154 mireds is coolest allowed color temp')
00225         elif value > 500:
00226             logger.warn('500 mireds is warmest allowed color temp')
00227         self._colortemp = value
00228         self._set('ct', self._colortemp)
00229 
00230     @property
00231     def colortemp_k(self):
00232         '''Get or set the color temperature of the light, in units of Kelvin [2000-6500]'''
00233         self._colortemp = self._get('ct')
00234         return int(round(1e6 / self._colortemp))
00235 
00236     @colortemp_k.setter
00237     def colortemp_k(self, value):
00238         if value > 6500:
00239             logger.warn('6500 K is max allowed color temp')
00240             value = 6500
00241         elif value < 2000:
00242             logger.warn('2000 K is min allowed color temp')
00243             value = 2000
00244 
00245         colortemp_mireds = int(round(1e6 / value))
00246         logger.debug("{0:d} K is {1} mireds".format(value, colortemp_mireds))
00247         self.colortemp = colortemp_mireds
00248 
00249     @property
00250     def effect(self):
00251         '''Check the effect setting of the light. [none|colorloop]'''
00252         self._effect = self._get('effect')
00253         return self._effect
00254 
00255     @effect.setter
00256     def effect(self, value):
00257         self._effect = value
00258         self._set('effect', self._effect)
00259 
00260     @property
00261     def alert(self):
00262         '''Get or set the alert state of the light [select|lselect|none]'''
00263         self._alert = self._get('alert')
00264         return self._alert
00265 
00266     @alert.setter
00267     def alert(self, value):
00268         if value is None:
00269             value = 'none'
00270         self._alert = value
00271         self._set('alert', self._alert)
00272 
00273     @property
00274     def reachable(self):
00275         '''Get the reachable state of the light [select|lselect|none]'''
00276         self._reachable = self._get('reachable')
00277         return self._reachable
00278 
00279 
00280 class Group(Light):
00281 
00282     """ A group of Hue lights, tracked as a group on the bridge
00283 
00284     Example:
00285 
00286         >>> b = Bridge()
00287         >>> g1 = Group(b, 1)
00288         >>> g1.hue = 50000 # all lights in that group turn blue
00289         >>> g1.on = False # all will turn off
00290 
00291         >>> g2 = Group(b, 'Kitchen')  # you can also look up groups by name
00292         >>> # will raise a LookupError if the name doesn't match
00293 
00294     """
00295 
00296     def __init__(self, bridge, group_id):
00297         Light.__init__(self, bridge, None)
00298         del self.light_id  # not relevant for a group
00299 
00300         try:
00301             self.group_id = int(group_id)
00302         except:
00303             name = group_id
00304             groups = bridge.get_group()
00305             for idnumber, info in groups.items():
00306                 if PY3K:
00307                     if info['name'] == name:
00308                         self.group_id = int(idnumber)
00309                         break
00310                 else:
00311                     if info['name'] == unicode(name, encoding='utf-8'):
00312                         self.group_id = int(idnumber)
00313                         break
00314             else:
00315                 raise LookupError("Could not find a group by that name.")
00316 
00317     # Wrapper functions for get/set through the bridge, adding support for
00318     # remembering the transitiontime parameter if the user has set it
00319     def _get(self, *args, **kwargs):
00320         return self.bridge.get_group(self.group_id, *args, **kwargs)
00321 
00322     def _set(self, *args, **kwargs):
00323         # let's get basic group functionality working first before adding
00324         # transition time...
00325         if self.transitiontime is not None:
00326             kwargs['transitiontime'] = self.transitiontime
00327             logger.debug("Setting with transitiontime = {0} ds = {1} s".format(
00328                 self.transitiontime, float(self.transitiontime) / 10))
00329 
00330             if args[0] == 'on' and args[1] is False:
00331                 self._reset_bri_after_on = True
00332         return self.bridge.set_group(self.group_id, *args, **kwargs)
00333 
00334     @property
00335     def name(self):
00336         '''Get or set the name of the light group [string]'''
00337         if PY3K:
00338             self._name = self._get('name')
00339         else:
00340             self._name = self._get('name').encode('utf-8')
00341         return self._name
00342 
00343     @name.setter
00344     def name(self, value):
00345         old_name = self.name
00346         self._name = value
00347         logger.debug("Renaming light group from '{0}' to '{1}'".format(
00348             old_name, value))
00349         self._set('name', self._name)
00350 
00351     @property
00352     def lights(self):
00353         """ Return a list of all lights in this group"""
00354         # response = self.bridge.request('GET', '/api/{0}/groups/{1}'.format(self.bridge.username, self.group_id))
00355         # return [Light(self.bridge, int(l)) for l in response['lights']]
00356         return [Light(self.bridge, int(l)) for l in self._get('lights')]
00357 
00358     @lights.setter
00359     def lights(self, value):
00360         """ Change the lights that are in this group"""
00361         logger.debug("Setting lights in group {0} to {1}".format(
00362             self.group_id, str(value)))
00363         self._set('lights', value)
00364 
00365 
00366 class AllLights(Group):
00367 
00368     """ All the Hue lights connected to your bridge
00369 
00370     This makes use of the semi-documented feature that
00371     "Group 0" of lights appears to be a group automatically
00372     consisting of all lights.  This is not returned by
00373     listing the groups, but is accessible if you explicitly
00374     ask for group 0.
00375     """
00376     def __init__(self, bridge=None):
00377         if bridge is None:
00378             bridge = Bridge()
00379         Group.__init__(self, bridge, 0)
00380 
00381 
00382 class Bridge(object):
00383 
00384     """ Interface to the Hue ZigBee bridge
00385 
00386     You can obtain Light objects by calling the get_light_objects method:
00387 
00388         >>> b = Bridge(ip='192.168.1.100')
00389         >>> b.get_light_objects()
00390         [<phue.Light at 0x10473d750>,
00391          <phue.Light at 0x1046ce110>]
00392 
00393     Or more succinctly just by accessing this Bridge object as a list or dict:
00394 
00395         >>> b[0]
00396         <phue.Light at 0x10473d750>
00397         >>> b['Kitchen']
00398         <phue.Light at 0x1046ce110>
00399 
00400 
00401 
00402     """
00403     def __init__(self, ip=None, username=None):
00404         """ Initialization function.
00405 
00406         Parameters:
00407         ------------
00408         ip : string
00409             IP address as dotted quad
00410         username : string, optional
00411 
00412         """
00413 
00414         self.ip = ip
00415         self.username = "newdeveloper"
00416         self.lights_by_id = {}
00417         self.lights_by_name = {}
00418         self._name = None
00419         self.is_connect = False
00420 
00421         # self.minutes = 600 # these do not seem to be used anywhere?
00422         # self.seconds = 10
00423 
00424         #self.connect()
00425 
00426     @property
00427     def name(self):
00428         '''Get or set the name of the bridge [string]'''
00429         self._name = self.request(
00430             'GET', '/api/' + self.username + '/config')['name']
00431         return self._name
00432 
00433     @name.setter
00434     def name(self, value):
00435         self._name = value
00436         data = {'name': self._name}
00437         self.request(
00438             'PUT', '/api/' + self.username + '/config', json.dumps(data))
00439 
00440     def request(self, mode='GET', address=None, data=None):
00441         """ Utility function for HTTP GET/PUT requests for the API"""
00442         try:
00443             connection = httplib.HTTPConnection(self.ip)
00444             if mode == 'GET' or mode == 'DELETE':
00445                 connection.request(mode, address)
00446             if mode == 'PUT' or mode == 'POST':
00447                 connection.request(mode, address, data)
00448             logger.debug("{0} {1} {2}".format(mode, address, str(data)))
00449             result = connection.getresponse()
00450             connection.close()
00451 
00452             if PY3K:
00453                 result = json.loads(str(result.read(), encoding='utf-8'))
00454                 if result == None:
00455                     raise PhueException(404, "No response from hue bridge in request: [%s]" % str(result))
00456                 elif len(result) == 0:
00457                     raise PhueException(404, "No response from hue bridge in request: [%s]" % str(result))
00458                 else:
00459                     return result
00460             else:
00461                 result_str = result.read()
00462                 logger.debug(result_str)
00463                 result = json.loads(result_str)
00464                 if result == None:
00465                     raise PhueException(404, "No response from hue bridge in request: [%s]" % str(result))
00466                 elif len(result) == 0:
00467                     raise PhueException(404, "No response from hue bridge in request: [%s]" % str(result))
00468                 else:
00469                     return result
00470         
00471         except socket.timeout, e:
00472             logger.info('time out error: %s' % str(e))
00473         except Exception, e:
00474             return ""
00475 
00476     def set_ip_address(self, ip_address='127.0.0.1'):
00477         self.ip = ip_address
00478 
00479     def get_ip_address(self, set_result=False):
00480 
00481         """ Get the bridge ip address from the meethue.com nupnp api """
00482         try:
00483             connection = httplib.HTTPConnection('www.meethue.com')
00484             connection.request('GET', '/api/nupnp')
00485             logger.info('Connecting to meethue.com/api/nupnp')
00486             result = connection.getresponse()
00487         except socket.timeout, e:
00488             logger.info('time out error: %s' % str(e))
00489             return False
00490         except Exception, e:
00491             return False
00492 
00493         if PY3K:
00494             data = json.loads(str(result.read(), encoding='utf-8'))
00495         else:
00496             result_str = result.read()
00497             data = json.loads(result_str)
00498 
00499         """ close connection after read() is done, to prevent issues with read() """
00500 
00501         connection.close()
00502         if len(data) is 0:
00503             return
00504         else:
00505             ip = str(data[0]['internalipaddress'])
00506             if ip is not '':
00507                 if set_result:
00508                     self.ip = ip
00509                 return ip
00510             else:
00511                 return False
00512 
00513     def register_app(self):
00514         """ Register this computer with the Hue bridge hardware and save the resulting access token """
00515         registration_request = {"devicetype": "rocon_hue", "username": self.username}
00516         data = json.dumps(registration_request)
00517         response = self.request('POST', '/api', data)
00518         if response == None:
00519             raise PhueException(404, "No response from hue bridge")
00520         if len(response) is 0:
00521             raise PhueException(404, "No response from hue bridge")
00522 
00523         for line in response:
00524             for key in line:
00525                 if 'error' in key:
00526                     error_type = line['error']['type']
00527                     if error_type == 101:
00528                         raise PhueRegistrationException(error_type,
00529                                                         'The link button has not been pressed in the last 30 seconds.')
00530                     if error_type == 7:
00531                         raise PhueException(error_type,
00532                                             'Unknown username')
00533 
00534     def check_user_validation(self):
00535         response = self.request('GET', '/api' + self.username)
00536         if len(response) is 0:
00537             raise PhueException(404, "No response from hue bridge")
00538 
00539         for line in response:
00540             for key in line:
00541                 if 'success' in key:
00542                     return
00543                 if 'error' in key:
00544                     error_type = line['error']['type']
00545                     if error_type == 101:
00546                         raise PhueRegistrationException(error_type,
00547                                                         'The link button has not been pressed in the last 30 seconds.')
00548                     if error_type == 7:
00549                         raise PhueException(error_type, 'Unknown username')
00550                     if error_type == 1:
00551                         raise PhueException(error_type, 'unauthorized user')
00552 
00553     def connect(self):
00554         """ Connect to the Hue bridge """
00555         logger.info('Attempting to connect to the bridge...')
00556         # If the ip and username were provided at class init
00557         if self.ip is not None and self.username is not None:
00558             logger.info('Using ip: ' + self.ip)
00559             logger.info('Using username: ' + self.username)
00560             try:
00561                 self.check_user_validation()
00562             except Exception as e:
00563                 self.register_app()
00564 
00565     def get_light_id_by_name(self, name):
00566         """ Lookup a light id based on string name. Case-sensitive. """
00567         lights = self.get_light()
00568         for light_id in lights:
00569             if PY3K:
00570                 if name == lights[light_id]['name']:
00571                     return light_id
00572             else:
00573                 if unicode(name, encoding='utf-8') == lights[light_id]['name']:
00574                     return light_id
00575         return False
00576 
00577     def get_light_objects(self, mode='list'):
00578         """Returns a collection containing the lights, either by name or id (use 'id' or 'name' as the mode)
00579         The returned collection can be either a list (default), or a dict.
00580         Set mode='id' for a dict by light ID, or mode='name' for a dict by light name.   """
00581         if self.lights_by_id == {}:
00582             lights = self.request('GET', '/api/' + self.username + '/lights/')
00583             if lights == None:
00584                 raise PhueException(404, "No response from hue bridge in get_light_objects")
00585             elif len(lights) == 0:
00586                 raise PhueException(404, "No response from hue bridge in get_light_objects")
00587                 
00588             for light in lights:
00589                 self.lights_by_id[int(light)] = Light(self, int(light))
00590                 self.lights_by_name[lights[light]['name']] = self.lights_by_id[int(light)]
00591         if mode == 'id':
00592             return self.lights_by_id
00593         if mode == 'name':
00594             return self.lights_by_name
00595         if mode == 'list':
00596             return [self.lights_by_id[x] for x in range(1, len(self.lights_by_id) + 1)]
00597 
00598     def __getitem__(self, key):
00599         """ Lights are accessibly by indexing the bridge either with
00600         an integer index or string name. """
00601         if self.lights_by_id == {}:
00602             self.get_light_objects()
00603 
00604         try:
00605             return self.lights_by_id[key]
00606         except:
00607             try:
00608                 if PY3K:
00609                     return self.lights_by_name[key]
00610                 else:
00611                     return self.lights_by_name[unicode(key, encoding='utf-8')]
00612             except:
00613                 raise KeyError(
00614                     'Not a valid key (integer index starting with 1, or light name): ' + str(key))
00615 
00616     @property
00617     def lights(self):
00618         """ Access lights as a list """
00619         return self.get_light_objects()
00620 
00621     def get_api(self):
00622         """ Returns the full api dictionary """
00623         return self.request('GET', '/api/' + self.username)
00624 
00625     def get_light(self, light_id=None, parameter=None):
00626         """ Gets state by light_id and parameter"""
00627 
00628         if PY3K:
00629             if isinstance(light_id, str):
00630                 light_id = self.get_light_id_by_name(light_id)
00631         else:
00632             if isinstance(light_id, str) or isinstance(light_id, unicode):
00633                 light_id = self.get_light_id_by_name(light_id)
00634         if light_id is None:
00635             return self.request('GET', '/api/' + self.username + '/lights/')
00636         state = self.request(
00637             'GET', '/api/' + self.username + '/lights/' + str(light_id))
00638         if state is "":
00639             return ""
00640         if parameter is None:
00641             return state
00642         if parameter == 'name':
00643             return state[parameter]
00644         else:
00645             return state['state'][parameter]
00646 
00647     def set_light(self, light_id, parameter, value=None, transitiontime=None):
00648         """ Adjust properties of one or more lights.
00649 
00650         light_id can be a single lamp or an array of lamps
00651         parameters: 'on' : True|False , 'bri' : 0-254, 'sat' : 0-254, 'ct': 154-500
00652 
00653         transitiontime : in **deciseconds**, time for this transition to take place
00654                          Note that transitiontime only applies to *this* light
00655                          command, it is not saved as a setting for use in the future!
00656                          Use the Light class' transitiontime attribute if you want
00657                          persistent time settings.
00658 
00659         """
00660         if isinstance(parameter, dict):
00661             data = parameter
00662         else:
00663             data = {parameter: value}
00664 
00665         if transitiontime is not None:
00666             data['transitiontime'] = int(round(
00667                 transitiontime))  # must be int for request format
00668 
00669         light_id_array = light_id
00670         if PY3K:
00671             if isinstance(light_id, int) or isinstance(light_id, str):
00672                 light_id_array = [light_id]
00673         else:
00674             if isinstance(light_id, int) or isinstance(light_id, str) or isinstance(light_id, unicode):
00675                 light_id_array = [light_id]
00676         result = []
00677         for light in light_id_array:
00678             logger.debug(str(data))
00679             if parameter == 'name':
00680                 result.append(self.request('PUT', '/api/' + self.username + '/lights/' + str(
00681                     light_id), json.dumps(data)))
00682             else:
00683                 if PY3K:
00684                     if isinstance(light, str):
00685                         converted_light = self.get_light_id_by_name(light)
00686                     else:
00687                         converted_light = light
00688                 else:
00689                     if isinstance(light, str) or isinstance(light, unicode):
00690                             converted_light = self.get_light_id_by_name(light)
00691                     else:
00692                         converted_light = light
00693                 result.append(self.request('PUT', '/api/' + self.username + '/lights/' + str(
00694                     converted_light) + '/state', json.dumps(data)))
00695             if result == '' or result == None:
00696                 return None
00697             elif result[-1] == None:
00698                 return None
00699             elif len(result[-1]) == 0:
00700                 return None
00701             elif 'error' in list(result[-1][0].keys()):
00702                 logger.warn("ERROR: {0} for light {1}".format(
00703                     result[-1][0]['error']['description'], light))
00704 
00705         logger.debug(result)
00706         return result
00707 
00708     # Groups of lights #####
00709     @property
00710     def groups(self):
00711         """ Access groups as a list """
00712         return [Group(self, int(groupid)) for groupid in self.get_group().keys()]
00713 
00714     def get_group_id_by_name(self, name):
00715         """ Lookup a group id based on string name. Case-sensitive. """
00716         groups = self.get_group()
00717         for group_id in groups:
00718             if PY3K:
00719                 if name == groups[group_id]['name']:
00720                     return group_id
00721             else:
00722                 if unicode(name, encoding='utf-8') == groups[group_id]['name']:
00723                     return group_id
00724         return False
00725 
00726     def get_group(self, group_id=None, parameter=None):
00727         if PY3K:
00728             if isinstance(group_id, str):
00729                 group_id = self.get_group_id_by_name(group_id)
00730         else:
00731             if isinstance(group_id, str) or isinstance(group_id, unicode):
00732                 group_id = self.get_group_id_by_name(group_id)
00733         if group_id is False:
00734             logger.error('Group name does not exit')
00735             return
00736         if group_id is None:
00737             return self.request('GET', '/api/' + self.username + '/groups/')
00738         if parameter is None:
00739             return self.request('GET', '/api/' + self.username + '/groups/' + str(group_id))
00740         elif parameter == 'name' or parameter == 'lights':
00741             return self.request('GET', '/api/' + self.username + '/groups/' + str(group_id))[parameter]
00742         else:
00743             return self.request('GET', '/api/' + self.username + '/groups/' + str(group_id))['action'][parameter]
00744 
00745     def set_group(self, group_id, parameter, value=None, transitiontime=None):
00746         """ Change light settings for a group
00747 
00748         group_id : int, id number for group
00749         parameter : 'name' or 'lights'
00750         value: string, or list of light IDs if you're setting the lights
00751 
00752         """
00753 
00754         if isinstance(parameter, dict):
00755             data = parameter
00756         elif parameter == 'lights' and (isinstance(value, list) or isinstance(value, int)):
00757             if isinstance(value, int):
00758                 value = [value]
00759             data = {parameter: [str(x) for x in value]}
00760         else:
00761             data = {parameter: value}
00762 
00763         if transitiontime is not None:
00764             data['transitiontime'] = int(round(
00765                 transitiontime))  # must be int for request format
00766 
00767         group_id_array = group_id
00768         if PY3K:
00769             if isinstance(group_id, int) or isinstance(group_id, str):
00770                 group_id_array = [group_id]
00771         else:
00772             if isinstance(group_id, int) or isinstance(group_id, str) or isinstance(group_id, unicode):
00773                 group_id_array = [group_id]
00774         result = []
00775         for group in group_id_array:
00776             logger.debug(str(data))
00777             if PY3K:
00778                 if isinstance(group, str):
00779                     converted_group = self.get_group_id_by_name(group)
00780                 else:
00781                     converted_group = group
00782             else:
00783                 if isinstance(group, str) or isinstance(group, unicode):
00784                         converted_group = self.get_group_id_by_name(group)
00785                 else:
00786                     converted_group = group
00787             if converted_group is False:
00788                 logger.error('Group name does not exit')
00789                 return
00790             if parameter == 'name' or parameter == 'lights':
00791                 result.append(self.request('PUT', '/api/' + self.username + '/groups/' + str(converted_group), json.dumps(data)))
00792             else:
00793                 result.append(self.request('PUT', '/api/' + self.username + '/groups/' + str(converted_group) + '/action', json.dumps(data)))
00794 
00795         if result == '' or result == None:
00796                 return None
00797         elif result[-1] == None:
00798             return None
00799         elif len(result[-1]) == 0:
00800             return None
00801         elif 'error' in list(result[-1][0].keys()):
00802             logger.warn("ERROR: {0} for group {1}".format(
00803                 result[-1][0]['error']['description'], group))
00804 
00805         logger.debug(result)
00806         return result
00807 
00808     def create_group(self, name, lights=None):
00809         """ Create a group of lights
00810 
00811         Parameters
00812         ------------
00813         name : string
00814             Name for this group of lights
00815         lights : list
00816             List of lights to be in the group.
00817 
00818         """
00819         data = {'lights': [str(x) for x in lights], 'name': name}
00820         return self.request('POST', '/api/' + self.username + '/groups/', json.dumps(data))
00821 
00822     def delete_group(self, group_id):
00823         return self.request('DELETE', '/api/' + self.username + '/groups/' + str(group_id))
00824 
00825     # Schedules #####
00826     def get_schedule(self, schedule_id=None, parameter=None):
00827         if schedule_id is None:
00828             return self.request('GET', '/api/' + self.username + '/schedules')
00829         if parameter is None:
00830             return self.request('GET', '/api/' + self.username + '/schedules/' + str(schedule_id))
00831 
00832     def create_schedule(self, name, time, light_id, data, description=' '):
00833         schedule = {
00834             'name': name,
00835             'time': time,
00836             'description': description,
00837             'command':
00838             {
00839             'method': 'PUT',
00840             'address': '/api/' + self.username +
00841                 '/lights/' + str(light_id) + '/state',
00842             'body': data
00843             }
00844         }
00845         return self.request('POST', '/api/' + self.username + '/schedules', json.dumps(schedule))
00846 
00847     def create_group_schedule(self, name, time, group_id, data, description=' '):
00848         schedule = {
00849             'name': name,
00850             'time': time,
00851             'description': description,
00852             'command':
00853             {
00854             'method': 'PUT',
00855             'address': '/api/' + self.username +
00856                 '/groups/' + str(group_id) + '/action',
00857             'body': data
00858             }
00859         }
00860         return self.request('POST', '/api/' + self.username + '/schedules', json.dumps(schedule))
00861 
00862     def delete_schedule(self, schedule_id):
00863         return self.request('DELETE', '/api/' + self.username + '/schedules/' + str(schedule_id))
00864 
00865 """
00866 if __name__ == '__main__':
00867     import argparse
00868 
00869     logging.basicConfig(level=logging.DEBUG)
00870 
00871     parser = argparse.ArgumentParser()
00872     parser.add_argument('--host', required=True)
00873     args = parser.parse_args()
00874 
00875     while True:
00876         try:
00877             b = Bridge(args.host)
00878             break
00879         except PhueRegistrationException as e:
00880             raw_input('Press button on Bridge then hit Enter to try again')
00881 """


rocon_python_hue
Author(s):
autogenerated on Thu Jun 6 2019 17:58:50