lifx 0.4.5 → 0.4.6.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e413317b0ac40abc57bdf3699b8373451b86614c
4
- data.tar.gz: 39852a66321e7352078e56e4b8073c4cb98f067b
3
+ metadata.gz: a0d7ac636c1a3c658b1859dbf7074fd845cd41e1
4
+ data.tar.gz: 112e36f614f01183d57d322d83d07807b58fe398
5
5
  SHA512:
6
- metadata.gz: c75b51ea1267b7605c5bcaf74bc0daf4c298143aed8e7155f9969231fdc7658ed3ec018bcec9cea0a483fc0b327366db72ab7f2fe17a8ac1f45a7f49efc8eef7
7
- data.tar.gz: 7b1b3274a505d44b2e793e1a616058bb4feb96054ea39ebbaf320c79e873f3550686c2a6c35ece2ec6cc0d99dd266fd96bf2b01fdf6e94c3b91b21b42dd03706
6
+ metadata.gz: 3693b61a7c84222e379dd535e6ccdb80f5e5381f4ac4f0893c0821f8c5ef4a269b19e0f76837158e1a4b5b42bff4b22c988e4b0d0ddf62f749b770a15eaacd90
7
+ data.tar.gz: 48a3b388801194eccccf878097c8f60ae83bab085e2e6dfa3d291baa6fb31780dcc6dacfd1b9f86214d7cda0e7a7e71e25ac66cae89af088e291a8718e727da2
data/CHANGES.md CHANGED
@@ -1,14 +1,26 @@
1
- # 0.4.5
1
+ ### 0.4.6.1
2
+
3
+ - Fix `Time.parse` issue
4
+
5
+ ### 0.4.6
6
+
7
+ - `Color#==` has been renamed to `Color#similar_to?`
8
+ - Broadcast IP configurable through `LIFX::Config.broadcast_ip`
9
+ - Removed Yell gem. Use stdlib Logger instead
10
+ - Uninitialized lights no longer shows up in `Client#lights`
11
+ - Handle Rubies that don't have IPv6 enabled
12
+
13
+ ### 0.4.5
2
14
 
3
15
  - Now supports Ruby 2.0
4
16
  - Light#label can be nil
5
17
  - Light#set_power and Light#set_power! now take :on and :off rather than magic number
6
18
  - Use timers 1.x so no compilation is required
7
19
 
8
- # 0.4.4
20
+ ### 0.4.4
9
21
 
10
22
  - Fix SO_REUSEPORT issue on older Linux kernels.
11
23
 
12
- # 0.4.3
24
+ ### 0.4.3
13
25
 
14
26
  - Initial public release
data/README.md CHANGED
@@ -13,8 +13,7 @@ This gem is in an early beta state. Expect breaking API changes.
13
13
 
14
14
  ## Requirements
15
15
 
16
- * Ruby 2.1.1
17
- * Bundler
16
+ * Ruby 2.0+
18
17
  * Tested on OS X Mavericks, but should work other *nix platforms. Please file an issue if you have any problems.
19
18
 
20
19
  ## Installation
@@ -34,7 +33,7 @@ $ bundle
34
33
  Or install the gem with:
35
34
 
36
35
  ```shell
37
- gem install lifx
36
+ gem install lifx # Add sudo if required.
38
37
  ```
39
38
 
40
39
  ## Usage
data/Rakefile CHANGED
@@ -10,7 +10,7 @@ task :console do
10
10
  require "lifx"
11
11
  require "pry"
12
12
  if ENV['DEBUG']
13
- LIFX::Config.logger = Yell.new(STDERR)
13
+ LIFX::Config.logger.level = Logger::DEBUG
14
14
  end
15
15
  LIFX::Client.lan.discover! do |c|
16
16
  c.lights.count > 0
@@ -27,7 +27,7 @@ end
27
27
 
28
28
  begin
29
29
  light_udp = LIFX::Transport::UDP.new('0.0.0.0', 56700)
30
- light_udp.add_observer(self) do |message:, ip:, transport:|
30
+ light_udp.add_observer(self) do |message: nil, ip: nil, transport: nil|
31
31
  if matchers.all? { |m| message.to_s =~ m }
32
32
  puts "#{Time.now.iso8601(5)} BROADCAST: #{ip} #{message}"
33
33
  end
@@ -35,7 +35,7 @@ begin
35
35
  light_udp.listen
36
36
 
37
37
  peer_udp = LIFX::Transport::UDP.new('0.0.0.0', 56750)
