rustle 0.1.1 → 0.1.2

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: a832c77bff50413388dc4b5e7930c623a8807c5e
4
- data.tar.gz: 4565b1dfd7ed5ddae95fe044b3419a3dfa850224
3
+ metadata.gz: 5471958598d61f4dc25f459bdad141ada82b1bd0
4
+ data.tar.gz: 9f0f17ec4a82206000b729e697bffd7778848d68
5
5
  SHA512:
6
- metadata.gz: ab2b36845325b8f6ad07c9c78ffbb83c6372b7c167c213d1444ffb1f3c9c18c7ba0fb42f5726c023a04cc2384b450ccf5596129764d41741a0d402bcf56a4774
7
- data.tar.gz: 5eeea99ff6e98b0e7d310aa55f5a0b603a5feffa132dc915d6e2d2870c820dd8cc4a010aea53cdfd53a64d1e3dae4cb6f37106573e98d91cf0900a7c8b92bf32
6
+ metadata.gz: 6744cbf1557218443148fc94c02f3728af062d97320202323d234e2251415a8696fb2369b2ec9d9401519e4cb5250b621a8a982ff153337f8f317847b6e240b7
7
+ data.tar.gz: 41a86f55fa7681a319da9853a3dcd3c06aa392daeac3cc91dadbb5cada709ae7a298e6c4d90e6dd3e4e5850b6907a45c45229b13aceb2314fc4f33bab1648368
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Rustle Changelog
2
2
 
3
+ ## 0.1.2
4
+
5
+ #### New
6
+
7
+ * Much more spec coverage.
8
+ * Invalid data handling
9
+ * **Debug mode**: to make specs easier, Receiver objects can be set to debug mode, in which no actual data will be sent to the Arduino, and instead will be returned as arrays.
10
+
11
+ #### Deprecated
12
+
13
+ * The old DSL-style Receiver instantiation syntax. See the documentation for Receiver#initialize because the syntax is now quite different.
14
+
3
15
  ## 0.1.1
4
16
 
5
17
  #### New
@@ -0,0 +1,18 @@
1
+ module Rustle
2
+ # = DebugPort
3
+ #
4
+ # This class's purpose is simply to provide a mock serial port for debugging
5
+ # purposes. Instead of writing to an actual TTY connection, it simply
6
+ # deserializes and returns the values passed into it. It's convenient because
7
+ # it allows one to test without requiring a physical Arduino.
8
+ class DebugPort
9
+ # @param [String] string the string of chars to be written to the mock
10
+ # serial port
11
+ #
12
+ # @return [Array<Fixnum>] an array containing the deserialized values found
13
+ # in +string+
14
+ def write(string)
15
+ string.chars.map(&:ord)
16
+ end
17
+ end
18
+ end
@@ -7,4 +7,13 @@ module Rustle
7
7
 
8
8
  # Raised when a user provides an invalid hexadecimal color
9
9
  class InvalidHexColorCode < Error; end
10
+
11
+ # Raised when a user does not provide a receiver when instantiating a strip
12
+ class ReceiverNotFound < Error; end
13
+
14
+ # Raised when a user does not specify the number of LEDs for a strip
15
+ class NumLEDsInvalid < Error; end
16
+
17
+ # Raised when a user tries to provide data that is not an array of {Color} objects
18
+ class InvalidLEDArray < Error; end
10
19
  end
data/lib/rustle/frame.rb CHANGED
@@ -28,6 +28,8 @@ module Rustle
28
28
  # @param [Array] leds n array of {Color} objects, whose length is the same
29
29
  # as the number of LEDs connected to the strip.
30
30
  def initialize(leds)
31
+ validate_leds(leds)
32
+
31
33
  @leds = leds
32
34
  end
33
35
 
@@ -38,5 +40,11 @@ module Rustle
38
40
  def serialize
39
41
  @leds.map(&:serialize).join + 255.chr
40
42
  end
43
+
44
+ private
45
+
46
+ def validate_leds(arr)
47
+ raise InvalidLEDArray unless arr.all? { |l| l.is_a? Color }
48
+ end
41
49
  end
42
50
  end
@@ -11,10 +11,7 @@ module Rustle
11
11
  #
12
12
  # The Receiver class is initialized using a block.
13
13
  #
