lifx 0.4.8 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c4d3a3b49f4182b136607335b3439a6d8c475af4
4
- data.tar.gz: 5119e5d44ca2c1649a9f4226678dc1c3c04900c3
3
+ metadata.gz: 86bc4e0b28d94c9b3d1d0bf22b5f550988c5cab3
4
+ data.tar.gz: ffc2b6c71d1f4efd5a6bd9732403599b6b357c69
5
5
  SHA512:
6
- metadata.gz: 76282a8c2b04cf4f0c0b199532d2847b97eacf7f8313c246c9aedafbf1cf6d35b02d9c75e75d472bb4f41a278988b92aae63cace417e5902a9e84095161f62f2
7
- data.tar.gz: 0b81b9d0165ce833a8436bb597a5f6398ebf4cebee892f02116a6af9a7450b851c782639c9c077b8672bd3b836cf1f6be03e7dfb219ca02f3255165b12311355
6
+ metadata.gz: f580ff26c0612fa04dff785c06f770b0bcbd262c463f826dc0795e2339ed61d5ef28a0bd13563b592b636e6ad57086a0d2702147b4b07430a7c910550ea91fc5
7
+ data.tar.gz: b6a20e239ac5a9b97fc2f8fad4f794937438b6b07439aabcb4c9bf28295b3eec5c3c8b35c973cb023f4a0c787a3ea2f0e8f811fb10b09f10690895b2aa025b0a
data/CHANGES.md CHANGED
@@ -1,3 +1,12 @@
1
+ ### 0.4.10
2
+
3
+ - Fix `message_rate` visibility bug
4
+
5
+ ### 0.4.9
6
+
7
+ - Message rate checker only runs when connection is idle
8
+ - Now uses `LIFX::TimeoutError` rather than `Timeout::Error` for internal timeout exceptions
9
+
1
10
  ### 0.4.8
2
11
 
3
12
  - Routing table is only updated from State messages
data/Rakefile CHANGED
@@ -7,6 +7,7 @@ end
7
7
  task :default => :spec
8
8
 
9
9
  task :console do
10
+ $LOAD_PATH << "lib"
10
11
  require "lifx"
11
12
  require "pry"
12
13
  if ENV['DEBUG']
@@ -20,4 +20,6 @@ require "lifx/client"
20
20
 
21
21
  module LIFX
22
22
  NULL_SITE_ID = "000000000000"
23
+
24
+ class TimeoutError < StandardError; end
23
25
  end
@@ -39,13 +39,13 @@ module LIFX
39
39
  @context.discover
40
40
  end
41
41
 
42
- class DiscoveryTimeout < Timeout::Error; end
42
+ class DiscoveryTimeout < TimeoutError; end
43
43
  # This method tells the {NetworkContext} to look for devices, and will block
44
44
  # until there's at least one device.
45
45
  #
46
46
  # @example Wait until at least three lights have been found
47
47
  # client.discover! { |c| c.lights.count >= 3 }
48
- #
48
+ #
49
49
  # @param timeout: [Numeric] How long to try to wait for before returning
50
50
  # @param condition_interval: [Numeric] Seconds between evaluating the block
51
51
  # @yield [Client] This block is evaluated every `condition_interval` seconds. If true, method returns. If no block is supplied, it will block until it finds at least one light.
@@ -75,7 +75,7 @@ module LIFX
75
75
  #
76
76
  # You cannot nest `sync` calls, nor call synchronous methods inside a `sync` block.
77
77
  #
78
- # Due to messaging rate constraints, the amount of messages determine the delay before
78
+ # Due to messaging rate constraints, the amount of messages determine the delay before
79
79
  # the commands are executed. This method also assumes all the lights have the same time.
80
80
  # @example This example sets all the lights to a random colour at the same time.
81
81
  # client.sync do
@@ -128,7 +128,7 @@ module LIFX
128
128
 
129
129
  # Blocks until all messages have been sent to the gateways
130
130
  # @param timeout: [Numeric] When specified, flush will wait `timeout:` seconds before throwing `Timeout::Error`