38
- peer_udp.add_observer(self) do |message:, ip:, transport:|
38
+ peer_udp.add_observer(self) do |message: nil, ip: nil, transport: nil|
39
39
  if matchers.all? { |m| message.to_s =~ m }
40
40
  puts "#{Time.now.iso8601(5)} PEER: #{ip} #{message}"
41
41
  end
@@ -17,5 +17,5 @@ require "lifx/config"
17
17
  require "lifx/client"
18
18
 
19
19
  module LIFX
20
-
20
+ NULL_SITE_ID = "000000000000"
21
21
  end
@@ -1,6 +1,5 @@
1
1
  require 'socket'
2
2
  require 'timeout'
3
- require 'yell'
4
3
 
5
4
  require 'lifx/network_context'
6
5
  require 'lifx/light_collection'
@@ -57,8 +56,10 @@ module LIFX
57
56
  try_until -> { block.arity == 1 ? block.call(self) : block.call },
58
57
  timeout: timeout,
59
58
  timeout_exception: DiscoveryTimeout,
60
- condition_interval: condition_interval do
59
+ condition_interval: condition_interval,
60
+ action_interval: 1 do
61
61
  discover
62
+ refresh
62
63
  end
63
64
  self
64
65
  end
@@ -174,16 +174,23 @@ module LIFX
174
174
  [hue, saturation, brightness, kelvin]
175
175
  end
176
176
 
177
- EQUALITY_THRESHOLD = 0.001 # 0.1% variance
177
+ DEFAULT_SIMILAR_THRESHOLD = 0.001 # 0.1% variance
178
178
  # Checks if colours are equal to 0.1% variance
179
179
  # @param other [Color] Color to compare to
180
+ # @param threshold: [Float] 0..1. Threshold to consider it similar
180
181
  # @return [Boolean]
181
- def ==(other)
182
+ def similar_to?(other, threshold: DEFAULT_SIMILAR_THRESHOLD)
182
183
  return false unless other.is_a?(Color)
183
184
  conditions = []
184
- conditions << ((hue - other.hue).abs < (EQUALITY_THRESHOLD * 360))
185
- conditions << ((saturation - other.saturation).abs < EQUALITY_THRESHOLD)
186
- conditions << ((brightness - other.brightness).abs < EQUALITY_THRESHOLD)
185
+
186
+ conditions << (((hue - other.hue).abs < (threshold * 360)) || begin
187
+ # FIXME: Surely there's a better way.
188
+ hues = [hue, other.hue].sort
189
+ hues[0] += 360
190
+ (hues[0] - hues[1]).abs < (threshold * 360)
191
+ end)
192
+ conditions << ((saturation - other.saturation).abs < threshold)
193
+ conditions << ((brightness - other.brightness).abs < threshold)
187
194
  conditions.all?
188
195
  end
189
196
  end
@@ -1,12 +1,13 @@
1
1
  require 'configatron/core'
2
- require 'yell'
2
+ require 'logger'
3
3
  module LIFX
4
4
  Config = Configatron::Store.new
5
5
 
6
6
  Config.default_duration = 1
7
+ Config.broadcast_ip = '255.255.255.255'
7
8
  Config.allowed_transports = [:udp, :tcp]
8
- Config.logger = Yell.new do |logger|
9
- logger.level = 'gte.warn'
10
- logger.adapter STDERR, format: '%d [%5L] %p/%t : %m'
9
+ Config.log_invalid_messages = false
10
+ Config.logger = Logger.new(STDERR).tap do |logger|
11
+ logger.level = Logger::WARN
11
12
  end
12
13
  end
@@ -1,3 +1,5 @@
1
+ require 'time'
2
+
1
3
  module LIFX
2
4
  # LIFX::Firmware handles decoding firmware payloads
3
5
  # @private
@@ -46,7 +46,6 @@ module LIFX
46
46
  hook.call(payload)
47
47
  end
48
48
  @message_signal.broadcast
49
- seen!
50
49
  end
51
50
 
52
51
  # Adds a block to be run when a payload of class `payload_class` is received
@@ -354,17 +353,19 @@ module LIFX
354
353
  # @return [Light] returns self for chaining
355
354
  def send_message(payload, acknowledge: true)
356
355
  context.send_message(target: Target.new(device_id: id, site_id: @site_id), payload: payload, acknowledge: acknowledge)
357
- self
358
356
  end
359
357
 
358
+ # An exception for when synchronous messages take too long to receive a response
359
+ class MessageTimeout < StandardError; end
360
+
360
361
  # Queues a message to be sent to the Light and waits for a response
