sparkle_motion 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 (43) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +7 -0
  3. data/LICENSE +22 -0
  4. data/README.md +47 -0
  5. data/bin/sm-discover +18 -0
  6. data/bin/sm-mark-lights +58 -0
  7. data/bin/sm-off +38 -0
  8. data/bin/sm-on +50 -0
  9. data/bin/sm-simulate +595 -0
  10. data/bin/sm-watch-memory +9 -0
  11. data/bin/sparkle-motion +48 -0
  12. data/config.yml +201 -0
  13. data/data/dynamic/bridges.csv +5 -0
  14. data/data/static/devices.csv +7 -0
  15. data/lib/sparkle_motion.rb +72 -0
  16. data/lib/sparkle_motion/config.rb +45 -0
  17. data/lib/sparkle_motion/env.rb +14 -0
  18. data/lib/sparkle_motion/http.rb +26 -0
  19. data/lib/sparkle_motion/hue/ssdp.rb +39 -0
  20. data/lib/sparkle_motion/launch_pad/color.rb +41 -0
  21. data/lib/sparkle_motion/launch_pad/widget.rb +187 -0
  22. data/lib/sparkle_motion/launch_pad/widgets/button.rb +29 -0
  23. data/lib/sparkle_motion/launch_pad/widgets/horizontal_slider.rb +43 -0
  24. data/lib/sparkle_motion/launch_pad/widgets/radio_group.rb +53 -0
  25. data/lib/sparkle_motion/launch_pad/widgets/toggle.rb +48 -0
  26. data/lib/sparkle_motion/launch_pad/widgets/vertical_slider.rb +43 -0
  27. data/lib/sparkle_motion/lazy_request_config.rb +87 -0
  28. data/lib/sparkle_motion/node.rb +80 -0
  29. data/lib/sparkle_motion/nodes/generator.rb +8 -0
  30. data/lib/sparkle_motion/nodes/generators/const.rb +15 -0
  31. data/lib/sparkle_motion/nodes/generators/perlin.rb +26 -0
  32. data/lib/sparkle_motion/nodes/generators/wave2.rb +20 -0
  33. data/lib/sparkle_motion/nodes/transform.rb +34 -0
  34. data/lib/sparkle_motion/nodes/transforms/contrast.rb +20 -0
  35. data/lib/sparkle_motion/nodes/transforms/range.rb +41 -0
  36. data/lib/sparkle_motion/nodes/transforms/spotlight.rb +35 -0
  37. data/lib/sparkle_motion/output.rb +69 -0
  38. data/lib/sparkle_motion/results.rb +78 -0
  39. data/lib/sparkle_motion/utility.rb +68 -0
  40. data/lib/sparkle_motion/vector2.rb +11 -0
  41. data/lib/sparkle_motion/version.rb +3 -0
  42. data/sparkle_motion.gemspec +44 -0
  43. metadata +178 -0
