lifx-lan 0.1.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.
Files changed (73) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.travis.yml +8 -0
  4. data/.yardopts +3 -0
  5. data/CHANGES.md +45 -0
  6. data/Gemfile +19 -0
  7. data/LICENSE.txt +23 -0
  8. data/README.md +15 -0
  9. data/Rakefile +20 -0
  10. data/bin/lifx-snoop +50 -0
  11. data/examples/auto-off/auto-off.rb +34 -0
  12. data/examples/blink/blink.rb +19 -0
  13. data/examples/identify/identify.rb +69 -0
  14. data/examples/travis-build-light/build-light.rb +57 -0
  15. data/lib/bindata_ext/bool.rb +30 -0
  16. data/lib/bindata_ext/record.rb +11 -0
  17. data/lib/lifx-lan.rb +27 -0
  18. data/lib/lifx/lan/client.rb +149 -0
  19. data/lib/lifx/lan/color.rb +199 -0
  20. data/lib/lifx/lan/config.rb +17 -0
  21. data/lib/lifx/lan/firmware.rb +60 -0
  22. data/lib/lifx/lan/gateway_connection.rb +185 -0
  23. data/lib/lifx/lan/light.rb +440 -0
  24. data/lib/lifx/lan/light_collection.rb +111 -0
  25. data/lib/lifx/lan/light_target.rb +185 -0
  26. data/lib/lifx/lan/logging.rb +14 -0
  27. data/lib/lifx/lan/message.rb +168 -0
  28. data/lib/lifx/lan/network_context.rb +188 -0
  29. data/lib/lifx/lan/observable.rb +66 -0
  30. data/lib/lifx/lan/protocol/address.rb +25 -0
  31. data/lib/lifx/lan/protocol/device.rb +387 -0
  32. data/lib/lifx/lan/protocol/header.rb +24 -0
  33. data/lib/lifx/lan/protocol/light.rb +142 -0
  34. data/lib/lifx/lan/protocol/message.rb +19 -0
  35. data/lib/lifx/lan/protocol/metadata.rb +23 -0
  36. data/lib/lifx/lan/protocol/payload.rb +12 -0
  37. data/lib/lifx/lan/protocol/sensor.rb +31 -0
  38. data/lib/lifx/lan/protocol/type.rb +204 -0
  39. data/lib/lifx/lan/protocol/wan.rb +51 -0
  40. data/lib/lifx/lan/protocol/wifi.rb +102 -0
  41. data/lib/lifx/lan/protocol_path.rb +85 -0
  42. data/lib/lifx/lan/required_keyword_arguments.rb +12 -0
  43. data/lib/lifx/lan/routing_manager.rb +114 -0
  44. data/lib/lifx/lan/routing_table.rb +48 -0
  45. data/lib/lifx/lan/seen.rb +25 -0
  46. data/lib/lifx/lan/site.rb +97 -0
  47. data/lib/lifx/lan/tag_manager.rb +111 -0
  48. data/lib/lifx/lan/tag_table.rb +49 -0
  49. data/lib/lifx/lan/target.rb +24 -0
  50. data/lib/lifx/lan/thread.rb +13 -0
  51. data/lib/lifx/lan/timers.rb +29 -0
  52. data/lib/lifx/lan/transport.rb +46 -0
  53. data/lib/lifx/lan/transport/tcp.rb +91 -0
  54. data/lib/lifx/lan/transport/udp.rb +87 -0
  55. data/lib/lifx/lan/transport_manager.rb +43 -0
  56. data/lib/lifx/lan/transport_manager/lan.rb +169 -0
  57. data/lib/lifx/lan/utilities.rb +36 -0
  58. data/lib/lifx/lan/version.rb +5 -0
  59. data/lifx-lan.gemspec +26 -0
  60. data/spec/color_spec.rb +43 -0
  61. data/spec/gateway_connection_spec.rb +30 -0
  62. data/spec/integration/client_spec.rb +42 -0
  63. data/spec/integration/light_spec.rb +56 -0
  64. data/spec/integration/tags_spec.rb +42 -0
  65. data/spec/light_collection_spec.rb +37 -0
  66. data/spec/message_spec.rb +183 -0
  67. data/spec/protocol_path_spec.rb +109 -0
  68. data/spec/routing_manager_spec.rb +25 -0
  69. data/spec/routing_table_spec.rb +23 -0
  70. data/spec/spec_helper.rb +56 -0
  71. data/spec/transport/udp_spec.rb +44 -0
  72. data/spec/transport_spec.rb +14 -0
  73. metadata +187 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4ef94c0b7aaaa1efaf0ed5510237c2f8e8638c69
