-
Notifications
You must be signed in to change notification settings - Fork 0
/
phue
2452 lines (1940 loc) · 78 KB
/
phue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Repository: studioimaginaire/phue
File: .gitignore
*.pyc
*~
*.swp
test.py
*.DS_Store
*.sublime-workspace
dist
MANIFEST
Repository: studioimaginaire/phue
File: .travis.yml
language: python
matrix:
fast_finish: true
include:
- python: "2.7"
env: TOXENV=py27
- python: "3.5"
env: TOXENV=py35
- python: "2.7"
env: TOXENV=pep8
install: pip install tox
script: tox
Repository: studioimaginaire/phue
File: CHANGELOG.md
# phue changelog
## r11
- Add support for deleting scenes
- Various bug fixes
## r10
- Misc bug fixes
- Better support for schedules
## r9
- Added unit tests (sdague)
- Added scene support (sdague)
- Added sensor support (eldstal)
- Added reachable and type attributes to the Light object (carlosperate)
- Changed License to MIT
## r8
- iOS compatibility (Nathanaël Lécaudé)
- Logging fixes
- Added effect changing options (bradykent)
- Several unicode fixes (Nathanaël Lécaudé)
- Misc bug fixes
## r7
- Added to pypi
- Added support for Python 3 (Nathanaël Lécaudé)
- Logging level can be set with b.set_logging() (Nathanaël Lécaudé)
- Logging level can be set at init: b = Bridge(logging = 'debug') (Nathanaël Lécaudé)
- Added docstrings to Light properties (Nathanaël Lécaudé)
- Added colormode property to Light class (Nathanaël Lécaudé)
- IP is now optional if present in config file (Nathanaël Lécaudé)
- Implemented groups (Nathanaël Lécaudé)
- Implemented schedules (Nathanaël Lécaudé)
- Renamed get_info to get_api (Nathanaël Lécaudé)
- Renamed get_lights to get_light_objects (Nathanaël Lécaudé)
- Renamed set_state and get_state to set_light and get_light (Nathanaël Lécaudé)
- Fixed important bug when using set_state with a list of lights (Nathanaël Lécaudé)
- Add access to Light objects via direct indexing of the Bridge object via __getitem__ (Marshall Perrin)
- Implement real logging using Python's logging module, including error checking and display of responses from the server. (Marshall Perrin)
- Add function colortemp_k for color temperatures in Kelvin. (Marshall Perrin)
- Some additional error checking for invalid or missing parameters (Marshall Perrin)
- More details in docstrings. (Marshall Perrin)
## r6
- Light objects are now obtained using the get_lights method
- Added the alert method to the Light object
- All requests now use httplib for consistency
- Moved all source to github
- Renamed the module to phue
## r5
- Renamed the Bulb() object to Light() so it reflects the official API better
- You can now pass the username as argument to the Bridge class if you don't want to read/store to file
- You can now get the bridge name with brdige.name or set it with bridge.name = 'newname'
- The set_state method can now use a dictionary as first argument to send more complex messages
Repository: studioimaginaire/phue
File: LICENSE
The MIT License (MIT)
Copyright (c) 2014 Nathanaël Lécaudé
https://github.com/studioimaginaire/phue
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Repository: studioimaginaire/phue
File: README.md
# phue: A Python library for Philips Hue
Full featured Python library to control the Philips Hue lighting system.
## Features
- Compliant with the Philips Hue API 1.0
- Support for Lights
- Support for Groups
- Support for Schedules
- Support for Scenes
- Support for Sensors
- Compatible with Python 2.6.x and upwards
- Compatible with Python 3
- No dependencies
- Simple structure, single phue.py file
- Work in a procedural way or object oriented way
## Installation
### Using distutils
```
sudo easy_install phue
```
or
```
pip install phue
```
### Manually
phue consists of a single file (phue.py) that you can put in your python search path or in site-packages (or dist-packages depending on the platform)
You can also simply run it by putting it in the same directory as you main script file or start a python interpreter in the same directory.
phue works with Python 2.6.x, 2.7.x and 3.x
## Examples
### Basic usage
Using the set_light and get_light methods you can control pretty much all the parameters :
```python
#!/usr/bin/python
from phue import Bridge
b = Bridge('ip_of_your_bridge')
# If the app is not registered and the button is not pressed, press the button and call connect() (this only needs to be run a single time)
b.connect()
# Get the bridge state (This returns the full dictionary that you can explore)
b.get_api()
# Prints if light 1 is on or not
b.get_light(1, 'on')
# Set brightness of lamp 1 to max
b.set_light(1, 'bri', 254)
# Set brightness of lamp 2 to 50%
b.set_light(2, 'bri', 127)
# Turn lamp 2 on
b.set_light(2,'on', True)
# You can also control multiple lamps by sending a list as lamp_id
b.set_light( [1,2], 'on', True)
# Get the name of a lamp
b.get_light(1, 'name')
# You can also use light names instead of the id
b.get_light('Kitchen')
b.set_light('Kitchen', 'bri', 254)
# Also works with lists
b.set_light(['Bathroom', 'Garage'], 'on', False)
# The set_light method can also take a dictionary as the second argument to do more fancy stuff
# This will turn light 1 on with a transition time of 30 seconds
command = {'transitiontime' : 300, 'on' : True, 'bri' : 254}
b.set_light(1, command)
```
### Light Objects
If you want to work in a more object-oriented way, there are several ways you can get Light objects.
#### Get a flat list of light objects
```python
lights = b.lights
# Print light names
for l in lights:
print(l.name)
# Set brightness of each light to 127
for l in lights:
l.brightness = 127
```
#### Get Light objects as dictionaries
```python
# Get a dictionary with the light id as the key
lights = b.get_light_objects('id')
# Get the name of light 1, set the brightness to 127
lights[1].name
lights[1].brightness = 127
# Get a dictionary with the light name as the key
light_names = b.get_light_objects('name')
# Set the brightness of the bulb named "Kitchen"
light_names["Kitchen"].brightness = 254
# Set lights using name as key
for light in ['Kitchen', 'Bedroom', 'Garage']
light_names[light].on = True
light_names[light].hue = 15000
light_names[light].saturation = 120
# Get a flat list of the light objects (same as calling b.lights)
lights_list = b.get_light_objects('list')
for light in lights_list:
light.on = True
light.brightness = 127
```
### Setting Transition Times
In the Hue API, transition times are specified in deciseconds (tenths
of a second). This
is not tracked as a device setting, but rather needs to be applied on
each individual transition command you want to control the time of.
This can be done by specifying a transitiontime keyword when calling
set_light on the bridge:
```python
# Set brightness of lamp 1 to max, rapidly
b.set_light(1, 'bri', 254, transitiontime=1)
```
As a convenience, the Light class implements a wrapper that remembers
a specified transition time for that light, and applies it
automatically to every transition:
```python
light = light_names['Kitchen']
light.transitiontime = 2
# this next transition will happen rapidly
light.brightness = 20
```
Note that there is a known bug where turning a light off with the
transitiontime specified can cause the brightness level to behave
erratically when the light is turned back on. See [this
discussion](http://www.everyhue.com/vanilla/discussion/204/bug-with-brightness-when-requesting-ontrue-transitiontime5)
This package attempts to work around this issue by automatically
resetting the brightness when necessary, but this may not work in all
cases.
Transition times from 0-300 deciseconds (i.e. 0 - 30 seconds) have
been tested to work.
### Groups
You can also work with the groups functionality of the Bridge. If groups aren't working, try re-setting the bridge by unpluging it and plugging it back again.
```python
# List groups
b.get_group()
# List group 1
b.get_group(1)
# Get name of group 1
b.get_group(1, 'name')
# Get lights in group 1
b.get_group(1,'lights')
# Create a group with lights 1 and 3
b.create_group('Kitchen', [1,3])
# Rename group with id 1
b.set_group(1, 'name', 'New Group Name')
# Change lights within group 1
b.set_group(1, 'lights', [3,4])
# Turn group 1 off
b.set_group(1, 'on', False)
# Delete group 2
b.delete_group(1)
```
### Schedules
You can view, create and delete schedules using the following methods. Note that updates to the Hue API now use local time instead of UTC. If you have issues with schedules not triggering correctly, double check that the time zone is set correctly on your Hue Bridge and that your time in your code is not in UTC by default.
```python
# Get the list of different schedules
b.get_schedule()
# Get the data of a particular schedules
b.get_schedule(1)
# Create a schedule for a light, arguments are name, time, light_id, data (as a dictionary) and optional description
data = {'on': False, 'transitiontime': 600}
b.create_schedule('My schedule', '2012-11-12T22:34:00', 1, data, 'Bedtime' )
# Create a schedule for a group, same as above but with a group_id instead of light_id
data = {'on': False, 'transitiontime': 600}
b.create_group_schedule('My schedule', '2012-11-12T22:34:00', 0, data, 'Bedtime' )
# Delete a schedule
b.delete_schedule(1)
```
## Using phue with Max/MSP via Jython
You can use the phue library within [Max/MSP](http://www.cycling74.com) by using [Nick Rothwell's](http://www.cassiel.com) Jython objects. He recently updated the version to support Jython 2.7 which is required for phue to work.
Download it here: https://github.com/cassiel/net.loadbang.jython
## Using phue on iOS via Pythonista
You can use phue on your iOS device via the [Pythonista](http://omz-software.com/pythonista) app.
This is a great way to build quick prototypes on iOS as you don't need to compile anything, you can code directly from the device itself.
See this little example:
http://www.youtube.com/embed/6K-fxWG6JSs
## Acknowledgments
Huge thanks to http://rsmck.co.uk/hue for hacking the protocol !
## License
MIT - http://opensource.org/licenses/MIT
"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.
Repository: studioimaginaire/phue
File: TODO.md
#phue TODO
* Find a more elegant way to deal with transitiontime
* Add a Group class
* Cleanup the connect and register_app methods
* ~~Replace prints with proper logging mechanism~~
* ~~Read/Write config file from cwd if home is not writable~~
* ~~Store IP in config file~~
* ~~Add support for groups~~
* ~~Make username passable as argument and config file optional (so it can run when no write access is present like on iphone)~~
* ~~Rename Bulb to Light to conform to API~~ (done)
* ~~Add the ability to get and set the bridge name~~ (done)
* ~~Update Bulbs dictionary when lights are renamed~~ (done)
Repository: studioimaginaire/phue
File: examples/flicker.py
import random
from time import sleep
from phue import Bridge
b = Bridge('192.168.0.23')
b.connect()
lights = b.lights
def select_multiple_lights():
'''
Selects a random number of lights from the list of lights every time, resulting in a 'flickering' look.
'''
return random.choices(range(1,len(lights)+1),k=random.randint(1,len(lights)))
def multi_modal():
'''
Generates a random transition time between 0.2 and 0.7 seconds folowing a multi-modal distribution.
This results in really fast transitions, but also slow transitions.
'''
return [2+int(random.betavariate(1,9)*5),2+int(random.betavariate(9,1)*5)][bool(random.getrandbits(1))]
def candle_flicker():
'''
Sends a command to change a certain number of lights a different color temperature every time. ct_inc was finicky, so I've used ct instead.
All inputs use a beta distribution, as it looked more natural. A similar look can be achieved using a triangular distribution as well.
'''
b.set_light(select_multiple_lights(), {'transitiontime' : multi_modal(), 'on' : True, 'bri' : 1+int(random.betavariate(2,5)*253), 'ct' : 153+int(random.betavariate(9,4)*347)})
while True:
candle_flicker()
sleep(random.random())
Repository: studioimaginaire/phue
File: examples/hue-rainbow.py
#!/usr/bin/python
# This script will have all lights, which are on, continuously loop through the rainbow
# in the time specified in totalTime
from phue import Bridge
import random
b = Bridge() # Enter bridge IP here.
# If running for the first time, press button on bridge and run with b.connect() uncommented
# b.connect()
lights = b.get_light_objects()
totalTime = 30 # in seconds
transitionTime = 1 # in seconds
maxHue = 65535
hueIncrement = maxHue / totalTime
for light in lights:
light.transitiontime = transitionTime * 10
light.brightness = 254
light.saturation = 254
# light.on = True # uncomment to turn all lights on
hue = 0
while True:
for light in lights:
light.hue = hue
hue = (hue + hueIncrement) % maxHue
sleep(transitionTime)
Repository: studioimaginaire/phue
File: examples/random_colors.py
#!/usr/bin/python
from phue import Bridge
import random
b = Bridge() # Enter bridge IP here.
#If running for the first time, press button on bridge and run with b.connect() uncommented
#b.connect()
lights = b.get_light_objects()
for light in lights:
light.brightness = 254
light.xy = [random.random(),random.random()]
Repository: studioimaginaire/phue
File: examples/rgb_colors.py
#!/usr/bin/python
from phue import Bridge
def rgb_to_xy(red, green, blue):
""" conversion of RGB colors to CIE1931 XY colors
Formulas implemented from: https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d
Args:
red (float): a number between 0.0 and 1.0 representing red in the RGB space
green (float): a number between 0.0 and 1.0 representing green in the RGB space
blue (float): a number between 0.0 and 1.0 representing blue in the RGB space
Returns:
xy (list): x and y
"""
# gamma correction
red = pow((red + 0.055) / (1.0 + 0.055), 2.4) if red > 0.04045 else (red / 12.92)
green = pow((green + 0.055) / (1.0 + 0.055), 2.4) if green > 0.04045 else (green / 12.92)
blue = pow((blue + 0.055) / (1.0 + 0.055), 2.4) if blue > 0.04045 else (blue / 12.92)
# convert rgb to xyz
x = red * 0.649926 + green * 0.103455 + blue * 0.197109
y = red * 0.234327 + green * 0.743075 + blue * 0.022598
z = green * 0.053077 + blue * 1.035763
# convert xyz to xy
x = x / (x + y + z)
y = y / (x + y + z)
# TODO check color gamut if known
return [x, y]
b = Bridge() # Enter bridge IP here.
#If running for the first time, press button on bridge and run with b.connect() uncommented
#b.connect()
# RGB colors to XY
xy = rgb_to_xy(1.0, 0.28627, 0.95686)
lights = b.get_light_objects()
for light in lights:
# y might be used as brightness value, however, dark colors will turn the lights off
#brightness = int(xy[1]*255)
brightness = 255
light.xy = xy
Repository: studioimaginaire/phue
File: examples/tk_gui_complex.py
#!/usr/bin/python
from Tkinter import *
from phue import Bridge
'''
This example creates 3 sliders for the first 3 lights
and shows the name of the light under each slider.
There is also a checkbox to toggle the light.
'''
b = Bridge() # Enter bridge IP here.
#If running for the first time, press button on bridge and run with b.connect() uncommented
#b.connect()
root = Tk()
horizontal_frame = Frame(root)
horizontal_frame.pack()
lights = b.get_light_objects('id')
for light_id in lights:
channel_frame = Frame(horizontal_frame)
channel_frame.pack(side = LEFT)
scale_command = lambda x, light_id=light_id: b.set_light(light_id,{'bri': int(x), 'transitiontime': 1})
scale = Scale(channel_frame, from_ = 254, to = 0, command = scale_command, length = 200, showvalue = 0)
scale.set(b.get_light(light_id,'bri'))
scale.pack()
button_var = BooleanVar()
button_var.set(b.get_light(light_id, 'on'))
button_command = lambda button_var=button_var, light_id=light_id: b.set_light(light_id, 'on', button_var.get())
button = Checkbutton(channel_frame, variable = button_var, command = button_command)
button.pack()
label = Label(channel_frame)
label.config(text = b.get_light(light_id,'name'))
label.pack()
root.mainloop()
Repository: studioimaginaire/phue
File: examples/tk_gui_hsb.py
#!/usr/bin/python
from Tkinter import *
from phue import Bridge
'''
This example creates 3 sliders for the first 3 lights
and shows the name of the light under each slider.
There is also a checkbox to toggle the light.
'''
b = Bridge() # Enter bridge IP here.
#If running for the first time, press button on bridge and run with b.connect() uncommented
#b.connect()
root = Tk()
lights = b.get_light_objects('id')
light_selection = []
def curry(fn, *cargs, **ckwargs):
def call_fn(*fargs, **fkwargs):
d = ckwargs.copy()
d.update(fkwargs)
return fn(*(cargs + fargs), **d)
return call_fn
def hue_command(x):
if len(light_selection) > 0:
b.set_light(light_selection, 'hue', int(x))
def sat_command(x):
if len(light_selection) > 0:
b.set_light(light_selection, 'sat', int(x))
def bri_command(x):
if len(light_selection) > 0:
b.set_light(light_selection, 'bri', int(x))
def select_button_command(light, button_state):
global light_selection
if button_state.get():
light_selection.append(light)
else:
light_selection.remove(light)
print light_selection
slider_frame = Frame(root)
slider_frame.pack(pady = 10)
channels_frame = Frame(root)
channels_frame.pack()
label_frame = Frame(channels_frame)
label_frame.pack(side=LEFT, padx = 10)
label_state = Label(label_frame)
label_state.config(text = 'State')
label_state.pack()
label_select = Label(label_frame)
label_select.config(text = 'Select')
label_select.pack()
label_name = Label(label_frame)
label_name.config(text = 'Name')
label_name.pack()
hue_slider = Scale(slider_frame, from_ = 65535, to = 0, command = hue_command)
sat_slider = Scale(slider_frame, from_ = 254, to = 0, command = sat_command)
bri_slider = Scale(slider_frame, from_ = 254, to = 0, command = bri_command)
hue_slider.pack(side=LEFT)
sat_slider.pack(side=LEFT)
bri_slider.pack(side=LEFT)
for light_id in lights:
channel_frame = Frame(channels_frame)
channel_frame.pack(side = LEFT, padx = 10)
button_var = BooleanVar()
button_var.set(b.get_light(light_id, 'on'))
button_command = lambda button_var=button_var, light_id=light_id: b.set_light(light_id, 'on', button_var.get())
button = Checkbutton(channel_frame, variable = button_var, command = button_command)
button.pack()
select_button_var = BooleanVar()
#select_button_var.set(b.get_light(light_id, 'on'))
select_button_callback = curry(select_button_command, light_id, select_button_var)
select_button = Checkbutton(channel_frame, variable = select_button_var, command = select_button_callback)
select_button.pack()
label = Label(channel_frame)
label.config(text = b.get_light(light_id,'name'))
label.pack()
root.mainloop()
Repository: studioimaginaire/phue
File: examples/tk_gui_simple.py
#!/usr/bin/python
from Tkinter import *
from phue import Bridge
'''
This example creates a slider that controls the
brightness of the first 3 lights.
'''
b = Bridge() # Enter bridge IP here.
#If running for the first time, press button on bridge and run with b.connect() uncommented
#b.connect()
b.set_light([1,2,3], 'on', True)
def sel(data):
b.set_light([1,2,3],{'bri':int(data), 'transitiontime': 1})
root = Tk()
scale = Scale( root, from_ = 254, to = 0, command= sel, length = 200 )
scale.set(b.get_light(1,'bri'))
scale.pack(anchor=CENTER)
root.mainloop()
Repository: studioimaginaire/phue
File: phue.py
#!/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 MIT license - See LICENSE file for more details.
"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 logging
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
logger = logging.getLogger('phue')
if platform.system() == 'Windows':
USER_HOME = 'USERPROFILE'
else:
USER_HOME = 'HOME'
__version__ = '1.2'
def is_string(data):
"""Utility method to see if data is a string."""
if PY3K:
return isinstance(data, str)
else:
return isinstance(data, str) or isinstance(data, unicode) # noqa
def encodeString(string):
"""Utility method to encode strings as utf-8."""
if PY3K:
return string
else:
return string.encode('utf-8')
def decodeString(string):
"""Utility method to decode strings as utf-8."""
if PY3K:
return string
else:
return string.decode('utf-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
self._reachable = None
self._type = 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) or (
kwargs.get('on', True) 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]'''
return encodeString(self._get('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
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))