hue-lib 0.7.1 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +26 -0
- data/hue-lib.gemspec +1 -1
- data/lib/hue/bridge.rb +1 -1
- data/lib/hue/bulb.rb +48 -9
- data/lib/hue/config/abstract.rb +3 -1
- data/lib/hue/config/application.rb +1 -1
- data/lib/hue.rb +10 -5
- data/spec/config/empty.yml +1 -0
- data/spec/hue/bulb_spec.rb +43 -0
- data/spec/hue/config/abstract_spec.rb +10 -0
- data/spec/hue/config/application_spec.rb +11 -0
- data/spec/hue/config/bridge_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -0
- data/test/connectivity.rb +44 -0
- metadata +4 -3
data/Rakefile
CHANGED
@@ -16,4 +16,30 @@ rescue LoadError
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
+
namespace :gem do
|
20
|
+
desc 'Build the gem'
|
21
|
+
task :build do
|
22
|
+
`mkdir -p pkg`
|
23
|
+
`gem build hue-lib.gemspec`
|
24
|
+
`mv *.gem pkg/`
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Publish the gem'
|
28
|
+
task :publish do
|
29
|
+
gem = `ls pkg`
|
30
|
+
# `gem push pkg/#{gem}`
|
31
|
+
end
|
32
|
+
|
33
|
+
desc 'Install the gem locally'
|
34
|
+
task :install do
|
35
|
+
gem = `ls pkg`.split.sort
|
36
|
+
`gem install pkg/#{gem.last}`
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
desc 'Remove generated files'
|
41
|
+
task :clean do
|
42
|
+
`rm -rf pkg`
|
43
|
+
end
|
44
|
+
|
19
45
|
task :default => [:spec]
|
data/hue-lib.gemspec
CHANGED
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "hue-lib"
|
6
|
-
s.version = '0.7.
|
6
|
+
s.version = '0.7.2'
|
7
7
|
s.authors = ["Birkir A. Barkarson", "Aaron Hurley"]
|
8
8
|
s.email = ["birkirb@stoicviking.net"]
|
9
9
|
s.homepage = "https://github.com/birkirb/hue-lib"
|
data/lib/hue/bridge.rb
CHANGED
@@ -104,7 +104,7 @@ module Hue
|
|
104
104
|
begin
|
105
105
|
http = Net::HTTP.new(url.host, url.port)
|
106
106
|
http.open_timeout = 3 # Quick timeout on connection fail.
|
107
|
-
http.read_timeout =
|
107
|
+
http.read_timeout = 8 # Slower timeout on read fail, but way faster than the default.
|
108
108
|
response = http.start { |http| http.request(request) }
|
109
109
|
rescue => err
|
110
110
|
Hue.logger.error(err.message)
|
data/lib/hue/bulb.rb
CHANGED
@@ -5,6 +5,8 @@ module Hue
|
|
5
5
|
class Bulb
|
6
6
|
|
7
7
|
BRIGHTNESS_MAX = 255
|
8
|
+
NONE = 'none'
|
9
|
+
COLOR_LOOP = 'colorloop'
|
8
10
|
|
9
11
|
include Animations::Candle
|
10
12
|
include Animations::Sunrise
|
@@ -34,6 +36,11 @@ module Hue
|
|
34
36
|
status['state']
|
35
37
|
end
|
36
38
|
|
39
|
+
# Free for all, no checking.
|
40
|
+
def state=(value)
|
41
|
+
update_state(value)
|
42
|
+
end
|
43
|
+
|
37
44
|
def [](item)
|
38
45
|
state[item.to_s]
|
39
46
|
end
|
@@ -104,36 +111,68 @@ module Hue
|
|
104
111
|
set_color
|
105
112
|
end
|
106
113
|
|
114
|
+
def effect
|
115
|
+
self['effect']
|
116
|
+
end
|
117
|
+
|
118
|
+
def effect=(value)
|
119
|
+
update_state(effect: value.to_s)
|
120
|
+
end
|
121
|
+
|
122
|
+
def effect?
|
123
|
+
NONE != self.effect
|
124
|
+
end
|
125
|
+
|
126
|
+
def color_loop
|
127
|
+
self.effect = COLOR_LOOP
|
128
|
+
end
|
129
|
+
alias :colorloop :color_loop
|
130
|
+
|
131
|
+
def color_loop?
|
132
|
+
COLOR_LOOP == self.effect
|
133
|
+
end
|
134
|
+
|
135
|
+
def clear_effect
|
136
|
+
self.effect = NONE
|
137
|
+
end
|
138
|
+
|
139
|
+
def alert
|
140
|
+
self['alert']
|
141
|
+
end
|
142
|
+
|
143
|
+
def alert=(value)
|
144
|
+
update_state(alert: value.to_s)
|
145
|
+
end
|
146
|
+
|
107
147
|
def blinking?
|
108
148
|
!solid?
|
109
149
|
end
|
110
150
|
|
111
151
|
def solid?
|
112
|
-
|
152
|
+
NONE == alert
|
113
153
|
end
|
114
154
|
|
115
155
|
def blink
|
116
|
-
|
156
|
+
self.alert = 'lselect'
|
117
157
|
end
|
118
158
|
|
119
159
|
def solid
|
120
|
-
|
160
|
+
self.alert = NONE
|
121
161
|
end
|
122
162
|
|
123
163
|
def flash
|
124
|
-
|
164
|
+
self.alert = 'select'
|
125
165
|
# immediately update to expected state
|
126
|
-
@status['state']['alert'] =
|
166
|
+
@status['state']['alert'] = NONE
|
127
167
|
end
|
128
168
|
|
169
|
+
# transition time in seconds
|
129
170
|
def transition_time
|
130
|
-
|
131
|
-
(options[:transitiontime] || 1).to_f / 10
|
171
|
+
(options[:transitiontime] || 0).to_f / 10
|
132
172
|
end
|
133
173
|
|
134
174
|
def transition_time=(time)
|
135
|
-
|
136
|
-
self.options[:transitiontime] = (time * 10).to_i
|
175
|
+
self.options[:transitiontime] = (time.to_f * 10).to_i
|
137
176
|
end
|
138
177
|
|
139
178
|
private
|
data/lib/hue/config/abstract.rb
CHANGED
@@ -18,7 +18,9 @@ module Hue
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def write(overwrite_existing_key = false)
|
21
|
-
yaml = YAML.load_file(self.path) rescue
|
21
|
+
yaml = YAML.load_file(self.path) rescue nil
|
22
|
+
yaml ||= Hash.new
|
23
|
+
|
22
24
|
if yaml.key?(name) && !overwrite_existing_key
|
23
25
|
raise "Key named '#{name}' already exists in config file '#{self.path}'.\nPlease remove it before creating a new one with the same name."
|
24
26
|
else
|
@@ -16,7 +16,7 @@ module Hue
|
|
16
16
|
|
17
17
|
def self.named(name)
|
18
18
|
yaml = read_file(file_path)
|
19
|
-
if named_yaml = yaml[name]
|
19
|
+
if yaml && named_yaml = yaml[name]
|
20
20
|
new(named_yaml[STRING_BRIDGE_ID], named_yaml[STRING_ID], name)
|
21
21
|
else
|
22
22
|
raise NotFound.new("Config named '#{name}' not found.")
|
data/lib/hue.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'net/http'
|
2
|
-
require 'digest/md5'
|
3
2
|
require 'json'
|
4
|
-
require '
|
3
|
+
require 'securerandom'
|
5
4
|
|
6
5
|
module Hue
|
7
6
|
|
@@ -15,7 +14,7 @@ module Hue
|
|
15
14
|
end
|
16
15
|
|
17
16
|
def self.one_time_uuid
|
18
|
-
|
17
|
+
SecureRandom.hex(16)
|
19
18
|
end
|
20
19
|
|
21
20
|
def self.register_default
|
@@ -71,10 +70,16 @@ ST: ssdp:all
|
|
71
70
|
loop do
|
72
71
|
message, (address_family, port, hostname, ip_add) = socket.recvfrom(1024)
|
73
72
|
if message =~ /IpBridge/ && location = /LOCATION: (.*)$/.match(message)
|
74
|
-
if
|
73
|
+
if uuid_match = /uuid:(.{36})/.match(message)
|
75
74
|
# Assume this is Philips Hue for now.
|
76
|
-
|
75
|
+
uuid = uuid_match.captures.first
|
76
|
+
if bridges[uuid].nil?
|
77
|
+
logger.info("Found bridge (#{hostname}:#{port}) with uuid: #{uuid}")
|
78
|
+
end
|
79
|
+
bridges[uuid] = "http://#{ip_add}/api"
|
77
80
|
end
|
81
|
+
else
|
82
|
+
logger.debug("Found #{hostname}:#{port}: #{message}")
|
78
83
|
end
|
79
84
|
end
|
80
85
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
--- {}
|
data/spec/hue/bulb_spec.rb
CHANGED
@@ -48,10 +48,21 @@ describe Hue::Bulb do
|
|
48
48
|
end
|
49
49
|
|
50
50
|
it "should report the alert state" do
|
51
|
+
bulb.alert.should == 'none'
|
51
52
|
bulb.blinking?.should be_false
|
52
53
|
bulb.solid?.should be_true
|
53
54
|
end
|
54
55
|
|
56
|
+
it "should report the effect state" do
|
57
|
+
bulb.effect?.should be_false
|
58
|
+
bulb.effect.should == 'none'
|
59
|
+
bulb.color_loop?.should be_false
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should report the transition time" do
|
63
|
+
bulb.transition_time.should == 0
|
64
|
+
end
|
65
|
+
|
55
66
|
context 'by changing state' do
|
56
67
|
|
57
68
|
it 'should allow turning bulps on and off' do
|
@@ -107,6 +118,38 @@ describe Hue::Bulb do
|
|
107
118
|
bulb.flash
|
108
119
|
bulb.solid?.should be_true
|
109
120
|
end
|
121
|
+
|
122
|
+
with_fake_update('lights/1/state', alert: 'crap') do
|
123
|
+
bulb.alert = 'crap'
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'should allow setting colorloop, and effect' do
|
128
|
+
with_fake_update('lights/1/state', effect: 'new')
|
129
|
+
bulb.effect = 'new'
|
130
|
+
bulb.effect.should == 'new'
|
131
|
+
bulb.effect?.should be_true
|
132
|
+
|
133
|
+
with_fake_update('lights/1/state', effect: 'colorloop')
|
134
|
+
bulb.colorloop
|
135
|
+
bulb.effect.should == 'colorloop'
|
136
|
+
bulb.effect?.should be_true
|
137
|
+
bulb.color_loop?.should be_true
|
138
|
+
|
139
|
+
with_fake_update('lights/1/state', effect: 'none')
|
140
|
+
bulb.clear_effect
|
141
|
+
bulb.effect.should == 'none'
|
142
|
+
|
143
|
+
with_fake_update('lights/1/state', effect: 'colorloop')
|
144
|
+
bulb.color_loop
|
145
|
+
bulb.effect.should == 'colorloop'
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'should allow setting the transitions time, and employ it for a state change' do
|
149
|
+
bulb.transition_time = 10
|
150
|
+
|
151
|
+
with_fake_update('lights/1/state', transitiontime: 100, bri: 255)
|
152
|
+
bulb.brightness = 255
|
110
153
|
end
|
111
154
|
|
112
155
|
end
|
@@ -32,4 +32,14 @@ describe Hue::Config::Abstract do
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
+
context 'given an existing config' do
|
36
|
+
config = described_class.new('test', EMPTY_CONFIG_FILE)
|
37
|
+
|
38
|
+
it 'should allow writing to the file' do
|
39
|
+
config.write
|
40
|
+
YAML.load_file(config.path)['test'].should be_a(Hash)
|
41
|
+
config.delete
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
35
45
|
end
|
@@ -58,4 +58,15 @@ describe Hue::Config::Application do
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
+
context 'given an non existing config' do
|
62
|
+
|
63
|
+
it "should throw and error if a named config doesn't exist" do
|
64
|
+
described_class.expects(:file_path).returns(EMPTY_CONFIG_FILE).once
|
65
|
+
|
66
|
+
lambda do
|
67
|
+
described_class.named('not_default')
|
68
|
+
end.should raise_error(Hue::Config::NotFound, /Config named (.*) not found/)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
61
72
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -36,6 +36,7 @@ def silence_warnings
|
|
36
36
|
end
|
37
37
|
|
38
38
|
SPEC_DIR = File.dirname(__FILE__)
|
39
|
+
Hue.logger.level = Logger::DEBUG
|
39
40
|
|
40
41
|
silence_warnings do
|
41
42
|
Hue.const_set(:DEFAULT_UDP_TIMEOUT, 0.01)
|
@@ -43,6 +44,7 @@ end
|
|
43
44
|
|
44
45
|
# APPLICATION CONFIG
|
45
46
|
|
47
|
+
EMPTY_CONFIG_FILE = File.join(SPEC_DIR, 'config', 'empty.yml')
|
46
48
|
TEST_CONFIG_APPLICATION_PATH = File.join(SPEC_DIR, 'config', 'applications.yml')
|
47
49
|
TEST_CONFIG_APPLICATION = YAML.load_file(TEST_CONFIG_APPLICATION_PATH)
|
48
50
|
TEST_JSON_DATA_PATH = File.join(SPEC_DIR, 'json')
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'hue'
|
2
|
+
|
3
|
+
bridge = Hue.application
|
4
|
+
|
5
|
+
MAX_LIGHTS = 4
|
6
|
+
|
7
|
+
@run = true
|
8
|
+
@command_count = 0
|
9
|
+
@error_count = 0
|
10
|
+
|
11
|
+
trap("SIGINT") do
|
12
|
+
@run = false
|
13
|
+
end
|
14
|
+
|
15
|
+
while(@run)
|
16
|
+
begin
|
17
|
+
@command_count += 1
|
18
|
+
number = rand(4)
|
19
|
+
light = rand(MAX_LIGHTS)
|
20
|
+
case number
|
21
|
+
when 0
|
22
|
+
puts bridge.status['config']['UTC']
|
23
|
+
when 1
|
24
|
+
print "#{light + 1} name: "
|
25
|
+
puts bridge.bulbs[light].refresh!['name']
|
26
|
+
when 2
|
27
|
+
print "#{light + 1} on: "
|
28
|
+
puts bridge.bulbs[light].on
|
29
|
+
when 3
|
30
|
+
print "#{light + 1} off: "
|
31
|
+
puts bridge.bulbs[light].off
|
32
|
+
else
|
33
|
+
raise "Unhandled case: #{number}"
|
34
|
+
end
|
35
|
+
rescue => err
|
36
|
+
puts err.message
|
37
|
+
@error_count += 1
|
38
|
+
end
|
39
|
+
sleep 1
|
40
|
+
end
|
41
|
+
|
42
|
+
puts "Command count: #{@command_count}"
|
43
|
+
puts "Fail count: #{@error_count}"
|
44
|
+
puts "Success rate: #{(1.0 - (@error_count/@command_count.to_f)) * 100}%"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hue-lib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-
|
13
|
+
date: 2013-09-04 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: json
|
@@ -106,6 +106,7 @@ files:
|
|
106
106
|
- lib/hue/config/bridge.rb
|
107
107
|
- spec/config/applications.yml
|
108
108
|
- spec/config/bridges.yml
|
109
|
+
- spec/config/empty.yml
|
109
110
|
- spec/hue/bridge_spec.rb
|
110
111
|
- spec/hue/bulb_spec.rb
|
111
112
|
- spec/hue/colors/color_spec.rb
|
@@ -130,6 +131,7 @@ files:
|
|
130
131
|
- spec/json/schedules.json
|
131
132
|
- spec/json/unauthorized.json
|
132
133
|
- spec/spec_helper.rb
|
134
|
+
- test/connectivity.rb
|
133
135
|
homepage: https://github.com/birkirb/hue-lib
|
134
136
|
licenses: []
|
135
137
|
post_install_message:
|
@@ -155,4 +157,3 @@ signing_key:
|
|
155
157
|
specification_version: 3
|
156
158
|
summary: Ruby library for controlling the Philips Hue system's lights and bridge.
|
157
159
|
test_files: []
|
158
|
-
has_rdoc:
|