Class: NLHue::Target

Inherits:
Object
  • Object
show all
Defined in:
lib/nlhue/target.rb

Overview

Base class representing a light or group known to a Hue bridge. See NLHue::Light and NLHue::Group.

Direct Known Subclasses

Group, Light

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(bridge, id, info, api_category, api_target) ⇒ Target

bridge - The Bridge that controls this light or group. id - The light or group’s ID (>=0 for groups, >=1 for lights). info - Parsed Hash of the JSON light or group info object from the bridge. api_category - The category to pass to the bridge for rate limiting API requests. Also forms part of the API URL. api_target - @api_target for lights, @api_target for groups



16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/nlhue/target.rb', line 16

def initialize(bridge, id, info, api_category, api_target)
	@bridge = bridge
	@id = id.to_i
	@api_category = api_category
	@api_target = api_target

	@changes = Set.new
	@defer = false

	@info = {api_target => {}}
	handle_json(info || {})
end

Instance Attribute Details

#bridgeObject (readonly)

Returns the value of attribute bridge.



8
9
10
# File 'lib/nlhue/target.rb', line 8

def bridge
  @bridge
end

#idObject (readonly)

Returns the value of attribute id.



8
9
10
# File 'lib/nlhue/target.rb', line 8

def id
  @id
end

#nameObject (readonly)

Returns the value of attribute name.



8
9
10
# File 'lib/nlhue/target.rb', line 8

def name
  @name
end

#transitiontimeObject

Returns the value of attribute transitiontime.



8
9
10
# File 'lib/nlhue/target.rb', line 8

def transitiontime
  @transitiontime
end

#typeObject (readonly)

Returns the value of attribute type.



8
9
10
# File 'lib/nlhue/target.rb', line 8

def type
  @type
end

Instance Method Details

#alertObject

Returns the current alert state of the light or group (or the stored state if defer() was called, but send() has not yet been called). Groups are not updated when their constituent lights are changed individually.



178
179
180
# File 'lib/nlhue/target.rb', line 178

def alert
	(@info[@api_target] || @info[@api_target])['alert']
end

#alert!(repeat = false) ⇒ Object

Tells the light or group to flash once if repeat is false, or several times if repeat is true. Sets the ‘alert’ property.



157
158
159
# File 'lib/nlhue/target.rb', line 157

def alert!(repeat=false)
	set({ 'alert' => repeat ? 'select' : 'lselect' })
end

#alert=(alert) ⇒ Object

Sets the light or group’s alert status to the given string (one of ‘select’ (flash once), ‘lselect’ (flash several times), or ‘none’ (stop flashing)). Any other value may result in an error from the bridge.



170
171
172
# File 'lib/nlhue/target.rb', line 170

def alert=(alert)
	set({ 'alert' => alert })
end

#briObject

The brightness most recently set with #bri=, or the last brightness received from the light or group due to calling #update on the target or on the bridge.



218
219
220
221
# File 'lib/nlhue/target.rb', line 218

def bri
	# TODO: Field storing @api_target or @api_target
	@info[@api_target]['bri'].to_i
end

#bri=(bri) ⇒ Object

Sets the brightness of this light or group (0-255 inclusive). Note that a brightness of 0 is not off. The light(s) must already be switched on for this to work, if not deferred.



208
209
210
211
212
213
# File 'lib/nlhue/target.rb', line 208

def bri=(bri)
	bri = 0 if bri < 0
	bri = 255 if bri > 255

	set({ 'bri' => bri.to_i })
end

#clear_alertObject

Stops any existing flashing of the light or group.



162
163
164
# File 'lib/nlhue/target.rb', line 162

def clear_alert
	set({ 'alert' => 'none' })
end

#colormodeObject

Returns the light or group’s current or last set color mode (‘ct’ for color temperature, ‘hs’ for hue/saturation, ‘xy’ for CIE XYZ).



341
342
343
# File 'lib/nlhue/target.rb', line 341

def colormode
	@info[@api_target]['colormode']
end

#ctObject

The color temperature most recently set with ct=, or the last color temperature received from the light due to calling #update on the light or on the bridge.



238
239
240
# File 'lib/nlhue/target.rb', line 238

def ct
	@info[@api_target]['ct'].to_i
end

#ct=(ct) ⇒ Object

Switches the light or group into color temperature mode and sets the color temperature of the light in mireds (154-500 inclusive, where 154 is highest temperature (bluer), 500 is lowest temperature (yellower)). The light(s) must be on for this to work, if not deferred.



228
229
230
231
232
233
# File 'lib/nlhue/target.rb', line 228

def ct=(ct)
	ct = 154 if ct < 154
	ct = 500 if ct > 500

	set({ 'ct' => ct.to_i, 'colormode' => 'ct' })
end

#deferObject

Call to queue changes to be sent all at once. Updates will not be sent to the light or group until #submit is called. Call #nodefer to stop deferring changes.