131
- # @raise [Timeout::Error] if `timeout:` was exceeded while waiting for send queue to flush
131
+ # @raise [TimeoutError] if `timeout:` was exceeded while waiting for send queue to flush
132
132
  # @return [void]
133
133
  def flush(timeout: nil)
134
134
  context.flush(timeout: timeout)
@@ -90,7 +90,7 @@ module LIFX
90
90
  end
91
91
  end
92
92
  if timeout
93
- Timeout.timeout(timeout) do
93
+ Timeout.timeout(timeout, TimeoutError) do
94
94
  proc.call
95
95
  end
96
96
  else
@@ -332,6 +332,12 @@ module LIFX
332
332
  context.tags_for_device(self)
333
333
  end
334
334
 
335
+ # Returns whether the light is a gateway
336
+ # @api private
337
+ def gateway?
338
+ context.transport_manager.gateways.include?(self)
339
+ end
340
+
335
341
  # Returns a nice string representation of the Light
336
342
  # @return [String]
337
343
  def to_s
@@ -356,7 +362,9 @@ module LIFX
356
362
  end
357
363
 
358
364
  # An exception for when synchronous messages take too long to receive a response
359
- class MessageTimeout < StandardError; end
365
+ class MessageTimeout < TimeoutError
366
+ attr_accessor :device
367
+ end
360
368
 
361
369
  # Queues a message to be sent to the Light and waits for a response
362
370
  # @param payload [Protocol::Payload] the payload to send
@@ -381,10 +389,11 @@ module LIFX
381
389
  send_message(payload)
382
390
  end
383
391
  result
384
- rescue Timeout::Error
392
+ rescue TimeoutError
385
393
  backtrace = caller_locations(2).map { |c| c.to_s }
386
394
  caller_method = caller_locations(2, 1).first.label
387
395
  ex = MessageTimeout.new("#{caller_method}: Timeout exceeded waiting for response from #{self}")
396
+ ex.device = self
388
397
  ex.set_backtrace(backtrace)
389
398
  raise ex
390
399
  ensure
@@ -41,7 +41,7 @@ module LIFX
41
41
 
42
42
  # Attempts to make the light(s) pulse `color` and then back to its original color. Asynchronous.
43
43
  # @param color [Color] Color to pulse
44
- # @param duty_cycle: [Float] Percentage of a cycle the light(s) is set to `color`
44
+ # @param duty_cycle: [Float] Ratio of a cycle the light(s) is set to `color`
45
45
  # @param cycles: [Integer] Number of cycles
46
46
  # @param transient: [Boolean] If false, the light will remain at the color the waveform is at when it ends
47
47
  # @param period: [Integer] Number of seconds a cycle. Must be above 1.0 (?)
@@ -64,6 +64,7 @@ module LIFX
64
64
  # Attempts to make the light(s) transition to `color` and back in a smooth sine wave. Asynchronous.
65
65
  # @param color [Color] Color
66
66
  # @param cycles: [Integer] Number of cycles
67
+ # @param peak: [Float] Defines the peak point of the wave. Defaults to 0.5 which is a standard sine
67
68
  # @param transient: [Boolean] If false, the light will remain at the color the waveform is at when it ends
68
69
  # @param period: [Integer] Number of seconds a cycle. Must be above 1.0 (?)
69
70
  # @param stream: [Integer] Unused
@@ -71,11 +72,12 @@ module LIFX
71
72
  # @note Marked as private pending bug fixes in firmware
72
73
  def sine(color, cycles: 1,
73
74
  period: 1.0,
75
+ peak: 0.5,
74
76
  transient: true,
75
77
  stream: 0)
76
78
  set_waveform(color, waveform: Protocol::Light::Waveform::SINE,
77
79
  cycles: cycles,
78
- duty_cycle: 0,
80
+ duty_cycle: peak,
79
81
  stream: stream,
80
82
  transient: transient,
81
83
  period: period)
@@ -140,7 +142,7 @@ module LIFX
140
142
 