@@ -0,0 +1,78 @@
1
+ # TODO: Namespacing/classes/etc!
2
+
3
+ # Helper class to hold onto stats about requests made to the bridges.
4
+ #
5
+ # NOTE: Methods ending with `!` are *not* thread-safe, methods without it *are*.
6
+ #
7
+ # TODO: Track things by light index, bridge, etc...
8
+ class Results
9
+ attr_reader :start_time, :end_time, :successes, :failures, :hard_timeouts,
10
+ :soft_timeouts
11
+
12
+ def initialize(logger:)
13
+ @logger = logger
14
+ @mutex = Mutex.new
15
+ clear!
16
+ end
17
+
18
+ def clear!
19
+ @successes = 0
20
+ @failures = 0
21
+ @hard_timeouts = 0
22
+ @soft_timeouts = 0
23
+ end
24
+
25
+ def begin!; @start_time ||= Time.now.to_f; end
26
+ def done!; @end_time ||= Time.now.to_f; end
27
+
28
+ # TODO: Colorized output for all feedback types, or running counters, or
29
+ # TODO: something...
30
+
31
+ def success!(info = nil)
32
+ @logger.error { info } if info
33
+ @successes += 1
34
+ end
35
+
36
+ def failure!(info = nil)
37
+ @logger.error { info } if info
38
+ @failures += 1
39
+ end
40
+
41
+ def hard_timeout!(info = nil)
42
+ @logger.error { info } if info
43
+ @hard_timeouts += 1
44
+ end
45
+
46
+ def soft_timeout!(info = nil)
47
+ @logger.error { info } if info
48
+ @soft_timeouts += 1
49
+ end
50
+
51
+ def elapsed; @end_time - @start_time; end
52
+ def requests; @successes + @failures + @hard_timeouts + @soft_timeouts; end
53
+ def all_failures; @failures + @hard_timeouts + @soft_timeouts; end
54
+
55
+ def requests_sec; ratio(requests, elapsed); end
56
+ def successes_sec; ratio(successes, elapsed); end
57
+ def failures_sec; ratio(failures, elapsed); end
58
+ def hard_timeouts_sec; ratio(hard_timeouts, elapsed); end
59
+ def soft_timeouts_sec; ratio(soft_timeouts, elapsed); end
60
+
61
+ def failure_rate; ratio(all_failures * 100, requests); end
62
+
63
+ def add_from(other)
64
+ @mutex.synchronize do
65
+ @successes += other.successes
66
+ @failures += other.failures
67
+ @hard_timeouts += other.hard_timeouts
68
+ @soft_timeouts += other.soft_timeouts
69
+ end
70
+ end
71
+
72
+ protected
73
+
74
+ def ratio(num, denom)
75
+ return nil unless num && denom && denom > 0
76
+ num / denom.to_f
77
+ end
78
+ end
@@ -0,0 +1,68 @@
1
+ # TODO: Namespacing/classes/etc!
2
+
3
+ # rubocop:disable Lint/RescueException
4
+ def guard_call(prefix, &block)
5
+ block.call
6
+ rescue Exception => e
7
+ SparkleMotion.logger.error { "#{prefix}: Exception for #{prefix}: #{e.message}" }
8
+ SparkleMotion.logger.error { "#{prefix}:\t#{e.backtrace.join("\n#{prefix}:\t")}" }
9
+ end
10
+ # rubocop:enable Lint/RescueException
11
+
12
+ module SparkleMotion
13
+ # Class to represent configurations and positioning of lights.
14
+ class LightConfig
15
+ attr_accessor :bridges, :lights, :masks
16
+
17
+ def initialize(config:, group:)
18
+ group_config = config[group]
19
+ num_lights = group_config.length
20
+
21
+ lights_by_bridge = group_lights_by_bridge(group_config)
22
+
23
+ index = 0
24
+ masks_by_bridge = {}
25
+ lights_by_bridge.each do |(bridge_name, lights)|
26
+ lights_by_bridge[bridge_name], index = index_lights(lights, index)
27
+ masks_by_bridge[bridge_name] = mask_lights(lights_by_bridge[bridge_name], num_lights)
28
+ end
29
+
30
+ set_state!(config, lights_by_bridge, masks_by_bridge)
31
+ end
32
+
33
+ protected
34
+
35
+ def set_state!(config, lights, masks)
36
+ @bridges = config["bridges"]
37
+ @lights = lights
38
+ @masks = masks
39
+ end
40
+
41
+ def group_lights_by_bridge(config)
42
+ groups = Hash.new { |hsh, x| hsh[x] = [] }
43
+ config.each do |(bridge_name, light_id)|
44
+ groups[bridge_name] << light_id
45
+ end
46
+ groups
47
+ end
48
+
49
+ # Determine globally unique index for each light, so we can address them
50
+ # logically, but also relate physical mappings.
51
+ def index_lights(lights, index)
52
+ indexed_lights = []
53
+ lights.each do |light_id|
54
+ indexed_lights << [index, light_id]
55
+ index += 1
56
+ end
57
+ [indexed_lights, index]
58
+ end
59
+
60
+ # Create a mask for the global set of lights to easily tell which ones
61
+ # belong to a given bridge.
62
+ def mask_lights(indexed_lights, length)
63
+ mask = [false] * length
64
+ indexed_lights.map(&:first).each { |idx| mask[idx] = true }
65
+ mask
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,11 @@
1
+ # TODO: Namespacing!
2
+ # A 2-component vector, where components go from 0.0..1.0.
3
+ class Vector2
4
+ attr_reader :x, :y
5
+ def initialize(x: 0.0, y: 0.0)
6
+ @x = x
7
+ @y = y
8
+ end
9
+
10
+ def to_s; "<<#{@x}, #{@y}>>"; end
11
+ end
@@ -0,0 +1,3 @@
1
+ module SparkleMotion
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,44 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $LOAD_PATH.push File.expand_path("../lib", __FILE__)
3
+ require "sparkle_motion/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "sparkle_motion"
7
+ s.version = SparkleMotion::VERSION
8
+ s.author = "Jon Frisby"
9
+ s.email = "jfrisby@mrjoy.com"
10
+ s.homepage = "http://github.com/MrJoy/sparkle_motion"
11
+ s.description = "A system for generative event lighting using Philips Hue controlled"\
12
+ " from a Novation Launchpad"
13
+ s.summary = "Generative event lighting using Philips Hue, and Novation Launchpad"
14
+ raw_file_list = `git ls-files`.split("\n")
15
+ s.files = raw_file_list
16
+ .reject do |fname|
17
+ fname =~ %r{
18
+ \A
19
+ (\..*
20
+ |Gemfile.*
21
+ |notes/.*
22
+ |tasks/.*
23
+ |tools/.*
24
+ |examples/.*
25
+ |tmp/.*
26
+ |Rakefile
27
+ |.*\.sublime-project
28
+ )
29
+ \z
30
+ }x
31
+ end
32
+ s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
33
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
34
+ s.extra_rdoc_files = %w(CHANGELOG.md README.md LICENSE)
35
+ s.require_paths = ["lib"]
36
+ s.required_ruby_version = Gem::Requirement.new(">= 2.2.0")
37
+
38
+ s.add_dependency "oj", "~> 2.12.13"
39
+ s.add_dependency "curb", "~> 0.8.8"
40
+ s.add_dependency "perlin_noise", "~> 0.1.2"
41
+ s.add_dependency "logger-better", "~> 0.2.1"
42
+ s.add_dependency "frisky"
43
+ s.add_dependency "mrjoy-launchpad"
44
+ end
metadata ADDED
@@ -0,0 +1,178 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sparkle_motion
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jon Frisby
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-09-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: oj
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.12.13
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.12.13
27
+ - !ruby/object:Gem::Dependency
28
+ name: curb
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.8.8
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.8.8
41
+ - !ruby/object:Gem::Dependency
42
+ name: perlin_noise
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.2
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.1.2
55
+ - !ruby/object:Gem::Dependency
56
+ name: logger-better
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.2.1
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.2.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: frisky
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: mrjoy-launchpad
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: A system for generative event lighting using Philips Hue controlled from
98
+ a Novation Launchpad
99
+ email: jfrisby@mrjoy.com
100
+ executables:
101
+ - sm-discover
102
+ - sm-mark-lights
103
+ - sm-off
104
+ - sm-on
105
+ - sm-simulate
106
+ - sm-watch-memory
107
+ - sparkle-motion
108
+ extensions: []
109
+ extra_rdoc_files:
110
+ - CHANGELOG.md
111
+ - README.md
112
+ - LICENSE
113
+ files:
114
+ - CHANGELOG.md
115
+ - LICENSE
116
+ - README.md
117
+ - bin/sm-discover
118
+ - bin/sm-mark-lights
119
+ - bin/sm-off
120
+ - bin/sm-on
121
+ - bin/sm-simulate
122
+ - bin/sm-watch-memory
123
+ - bin/sparkle-motion
124
+ - config.yml
125
+ - data/dynamic/bridges.csv
126
+ - data/static/devices.csv
127
+ - lib/sparkle_motion.rb
128
+ - lib/sparkle_motion/config.rb
129
+ - lib/sparkle_motion/env.rb
130
+ - lib/sparkle_motion/http.rb
131
+ - lib/sparkle_motion/hue/ssdp.rb
132
+ - lib/sparkle_motion/launch_pad/color.rb
133
+ - lib/sparkle_motion/launch_pad/widget.rb
134
+ - lib/sparkle_motion/launch_pad/widgets/button.rb
135
+ - lib/sparkle_motion/launch_pad/widgets/horizontal_slider.rb
136
+ - lib/sparkle_motion/launch_pad/widgets/radio_group.rb
137
+ - lib/sparkle_motion/launch_pad/widgets/toggle.rb
138
+ - lib/sparkle_motion/launch_pad/widgets/vertical_slider.rb
139
+ - lib/sparkle_motion/lazy_request_config.rb
140
+ - lib/sparkle_motion/node.rb
141
+ - lib/sparkle_motion/nodes/generator.rb
142
+ - lib/sparkle_motion/nodes/generators/const.rb
143
+ - lib/sparkle_motion/nodes/generators/perlin.rb
144
+ - lib/sparkle_motion/nodes/generators/wave2.rb
145
+ - lib/sparkle_motion/nodes/transform.rb
146
+ - lib/sparkle_motion/nodes/transforms/contrast.rb
147
+ - lib/sparkle_motion/nodes/transforms/range.rb
148
+ - lib/sparkle_motion/nodes/transforms/spotlight.rb
149
+ - lib/sparkle_motion/output.rb
150
+ - lib/sparkle_motion/results.rb
151
+ - lib/sparkle_motion/utility.rb
152
+ - lib/sparkle_motion/vector2.rb
153
+ - lib/sparkle_motion/version.rb
154
+ - sparkle_motion.gemspec
155
+ homepage: http://github.com/MrJoy/sparkle_motion
156
+ licenses: []
157
+ metadata: {}
158
+ post_install_message:
159
+ rdoc_options: []
160
+ require_paths:
161
+ - lib
162
+ required_ruby_version: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: 2.2.0
167
+ required_rubygems_version: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ requirements: []
173
+ rubyforge_project:
174
+ rubygems_version: 2.4.5.1
175
+ signing_key:
176
+ specification_version: 4
177
+ summary: Generative event lighting using Philips Hue, and Novation Launchpad
178
+ test_files: []