86
87
88
# File 'lib/nlhue/target.rb', line 86

def defer
	@defer = true
end

#effectObject

The light or group’s last set special effect mode.



334
335
336
# File 'lib/nlhue/target.rb', line 334

def effect
	@info[@api_target]['effect']
end

#effect=(effect) ⇒ Object

Sets the light or group’s special effect mode (either ‘none’ or ‘colorloop’).



328
329
330
331
# File 'lib/nlhue/target.rb', line 328

def effect= effect
	effect = 'none' unless effect == 'colorloop'
	set({ 'effect' => effect })
end

#handle_json(info) ⇒ Object

Updates this light or group object using a Hash parsed from the JSON info from the Hue bridge.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/nlhue/target.rb', line 31

def handle_json(info)
	raise "Light/group info must be a Hash, not #{info.class}." unless info.is_a?(Hash)

	# A group contains no 'xy' for a short time after creation.
	# Add fake xy color for lamps that don't support color.
	info[@api_target] = {} unless info[@api_target].is_a?(Hash)
	info[@api_target]['xy'] ||= [0.33333, 0.33333]

	info['id'] = @id

	# Preserve deferred changes that have not yet been sent to the bridge
	@changes.each do |key|
		info[@api_target][key] = @info[@api_target][key]
	end

	@info = info
	@type = @info['type']
	@name = @info['name'] || @name || "Lightset #{@id}"
end

#hueObject

The hue most recently set with #hue=, or the last hue received from the light or group due to calling #update on the target or on the bridge.



306
307
308
# File 'lib/nlhue/target.rb', line 306

def hue
	@info[@api_target]['hue'].to_i * 360 / 65536.0
end

#hue=(hue) ⇒ Object

Switches the light or group into hue/saturation mode and sets the hue to the given value (floating point degrees, wrapped to 0-360). The light(s) must already be on for this to work.



298
299
300
301
# File 'lib/nlhue/target.rb', line 298

def hue=(hue)
	hue = (hue * 65536 / 360).to_i & 65535
	set({ 'hue' => hue, 'colormode' => 'hs' })
end

#nodeferObject

Stops deferring changes and sends any queued changes immediately.



92
93
94
95
# File 'lib/nlhue/target.rb', line 92

def nodefer
	@defer = false
	set {}
end

#off!Object

Turns the light or group off.



201
202
203
# File 'lib/nlhue/target.rb', line 201

def off!
	self.on = false
end

#on!Object

Turns the light or group on.



196
197
198
# File 'lib/nlhue/target.rb', line 196

def on!
	self.on = true
end

#on=(on) ⇒ Object

Sets the on/off state of this light or group (true or false). Lights must be on before other parameters can be changed.



184
185
186
# File 'lib/nlhue/target.rb', line 184

def on=(on)
	set({ 'on' => !!on })
end

#on?Boolean

The light state most recently set with on=, #on! or #off!, or the last light state received from the bridge due to calling #update on the light/group or on the NLHue::Bridge.

Returns:

  • (Boolean)


191
192
193
# File 'lib/nlhue/target.rb', line 191

def on?
	@info[@api_target]['on']
end

#satObject

The saturation most recently set with #saturation=, or the last saturation received from the light due to calling #update on the light or on the bridge.



322
323
324
# File 'lib/nlhue/target.rb', line 322

def sat
	@info[@api_target]['sat'].to_i
end

#sat=(sat) ⇒ Object

Switches the light into hue/saturation mode and sets the light’s saturation to the given value (0-255 inclusive).



312
313
314
315
316
317
# File 'lib/nlhue/target.rb', line 312

def sat=(sat)
	sat = 0 if sat < 0
	sat = 255 if sat > 255

	set({ 'sat' => sat.to_i, 'colormode' => 'hs' })
end

#send_changes(&block) ⇒ Object

Sends parameters named in @changes to the bridge. The block, if given, will be called with true and the response, or false and an Exception. This should only be called internally or by the NLHue::Bridge.



349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# File 'lib/nlhue/target.rb', line 349

def send_changes(&block)
	msg = {}

	@changes.each do |param|
		case param
		when 'colormode'
			case @info[@api_target]['colormode']
			when 'hs'
				msg['hue'] = @info[@api_target]['hue'] if @changes.include? 'hue'
				msg['sat'] = @info[@api_target]['sat'] if @changes.include? 'sat'
			when 'xy'
				msg['xy'] = @info[@api_target]['xy']
			when 'ct'
				msg['ct'] = @info[@api_target]['ct']
			end

		when 'bri', 'on', 'alert', 'effect', 'scene'
			msg[param] = @info[@api_target][param]
		end
	end

	msg['transitiontime'] = @transitiontime if @transitiontime

	put_target(msg) do |status, result|
		rmsg = result.to_s
		# TODO: Parse individual parameters' error messages?  Example:
		# [{"error":{"type":6,"address":"/lights/2/state/zfhue","description":"parameter, zfhue, not available"}},{"success":{"/lights/2/state/transitiontime":0}}]
		@changes.delete('alert') if rmsg.include? 'Device is set to off'
		@changes.clear if status || rmsg =~ /(invalid value|not available)/
		yield status, result if block_given?
	end

	@transitiontime = nil