361
362
  # @param payload [Protocol::Payload] the payload to send
362
363
  # @param wait_for: [Class] the payload class to wait for
363
364
  # @param wait_timeout: [Numeric] wait timeout
364
365
  # @param block: [Proc] the block that is executed when the expected `wait_for` payload comes back. If the return value is false or nil, it will try to send the message again.
365
366
  # @return [Object] the truthy result of `block` is returned.
366
- # @raise [Timeout::Error]
367
- def send_message!(payload, wait_for: wait_for, wait_timeout: 3, timeout_exception: Timeout::Error, &block)
367
+ # @raise [MessageTimeout] if the device doesn't respond in time
368
+ def send_message!(payload, wait_for: wait_for, wait_timeout: 3, &block)
368
369
  if Thread.current[:sync_enabled]
369
370
  raise "Cannot use synchronous methods inside a sync block"
370
371
  end
@@ -376,10 +377,16 @@ module LIFX
376
377
  result = block.call(payload)
377
378
  }
378
379
  add_hook(wait_for, proc)
379
- try_until -> { result }, signal: @message_signal, timeout_exception: timeout_exception do
380
+ try_until -> { result }, signal: @message_signal do
380
381
  send_message(payload)
381
382
  end
382
383
  result
384
+ rescue Timeout::Error
385
+ backtrace = caller_locations(2).map { |c| c.to_s }
386
+ caller_method = caller_locations(2, 1).first.label
387
+ ex = MessageTimeout.new("#{caller_method}: Timeout exceeded waiting for response from #{self}")
388
+ ex.set_backtrace(backtrace)
389
+ raise ex
383
390
  ensure
384
391
  remove_hook(wait_for, proc)
385
392
  end
@@ -390,6 +397,7 @@ module LIFX
390
397
  def add_hooks
391
398
  add_hook(Protocol::Device::StateLabel) do |payload|
392
399
  @label = payload.label.to_s
400
+ seen!
393
401
  end
394
402
 
395
403
  add_hook(Protocol::Light::State) do |payload|
@@ -397,22 +405,27 @@ module LIFX
397
405
  @color = Color.from_struct(payload.color.snapshot)
398
406
  @power = payload.power.to_i
399
407
  @tags_field = payload.tags
408
+ seen!
400
409
  end
401
410
 
402
411
  add_hook(Protocol::Device::StateTags) do |payload|
403
412
  @tags_field = payload.tags
413
+ seen!
404
414
  end
405
415
 
406
416
  add_hook(Protocol::Device::StatePower) do |payload|
407
417
  @power = payload.level.to_i
418
+ seen!
408
419
  end
409
420
 
410
421
  add_hook(Protocol::Device::StateMeshFirmware) do |payload|
411
422
  @mesh_firmware = Firmware.new(payload)
423
+ seen!
412
424
  end
413
425
 
414
426
  add_hook(Protocol::Device::StateWifiFirmware) do |payload|
415
427
  @wifi_firmware = Firmware.new(payload)
428
+ seen!
416
429
  end
417
430
  end
418
431
  end
@@ -22,8 +22,6 @@ module LIFX
22
22
  PROTOCOL_VERSION = 1024
23
23
 
24
24
  class << self
25
- attr_accessor :log_invalid_messages
26
-
27
25
  def unpack(data)
28
26
  raise InvalidFrame if data.length < 2
29
27
 
@@ -35,7 +33,7 @@ module LIFX
35
33
  path = ProtocolPath.new(raw_site: message.raw_site, raw_target: message.raw_target, tagged: message.tagged)
36
34
  payload_class = message_type_for_id(message.type.snapshot)
37
35
  if payload_class.nil?
38
- if self.log_invalid_messages
36
+ if Config.log_invalid_messages
39
37
  logger.error("Message.unpack: Unrecognised payload ID: #{message.type}")
40
38
  logger.error("Message.unpack: Message: #{message}")
41
39
  end
@@ -48,7 +46,7 @@ module LIFX
48
46
  if message.raw_site == "\x00" * 6
49
47
  logger.info("Message.unpack: Ignoring malformed message from virgin bulb")
50
48
  else
51
- if self.log_invalid_messages
49
+ if Config.log_invalid_messages
52
50
  logger.error("Message.unpack: Exception while unpacking payload of type #{payload_class}: #{ex}")
53
51
  logger.error("Message.unpack: Data: #{data.inspect}")
54
52
  end
