hue 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Readme.markdown +39 -8
- data/Todo.markdown +0 -2
- data/hue.gemspec +4 -1
- data/lib/hue.rb +4 -0
- data/lib/hue/bridge.rb +20 -2
- data/lib/hue/cli.rb +51 -5
- data/lib/hue/client.rb +85 -36
- data/lib/hue/editable_state.rb +27 -0
- data/lib/hue/group.rb +181 -0
- data/lib/hue/light.rb +4 -35
- data/lib/hue/scene.rb +50 -0
- data/lib/hue/translate_keys.rb +21 -0
- data/lib/hue/version.rb +1 -1
- metadata +50 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 710c4221738dfdb074848e444283c1e7dce6d356
|
4
|
+
data.tar.gz: c861ca67f30f33986b7a1ede40a368cc71815c3b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d9571dacb6fdb61edc5255f58610096c30a0fd2a7c5ce9ff66d79638687a48f08aa50251acb9516efb98c30d40aa28b14a1978cb373c194809b4dfe428a0a62f
|
7
|
+
data.tar.gz: a73d019ab7664247744638dfced2b7cf582d913d05c35b2a96f848ec91ed17fb06e0275ec6d476594f1141d6375879d74dc0552e8db7a6cc1c616d840d3ad2f9
|
data/Readme.markdown
CHANGED
@@ -28,24 +28,55 @@ $ gem install hue
|
|
28
28
|
|
29
29
|
The first time you use it, it will automatically create a user for you. Doing this requires you to have pushed the button on your bridge in the last 30 seconds. If you haven't it will throw an exception and let you know you need to push the button. Simply press the button and run the command again.
|
30
30
|
|
31
|
-
|
31
|
+
### CLI
|
32
32
|
|
33
33
|
``` shell
|
34
34
|
$ hue all on
|
35
35
|
$ hue all off
|
36
|
+
$ hue all --hue 65280 --brightness 20
|
36
37
|
$ hue light 2 on
|
37
38
|
$ hue light 2 --brightness 20
|
38
39
|
```
|
39
40
|
|
40
|
-
|
41
|
+
### Ruby
|
41
42
|
|
42
43
|
``` ruby
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
44
|
+
client = Hue::Client.new
|
45
|
+
```
|
46
|
+
|
47
|
+
#### Lights
|
48
|
+
|
49
|
+
``` ruby
|
50
|
+
light = client.lights.first
|
51
|
+
light.on!
|
52
|
+
light.hue = 46920
|
53
|
+
light.color_temperature = 100
|
54
|
+
transition_time = 10*5 # Hue transition times are in 1/10 of a second.
|
55
|
+
light.set_state({:color_temperature => 400}, transition_time)
|
56
|
+
```
|
57
|
+
|
58
|
+
#### Groups
|
59
|
+
|
60
|
+
``` ruby
|
61
|
+
# Fetching
|
62
|
+
group = client.groups.first
|
63
|
+
group = client.group(1)
|
64
|
+
|
65
|
+
# Accessing group lights
|
66
|
+
group.lights.first.on!
|
67
|
+
group.lights.each { |light| light.hue = rand(0...65535) }
|
68
|
+
|
69
|
+
# Creating groups
|
70
|
+
group = client.group # Don't specify an ID
|
71
|
+
group.name = "My Group"
|
72
|
+
group.lights = [3, 4] # Can specify lights by ID
|
73
|
+
group.lights = client.lights.first(2) # Or by Light objects
|
74
|
+
group.new? # => true
|
75
|
+
group.create! # Once the group is created, you can continue to customize it
|
76
|
+
group.new? # => false
|
77
|
+
|
78
|
+
# Destroying groups
|
79
|
+
client.groups.last.destroy!
|
49
80
|
```
|
50
81
|
|
51
82
|
## Contributing
|
data/Todo.markdown
CHANGED
data/hue.gemspec
CHANGED
@@ -18,7 +18,10 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.required_ruby_version = '>= 1.
|
21
|
+
spec.required_ruby_version = '>= 1.9.3'
|
22
22
|
spec.add_dependency 'thor'
|
23
23
|
spec.add_dependency 'json'
|
24
|
+
spec.add_dependency 'log_switch', '0.4.0'
|
25
|
+
spec.add_dependency 'playful'
|
26
|
+
spec.add_dependency 'curb'
|
24
27
|
end
|
data/lib/hue.rb
CHANGED
@@ -2,7 +2,11 @@ require 'hue/version'
|
|
2
2
|
require 'hue/errors'
|
3
3
|
require 'hue/client'
|
4
4
|
require 'hue/bridge'
|
5
|
+
require 'hue/editable_state'
|
6
|
+
require 'hue/translate_keys'
|
5
7
|
require 'hue/light'
|
8
|
+
require 'hue/group'
|
9
|
+
require 'hue/scene'
|
6
10
|
|
7
11
|
module Hue
|
8
12
|
USERNAME_RANGE = 10..40
|
data/lib/hue/bridge.rb
CHANGED
@@ -70,7 +70,7 @@ module Hue
|
|
70
70
|
|
71
71
|
def lights
|
72
72
|
@lights ||= begin
|
73
|
-
json = JSON(Net::HTTP.get(URI.parse(
|
73
|
+
json = JSON(Net::HTTP.get(URI.parse(base_url)))
|
74
74
|
json['lights'].map do |key, value|
|
75
75
|
Light.new(@client, self, key, value)
|
76
76
|
end
|
@@ -78,12 +78,30 @@ module Hue
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def add_lights
|
81
|
-
uri = URI.parse("
|
81
|
+
uri = URI.parse("#{base_url}/lights")
|
82
82
|
http = Net::HTTP.new(uri.host)
|
83
83
|
response = http.request_post(uri.path, nil)
|
84
84
|
(response.body).first
|
85
85
|
end
|
86
86
|
|
87
|
+
def groups
|
88
|
+
@groups ||= begin
|
89
|
+
json = JSON(Net::HTTP.get(URI.parse("#{base_url}/groups")))
|
90
|
+
json.map do |id, data|
|
91
|
+
Group.new(@client, self, id, data)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def scenes
|
97
|
+
@scenes ||= begin
|
98
|
+
json = JSON(Net::HTTP.get(URI.parse("#{base_url}/scenes")))
|
99
|
+
json.map do |id, data|
|
100
|
+
Scene.new(@client, self, id, data)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
87
105
|
private
|
88
106
|
|
89
107
|
KEYS_MAP = {
|
data/lib/hue/cli.rb
CHANGED
@@ -17,11 +17,26 @@ module Hue
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
desc 'light ID STATE [COLOR]', 'Access a light'
|
21
|
+
long_desc <<-LONGDESC
|
22
|
+
Examples: \n
|
23
|
+
hue all on \n
|
24
|
+
hue all off \n
|
25
|
+
hue all --hue 12345 \n
|
26
|
+
hue all --bri 25 \n
|
27
|
+
hue all --hue 50000 --bri 200 --sat 240 \n
|
28
|
+
hue all --alert lselect \n
|
29
|
+
LONGDESC
|
30
|
+
option :hue, :type => :numeric
|
31
|
+
option :sat, :type => :numeric, :aliases => '--saturation'
|
32
|
+
option :bri, :type => :numeric, :aliases => '--brightness'
|
33
|
+
option :alert, :type => :string
|
20
34
|
desc 'all STATE', 'Send commands to all lights'
|
21
|
-
def all(state)
|
22
|
-
|
35
|
+
def all(state = 'on')
|
36
|
+
body = options.dup
|
37
|
+
body[:on] = state == 'on'
|
23
38
|
client.lights.each do |light|
|
24
|
-
light.
|
39
|
+
puts light.set_state body
|
25
40
|
end
|
26
41
|
end
|
27
42
|
|
@@ -34,8 +49,8 @@ module Hue
|
|
34
49
|
hue light 1 off
|
35
50
|
LONGDESC
|
36
51
|
option :hue, :type => :numeric
|
37
|
-
option :sat, :type => :numeric
|
38
|
-
option :
|
52
|
+
option :sat, :type => :numeric, :aliases => '--saturation'
|
53
|
+
option :brightness, :type => :numeric, :aliases => '--brightness'
|
39
54
|
option :alert, :type => :string
|
40
55
|
def light(id, state = nil)
|
41
56
|
light = client.light(id)
|
@@ -46,6 +61,37 @@ module Hue
|
|
46
61
|
puts light.set_state(body) if body.length > 0
|
47
62
|
end
|
48
63
|
|
64
|
+
desc 'groups', 'Find all light groups on your network'
|
65
|
+
def groups
|
66
|
+
client.groups.each do |group|
|
67
|
+
puts group.id.to_s.ljust(6) + group.name
|
68
|
+
group.lights.each do |light|
|
69
|
+
puts " -> " + light.id.to_s.ljust(6) + light.name
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
desc 'group ID STATE [COLOR]', 'Update a group of lights'
|
75
|
+
long_desc <<-LONGDESC
|
76
|
+
Examples: \n
|
77
|
+
hue groups 1 on --hue 12345
|
78
|
+
hue groups 1 --bri 25
|
79
|
+
hue groups 1 --alert lselect
|
80
|
+
hue groups 1 off
|
81
|
+
LONGDESC
|
82
|
+
option :hue, :type => :numeric
|
83
|
+
option :sat, :type => :numeric, :aliases => '--saturation'
|
84
|
+
option :brightness, :type => :numeric, :aliases => '--brightness'
|
85
|
+
option :alert, :type => :string
|
86
|
+
def group(id, state = nil)
|
87
|
+
group = client.group(id)
|
88
|
+
puts group.name
|
89
|
+
|
90
|
+
body = options.dup
|
91
|
+
body[:on] = (state == 'on' || !(state == 'off'))
|
92
|
+
puts group.set_state(body) if body.length > 0
|
93
|
+
end
|
94
|
+
|
49
95
|
private
|
50
96
|
|
51
97
|
def client
|
data/lib/hue/client.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
require 'net/http'
|
2
2
|
require 'json'
|
3
|
+
require 'playful/ssdp'
|
4
|
+
require 'curb'
|
5
|
+
|
6
|
+
# Playful is super verbose
|
7
|
+
Playful.log = false
|
3
8
|
|
4
9
|
module Hue
|
5
10
|
class Client
|
@@ -11,7 +16,12 @@ module Hue
|
|
11
16
|
end
|
12
17
|
|
13
18
|
@username = username
|
14
|
-
|
19
|
+
|
20
|
+
begin
|
21
|
+
validate_user
|
22
|
+
rescue Hue::UnauthorizedUser
|
23
|
+
register_user
|
24
|
+
end
|
15
25
|
end
|
16
26
|
|
17
27
|
def bridge
|
@@ -23,11 +33,31 @@ module Hue
|
|
23
33
|
|
24
34
|
def bridges
|
25
35
|
@bridges ||= begin
|
26
|
-
|
27
|
-
|
28
|
-
|
36
|
+
devices = Playful::SSDP.search 'IpBridge'
|
37
|
+
|
38
|
+
if devices.count == 0
|
39
|
+
# UPnP failed, lets use N-UPnP
|
40
|
+
bs = []
|
41
|
+
easy = Curl::Easy.new
|
42
|
+
easy.follow_location = true
|
43
|
+
easy.max_redirects = 10
|
44
|
+
easy.url = 'https://www.meethue.com/api/nupnp'
|
45
|
+
easy.perform
|
46
|
+
JSON(easy.body).each do |hash|
|
47
|
+
bs << Bridge.new(self, hash)
|
48
|
+
end
|
49
|
+
bs
|
50
|
+
else
|
51
|
+
devices
|
52
|
+
.uniq { |d| d[:location] }
|
53
|
+
.map do |bridge|
|
54
|
+
Bridge.new(self, {
|
55
|
+
'id' => bridge[:usn],
|
56
|
+
'name' => bridge[:st],
|
57
|
+
'internalipaddress' => URI.parse(bridge[:location]).host
|
58
|
+
})
|
59
|
+
end
|
29
60
|
end
|
30
|
-
bs
|
31
61
|
end
|
32
62
|
end
|
33
63
|
|
@@ -40,49 +70,68 @@ module Hue
|
|
40
70
|
end
|
41
71
|
|
42
72
|
def light(id)
|
43
|
-
|
73
|
+
id = id.to_s
|
74
|
+
lights.select { |l| l.id == id }.first
|
44
75
|
end
|
45
76
|
|
46
|
-
|
77
|
+
def groups
|
78
|
+
bridge.groups
|
79
|
+
end
|
47
80
|
|
48
|
-
def
|
49
|
-
|
81
|
+
def group(id = nil)
|
82
|
+
return Group.new(self, bridge) if id.nil?
|
50
83
|
|
51
|
-
|
52
|
-
|
53
|
-
|
84
|
+
id = id.to_s
|
85
|
+
groups.select { |g| g.id == id }.first
|
86
|
+
end
|
54
87
|
|
55
|
-
|
56
|
-
|
57
|
-
end
|
58
|
-
response['success']
|
88
|
+
def scenes
|
89
|
+
bridge.scenes
|
59
90
|
end
|
60
91
|
|
61
|
-
def
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
}
|
92
|
+
def scene(id)
|
93
|
+
id = id.to_s
|
94
|
+
scenes.select { |s| s.id == id }.first
|
95
|
+
end
|
66
96
|
|
67
|
-
|
68
|
-
http = Net::HTTP.new(uri.host)
|
69
|
-
response = JSON(http.request_post(uri.path, JSON.dump(body)).body).first
|
97
|
+
private
|
70
98
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
99
|
+
def validate_user
|
100
|
+
response = JSON(Net::HTTP.get(URI.parse("http://#{bridge.ip}/api/#{@username}")))
|
101
|
+
|
102
|
+
if response.is_a? Array
|
103
|
+
response = response.first
|
104
|
+
end
|
105
|
+
|
106
|
+
if error = response['error']
|
107
|
+
raise get_error(error)
|
75
108
|
end
|
76
109
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
110
|
+
response['success']
|
111
|
+
end
|
112
|
+
|
113
|
+
def register_user
|
114
|
+
body = JSON.dump({
|
115
|
+
devicetype: 'Ruby',
|
116
|
+
username: @username
|
117
|
+
})
|
118
|
+
|
119
|
+
uri = URI.parse("http://#{bridge.ip}/api")
|
120
|
+
http = Net::HTTP.new(uri.host)
|
121
|
+
response = JSON(http.request_post(uri.path, body).body).first
|
81
122
|
|
82
|
-
|
83
|
-
raise
|
84
|
-
rescue Hue::UnauthorizedUser
|
85
|
-
register_user
|
123
|
+
if error = response['error']
|
124
|
+
raise get_error(error)
|
86
125
|
end
|
126
|
+
|
127
|
+
response['success']
|
128
|
+
end
|
129
|
+
|
130
|
+
def get_error(error)
|
131
|
+
# Find error class and return instance
|
132
|
+
klass = Hue::ERROR_MAP[error['type']] || UnknownError unless klass
|
133
|
+
klass.new(error['description'])
|
134
|
+
end
|
135
|
+
|
87
136
|
end
|
88
137
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Hue
|
2
|
+
module EditableState
|
3
|
+
def on?
|
4
|
+
@state['on']
|
5
|
+
end
|
6
|
+
|
7
|
+
def on!
|
8
|
+
self.on = true
|
9
|
+
end
|
10
|
+
|
11
|
+
def off!
|
12
|
+
self.on = false
|
13
|
+
end
|
14
|
+
|
15
|
+
%w{on hue saturation brightness color_temperature alert effect}.each do |key|
|
16
|
+
define_method "#{key}=".to_sym do |value|
|
17
|
+
set_state({key.to_sym => value})
|
18
|
+
instance_variable_set("@#{key}".to_sym, value)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def set_xy(x, y)
|
23
|
+
set_state({:xy => [x, y]})
|
24
|
+
@x, @y = x, y
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/hue/group.rb
ADDED
@@ -0,0 +1,181 @@
|
|
1
|
+
module Hue
|
2
|
+
class Group
|
3
|
+
include Enumerable
|
4
|
+
include TranslateKeys
|
5
|
+
include EditableState
|
6
|
+
|
7
|
+
# Unique identification number.
|
8
|
+
attr_reader :id
|
9
|
+
|
10
|
+
# Bridge the group is associated with
|
11
|
+
attr_reader :bridge
|
12
|
+
|
13
|
+
# A unique, editable name given to the group.
|
14
|
+
attr_accessor :name
|
15
|
+
|
16
|
+
# Hue of the group. This is a wrapping value between 0 and 65535.
|
17
|
+
# Both 0 and 65535 are red, 25500 is green and 46920 is blue.
|
18
|
+
attr_accessor :hue
|
19
|
+
|
20
|
+
# Saturation of the group. 255 is the most saturated (colored)
|
21
|
+
# and 0 is the least saturated (white).
|
22
|
+
attr_accessor :saturation
|
23
|
+
|
24
|
+
# Brightness of the group. This is a scale from the minimum
|
25
|
+
# brightness the group is capable of, 0, to the maximum capable
|
26
|
+
# brightness, 255. Note a brightness of 0 is not off.
|
27
|
+
attr_accessor :brightness
|
28
|
+
|
29
|
+
# The x coordinate of a color in CIE color space. Between 0 and 1.
|
30
|
+
#
|
31
|
+
# @see http://developers.meethue.com/coreconcepts.html#color_gets_more_complicated
|
32
|
+
attr_reader :x
|
33
|
+
|
34
|
+
# The y coordinate of a color in CIE color space. Between 0 and 1.
|
35
|
+
#
|
36
|
+
# @see http://developers.meethue.com/coreconcepts.html#color_gets_more_complicated
|
37
|
+
attr_reader :y
|
38
|
+
|
39
|
+
# The Mired Color temperature of the light. 2012 connected lights
|
40
|
+
# are capable of 153 (6500K) to 500 (2000K).
|
41
|
+
#
|
42
|
+
# @see http://en.wikipedia.org/wiki/Mired
|
43
|
+
attr_accessor :color_temperature
|
44
|
+
|
45
|
+
# A fixed name describing the type of group.
|
46
|
+
attr_reader :type
|
47
|
+
|
48
|
+
def initialize(client, bridge, id = nil, data = {})
|
49
|
+
@client = client
|
50
|
+
@bridge = bridge
|
51
|
+
@id = id
|
52
|
+
|
53
|
+
unpack(data)
|
54
|
+
end
|
55
|
+
|
56
|
+
def each(&block)
|
57
|
+
lights.each(&block)
|
58
|
+
end
|
59
|
+
|
60
|
+
def lights
|
61
|
+
@lights ||= begin
|
62
|
+
@light_ids.map do |light_id|
|
63
|
+
@client.light(light_id)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def name=(name)
|
69
|
+
resp = set_group_state({:name => name})
|
70
|
+
@name = new? ? name : resp[0]['success']["/groups/#{id}/name"]
|
71
|
+
end
|
72
|
+
|
73
|
+
def lights=(light_ids)
|
74
|
+
light_ids.map! do |light_id|
|
75
|
+
light_id.is_a?(Light) ? light_id.id : light_id.to_s
|
76
|
+
end
|
77
|
+
|
78
|
+
@light_ids = light_ids.uniq
|
79
|
+
@lights = nil # resets the memoization
|
80
|
+
|
81
|
+
set_group_state({:lights => @light_ids})
|
82
|
+
end
|
83
|
+
|
84
|
+
def scene=(scene)
|
85
|
+
scene_id = scene.is_a?(Scene) ? scene.id : scene
|
86
|
+
set_group_state({:scene => scene_id})
|
87
|
+
end
|
88
|
+
|
89
|
+
def <<(light_id)
|
90
|
+
@light_ids << light_id
|
91
|
+
set_group_state({:lights => @light_ids})
|
92
|
+
end
|
93
|
+
alias_method :add_light, :<<
|
94
|
+
|
95
|
+
def set_group_state(attributes)
|
96
|
+
return if new?
|
97
|
+
body = translate_keys(attributes, GROUP_KEYS_MAP)
|
98
|
+
|
99
|
+
uri = URI.parse(base_url)
|
100
|
+
http = Net::HTTP.new(uri.host)
|
101
|
+
response = http.request_put(uri.path, JSON.dump(body))
|
102
|
+
JSON(response.body)
|
103
|
+
end
|
104
|
+
|
105
|
+
def set_state(attributes)
|
106
|
+
return if new?
|
107
|
+
body = translate_keys(attributes, STATE_KEYS_MAP)
|
108
|
+
|
109
|
+
uri = URI.parse("#{base_url}/action")
|
110
|
+
http = Net::HTTP.new(uri.host)
|
111
|
+
response = http.request_put(uri.path, JSON.dump(body))
|
112
|
+
JSON(response.body)
|
113
|
+
end
|
114
|
+
|
115
|
+
def refresh
|
116
|
+
json = JSON(Net::HTTP.get(URI.parse(base_url)))
|
117
|
+
unpack(json)
|
118
|
+
@lights = nil
|
119
|
+
end
|
120
|
+
|
121
|
+
def create!
|
122
|
+
body = {
|
123
|
+
:name => @name,
|
124
|
+
:lights => @light_ids,
|
125
|
+
}
|
126
|
+
|
127
|
+
uri = URI.parse("http://#{@bridge.ip}/api/#{@client.username}/groups")
|
128
|
+
http = Net::HTTP.new(uri.host)
|
129
|
+
response = http.request_post(uri.path, JSON.dump(body))
|
130
|
+
json = JSON(response.body)
|
131
|
+
|
132
|
+
@id = json[0]['success']['id']
|
133
|
+
end
|
134
|
+
|
135
|
+
def destroy!
|
136
|
+
uri = URI.parse(base_url)
|
137
|
+
http = Net::HTTP.new(uri.host)
|
138
|
+
response = http.delete(uri.path)
|
139
|
+
json = JSON(response.body)
|
140
|
+
@id = nil if json[0]['success']
|
141
|
+
end
|
142
|
+
|
143
|
+
def new?
|
144
|
+
@id.nil?
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
GROUP_KEYS_MAP = {
|
150
|
+
:name => :name,
|
151
|
+
:light_ids => :lights,
|
152
|
+
:type => :type,
|
153
|
+
:state => :action
|
154
|
+
}
|
155
|
+
|
156
|
+
STATE_KEYS_MAP = {
|
157
|
+
:on => :on,
|
158
|
+
:brightness => :bri,
|
159
|
+
:hue => :hue,
|
160
|
+
:saturation => :sat,
|
161
|
+
:xy => :xy,
|
162
|
+
:color_temperature => :ct,
|
163
|
+
:alert => :alert,
|
164
|
+
:effect => :effect,
|
165
|
+
:color_mode => :colormode,
|
166
|
+
}
|
167
|
+
|
168
|
+
def unpack(data)
|
169
|
+
unpack_hash(data, GROUP_KEYS_MAP)
|
170
|
+
|
171
|
+
unless new?
|
172
|
+
unpack_hash(@state, STATE_KEYS_MAP)
|
173
|
+
@x, @y = @state['xy']
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def base_url
|
178
|
+
"http://#{@bridge.ip}/api/#{@client.username}/groups/#{id}"
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
data/lib/hue/light.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
module Hue
|
2
2
|
class Light
|
3
|
+
include TranslateKeys
|
4
|
+
include EditableState
|
5
|
+
|
3
6
|
HUE_RANGE = 0..65535
|
4
7
|
SATURATION_RANGE = 0..255
|
5
8
|
BRIGHTNESS_RANGE = 0..255
|
@@ -108,22 +111,6 @@ module Hue
|
|
108
111
|
end
|
109
112
|
end
|
110
113
|
|
111
|
-
def on?
|
112
|
-
@state['on']
|
113
|
-
end
|
114
|
-
|
115
|
-
%w{on hue saturation brightness color_temperature alert}.each do |key|
|
116
|
-
define_method "#{key}=".to_sym do |value|
|
117
|
-
set_state({key.to_sym => value})
|
118
|
-
instance_variable_set("@#{key}".to_sym, value)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
def set_xy(x, y)
|
123
|
-
set_state({:xy => [x, y]})
|
124
|
-
@x, @y = x, y
|
125
|
-
end
|
126
|
-
|
127
114
|
# Indicates if a light can be reached by the bridge. Currently
|
128
115
|
# always returns true, functionality will be added in a future
|
129
116
|
# patch.
|
@@ -136,7 +123,7 @@ module Hue
|
|
136
123
|
# defaults to 4 (400ms). For example, setting transistiontime:10 will
|
137
124
|
# make the transition last 1 second.
|
138
125
|
def set_state(attributes, transition = nil)
|
139
|
-
body = translate_keys(attributes)
|
126
|
+
body = translate_keys(attributes, STATE_KEYS_MAP)
|
140
127
|
|
141
128
|
# Add transition
|
142
129
|
body.merge!({:transitiontime => transition}) if transition
|
@@ -177,30 +164,12 @@ module Hue
|
|
177
164
|
:reachable => :reachable,
|
178
165
|
}
|
179
166
|
|
180
|
-
def translate_keys(hash)
|
181
|
-
new_hash = {}
|
182
|
-
hash.each do |key, value|
|
183
|
-
new_key = STATE_KEYS_MAP[key.to_sym]
|
184
|
-
key = new_key if new_key
|
185
|
-
new_hash[key] = value
|
186
|
-
end
|
187
|
-
new_hash
|
188
|
-
end
|
189
|
-
|
190
167
|
def unpack(hash)
|
191
168
|
unpack_hash(hash, KEYS_MAP)
|
192
169
|
unpack_hash(@state, STATE_KEYS_MAP)
|
193
170
|
@x, @y = @state['xy']
|
194
171
|
end
|
195
172
|
|
196
|
-
def unpack_hash(hash, map)
|
197
|
-
map.each do |local_key, remote_key|
|
198
|
-
value = hash[remote_key.to_s]
|
199
|
-
next unless value
|
200
|
-
instance_variable_set("@#{local_key}", value)
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
173
|
def base_url
|
205
174
|
"http://#{@bridge.ip}/api/#{@client.username}/lights/#{id}"
|
206
175
|
end
|
data/lib/hue/scene.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
module Hue
|
2
|
+
class Scene
|
3
|
+
include Enumerable
|
4
|
+
include TranslateKeys
|
5
|
+
|
6
|
+
# Unique identification number.
|
7
|
+
attr_reader :id
|
8
|
+
|
9
|
+
# Bridge the scene is associated with
|
10
|
+
attr_reader :bridge
|
11
|
+
|
12
|
+
# A unique, editable name given to the scene.
|
13
|
+
attr_accessor :name
|
14
|
+
|
15
|
+
# Whether or not the scene is active on a group.
|
16
|
+
attr_reader :active
|
17
|
+
|
18
|
+
def initialize(client, bridge, id, data)
|
19
|
+
@client = client
|
20
|
+
@bridge = bridge
|
21
|
+
@id = id
|
22
|
+
|
23
|
+
unpack(data)
|
24
|
+
end
|
25
|
+
|
26
|
+
def lights
|
27
|
+
@lights ||= begin
|
28
|
+
@light_ids.map do |light_id|
|
29
|
+
@client.light(light_id)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
SCENE_KEYS_MAP = {
|
37
|
+
:name => :name,
|
38
|
+
:light_ids => :lights,
|
39
|
+
:active => :active,
|
40
|
+
}
|
41
|
+
|
42
|
+
def unpack(data)
|
43
|
+
unpack_hash(data, SCENE_KEYS_MAP)
|
44
|
+
end
|
45
|
+
|
46
|
+
def base_url
|
47
|
+
"http://#{@bridge.ip}/api/#{@client.username}/scenes/#{id}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Hue
|
2
|
+
module TranslateKeys
|
3
|
+
def translate_keys(hash, map)
|
4
|
+
new_hash = {}
|
5
|
+
hash.each do |key, value|
|
6
|
+
new_key = map[key.to_sym]
|
7
|
+
key = new_key if new_key
|
8
|
+
new_hash[key] = value
|
9
|
+
end
|
10
|
+
new_hash
|
11
|
+
end
|
12
|
+
|
13
|
+
def unpack_hash(hash, map)
|
14
|
+
map.each do |local_key, remote_key|
|
15
|
+
value = hash[remote_key.to_s]
|
16
|
+
next unless value
|
17
|
+
instance_variable_set("@#{local_key}", value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/hue/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hue
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Soffes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-03-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -38,6 +38,48 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: log_switch
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.4.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.4.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: playful
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: curb
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
41
83
|
description: Work with Philips Hue light bulbs.
|
42
84
|
email:
|
43
85
|
- sam@soff.es
|
@@ -59,8 +101,12 @@ files:
|
|
59
101
|
- lib/hue/bridge.rb
|
60
102
|
- lib/hue/cli.rb
|
61
103
|
- lib/hue/client.rb
|
104
|
+
- lib/hue/editable_state.rb
|
62
105
|
- lib/hue/errors.rb
|
106
|
+
- lib/hue/group.rb
|
63
107
|
- lib/hue/light.rb
|
108
|
+
- lib/hue/scene.rb
|
109
|
+
- lib/hue/translate_keys.rb
|
64
110
|
- lib/hue/version.rb
|
65
111
|
homepage: https://github.com/soffes/hue
|
66
112
|
licenses:
|
@@ -74,7 +120,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
74
120
|
requirements:
|
75
121
|
- - ">="
|
76
122
|
- !ruby/object:Gem::Version
|
77
|
-
version: 1.
|
123
|
+
version: 1.9.3
|
78
124
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
125
|
requirements:
|
80
126
|
- - ">="
|
@@ -82,7 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
82
128
|
version: '0'
|
83
129
|
requirements: []
|
84
130
|
rubyforge_project:
|
85
|
-
rubygems_version: 2.
|
131
|
+
rubygems_version: 2.4.5
|
86
132
|
signing_key:
|
87
133
|
specification_version: 4
|
88
134
|
summary: Work with Philips Hue light bulbs from Ruby.
|