blinkytape-orb 0.0.1
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.
- 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
|