00001
00002
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
00073 self._reset_bri_after_on = None
00074 self._reachable = False
00075
00076 def __repr__(self):
00077
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
00085
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
00131
00132
00133
00134
00135
00136
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
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
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
00318
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
00324
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
00355
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
00422
00423
00424
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
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))
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
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))
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
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 """