huey 0.2.0 → 1.0.0
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.
- data/Gemfile +6 -1
- data/Gemfile.lock +10 -5
- data/README.markdown +44 -3
- data/huey.gemspec +1 -0
- data/lib/huey/event.rb +59 -0
- data/lib/huey/version.rb +2 -2
- data/lib/huey.rb +2 -0
- data/test/fixtures/events.yml +13 -0
- data/test/fixtures/groups.yml +3 -0
- data/test/test_helper.rb +1 -1
- data/test/unit/event_test.rb +99 -0
- data/test/unit/group_test.rb +3 -3
- metadata +22 -3
- data/test/fixtures/group.yml +0 -3
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
huey (
|
4
|
+
huey (1.0.0)
|
5
|
+
chronic (>= 0.9.0)
|
5
6
|
eventmachine (>= 1.0.0)
|
6
7
|
httparty (>= 0.9.0)
|
7
8
|
|
@@ -9,18 +10,20 @@ GEM
|
|
9
10
|
remote: http://rubygems.org/
|
10
11
|
specs:
|
11
12
|
addressable (2.3.2)
|
13
|
+
chronic (0.9.0)
|
12
14
|
color-tools (1.3.0)
|
13
15
|
crack (0.3.1)
|
14
16
|
eventmachine (1.0.0)
|
15
|
-
httparty (0.
|
17
|
+
httparty (0.10.2)
|
16
18
|
multi_json (~> 1.0)
|
17
|
-
multi_xml
|
19
|
+
multi_xml (>= 0.5.2)
|
18
20
|
metaclass (0.0.1)
|
19
21
|
mocha (0.13.1)
|
20
22
|
metaclass (~> 0.0.1)
|
21
|
-
multi_json (1.
|
22
|
-
multi_xml (0.5.
|
23
|
+
multi_json (1.6.1)
|
24
|
+
multi_xml (0.5.3)
|
23
25
|
rake (0.9.5)
|
26
|
+
timecop (0.5.9.2)
|
24
27
|
webmock (1.9.0)
|
25
28
|
addressable (>= 2.2.7)
|
26
29
|
crack (>= 0.1.7)
|
@@ -31,9 +34,11 @@ PLATFORMS
|
|
31
34
|
|
32
35
|
DEPENDENCIES
|
33
36
|
bundler
|
37
|
+
chronic
|
34
38
|
color-tools
|
35
39
|
huey!
|
36
40
|
mocha (>= 0.13.1)
|
37
41
|
rake
|
42
|
+
timecop
|
38
43
|
webmock (>= 1.9.0)
|
39
44
|
yard (>= 0.8.3)
|
data/README.markdown
CHANGED
@@ -7,11 +7,9 @@ Easy control of your Phillips Hue lights, in an attractive Gem format!
|
|
7
7
|
Installing Huey is pretty simple. First include the Gem in your Gemfile:
|
8
8
|
|
9
9
|
```ruby
|
10
|
-
gem 'huey'
|
10
|
+
gem 'huey'
|
11
11
|
```
|
12
12
|
|
13
|
-
(It's not in RubyGems yet because I'm not totally sure it's actually stable enough for release.)
|
14
|
-
|
15
13
|
You shouldn't need to initialize anything to make Huey work correctly, but if you want to specify some configuration options go nuts:
|
16
14
|
|
17
15
|
```ruby
|
@@ -106,6 +104,49 @@ group.save # All changes you've made are committed to all the bulbs in a group
|
|
106
104
|
group.update(bri: 200, ct: 500) # Set and save in one step
|
107
105
|
```
|
108
106
|
|
107
|
+
### Events
|
108
|
+
|
109
|
+
You probably want to always do the same actions over and over again to a group of bulbs. To help encapsulate that idea, we have events.
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
all = Huey::Group.new(bulbs: Huey::Bulb.all)
|
113
|
+
event = Huey::Event.new(name: 'All Lights Off', group: all, actions: {on: false})
|
114
|
+
|
115
|
+
event.execute # All lights turn off
|
116
|
+
```
|
117
|
+
|
118
|
+
If you like, you can schedule an event to execute only at a particular time if you have a really gimpy scheduling system.
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
event = Huey::Event.new(name: 'All Lights Off', group: all, actions: {on: false}, at: '9PM')
|
122
|
+
|
123
|
+
event.execute # nothing happens unless it's 9PM
|
124
|
+
Huey::Event.execute # run all events that should be run this second
|
125
|
+
```
|
126
|
+
|
127
|
+
It's probably easier for you to just directly invoke events from your scheduling system (cron or the like). To aid with that you can load events from a YAML file:
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
Huey::Group.import('groups.yml') # So that we can find groups
|
131
|
+
Huey::Event.import('events.yml')
|
132
|
+
# The file should look like this:
|
133
|
+
# Wakeup Call:
|
134
|
+
# group: Bedroom
|
135
|
+
# at: 9AM
|
136
|
+
# actions:
|
137
|
+
# bri: 100
|
138
|
+
# "on": true # Note the quotes, `on` is a reserved word for Yaml parsers
|
139
|
+
#
|
140
|
+
# Goodnight Time:
|
141
|
+
# group: Living Room
|
142
|
+
# at: 12AM
|
143
|
+
# actions:
|
144
|
+
# bri: 10
|
145
|
+
# "on": false # Note the quotes, `on` is a reserved word for Yaml parsers
|
146
|
+
|
147
|
+
Huey::Event.find('Wakeup Call').execute
|
148
|
+
```
|
149
|
+
|
109
150
|
## Attribution
|
110
151
|
|
111
152
|
The structure of the configuration files and the modules are taken from [Mongoid](https://github.com/mongoid/mongoid), which had some really great ideas.
|
data/huey.gemspec
CHANGED
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
|
|
20
20
|
|
21
21
|
s.add_dependency('eventmachine', '>=1.0.0')
|
22
22
|
s.add_dependency('httparty', '>=0.9.0')
|
23
|
+
s.add_dependency('chronic', '>=0.9.0')
|
23
24
|
|
24
25
|
s.add_development_dependency('bundler', '>=0')
|
25
26
|
s.add_development_dependency('yard', '>=0.8.3')
|
data/lib/huey/event.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Huey
|
4
|
+
|
5
|
+
# An event encapsulates logic to send to a group, either at a certain time or arbitrarily
|
6
|
+
class Event
|
7
|
+
attr_accessor :group, :at, :actions, :name
|
8
|
+
|
9
|
+
def self.import(file)
|
10
|
+
hash = YAML.load_file(file)
|
11
|
+
|
12
|
+
hash.each do |key, value|
|
13
|
+
options = {name: key}
|
14
|
+
value.each do |k, v|
|
15
|
+
options[k.to_sym] = v
|
16
|
+
end
|
17
|
+
|
18
|
+
Huey::Event.new(options)
|
19
|
+
end
|
20
|
+
Huey::Event.all
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.all
|
24
|
+
@all ||= []
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.find(name)
|
28
|
+
Huey::Event.all.find {|s| s.name == name}
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.execute(force = false)
|
32
|
+
Huey::Event.all.collect {|s| s.execute(force)}
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(options)
|
36
|
+
[:group, :actions].each do |key|
|
37
|
+
raise ArgumentError, "You must supply #{key} to create an event" unless options.keys.include?(key)
|
38
|
+
|
39
|
+
self.instance_variable_set("@#{key}".to_sym, options[key])
|
40
|
+
end
|
41
|
+
|
42
|
+
self.at = options[:at]
|
43
|
+
self.name = options[:name]
|
44
|
+
self.group = Huey::Group.find(self.group) unless self.group.is_a?(Huey::Group)
|
45
|
+
|
46
|
+
Huey::Event.all << self
|
47
|
+
end
|
48
|
+
|
49
|
+
def should_run?
|
50
|
+
((Chronic.parse(self.at) - 0.5)..(Chronic.parse(self.at) + 0.5)).cover?(Time.now)
|
51
|
+
end
|
52
|
+
|
53
|
+
def execute(force = false)
|
54
|
+
self.group.send(:update, actions) if force || at.nil? || should_run?
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
data/lib/huey/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module Huey
|
2
|
-
VERSION = "0.
|
3
|
-
end
|
2
|
+
VERSION = "1.0.0"
|
3
|
+
end
|
data/lib/huey.rb
CHANGED
@@ -5,6 +5,7 @@ require 'logger'
|
|
5
5
|
require 'httparty'
|
6
6
|
require 'color'
|
7
7
|
require 'yaml'
|
8
|
+
require 'chronic'
|
8
9
|
|
9
10
|
require 'huey/version'
|
10
11
|
|
@@ -14,6 +15,7 @@ require 'huey/ssdp'
|
|
14
15
|
require 'huey/request'
|
15
16
|
require 'huey/bulb'
|
16
17
|
require 'huey/group'
|
18
|
+
require 'huey/event'
|
17
19
|
|
18
20
|
module Huey
|
19
21
|
extend self
|
data/test/test_helper.rb
CHANGED
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class EventTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
super
|
7
|
+
Huey::Event.stubs(:all).returns([])
|
8
|
+
|
9
|
+
@bulb1 = init_bulb('1', 'Living Room - TV')
|
10
|
+
@bulb2 = init_bulb('2', 'Living Room - Fireplace')
|
11
|
+
@bulb3 = init_bulb('3', 'Foyer')
|
12
|
+
@bulb4 = init_bulb('4', 'Bedroom')
|
13
|
+
Huey::Bulb.stubs(:all).returns([@bulb1, @bulb2, @bulb3, @bulb4])
|
14
|
+
|
15
|
+
@group1 = Huey::Group.new(@bulb1, @bulb2)
|
16
|
+
@group1.name = 'Living Room'
|
17
|
+
@group2 = Huey::Group.new(@bulb1, @bulb2, @bulb3)
|
18
|
+
@group3 = Huey::Group.new(@bulb3)
|
19
|
+
@group4 = Huey::Group.new(@bulb4)
|
20
|
+
Huey::Group.stubs(:all).returns([@group1, @group2, @group3, @group4])
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_initializes_event
|
24
|
+
@event = Huey::Event.new(group: @group1, at: '8PM', actions: {bri: 100, on: true})
|
25
|
+
|
26
|
+
assert_equal @group1, @event.group
|
27
|
+
assert_equal '8PM', @event.at
|
28
|
+
assert_equal @event.actions, {bri: 100, on: true}
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_initializes_event_with_name
|
32
|
+
@event = Huey::Event.new(group: 'Living Room', at: '8PM', actions: {bri: 100, on: true})
|
33
|
+
|
34
|
+
assert_equal @group1, @event.group
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_executes_event
|
38
|
+
@event = Huey::Event.new(group: @group1, at: '8PM', actions: {bri: 100, on: true})
|
39
|
+
|
40
|
+
@group1.expects(:update).once.returns(true)
|
41
|
+
|
42
|
+
Timecop.freeze(Chronic.parse('8PM')) do
|
43
|
+
assert @event.should_run?
|
44
|
+
Huey::Event.execute
|
45
|
+
end
|
46
|
+
|
47
|
+
Timecop.freeze(Chronic.parse('10PM')) do
|
48
|
+
assert !@event.should_run?
|
49
|
+
Huey::Event.execute
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_executes_event_with_some_leeway
|
54
|
+
@event = Huey::Event.new(group: @group1, at: '8PM', actions: {bri: 100, on: true})
|
55
|
+
|
56
|
+
@group1.expects(:update).once.returns(true)
|
57
|
+
|
58
|
+
Timecop.freeze(Chronic.parse('8PM') - 0.3) do
|
59
|
+
assert @event.should_run?
|
60
|
+
Huey::Event.execute
|
61
|
+
end
|
62
|
+
|
63
|
+
Timecop.freeze(Chronic.parse('8PM') + 0.8) do
|
64
|
+
assert !@event.should_run?
|
65
|
+
Huey::Event.execute
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_force_execution
|
70
|
+
@event = Huey::Event.new(group: @group1, at: '8PM', actions: {bri: 100, on: true})
|
71
|
+
|
72
|
+
@group1.expects(:update).twice.returns(true)
|
73
|
+
|
74
|
+
Timecop.freeze(Chronic.parse('10PM')) do
|
75
|
+
assert !@event.should_run?
|
76
|
+
@event.execute(true)
|
77
|
+
Huey::Event.execute(true)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_execute_event_without_schedule
|
82
|
+
@event = Huey::Event.new(group: @group1, actions: {bri: 100, on: true})
|
83
|
+
|
84
|
+
@group1.expects(:update).once.returns(true)
|
85
|
+
|
86
|
+
@event.execute
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_import_schedule_from_yaml
|
90
|
+
Huey::Event.import('test/fixtures/events.yml')
|
91
|
+
|
92
|
+
assert_equal 2, Huey::Event.all.count
|
93
|
+
assert_equal 'Wakeup Call', Huey::Event.all[0].name
|
94
|
+
assert_equal Huey::Group.find('Bedroom'), Huey::Event.all[0].group
|
95
|
+
assert_equal '9AM', Huey::Event.all[0].at
|
96
|
+
assert_equal Huey::Event.all[0].actions, {'bri' => 100, 'on' => true}
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
data/test/unit/group_test.rb
CHANGED
@@ -4,6 +4,8 @@ class GroupTest < Test::Unit::TestCase
|
|
4
4
|
|
5
5
|
def setup
|
6
6
|
super
|
7
|
+
Huey::Group.stubs(:all).returns([])
|
8
|
+
|
7
9
|
@bulb1 = init_bulb('1', 'Living Room - TV')
|
8
10
|
@bulb2 = init_bulb('2', 'Living Room - Fireplace')
|
9
11
|
@bulb3 = init_bulb('3', 'Foyer')
|
@@ -31,9 +33,7 @@ class GroupTest < Test::Unit::TestCase
|
|
31
33
|
end
|
32
34
|
|
33
35
|
def test_initializes_groups_from_yml
|
34
|
-
Huey::Group.
|
35
|
-
|
36
|
-
Huey::Group.import('test/fixtures/group.yml')
|
36
|
+
Huey::Group.import('test/fixtures/groups.yml')
|
37
37
|
|
38
38
|
assert_equal 3, Huey::Group.all.count
|
39
39
|
assert_equal [@bulb1, @bulb2], Huey::Group.all[0].bulbs
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: huey
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-02-
|
12
|
+
date: 2013-02-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: eventmachine
|
@@ -43,6 +43,22 @@ dependencies:
|
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: 0.9.0
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: chronic
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.9.0
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.9.0
|
46
62
|
- !ruby/object:Gem::Dependency
|
47
63
|
name: bundler
|
48
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -128,14 +144,17 @@ files:
|
|
128
144
|
- lib/huey/config.rb
|
129
145
|
- lib/huey/config/options.rb
|
130
146
|
- lib/huey/errors.rb
|
147
|
+
- lib/huey/event.rb
|
131
148
|
- lib/huey/group.rb
|
132
149
|
- lib/huey/request.rb
|
133
150
|
- lib/huey/ssdp.rb
|
134
151
|
- lib/huey/ssdp/searcher.rb
|
135
152
|
- lib/huey/version.rb
|
136
|
-
- test/fixtures/
|
153
|
+
- test/fixtures/events.yml
|
154
|
+
- test/fixtures/groups.yml
|
137
155
|
- test/test_helper.rb
|
138
156
|
- test/unit/bulb_test.rb
|
157
|
+
- test/unit/event_test.rb
|
139
158
|
- test/unit/group_test.rb
|
140
159
|
- test/unit/request_test.rb
|
141
160
|
- test/unit/ssdp_test.rb
|
data/test/fixtures/group.yml
DELETED