14
- # bedroom_arduino = Rustle::Receiver.new do
15
- # port_file "/dev/[PORT_FILE]"
16
- # num_leds 30
17
- # end
14
+ # bedroom_arduino = Rustle::Receiver.new("/dev/[PORT_FILE]")
18
15
  #
19
16
  # Your port file can be found using the Arduino IDE.
20
17
  class Receiver
@@ -23,29 +20,33 @@ module Rustle
23
20
  # @return [Strip] the strip associated with the Receiver
24
21
  attr_reader :strip
25
22
 
26
- # Initializes a new receiver.
23
+ # Initializes a new receiver.
27
24
  #
28
25
  # @example
29
- # kitchen_arduino = Rustle::Receiver.new do
30
- # port_file "/dev/tty.usbmodem411" # replace this
31
- # num_leds 60
32
- # end
26
+ # kitchen_arduino = Rustle::Receiver.new("/deb/tty.usbmodem411",
27
+ # num_leds: 30, baud: 921_600, debug: false)
33
28
  #
34
- # @yieldparam [String] port_file the location of serial port file. It can be
29
+ # @param [String] port_file the location of serial port file. It can be
35
30
  # found in the Arduino IDE (or via Ino).
36
- # @yieldparam [Fixnum] baud (optional) the serial baud rate (make sure it matches the one in
31
+ # @param [Fixnum] baud the serial baud rate (make sure it matches the one in
37
32
  # your sketch)
38
- # @yieldparam [Fixnum] num_leds (optional) the total number of LEDs connected to your
33
+ # @param [Fixnum] num_leds the total number of LEDs connected to your
39
34
  # receiver. Note that this attribute only affects how the {Strip} object
40
35
  # is instantiated; the number of LEDs is not actually stored in the
41
36
  # Receiver object.
42
- def initialize(&block)
43
- # Default value
44
- @baud = 921_600
45
-
46
- instance_eval &block
37
+ # @param [Boolean] debug whether or not to enable debug mode. See
38
+ # {DebugPort}.
39
+ def initialize(port_file = nil, baud: 921_600, num_leds: 30, debug: false)
40
+ @port_file = port_file
41
+ @baud = baud
42
+ @debug = debug
43
+ @strip = Strip.new(self, num_leds)
47
44
 
48
45
  init_serialport
46
+
47
+ # Sending a blank frame upon initialization seems to fix all timing
48
+ # constraint problems.
49
+ @strip.off!
49
50
  end
50
51
 
51
52
  # Serializes +frame+ and sends it off to the the serial port. +push_frame+
@@ -58,16 +59,14 @@ module Rustle
58
59
 
59
60
  private
60
61
 
61
- # instance_eval-specific methods for our DSL
62
- def port_file(file); @port_file = file; end
63
- def baud(int); @baud = int; end
64
- def num_leds(count)
65
- @strip = Strip.new(self, count)
66
- end
67
-
68
- # Instantiates a new serial port
62
+ # Instantiates a new port
69
63
  def init_serialport
70
- @port = SerialPort.new @port_file, @baud, 8, 1, SerialPort::NONE
64
+ if @debug
65
+ @port = DebugPort.new
66
+ else
67
+ raise PortFileNotSpecified if @debug == false
68
+ @port = SerialPort.new @port_file, @baud, 8, 1, SerialPort::NONE
69
+ end
71
70
  end
72
71
  end
73
72
  end
data/lib/rustle/strip.rb CHANGED
@@ -3,7 +3,7 @@ require 'active_support/inflector'
3
3
  module Rustle
4
4
  # = Strips
5
5
  #
6
- # The Strip class' purpose is to respond to requests to change the color of
6
+ # The Strip class's purpose is to respond to requests to change the color of
7
7
  # the physical strip, and send changes to the {Receiver} when appropriate.
8
8
  # All Strip objects also have a buffer, which is simply an array of {Frame}
9
9
  # objects. Calling any method which advances to the next frame causes the
@@ -27,6 +27,9 @@ module Rustle
27
27
  @receiver = receiver
28
28
  @num_leds = num_leds
29
29
  @queue = []
30
+
31
+ raise ReceiverNotFound unless receiver.is_a? Receiver
32
+ raise NumLEDsInvalid unless @num_leds && @num_leds > 0
30
33
  end
31
34
 
32
35
  # @return [Frame] the next frame in the buffer. If the buffer only has one
@@ -56,6 +59,7 @@ module Rustle
56
59
 
