hue 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Readme.markdown +2 -0
- data/Todo.markdown +0 -1
- data/lib/hue.rb +1 -0
- data/lib/hue/bridge.rb +104 -0
- data/lib/hue/client.rb +23 -16
- data/lib/hue/errors.rb +1 -0
- data/lib/hue/light.rb +59 -40
- data/lib/hue/version.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d6a7f55311b35aa3cb7e2907ecad349632e102b7
|
4
|
+
data.tar.gz: 3201fe193181c257741f03f14a71b78b78ca3ecf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76884d923bbe4ee4084bd121caae4f0004cb25f0fcd8e0618f27acd5887c89350f412e4d765c2e0ac148c079e82f245261d0a8664eff2eb6dbb3a7a64d8f88b3
|
7
|
+
data.tar.gz: c86bbdea9bca5ec707791137c72836fae70f3a4fd9978eff41b472968391f2a32b14494bb9885fa943a8f636ac9d4e9a62de83d15bc24917fcdcdeae2829c150
|
data/Readme.markdown
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
Work with Philips Hue light bulbs from Ruby.
|
4
4
|
|
5
|
+
[](https://codeclimate.com/github/soffes/hue) [](https://gemnasium.com/soffes/hue) [](http://badge.fury.io/rb/hue)
|
6
|
+
|
5
7
|
## Installation
|
6
8
|
|
7
9
|
Add this line to your application's Gemfile:
|
data/Todo.markdown
CHANGED
data/lib/hue.rb
CHANGED
data/lib/hue/bridge.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
module Hue
|
2
|
+
class Bridge
|
3
|
+
# ID of the bridge.
|
4
|
+
attr_reader :id
|
5
|
+
|
6
|
+
# Name of the bridge. This is also its uPnP name, so will reflect the
|
7
|
+
# actual uPnP name after any conflicts have been resolved.
|
8
|
+
attr_accessor :name
|
9
|
+
|
10
|
+
# IP address of the bridge.
|
11
|
+
attr_reader :ip
|
12
|
+
|
13
|
+
# MAC address of the bridge.
|
14
|
+
attr_reader :mac_address
|
15
|
+
|
16
|
+
# IP Address of the proxy server being used.
|
17
|
+
attr_reader :proxy_address
|
18
|
+
|
19
|
+
# Port of the proxy being used by the bridge. If set to 0 then a proxy is
|
20
|
+
# not being used.
|
21
|
+
attr_reader :proxy_port
|
22
|
+
|
23
|
+
# Software version of the bridge.
|
24
|
+
attr_reader :software_version
|
25
|
+
|
26
|
+
# Contains information related to software updates.
|
27
|
+
attr_reader :software_update
|
28
|
+
|
29
|
+
# An array of whitelisted user IDs.
|
30
|
+
attr_reader :ip_whitelist
|
31
|
+
|
32
|
+
# Network mask of the bridge.
|
33
|
+
attr_reader :network_mask
|
34
|
+
|
35
|
+
# Gateway IP address of the bridge.
|
36
|
+
attr_reader :gateway
|
37
|
+
|
38
|
+
# Whether the IP address of the bridge is obtained with DHCP.
|
39
|
+
attr_reader :dhcp
|
40
|
+
|
41
|
+
def initialize(client, hash)
|
42
|
+
@client = client
|
43
|
+
unpack(hash)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Current time stored on the bridge.
|
47
|
+
def utc
|
48
|
+
json = get_configuration
|
49
|
+
DateTime.parse(json['utc'])
|
50
|
+
end
|
51
|
+
|
52
|
+
# Indicates whether the link button has been pressed within the last 30
|
53
|
+
# seconds.
|
54
|
+
def link_button_pressed?
|
55
|
+
json = get_configuration
|
56
|
+
json['linkbutton']
|
57
|
+
end
|
58
|
+
|
59
|
+
# This indicates whether the bridge is registered to synchronize data with a
|
60
|
+
# portal account.
|
61
|
+
def has_portal_services?
|
62
|
+
json = get_configuration
|
63
|
+
json['portalservices']
|
64
|
+
end
|
65
|
+
|
66
|
+
def refresh
|
67
|
+
json = get_configuration
|
68
|
+
unpack(json)
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
KEYS_MAP = {
|
74
|
+
:id => :id,
|
75
|
+
:ip => :internalipaddress,
|
76
|
+
:name => :name,
|
77
|
+
:proxy_port => :proxyport,
|
78
|
+
:software_update => :swupdate,
|
79
|
+
:ip_whitelist => :whitelist,
|
80
|
+
:software_version => :swversion,
|
81
|
+
:proxy_address => :proxyaddress,
|
82
|
+
:mac_address => :macaddress,
|
83
|
+
:network_mask => :netmask,
|
84
|
+
:portal_services => :portalservices,
|
85
|
+
}
|
86
|
+
|
87
|
+
def unpack(hash)
|
88
|
+
puts hash
|
89
|
+
KEYS_MAP.each do |local_key, remote_key|
|
90
|
+
value = hash[remote_key.to_s]
|
91
|
+
next unless value
|
92
|
+
instance_variable_set("@#{local_key}", value)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def get_configuration
|
97
|
+
MultiJson.load(Net::HTTP.get(URI.parse("#{base_url}/config")))
|
98
|
+
end
|
99
|
+
|
100
|
+
def base_url
|
101
|
+
"http://#{ip}/api/#{@client.username}"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
data/lib/hue/client.rb
CHANGED
@@ -14,23 +14,29 @@ module Hue
|
|
14
14
|
validate_user
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
17
|
+
def bridge
|
18
18
|
# Pick the first one for now. In theory, they should all do the same thing.
|
19
|
-
|
20
|
-
raise
|
21
|
-
|
19
|
+
bridge = bridges.first
|
20
|
+
raise NoBridgeFound unless bridge
|
21
|
+
bridge
|
22
22
|
end
|
23
23
|
|
24
|
-
def
|
25
|
-
@
|
24
|
+
def bridges
|
25
|
+
@bridges ||= begin
|
26
|
+
bs = []
|
27
|
+
MultiJson.load(Net::HTTP.get(URI.parse('http://www.meethue.com/api/nupnp'))).each do |hash|
|
28
|
+
bs << Bridge.new(self, hash)
|
29
|
+
end
|
30
|
+
bs
|
31
|
+
end
|
26
32
|
end
|
27
33
|
|
28
34
|
def lights
|
29
35
|
@lights ||= begin
|
30
36
|
ls = []
|
31
|
-
json = MultiJson.load(Net::HTTP.get(URI.parse("http://#{
|
32
|
-
json.each do |key, value|
|
33
|
-
ls << Light.new(self, key, value
|
37
|
+
json = MultiJson.load(Net::HTTP.get(URI.parse("http://#{bridge.ip}/api/#{@username}")))
|
38
|
+
json['lights'].each do |key, value|
|
39
|
+
ls << Light.new(self, bridge, key, value)
|
34
40
|
end
|
35
41
|
ls
|
36
42
|
end
|
@@ -43,7 +49,12 @@ module Hue
|
|
43
49
|
private
|
44
50
|
|
45
51
|
def validate_user
|
46
|
-
response = MultiJson.load(Net::HTTP.get(URI.parse("http://#{
|
52
|
+
response = MultiJson.load(Net::HTTP.get(URI.parse("http://#{bridge.ip}/api/#{@username}")))
|
53
|
+
|
54
|
+
if response.is_a? Array
|
55
|
+
response = response.first
|
56
|
+
end
|
57
|
+
|
47
58
|
if error = response['error']
|
48
59
|
parse_error(error)
|
49
60
|
end
|
@@ -56,8 +67,8 @@ module Hue
|
|
56
67
|
username: @username
|
57
68
|
}
|
58
69
|
|
59
|
-
uri = URI.parse("http://#{
|
60
|
-
http = Net::HTTP.new(uri.
|
70
|
+
uri = URI.parse("http://#{bridge.ip}/api")
|
71
|
+
http = Net::HTTP.new(uri.host)
|
61
72
|
response = MultiJson.load(http.request_post(uri.path, MultiJson.dump(body)).body).first
|
62
73
|
|
63
74
|
if error = response['error']
|
@@ -66,10 +77,6 @@ module Hue
|
|
66
77
|
response['success']
|
67
78
|
end
|
68
79
|
|
69
|
-
def bridge_ip
|
70
|
-
base_station['internalipaddress']
|
71
|
-
end
|
72
|
-
|
73
80
|
def parse_error(error)
|
74
81
|
# Find error or return
|
75
82
|
klass = Hue::ERROR_MAP[error['type']]
|
data/lib/hue/errors.rb
CHANGED
data/lib/hue/light.rb
CHANGED
@@ -8,6 +8,9 @@ module Hue
|
|
8
8
|
# Unique identification number.
|
9
9
|
attr_reader :id
|
10
10
|
|
11
|
+
# Bridge the light is associated with
|
12
|
+
attr_reader :bridge
|
13
|
+
|
11
14
|
# A unique, editable name given to the light.
|
12
15
|
attr_accessor :name
|
13
16
|
|
@@ -78,15 +81,11 @@ module Hue
|
|
78
81
|
# Reserved for future functionality.
|
79
82
|
attr_reader :point_symbol
|
80
83
|
|
81
|
-
def initialize(client, id,
|
84
|
+
def initialize(client, bridge, id, hash)
|
82
85
|
@client = client
|
86
|
+
@bridge = bridge
|
83
87
|
@id = id
|
84
|
-
|
85
|
-
refresh
|
86
|
-
end
|
87
|
-
|
88
|
-
def [](index)
|
89
|
-
lights[index]
|
88
|
+
unpack(hash)
|
90
89
|
end
|
91
90
|
|
92
91
|
def name=(new_name)
|
@@ -99,7 +98,7 @@ module Hue
|
|
99
98
|
}
|
100
99
|
|
101
100
|
uri = URI.parse(base_url)
|
102
|
-
http = Net::HTTP.new(uri.
|
101
|
+
http = Net::HTTP.new(uri.host)
|
103
102
|
response = http.request_put(uri.path, MultiJson.dump(body))
|
104
103
|
response = MultiJson.load(response.body).first
|
105
104
|
if response['success']
|
@@ -133,28 +132,17 @@ module Hue
|
|
133
132
|
end
|
134
133
|
|
135
134
|
# @param transition The duration of the transition from the light’s current
|
136
|
-
# state to the new state. This is given as a multiple of 100ms and
|
137
|
-
# to 4 (400ms). For example, setting transistiontime:10 will
|
138
|
-
# transition last 1 second.
|
135
|
+
# state to the new state. This is given as a multiple of 100ms and
|
136
|
+
# defaults to 4 (400ms). For example, setting transistiontime:10 will
|
137
|
+
# make the transition last 1 second.
|
139
138
|
def set_state(attributes, transition = nil)
|
140
|
-
|
141
|
-
:brightness => :bri,
|
142
|
-
:saturation => :sat,
|
143
|
-
:color_temperature => :ct,
|
144
|
-
}
|
145
|
-
|
146
|
-
body = {}
|
147
|
-
attributes.each do |key, value|
|
148
|
-
new_key = map[key.to_sym]
|
149
|
-
key = new_key if new_key
|
150
|
-
body[key] = value
|
151
|
-
end
|
139
|
+
body = translate_keys(attributes)
|
152
140
|
|
153
141
|
# Add transition
|
154
142
|
body.merge!({:transitiontime => transition}) if transition
|
155
143
|
|
156
144
|
uri = URI.parse("#{base_url}/state")
|
157
|
-
http = Net::HTTP.new(uri.
|
145
|
+
http = Net::HTTP.new(uri.host)
|
158
146
|
response = http.request_put(uri.path, MultiJson.dump(body))
|
159
147
|
MultiJson.load(response.body)
|
160
148
|
end
|
@@ -162,28 +150,59 @@ module Hue
|
|
162
150
|
# Refresh the state of the lamp
|
163
151
|
def refresh
|
164
152
|
json = MultiJson.load(Net::HTTP.get(URI.parse(base_url)))
|
153
|
+
unpack(json)
|
154
|
+
end
|
165
155
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
156
|
+
private
|
157
|
+
|
158
|
+
KEYS_MAP = {
|
159
|
+
:state => :state,
|
160
|
+
:type => :type,
|
161
|
+
:name => :name,
|
162
|
+
:model => :modelid,
|
163
|
+
:software_version => :swversion,
|
164
|
+
:point_symbol => :pointsymbol
|
165
|
+
}
|
166
|
+
|
167
|
+
STATE_KEYS_MAP = {
|
168
|
+
:on => :on,
|
169
|
+
:brightness => :bri,
|
170
|
+
:hue => :hue,
|
171
|
+
:saturation => :sat,
|
172
|
+
:xy => :xy,
|
173
|
+
:color_temperature => :ct,
|
174
|
+
:alert => :alert,
|
175
|
+
:effect => :effect,
|
176
|
+
:color_mode => :colormode,
|
177
|
+
:reachable => :reachable,
|
178
|
+
}
|
179
|
+
|
180
|
+
def translate_keys(hash)
|
181
|
+
new_hash = {}
|
182
|
+
hash.each do |key, value|
|
183
|
+
new_key = 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
|
+
def unpack(hash)
|
191
|
+
unpack_hash(hash, KEYS_MAP)
|
192
|
+
unpack_hash(@state, STATE_KEYS_MAP)
|
170
193
|
@x, @y = @state['xy']
|
171
|
-
@color_temperature = @state['ct']
|
172
|
-
@alert = @state['alert'].to_sym
|
173
|
-
@effect = @state['effect'].to_sym
|
174
|
-
@color_mode = @state['colormode']
|
175
|
-
@type = json['type']
|
176
|
-
@name = json['name']
|
177
|
-
@model = json['modelid']
|
178
|
-
@software_version = json['swversion']
|
179
|
-
@point_symbol = json['pointsymbol']
|
180
194
|
end
|
181
195
|
|
182
|
-
|
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
|
183
203
|
|
184
204
|
def base_url
|
185
|
-
|
186
|
-
"http://#{bridge_ip}/api/#{@client.username}/lights/#{id}"
|
205
|
+
"http://#{@bridge.ip}/api/#{@client.username}/lights/#{id}"
|
187
206
|
end
|
188
207
|
end
|
189
208
|
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.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Soffes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-03
|
11
|
+
date: 2013-06-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: multi_json
|
@@ -56,6 +56,7 @@ files:
|
|
56
56
|
- bin/hue
|
57
57
|
- hue.gemspec
|
58
58
|
- lib/hue.rb
|
59
|
+
- lib/hue/bridge.rb
|
59
60
|
- lib/hue/cli.rb
|
60
61
|
- lib/hue/client.rb
|
61
62
|
- lib/hue/errors.rb
|
@@ -81,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
81
82
|
version: '0'
|
82
83
|
requirements: []
|
83
84
|
rubyforge_project:
|
84
|
-
rubygems_version: 2.0.
|
85
|
+
rubygems_version: 2.0.2
|
85
86
|
signing_key:
|
86
87
|
specification_version: 4
|
87
88
|
summary: Work with Philips Hue light bulbs from Ruby.
|