BBB 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/examples/analog_pin.rb +4 -6
- data/examples/{led.rb → blinker.rb} +2 -3
- data/examples/ldr_light_switch.rb +16 -22
- data/examples/light_switch.rb +10 -33
- data/examples/{nunchuck.rb → nunchuck_websocket.rb} +13 -13
- data/examples/quadcopter.rb +77 -0
- data/examples/servo_ldr.rb +104 -14
- data/lib/BBB.rb +16 -2
- data/lib/BBB/application.rb +10 -4
- data/lib/BBB/attachable.rb +77 -0
- data/lib/BBB/circuit.rb +7 -47
- data/lib/BBB/components/button.rb +45 -5
- data/lib/BBB/components/esc.rb +1 -1
- data/lib/BBB/components/led.rb +19 -0
- data/lib/BBB/components/nunchuck.rb +0 -43
- data/lib/BBB/components/pinnable.rb +4 -1
- data/lib/BBB/components/wii_motion_plus.rb +4 -0
- data/lib/BBB/configuration.rb +14 -0
- data/lib/BBB/pins/pinnable.rb +1 -1
- data/lib/BBB/version.rb +1 -1
- data/spec/application_spec.rb +27 -5
- data/spec/bbb_spec.rb +23 -0
- data/spec/configuration_spec.rb +16 -0
- data/spec/examples/analog_pin_spec.rb +13 -0
- data/spec/examples/blinker_spec.rb +17 -0
- data/spec/examples/ldr_light_switch_spec.rb +38 -0
- data/spec/examples/light_switch_spec.rb +47 -0
- data/spec/examples/nunchuck_websocket_spec.rb +20 -0
- data/spec/examples/quadcopter_spec.rb +90 -0
- data/spec/examples/servo_ldr_spec.rb +95 -0
- data/spec/pins/pinnable_spec.rb +4 -2
- data/spec/spec_helper.rb +1 -0
- metadata +26 -7
- data/examples/sketches.rb +0 -86
- data/spec/examples/led_spec.rb +0 -40
data/lib/BBB.rb
CHANGED
@@ -2,12 +2,26 @@ require "json"
|
|
2
2
|
require "stringio"
|
3
3
|
|
4
4
|
require "BBB/version"
|
5
|
+
require "BBB/configuration"
|
5
6
|
|
6
|
-
require "BBB/circuit"
|
7
|
-
require "BBB/exceptions"
|
8
7
|
require "BBB/pins"
|
9
8
|
require "BBB/components"
|
9
|
+
require "BBB/attachable"
|
10
|
+
require "BBB/circuit"
|
11
|
+
require "BBB/exceptions"
|
10
12
|
require "BBB/application"
|
11
13
|
|
12
14
|
module BBB
|
15
|
+
|
16
|
+
def self.configuration
|
17
|
+
Configuration.instance
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.escape_test(&block)
|
21
|
+
old_mode = configuration.test_mode
|
22
|
+
configuration.test_mode = false
|
23
|
+
yield
|
24
|
+
configuration.test_mode = old_mode
|
25
|
+
end
|
26
|
+
|
13
27
|
end
|
data/lib/BBB/application.rb
CHANGED
@@ -1,17 +1,23 @@
|
|
1
1
|
module BBB
|
2
2
|
class Application
|
3
3
|
include Attachable
|
4
|
+
include Components
|
4
5
|
|
6
|
+
##
|
7
|
+
# Start the application by activating the components and
|
8
|
+
# load the run loop.
|
9
|
+
#
|
5
10
|
def start
|
6
|
-
activate_components
|
7
11
|
loop do
|
8
12
|
run
|
9
13
|
end
|
10
14
|
end
|
11
15
|
|
12
|
-
|
13
|
-
|
14
|
-
|
16
|
+
##
|
17
|
+
# The run funciton gets called as part of the run loop on every iteration.
|
18
|
+
# This is where you put your main application code that needs to be
|
19
|
+
# evaluaded.
|
20
|
+
#
|
15
21
|
def run
|
16
22
|
raise NotImplementedError
|
17
23
|
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module BBB
|
2
|
+
module Attachable
|
3
|
+
module ClassMethods
|
4
|
+
|
5
|
+
def class_components
|
6
|
+
@class_components ||= {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def class_component_groups
|
10
|
+
@class_component_groups ||= Hash.new { |hash, key| hash[key] = [] }
|
11
|
+
end
|
12
|
+
|
13
|
+
##
|
14
|
+
# Attach a component of a certain type to the circuit
|
15
|
+
#
|
16
|
+
# @param component [Class] The class of the object you # want to attach.
|
17
|
+
# @param opts [Hash] Hash of options that setup the component
|
18
|
+
#
|
19
|
+
# @option opts [Symbol] :pin The pin position for the component
|
20
|
+
# @option opts [Array<Symbol>] :pins The list of pin numbers used on the
|
21
|
+
# circuit.
|
22
|
+
# @options opts [Symbol] :as The name of the component
|
23
|
+
#
|
24
|
+
def attach(object, opts={})
|
25
|
+
name = opts.delete(:as)
|
26
|
+
group = opts.delete(:group)
|
27
|
+
|
28
|
+
class_components[name] = object
|
29
|
+
define_method_for_object(object, name, opts)
|
30
|
+
|
31
|
+
define_method_for_group(group)
|
32
|
+
add_to_group(name, group) if group
|
33
|
+
end
|
34
|
+
|
35
|
+
def define_method_for_object(component, name, opts)
|
36
|
+
define_method(name) do
|
37
|
+
value = components[name]
|
38
|
+
return value if value
|
39
|
+
|
40
|
+
object = self.class.class_components[name]
|
41
|
+
value = object.kind_of?(Class) ? object.new(opts) : object
|
42
|
+
components[name] = value
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def define_method_for_group(group_name)
|
47
|
+
return if group_name.nil? || respond_to?(group_name)
|
48
|
+
define_method(group_name) do
|
49
|
+
if component_groups[group_name].empty?
|
50
|
+
component_groups[group_name] = self.class.class_component_groups[group_name]
|
51
|
+
end
|
52
|
+
|
53
|
+
component_groups[group_name].map do |component_name|
|
54
|
+
self.send(component_name)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def add_to_group(component_name, group_name)
|
60
|
+
class_component_groups[group_name] << component_name
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.included(base)
|
66
|
+
base.extend(ClassMethods)
|
67
|
+
end
|
68
|
+
|
69
|
+
def components
|
70
|
+
@components ||= {}
|
71
|
+
end
|
72
|
+
|
73
|
+
def component_groups
|
74
|
+
@component_groups ||= Hash.new { |hash, key| hash[key] = [] }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/lib/BBB/circuit.rb
CHANGED
@@ -1,51 +1,4 @@
|
|
1
1
|
module BBB
|
2
|
-
module Attachable
|
3
|
-
module ClassMethods
|
4
|
-
|
5
|
-
def class_components
|
6
|
-
@class_components ||= {}
|
7
|
-
end
|
8
|
-
|
9
|
-
##
|
10
|
-
# Attach a component of a certain type to the circuit
|
11
|
-
#
|
12
|
-
# @param component [Class] The class of the object you # want to attach.
|
13
|
-
# @param opts [Hash] Hash of options that setup the component
|
14
|
-
#
|
15
|
-
# @option opts [Symbol] :pin The pin position for the component
|
16
|
-
# @option opts [Array<Symbol>] :pins The list of pin numbers used on the
|
17
|
-
# circuit.
|
18
|
-
# @options opts [Symbol] :as The name of the component
|
19
|
-
#
|
20
|
-
def attach(object, opts={})
|
21
|
-
name = opts.delete(:as)
|
22
|
-
class_components[name] = object
|
23
|
-
define_method_for_object(object, name)
|
24
|
-
end
|
25
|
-
|
26
|
-
def define_method_for_object(component, name)
|
27
|
-
define_method(name) do
|
28
|
-
value = components[name]
|
29
|
-
return value if value
|
30
|
-
|
31
|
-
object = self.class.class_components[name]
|
32
|
-
value = object.kind_of?(Class) ? object.new : object
|
33
|
-
|
34
|
-
components[name] = value
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.included(base)
|
40
|
-
base.extend(ClassMethods)
|
41
|
-
end
|
42
|
-
|
43
|
-
def components
|
44
|
-
@components ||= {}
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
2
|
##
|
50
3
|
# The idea here is to attach a piece of equipment to a circuit.
|
51
4
|
#
|
@@ -59,6 +12,13 @@ module BBB
|
|
59
12
|
# boards. For example by mapping P8_3 on BBB to P1 on an Arduino.
|
60
13
|
#
|
61
14
|
class Circuit
|
15
|
+
attr_reader :options
|
16
|
+
|
62
17
|
include Attachable
|
18
|
+
include Components
|
19
|
+
|
20
|
+
def initialize(options={})
|
21
|
+
@options = options
|
22
|
+
end
|
63
23
|
end
|
64
24
|
end
|
@@ -1,10 +1,55 @@
|
|
1
1
|
module BBB
|
2
2
|
module Components
|
3
3
|
class Button
|
4
|
+
attr_reader :status
|
5
|
+
attr_accessor :release_callbacks, :press_callbacks
|
6
|
+
|
4
7
|
include Pinnable
|
5
8
|
|
6
9
|
uses BBB::Pins::DigitalInputPin
|
7
10
|
|
11
|
+
def initialize(options={})
|
12
|
+
@status = :released
|
13
|
+
@release_callbacks = []
|
14
|
+
@press_callbacks = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def pressed?
|
18
|
+
status == :pressed
|
19
|
+
end
|
20
|
+
|
21
|
+
def released?
|
22
|
+
!pressed
|
23
|
+
end
|
24
|
+
|
25
|
+
def press!
|
26
|
+
old_state = status
|
27
|
+
@status = :pressed
|
28
|
+
on_press if old_state != status
|
29
|
+
end
|
30
|
+
|
31
|
+
def release!
|
32
|
+
old_state = status
|
33
|
+
@status = :released
|
34
|
+
on_release if old_state != status
|
35
|
+
end
|
36
|
+
|
37
|
+
def update(value=pin.high?)
|
38
|
+
value == true ? press! : release!
|
39
|
+
end
|
40
|
+
|
41
|
+
def on_release(&block)
|
42
|
+
@release_callbacks.each{ |c| c.call(status) }
|
43
|
+
end
|
44
|
+
|
45
|
+
def on_press(&block)
|
46
|
+
if block_given?
|
47
|
+
@press_callbacks << block
|
48
|
+
else
|
49
|
+
@press_callbacks.each{ |c| c.call(status) }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
8
53
|
def high?
|
9
54
|
pin.on?
|
10
55
|
end
|
@@ -14,11 +59,6 @@ module BBB
|
|
14
59
|
!high
|
15
60
|
end
|
16
61
|
alias_method :off?, :low?
|
17
|
-
|
18
|
-
def status
|
19
|
-
pin.status
|
20
|
-
end
|
21
|
-
alias_method :state, :status
|
22
62
|
end
|
23
63
|
end
|
24
64
|
end
|
data/lib/BBB/components/esc.rb
CHANGED
data/lib/BBB/components/led.rb
CHANGED
@@ -49,6 +49,25 @@ module BBB
|
|
49
49
|
pin.off?
|
50
50
|
end
|
51
51
|
|
52
|
+
|
53
|
+
##
|
54
|
+
# Returns the status of the current led
|
55
|
+
#
|
56
|
+
def status
|
57
|
+
on? ? :on : :off
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Toggle the led between on and off
|
62
|
+
#
|
63
|
+
def toggle!
|
64
|
+
if on?
|
65
|
+
off!
|
66
|
+
elsif off?
|
67
|
+
on!
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
52
71
|
end
|
53
72
|
end
|
54
73
|
end
|
@@ -130,49 +130,6 @@ module BBB
|
|
130
130
|
@axis[:y].update(bytes[1])
|
131
131
|
end
|
132
132
|
|
133
|
-
class Button
|
134
|
-
attr_reader :status
|
135
|
-
attr_accessor :release_callbacks, :press_callbacks
|
136
|
-
|
137
|
-
def initialize
|
138
|
-
@status = :released
|
139
|
-
@release_callbacks = []
|
140
|
-
@press_callbacks = []
|
141
|
-
end
|
142
|
-
|
143
|
-
def pressed?
|
144
|
-
status == :pressed
|
145
|
-
end
|
146
|
-
|
147
|
-
def press!
|
148
|
-
@status = :pressed
|
149
|
-
on_press if old_state != status
|
150
|
-
end
|
151
|
-
|
152
|
-
def release!
|
153
|
-
old_state = status
|
154
|
-
@status = :released
|
155
|
-
on_release if old_state != status
|
156
|
-
end
|
157
|
-
|
158
|
-
def released?
|
159
|
-
!pressed
|
160
|
-
end
|
161
|
-
|
162
|
-
def update(value)
|
163
|
-
value == true ? release! : press!
|
164
|
-
end
|
165
|
-
|
166
|
-
def on_release
|
167
|
-
@release_callbacks.each{ |c| c.call(status) }
|
168
|
-
end
|
169
|
-
|
170
|
-
def on_press
|
171
|
-
@press_callbacks.each{ |c| c.call(status) }
|
172
|
-
end
|
173
|
-
|
174
|
-
end
|
175
|
-
|
176
133
|
class ControlAxis
|
177
134
|
attr_accessor :value
|
178
135
|
attr_accessor :change_callbacks
|
@@ -147,7 +147,10 @@ module BBB
|
|
147
147
|
# @param options [Hash]
|
148
148
|
#
|
149
149
|
def set_options(options)
|
150
|
-
@positions = [options
|
150
|
+
@positions = [options[:pin],
|
151
|
+
options[:pins],
|
152
|
+
options[:position],
|
153
|
+
options[:path]].flatten.compact
|
151
154
|
end
|
152
155
|
end
|
153
156
|
end
|
@@ -27,11 +27,15 @@ module BBB
|
|
27
27
|
|
28
28
|
attr_reader :gyro, :positions
|
29
29
|
|
30
|
+
##
|
31
|
+
# the WMP uses I2C pins, so you can give it a name like "I2C2_SDA"
|
32
|
+
#
|
30
33
|
def initialize(options = {})
|
31
34
|
@started = false
|
32
35
|
@calibrated = false
|
33
36
|
@gyro = Gyro.new
|
34
37
|
@positions = [options.fetch(:i2c, nil)].compact
|
38
|
+
@extension = options[:extension]
|
35
39
|
end
|
36
40
|
|
37
41
|
def start
|
data/lib/BBB/pins/pinnable.rb
CHANGED
data/lib/BBB/version.rb
CHANGED
data/spec/application_spec.rb
CHANGED
@@ -6,23 +6,45 @@ describe BBB::Application do
|
|
6
6
|
lambda { BBB::Application.new }.should_not raise_exception
|
7
7
|
end
|
8
8
|
|
9
|
+
it "it responds to start" do
|
10
|
+
BBB::Application.new.respond_to?(:start).should be_true
|
11
|
+
end
|
12
|
+
|
13
|
+
it "start calls run" do
|
14
|
+
app = BBB::Application.new
|
15
|
+
app.should_receive(:run).and_raise(StopIteration)
|
16
|
+
app.start
|
17
|
+
end
|
18
|
+
|
19
|
+
it "run raises NotImplementedError" do
|
20
|
+
app = BBB::Application.new
|
21
|
+
lambda { app.run }.should raise_error(NotImplementedError)
|
22
|
+
end
|
23
|
+
|
9
24
|
class TestLedCircuit < BBB::Circuit
|
10
|
-
attach
|
25
|
+
attach Led, as: :led
|
11
26
|
end
|
12
27
|
|
13
|
-
class
|
28
|
+
class TestCircuitConnectionApp < BBB::Application
|
14
29
|
attach TestLedCircuit, as: :circuit
|
15
30
|
end
|
16
31
|
|
17
32
|
it "attaches virtual pins to board pins" do
|
18
|
-
app =
|
33
|
+
app = TestCircuitConnectionApp.new
|
19
34
|
app.circuit.respond_to?(:led).should be_true
|
20
35
|
app.circuit.led.respond_to?(:on!).should be_true
|
21
36
|
end
|
22
37
|
|
23
|
-
class
|
24
|
-
attach
|
38
|
+
class TestBasicApp < BBB::Application
|
39
|
+
attach Led, as: :led
|
40
|
+
end
|
25
41
|
|
42
|
+
it "adds helper functions to applications" do
|
43
|
+
app = TestBasicApp.new
|
44
|
+
app.respond_to?(:led).should be_true
|
45
|
+
end
|
46
|
+
|
47
|
+
class FunctionsInApp < BBB::Application
|
26
48
|
def run
|
27
49
|
raise StopIteration
|
28
50
|
end
|