lifx 0.0.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|