@@ -56,7 +54,7 @@ module LIFX
56
54
  end
57
55
  new(path, message, payload)
58
56
  rescue => ex
59
- if self.log_invalid_messages
57
+ if Config.log_invalid_messages
60
58
  logger.debug("Message.unpack: Exception while unpacking #{data.inspect}")
61
59
  logger.debug("Message.unpack: #{ex} - #{ex.backtrace.join("\n")}")
62
60
  end
@@ -121,6 +121,7 @@ module LIFX
121
121
  end
122
122
 
123
123
  def register_device(device)
124
+ return if device.site_id == NULL_SITE_ID
124
125
  device_id = device.id
125
126
  @devices[device_id] = device # What happens when there's already one registered?
126
127
  end
@@ -170,6 +171,7 @@ module LIFX
170
171
  register_device(device)
171
172
  end
172
173
  device = @devices[message.device_id]
174
+ return if !device # Virgin bulb
173
175
  device.handle_message(message, ip, transport)
174
176
  end
175
177
  end
@@ -2,6 +2,9 @@ module LIFX
2
2
  # @api private
3
3
  module Protocol
4
4
  class Payload < BinData::Record
5
+ def to_s
6
+ "#<#{self.class} #{super}>"
7
+ end
5
8
  end
6
9
  end
7
10
  end
@@ -54,6 +54,7 @@ module LIFX
54
54
  end
55
55
 
56
56
  def update_from_message(message)
57
+ return if message.site_id == NULL_SITE_ID
57
58
  if message.tagged?
58
59
  case message.payload
59
60
  when Protocol::Light::Get
@@ -52,8 +52,9 @@ module LIFX
52
52
 
53
53
  notify_observers(message: message, ip: host, transport: self)
54
54
  rescue Message::UnpackError
55
- if !@ignore_unpackable_messages
56
- logger.warn("#{self}: Exception occured - #{ex}")
55
+ if Config.log_invalid_messages
56
+ logger.info("#{self}: Exception occured while decoding message - #{ex}")
57
+ logger.info("Data: #{data.inspect}")
57
58
  end
58
59
  rescue => ex
59
60
  logger.warn("#{self}: Exception occured in #listen - #{ex}")
@@ -41,7 +41,7 @@ module LIFX
41
41
  message = Message.unpack(bytes)
42
42
  notify_observers(message: message, ip: ip, transport: self)
43
43
  rescue Message::UnpackError
44
- if !@ignore_unpackable_messages
44
+ if Config.log_invalid_messages
45
45
  logger.warn("#{self}: Unrecognised bytes: #{bytes.bytes.map { |b| '%02x ' % b }.join}")
46
46
  end
47
47
  end
@@ -3,7 +3,7 @@ require 'lifx/site'
3
3
  module LIFX
4
4
  module TransportManager
5
5
  class LAN < Base
6
- def initialize(bind_ip: '0.0.0.0', send_ip: '255.255.255.255', port: 56700, peer_port: 56750)
6
+ def initialize(bind_ip: '0.0.0.0', send_ip: Config.broadcast_ip, port: 56700, peer_port: 56750)
7
7
  super
8
8
  @bind_ip = bind_ip
9
9
  @send_ip = send_ip
@@ -76,7 +76,7 @@ module LIFX
76
76
  else # Ruby 2.0
77
77
  Socket.ip_address_list.any? do |addrinfo|
78
78
  # Not entirely sure how to check if on a LAN with IPv6
79
- addrinfo.ipv4_private? || addrinfo.ipv6_unique_local?
79
+ addrinfo.ipv4_private? || (addrinfo.respond_to?(:ipv6_unique_local?) && addrinfo.ipv6_unique_local?)
80
80
  end
81
81
  end
82
82
  end
@@ -128,6 +128,7 @@ module LIFX
128
128
  end
129
129
 
130
130
  def handle_broadcast_message(message, ip, transport)
131
+ return if message.nil?
131
132
  payload = message.payload
132
133
  case payload
133
134
  when Protocol::Device::StatePanGateway
@@ -1,3 +1,3 @@
1
1
  module LIFX
2
- VERSION = "0.4.5"
2
+ VERSION = "0.4.6.1"
3
3
  end
@@ -20,7 +20,6 @@ Gem::Specification.new do |spec|
20
20
  spec.required_ruby_version = ">= 2.0"
21
21
 
22
22
  spec.add_dependency "bindata", "~> 2.0"
23
- spec.add_dependency "yell", "~> 2.0"
24
23
  spec.add_dependency "timers", "~> 1.0"
