lifx 0.0.1 → 0.4.0
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 +4 -4
- data/.yardopts +1 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +1 -1
- data/README.md +71 -13
- data/Rakefile +12 -0
- data/bin/lifx-console +15 -0
- data/bin/lifx-snoop +50 -0
- data/examples/auto-off/Gemfile +3 -0
- data/examples/auto-off/auto-off.rb +35 -0
- data/examples/identify/Gemfile +3 -0
- data/examples/identify/identify.rb +70 -0
- data/examples/travis-build-light/Gemfile +4 -0
- data/examples/travis-build-light/build-light.rb +57 -0
- data/lib/bindata_ext/bool.rb +29 -0
- data/lib/bindata_ext/record.rb +11 -0
- data/lib/lifx/client.rb +136 -0
- data/lib/lifx/color.rb +190 -0
- data/lib/lifx/config.rb +12 -0
- data/lib/lifx/firmware.rb +55 -0
- data/lib/lifx/gateway_connection.rb +177 -0
- data/lib/lifx/light.rb +406 -0
- data/lib/lifx/light_collection.rb +105 -0
- data/lib/lifx/light_target.rb +189 -0
- data/lib/lifx/logging.rb +11 -0
- data/lib/lifx/message.rb +166 -0
- data/lib/lifx/network_context.rb +200 -0
- data/lib/lifx/observable.rb +46 -0
- data/lib/lifx/protocol/address.rb +21 -0
- data/lib/lifx/protocol/device.rb +225 -0
- data/lib/lifx/protocol/header.rb +24 -0
- data/lib/lifx/protocol/light.rb +110 -0
- data/lib/lifx/protocol/message.rb +17 -0
- data/lib/lifx/protocol/metadata.rb +21 -0
- data/lib/lifx/protocol/payload.rb +7 -0
- data/lib/lifx/protocol/sensor.rb +29 -0
- data/lib/lifx/protocol/type.rb +134 -0
- data/lib/lifx/protocol/wan.rb +50 -0
- data/lib/lifx/protocol/wifi.rb +76 -0
- data/lib/lifx/protocol_path.rb +84 -0
- data/lib/lifx/routing_manager.rb +110 -0
- data/lib/lifx/routing_table.rb +33 -0
- data/lib/lifx/seen.rb +15 -0
- data/lib/lifx/site.rb +89 -0
- data/lib/lifx/tag_manager.rb +105 -0
- data/lib/lifx/tag_table.rb +47 -0
- data/lib/lifx/target.rb +23 -0
- data/lib/lifx/timers.rb +18 -0
- data/lib/lifx/transport/tcp.rb +81 -0
- data/lib/lifx/transport/udp.rb +67 -0
- data/lib/lifx/transport.rb +41 -0
- data/lib/lifx/transport_manager/lan.rb +140 -0
- data/lib/lifx/transport_manager.rb +34 -0
- data/lib/lifx/utilities.rb +33 -0
- data/lib/lifx/version.rb +1 -1
- data/lib/lifx.rb +15 -1
- data/lifx.gemspec +11 -7
- data/spec/color_spec.rb +45 -0
- data/spec/gateway_connection_spec.rb +32 -0
- data/spec/integration/client_spec.rb +40 -0
- data/spec/integration/light_spec.rb +43 -0
- data/spec/integration/tags_spec.rb +31 -0
- data/spec/message_spec.rb +163 -0
- data/spec/protocol_path_spec.rb +109 -0
- data/spec/routing_manager_spec.rb +22 -0
- data/spec/spec_helper.rb +52 -0
- data/spec/transport/udp_spec.rb +38 -0
- data/spec/transport_spec.rb +14 -0
- metadata +143 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 357ce53a9c5e511833c6917f09d72396d203df38
|
4
|
+
data.tar.gz: 135ecdc739e64aaf4615702eedb273f9c3cb570e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d2ad759de8697cf02de2914782742315be5c545678bae5b848e9dfeb13acc945823b78a1145f82df308e2dec308c31ec01aae6601c67262632cf64f36f56867
|
7
|
+
data.tar.gz: 212a318bab27a3f967971364e8384daa82842334a3b8f9327de66c12e3e01309b9b2d015f9c650dea8e0e91ea1cbf63a7ed3b2e722fc47186889b21f908506a4
|
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--markup markdown
|
data/Gemfile
CHANGED
@@ -1,4 +1,14 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
+
group :development do
|
4
|
+
gem 'redcarpet'
|
5
|
+
gem 'erubis'
|
6
|
+
gem 'ruby-prof'
|
7
|
+
gem 'pry-byebug'
|
8
|
+
gem 'pry-rescue'
|
9
|
+
gem 'pry-stack_explorer'
|
10
|
+
gem 'yard'
|
11
|
+
end
|
12
|
+
|
3
13
|
# Specify your gem's dependencies in lifx.gemspec
|
4
14
|
gemspec
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,29 +1,87 @@
|
|
1
1
|
# LIFX
|
2
2
|
|
3
|
-
|
3
|
+
This gem allows you to control your [LIFX](http://lifx.co) lights.
|
4
|
+
|
5
|
+
It handles discovery, gateway connections, tags, and provides a object-based API
|
6
|
+
for talking to Lights.
|
7
|
+
|
8
|
+
Due to the nature of the current protocol, some methods are asynchronous.
|
9
|
+
|
10
|
+
This gem is in an early beta state. Expect breaking API changes.
|
11
|
+
|
12
|
+
## Requirements
|
13
|
+
|
14
|
+
* Ruby 2.1.1
|
15
|
+
* Bundler
|
4
16
|
|
5
17
|
## Installation
|
6
18
|
|
7
19
|
Add this line to your application's Gemfile:
|
8
20
|
|
9
|
-
|
21
|
+
```ruby
|
22
|
+
gem 'lifx', git: "git@github.com:LIFX/lifx-gem.git"
|
23
|
+
```
|
10
24
|
|
11
25
|
And then execute:
|
12
26
|
|
13
|
-
|
27
|
+
```shell
|
28
|
+
$ bundle
|
29
|
+
```
|
30
|
+
|
31
|
+
## Usage
|
14
32
|
|
15
|
-
|
33
|
+
```ruby
|
34
|
+
client = LIFX::Client.lan # Talk to bulbs on the LAN
|
35
|
+
client.discover! do |c| # Discover lights. Blocks until a light with the label 'Office' is found
|
36
|
+
c.lights.with_label('Office')
|
37
|
+
end
|
38
|
+
# Blocks for a default of 10 seconds or until a light is found
|
39
|
+
client.lights.turn_on # Tell all lights to turn on
|
40
|
+
light = client.lights.with_label('Office') # Get light with label 'Office'
|
16
41
|
|
17
|
-
|
42
|
+
# Set the Office light to pale green over 5 seconds
|
43
|
+
green = LIFX::Color.green(saturation: 0.5)
|
44
|
+
light.set_color(green, duration: 5) # Light#set_color is asynchronous
|
18
45
|
|
19
|
-
|
46
|
+
sleep 5 # Wait for light to finish changing
|
47
|
+
light.set_label('My Office')
|
48
|
+
|
49
|
+
light.add_tag('Offices') # Add tag to light
|
50
|
+
|
51
|
+
client.lights.with_tag('Offices').turn_off
|
52
|
+
|
53
|
+
client.flush # Wait until all the packets have been sent
|
54
|
+
```
|
55
|
+
|
56
|
+
## Documentation
|
57
|
+
|
58
|
+
Documentation is available at http://rubydoc.info/gems/lifx. Please note that undocumented classes/methods and classes/methods marked private are not intended for public use.
|
59
|
+
|
60
|
+
## Examples
|
61
|
+
|
62
|
+
Examples are located in the `examples/` folder.
|
63
|
+
|
64
|
+
* [travis-build-light](examples/travis-build-light/build-light.rb): Changes the colour of a light based on the build status of a project on Travis.
|
65
|
+
* [auto-off](examples/auto-off/auto-off.rb): Turns a light off after X seconds of it being detected turned on.
|
66
|
+
* [identify](examples/identify/identify.rb): Use divide-and-conquer search algorithm to identify a light visually.
|
67
|
+
|
68
|
+
## Useful utilities
|
69
|
+
|
70
|
+
* [lifx-console](http://github.com/chendo/lifx-console): A Pry-enabled REPL to play with LIFX easily.
|
71
|
+
* [lifx-http](http://github.com/chendo/lifx-http): A HTTP API for LIFX.
|
72
|
+
|
73
|
+
## Testing
|
74
|
+
|
75
|
+
Run with `bundle exec rspec`.
|
76
|
+
|
77
|
+
The integration specs rely on a least one device tagged with `Test` to function. At this point, they can fail occasionally due to the async nature of the protocol, and there's not much coverage at the moment as the architecture is still in flux.
|
78
|
+
|
79
|
+
A more comprehensive test suite is in the works.
|
80
|
+
|
81
|
+
## Feedback
|
20
82
|
|
21
|
-
|
83
|
+
Please file an issue for general feedback, bugs, clarification, examples, etc etc. Feel free to hit me up on Twitter, too: [@chendo](https://twitter.com/chendo).
|
22
84
|
|
23
|
-
##
|
85
|
+
## License
|
24
86
|
|
25
|
-
|
26
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
-
5. Create new Pull Request
|
87
|
+
MIT. See `LICENSE.txt`
|
data/Rakefile
CHANGED
data/bin/lifx-console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# LIFX Console
|
3
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), "..", "lib")
|
4
|
+
require 'lifx'
|
5
|
+
require 'rubygems'
|
6
|
+
begin
|
7
|
+
require 'pry'
|
8
|
+
rescue LoadError
|
9
|
+
$stderr.puts("You must have pry installed to use lifx-console. gem install pry")
|
10
|
+
end
|
11
|
+
|
12
|
+
c = LIFX::Client.lan
|
13
|
+
c.discover!
|
14
|
+
c.extend(LIFX::Colors)
|
15
|
+
c.pry
|
data/bin/lifx-snoop
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# lifx-snoop is a utility that snoops on LIFX UDP traffic on both the broadcast port
|
3
|
+
# and the peer broadcast port.
|
4
|
+
#
|
5
|
+
# Usage:
|
6
|
+
# lifx-snoop [regexp, ...]
|
7
|
+
#
|
8
|
+
# By default, it will show all messages. Any arguments passed in will become
|
9
|
+
# regular expressions, which will then match on the string representation of the
|
10
|
+
# message.
|
11
|
+
#
|
12
|
+
# Example:
|
13
|
+
# lifx-snoop Light::Get # Shows only Light::Get messages
|
14
|
+
# lifx-snoop Light::State site=d073d5000000 # Shows only Light::State messages matching site d073d5000000
|
15
|
+
|
16
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), "..", "lib")
|
17
|
+
require 'lifx'
|
18
|
+
require 'time'
|
19
|
+
|
20
|
+
matchers = ARGV.map do |arg|
|
21
|
+
Regexp.new(arg, Regexp::IGNORECASE)
|
22
|
+
end
|
23
|
+
|
24
|
+
if matchers.empty?
|
25
|
+
matchers << //
|
26
|
+
end
|
27
|
+
|
28
|
+
begin
|
29
|
+
light_udp = LIFX::Transport::UDP.new('0.0.0.0', 56700)
|
30
|
+
light_udp.add_observer(self) do |message:, ip:, transport:|
|
31
|
+
if matchers.all? { |m| message.to_s =~ m }
|
32
|
+
puts "#{Time.now.iso8601(5)} BROADCAST: #{ip} #{message}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
light_udp.listen
|
36
|
+
|
37
|
+
peer_udp = LIFX::Transport::UDP.new('0.0.0.0', 56750)
|
38
|
+
peer_udp.add_observer(self) do |message:, ip:, transport:|
|
39
|
+
if matchers.all? { |m| message.to_s =~ m }
|
40
|
+
puts "#{Time.now.iso8601(5)} PEER: #{ip} #{message}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
peer_udp.listen
|
44
|
+
rescue LIFX::Message::UnsupportedProtocolVersion
|
45
|
+
end
|
46
|
+
|
47
|
+
puts "Listening on 56700 and 56750..."
|
48
|
+
puts "^C to quit."
|
49
|
+
|
50
|
+
sleep
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Auto-off script
|
2
|
+
#
|
3
|
+
# This script will turn a light off after 10 seconds when it has detected it has turned on.
|
4
|
+
# To run: bundle; bundle ruby auto-off.rb [light label]
|
5
|
+
|
6
|
+
require 'bundler'
|
7
|
+
Bundler.require
|
8
|
+
|
9
|
+
AUTO_OFF_DELAY = 10
|
10
|
+
|
11
|
+
label = ARGV.first
|
12
|
+
lifx = LIFX::Client.lan
|
13
|
+
lifx.discover! do
|
14
|
+
label ? lifx.lights.with_label(label) : lifx.lights.first
|
15
|
+
end
|
16
|
+
|
17
|
+
light = label ? lifx.lights.with_label(label) : lifx.lights.first
|
18
|
+
|
19
|
+
puts "#{light} will be automatically turned off after #{AUTO_OFF_DELAY} seconds"
|
20
|
+
|
21
|
+
thr = Thread.new do
|
22
|
+
loop do
|
23
|
+
if light.on? && !(@off_thr && @off_thr.alive?)
|
24
|
+
puts "Light detected on. Turning off in #{AUTO_OFF_DELAY}"
|
25
|
+
@off_thr = Thread.new do
|
26
|
+
sleep AUTO_OFF_DELAY
|
27
|
+
light.turn_off
|
28
|
+
puts "Turning off"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
sleep 1
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
thr.join
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# Identify
|
2
|
+
#
|
3
|
+
# This example uses a divide and conquer search algorithm to identify a light visually.
|
4
|
+
# It will set all lights to white, then partition them by colour.
|
5
|
+
# On each iteration, it will ask you what colour the bulb you're trying to identify is showing
|
6
|
+
# until it narrows it down to a single bulb.
|
7
|
+
# Please note it does not restore the light state before identification.
|
8
|
+
|
9
|
+
require 'bundler'
|
10
|
+
Bundler.require
|
11
|
+
|
12
|
+
COLOURS = {
|
13
|
+
'red' => [0, 1, 1],
|
14
|
+
'yellow' => [50, 1, 1],
|
15
|
+
'green' => [120, 1, 1],
|
16
|
+
'blue' => [220, 1, 1]
|
17
|
+
}
|
18
|
+
|
19
|
+
LIFX::Config.logger = Yell.new(STDERR, :level => :error)
|
20
|
+
c = LIFX::Client.lan
|
21
|
+
c.discover
|
22
|
+
5.times do
|
23
|
+
c.lights.refresh
|
24
|
+
c.flush
|
25
|
+
sleep 1
|
26
|
+
puts "Lights found: #{c.lights.count}"
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def partition(list, partitions)
|
31
|
+
[].tap do |array|
|
32
|
+
list.each_slice((list.count / partitions.to_f).ceil) do |chunk|
|
33
|
+
array << chunk
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
lights = c.lights.to_a
|
39
|
+
mapping = {}
|
40
|
+
|
41
|
+
while lights.count > 1
|
42
|
+
puts "Searching through #{lights.count} lights..."
|
43
|
+
c.lights.set_color(LIFX::Color.white)
|
44
|
+
partitions = partition(lights, COLOURS.values.count)
|
45
|
+
COLOURS.keys.each_with_index do |color_name, index|
|
46
|
+
color = LIFX::Color.hsb(*COLOURS[color_name])
|
47
|
+
mapping[color_name] = partitions[index]
|
48
|
+
next if partitions[index].nil?
|
49
|
+
partitions[index].each do |l|
|
50
|
+
l.set_color(color, duration: 0)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
puts "Waiting for flush."
|
54
|
+
c.flush
|
55
|
+
puts "What colour is the bulb you're trying to identify? (#{COLOURS.keys.join(', ')})"
|
56
|
+
resp = gets.strip
|
57
|
+
if mapping.has_key?(resp)
|
58
|
+
lights = mapping[resp]
|
59
|
+
else
|
60
|
+
puts "Colour not found. Iterating again"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
if lights.count == 1
|
65
|
+
puts "Light identified: #{lights.first}"
|
66
|
+
else
|
67
|
+
puts "No bulbs found."
|
68
|
+
end
|
69
|
+
|
70
|
+
c.flush
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# A Travis CI Build Light
|
2
|
+
#
|
3
|
+
# To run: bundle; bundle ruby build-light.rb [user/repo]
|
4
|
+
# Please note this doesn't have error handling yet.
|
5
|
+
|
6
|
+
require 'bundler'
|
7
|
+
Bundler.require
|
8
|
+
|
9
|
+
lifx = LIFX::Client.lan
|
10
|
+
lifx.discover!
|
11
|
+
sleep 2 # Wait for tag data to come back
|
12
|
+
|
13
|
+
light = if lifx.tags.include?('Build Light')
|
14
|
+
lights = lifx.lights.with_tag('Build Light')
|
15
|
+
if lights.empty?
|
16
|
+
puts "No lights in the Build Light tag, using the first light found."
|
17
|
+
lifx.lights.first
|
18
|
+
else
|
19
|
+
lights
|
20
|
+
end
|
21
|
+
else
|
22
|
+
lifx.lights.first
|
23
|
+
end
|
24
|
+
|
25
|
+
if !light
|
26
|
+
puts "No LIFX lights found."
|
27
|
+
exit 1
|
28
|
+
end
|
29
|
+
|
30
|
+
puts "Using light(s): #{light}"
|
31
|
+
repo_path = ARGV.first || 'rails/rails'
|
32
|
+
|
33
|
+
repo = Travis::Repository.find(repo_path)
|
34
|
+
puts "Watching repository #{repo.slug}"
|
35
|
+
|
36
|
+
def update_light(light, repository)
|
37
|
+
color = case repository.color
|
38
|
+
when 'green'
|
39
|
+
LIFX::Color.hsb(120, 1, 1)
|
40
|
+
when 'yellow'
|
41
|
+
LIFX::Color.hsb(60, 1, 1)
|
42
|
+
when 'red'
|
43
|
+
LIFX::Color.hsb(0, 1, 1)
|
44
|
+
end
|
45
|
+
|
46
|
+
light.turn_on!
|
47
|
+
light.set_color(color, duration: 0.2)
|
48
|
+
puts "#{Time.now}: Build ##{repository.last_build.number} is #{repository.color}."
|
49
|
+
end
|
50
|
+
|
51
|
+
update_light(light, repo)
|
52
|
+
|
53
|
+
Travis.listen(repo) do |stream|
|
54
|
+
stream.on('build:started', 'build:finished') do |event|
|
55
|
+
update_light(light, event.repository)
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module BinData
|
2
|
+
class Bool < Primitive
|
3
|
+
uint8 :_value
|
4
|
+
|
5
|
+
def get
|
6
|
+
(self._value || 0) > 0
|
7
|
+
end
|
8
|
+
|
9
|
+
def set(value)
|
10
|
+
self._value = value ? 1 : 0
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class BoolBit1 < Primitive
|
15
|
+
bit1le :_value
|
16
|
+
|
17
|
+
def get
|
18
|
+
(self._value || 0) > 0
|
19
|
+
end
|
20
|
+
|
21
|
+
def set(value)
|
22
|
+
self._value = value ? 1 : 0
|
23
|
+
end
|
24
|
+
|
25
|
+
def !
|
26
|
+
!get
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/lifx/client.rb
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'timeout'
|
3
|
+
require 'yell'
|
4
|
+
|
5
|
+
require 'lifx/network_context'
|
6
|
+
require 'lifx/light_collection'
|
7
|
+
|
8
|
+
module LIFX
|
9
|
+
# {LIFX::Client} is the top level interface to the library. It mainly maps
|
10
|
+
# methods to the backing {NetworkContext} instance.
|
11
|
+
class Client
|
12
|
+
|
13
|
+
class << self
|
14
|
+
# Returns a {Client} set up for accessing devices on the LAN
|
15
|
+
#
|
16
|
+
# @return [Client] A LAN LIFX::Client
|
17
|
+
def lan
|
18
|
+
@lan ||= new
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
extend Forwardable
|
23
|
+
include Utilities
|
24
|
+
|
25
|
+
# Refers to the client's network context.
|
26
|
+
# @return [NetworkContext] Enclosed network context
|
27
|
+
attr_reader :context
|
28
|
+
|
29
|
+
# @param transport: [:lan] Specify which transport to use
|
30
|
+
def initialize(transport: :lan)
|
31
|
+
@context = NetworkContext.new(transport: transport)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Default timeout in seconds for discovery
|
35
|
+
DISCOVERY_DEFAULT_TIMEOUT = 10
|
36
|
+
|
37
|
+
# This method tells the {NetworkContext} to look for devices asynchronously.
|
38
|
+
# @return [Client] self
|
39
|
+
def discover
|
40
|
+
@context.discover
|
41
|
+
end
|
42
|
+
|
43
|
+
class DiscoveryTimeout < Timeout::Error; end
|
44
|
+
# This method tells the {NetworkContext} to look for devices, and will block
|
45
|
+
# until there's at least one device.
|
46
|
+
#
|
47
|
+
# @example Wait until at least three lights have been found
|
48
|
+
# client.discover! { |c| c.lights.count >= 3 }
|
49
|
+
#
|
50
|
+
# @param timeout: [Numeric] How long to try to wait for before returning
|
51
|
+
# @param condition_interval: [Numeric] Seconds between evaluating the block
|
52
|
+
# @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.
|
53
|
+
# @raise [DiscoveryTimeout] If discovery times out
|
54
|
+
# @return [Client] self
|
55
|
+
def discover!(timeout: DISCOVERY_DEFAULT_TIMEOUT, condition_interval: 0.1, &block)
|
56
|
+
block ||= -> { self.lights.count > 0 }
|
57
|
+
try_until -> { block.arity == 1 ? block.call(self) : block.call },
|
58
|
+
timeout: timeout,
|
59
|
+
timeout_exception: DiscoveryTimeout,
|
60
|
+
condition_interval: condition_interval do
|
61
|
+
discover
|
62
|
+
end
|
63
|
+
self
|
64
|
+
end
|
65
|
+
|
66
|
+
# Sends a request to refresh devices and tags.
|
67
|
+
# @return [void]
|
68
|
+
def refresh
|
69
|
+
@context.refresh
|
70
|
+
end
|
71
|
+
|
72
|
+
# This method takes a block consisting of multiple asynchronous color or power changing targets
|
73
|
+
# and it will try to schedule them so they run at the same time.
|
74
|
+
#
|
75
|
+
# You cannot nest `sync` calls, nor call synchronous methods inside a `sync` block.
|
76
|
+
#
|
77
|
+
# Due to messaging rate constraints, the amount of messages determine the delay before
|
78
|
+
# the commands are executed. This method also assumes all the lights have the same time.
|
79
|
+
# @example This example sets all the lights to a random colour at the same time.
|
80
|
+
# client.sync do
|
81
|
+
# client.lights.each do |light|
|
82
|
+
# light.set_color(rand(4) * 90, 1, 1)
|
83
|
+
# end
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# @note This method is in alpha and might go away. Use tags for better group messaging.
|
87
|
+
# @yield Block of commands to synchronize
|
88
|
+
# @return [Float] Number of seconds until commands are executed
|
89
|
+
def sync(&block)
|
90
|
+
@context.sync(&block)
|
91
|
+
end
|
92
|
+
|
93
|
+
# This is the same as {#sync}, except it will block until the commands have been executed.
|
94
|
+
# @see #sync
|
95
|
+
# @return [Float] Number of seconds slept
|
96
|
+
def sync!(&block)
|
97
|
+
sync(&block).tap do |delay|
|
98
|
+
sleep(delay)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# @return [LightCollection] Lights available to the client
|
103
|
+
# @see [NetworkContext#lights]
|
104
|
+
def lights
|
105
|
+
context.lights
|
106
|
+
end
|
107
|
+
|
108
|
+
# @return [Array<String>] All tags visible to the client
|
109
|
+
# @see [NetworkContext#tags]
|
110
|
+
def tags
|
111
|
+
context.tags
|
112
|
+
end
|
113
|
+
|
114
|
+
# @return [Array<String>] Tags that are currently unused by known devices
|
115
|
+
# @see [NetworkContext#unused_tags]
|
116
|
+
def unused_tags
|
117
|
+
context.unused_tags
|
118
|
+
end
|
119
|
+
|
120
|
+
# Purges unused tags from the system.
|
121
|
+
# Should only use when all devices are on the network, otherwise
|
122
|
+
# offline devices using their tags will not be tagged correctly.
|
123
|
+
# @return [Array<String>] Tags that were purged
|
124
|
+
def purge_unused_tags!
|
125
|
+
context.purge_unused_tags!
|
126
|
+
end
|
127
|
+
|
128
|
+
# Blocks until all messages have been sent to the gateways
|
129
|
+
# @param timeout: [Numeric] When specified, flush will wait `timeout:` seconds before throwing `Timeout::Error`
|
130
|
+
# @raise [Timeout::Error] if `timeout:` was exceeded while waiting for send queue to flush
|
131
|
+
# @return [void]
|
132
|
+
def flush(timeout: nil)
|
133
|
+
context.flush(timeout: timeout)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|