lights 0.8.18 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MTUwNmZjMWQ4MzMyMjA2ODU1ZmJhMTVmNGY5ODJiNWFjZTU5ZjgyMQ==
5
- data.tar.gz: !binary |-
6
- MGQxNTExYWM5NjI1MzRlMzZlOGI1OTVlNjM2Y2YyNjlmOTEwMTFhMA==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- ZDg4MGE0MmIwNjdhNzljZmFjNmI2YWQ3ZTAyNTRkZDExYzg4MTZkZmY4N2Fi
10
- Y2ZlYWQ1Yjk4NmYzZDFiM2NlOGQzNDQ5MDgzYzE2NmM3OTE4MzAxMDQwZmZl
11
- N2I1N2M5NjA1YWY2MWM2MzQ0ZDFlNjFmNzM0MWNmZDhlMTY2ZTc=
12
- data.tar.gz: !binary |-
13
- Y2Q2OWVkMDI3ODAzMjI5NjUwYTI3MjU2YjY0MjY0NTE5YzEzNWE0MmZhODBj
14
- NDcwODRhYTc2MDQ3OWI3YzM4MWQ3ZTkyY2Q3ZDE1Y2ViODhiYjU2ZGM4MmQx
15
- OGE5NWU5N2Q2ZTFiNzE2MDNjNDAyMjgxYjljODUxMmQzMGNmNDA=
2
+ SHA256:
3
+ metadata.gz: a3bf9fc0031f505e57aeff2a521fa844f66da4d2d8f58cd72274bbe99ab16157
4
+ data.tar.gz: fd88ad10da1cdd5a82d7385e7e8eff031d13f2665ddc7db71e1f846ffb32dfa1
5
+ SHA512:
6
+ metadata.gz: f651502f6f3b129085fb3973acdff5f96bc7fe6a789148dc93c1412733c53756547586f433a9aa913eb459e1c8ead64549074106aec944f2b92edb6339e4631f
7
+ data.tar.gz: 8b732115636f705f482f1d6cd14f0af1c63fb0b6b88f0bcbec90ee9de2d30c143a965eddd0b786e9011fbf07e1933abe8d8c03f38470f950d58c9fe890c1faca
data/README.md CHANGED
@@ -16,7 +16,7 @@ Basic Usage
16
16
  ```ruby
17
17
  require 'lights'
18
18
  client = Lights.new( '192.168.x.x', 'username' )
19
- client.register_username
19
+ client.register
20
20
  client.request_bulb_list
21
21
  ```