57
60
  # Turns off all LEDs on the strip
58
61
  def off!
62
+ sleep 0.0025
59
63
  @queue << Frame.new([Color.new(0,0,0)] * @num_leds)
60
64
  next_frame!
61
65
  end
@@ -64,6 +68,7 @@ module Rustle
64
68
  #
65
69
  # @param [Color] color
66
70
  def to(color)
71
+ sleep 0.0025
67
72
  @queue << Frame.new([color] * @num_leds)
68
73
  next_frame!
69
74
  end
@@ -89,7 +94,7 @@ module Rustle
89
94
  # :fade_to => FadeToTransition
90
95
  klass = "#{klass.to_s.camelize}Transition".constantize
91
96
 
92
- klass.new(self, duration, opts).frames
97
+ klass.new(self, duration, opts)
93
98
  end
94
99
  end
95
100
  end
@@ -1,3 +1,3 @@
1
1
  module Rustle
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
data/lib/rustle.rb CHANGED
@@ -4,10 +4,13 @@ require "rustle/receiver"
4
4
  require "rustle/strip"
5
5
  require "rustle/color"
6
6
  require "rustle/frame"
7
+
7
8
  require "rustle/transition"
8
9
  require "rustle/transitions/wipe_to_transition"
9
10
  require "rustle/transitions/fade_to_transition"
11
+
10
12
  require "rustle/exceptions"
13
+ require "rustle/debug_port"
11
14
 
12
15
  module Rustle
13
16
  FRAME_RATE = 60
data/spec/color_spec.rb CHANGED
@@ -8,49 +8,38 @@ describe Rustle::Color do
8
8
  let(:color_with_invalid_params) { Rustle::Color.new(-100,1000,0) }
9
9
 
10
10
  it "corrects negative rgb values to zero" do
11
- (color_with_invalid_params.r).should eq(0)
11
+ expect(color_with_invalid_params.r).to eq(0)
12
12
  end
13
13
 
14
14
  it "corrects very large rgb values to 255" do
15
- (color_with_invalid_params.g).should eq(255)
15
+ expect(color_with_invalid_params.g).to eq(255)
16
16
  end
17
17
 
18
18
  it "makes no changes to rgb values between 0 and 255" do
19
19
  color1 = Rustle::Color.new(0,0,0)
20
- (color1.r).should eq(0)
21
- (color1.g).should eq(0)
22
- (color1.b).should eq(0)
20
+ expect(color1.r).to eq(0)
21
+ expect(color1.g).to eq(0)
22
+ expect(color1.b).to eq(0)
23
23
 
24
24
  color2 = Rustle::Color.new(255,255,255)
25
- (color2.r).should eq(255)
26
- (color2.g).should eq(255)
27
- (color2.b).should eq(255)
25
+ expect(color2.r).to eq(255)
26
+ expect(color2.g).to eq(255)
27
+ expect(color2.b).to eq(255)
28
28
  end
29
29
  end
30
30
 
31
31
  describe "#to_a" do
32
32
  it "returns an array" do
33
- (color.to_a).should be_a(Array)
33
+ expect(color.to_a).to be_a(Array)
34
34
  end
35
35
 
36
36
  it "the array has the correct [r,g,b] values" do
37
- (color.to_a).should eq([128,128,128])
37
+ expect(color.to_a).to eq([128,128,128])
38
38
  end
39
39
 
40
40
  it "rounds decimal values down to the nearest whole number" do
41
41
  fractional_rgbs = Rustle::Color.rgb(0.5,10.7,99.9)
42
- (fractional_rgbs.to_a).should eq([0, 10, 99])
43
- end
44
- end
45
-
46
- describe "#to_s" do
47
- it "returns a string with information about the color" do
48
- (color.to_s).should eq("rgb(128, 128, 128)")
49
- end
50
-
51
- it "pads strings so that even small rgb values align properly" do
52
- other_color = Rustle::Color.rgb(0,1,2)
53
- (other_color.to_s).should eq("rgb( 0, 1, 2)")
42
+ expect(fractional_rgbs.to_a).to eq([0, 10, 99])
54
43
  end
55
44
  end
56
45
 
@@ -60,11 +49,11 @@ describe Rustle::Color do
60
49
  let(:colorB) { Rustle::Color.rgb(0, 0, 0) }
61
50
 
62
51
  it "returns true if the reciever and parameter objects hold equivalent rgb values" do