end

#stateObject

Returns a Hash containing the light’s info and current state, with symbolized key names and hue scaled to 0..360. Example:

:id => 1,
:name => 'Hue Lamp 2',
:type => 'Extended color light',
:on => false,
:bri => 220,
:ct => 500,
:x => 0.5,
:y => 0.5,
:hue => 193.5,
:sat => 255,
:colormode => 'hs'



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/nlhue/target.rb', line 139

def state
	{
		:id => id,
		:name => name,
		:type => type,
		:on => on?,
		:bri => bri,
		:ct => ct,
		:x => x,
		:y => y,
		:hue => hue,
		:sat => sat,
		:colormode => colormode
	}
end

#submit(&block) ⇒ Object

Tells the Bridge object that this Light or Group is ready to have its deferred data sent. The NLHue::Bridge will schedule a rate-limited call to #send_changes, which sends all changes queued since the last call to defer. The block, if given, will be called with true and the response on success, or false and an Exception on error. The transition time sent to the bridge can be controlled with transitiontime=. If no transition time is set, the default transition time will be used by the bridge.



119
120
121
122
# File 'lib/nlhue/target.rb', line 119

def submit(&block)
	puts "Submitting changes to #{self}" # XXX
	@bridge.add_target self, &block
end

#to_hObject

Returns a copy of the hash representing the light or group’s state as parsed from the JSON returned by the bridge, without any range scaling (e.g. so hue range is 0..65535).



74
75
76
# File 'lib/nlhue/target.rb', line 74

def to_h
	@info.clone
end

#to_json(*args) ⇒ Object

Converts the Hash returned by #state to JSON.



79
80
81
# File 'lib/nlhue/target.rb', line 79

def to_json(*args)
	state.to_json(*args)
end

#update(&block) ⇒ Object

Gets the current state of this light or group from the bridge. The block, if given, will be called with true and the response on success, or false and an Exception on error.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/nlhue/target.rb', line 54

def update(&block)
	tx = rand
	@bridge.get_api "/#{@api_category}/#{@id}", @api_category do |response|
		puts "#{tx} Target #{@id} update response: #{response}" # XXX

		begin
			status, result = @bridge.check_json(response)
			handle_json(result) if status
		rescue => e
			status = false
			result = e
		end

		yield status, result if block_given?
	end
end

#xObject

The X color coordinate most recently set with #x= or #xy=, or the last X color coordinate received from the light or group.



252
253
254
# File 'lib/nlhue/target.rb', line 252

def x
	@info[@api_target]['xy'][0].to_f
end

#x=(x) ⇒ Object

Switches the light or group into CIE XYZ color mode and sets the X color coordinate to the given floating point value between 0 and 1, inclusive. Lights must be on for this to work.



246
247
248
# File 'lib/nlhue/target.rb', line 246

def x=(x)
	self.xy = [ x, @info[@api_target]['xy'][1] ]
end

#xyObject

The XY color coordinates most recently set with #x=, #y=, or #xy=, or the last color coordinates received from the light or group due to calling #update on the target or the bridge.



290
291
292
293
# File 'lib/nlhue/target.rb', line 290

def xy
	xy = @info[@api_target]['xy']
	[ xy[0].to_f, xy[1].to_f ]
end

#xy=(xy) ⇒ Object

Switches the light or group into CIE XYZ color mode and sets the XY color coordinates to the given two-element array of floating point values between 0 and 1, inclusive. Lights must be on for this to work, if not deferred.



274
275
276
277
278
279
280
281
282
283
284
285
# File 'lib/nlhue/target.rb', line 274

def xy=(xy)
	unless xy.is_a?(Array) && xy.length == 2 && xy[0].is_a?(Numeric) && xy[1].is_a?(Numeric)
		raise 'Pass a two-element array of numbers to xy=.'
	end

	xy[0] = 0 if xy[0] < 0
	xy[0] = 1 if xy[0] > 1
	xy[1] = 0 if xy[1] < 0
	xy[1] = 1 if xy[1] > 1

	set({ 'xy' => xy, 'colormode' => 'xy' })
end

#yObject

The Y color coordinate most recently set with #y= or #xy=, or the last Y color coordinate received from the light or group.



266
267
268
# File 'lib/nlhue/target.rb', line 266

def y
	@info[@api_target]['xy'][1].to_f
end

#y=(y) ⇒ Object

Switches the light or group into CIE XYZ color mode and sets the Y color coordinate to the given floating point value between 0 and 1, inclusive. Lights must be on for this to work.



260
261
262
# File 'lib/nlhue/target.rb', line 260

def y=(y)
	self.xy = [ @info[@api_target]['xy'][0], y ]
end