25
24
  spec.add_dependency "configatron", "~> 3.0"
26
25
  spec.add_development_dependency "bundler", "~> 1.3"
@@ -22,5 +22,20 @@ module LIFX
22
22
  it_behaves_like 'translating color', 'black', [0, 0, 0], [0, 0, 0]
23
23
  end
24
24
  end
25
+
26
+ describe '#similar_to?' do
27
+ it 'matches reds on on either end of hue spectrums' do
28
+ expect(Color.hsb(359.9, 1, 1)).to be_similar_to(Color.hsb(0, 1, 1))
29
+ expect(Color.hsb(0, 1, 1)).to be_similar_to(Color.hsb(359.9, 1, 1))
30
+ end
31
+
32
+ it 'does not match different colours' do
33
+ expect(Color.hsb(120, 1, 1)).to_not be_similar_to(Color.hsb(0, 1, 1))
34
+ end
35
+
36
+ it 'matches similar colours' do
37
+ expect(Color.hsb(120, 1, 1)).to be_similar_to(Color.hsb(120.3, 1, 1))
38
+ end
39
+ end
25
40
  end
26
41
  end
@@ -27,7 +27,7 @@ module LIFX
27
27
  light.set_color(color, duration: 0)
28
28
  sleep 1
29
29
  light.refresh
30
- wait { expect(light.color).to eq color }
30
+ wait { expect(light.color).to be_similar_to(color) }
31
31
  end
32
32
  end
33
33
 
@@ -16,7 +16,7 @@ module LIFX
16
16
  # It also returns the current light state rather than the
17
17
  # final state
18
18
  light.refresh
19
- wait { expect(light.color).to eq color }
19
+ wait { expect(light.color).to be_similar_to(color) }
20
20
 
21
21
  light.remove_tag('Foo')
22
22
  wait { expect(light.tags).not_to include('Foo') }
@@ -1,39 +1,42 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe LIFX::Transport::UDP, integration: true do
4
- subject(:udp) { LIFX::Transport::UDP.new(host, port) }
3
+ module LIFX
4
+ describe Transport::UDP, integration: true do
5
+ subject(:udp) { Transport::UDP.new(host, port) }
5
6
 
6
- let(:host) { 'localhost' }
7
- let(:message) { double }
8
- let(:port) { 45_828 }
7
+ let(:host) { 'localhost' }
8
+ let(:message) { double }
9
+ let(:port) { 45_828 }
9
10
 
10
- describe '#write' do
11
- let(:payload) { double }
11
+ describe '#write' do
12
+ let(:payload) { double }
12
13
 
13
- it 'writes a Message to specified host' do
14
- expect(message).to receive(:pack).and_return(payload)
15
- expect_any_instance_of(UDPSocket).to receive(:send)
16
- .with(payload, 0, host, port)
17
- udp.write(message)
14
+ it 'writes a Message to specified host' do
15
+ expect(message).to receive(:pack).and_return(payload)
16
+ expect_any_instance_of(UDPSocket).to receive(:send)
17
+ .with(payload, 0, host, port)
18
+ udp.write(message)
19
+ end
18
20
  end
19
- end
20
21
 
21
- describe '#listen' do
22
- let(:raw_message) { 'some binary data' }
23
- let(:socket) { UDPSocket.new }
24
-
25
- it 'listens to the specified socket data, unpacks it and notifies observers' do
26
- messages = []
27
- udp.add_observer(self) do |message: nil, ip: nil, transport: nil|
28
- messages << message
22
+ describe '#listen' do
23
+ let(:raw_message) { 'some binary data' }
24
+ let(:socket) { UDPSocket.new }
25
+ let(:messages) { [] }
26
+ before do
27
+ udp.add_observer(self) do |message: nil, ip: nil, transport: nil|
28
+ messages << message
29
+ end
30
+ udp.listen
29
31
  end
30
- udp.listen
31
32
 
32
- expect(LIFX::Message).to receive(:unpack)
33
- .with(raw_message)
34
- .and_return(message)
35
- socket.send(raw_message, 0, host, port)
36
- wait { expect(messages).to include(message) }
33
+ it 'listens to the specified socket data, unpacks it and notifies observers' do
34
+ expect(Message).to receive(:unpack)
35
+ .with(raw_message)
36
+ .and_return(message)
37
+ socket.send(raw_message, 0, host, port)
38
+ wait { expect(messages).to include(message) }
39
+ end
37
40
  end
38
41
  end
39
42
  end