63
- (colorA.eql?(another_colorA)).should be_true
52
+ expect(colorA.eql?(another_colorA)).to be_true
64
53
  end
65
54
 
66
55
  it "returns false if the reciever and parameter objects differ in rgb values" do
67
- (colorA.eql?(colorB)).should be_false
56
+ expect(colorA.eql?(colorB)).to be_false
68
57
  end
69
58
  end
70
59
 
@@ -75,11 +64,11 @@ describe Rustle::Color do
75
64
  let (:badass) { Rustle::Color.hex "BADA55" }
76
65
 
77
66
  it "creates a color object" do
78
- (badass).should be_a(Rustle::Color)
67
+ expect(badass).to be_a(Rustle::Color)
79
68
  end
80
69
 
81
70
  it "has the proper rgb values" do
82
- (badass).should eql(badass_rgb)
71
+ expect(badass).to eql(badass_rgb)
83
72
  end
84
73
  end
85
74
 
@@ -87,11 +76,11 @@ describe Rustle::Color do
87
76
  let(:badass) { Rustle::Color.hex "#BADA55" }
88
77
 
89
78
  it "creates a color object" do
90
- (badass).should be_a(Rustle::Color)
79
+ expect(badass).to be_a(Rustle::Color)
91
80
  end
92
81
 
93
82
  it "has the right rgb values" do
94
- (badass).should eql(badass_rgb)
83
+ expect(badass).to eql(badass_rgb)
95
84
  end
96
85
  end
97
86
 
@@ -100,18 +89,18 @@ describe Rustle::Color do
100
89
  let(:bad_rgb) { Rustle::Color.rgb 187, 170, 221 }
101
90
 
102
91
  it "creates a color object" do
103
- (bad_hex).should be_a(Rustle::Color)
92
+ expect(bad_hex).to be_a(Rustle::Color)
104
93
  end
105
94
 
106
95
  it "should have the correct rgb values" do
107
- (bad_hex).should eql(bad_rgb)
96
+ expect(bad_hex).to eql(bad_rgb)
108
97
  end
109
98
  end
110
99
 
111
100
  it "is case insensitive" do
112
101
  first_badass = Rustle::Color.hex "#BADa55"
113
102
  second_badass = Rustle::Color.hex "#badA55"
114
- (first_badass).should eql(second_badass)
103
+ expect(first_badass).to eql(second_badass)
115
104
  end
116
105
 
117
106
  it "raises an error when given an invalid color code string" do
@@ -127,14 +116,14 @@ describe Rustle::Color do
127
116
  # HSV: 260 (260), saturation: 23 (23.0769), value: 87 (86.6667)
128
117
 
129
118
  it "produces a color object" do
130
- hsb.should be_a(Rustle::Color)
119
+ expect(hsb).to be_a(Rustle::Color)
131
120
  end
132
121
 
133
122
  it "has the correct rgb properties" do
134
123
  # Use be_within to give some allowance for rounting errors
135
- (hsb.r).should be_within(3).of(rgb.r)
136
- (hsb.g).should be_within(3).of(rgb.g)
137
- (hsb.b).should be_within(3).of(rgb.b)
124
+ expect(hsb.r).to be_within(3).of(rgb.r)
125
+ expect(hsb.g).to be_within(3).of(rgb.g)
126
+ expect(hsb.b).to be_within(3).of(rgb.b)
138
127
  end
139
128
  end
140
129
 
@@ -142,14 +131,14 @@ describe Rustle::Color do
142
131
  let(:hsb) { Rustle::Color.hsb 180, 0.5, 0.8 }
143
132
 
144
133
  it "returns an array of [h,s,v] coordinates" do
145
- color.to_hsb.should be_a(Array)
134
+ expect(color.to_hsb).to be_a(Array)
146
135
  end
147
136
 
148
137
  it "should have the (approximate) [h,s,v] coordinates" do
149
138
  hsb_arr = hsb.to_hsb
150
- hsb_arr[0].should be_within(1).of(180)
151
- hsb_arr[1].should be_within(0.1).of(0.5)
152
- hsb_arr[2].should be_within(0.1).of(0.8)
139
+ expect(hsb_arr[0]).to be_within(1).of(180)
140
+ expect(hsb_arr[1]).to be_within(0.1).of(0.5)
141
+ expect(hsb_arr[2]).to be_within(0.1).of(0.8)
153
142
  end
154
143
 
155
144
  end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rustle::Frame do
4
+ describe "initialization" do
5
+ it "should require a valid array of LEDs" do
6
+ valid = [Rustle::Color.rgb(255, 0, 0)] * 5
7
+ invalid = ["poop"] * 5
8
+
9
+ expect { Rustle::Frame.new(invalid) }
10
+ .to raise_error(Rustle::InvalidLEDArray)
11
+
12
+ expect { Rustle::Frame.new(valid) }
13
+ .not_to raise_error
14
+ end
15
+ end
16
+ end
@@ -1,5 +1,32 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Rustle::Receiver do
4
- it "does nothing"
4
+ describe "#initialize" do
5
+ let(:receiver) do
6
+ Rustle::Receiver.new(nil, num_leds: 30, debug: true)
7
+ end
8
+
9
+ it "should intantiate a Strip with the appropriate number of LEDs" do
10
+ expect(receiver.strip).to be_a(Rustle::Strip)
11
+ expect(receiver.strip.num_leds).to eq(30)
12
+ end
13
+
14
+ it "should only require a portfile when not in debug mode" do
15
+ expect { Rustle::Receiver.new(nil, debug: false) }
16
+ .to raise_error(Rustle::PortFileNotSpecified)
17
+ expect { Rustle::Receiver.new(nil, debug: true) }
18
+ .not_to raise_error
19
+ end
20
+ end
21
+
22
+ describe "#push_frame" do
23
+ let(:receiver) do
24
+ Rustle::Receiver.new(nil, num_leds: 30, debug: true)
25
+ end
26
+
27
+ it "should send a frame to the port" do
28
+ frame = Rustle::Frame.new([Rustle::Color.new(0,0,0)] * 30)
29
+ expect(receiver.push_frame(frame)).to have(91).items
30
+ end
31
+ end
5
32
  end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rustle::Strip do
4
+ context "when initializing" do
5
+ it "should require a receiver" do
6
+ expect { Rustle::Strip.new(nil, 30) }.to raise_error(Rustle::ReceiverNotFound)
7
+ end
8
+
9
+ it "should require an LED count" do
10
+ receiver = Rustle::Receiver.new(nil, debug: true)
11
+ expect { Rustle::Strip.new(receiver, nil) }.to raise_error(Rustle::NumLEDsInvalid)
12
+ end
13
+ end
14
+
15
+ describe "queue" do
16
+ let(:strip) { Rustle::Receiver.new(nil, num_leds: 5, debug: true).strip }
17
+
18
+ it "should be initialized with a black frame" do
19
+ expect(strip.current_frame).to_not be_nil
20
+ end
21
+
22
+ it "should be initialized with a black frame" do
23
+ frame = Rustle::Frame.new [Rustle::Color.new(255, 0, 0)] * 5
24
+
25
+ strip.queue_frames [frame]
26
+ expect(strip.next_frame).to_not be_nil
27
+
28
+ # After advancing to the next frame, there shouldn't be a next_frame
29
+ strip.next_frame!
30
+ expect(strip.next_frame).to eq(strip.current_frame)
31
+ end
32
+ end
33
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rustle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Hamon
@@ -117,6 +117,7 @@ files:
117
117
  - Rakefile
118
118
  - lib/rustle.rb
119
119
  - lib/rustle/color.rb
120
+ - lib/rustle/debug_port.rb
120
121
  - lib/rustle/exceptions.rb
121
122
  - lib/rustle/frame.rb
122
123
  - lib/rustle/receiver.rb
@@ -129,8 +130,10 @@ files:
129
130
  - rustle_logo.png
130
131
  - sketches/basic.ino
131
132
  - spec/color_spec.rb
133
+ - spec/frame_spec.rb
132
134
  - spec/receiver_spec.rb
133
135
  - spec/spec_helper.rb
136
+ - spec/strip_spec.rb
134
137
  homepage: ''
135
138
  licenses:
136
139
  - MIT
@@ -158,6 +161,8 @@ specification_version: 4
158
161
  summary: Control an individually-addressable RGB LED strip in Ruby.
159
162
  test_files:
160
163
  - spec/color_spec.rb
164
+ - spec/frame_spec.rb
161
165
  - spec/receiver_spec.rb
162
166
  - spec/spec_helper.rb
167
+ - spec/strip_spec.rb
163
168
  has_rdoc: