huey 0.2.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -2,4 +2,9 @@ source "http://rubygems.org"
2
2
  gemspec
3
3
 
4
4
  gem 'rake'
5
- gem 'color-tools'
5
+ gem 'color-tools'
6
+ gem 'chronic'
7
+
8
+ group :development, :test do
9
+ gem 'timecop'
10
+ end
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- huey (0.1.0)
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.9.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.5.0)
22
- multi_xml (0.5.1)
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', git: 'git://github.com/Veraticus/huey.git'
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.2.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
@@ -0,0 +1,13 @@
1
+ Wakeup Call:
2
+ group: Bedroom
3
+ at: 9AM
4
+ actions:
5
+ bri: 100
6
+ "on": true
7
+
8
+ Goodnight Time:
9
+ group: Living Room
10
+ at: 12AM
11
+ actions:
12
+ bri: 10
13
+ "on": false
@@ -0,0 +1,3 @@
1
+ Living Room: [TV, Living Room - Fireplace]
2
+ Foyer: [Foyer]
3
+ Bedroom: [Bedroom]
data/test/test_helper.rb CHANGED
@@ -1,9 +1,9 @@
1
1
  require 'test/unit'
2
2
  require 'webmock/test_unit'
3
3
  require "mocha/setup"
4
+ require 'timecop'
4
5
  require 'huey'
5
6
 
6
-
7
7
  class Test::Unit::TestCase
8
8
  def setup
9
9
  super
@@ -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
@@ -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.instance_variable_set(:@all, [])
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.2.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-20 00:00:00.000000000 Z
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/group.yml
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
@@ -1,3 +0,0 @@
1
- living_room: [TV, Living Room - Fireplace]
2
- foyer: [Foyer]
3
- bedroom: [Bedroom]