metadata CHANGED
@@ -1,111 +1,97 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lifx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.4.6.1
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-03-28 00:00:00.000000000 Z
11
+ date: 2014-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bindata
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '2.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
25
- - !ruby/object:Gem::Version
26
- version: '2.0'
27
- - !ruby/object:Gem::Dependency
28
- name: yell
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ~>
32
- - !ruby/object:Gem::Version
33
- version: '2.0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ~>
24
+ - - "~>"
39
25
  - !ruby/object:Gem::Version
40
26
  version: '2.0'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: timers
43
29
  requirement: !ruby/object:Gem::Requirement
44
30
  requirements:
45
- - - ~>
31
+ - - "~>"
46
32
  - !ruby/object:Gem::Version
47
33
  version: '1.0'
48
34
  type: :runtime
49
35
  prerelease: false
50
36
  version_requirements: !ruby/object:Gem::Requirement
51
37
  requirements:
52
- - - ~>
38
+ - - "~>"
53
39
  - !ruby/object:Gem::Version
54
40
  version: '1.0'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: configatron
57
43
  requirement: !ruby/object:Gem::Requirement
58
44
  requirements:
59
- - - ~>
45
+ - - "~>"
60
46
  - !ruby/object:Gem::Version
61
47
  version: '3.0'
62
48
  type: :runtime
63
49
  prerelease: false
64
50
  version_requirements: !ruby/object:Gem::Requirement
65
51
  requirements:
66
- - - ~>
52
+ - - "~>"
67
53
  - !ruby/object:Gem::Version
68
54
  version: '3.0'
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: bundler
71
57
  requirement: !ruby/object:Gem::Requirement
72
58
  requirements:
73
- - - ~>
59
+ - - "~>"
74
60
  - !ruby/object:Gem::Version
75
61
  version: '1.3'
76
62
  type: :development
77
63
  prerelease: false
78
64
  version_requirements: !ruby/object:Gem::Requirement
79
65
  requirements:
80
- - - ~>
66
+ - - "~>"
81
67
  - !ruby/object:Gem::Version
82
68
  version: '1.3'
83
69
  - !ruby/object:Gem::Dependency
84
70
  name: rake
85
71
  requirement: !ruby/object:Gem::Requirement
86
72
  requirements:
87
- - - ~>
73
+ - - "~>"
88
74
  - !ruby/object:Gem::Version
89
75
  version: '10.1'
90
76
  type: :development
91
77
  prerelease: false
92
78
  version_requirements: !ruby/object:Gem::Requirement
93
79
  requirements:
94
- - - ~>
80
+ - - "~>"
95
81
  - !ruby/object:Gem::Version
96
82
  version: '10.1'
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: rspec
99
85
  requirement: !ruby/object:Gem::Requirement
100
86
  requirements:
101
- - - ~>
87
+ - - "~>"
102
88
  - !ruby/object:Gem::Version
103
89
  version: '2.14'
104
90
  type: :development
105
91
  prerelease: false
106
92
  version_requirements: !ruby/object:Gem::Requirement
107
93
  requirements:
108
- - - ~>
94
+ - - "~>"
109
95
  - !ruby/object:Gem::Version
110
96
  version: '2.14'
111
97
  description: A Ruby gem that allows easy interaction with LIFX devices.
@@ -116,9 +102,9 @@ executables:
116
102
  extensions: []
117
103
  extra_rdoc_files: []
118
104
  files:
119
- - .gitignore
120
- - .travis.yml
121
- - .yardopts
105
+ - ".gitignore"
106
+ - ".travis.yml"
107
+ - ".yardopts"
122
108
  - CHANGES.md
123
109
  - Gemfile
124
110
  - LICENSE.txt
@@ -197,17 +183,17 @@ require_paths:
197
183
  - lib
198
184
  required_ruby_version: !ruby/object:Gem::Requirement
199
185
  requirements:
200
- - - '>='
186
+ - - ">="
201
187
  - !ruby/object:Gem::Version
202
188
  version: '2.0'
203
189
  required_rubygems_version: !ruby/object:Gem::Requirement
204
190
  requirements:
205
- - - '>='
191
+ - - ">="
206
192
  - !ruby/object:Gem::Version
207
193
  version: '0'
208
194
  requirements: []
209
195
  rubyforge_project:
210
- rubygems_version: 2.0.3
196
+ rubygems_version: 2.2.2
211
197
  signing_key:
212
198
  specification_version: 4
213
199
  summary: A Ruby gem that allows easy interaction with LIFX devices. Handles discovery,