141
143
  # Attempts to set the power state to `state` asynchronously.
142
144
  # This method cannot guarantee the message was received.
143
- # @param state [:on, :off]
145
+ # @param state [:on, :off]
144
146
  # @return [Light, LightCollection] self for chaining
145
147
  def set_power(state)
146
148
  level = case state
@@ -38,8 +38,8 @@ module LIFX
38
38
  @transport_manager.discover
39
39
  end
40
40
 
41
- def refresh
42
- @routing_manager.refresh
41
+ def refresh(force: true)
42
+ @routing_manager.refresh(force: force)
43
43
  end
44
44
 
45
45
  def reset!
@@ -86,9 +86,10 @@ module LIFX
86
86
  # Synchronize asynchronous set_color, set_waveform and set_power messages to multiple devices.
87
87
  # You cannot use synchronous methods in the block
88
88
  # @note This is alpha
89
+ # @param delay: [Float] The delay to add to sync commands when dealing with latency.
89
90
  # @yield Block to synchronize commands in
90
91
  # @return [Float] Delay before messages are executed
91
- def sync(&block)
92
+ def sync(delay: 0, &block)
92
93
  if within_sync?
93
94
  raise "You cannot nest sync"
94
95
  end
@@ -106,7 +107,7 @@ module LIFX
106
107
  time = light && light.time
107
108
  end
108
109
 
109
- delay = (messages.count + 1) * (1.0 / @transport_manager.message_rate)
110
+ delay += (messages.count + 1) * (1.0 / @transport_manager.message_rate)
110
111
  at_time = ((time.to_f + delay) * 1_000_000_000).to_i
111
112
  messages.each do |m|
112
113
  m.at_time = at_time
@@ -8,7 +8,7 @@ module LIFX
8
8
 
9
9
  def add_observer(obj, type, &callback)
10
10
  if !callback_type_exists?(type)
11
- raise ObserverCallbackNotFound.new
11
+ raise ObserverCallbackNotFound.new("Callback #{type} not found in #{observer_callback_definition.keys}")
12
12
  end
13
13
  if !callback_has_required_keys?(type, callback)
14
14
  raise ObserverCallbackMismatch.new
@@ -25,6 +25,9 @@ module LIFX
25
25
  end
26
26
 
27
27
  def notify_observers(type, **args)
28
+ if !callback_type_exists?(type)
29
+ raise ObserverCallbackNotFound.new("Callback #{type} not found in #{observer_callback_definition.keys}")
30
+ end
28
31
  observers[type].each do |_, callback|
29
32
  callback.call(**args)
30
33
  end
@@ -96,10 +96,10 @@ module LIFX
96
96
  end
97
97
  end
98
98
 
99
- MINIMUM_REFRESH_INTERVAL = 20
100
- def refresh
99
+ MINIMUM_REFRESH_INTERVAL = 15
100
+ def refresh(force: false)
101
101
  @routing_table.site_ids.each do |site_id|
102
- next if (seen = @last_refresh_seen[site_id]) && Time.now - seen < MINIMUM_REFRESH_INTERVAL
102
+ next if (seen = @last_refresh_seen[site_id]) && Time.now - seen < MINIMUM_REFRESH_INTERVAL && !force
103
103
  refresh_site(site_id)
104
104
  end
105
105
  end
@@ -30,7 +30,8 @@ module LIFX
30
30
 
31
31
  def observer_callback_definition
32
32
  {
33
- message_received: -> (message: nil, ip: nil, transport: nil) {}
33
+ message_received: -> (message: nil, ip: nil, transport: nil) {},
34
+ disconnected: -> {}
34
35
  }
35
36
  end
36
37
  end
@@ -80,6 +80,7 @@ module LIFX
80
80
  end
81
81
  end
82
82
  broadcast_to_peers(message)
83
+ @message_rate_timer.reset
83
84
  end
84
85
 
85
86
  def on_network?
@@ -112,23 +113,29 @@ module LIFX
112
113
  end
113
114
 