22
22
  See [lights-examples](https://github.com/turnerba/lights-examples) for more usage examples.
@@ -26,11 +26,10 @@ CLI Quick Setup
26
26
 
27
27
  ```
28
28
  lights discover -s
29
- lights config -f --user <username>
30
29
  lights register
31
30
  lights list
32
- lights on -l all
33
- lights off -l all
31
+ lights on
32
+ lights off
34
33
  ```
35
34
 
36
35
  See [Sample Usage (Implemented)](https://github.com/turnerba/lights/wiki/Sample-Usage-(Implemented)) for more usage examples.
data/bin/lights CHANGED
@@ -18,18 +18,22 @@ class LightsCli
18
18
  def configured?
19
19
  @config["username"] && @config["bridge_ip"]
20
20
  end
21
+
22
+ def ip_configured?
23
+ @config["bridge_ip"]
24
+ end
21
25
 
22
26
  def config
23
27
  options = {}
24
28
  OptionParser.new do |opts|
25
- opts.on("-u", "--user <username>", String, "Username"){|url| options[:user]=url}
26
29
  opts.on("-i", "--ip <bridge ip>", String, "Bridge ip address"){|ip| options[:ip]=ip}
27
30
  opts.on("-f", "--force", "Force write to config file"){|f| options[:force]=f}
28
31
  opts.on("-l", "--list", "List saved configuration settings") {|l| options[:list]=l}
29
32
  end.parse!
30
33
 
31
- if !options[:user] && !options[:ip] && !options[:list]
32
- puts "Must specify username and/or bridge IP: --user <username> --ip <IP addr. of bridge>"
34
+ unless options[:ip] || options[:list]
35
+ puts "usage:"
36
+ puts " #{File.basename(__FILE__)} config (--ip <bridge IP> | --list)"
33
37
  exit 1
34
38
  end
35
39
 
@@ -52,7 +56,6 @@ class LightsCli
52
56
  end
53
57
  end
54
58
 
55
- @config["username"] = options[:user] || @config["username"]
56
59
  @config["bridge_ip"] = options[:ip] || @config["bridge_ip"]
57
60
 
58
61
  write_config
@@ -70,7 +73,8 @@ class LightsCli
70
73
  OptionParser.new do |opts|
71
74
  opts.on("-l", "--lights 1,2,...N", Array, "Which lights are in the scene"){|l| options[:lights]=l}
72
75
  opts.on("-n", "--name <name>", String, "Set scene name"){|n| options[:name]=n}
73
- opts.on("-i", "--id <id>", String, "Set scene ID"){|i| options[:id]=i}
76
+ opts.on("-r", "--recycle", "Can bridge recycle scene"){|r| options[:recycle]=r}
77
+ opts.on("-d", "--duration seconds", OptionParser::DecimalInteger, "Transition duration in seconds"){|d| options[:duration]=d}
74
78
  end.parse!
75
79
 
76
80
  if !options[:lights]
@@ -81,14 +85,12 @@ class LightsCli
81
85
  puts "Must specify scene name."
82
86
  exit 1
83
87
  end
84
- if !options[:id]
85
- puts "Must specify scene id."
86
- exit 1
87
- end
88
88
 
89
- s = Scene.new options[:id]
89
+ s = Scene.new
90
90
  s.name = options[:name]
91
91
  s.lights = options[:lights]
92
+ s.recycle = options[:recycle] || false
93
+ s.transition_time = options[:duration]
92
94
  hue.create_scene s
93
95
  when "group"
94
96
  OptionParser.new do |opts|
@@ -189,7 +191,14 @@ class LightsCli
189
191
 
190
192
  hue.delete_user id
191
193
  when "scene"
192
- STDERR.puts "Cannot delete scenes."
194
+ id = ARGV.shift
195
+
196
+ if !id
197
+ puts "Must specify scene id."
198
+ exit 1
199
+ end
200
+
201
+ hue.delete_scene id
193
202
  when nil
194
203
  STDERR.puts "Must specify a type to delete."
195
204
  else
@@ -213,8 +222,8 @@ class LightsCli
213
222
  when nil, "","lights"
214
223
  response = options[:new] ? hue.request_new_bulb_list : hue.request_bulb_list
215
224
  objects = BulbList.new(response)
216
- titles = ["ID","NAME"]
217
- methods = [:id,:name]
225
+ titles = ["ID","NAME","REACHABLE?"]
226
+ methods = [:id,:name,[:state,:reachable]]
218
227
  when "sensors"
219
228
  response = options[:new] ? hue.request_new_sensor_list : hue.request_sensor_list
220
229
  objects = SensorList.new(response)
@@ -228,8 +237,8 @@ class LightsCli
228
237
  when "scenes"
229
238
  response = hue.request_scene_list
230
239
  objects = SceneList.new(response)
231
- titles = ["ID","NAME","LIGHTS"]
232
- methods = [:id,:name,:lights]
240
+ titles = ["ID","NAME","LIGHTS","RECYCLE"]
241
+ methods = [:id,:name,:lights,:recycle]
233
242
  when "users"
234
243
  response = hue.request_config
235
244
  objects = UserList.new(response["whitelist"])
@@ -263,7 +272,9 @@ class LightsCli
263
272
 
264
273
  def register
265
274
  lights = Lights.new @config["bridge_ip"], @config["username"]
266
- response = lights.register_username
275
+ response = lights.register
276
+ @config["username"] = lights.username
277
+ write_config
267
278
  end
268
279
 
269
280
  def discover
@@ -447,12 +458,14 @@ begin
447
458
  cli.config
448
459
  elsif command == "discover"
449
460
  cli.discover
461
+ elsif !cli.ip_configured?
462
+ puts "Please run 'lights discover -s' or 'lights config --ip <IP>' before using."
463
+ elsif command == "register"
464
+ cli.register
450
465
  elsif !cli.configured?
451
- puts "Please run 'lights config' before using."
466
+ puts "Please run 'lights register' before using."
452
467
  elsif command == "list"
453
468
  cli.list
454
- elsif command == "register"
455
- cli.register
456
469
  elsif command == "on"
457
470
  cli.on
458
471
  elsif command == "off"
@@ -12,8 +12,8 @@ require 'lights/loggerconfig'
12
12
 
13
13
  class Lights
14
14
 
15
- attr_reader :bulbs
16
- def initialize(ip,username)
15
+ attr_reader :bulbs, :username
16
+ def initialize(ip,username=nil)
17
17
  @ip = ip
18
18
  @username = username
19
19
  @http = Net::HTTP.new(ip,80)
@@ -25,9 +25,9 @@ class Lights
25
25
  end
26
26
 
27
27
  def discover_hubs
28
- http = Net::HTTP.new("www.meethue.com",443)
28
+ http = Net::HTTP.new("discovery.meethue.com",443)
29
29
  http.use_ssl = true
30
- request = Net::HTTP::Get.new( "/api/nupnp" )
30
+ request = Net::HTTP::Get.new( "/" )
31
31
  response = http.request request
32
32
 
33
33
  case response.code.to_i
@@ -35,21 +35,28 @@ class Lights
35
35
  result = JSON.parse( response.body )
36
36
  result.each { |b| @bridges << Bridge.new(b) }
37
37
  else
38
+ @logger.fatal "Could not discover bridge. HTTP error #{response.code}"
39
+ @logger.fatal "Response: #{response.body}"
38
40
  raise "Unknown error"
39
41
  end
40
42
  @bridges
41
43
  end
42
44
 
43
- def register_username
44
- data = { "devicetype"=>"lights",
45
- "username"=>@username }
45
+ def register
46
+ data = { "devicetype"=>"lights" }
46
47
  response = @http.post "/api", data.to_json
47
48
  result = JSON.parse(response.body).first
48
49
  if result.has_key? "error"
49
50
  process_error result
51
+ elsif result["success"]
52
+ @username = result["success"]["username"]
50
53
  end
54
+ result
51
55
  end
52
56
 
57
+ # backwards compatibility
58
+ alias_method :register_username, :register
59
+
53
60
  def request_config
54
61
  get "config"
55
62
  end
@@ -134,7 +141,11 @@ class Lights
134
141
  end
135
142
 
136
143
  def create_scene( scene )
137
- put "scenes/#{scene.id}", scene
144
+ post "scenes/#{scene.id}", scene
145
+ end
146
+
147
+ def delete_scene( id )
148
+ delete "scenes/#{id}"
138
149
  end
139
150
 
140
151
  def delete_group( id )
@@ -165,6 +176,8 @@ private
165
176
  raise ParameterUnavailableException, result["error"]["description"]
166
177
  when 101
167
178
  raise BridgeConnectException
179
+ when 403
180
+ raise SceneLockedException, result["error"]["description"]
168
181
  else
169
182
  raise "Unknown Error: #{result["error"]["description"]}"
170
183
  end
@@ -172,6 +185,7 @@ private
172
185
 
173
186
  def get( path )
174
187
  @logger.debug "==> GET: #{path}"
188
+ raise UsernameException unless @username
175
189
  request = Net::HTTP::Get.new( "/api/#{@username}/#{path}" )
176
190
  response = @http.request request
177
191
  result = JSON.parse( response.body )
@@ -185,6 +199,7 @@ private
185
199
 
186
200
  def put( path, data={} )
187
201
  @logger.debug "==> PUT: #{path}"
202
+ raise UsernameException unless @username
188
203
  @logger.debug data.to_json
189
204
  response = @http.put( "/api/#{@username}/#{path}", data.to_json )
190
205
  result = JSON.parse( response.body )
@@ -198,6 +213,7 @@ private
198
213
 
199
214
  def post( path, data={} )
200
215
  @logger.debug "==> POST: #{path}"
216
+ raise UsernameException unless @username
201
217
  @logger.debug data.to_json
202
218
  response = @http.post( "/api/#{@username}/#{path}", data.to_json )
203
219
  result = JSON.parse( response.body )
@@ -211,6 +227,7 @@ private
211
227
 
212
228
  def delete( path )
213
229
  @logger.debug "==> DELETE: #{path}"
230
+ raise UsernameException unless @username
214
231
  request = Net::HTTP::Delete.new( "/api/#{@username}/#{path}" )
215
232
  response = @http.request request
216
233
  result = JSON.parse( response.body )
@@ -4,7 +4,6 @@ class Bridge < HObject
4
4
 
5
5
  attr_reader :id, :ip, :name, :mac
6
6
  def initialize(data = {})
7
- super
8
7
  @id = data["id"]
9
8
  @ip = data["internalipaddress"]
10
9
  @mac = data["macaddress"]
@@ -2,22 +2,29 @@ require 'lights/bulbstate'
2
2
  require 'lights/hobject'
3
3
 
4
4
  class Bulb < HObject
5
- attr_reader :id, :name, :type, :swversion, :state
5
+ attr_reader :id, :name, :type, :sw_version, :state,
6
+ :point_symbol, :model_id, :unique_id
7
+ attr_writer :name, :state
6
8
  def initialize(id,data = {})
7
- super(data)
8
9
  @id = id
9
10
  @name = data["name"]
10
11
  @type = data["type"]
11
- @swversion = data["swversion"]
12
+ @sw_version = data["swversion"]
13
+ @point_symbol = data["pointsymbol"]
14
+ @model_id = data["modelid"]
15
+ @unique_id = data["uniqueid"]
12
16
  @state = BulbState.new data["state"]
13
17
  end
14
18
 
15
19
  def data
16
- data = @data
20
+ data = {}
17
21
  data["name"] = @name if @name
18
22
  data["type"] = @type if @type
19
- data["swversion"] = @swversion if @swversion
20
- data["state"] = @state.data if !@state.data.empty?
23
+ data["swversion"] = @sw_version if @sw_version
24
+ data["state"] = @state.data unless @state.data.empty?
25
+ data["pointsymbol"] = @point_symbol if @point_symbol
26
+ data["modelid"] = @model_id if @model_id
27
+ data["uniqueid"] = @unique_id if @unique_id
21
28
  data
22
29
  end
23
30
  end
@@ -45,18 +45,21 @@ class BulbState < HObject
45
45
  :reachable, :transition_time
46
46
  def initialize( data = {} )
47
47
  data = {} if data == nil
48
- super
49
- @on = data["on"]
50
- set_bri data["bri"]
51
- set_hue data["hue"]
52
- set_sat data["sat"]
53
- set_xy data["xy"]
54
- set_ct data["ct"]
55
- set_alert data["alert"]
56
- set_effect data["effect"]
57
- set_color_mode data["colormode"]
58
48
  @reachable = data["reachable"]
59
- set_transition_time data["transitiontime"]
49
+
50
+ # bridge returns invaild values for state variables when reachable is false
51
+ unless @reachable == false
52
+ @on = data["on"]
53
+ set_bri data["bri"]
54
+ set_hue data["hue"]
55
+ set_sat data["sat"]
56
+ set_xy data["xy"]
57
+ set_ct data["ct"]
58
+ set_alert data["alert"]
59
+ set_effect data["effect"]
60
+ set_color_mode data["colormode"]
61
+ set_transition_time data["transitiontime"]
62
+ end
60
63
  end
61
64
 
62
65
  def color_mode=(value) set_color_mode(value) end
@@ -172,8 +175,8 @@ class BulbState < HObject
172
175
  end
173
176
 
174
177
  def data
175
- data = @data
176
- data["on"] = @on if (@on!=nil)
178
+ data = {}
179
+ data["on"] = @on unless @on.nil?
177
180
  data["bri"] = @bri if @bri
178
181
  data["hue"] = @hue if @hue
179
182
  data["sat"] = @sat if @sat
@@ -182,7 +185,7 @@ class BulbState < HObject
182
185
  data["alert"] = @alert if @alert
183
186
  data["effect"] = @effect if @effect
184
187
  data["colormode"] = @color_mode if @color_mode
185
- data["reachable"] = @reachable if @reachable
188
+ data["reachable"] = @reachable unless @reachable.nil?
186
189
  data["transitiontime"] = @transition_time if @transition_time
187
190
  data
188
191
  end
@@ -3,14 +3,13 @@ require 'lights/hobject'
3
3
  class Command < HObject
4
4
  attr_reader :address, :method, :body
5
5
  def initialize(data = {})
6
- super
7
6
  @address = data["address"]
8
7
  @body = data["body"]
9
8
  @method = data["method"]
10
9
  end
11
10
 
12
11
  def data
13
- data = @data
12
+ data = {}
14
13
  data["address"] = @address if @address
15
14
  data["body"] = @body if @body
16
15
  data["method"] = @method if @method
@@ -2,19 +2,58 @@ require 'lights/userlist'
2
2
  require 'lights/hobject'
3
3
 
4
4
  class HueConfig < HObject
5
- attr_reader :name, :swversion, :whitelist
5
+ attr_reader :name, :zigbee_channel, :mac, :dhcp,
6
+ :ip_address, :netmask, :gateway,
7
+ :proxy_address, :proxy_port, :utc,
8
+ :local_time, :time_zone, :whitelist,
9
+ :swversion, :api_version, :sw_update,
10
+ :link_button, :portal_services,
11
+ :portal_connection, :portal_state
6
12
  def initialize(data = {})
7
- super
8
13
  @name = data["name"]
9
- @swversion = data["swversion"]
14
+ @zigbee_channel = data["zigbeechannel"]
15
+ @mac = data["mac"]
16
+ @dhcp = data["dhcp"]
17
+ @ip_address = data["ipaddress"]
18
+ @netmask = data["netmask"]
19
+ @gateway = data["gateway"]
20
+ @proxy_address = data["proxyaddress"]
21
+ @proxy_port = data["proxyport"]
22
+ @utc = data["UTC"]
23
+ @local_time = data["localtime"]
24
+ @time_zone = data["timezone"]
10
25
  @whitelist = UserList.new(data["whitelist"])
26
+ @sw_version = data["swversion"]
27
+ @api_version = data["apiversion"]
28
+ @sw_update = data["swupdate"]
29
+ @link_button = data["linkbutton"]
30
+ @portal_services = data["portalservices"]
31
+ @portal_connection = data["portalconnection"]
32
+ @portal_state = data["portalstate"]
11
33
  end
12
34
 
13
35
  def data
14
- data = @data
36
+ data = {}
15
37
  data["name"] = @name if @name
16
- data["swversion"] = @swversion if @swversion
17
- data["whitelist"] = @whitelist.data if !@whitelist.data.empty?
38
+ data["zigbeechannel"] = @zigbee_channel if @zigbee_channel
39
+ data["mac"] = @mac if @mac
40
+ data["dhcp"] = @dhcp unless @dhcp.nil?
41
+ data["ipaddress"] = @ip_address if @ip_address
42
+ data["netmask"] = @netmask if @netmask
43
+ data["gateway"] = @gateway if @gateway
44
+ data["proxyaddress"] = @proxy_address if @proxy_address
45
+ data["proxyport"] = @proxy_port if @proxy_port
46
+ data["UTC"] = @utc if @utc
47
+ data["localtime"] = @local_time if @local_time
48
+ data["timezone"] = @time_zone if @time_zone
49
+ data["whitelist"] = @whitelist.data unless @whitelist.data.empty?
50
+ data["swversion"] = @sw_version if @sw_version
51
+ data["apiversion"] = @api_version if @api_version
52
+ data["swupdate"] = @sw_update unless @sw_update.nil?
53
+ data["linkbutton"] = @link_button unless @link_button.nil?
54
+ data["portalservices"] = @portal_services unless @portal_services.nil?
55
+ data["portalconnection"] = @portal_connection if @portal_connection
56
+ data["portalstate"] = @portal_state unless @portal_state.nil?
18
57
  data
19
58
  end
20
59
  end
@@ -11,7 +11,6 @@ class Datastore < HObject
11
11
  attr_reader :lights, :groups, :config, :rules,
12
12
  :scenes, :schedules, :sensors
13
13
  def initialize(data = {})
14
- super
15
14
  @lights = BulbList.new(data["lights"])
16
15
  @groups = GroupList.new(data["groups"])
17
16
  @config = HueConfig.new(data["config"])
@@ -32,7 +31,7 @@ class Datastore < HObject
32
31
  end
33
32
 
34
33
  def data
35
- data = @data
34
+ data = {}
36
35
  data["lights"] = @lights.data if !@lights.data.empty?
37
36
  data["groups"] = @groups.data if !@groups.data.empty?
38
37
  data["config"] = @config.data if !@config.data.empty?
@@ -12,7 +12,7 @@ end
12
12
 
13
13
  class BulbStateValueOutOfRangeException < Exception
14
14
  def initalize(msg = "Value out of range.")
15
- super(msg)
15
+ super
16
16
  end
17
17
  end
18
18
 
@@ -33,3 +33,9 @@ class ParameterUnavailableException < Exception
33
33
  super
34
34
  end
35
35
  end
36
+
37
+ class SceneLockedException < Exception
38
+ def initialize(msg = "Scene could not be removed, because it's locked.")
39
+ super
40
+ end
41
+ end
@@ -1,21 +1,22 @@
1
1
  require 'lights/hobject'
2
2
 
3
3
  class Group < HObject
4
- attr_reader :id, :data, :name, :lights, :action
4
+ attr_reader :id, :data, :name, :lights, :action, :type
5
5
  attr_writer :name, :lights, :action
6
6
  def initialize( id = nil, data = {} )
7
- super(data)
8
7
  @id = id
9
8
  @action = BulbState.new(data["action"])
10
9
  @name = data["name"]
11
10
  @lights = data["lights"]
11
+ @type = data["type"]
12
12
  end
13
13
 
14
14
  def data
15
- data = @data
15
+ data = {}
16
16
  data["name"] = @name if @name
17
17
  data["lights"] = @lights if @lights
18
- data["action"] = @action.data if @action.data != {}
18
+ data["type"] = @type if @type
19
+ data["action"] = @action.data unless @action.data.empty?
19
20
  data
20
21
  end
21
22
  end
@@ -1,6 +1,5 @@
1
1
  class HObject
2
- def initialize(data={})
3
- @data = data
2
+ def initialize(*args)
4
3
  end
5
4
 
6
5
  def to_json(options={})
@@ -9,12 +9,11 @@ class List < HObject
9
9
 
10
10
  attr_reader :list
11
11
  def initialize(data = {})
12
- super
13
12
  @list = []
14
13
  end
15
14
 
16
15
  def data
17
- data = @data
16
+ data = {}
18
17
  @list.each {|b| data[b.id] = b.data} if @list
19
18
  data
20
19
  end
@@ -1,16 +1,31 @@
1
1
  require 'lights/hobject'
2
2
 
3
3
  class Rule < HObject
4
- attr_reader :id, :data, :name
4
+ attr_reader :id, :name, :owner, :created,
5
+ :last_triggered, :times_triggered,
6
+ :status, :conditions, :actions
5
7
  def initialize( id = nil, data = {} )
6
- super(data)
7
8
  @id = id
8
9
  @name = data["name"]
10
+ @owner = data["owner"]
11
+ @created = data["created"]
12
+ @last_triggered = data["lasttriggered"]
13
+ @times_triggered = data["timestriggered"]
14
+ @status = data["status"]
15
+ @conditions = data["conditions"]
16
+ @actions = data["actions"]
9
17
  end
10
18
 
11
19
  def data
12
- data = @data
20
+ data = {}
13
21
  data["name"] = @name if @name
22
+ data["owner"] = @owner if @owner
23
+ data["created"] = @created if @created
24
+ data["lasttriggered"] = @last_triggered if @last_triggered
25
+ data["timestriggered"] = @times_triggered if @times_triggered
26
+ data["status"] = @status if @status
27
+ data["conditions"] = @conditions if @conditions
28
+ data["actions"] = @actions if @actions
14
29
  data
15
30
  end
16
31
  end
@@ -1,20 +1,23 @@
1
1
  require 'lights/hobject'
2
2
 
3
3
  class Scene < HObject
4
- attr_accessor :id, :name, :active, :lights
5
- def initialize(id,data = {})
6
- super(data)
4
+ attr_accessor :id, :name, :active, :lights, :recycle, :transition_time
5
+ def initialize(id = nil,data = {})
7
6
  @id = id
8
7
  @name = data["name"]
9
8
  @active = data["active"]
10
9
  @lights = data["lights"]
10
+ @recycle = data["recycle"]
11
+ @transition_time = data["transitiontime"]
11
12
  end
12
13
 
13
14
  def data
14
15
  data = {}
15
16
  data["name"] = @name if @name
16
- data["active"] = @active if @active
17
+ data["active"] = @active unless @active.nil?
17
18
  data["lights"] = @lights if @lights
19
+ data["recycle"] = @recycle unless @recycle.nil?
20
+ data["transitiontime"] = @transition_time if @transition_time
18
21
  data
19
22
  end
20
23
  end
@@ -2,13 +2,17 @@ require 'lights/command'
2
2
  require 'lights/hobject'
3
3
 
4
4
  class Schedule < HObject
5
- attr_reader :id, :name, :time, :status
5
+ attr_reader :id, :name, :time, :status,
6
+ :description, :local_time,
7
+ :created, :command
6
8
  def initialize(id,data = {})
7
- super(data)
8
9
  @id = id
9
10
  @name = data["name"]
10
11
  @time = data["time"]
11
12
  @status = data["status"]
13
+ @description = data["description"]
14
+ @local_time = data["localtime"]
15
+ @created = data["created"]
12
16
  @command = Command.new(data["command"])
13
17
  end
14
18
 
@@ -17,11 +21,14 @@ class Schedule < HObject
17
21
  end
18
22
 
19
23
  def data
20
- data = @data
24
+ data = {}
21
25
  data["name"] = @name if @name
22
26
  data["time"] = @time if @time
23
27
  data["status"] = @status if @status
24
- data["command"] = @command.data if !@command.data.empty?
28
+ data["description"] = @description if @description
29
+ data["localtime"] = @local_time if @local_time
30
+ data["created"] = @created if @created
31
+ data["command"] = @command.data unless @command.data.empty?
25
32
  data
26
33
  end
27
34
  end
@@ -1,35 +1,25 @@
1
1
  class SensorState < HObject
2
2
  attr_reader :last_updated
3
3
  def initialize(data)
4
- super
5
4
  @last_updated = data["lastupdated"]
5
+ @daylight = data["daylight"]
6
+ @button_event = data["buttonevent"]
6
7
  end
7
8
 
8
9
  def data
9
- data = @data
10
+ data = {}
10
11
  data["lastupdated"] = @last_updated if @last_updated
11
- data
12
- end
13
- end
14
-
15
- class TapState < SensorState
16
- attr_reader :button_event
17
- def initialize(data)
18
- super
19
- @button_event = data["button_event"]
20
- end
21
-
22
- def data
23
- data = @data
24
- data["button_event"] = @button_event if @button_event
12
+ data["daylight"] = @daylight unless @daylight.nil?
13
+ data["buttonevent"] = @button_event if @button_event
25
14
  data
26
15
  end
27
16
  end
28
17
 
29
18
  class Sensor < HObject
30
- attr_reader :id, :data, :name, :type, :model_id, :manufacturer_name, :unique_id, :sw_version, :state
19
+ attr_reader :id, :data, :name, :type, :model_id,
20
+ :manufacturer_name, :unique_id,
21
+ :sw_version, :state
31
22
  def initialize( id, data = {} )
32
- super(data)
33
23
  @id = id
34
24
  @name = data["name"]
35
25
  @type = data["type"]
@@ -37,19 +27,20 @@ class Sensor < HObject
37
27
  @manufacturer_name = data["manufacturername"]
38
28
  @unique_id = data["uniqueid"]
39
29
  @sw_version = data["swversion"]
30
+ @config = data["config"]
40
31
  @state = SensorState.new(data["state"])
41
- #@config = SensorConfig.new(data["config"])
42
32
  end
43
33
 
44
34
  def data
45
- data = @data
35
+ data = {}
46
36
  data["name"] = @name if @name
47
37
  data["type"] = @type if @type
48
38
  data["modelid"] = @model_id if @model_id
49
39
  data["manufacturername"] = @manufacturer_name if @manufacturer_name
50
40
  data["uniqueid"] = @unique_id if @unique_id
51
41
  data["swversion"] = @sw_version if @sw_version
52
- data["state"] = @state.data if @state.data if !@state.data.empty?
42
+ data["config"] = @config if @config
43
+ data["state"] = @state.data unless @state.data.empty?
53
44
  data
54
45
  end
55
46
  end
@@ -3,7 +3,6 @@ require 'lights/hobject'
3
3
  class User < HObject
4
4
  attr_reader :id, :name, :create_date, :last_use_date
5
5
  def initialize( id, data = {} )
6
- super(data)
7
6
  @id = id
8
7
  @name = data["name"]
9
8
  @create_date = data["create date"]
@@ -11,7 +10,7 @@ class User < HObject
11
10
  end
12
11
 
13
12
  def data
14
- data = @data
13
+ data = {}
15
14
  data["name"] = @name if @name
16
15
  data["create date"] = @create_date if @create_date
17
16
  data["last use date"] = @last_use_date if @last_use_date
@@ -1,3 +1,3 @@
1
1
  module LightsConst
2
- VERSION = "0.8.18"
2
+ VERSION = "1.0.2"
3
3
  end
@@ -2,6 +2,7 @@
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'lights/version'
5
+ require 'date'
5
6
 
6
7
  Gem::Specification.new do |s|
7
8
  s.name = 'lights'
@@ -12,14 +13,14 @@ Gem::Specification.new do |s|
12
13
  s.summary = "lights"
13
14
  s.homepage = 'http://rubygems.org/gems/lights'
14
15
  s.license = 'MIT'
15
- s.date = '2014-10-11'
16
+ s.date = Date.today.to_s
16
17
 
17
18
  s.files = `git ls-files`.split($/)
18
19
  s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
20
  s.test_files = s.files.grep(%r{^(test|spec|features)/})
20
21
  s.require_paths = ["lib"]
21
22
 
22
- s.add_runtime_dependency "simpletable", "~> 0.3.1"
23
+ s.add_runtime_dependency "simpletable", "~> 0.3.2"
23
24
 
24
25
  s.add_development_dependency "bundler", "~> 1.3"
25
26
  s.add_development_dependency "rake"
@@ -7,6 +7,13 @@ describe Bulb do
7
7
  bulb.name.should eql "test name"
8
8
  end
9
9
 
10
+ it "properly set name parameter" do
11
+ data = { "name" => "test name" }
12
+ bulb = Bulb.new(1,data)
13
+ bulb.name = "new test name"
14
+ bulb.name.should eql "new test name"
15
+ end
16
+
10
17
  it "properly creates state object" do
11
18
  data = {
12
19
  "name" => "test name",
@@ -248,6 +248,16 @@ describe BulbState do
248
248
  expect { b.ct = BulbState::MIN_CT - 1 }.to raise_error
249
249
  end
250
250
 
251
+ it "should ignore out of range color temperature when 'reachable'= false" do
252
+ state = {
253
+ "reachable" => false,
254
+ "ct" => 0
255
+ }
256
+ b = BulbState.new state
257
+ b.data["ct"].should eq nil
258
+ b.data["reachable"].should eq false
259
+ end
260
+
251
261
  # EFFECT
252
262
  it "should properly set effect value in constructor" do
253
263
  data = { "effect" => BulbState::Effect::COLORLOOP }
@@ -2,15 +2,45 @@ require 'lights'
2
2
 
3
3
  describe Datastore do
4
4
  it "properly reconstructs sub objects" do
5
+ data = JSON.parse(DATASTORE_JSON)
6
+ ds = Datastore.new data
7
+ ds.data.should eql data
8
+ end
9
+
10
+ it "properly reconstructs light objects" do
5
11
  data = JSON.parse(DATASTORE_JSON)
6
12
  ds = Datastore.new data
7
13
  ds.lights.data.should eql data["lights"]
14
+ end
15
+ it "properly reconstructs group objects" do
16
+ data = JSON.parse(DATASTORE_JSON)
17
+ ds = Datastore.new data
8
18
  ds.groups.data.should eql data["groups"]
19
+ end
20
+ it "properly reconstructs rule objects" do
21
+ data = JSON.parse(DATASTORE_JSON)
22
+ ds = Datastore.new data
9
23
  ds.rules.data.should eql data["rules"]
24
+ end
25
+ it "properly reconstructs scene objects" do
26
+ data = JSON.parse(DATASTORE_JSON)
27
+ ds = Datastore.new data
10
28
  ds.scenes.data.should eql data["scenes"]
29
+ end
30
+ it "properly reconstructs schedule objects" do
31
+ data = JSON.parse(DATASTORE_JSON)
32
+ ds = Datastore.new data
11
33
  ds.schedules.data.should eql data["schedules"]
34
+ end
35
+ it "properly reconstructs sensor objects" do
36
+ data = JSON.parse(DATASTORE_JSON)
37
+ ds = Datastore.new data
12
38
  ds.sensors.data.should eql data["sensors"]
13
- ds.data.should eql data
39
+ end
40
+ it "properly reconstructs config object" do
41
+ data = JSON.parse(DATASTORE_JSON)
42
+ ds = Datastore.new data
43
+ ds.config.data.should eql data["config"]
14
44
  end
15
45
  end
16
46
 
@@ -19,7 +49,7 @@ DATASTORE_JSON = %Q{
19
49
  "lights": {
20
50
  "1": {
21
51
  "state": {
22
- "on": true,
52
+ "on": false,
23
53
  "bri": 254,
24
54
  "hue": 34495,
25
55
  "sat": 232,
@@ -227,7 +257,7 @@ DATASTORE_JSON = %Q{
227
257
  "name": "Philips hue",
228
258
  "zigbeechannel": 25,
229
259
  "mac": "00:11:22:33:44:55",
230
- "dhcp": true,
260
+ "dhcp": false,
231
261
  "ipaddress": "192.168.1.27",
232
262
  "netmask": "255.255.255.0",
233
263
  "gateway": "192.168.1.1",
@@ -269,7 +299,7 @@ DATASTORE_JSON = %Q{
269
299
  "notify": false
270
300
  },
271
301
  "linkbutton": false,
272
- "portalservices": true,
302
+ "portalservices": false,
273
303
  "portalconnection": "connected",
274
304
  "portalstate": {
275
305
  "signedon": true,
@@ -320,7 +350,7 @@ DATASTORE_JSON = %Q{
320
350
  "4",
321
351
  "5"
322
352
  ],
323
- "active": true
353
+ "active": false
324
354
  },
325
355
  "da01b1eaf-on-0": {
326
356
  "name": "Purple on 0",
@@ -2,22 +2,152 @@ require 'lights'
2
2
 
3
3
  describe Group do
4
4
  it "properly parses input parameters" do
5
- data = {
6
- "key1" => "value 1",
7
- "key2" => "value 2",
8
- }
5
+ data = JSON.parse(GROUPS_JSON)["1"]
9
6
  group = Group.new(1,data)
10
7
  group.id.should eql 1
11
- group.data.should eql data
8
+ group.name.should eql "Ceiling light"
9
+ group.type.should eql "LightGroup"
10
+ group.lights.should eql ["1","2","3","4"]
12
11
  end
13
12
 
14
13
  it "properly reconstucts object hash" do
15
- data = {
16
- "key1" => "value 1",
17
- "key2" => "value 2",
18
- }
14
+ data = JSON.parse(GROUPS_JSON)["1"]
19
15
  group = Group.new(1,data)
20
16
  group.id.should eql 1
21
17
  group.data.should eql data
22
18
  end
23
19
  end
20
+
21
+ GROUPS_JSON = %Q{
22
+ {
23
+ "1": {
24
+ "name": "Ceiling light",
25
+ "lights": [
26
+ "1",
27
+ "2",
28
+ "3",
29
+ "4"
30
+ ],
31
+ "type": "LightGroup",
32
+ "action": {
33
+ "on": true,
34
+ "bri": 254,
35
+ "hue": 56100,
36
+ "sat": 232,
37
+ "effect": "none",
38
+ "xy": [
39
+ 0.4119,
40
+ 0.1949
41
+ ],
42
+ "ct": 293,
43
+ "colormode": "xy"
44
+ }
45
+ },
46
+ "2": {
47
+ "name": "Lamp",
48
+ "lights": [
49
+ "5"
50
+ ],
51
+ "type": "LightGroup",
52
+ "action": {
53
+ "on": true,
54
+ "bri": 254,
55
+ "hue": 56100,
56
+ "sat": 232,
57
+ "effect": "none",
58
+ "xy": [
59
+ 0.4119,
60
+ 0.1949
61
+ ],
62
+ "ct": 293,
63
+ "colormode": "xy"
64
+ }
65
+ },
66
+ "3": {
67
+ "name": "HueCraft_Ambiance1",
68
+ "lights": [
69
+ "1",
70
+ "2"
71
+ ],
72
+ "type": "LightGroup",
73
+ "action": {
74
+ "on": true,
75
+ "bri": 254,
76
+ "hue": 56100,
77
+ "sat": 232,
78
+ "effect": "none",
79
+ "xy": [
80
+ 0.4119,
81
+ 0.1949
82
+ ],
83
+ "ct": 293,
84
+ "colormode": "xy"
85
+ }
86
+ },
87
+ "4": {
88
+ "name": "HueCraft_Ambiance2",
89
+ "lights": [
90
+ "3",
91
+ "4"
92
+ ],
93
+ "type": "LightGroup",
94
+ "action": {
95
+ "on": true,
96
+ "bri": 254,
97
+ "hue": 56100,
98
+ "sat": 232,
99
+ "effect": "none",
100
+ "xy": [
101
+ 0.4119,
102
+ 0.1949
103
+ ],
104
+ "ct": 293,
105
+ "colormode": "xy"
106
+ }
107
+ },
108
+ "5": {
109
+ "name": "HueCraft_Effect1",
110
+ "lights": [
111
+ "5"
112
+ ],
113
+ "type": "LightGroup",
114
+ "action": {
115
+ "on": true,
116
+ "bri": 254,
117
+ "hue": 56100,
118
+ "sat": 232,
119
+ "effect": "none",
120
+ "xy": [
121
+ 0.4119,
122
+ 0.1949
123
+ ],
124
+ "ct": 293,
125
+ "colormode": "xy"
126
+ }
127
+ },
128
+ "6": {
129
+ "name": "HueCraft_HueCraft",
130
+ "lights": [
131
+ "1",
132
+ "2",
133
+ "3",
134
+ "4",
135
+ "5"
136
+ ],
137
+ "type": "LightGroup",
138
+ "action": {
139
+ "on": true,
140
+ "bri": 254,
141
+ "hue": 56100,
142
+ "sat": 232,
143
+ "effect": "none",
144
+ "xy": [
145
+ 0.4119,
146
+ 0.1949
147
+ ],
148
+ "ct": 293,
149
+ "colormode": "xy"
150
+ }
151
+ }
152
+ }
153
+ }
@@ -4,8 +4,6 @@ describe Rule do
4
4
  it "properly reconstucts object hash" do
5
5
  data = {
6
6
  "name" => "test name",
7
- "key1" => "value 1",
8
- "key2" => "value 2",
9
7
  }
10
8
  rule = Rule.new(1,data)
11
9
  rule.id.should eql 1
metadata CHANGED
@@ -1,97 +1,97 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lights
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.18
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brady Turner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-11 00:00:00.000000000 Z
11
+ date: 2020-06-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: simpletable
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.3.1
19
+ version: 0.3.2
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.1
26
+ version: 0.3.2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '1.3'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.3'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ! '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ! '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: '2.6'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '2.6'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: cucumber
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ! '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ! '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: aruba
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ! '>='
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ! '>='
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  description: Client library and CLI for controlling Philips Hue lights.
@@ -101,7 +101,7 @@ executables:
101
101
  extensions: []
102
102
  extra_rdoc_files: []
103
103
  files:
104
- - .gitignore
104
+ - ".gitignore"
105
105
  - Gemfile
106
106
  - LICENSE.txt
107
107
  - README.md
@@ -154,17 +154,16 @@ require_paths:
154
154
  - lib
155
155
  required_ruby_version: !ruby/object:Gem::Requirement
156
156
  requirements:
157
- - - ! '>='
157
+ - - ">="
158
158
  - !ruby/object:Gem::Version
159
159
  version: '0'
160
160
  required_rubygems_version: !ruby/object:Gem::Requirement
161
161
  requirements:
162
- - - ! '>='
162
+ - - ">="
163
163
  - !ruby/object:Gem::Version
164
164
  version: '0'
165
165
  requirements: []
166
- rubyforge_project:
167
- rubygems_version: 2.0.6
166
+ rubygems_version: 3.0.6
168
167
  signing_key:
169
168
  specification_version: 4
170
169
  summary: lights