4
+ data.tar.gz: 24ecd96f704325934c37882f5bd7f7417dbb4287
5
+ SHA512:
6
+ metadata.gz: 87d2775a26c2104f0789d07a9bb38ea1dda76ca5d03ac3031bdd41190f76cabc34e932a5785edc940e67458fdab064874a10d50f6a06a0d41da159d8f596157a
7
+ data.tar.gz: 18691da3eb56988e02c2a3fb94ec9f74b1271a901ea80b76a80e6c91e85bad86b32ea7c5c77051687df06495a88e406810a8fbea5dfa6f48bd6ca53d20c1bc36
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ bundler_args: --without development
3
+ notifications:
4
+ slack: lifx:z9PYWaIkFUpHw0aFu9mMQXDl
5
+ email: false
6
+ rvm:
7
+ - 2.0.0
8
+ - 2.1.1
@@ -0,0 +1,3 @@
1
+ --markup markdown
2
+ --no-private
3
+ --hide-api private
@@ -0,0 +1,45 @@
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
+
10
+ ### 0.4.8
11
+
12
+ - Routing table is only updated from State messages
13
+ - Fix memory leaks
14
+
15
+ ### 0.4.7
16
+
17
+ - Only create Light devices when a Light::State is received
18
+ - Message rate checker only checks lights considered alive
19
+
20
+ ### 0.4.6.1
21
+
22
+ - Fix `Time.parse` issue
23
+
24
+ ### 0.4.6
25
+
26
+ - `Color#==` has been renamed to `Color#similar_to?`
27
+ - Broadcast IP configurable through `LIFX::Config.broadcast_ip`
28
+ - Removed Yell gem. Use stdlib Logger instead
29
+ - Uninitialized lights no longer shows up in `Client#lights`
30
+ - Handle Rubies that don't have IPv6 enabled
31
+
32
+ ### 0.4.5
33
+
34
+ - Now supports Ruby 2.0
35
+ - Light#label can be nil
36
+ - Light#set_power and Light#set_power! now take :on and :off rather than magic number
37
+ - Use timers 1.x so no compilation is required
38
+
39
+ ### 0.4.4
40
+
41
+ - Fix SO_REUSEPORT issue on older Linux kernels.
42
+
43
+ ### 0.4.3
44
+
45
+ - Initial public release
data/Gemfile ADDED
@@ -0,0 +1,19 @@
1
+ source 'https://rubygems.org'
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
+
13
+ group :test do
14
+ gem 'rake', '~> 10.1'
15
+ gem 'rspec', '~> 3.0.0'
16
+ end
17
+
18
+ # Specify your gem's dependencies in lifx.gemspec
19
+ gemspec
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2012-2014 LIFX Labs
2
+ Copyright (c) 2017-2018 Julian Cheal
3
+
4
+ MIT License
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ "Software"), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,15 @@
1
+ # LIFX-lan
2
+
3
+ [![Build Status](https://travis-ci.org/juliancheal/lifx-lan.svg)](https://travis-ci.org/juliancheal/lifx-lan)
4
+ [![Code Climate](https://codeclimate.com/github/juliancheal/lifx-lan/badges/gpa.svg)](https://codeclimate.com/github/juliancheal/lifx-lan)
5
+ [![Coverage Status](https://coveralls.io/repos/juliancheal/lifx-lan/badge.svg?branch=master&service=github)](https://coveralls.io/github/juliancheal/lifx-lan?branch=master)
6
+ [![Dependency Status](https://gemnasium.com/juliancheal/lifx-lan.svg)](https://gemnasium.com/juliancheal/lifx-lan)
7
+ [![Security](https://hakiri.io/github/juliancheal/lifx-lan/master.svg)](https://hakiri.io/github/juliancheal/lifx-lan/master)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+
10
+
11
+ [![Build history for master branch](https://buildstats.info/travisci/chart/ManageIQ/manageiq?branch=master&buildCount=50)](https://travis-ci.org/juliancheal/lifx-lan/branches)
12
+
13
+ LIFX-lan is a fork of the [lifx-gem](https://github.com/LIFX/lifx-gem). This gem is based on the [Lifx LAN](https://api.developer.lifx.com/) protocol.
14
+
15
+ Lifx have a Developer Zone over on their community site https://community.lifx.com/
@@ -0,0 +1,20 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec) do |t|
5
+ t.rspec_opts = "--tag ~integration"
6
+ end
7
+ task :default => :spec
8
+
9
+ task :console do
10
+ $LOAD_PATH << "lib"
11
+ require "lifx"
12
+ require "pry"
13
+ if ENV['DEBUG']
14
+ LIFX::LAN::Config.logger.level = Logger::DEBUG
15
+ end
16
+ LIFX::LAN::Client.lan.discover! do |c|
17
+ c.lights.count > 0
18
+ end
19
+ LIFX::LAN::Client.lan.pry
20
+ end
@@ -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-lan'
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::LAN::Transport::UDP.new('0.0.0.0', 56700)
30
+ light_udp.add_observer(self, :message_received) do |message: nil, ip: nil, transport: nil|
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::LAN::Transport::UDP.new('0.0.0.0', 56750)
38
+ peer_udp.add_observer(self, :message_received) do |message: nil, ip: nil, transport: nil|
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::LAN::Message::UnsupportedProtocolVersion
45
+ end
46
+
47
+ puts "Listening on 56700 and 56750..."
48
+ puts "^C to quit."
49
+
50
+ sleep
@@ -0,0 +1,34 @@
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 'lifx-lan'
7
+
8
+ AUTO_OFF_DELAY = 10
9
+
10
+ label = ARGV.first
11
+ lifx = LIFX::LAN::Client.lan
12
+ lifx.discover! do
13
+ label ? lifx.lights.with_label(label) : lifx.lights.first
14
+ end
15
+
16
+ light = label ? lifx.lights.with_label(label) : lifx.lights.first
17
+
18
+ puts "#{light} will be automatically turned off after #{AUTO_OFF_DELAY} seconds"
19
+
20
+ thr = Thread.new do
21
+ loop do
22
+ if light.on? && !(@off_thr && @off_thr.alive?)
23
+ puts "Light detected on. Turning off in #{AUTO_OFF_DELAY}"
24
+ @off_thr = Thread.new do
25
+ sleep AUTO_OFF_DELAY
26
+ light.turn_off
27
+ puts "Turning off"
28
+ end
29
+ end
30
+ sleep 1
31
+ end
32
+ end
33
+
34
+ thr.join
@@ -0,0 +1,19 @@
1
+ require 'lifx-lan'
2
+
3
+ lifx = LIFX::LAN::Client.lan
4
+ lifx.discover!
5
+
6
+ light = lifx.lights.first
7
+ light.set_color LIFX::LAN::Color.white, duration: 0
8
+
9
+ sleep(0.5)
10
+
11
+ light.set_color LIFX::LAN::Color.red, duration: 0
12
+
13
+ sleep(0.5)
14
+
15
+ light.set_color LIFX::LAN::Color.white, duration: 0
16
+
17
+ sleep(0.5)
18
+
19
+ light.set_color LIFX::LAN::Color.red, duration: 0
@@ -0,0 +1,69 @@
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 'lifx-lan'
10
+
11
+ COLOURS = {
12
+ 'red' => [0, 1, 1],
13
+ 'yellow' => [50, 1, 1],
14
+ 'green' => [120, 1, 1],
15
+ 'blue' => [220, 1, 1]
16
+ }
17
+
18
+ LIFX::LAN::Config.logger = Logger.new(STDERR)
19
+ c = LIFX::Client.lan
20
+ c.discover
21
+ 5.times do
22
+ c.lights.refresh
23
+ c.flush
24
+ sleep 1
25
+ puts "Lights found: #{c.lights.count}"
26
+ end
27
+
28
+
29
+ def partition(list, partitions)
30
+ [].tap do |array|
31
+ list.each_slice((list.count / partitions.to_f).ceil) do |chunk|
32
+ array << chunk
33
+ end
34
+ end
35
+ end
36
+
37
+ lights = c.lights.to_a
38
+ mapping = {}
39
+
40
+ while lights.count > 1
41
+ puts "Searching through #{lights.count} lights..."
42
+ c.lights.set_color(LIFX::LAN::Color.white)
43
+ partitions = partition(lights, COLOURS.values.count)
44
+ COLOURS.keys.each_with_index do |color_name, index|
45
+ color = LIFX::LAN::Color.hsb(*COLOURS[color_name])
46
+ mapping[color_name] = partitions[index]
47
+ next if partitions[index].nil?
48
+ partitions[index].each do |l|
49
+ l.set_color(color, duration: 0)
50
+ end
51
+ end
52
+ puts "Waiting for flush."
53
+ c.flush
54
+ puts "What colour is the bulb you're trying to identify? (#{COLOURS.keys.join(', ')})"
55
+ resp = gets.strip
56
+ if mapping.has_key?(resp)
57
+ lights = mapping[resp]
58
+ else
59
+ puts "Colour not found. Iterating again"
60
+ end
61
+ end
62
+
63
+ if lights.count == 1
64
+ puts "Light identified: #{lights.first}"
65
+ else
66
+ puts "No bulbs found."
67
+ end
68
+
69
+ 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 'travis'
7
+ require 'lifx-lan'
8
+
9
+ lifx = LIFX::LAN::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::LAN::Color.hsb(120, 1, 1)
40
+ when 'yellow'
41
+ LIFX::LAN::Color.hsb(60, 1, 1)
42
+ when 'red'
43
+ LIFX::LAN::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,30 @@
1
+ # @private
2
+ module BinData
3
+ class Bool < Primitive
4
+ uint8 :_value
5
+
6
+ def get
7
+ (self._value || 0) > 0
8
+ end
9
+
10
+ def set(value)
11
+ self._value = value ? 1 : 0
12
+ end
13
+ end
14
+
15
+ class BoolBit1 < Primitive
16
+ bit1le :_value
17
+
18
+ def get
19
+ (self._value || 0) > 0
20
+ end
21
+
22
+ def set(value)
23
+ self._value = value ? 1 : 0
24
+ end
25
+
26
+ def !
27
+ !get
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,11 @@
1
+ require 'stringio'
2
+ BinData::Record
3
+ module BinData
4
+ class Record
5
+ def pack
6
+ s = StringIO.new
7
+ write(s)
8
+ s.string.b
9
+ end
10
+ end
11
+ end