lights 0.8.9 → 0.8.10
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 +8 -8
- data/README.md +1 -1
- data/bin/lights +1 -6
- data/lib/lights.rb +1 -7
- data/lib/lights/bulb.rb +7 -2
- data/lib/lights/bulblist.rb +22 -0
- data/lib/lights/bulbstate.rb +18 -17
- data/lib/lights/command.rb +1 -1
- data/lib/lights/config.rb +26 -0
- data/lib/lights/datastore.rb +50 -0
- data/lib/lights/group.rb +1 -3
- data/lib/lights/grouplist.rb +22 -0
- data/lib/lights/rule.rb +1 -3
- data/lib/lights/rulelist.rb +22 -0
- data/lib/lights/scene.rb +4 -0
- data/lib/lights/scenelist.rb +22 -0
- data/lib/lights/schedule.rb +1 -1
- data/lib/lights/schedulelist.rb +22 -0
- data/lib/lights/sensor.rb +36 -0
- data/lib/lights/sensorlist.rb +23 -0
- data/lib/lights/user.rb +12 -0
- data/lib/lights/userlist.rb +22 -0
- data/lib/lights/version.rb +1 -1
- data/lights.gemspec +1 -1
- data/spec/datastore_spec.rb +515 -0
- metadata +14 -3
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MWJlYThiNGQ5NzkxYjA3NjRmOTcxYzNmMGFkMzcyY2I0Mzk5MjY5Mg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZDFiM2M3ZDE3OWU5YWMwZDgyOTY5YTk4MjRiMzA5NmVjY2Q5NDEyNw==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MTEwOTkwNTdhYjUyMTNmZDJiOTkwYWIzZWZlNzc0MWJlYjNmYjgzMWE1Y2Yy
|
10
|
+
ZGFmYmRlNTBiNmRjYWExNGUwYWE1M2I1YTdmNjVjYmI5NzcyYWExZjFjMTgx
|
11
|
+
M2EwMmMwNjQ1MmY3NmFhMmMzMmY2NzZhZGIwYjE4ODFjNDVmZGE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZmU0YTE1ZGUxOTgyNTAyMzlhNzQ4OTUzZDg4NDMyMmRlNDEzOTY3M2ViODNm
|
14
|
+
NzhiMTM5MDNkYTI0MDQyYTc1ZGU0N2RkZjVlNTYwZjRiNDg0ZjA4NjE4MGM1
|
15
|
+
OTg5MGNhM2E1MzM5OGRjMjczN2U1YzcyZGU1MjUyZTA3ZTcwNDk=
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
lights
|
2
2
|
========
|
3
|
-
A Ruby library & CLI for
|
3
|
+
A Ruby library & CLI for interacting with Philips Hue.
|
4
4
|
|
5
5
|
* Philips Hue API Documentation: http://www.developers.meethue.com/philips-hue-api
|
6
6
|
* lights on RubyGems: https://rubygems.org/gems/lights
|
data/bin/lights
CHANGED
@@ -173,12 +173,7 @@ class LightsCli
|
|
173
173
|
methods = [:id,:name,:time,:scene,:status]
|
174
174
|
when "datastore"
|
175
175
|
response = hue.request_datastore
|
176
|
-
|
177
|
-
response["groups"].each {|id,value| objects << Group.new(id,value)}
|
178
|
-
response["config"]["whitelist"].each {|id,value| objects << User.new(id,value)}
|
179
|
-
response["rules"].each {|id,value| objects << Rule.new(id,value)}
|
180
|
-
response["scenes"].each {|id,value| objects << Scene.new(id,value)}
|
181
|
-
response["schedules"].each {|id,value| objects << Schedule.new(id,value)}
|
176
|
+
objects = Datastore.new(response).all
|
182
177
|
titles = ["TYPE","ID","NAME"]
|
183
178
|
methods = [:class,:id,:name]
|
184
179
|
else
|
data/lib/lights.rb
CHANGED
@@ -4,15 +4,9 @@ require 'net/http'
|
|
4
4
|
require 'uri'
|
5
5
|
require 'json'
|
6
6
|
|
7
|
-
require 'lights/bulb'
|
8
|
-
require 'lights/group'
|
9
7
|
require 'lights/bridge'
|
10
8
|
require 'lights/exception'
|
11
|
-
require 'lights/
|
12
|
-
require 'lights/scene'
|
13
|
-
require 'lights/user'
|
14
|
-
require 'lights/rule'
|
15
|
-
require 'lights/schedule'
|
9
|
+
require 'lights/datastore'
|
16
10
|
require 'lights/loggerconfig'
|
17
11
|
|
18
12
|
def jp( s )
|
data/lib/lights/bulb.rb
CHANGED
@@ -9,17 +9,22 @@ class Bulb
|
|
9
9
|
@id = id
|
10
10
|
@name = data["name"]
|
11
11
|
@type = data["type"]
|
12
|
-
@swversion = data["
|
12
|
+
@swversion = data["swversion"]
|
13
13
|
@state = BulbState.new data["state"]
|
14
|
+
@data = data
|
14
15
|
end
|
15
16
|
|
16
17
|
def data
|
17
|
-
data =
|
18
|
+
data = @data
|
18
19
|
data["name"] = @name if @name
|
19
20
|
data["type"] = @type if @type
|
20
21
|
data["swversion"] = @swversion if @swversion
|
21
22
|
data["state"] = @state.data if !@state.data.empty?
|
22
23
|
data
|
23
24
|
end
|
25
|
+
|
26
|
+
def to_json(options={})
|
27
|
+
data.to_json
|
28
|
+
end
|
24
29
|
end
|
25
30
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'lights/bulb'
|
2
|
+
|
3
|
+
class BulbList
|
4
|
+
|
5
|
+
attr_reader :bulbs
|
6
|
+
def initialize(data = {})
|
7
|
+
@bulbs = []
|
8
|
+
data.each{|id,value| @bulbs << Bulb.new(id,value)} if data
|
9
|
+
@data = data
|
10
|
+
end
|
11
|
+
|
12
|
+
def data
|
13
|
+
data = @data
|
14
|
+
@bulbs.each {|b| data[b.id] = b.data} if @bulbs
|
15
|
+
data
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_json(options={})
|
19
|
+
data.to_json
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
data/lib/lights/bulbstate.rb
CHANGED
@@ -46,6 +46,7 @@ class BulbState
|
|
46
46
|
set_color_mode data["colormode"]
|
47
47
|
@reachable = data["reachable"]
|
48
48
|
set_transition_time data["transitiontime"]
|
49
|
+
@data = data
|
49
50
|
end
|
50
51
|
|
51
52
|
def color_mode=(value) set_color_mode(value) end
|
@@ -55,7 +56,7 @@ class BulbState
|
|
55
56
|
|| value == ColorMode::CT
|
56
57
|
@color_mode = value
|
57
58
|
else
|
58
|
-
raise BulbStateValueTypeException, "
|
59
|
+
raise BulbStateValueTypeException, "Color mode value has incorrect type. Requires 'hs', 'xy', or 'ct'. Was #{value.inspect}"
|
59
60
|
end
|
60
61
|
end
|
61
62
|
|
@@ -66,7 +67,7 @@ class BulbState
|
|
66
67
|
|| value == Alert::LSELECT
|
67
68
|
@alert = value
|
68
69
|
else
|
69
|
-
raise BulbStateValueTypeException, "
|
70
|
+
raise BulbStateValueTypeException, "Alert value has incorrect type. Requires 'none', 'select', or 'lselect'. Was #{value.inspect}"
|
70
71
|
end
|
71
72
|
end
|
72
73
|
|
@@ -75,7 +76,7 @@ class BulbState
|
|
75
76
|
if value.nil? || value == Effect::NONE || value == Effect::COLORLOOP
|
76
77
|
@effect = value
|
77
78
|
else
|
78
|
-
raise BulbStateValueTypeException, "
|
79
|
+
raise BulbStateValueTypeException, "Effect value has incorrect type. Requires 'none' or 'colorloop'. Was #{value.inspect}"
|
79
80
|
end
|
80
81
|
end
|
81
82
|
|
@@ -85,7 +86,7 @@ class BulbState
|
|
85
86
|
if !!value == value
|
86
87
|
@on = value
|
87
88
|
else
|
88
|
-
raise BulbStateValueTypeException, "
|
89
|
+
raise BulbStateValueTypeException, "On value has incorrect type. Requires boolean, got #{value.class}. Was #{value.inspect}"
|
89
90
|
end
|
90
91
|
end
|
91
92
|
|
@@ -94,58 +95,58 @@ class BulbState
|
|
94
95
|
if value.nil? || value.between?(MIN_BRI,MAX_BRI)
|
95
96
|
@bri = value
|
96
97
|
else
|
97
|
-
raise BulbStateValueOutOfRangeException, "
|
98
|
+
raise BulbStateValueOutOfRangeException, "Brightness value out of range. Must be [#{MIN_BRI},#{MAX_BRI}]. Was #{value.inspect}"
|
98
99
|
end
|
99
100
|
end
|
100
101
|
|
101
102
|
def ct=(value); set_ct(value) end
|
102
103
|
def set_ct(value)
|
103
104
|
if !value.nil? && (!value.is_a? Integer)
|
104
|
-
raise BulbStateValueTypeException, "
|
105
|
+
raise BulbStateValueTypeException, "Color temperature value has incorrect type. Requires integer, got #{value.class}"
|
105
106
|
elsif value.nil? || value.between?(MIN_CT,MAX_CT)
|
106
107
|
@ct = value
|
107
108
|
else
|
108
|
-
raise BulbStateValueOutOfRangeException, "
|
109
|
+
raise BulbStateValueOutOfRangeException, "Color temperature value out of range. Must be [#{MIN_CT},#{MAX_CT}]. Was #{value.inspect}"
|
109
110
|
end
|
110
111
|
end
|
111
112
|
|
112
113
|
def sat=(value); set_sat(value) end
|
113
114
|
def set_sat(value)
|
114
115
|
if !value.nil? && (!value.is_a? Integer)
|
115
|
-
raise BulbStateValueTypeException, "
|
116
|
+
raise BulbStateValueTypeException, "Saturation value has incorrect type. Requires integer, got #{value.class}"
|
116
117
|
elsif value.nil? || value.between?(MIN_SAT,MAX_SAT)
|
117
118
|
@sat = value
|
118
119
|
else
|
119
|
-
raise BulbStateValueOutOfRangeException, "
|
120
|
+
raise BulbStateValueOutOfRangeException, "Saturation alue out of range. Must be [#{MIN_SAT},#{MAX_SAT}]. Was #{value.inspect}"
|
120
121
|
end
|
121
122
|
end
|
122
123
|
|
123
124
|
def hue=(value); set_hue(value) end
|
124
125
|
def set_hue(value)
|
125
126
|
if !value.nil? && (!value.is_a? Integer)
|
126
|
-
raise BulbStateValueTypeException, "
|
127
|
+
raise BulbStateValueTypeException, "Hue value has incorrect type. Requires integer, got #{value.class}"
|
127
128
|
elsif value.nil? || value.between?(MIN_HUE,MAX_HUE)
|
128
129
|
@hue = value
|
129
130
|
else
|
130
|
-
raise BulbStateValueOutOfRangeException, "
|
131
|
+
raise BulbStateValueOutOfRangeException, "Hue value out of range. Must be [#{MIN_HUE},#{MAX_HUE}]. Was #{value.inspect}"
|
131
132
|
end
|
132
133
|
end
|
133
134
|
|
134
135
|
def transition_time=(value); set_transition_time(value) end
|
135
136
|
def set_transition_time(value)
|
136
137
|
if !value.nil? && (!value.is_a? Numeric)
|
137
|
-
raise BulbStateValueTypeException, "
|
138
|
+
raise BulbStateValueTypeException, "Transition time value has incorrect type. Requires decimal, got #{value.class}"
|
138
139
|
elsif value.nil? || value >= MIN_TRANSITION_TIME
|
139
140
|
@transition_time = value
|
140
141
|
else
|
141
|
-
raise BulbStateValueOutOfRangeException, "
|
142
|
+
raise BulbStateValueOutOfRangeException, "Transition time value out of range. Must be > #{MIN_TRANSITION_TIME}. Was #{value.inspect}"
|
142
143
|
end
|
143
144
|
end
|
144
145
|
|
145
146
|
def xy=(value); set_xy(value) end
|
146
147
|
def set_xy(value)
|
147
148
|
if !value.nil? && (!value.is_a? Array)
|
148
|
-
raise BulbStateValueTypeException, "
|
149
|
+
raise BulbStateValueTypeException, "XY value has incorrect type. Requires array, got #{value.class}"
|
149
150
|
elsif value.nil?
|
150
151
|
return
|
151
152
|
elsif value.length == 2 && value[0].is_a?(Numeric) \
|
@@ -156,12 +157,12 @@ class BulbState
|
|
156
157
|
@xy[0] = value[0].to_f
|
157
158
|
@xy[1] = value[1].to_f
|
158
159
|
else
|
159
|
-
raise BulbStateValueOutOfRangeException, "
|
160
|
+
raise BulbStateValueOutOfRangeException, "XY value out of range. Must be [#{MIN_XY},#{MAX_XY}]. Was #{value.inspect}"
|
160
161
|
end
|
161
162
|
end
|
162
163
|
|
163
164
|
def data
|
164
|
-
data =
|
165
|
+
data = @data
|
165
166
|
data["on"] = @on if (@on!=nil)
|
166
167
|
data["bri"] = @bri if @bri
|
167
168
|
data["hue"] = @hue if @hue
|
@@ -176,7 +177,7 @@ class BulbState
|
|
176
177
|
data
|
177
178
|
end
|
178
179
|
|
179
|
-
def to_json
|
180
|
+
def to_json(options={})
|
180
181
|
data.to_json
|
181
182
|
end
|
182
183
|
end
|
data/lib/lights/command.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'lights/userlist'
|
2
|
+
|
3
|
+
class HueConfig
|
4
|
+
|
5
|
+
attr_reader :name, :swversion, :whitelist
|
6
|
+
|
7
|
+
def initialize(data = {})
|
8
|
+
@name = data["name"]
|
9
|
+
@swversion = data["swversion"]
|
10
|
+
@whitelist = UserList.new(data["whitelist"])
|
11
|
+
@data = data
|
12
|
+
end
|
13
|
+
|
14
|
+
def data
|
15
|
+
data = @data
|
16
|
+
data["name"] = @name if @name
|
17
|
+
data["swversion"] = @swversion if @swversion
|
18
|
+
data["whitelist"] = @whitelist.data if !@whitelist.data.empty?
|
19
|
+
data
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_json(options={})
|
23
|
+
data.to_json
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'lights/config'
|
2
|
+
require 'lights/bulblist'
|
3
|
+
require 'lights/grouplist'
|
4
|
+
require 'lights/scenelist'
|
5
|
+
require 'lights/rulelist'
|
6
|
+
require 'lights/schedulelist'
|
7
|
+
require 'lights/sensorlist'
|
8
|
+
|
9
|
+
class Datastore
|
10
|
+
|
11
|
+
attr_reader :lights, :groups, :config, :rules,
|
12
|
+
:scenes, :schedules, :sensors
|
13
|
+
def initialize(data = {})
|
14
|
+
@data = {}
|
15
|
+
@lights = BulbList.new(data["lights"])
|
16
|
+
@groups = GroupList.new(data["groups"])
|
17
|
+
@config = HueConfig.new(data["config"])
|
18
|
+
@schedules = ScheduleList.new(data["schedules"])
|
19
|
+
@scenes = SceneList.new(data["scenes"])
|
20
|
+
@rules = RuleList.new(data["rules"])
|
21
|
+
@sensors = SensorList.new(data["sensors"])
|
22
|
+
end
|
23
|
+
|
24
|
+
def all
|
25
|
+
@lights.bulbs + \
|
26
|
+
@groups.groups + \
|
27
|
+
[@config] + \
|
28
|
+
@schedules.schedules + \
|
29
|
+
@scenes.scenes + \
|
30
|
+
@rules.rules + \
|
31
|
+
@sensors.sensors
|
32
|
+
end
|
33
|
+
|
34
|
+
def data
|
35
|
+
data = @data
|
36
|
+
data["lights"] = @lights.data if !@lights.data.empty?
|
37
|
+
data["groups"] = @groups.data if !@groups.data.empty?
|
38
|
+
data["config"] = @config.data if !@config.data.empty?
|
39
|
+
data["schedules"] = @schedules.data if !@schedules.data.empty?
|
40
|
+
data["scenes"] = @scenes.data if !@scenes.data.empty?
|
41
|
+
data["rules"] = @rules.data if !@rules.data.empty?
|
42
|
+
data["sensors"] = @sensors.data if !@sensors.data.empty?
|
43
|
+
data
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_json(options={})
|
47
|
+
data.to_json
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
data/lib/lights/group.rb
CHANGED
@@ -16,15 +16,13 @@ class Group
|
|
16
16
|
|
17
17
|
def data
|
18
18
|
data = @data
|
19
|
-
data["id"] = @id if @id
|
20
19
|
data["name"] = @name if @name
|
21
20
|
data["lights"] = @lights if @lights
|
22
21
|
data["action"] = @action.data if @action.data != {}
|
23
22
|
data
|
24
23
|
end
|
25
24
|
|
26
|
-
def to_json
|
25
|
+
def to_json(options={})
|
27
26
|
data.to_json
|
28
27
|
end
|
29
|
-
|
30
28
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'lights/group'
|
2
|
+
|
3
|
+
class GroupList
|
4
|
+
|
5
|
+
attr_reader :groups
|
6
|
+
def initialize(data = {})
|
7
|
+
@groups = []
|
8
|
+
data.each{|id,value| @groups << Group.new(id,value)} if data
|
9
|
+
@data = data
|
10
|
+
end
|
11
|
+
|
12
|
+
def data
|
13
|
+
data = @data
|
14
|
+
@groups.each {|g| data[g.id] = g.data} if @groups
|
15
|
+
data
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_json(options={})
|
19
|
+
data.to_json
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
data/lib/lights/rule.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'lights/rule'
|
2
|
+
|
3
|
+
class RuleList
|
4
|
+
|
5
|
+
attr_reader :rules
|
6
|
+
def initialize(data = {})
|
7
|
+
@rules = []
|
8
|
+
data.each{|id,value| @rules << Rule.new(id,value)} if data
|
9
|
+
@data = data
|
10
|
+
end
|
11
|
+
|
12
|
+
def data
|
13
|
+
data = @data
|
14
|
+
@rules.each {|b| data[b.id] = b.data} if @rules
|
15
|
+
data
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_json(options={})
|
19
|
+
data.to_json
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
data/lib/lights/scene.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'lights/scene'
|
2
|
+
|
3
|
+
class SceneList
|
4
|
+
|
5
|
+
attr_reader :scenes
|
6
|
+
def initialize(data = {})
|
7
|
+
@scenes = []
|
8
|
+
data.each{|id,value| @scenes << Scene.new(id,value)} if data
|
9
|
+
@data = data
|
10
|
+
end
|
11
|
+
|
12
|
+
def data
|
13
|
+
data = @data
|
14
|
+
@scenes.each {|b| data[b.id] = b.data} if @scenes
|
15
|
+
data
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_json(options={})
|
19
|
+
data.to_json
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
data/lib/lights/schedule.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'lights/schedule'
|
2
|
+
|
3
|
+
class ScheduleList
|
4
|
+
|
5
|
+
attr_reader :schedules
|
6
|
+
def initialize(data = {})
|
7
|
+
@schedules = []
|
8
|
+
data.each{|id,value| @schedules << Schedule.new(id,value)} if data
|
9
|
+
@data = data
|
10
|
+
end
|
11
|
+
|
12
|
+
def data
|
13
|
+
data = @data
|
14
|
+
@schedules.each {|s| data[s.id] = s.data} if @schedules
|
15
|
+
data
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_json(options={})
|
19
|
+
data.to_json
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
data/lib/lights/sensor.rb
CHANGED
@@ -4,6 +4,16 @@ class SensorState
|
|
4
4
|
@data = data
|
5
5
|
@last_updated = data["lastupdated"]
|
6
6
|
end
|
7
|
+
|
8
|
+
def data
|
9
|
+
data = @data
|
10
|
+
data["lastupdated"] = @last_updated if @last_updated
|
11
|
+
data
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_json(options={})
|
15
|
+
data.to_json
|
16
|
+
end
|
7
17
|
end
|
8
18
|
|
9
19
|
class TapState < SensorState
|
@@ -12,6 +22,16 @@ class TapState < SensorState
|
|
12
22
|
@button_event = data["button_event"]
|
13
23
|
super
|
14
24
|
end
|
25
|
+
|
26
|
+
def data
|
27
|
+
data = @data
|
28
|
+
data["button_event"] = @button_event if @button_event
|
29
|
+
data
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_json(options={})
|
33
|
+
data.to_json
|
34
|
+
end
|
15
35
|
end
|
16
36
|
|
17
37
|
class Sensor
|
@@ -28,4 +48,20 @@ class Sensor
|
|
28
48
|
@state = SensorState.new(data["state"])
|
29
49
|
#@config = SensorConfig.new(data["config"])
|
30
50
|
end
|
51
|
+
|
52
|
+
def data
|
53
|
+
data = @data
|
54
|
+
data["name"] = @name if @name
|
55
|
+
data["type"] = @type if @type
|
56
|
+
data["modelid"] = @model_id if @model_id
|
57
|
+
data["manufacturername"] = @manufacturer_name if @manufacturer_name
|
58
|
+
data["uniqueid"] = @unique_id if @unique_id
|
59
|
+
data["swversion"] = @sw_version if @sw_version
|
60
|
+
data["state"] = @state.data if @state.data if !@state.data.empty?
|
61
|
+
data
|
62
|
+
end
|
63
|
+
|
64
|
+
def to_json(options={})
|
65
|
+
data.to_json
|
66
|
+
end
|
31
67
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'lights/sensor'
|
2
|
+
|
3
|
+
class SensorList
|
4
|
+
|
5
|
+
attr_reader :sensors
|
6
|
+
|
7
|
+
def initialize(data = {})
|
8
|
+
@sensors = []
|
9
|
+
data.each{|id,value| @sensors << Sensor.new(id,value)} if data
|
10
|
+
@data = data
|
11
|
+
end
|
12
|
+
|
13
|
+
def data
|
14
|
+
data = @data
|
15
|
+
@sensors.each {|s| data[s.id] = s.data} if @sensors
|
16
|
+
data
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_json(options={})
|
20
|
+
data.to_json
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
data/lib/lights/user.rb
CHANGED
@@ -8,4 +8,16 @@ class User
|
|
8
8
|
@create_date = data["create date"]
|
9
9
|
@last_use_date = data["last use date"]
|
10
10
|
end
|
11
|
+
|
12
|
+
def data
|
13
|
+
data = @data
|
14
|
+
data["name"] = @name if @name
|
15
|
+
data["create date"] = @create_date if @create_date
|
16
|
+
data["last use date"] = @last_use_date if @last_use_date
|
17
|
+
data
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_json(options={})
|
21
|
+
data.to_json
|
22
|
+
end
|
11
23
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'lights/user'
|
2
|
+
|
3
|
+
class UserList
|
4
|
+
|
5
|
+
attr_reader :users
|
6
|
+
def initialize(data = {})
|
7
|
+
@users = []
|
8
|
+
data.each{|id,value| @users << User.new(id,value)} if data
|
9
|
+
@data = data
|
10
|
+
end
|
11
|
+
|
12
|
+
def data
|
13
|
+
data = @data
|
14
|
+
@users.each {|u| data[u.id] = u.data} if @users
|
15
|
+
data
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_json(options={})
|
19
|
+
data.to_json
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
data/lib/lights/version.rb
CHANGED
data/lights.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
|
22
|
-
s.add_runtime_dependency "simpletable", "~> 0.3.
|
22
|
+
s.add_runtime_dependency "simpletable", "~> 0.3.1"
|
23
23
|
|
24
24
|
s.add_development_dependency "bundler", "~> 1.3"
|
25
25
|
s.add_development_dependency "rake"
|
@@ -0,0 +1,515 @@
|
|
1
|
+
require 'lights'
|
2
|
+
|
3
|
+
describe Datastore do
|
4
|
+
it "properly reconstructs sub objects" do
|
5
|
+
data = JSON.parse(DATASTORE_JSON)
|
6
|
+
ds = Datastore.new data
|
7
|
+
ds.lights.data.should eql data["lights"]
|
8
|
+
ds.groups.data.should eql data["groups"]
|
9
|
+
ds.rules.data.should eql data["rules"]
|
10
|
+
ds.scenes.data.should eql data["scenes"]
|
11
|
+
ds.schedules.data.should eql data["schedules"]
|
12
|
+
ds.sensors.data.should eql data["sensors"]
|
13
|
+
ds.data.should eql data
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
DATASTORE_JSON = %Q{
|
18
|
+
{
|
19
|
+
"lights": {
|
20
|
+
"1": {
|
21
|
+
"state": {
|
22
|
+
"on": true,
|
23
|
+
"bri": 254,
|
24
|
+
"hue": 34495,
|
25
|
+
"sat": 232,
|
26
|
+
"effect": "none",
|
27
|
+
"xy": [
|
28
|
+
0.3151,
|
29
|
+
0.3251
|
30
|
+
],
|
31
|
+
"ct": 155,
|
32
|
+
"alert": "none",
|
33
|
+
"colormode": "xy",
|
34
|
+
"reachable": true
|
35
|
+
},
|
36
|
+
"type": "Extended color light",
|
37
|
+
"name": "Hue Lamp 1",
|
38
|
+
"modelid": "LCT001",
|
39
|
+
"uniqueid": "00:17:88:01:00:aa:bb:cb-0b",
|
40
|
+
"swversion": "66013452",
|
41
|
+
"pointsymbol": {
|
42
|
+
"1": "0a00f1f01f1f1001f1ff100000000001f2000000",
|
43
|
+
"2": "none",
|
44
|
+
"3": "none",
|
45
|
+
"4": "none",
|
46
|
+
"5": "none",
|
47
|
+
"6": "none",
|
48
|
+
"7": "none",
|
49
|
+
"8": "none"
|
50
|
+
}
|
51
|
+
},
|
52
|
+
"2": {
|
53
|
+
"state": {
|
54
|
+
"on": true,
|
55
|
+
"bri": 254,
|
56
|
+
"hue": 34495,
|
57
|
+
"sat": 232,
|
58
|
+
"effect": "none",
|
59
|
+
"xy": [
|
60
|
+
0.3151,
|
61
|
+
0.3251
|
62
|
+
],
|
63
|
+
"ct": 155,
|
64
|
+
"alert": "none",
|
65
|
+
"colormode": "xy",
|
66
|
+
"reachable": true
|
67
|
+
},
|
68
|
+
"type": "Extended color light",
|
69
|
+
"name": "Hue Lamp 2",
|
70
|
+
"modelid": "LCT001",
|
71
|
+
"uniqueid": "00:17:88:01:00:aa:bb:ca-0b",
|
72
|
+
"swversion": "66013452",
|
73
|
+
"pointsymbol": {
|
74
|
+
"1": "0a00f1f01f1f1001f1ff100000000001f2000000",
|
75
|
+
"2": "none",
|
76
|
+
"3": "none",
|
77
|
+
"4": "none",
|
78
|
+
"5": "none",
|
79
|
+
"6": "none",
|
80
|
+
"7": "none",
|
81
|
+
"8": "none"
|
82
|
+
}
|
83
|
+
},
|
84
|
+
"3": {
|
85
|
+
"state": {
|
86
|
+
"on": true,
|
87
|
+
"bri": 254,
|
88
|
+
"hue": 34495,
|
89
|
+
"sat": 232,
|
90
|
+
"effect": "none",
|
91
|
+
"xy": [
|
92
|
+
0.3151,
|
93
|
+
0.3251
|
94
|
+
],
|
95
|
+
"ct": 155,
|
96
|
+
"alert": "none",
|
97
|
+
"colormode": "xy",
|
98
|
+
"reachable": true
|
99
|
+
},
|
100
|
+
"type": "Extended color light",
|
101
|
+
"name": "Hue Lamp 3",
|
102
|
+
"modelid": "LCT001",
|
103
|
+
"uniqueid": "00:17:88:01:00:aa:bb:c9-0b",
|
104
|
+
"swversion": "66013452",
|
105
|
+
"pointsymbol": {
|
106
|
+
"1": "0a00f1f01f1f1001f1ff100000000001f2000000",
|
107
|
+
"2": "none",
|
108
|
+
"3": "none",
|
109
|
+
"4": "none",
|
110
|
+
"5": "none",
|
111
|
+
"6": "none",
|
112
|
+
"7": "none",
|
113
|
+
"8": "none"
|
114
|
+
}
|
115
|
+
},
|
116
|
+
"4": {
|
117
|
+
"state": {
|
118
|
+
"on": true,
|
119
|
+
"bri": 254,
|
120
|
+
"hue": 34495,
|
121
|
+
"sat": 232,
|
122
|
+
"effect": "none",
|
123
|
+
"xy": [
|
124
|
+
0.3151,
|
125
|
+
0.3251
|
126
|
+
],
|
127
|
+
"ct": 155,
|
128
|
+
"alert": "none",
|
129
|
+
"colormode": "xy",
|
130
|
+
"reachable": true
|
131
|
+
},
|
132
|
+
"type": "Extended color light",
|
133
|
+
"name": "Hue Lamp 4",
|
134
|
+
"modelid": "LCT001",
|
135
|
+
"uniqueid": "00:17:88:01:00:aa:bb:c8-0b",
|
136
|
+
"swversion": "66013452",
|
137
|
+
"pointsymbol": {
|
138
|
+
"1": "none",
|
139
|
+
"2": "none",
|
140
|
+
"3": "none",
|
141
|
+
"4": "none",
|
142
|
+
"5": "none",
|
143
|
+
"6": "none",
|
144
|
+
"7": "none",
|
145
|
+
"8": "none"
|
146
|
+
}
|
147
|
+
},
|
148
|
+
"5": {
|
149
|
+
"state": {
|
150
|
+
"on": true,
|
151
|
+
"bri": 254,
|
152
|
+
"hue": 34495,
|
153
|
+
"sat": 232,
|
154
|
+
"effect": "none",
|
155
|
+
"xy": [
|
156
|
+
0.3151,
|
157
|
+
0.3251
|
158
|
+
],
|
159
|
+
"ct": 155,
|
160
|
+
"alert": "select",
|
161
|
+
"colormode": "xy",
|
162
|
+
"reachable": true
|
163
|
+
},
|
164
|
+
"type": "Extended color light",
|
165
|
+
"name": "BT Lamp",
|
166
|
+
"modelid": "LCT001",
|
167
|
+
"uniqueid": "00:17:88:01:00:aa:bb:c7-0b",
|
168
|
+
"swversion": "66013452",
|
169
|
+
"pointsymbol": {
|
170
|
+
"1": "none",
|
171
|
+
"2": "none",
|
172
|
+
"3": "none",
|
173
|
+
"4": "none",
|
174
|
+
"5": "none",
|
175
|
+
"6": "none",
|
176
|
+
"7": "none",
|
177
|
+
"8": "none"
|
178
|
+
}
|
179
|
+
}
|
180
|
+
},
|
181
|
+
"groups": {
|
182
|
+
"1": {
|
183
|
+
"name": "Ceiling light",
|
184
|
+
"lights": [
|
185
|
+
"1",
|
186
|
+
"2",
|
187
|
+
"3",
|
188
|
+
"4"
|
189
|
+
],
|
190
|
+
"type": "LightGroup",
|
191
|
+
"action": {
|
192
|
+
"on": true,
|
193
|
+
"bri": 254,
|
194
|
+
"hue": 34495,
|
195
|
+
"sat": 232,
|
196
|
+
"effect": "none",
|
197
|
+
"xy": [
|
198
|
+
0.3151,
|
199
|
+
0.3251
|
200
|
+
],
|
201
|
+
"ct": 155,
|
202
|
+
"colormode": "xy"
|
203
|
+
}
|
204
|
+
},
|
205
|
+
"2": {
|
206
|
+
"name": "Lamp",
|
207
|
+
"lights": [
|
208
|
+
"5"
|
209
|
+
],
|
210
|
+
"type": "LightGroup",
|
211
|
+
"action": {
|
212
|
+
"on": true,
|
213
|
+
"bri": 254,
|
214
|
+
"hue": 34495,
|
215
|
+
"sat": 232,
|
216
|
+
"effect": "none",
|
217
|
+
"xy": [
|
218
|
+
0.3151,
|
219
|
+
0.3251
|
220
|
+
],
|
221
|
+
"ct": 155,
|
222
|
+
"colormode": "xy"
|
223
|
+
}
|
224
|
+
}
|
225
|
+
},
|
226
|
+
"config": {
|
227
|
+
"name": "Philips hue",
|
228
|
+
"zigbeechannel": 25,
|
229
|
+
"mac": "00:11:22:33:44:55",
|
230
|
+
"dhcp": true,
|
231
|
+
"ipaddress": "192.168.1.27",
|
232
|
+
"netmask": "255.255.255.0",
|
233
|
+
"gateway": "192.168.1.1",
|
234
|
+
"proxyaddress": "none",
|
235
|
+
"proxyport": 0,
|
236
|
+
"UTC": "2015-01-01T00:11:24",
|
237
|
+
"localtime": "2014-12-31T19:11:24",
|
238
|
+
"timezone": "America/New_York",
|
239
|
+
"whitelist": {
|
240
|
+
"testuser1": {
|
241
|
+
"last use date": "2015-01-01T00:11:24",
|
242
|
+
"create date": "2014-12-30T20:05:07",
|
243
|
+
"name": "lights"
|
244
|
+
},
|
245
|
+
"test user 2": {
|
246
|
+
"last use date": "2014-05-26T14:20:54",
|
247
|
+
"create date": "2013-08-03T17:05:51",
|
248
|
+
"name": "unofficial hue app for osx"
|
249
|
+
},
|
250
|
+
"test user 3": {
|
251
|
+
"last use date": "2014-12-31T02:19:57",
|
252
|
+
"create date": "2013-08-03T18:48:19",
|
253
|
+
"name": "test user"
|
254
|
+
}
|
255
|
+
},
|
256
|
+
"swversion": "01018228",
|
257
|
+
"apiversion": "1.5.0",
|
258
|
+
"swupdate": {
|
259
|
+
"updatestate": 0,
|
260
|
+
"checkforupdate": false,
|
261
|
+
"devicetypes": {
|
262
|
+
"bridge": false,
|
263
|
+
"lights": [
|
264
|
+
|
265
|
+
]
|
266
|
+
},
|
267
|
+
"url": "",
|
268
|
+
"text": "",
|
269
|
+
"notify": false
|
270
|
+
},
|
271
|
+
"linkbutton": false,
|
272
|
+
"portalservices": true,
|
273
|
+
"portalconnection": "connected",
|
274
|
+
"portalstate": {
|
275
|
+
"signedon": true,
|
276
|
+
"incoming": true,
|
277
|
+
"outgoing": true,
|
278
|
+
"communication": "disconnected"
|
279
|
+
}
|
280
|
+
},
|
281
|
+
"schedules": {
|
282
|
+
"6033895564917352": {
|
283
|
+
"name": "Alarm",
|
284
|
+
"description": "Energize",
|
285
|
+
"command": {
|
286
|
+
"address": "/api/8Wc85V5IrG0XTHfB/groups/0/action",
|
287
|
+
"body": {
|
288
|
+
"scene": "d942060b6-on-5"
|
289
|
+
},
|
290
|
+
"method": "PUT"
|
291
|
+
},
|
292
|
+
"localtime": "W124/T06:40:00",
|
293
|
+
"time": "W124/T11:40:00",
|
294
|
+
"created": "2014-09-18T02:54:16",
|
295
|
+
"status": "disabled"
|
296
|
+
},
|
297
|
+
"0326522980291031": {
|
298
|
+
"name": "Alarm",
|
299
|
+
"description": "",
|
300
|
+
"command": {
|
301
|
+
"address": "/api/8Wc85V5IrG0XTHfB/groups/0/action",
|
302
|
+
"body": {
|
303
|
+
"scene": "19a493ad2-off-0"
|
304
|
+
},
|
305
|
+
"method": "PUT"
|
306
|
+
},
|
307
|
+
"localtime": "W124/T07:45:00",
|
308
|
+
"time": "W124/T12:45:00",
|
309
|
+
"created": "2014-09-09T01:13:57",
|
310
|
+
"status": "enabled"
|
311
|
+
}
|
312
|
+
},
|
313
|
+
"scenes": {
|
314
|
+
"fd0ceaedb-on-0": {
|
315
|
+
"name": "Purple and Green",
|
316
|
+
"lights": [
|
317
|
+
"1",
|
318
|
+
"2",
|
319
|
+
"3",
|
320
|
+
"4",
|
321
|
+
"5"
|
322
|
+
],
|
323
|
+
"active": true
|
324
|
+
},
|
325
|
+
"da01b1eaf-on-0": {
|
326
|
+
"name": "Purple on 0",
|
327
|
+
"lights": [
|
328
|
+
"1",
|
329
|
+
"2",
|
330
|
+
"3",
|
331
|
+
"4",
|
332
|
+
"5"
|
333
|
+
],
|
334
|
+
"active": true
|
335
|
+
},
|
336
|
+
"182a404bb-on-0": {
|
337
|
+
"name": "Deck flower on 0",
|
338
|
+
"lights": [
|
339
|
+
"1",
|
340
|
+
"2",
|
341
|
+
"3",
|
342
|
+
"4",
|
343
|
+
"5"
|
344
|
+
],
|
345
|
+
"active": true
|
346
|
+
},
|
347
|
+
"8fc639a85f-on-0": {
|
348
|
+
"name": "Reading on 0",
|
349
|
+
"lights": [
|
350
|
+
"5"
|
351
|
+
],
|
352
|
+
"active": true
|
353
|
+
},
|
354
|
+
"fedd8e5db-on-0": {
|
355
|
+
"name": "Dark red on 0",
|
356
|
+
"lights": [
|
357
|
+
"1",
|
358
|
+
"2",
|
359
|
+
"3",
|
360
|
+
"4",
|
361
|
+
"5"
|
362
|
+
],
|
363
|
+
"active": true
|
364
|
+
}
|
365
|
+
},
|
366
|
+
"rules": {
|
367
|
+
"1": {
|
368
|
+
"name": "Tap 2.3 Reading",
|
369
|
+
"owner": "8Wc85V5IrG0XTHfB",
|
370
|
+
"created": "2014-09-17T23:34:25",
|
371
|
+
"lasttriggered": "2014-12-31T03:29:37",
|
372
|
+
"timestriggered": 10,
|
373
|
+
"status": "enabled",
|
374
|
+
"conditions": [
|
375
|
+
{
|
376
|
+
"address": "/sensors/2/state/buttonevent",
|
377
|
+
"operator": "eq",
|
378
|
+
"value": "17"
|
379
|
+
},
|
380
|
+
{
|
381
|
+
"address": "/sensors/2/state/lastupdated",
|
382
|
+
"operator": "dx"
|
383
|
+
}
|
384
|
+
],
|
385
|
+
"actions": [
|
386
|
+
{
|
387
|
+
"address": "/groups/0/action",
|
388
|
+
"method": "PUT",
|
389
|
+
"body": {
|
390
|
+
"scene": "dc8a6e2b5-on-0"
|
391
|
+
}
|
392
|
+
}
|
393
|
+
]
|
394
|
+
},
|
395
|
+
"2": {
|
396
|
+
"name": "Tap 2.1 All lights off",
|
397
|
+
"owner": "8Wc85V5IrG0XTHfB",
|
398
|
+
"created": "2014-07-16T20:43:43",
|
399
|
+
"lasttriggered": "2014-12-31T06:29:46",
|
400
|
+
"timestriggered": 12,
|
401
|
+
"status": "enabled",
|
402
|
+
"conditions": [
|
403
|
+
{
|
404
|
+
"address": "/sensors/2/state/buttonevent",
|
405
|
+
"operator": "eq",
|
406
|
+
"value": "34"
|
407
|
+
},
|
408
|
+
{
|
409
|
+
"address": "/sensors/2/state/lastupdated",
|
410
|
+
"operator": "dx"
|
411
|
+
}
|
412
|
+
],
|
413
|
+
"actions": [
|
414
|
+
{
|
415
|
+
"address": "/groups/0/action",
|
416
|
+
"method": "PUT",
|
417
|
+
"body": {
|
418
|
+
"scene": "19a493ad2-off-0"
|
419
|
+
}
|
420
|
+
}
|
421
|
+
]
|
422
|
+
},
|
423
|
+
"3": {
|
424
|
+
"name": "Tap 2.4 Purple",
|
425
|
+
"owner": "8Wc85V5IrG0XTHfB",
|
426
|
+
"created": "2014-07-19T16:32:31",
|
427
|
+
"lasttriggered": "none",
|
428
|
+
"timestriggered": 0,
|
429
|
+
"status": "enabled",
|
430
|
+
"conditions": [
|
431
|
+
{
|
432
|
+
"address": "/sensors/2/state/buttonevent",
|
433
|
+
"operator": "eq",
|
434
|
+
"value": "18"
|
435
|
+
},
|
436
|
+
{
|
437
|
+
"address": "/sensors/2/state/lastupdated",
|
438
|
+
"operator": "dx"
|
439
|
+
}
|
440
|
+
],
|
441
|
+
"actions": [
|
442
|
+
{
|
443
|
+
"address": "/groups/0/action",
|
444
|
+
"method": "PUT",
|
445
|
+
"body": {
|
446
|
+
"scene": "da01b1eaf-on-0"
|
447
|
+
}
|
448
|
+
}
|
449
|
+
]
|
450
|
+
},
|
451
|
+
"4": {
|
452
|
+
"name": "Tap 2.2 Energize",
|
453
|
+
"owner": "8Wc85V5IrG0XTHfB",
|
454
|
+
"created": "2014-07-16T20:43:43",
|
455
|
+
"lasttriggered": "2014-12-31T21:42:04",
|
456
|
+
"timestriggered": 9,
|
457
|
+
"status": "enabled",
|
458
|
+
"conditions": [
|
459
|
+
{
|
460
|
+
"address": "/sensors/2/state/buttonevent",
|
461
|
+
"operator": "eq",
|
462
|
+
"value": "16"
|
463
|
+
},
|
464
|
+
{
|
465
|
+
"address": "/sensors/2/state/lastupdated",
|
466
|
+
"operator": "dx"
|
467
|
+
}
|
468
|
+
],
|
469
|
+
"actions": [
|
470
|
+
{
|
471
|
+
"address": "/groups/0/action",
|
472
|
+
"method": "PUT",
|
473
|
+
"body": {
|
474
|
+
"scene": "d942060b6-on-0"
|
475
|
+
}
|
476
|
+
}
|
477
|
+
]
|
478
|
+
}
|
479
|
+
},
|
480
|
+
"sensors": {
|
481
|
+
"1": {
|
482
|
+
"state": {
|
483
|
+
"daylight": false,
|
484
|
+
"lastupdated": "none"
|
485
|
+
},
|
486
|
+
"config": {
|
487
|
+
"on": true,
|
488
|
+
"long": "none",
|
489
|
+
"lat": "none",
|
490
|
+
"sunriseoffset": 30,
|
491
|
+
"sunsetoffset": -30
|
492
|
+
},
|
493
|
+
"name": "Daylight",
|
494
|
+
"type": "Daylight",
|
495
|
+
"modelid": "PHDL00",
|
496
|
+
"manufacturername": "Philips",
|
497
|
+
"swversion": "1.0"
|
498
|
+
},
|
499
|
+
"2": {
|
500
|
+
"state": {
|
501
|
+
"buttonevent": 16,
|
502
|
+
"lastupdated": "2014-12-31T21:42:04"
|
503
|
+
},
|
504
|
+
"config": {
|
505
|
+
"on": true
|
506
|
+
},
|
507
|
+
"name": "Hue Tap 1",
|
508
|
+
"type": "ZGPSwitch",
|
509
|
+
"modelid": "ZGPSWITCH",
|
510
|
+
"manufacturername": "Philips",
|
511
|
+
"uniqueid": "00:00:00:00:00:aa:bb:cc-f2"
|
512
|
+
}
|
513
|
+
}
|
514
|
+
}
|
515
|
+
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lights
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brady Turner
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.3.
|
19
|
+
version: 0.3.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.3.
|
26
|
+
version: 0.3.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -110,21 +110,31 @@ files:
|
|
110
110
|
- lib/lights.rb
|
111
111
|
- lib/lights/bridge.rb
|
112
112
|
- lib/lights/bulb.rb
|
113
|
+
- lib/lights/bulblist.rb
|
113
114
|
- lib/lights/bulbstate.rb
|
114
115
|
- lib/lights/command.rb
|
116
|
+
- lib/lights/config.rb
|
117
|
+
- lib/lights/datastore.rb
|
115
118
|
- lib/lights/exception.rb
|
116
119
|
- lib/lights/group.rb
|
120
|
+
- lib/lights/grouplist.rb
|
117
121
|
- lib/lights/loggerconfig.rb
|
118
122
|
- lib/lights/rule.rb
|
123
|
+
- lib/lights/rulelist.rb
|
119
124
|
- lib/lights/scene.rb
|
125
|
+
- lib/lights/scenelist.rb
|
120
126
|
- lib/lights/schedule.rb
|
127
|
+
- lib/lights/schedulelist.rb
|
121
128
|
- lib/lights/sensor.rb
|
129
|
+
- lib/lights/sensorlist.rb
|
122
130
|
- lib/lights/user.rb
|
131
|
+
- lib/lights/userlist.rb
|
123
132
|
- lib/lights/version.rb
|
124
133
|
- lights.gemspec
|
125
134
|
- spec/bridge_spec.rb
|
126
135
|
- spec/bulb_spec.rb
|
127
136
|
- spec/bulbstate_spec.rb
|
137
|
+
- spec/datastore_spec.rb
|
128
138
|
- spec/features/lights.feature
|
129
139
|
- spec/features/support/setup.rb
|
130
140
|
- spec/group_spec.rb
|
@@ -158,6 +168,7 @@ test_files:
|
|
158
168
|
- spec/bridge_spec.rb
|
159
169
|
- spec/bulb_spec.rb
|
160
170
|
- spec/bulbstate_spec.rb
|
171
|
+
- spec/datastore_spec.rb
|
161
172
|
- spec/features/lights.feature
|
162
173
|
- spec/features/support/setup.rb
|
163
174
|
- spec/group_spec.rb
|