114
115
  def gateways
115
- @sites.values.map(&:gateways)
116
+ @sites.values.map(&:gateways).map(&:keys).flatten.uniq.map { |id| context.lights.with_id(id) }.compact
116
117
  end
117
118
 
118
119
  def gateway_connections
119
- gateways.map(&:values).flatten
120
+ @sites.values.map(&:gateways).map(&:values).flatten
121
+ end
122
+
123
+ def message_rate
124
+ @message_rate || DEFAULT_MESSAGE_RATE
120
125
  end
121
126
 
122
127
  protected
123
128
 
124
129
  def initialize_periodic_refresh
125
130
  timers.every(10) do
126
- context.refresh
131
+ context.refresh(force: false)
127
132
  end
128
133
  end
129
134
 
135
+ DEFAULT_MESSAGE_RATE = 5 # per second
136
+ MESSAGE_RATE_1_2 = 20
130
137
  def initialize_message_rate_updater
131
- timers.every(5) do
138
+ @message_rate_timer = timers.every(2) do
132
139
  missing_mesh_firmware = context.lights.alive.select { |l| l.mesh_firmware(fetch: false).nil? }
133
140
  if missing_mesh_firmware.count > 10
134
141
  context.send_message(target: Target.new(broadcast: true), payload: Protocol::Device::GetMeshFirmware.new)
@@ -138,7 +145,7 @@ module LIFX
138
145
  @message_rate = context.lights.alive.all? do |light|
139
146
  m = light.mesh_firmware(fetch: false)
140
147
  m && m >= '1.2'
141
- end ? 20 : 5
148
+ end ? MESSAGE_RATE_1_2 : DEFAULT_MESSAGE_RATE
142
149
  gateway_connections.each do |connection|
143
150
  connection.set_message_rate(@message_rate)
144
151
  end
@@ -146,11 +153,6 @@ module LIFX
146
153
  end
147
154
  end
148
155
 
149
- DEFAULT_MESSAGING_RATE = 5 # per second
150
- def message_rate
151
- @message_rate || 5
152
- end
153
-
154
156
  def initialize_transports
155
157
  create_broadcast_transport
156
158
  create_peer_transport
@@ -1,7 +1,7 @@
1
1
  module LIFX
2
2
  # @private
3
3
  module Utilities
4
- def try_until(condition_proc, timeout_exception: Timeout::Error,
4
+ def try_until(condition_proc, timeout_exception: TimeoutError,
5
5
  timeout: 3,
6
6
  condition_interval: 0.1,
7
7
  action_interval: 0.5,
@@ -1,3 +1,3 @@
1
1
  module LIFX
2
- VERSION = "0.4.8"
2
+ VERSION = "0.4.10"
3
3
  end
@@ -14,7 +14,7 @@ module LIFX
14
14
  it 'does not send if there is no available connection' do
15
15
  expect(gateway).to_not receive(:actually_write)
16
16
  gateway.write(message)
17
- expect { gateway.flush(timeout: 0.5) }.to raise_error(Timeout::Error)
17
+ expect { gateway.flush(timeout: 0.5) }.to raise_error(TimeoutError)
18
18
  end
19
19
 
20
20
  it 'pushes message back into queue if unable to write' do
@@ -16,7 +16,7 @@ shared_context 'integration', integration: true do
16
16
  c.discover! do
17
17
  c.tags.include?('_Test') && c.lights.with_tag('_Test').count > 0
18
18
  end
19
- rescue Timeout::Error
19
+ rescue DiscoveryTimeout
20
20
  raise "Could not find any lights with tag _Test in #{c.lights.inspect}"
21
21
  end
22
22
  c
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lifx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.8
4
+ version: 0.4.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jack Chen (chendo)
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-05 00:00:00.000000000 Z
11
+ date: 2014-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bindata
@@ -215,4 +215,3 @@ test_files:
215
215
  - spec/spec_helper.rb
216
216
  - spec/transport/udp_spec.rb
217
217
  - spec/transport_spec.rb
218
- has_rdoc: