blinkytape-orb 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +5 -0
- data/Gemfile +8 -0
- data/README.md +45 -0
- data/arduino/blinkytape_orb.ino +230 -0
- data/blinkytape-orb.gemspec +21 -0
- data/lib/blinkytape-orb.rb +92 -0
- data/lib/blinkytape-orb/version.rb +3 -0
- data/spec/lib/.blinkytape-orb_spec.rb.swp +0 -0
- data/spec/lib/blinkytape-orb_spec.rb +145 -0
- data/spec/spec_helper.rb +13 -0
- metadata +70 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
M2U5ZTcxOWE3OGMxYTllMWY1YTMzNTY4MGZjMzJkYzRmNDdiNjk3Yg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MTA2NDAwNjY4YTZjNWM4MjZlNDBkMTcxNjU3NzkxOGEyYzliNDY3Mg==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ZWUzZTk1YzEwYWMxMzJiMGJiZTU0NjdjMjFiMjRjOTdmOGU2Zjk3NDkwM2U2
|
10
|
+
MTExY2U4ODdlZDFhYjE4NTNlYTcwMTQ5NWMxOTRiZjY0OWVlMDFhMGRiNjNj
|
11
|
+
NjYzYTY4YTk4ZmQ4ZDc1OTA2N2IxMjZlOTlmMTRiYzg0ZTU4Y2E=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
ZjdjYTNmZGZmYmI3MGE3N2ZmYWUwMDViNWUxMjAzMzlmZmIwYWIyNzFkNDky
|
14
|
+
ZjM1NDM0N2I2ODllNDhlMmM3YTdhNWExNTMwMzgxZjY3NDlhYWMyYzAxMjA4
|
15
|
+
YTdjZTRlNzUzZjljM2MxZjAzNmZhMjQwNjEzOGJkZTlmOTUzMWQ=
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
BlinkyTape Orb
|
2
|
+
==============
|
3
|
+
|
4
|
+
Ruby code to interface with a [BlinkyTape controller board](http://blinkinlabs.myshopify.com/collections/frontpage/products/blinkytape-control-board)
|
5
|
+
running the custom firmware in the `arduino` directory of this repository. See
|
6
|
+
the [Blinkinlabs arduino instructions](http://blinkinlabs.com/blinkytape/arduino/)
|
7
|
+
for how to install the firmware. The firmware can be made to work on an Arduino
|
8
|
+
Uno R3 with some modifications, mainly around the button handling.
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
require 'blinkytape-orb'
|
12
|
+
|
13
|
+
# device is automatically detected on OS X
|
14
|
+
orb = BlinkyTapeOrb.new
|
15
|
+
|
16
|
+
# a device can be passed manually
|
17
|
+
#orb = BlinkyTapeOrb.new(:device => '/dev/ttyS0')
|
18
|
+
|
19
|
+
# a logger can also be passed
|
20
|
+
#orb = BlinkyTapeOrb.new(:logger => Logger.new(STDOUT))
|
21
|
+
#orb.logger.level = Logger::DEBUG
|
22
|
+
|
23
|
+
[
|
24
|
+
BlinkyTapeOrb::BRIGHTNESS_MIN,
|
25
|
+
BlinkyTapeOrb::BRIGHTNESS_MED,
|
26
|
+
BlinkyTapeOrb::BRIGHTNESS_MAX,
|
27
|
+
].each do |brightness|
|
28
|
+
orb.setBrightness(brightness)
|
29
|
+
sleep(1)
|
30
|
+
end
|
31
|
+
|
32
|
+
sleep(3)
|
33
|
+
|
34
|
+
[
|
35
|
+
[ BlinkyTapeOrb::COLOR_GREEN, BlinkyTapeOrb::PULSE_NONE ],
|
36
|
+
[ BlinkyTapeOrb::COLOR_BLUE, BlinkyTapeOrb::PULSE_SLOW ],
|
37
|
+
[ BlinkyTapeOrb::COLOR_PURPLE, BlinkyTapeOrb::PULSE_SLOW ],
|
38
|
+
[ BlinkyTapeOrb::COLOR_YELLOW, BlinkyTapeOrb::PULSE_MED ],
|
39
|
+
[ BlinkyTapeOrb::COLOR_ORANGE, BlinkyTapeOrb::PULSE_MED ],
|
40
|
+
[ BlinkyTapeOrb::COLOR_RED, BlinkyTapeOrb::PULSE_FAST ],
|
41
|
+
].each do |(color, animation)|
|
42
|
+
orb.update(color, animation)
|
43
|
+
sleep(10)
|
44
|
+
end
|
45
|
+
```
|
@@ -0,0 +1,230 @@
|
|
1
|
+
#include "FastLED.h"
|
2
|
+
|
3
|
+
// hardware
|
4
|
+
#define NUM_LEDS 12
|
5
|
+
#define LED_CORRECTION TypicalSMD5050
|
6
|
+
|
7
|
+
#define DATA_PIN 13
|
8
|
+
#define BUTTON_IN 10
|
9
|
+
#define ANALOG_INPUT A9
|
10
|
+
#define EXTRA_PIN_A 7
|
11
|
+
#define EXTRA_PIN_B 11
|
12
|
+
|
13
|
+
// visuals
|
14
|
+
#define PULSE_MAX_VAL 255
|
15
|
+
#define PULSE_MIN_VAL 160
|
16
|
+
#define PULSE_DURATION_SLOW 3000
|
17
|
+
#define PULSE_DURATION_MED 1500
|
18
|
+
#define PULSE_DURATION_FAST 0
|
19
|
+
|
20
|
+
#define CHANGE_MIN_VAL 64
|
21
|
+
#define CHANGE_DURATION 800
|
22
|
+
|
23
|
+
#define BRIGHTNESS_MAX 255
|
24
|
+
#define BRIGHTNESS_MED 106
|
25
|
+
#define BRIGHTNESS_MIN 32
|
26
|
+
|
27
|
+
// state
|
28
|
+
CRGB leds[NUM_LEDS];
|
29
|
+
|
30
|
+
bool initialized;
|
31
|
+
|
32
|
+
uint8_t hue;
|
33
|
+
uint8_t val;
|
34
|
+
bool pulse;
|
35
|
+
long pulse_duration;
|
36
|
+
|
37
|
+
bool buttonDebounced;
|
38
|
+
uint8_t brightness;
|
39
|
+
|
40
|
+
|
41
|
+
void fade(uint8_t new_val, long duration) {
|
42
|
+
if (val == new_val) {
|
43
|
+
// setBrightness() requires a call to delay() periodically
|
44
|
+
FastLED.delay(duration);
|
45
|
+
return;
|
46
|
+
}
|
47
|
+
|
48
|
+
int incr;
|
49
|
+
long delay_ms;
|
50
|
+
long change_delay_ms;
|
51
|
+
if (val < new_val) {
|
52
|
+
incr = 1;
|
53
|
+
delay_ms = duration / (new_val - val);
|
54
|
+
if (CHANGE_DURATION / 2 < duration) {
|
55
|
+
change_delay_ms = (CHANGE_DURATION / 2) / (new_val - val);
|
56
|
+
} else {
|
57
|
+
change_delay_ms = delay_ms;
|
58
|
+
}
|
59
|
+
} else if (val > new_val) {
|
60
|
+
incr = -1;
|
61
|
+
delay_ms = duration / (val - new_val);
|
62
|
+
if (CHANGE_DURATION / 2 < duration) {
|
63
|
+
change_delay_ms = (CHANGE_DURATION / 2) / (val - new_val);
|
64
|
+
} else {
|
65
|
+
change_delay_ms = delay_ms;
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
for (uint8_t v = val; v != new_val; v += incr) {
|
70
|
+
for (int i = 0; i < NUM_LEDS; i++) {
|
71
|
+
if (initialized) {
|
72
|
+
leds[i] = CHSV(hue, 255, v);
|
73
|
+
} else {
|
74
|
+
leds[i] = CRGB(v, v, v);
|
75
|
+
}
|
76
|
+
}
|
77
|
+
FastLED.show();
|
78
|
+
|
79
|
+
// check to see if we've been given a new command, if so, hurry things along
|
80
|
+
if (Serial.available() > 0) {
|
81
|
+
FastLED.delay(change_delay_ms);
|
82
|
+
} else {
|
83
|
+
FastLED.delay(delay_ms);
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
val = new_val;
|
88
|
+
}
|
89
|
+
|
90
|
+
void setup() {
|
91
|
+
Serial.begin(57600);
|
92
|
+
|
93
|
+
FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
|
94
|
+
FastLED.setCorrection(LED_CORRECTION);
|
95
|
+
|
96
|
+
initialized = false;
|
97
|
+
|
98
|
+
val = PULSE_MAX_VAL;
|
99
|
+
pulse = true;
|
100
|
+
pulse_duration = PULSE_DURATION_MED;
|
101
|
+
|
102
|
+
brightness = BRIGHTNESS_MED;
|
103
|
+
FastLED.setBrightness(brightness);
|
104
|
+
|
105
|
+
for (int i = 0; i < NUM_LEDS; i++) {
|
106
|
+
leds[i] = CRGB(val, val, val);
|
107
|
+
}
|
108
|
+
FastLED.show();
|
109
|
+
|
110
|
+
pinMode(BUTTON_IN, INPUT_PULLUP);
|
111
|
+
pinMode(ANALOG_INPUT, INPUT_PULLUP);
|
112
|
+
pinMode(EXTRA_PIN_A, INPUT_PULLUP);
|
113
|
+
pinMode(EXTRA_PIN_B, INPUT_PULLUP);
|
114
|
+
|
115
|
+
// Interrupt set-up; see Atmega32u4 datasheet section 11
|
116
|
+
PCIFR |= (1 << PCIF0); // Just in case, clear interrupt flag
|
117
|
+
PCMSK0 |= (1 << PCINT6); // Set interrupt mask to the button pin (PCINT6)
|
118
|
+
PCICR |= (1 << PCIE0); // Enable interrupt
|
119
|
+
}
|
120
|
+
|
121
|
+
void loop() {
|
122
|
+
if (pulse) {
|
123
|
+
fade(PULSE_MIN_VAL, pulse_duration / 2);
|
124
|
+
}
|
125
|
+
|
126
|
+
if (Serial.available() > 0) {
|
127
|
+
byte c = Serial.read();
|
128
|
+
c -= 65; // align to ASCII "A"
|
129
|
+
switch (c) {
|
130
|
+
case 32:
|
131
|
+
brightness = BRIGHTNESS_MIN;
|
132
|
+
FastLED.setBrightness(brightness);
|
133
|
+
break;
|
134
|
+
case 33:
|
135
|
+
brightness = BRIGHTNESS_MED;
|
136
|
+
FastLED.setBrightness(brightness);
|
137
|
+
break;
|
138
|
+
case 34:
|
139
|
+
brightness = BRIGHTNESS_MAX;
|
140
|
+
FastLED.setBrightness(brightness);
|
141
|
+
break;
|
142
|
+
default:
|
143
|
+
if (c < 24) { // filter out garbage values
|
144
|
+
fade(CHANGE_MIN_VAL, CHANGE_DURATION / 2);
|
145
|
+
|
146
|
+
switch (c & B00000011) {
|
147
|
+
case 0:
|
148
|
+
pulse = false;
|
149
|
+
pulse_duration = CHANGE_DURATION;
|
150
|
+
break;
|
151
|
+
case 1:
|
152
|
+
pulse = true;
|
153
|
+
pulse_duration = PULSE_DURATION_SLOW;
|
154
|
+
break;
|
155
|
+
case 2:
|
156
|
+
pulse = true;
|
157
|
+
pulse_duration = PULSE_DURATION_MED;
|
158
|
+
break;
|
159
|
+
case 3:
|
160
|
+
pulse = true;
|
161
|
+
pulse_duration = PULSE_DURATION_FAST;
|
162
|
+
break;
|
163
|
+
}
|
164
|
+
|
165
|
+
switch ((c & B00011100) >> 2) {
|
166
|
+
case 0:
|
167
|
+
hue = HUE_RED;
|
168
|
+
break;
|
169
|
+
case 1:
|
170
|
+
hue = HUE_ORANGE;
|
171
|
+
break;
|
172
|
+
case 2:
|
173
|
+
hue = HUE_YELLOW;
|
174
|
+
break;
|
175
|
+
case 3:
|
176
|
+
hue = HUE_GREEN;
|
177
|
+
break;
|
178
|
+
case 4:
|
179
|
+
hue = HUE_BLUE;
|
180
|
+
break;
|
181
|
+
case 5:
|
182
|
+
hue = HUE_PURPLE;
|
183
|
+
break;
|
184
|
+
}
|
185
|
+
|
186
|
+
initialized = true;
|
187
|
+
|
188
|
+
fade(PULSE_MIN_VAL, CHANGE_DURATION / 2);
|
189
|
+
}
|
190
|
+
break;
|
191
|
+
}
|
192
|
+
}
|
193
|
+
|
194
|
+
fade(PULSE_MAX_VAL, pulse_duration / 2);
|
195
|
+
}
|
196
|
+
|
197
|
+
// Called when the button is both pressed and released
|
198
|
+
ISR(PCINT0_vect){
|
199
|
+
if (!(PINB & (1 << PINB6))) {
|
200
|
+
buttonDebounced = false;
|
201
|
+
|
202
|
+
// Configure and start timer4 interrupt.
|
203
|
+
TCCR4B = 0x0F; // Slowest prescaler
|
204
|
+
TCCR4D = _BV(WGM41) | _BV(WGM40); // Fast PWM mode
|
205
|
+
OCR4C = 0x10; // some random percentage of the clock
|
206
|
+
TCNT4 = 0; // Reset the counter
|
207
|
+
TIMSK4 = _BV(TOV4); // turn on the interrupt
|
208
|
+
} else {
|
209
|
+
TIMSK4 = 0; // turn off the interrupt
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
// Called every xx ms while the button is being held down
|
214
|
+
ISR(TIMER4_OVF_vect) {
|
215
|
+
if (buttonDebounced == false) {
|
216
|
+
buttonDebounced = true;
|
217
|
+
switch (brightness) {
|
218
|
+
case BRIGHTNESS_MIN:
|
219
|
+
brightness = BRIGHTNESS_MED;
|
220
|
+
break;
|
221
|
+
case BRIGHTNESS_MED:
|
222
|
+
brightness = BRIGHTNESS_MAX;
|
223
|
+
break;
|
224
|
+
case BRIGHTNESS_MAX:
|
225
|
+
brightness = BRIGHTNESS_MIN;
|
226
|
+
break;
|
227
|
+
}
|
228
|
+
FastLED.setBrightness(brightness);
|
229
|
+
}
|
230
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
require 'blinkytape-orb/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "blinkytape-orb"
|
8
|
+
s.version = BlinkyTapeOrb::VERSION
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.authors = ["Jon Tai"]
|
11
|
+
s.email = ["jon.tai@gmail.com"]
|
12
|
+
s.homepage = "https://github.com/jtai/blinkytape-orb"
|
13
|
+
s.summary = "Ruby code to interface with BlinkyTape controller board running custom firmware"
|
14
|
+
s.description = "Other hardware (e.g., arduino) may be supported with minor firmware modifications"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
18
|
+
s.require_path = 'lib'
|
19
|
+
|
20
|
+
s.add_runtime_dependency 'serialport', '>= 1.3.1'
|
21
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'blinkytape-orb/version'
|
2
|
+
require 'logger'
|
3
|
+
require 'serialport'
|
4
|
+
|
5
|
+
class BlinkyTapeOrb
|
6
|
+
|
7
|
+
SERIAL_PORT_BAUD_RATE = 57600
|
8
|
+
|
9
|
+
COLOR_RED = 0
|
10
|
+
COLOR_ORANGE = 1
|
11
|
+
COLOR_YELLOW = 2
|
12
|
+
COLOR_GREEN = 3
|
13
|
+
COLOR_BLUE = 4
|
14
|
+
COLOR_PURPLE = 5
|
15
|
+
|
16
|
+
PULSE_NONE = 0
|
17
|
+
PULSE_SLOW = 1
|
18
|
+
PULSE_MED = 2
|
19
|
+
PULSE_FAST = 3
|
20
|
+
|
21
|
+
BRIGHTNESS_MIN = 0
|
22
|
+
BRIGHTNESS_MED = 1
|
23
|
+
BRIGHTNESS_MAX = 2
|
24
|
+
|
25
|
+
def initialize(options = {})
|
26
|
+
@opts = options
|
27
|
+
end
|
28
|
+
|
29
|
+
def device
|
30
|
+
@device ||= begin
|
31
|
+
dev = @opts[:device] || autodetect_device
|
32
|
+
|
33
|
+
unless dev && File.exist?(dev) && File.stat(dev).chardev?
|
34
|
+
raise ArgumentError, 'invalid device'
|
35
|
+
end
|
36
|
+
|
37
|
+
logger.info("selected device #{dev}")
|
38
|
+
|
39
|
+
dev
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def logger
|
44
|
+
@logger ||= begin
|
45
|
+
@opts[:logger] || Logger.new(nil)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def update(color, pulse)
|
50
|
+
if (color < 0 || color > 5)
|
51
|
+
raise ArgumentError, 'color must be between 0 and 5'
|
52
|
+
end
|
53
|
+
|
54
|
+
if (pulse < 0 || pulse > 3)
|
55
|
+
raise ArgumentError, 'pulse must be between 0 and 3'
|
56
|
+
end
|
57
|
+
|
58
|
+
logger.info("updating with color=#{color}, pulse=#{pulse}")
|
59
|
+
|
60
|
+
send((65 + (color * 4) + pulse).chr)
|
61
|
+
end
|
62
|
+
|
63
|
+
def setBrightness(brightness)
|
64
|
+
if (brightness < 0 || brightness > 2)
|
65
|
+
raise ArgumentError, 'brightness must be between 0 and 2'
|
66
|
+
end
|
67
|
+
|
68
|
+
logger.info("setting brightness=#{brightness}")
|
69
|
+
|
70
|
+
send((65 + 32 + brightness).chr)
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def autodetect_device
|
76
|
+
devices = Dir.glob('/dev/*.usbmodem*') + Dir.glob('/dev/*.usbserial*')
|
77
|
+
|
78
|
+
devices.each do |dev|
|
79
|
+
logger.debug("autodetect_device found #{dev}")
|
80
|
+
end
|
81
|
+
|
82
|
+
devices.first
|
83
|
+
end
|
84
|
+
|
85
|
+
def send(command)
|
86
|
+
SerialPort.open(device, SERIAL_PORT_BAUD_RATE) do |serial_port|
|
87
|
+
logger.debug("send \"#{command}\"")
|
88
|
+
serial_port.write(command)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
Binary file
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BlinkyTapeOrb do
|
4
|
+
|
5
|
+
let (:options) { {} }
|
6
|
+
let (:orb) { BlinkyTapeOrb.new(options) }
|
7
|
+
|
8
|
+
describe '#device' do
|
9
|
+
|
10
|
+
context 'with valid device option' do
|
11
|
+
let (:options) { { :device => '/dev/zero' } }
|
12
|
+
|
13
|
+
it 'returns device' do
|
14
|
+
expect(orb.device).to eq('/dev/zero')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'with non-existent device' do
|
19
|
+
let (:options) { { :device => '/dev/nosuchdevice' } }
|
20
|
+
|
21
|
+
it 'raises ArgumentError' do
|
22
|
+
expect {
|
23
|
+
orb.device
|
24
|
+
}.to raise_error(ArgumentError)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'with block device' do
|
29
|
+
let (:options) { { :device => `df #{__FILE__} | tail -1 | cut -d ' ' -f 1` } }
|
30
|
+
|
31
|
+
it 'raises ArgumentError' do
|
32
|
+
expect {
|
33
|
+
orb.device
|
34
|
+
}.to raise_error(ArgumentError)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'with autodetected device' do
|
39
|
+
it 'returns first device matching pattern' do
|
40
|
+
expect(Dir).to receive(:glob).twice.and_return(['/dev/urandom', '/dev/random'])
|
41
|
+
expect(orb.device).to eq('/dev/urandom')
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#update' do
|
48
|
+
|
49
|
+
let (:color) { BlinkyTapeOrb::COLOR_RED }
|
50
|
+
let (:pulse) { BlinkyTapeOrb::PULSE_NONE }
|
51
|
+
|
52
|
+
context 'with out of range color' do
|
53
|
+
let (:color) { 6 }
|
54
|
+
|
55
|
+
it 'raises ArgumentError' do
|
56
|
+
expect {
|
57
|
+
orb.update(color, pulse)
|
58
|
+
}.to raise_error(ArgumentError)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'with out of range pulse' do
|
63
|
+
let (:pulse) { 4 }
|
64
|
+
|
65
|
+
it 'raises ArgumentError' do
|
66
|
+
expect {
|
67
|
+
orb.update(color, pulse)
|
68
|
+
}.to raise_error(ArgumentError)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'with valid arguments' do
|
73
|
+
it 'sends correct update' do
|
74
|
+
expect(orb).to receive(:send).with('A')
|
75
|
+
orb.update(color, pulse)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'with purple color' do
|
80
|
+
let (:color) { BlinkyTapeOrb::COLOR_PURPLE }
|
81
|
+
|
82
|
+
it 'sends correct update' do
|
83
|
+
expect(orb).to receive(:send).with('U')
|
84
|
+
orb.update(color, pulse)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'with fast pulse' do
|
89
|
+
let (:pulse) { BlinkyTapeOrb::PULSE_FAST }
|
90
|
+
|
91
|
+
it 'sends correct update' do
|
92
|
+
expect(orb).to receive(:send).with('D')
|
93
|
+
orb.update(color, pulse)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
describe '#setBrightness' do
|
100
|
+
|
101
|
+
let (:brightness) { BlinkyTapeOrb::BRIGHTNESS_MAX }
|
102
|
+
|
103
|
+
context 'with out of range brightness' do
|
104
|
+
let (:brightness) { 3 }
|
105
|
+
|
106
|
+
it 'raises ArgumentError' do
|
107
|
+
expect {
|
108
|
+
orb.setBrightness(brightness)
|
109
|
+
}.to raise_error(ArgumentError)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'with valid arguments' do
|
114
|
+
it 'sends correct update' do
|
115
|
+
expect(orb).to receive(:send).with('c')
|
116
|
+
orb.setBrightness(brightness)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'with min brightness' do
|
121
|
+
let (:brightness) { BlinkyTapeOrb::BRIGHTNESS_MIN }
|
122
|
+
|
123
|
+
it 'sends correct update' do
|
124
|
+
expect(orb).to receive(:send).with('a')
|
125
|
+
orb.setBrightness(brightness)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
describe '#send' do
|
132
|
+
|
133
|
+
let (:options) { { :device => '/dev/zero' } }
|
134
|
+
let (:io) { IO.new }
|
135
|
+
|
136
|
+
it 'sends commands' do
|
137
|
+
io = double('serial_port')
|
138
|
+
expect(io).to receive(:write).with('A')
|
139
|
+
expect(SerialPort).to receive(:open).and_yield(io)
|
140
|
+
orb.update(BlinkyTapeOrb::COLOR_RED, BlinkyTapeOrb::PULSE_NONE)
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: blinkytape-orb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jon Tai
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-01-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: serialport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ! '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.3.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ! '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.3.1
|
27
|
+
description: Other hardware (e.g., arduino) may be supported with minor firmware modifications
|
28
|
+
email:
|
29
|
+
- jon.tai@gmail.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- .gitignore
|
35
|
+
- Gemfile
|
36
|
+
- README.md
|
37
|
+
- arduino/blinkytape_orb.ino
|
38
|
+
- blinkytape-orb.gemspec
|
39
|
+
- lib/blinkytape-orb.rb
|
40
|
+
- lib/blinkytape-orb/version.rb
|
41
|
+
- spec/lib/.blinkytape-orb_spec.rb.swp
|
42
|
+
- spec/lib/blinkytape-orb_spec.rb
|
43
|
+
- spec/spec_helper.rb
|
44
|
+
homepage: https://github.com/jtai/blinkytape-orb
|
45
|
+
licenses: []
|
46
|
+
metadata: {}
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements: []
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 2.0.0
|
64
|
+
signing_key:
|
65
|
+
specification_version: 4
|
66
|
+
summary: Ruby code to interface with BlinkyTape controller board running custom firmware
|
67
|
+
test_files:
|
68
|
+
- spec/lib/.blinkytape-orb_spec.rb.swp
|
69
|
+
- spec/lib/blinkytape-orb_spec.rb
|
70
|
+
- spec/spec_helper.rb
|