birdbrain 0.2.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 +7 -0
- data/.gitignore +57 -0
- data/.rubocop.yml +135 -0
- data/CHANGELOG.md +0 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +48 -0
- data/LICENSE.txt +21 -0
- data/README.md +45 -0
- data/Rakefile +14 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/birdbrain.gemspec +37 -0
- data/lib/birdbrain/birdbrain_device.rb +60 -0
- data/lib/birdbrain/birdbrain_exception.rb +14 -0
- data/lib/birdbrain/birdbrain_finch.rb +168 -0
- data/lib/birdbrain/birdbrain_finch_input.rb +115 -0
- data/lib/birdbrain/birdbrain_finch_output.rb +36 -0
- data/lib/birdbrain/birdbrain_hummingbird.rb +75 -0
- data/lib/birdbrain/birdbrain_hummingbird_input.rb +34 -0
- data/lib/birdbrain/birdbrain_hummingbird_output.rb +33 -0
- data/lib/birdbrain/birdbrain_microbit.rb +46 -0
- data/lib/birdbrain/birdbrain_microbit_input.rb +70 -0
- data/lib/birdbrain/birdbrain_microbit_output.rb +28 -0
- data/lib/birdbrain/birdbrain_request.rb +123 -0
- data/lib/birdbrain/birdbrain_state.rb +22 -0
- data/lib/birdbrain/version.rb +8 -0
- data/lib/birdbrain.rb +21 -0
- metadata +76 -0
@@ -0,0 +1,115 @@
|
|
1
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2021 Base2 Incorporated--All Rights Reserved.
|
3
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
4
|
+
class BirdbrainFinchInput < BirdbrainRequest
|
5
|
+
DEFAULT_FACTOR = 1.0
|
6
|
+
DEFAULT_MIN_RESPONSE = 0
|
7
|
+
DEFAULT_MAX_RESPONSE = 100
|
8
|
+
DEFAULT_TYPE_METHOD = 'to_i'
|
9
|
+
DEFAULT_UNLIMITED_MIN_RESPONSE = -1000000
|
10
|
+
DEFAULT_UNLIMITED_MAX_RESPONSE = 1000000
|
11
|
+
ORIENTATIONS = ['Beak%20Up', 'Beak%20Down', 'Tilt%20Left', 'Tilt%20Right', 'Level', 'Upside%20Down']
|
12
|
+
ORIENTATION_RESULTS = ['Beak up', 'Beak down', 'Tilt left', 'Tilt right', 'Level', 'Upside down']
|
13
|
+
ORIENTATION_IN_BETWEEN = 'In between'
|
14
|
+
|
15
|
+
def self.finch?(device)
|
16
|
+
request_status(response_body('hummingbird', 'in', 'isHummingbird', 'static', device))
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.moving?(device)
|
20
|
+
request_status(response_body('hummingbird', 'in', 'finchIsMoving', 'static', device))
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.light(device, direction)
|
24
|
+
sensor(device, 'Light', calculate_left_or_right(direction))
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.distance(device)
|
28
|
+
distance_options = {}
|
29
|
+
distance_options[:factor] = 0.0919
|
30
|
+
distance_options[:min_response] = DEFAULT_UNLIMITED_MIN_RESPONSE
|
31
|
+
distance_options[:max_response] = DEFAULT_UNLIMITED_MAX_RESPONSE
|
32
|
+
|
33
|
+
sensor(device, 'Distance', 'static', distance_options)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.line(device, direction)
|
37
|
+
sensor(device, 'Line', calculate_left_or_right(direction))
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.encoder(device, direction)
|
41
|
+
encoder_options = {}
|
42
|
+
encoder_options[:min_response] = DEFAULT_UNLIMITED_MIN_RESPONSE
|
43
|
+
encoder_options[:max_response] = DEFAULT_UNLIMITED_MAX_RESPONSE
|
44
|
+
encoder_options[:type_method] = 'to_f'
|
45
|
+
|
46
|
+
sensor(device, 'Encoder', calculate_left_or_right(direction), encoder_options)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.accelerometer(device)
|
50
|
+
xyz_response(device, 'finchAccel')
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.compass(device)
|
54
|
+
(response = response_body('hummingbird', 'in', 'finchCompass', 'static', device)).nil? ? response : response.to_i
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.magnetometer(device)
|
58
|
+
xyz_response(device, 'finchMag')
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.orientation(device)
|
62
|
+
ORIENTATIONS.each_with_index do |orientation, index|
|
63
|
+
return nil if (response = response_body('hummingbird', 'in', 'finchOrientation', orientation, device)).nil?
|
64
|
+
|
65
|
+
return ORIENTATION_RESULTS[index] if request_status(response)
|
66
|
+
end
|
67
|
+
|
68
|
+
ORIENTATION_IN_BETWEEN
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.orientation_beak_up?(device)
|
72
|
+
orientation_check(device, 0)
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.orientation_beak_down?(device)
|
76
|
+
orientation_check(device, 1)
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.orientation_tilt_left?(device)
|
80
|
+
orientation_check(device, 2)
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.orientation_tilt_right?(device)
|
84
|
+
orientation_check(device, 3)
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.orientation_level?(device)
|
88
|
+
orientation_check(device, 4)
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.orientation_upside_down?(device)
|
92
|
+
orientation_check(device, 5)
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.orientation_check(device, index)
|
96
|
+
request_status(response_body('hummingbird', 'in', 'finchOrientation', ORIENTATIONS[index], device))
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.sensor(device, sensor, other = nil, options = {})
|
100
|
+
return false if other == false # for invalid directions
|
101
|
+
|
102
|
+
factor = options.key?(:factor) ? options[:factor] : DEFAULT_FACTOR
|
103
|
+
min_response = options.key?(:min_response) ? options[:min_response] : DEFAULT_MIN_RESPONSE
|
104
|
+
max_response = options.key?(:max_response) ? options[:max_response] : DEFAULT_MAX_RESPONSE
|
105
|
+
type_method = options.key?(:type_method) ? options[:type_method] : DEFAULT_TYPE_METHOD
|
106
|
+
|
107
|
+
request = ['hummingbird', 'in', sensor]
|
108
|
+
request << other unless other.nil?
|
109
|
+
request << device
|
110
|
+
|
111
|
+
response = response_body(request)
|
112
|
+
|
113
|
+
(response.nil? ? nil : bounds((response.to_f * factor).send(type_method), min_response, max_response))
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2021 Base2 Incorporated--All Rights Reserved.
|
3
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
4
|
+
class BirdbrainFinchOutput < BirdbrainRequest
|
5
|
+
def self.move(device, direction, distance, speed)
|
6
|
+
calc_direction = 'Forward' if direction == BirdbrainFinch::FORWARD
|
7
|
+
calc_direction = 'Backward' if direction == BirdbrainFinch::BACKWARD
|
8
|
+
calc_distance = bounds(distance, -10000, 10000)
|
9
|
+
calc_speed = bounds(speed, 0, 100)
|
10
|
+
|
11
|
+
request_status(response_body('hummingbird', 'out', 'move', device, calc_direction, calc_distance, calc_speed))
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.turn(device, direction, angle, speed)
|
15
|
+
calc_direction = calculate_left_or_right(direction)
|
16
|
+
calc_angle = bounds(angle, 0, 360)
|
17
|
+
calc_speed = bounds(speed, 0, 100)
|
18
|
+
|
19
|
+
request_status(response_body('hummingbird', 'out', 'turn', device, calc_direction, calc_angle, calc_speed))
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.motors(device, left_speed, right_speed)
|
23
|
+
calc_left_speed = bounds(left_speed, -100, 100)
|
24
|
+
calc_right_speed = bounds(right_speed, -100, 100)
|
25
|
+
|
26
|
+
request_status(response_body('hummingbird', 'out', 'wheels', device, calc_left_speed, calc_right_speed))
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.stop(device)
|
30
|
+
request_status(response_body('hummingbird', 'out', 'stopFinch', device))
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.reset_encoders(device)
|
34
|
+
request_status(response_body('hummingbird', 'out', 'resetEncoders', device))
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2021 Base2 Incorporated--All Rights Reserved.
|
3
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
4
|
+
class BirdbrainHummingbird < BirdbrainMicrobit
|
5
|
+
LEFT = BirdbrainDevice::LEFT
|
6
|
+
RIGHT = BirdbrainDevice::RIGHT
|
7
|
+
VALID_LED_PORTS = '123'
|
8
|
+
VALID_TRILED_PORTS = '12'
|
9
|
+
VALID_SENSOR_PORTS = '123'
|
10
|
+
VALID_SERVO_PORTS = '1234'
|
11
|
+
|
12
|
+
def light(port)
|
13
|
+
BirdbrainHummingbirdInput.light(device, port) if connected_and_valid?(port, VALID_SENSOR_PORTS)
|
14
|
+
end
|
15
|
+
|
16
|
+
def sound(port)
|
17
|
+
BirdbrainHummingbirdInput.sound(device, port) if connected_and_valid?(port, VALID_SENSOR_PORTS)
|
18
|
+
end
|
19
|
+
|
20
|
+
def distance(port)
|
21
|
+
BirdbrainHummingbirdInput.distance(device, port) if connected_and_valid?(port, VALID_SENSOR_PORTS)
|
22
|
+
end
|
23
|
+
|
24
|
+
def dial(port)
|
25
|
+
BirdbrainHummingbirdInput.dial(device, port) if connected_and_valid?(port, VALID_SENSOR_PORTS)
|
26
|
+
end
|
27
|
+
|
28
|
+
def voltage(port)
|
29
|
+
BirdbrainHummingbirdInput.voltage(device, port) if connected_and_valid?(port, VALID_SENSOR_PORTS)
|
30
|
+
end
|
31
|
+
|
32
|
+
def position_servo(port, angle)
|
33
|
+
BirdbrainHummingbirdOutput.position_servo(device, port, angle) if connected_and_valid?(port, VALID_SERVO_PORTS)
|
34
|
+
end
|
35
|
+
|
36
|
+
def rotation_servo(port, speed)
|
37
|
+
BirdbrainHummingbirdOutput.rotation_servo(device, port, speed) if connected_and_valid?(port, VALID_SERVO_PORTS)
|
38
|
+
end
|
39
|
+
|
40
|
+
def led(port, intensity)
|
41
|
+
BirdbrainHummingbirdOutput.led(device, port, intensity) if connected_and_valid?(port, VALID_LED_PORTS)
|
42
|
+
end
|
43
|
+
|
44
|
+
def tri_led(port, r_intensity, g_intensity, b_intensity)
|
45
|
+
BirdbrainHummingbirdOutput.tri_led(device, port, r_intensity, g_intensity, b_intensity) if connected_and_valid?(port, VALID_TRILED_PORTS)
|
46
|
+
end
|
47
|
+
|
48
|
+
def play_note(note, beats)
|
49
|
+
BirdbrainHummingbirdOutput.play_note(device, note, beats) if connected?
|
50
|
+
end
|
51
|
+
|
52
|
+
def orientation_screen_up?
|
53
|
+
BirdbrainMicrobitInput.orientation_screen_up?(device) if connected?
|
54
|
+
end
|
55
|
+
|
56
|
+
def orientation_screen_down?
|
57
|
+
BirdbrainMicrobitInput.orientation_screen_down?(device) if connected?
|
58
|
+
end
|
59
|
+
|
60
|
+
def orientation_tilt_left?
|
61
|
+
BirdbrainMicrobitInput.orientation_tilt_left?(device) if connected?
|
62
|
+
end
|
63
|
+
|
64
|
+
def orientation_tilt_right?
|
65
|
+
BirdbrainMicrobitInput.orientation_tilt_right?(device) if connected?
|
66
|
+
end
|
67
|
+
|
68
|
+
def orientation_logo_up?
|
69
|
+
BirdbrainMicrobitInput.orientation_logo_up?(device) if connected?
|
70
|
+
end
|
71
|
+
|
72
|
+
def orientation_logo_down?
|
73
|
+
BirdbrainMicrobitInput.orientation_logo_down?(device) if connected?
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2021 Base2 Incorporated--All Rights Reserved.
|
3
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
4
|
+
class BirdbrainHummingbirdInput < BirdbrainRequest
|
5
|
+
def self.hummingbird?(device)
|
6
|
+
request_status(response_body('hummingbird', 'in', 'isHummingbird', 'static', device))
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.light(device, port)
|
10
|
+
sensor(device, port, 0.39215686274509803) # factor=100/255
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.sound(device, port)
|
14
|
+
sensor(device, port, 0.7843137254901961) # factor=200/255
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.distance(device, port)
|
18
|
+
sensor(device, port, 1.17) # factor=117/100
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.dial(device, port)
|
22
|
+
sensor(device, port, 0.43478260869565216) # factor=100/230
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.voltage(device, port)
|
26
|
+
sensor(device, port, 0.012941176470588235) # factor=3.3/255
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.sensor(device, port, factor)
|
30
|
+
response = response_body('hummingbird', 'in', 'sensor', port, device)
|
31
|
+
|
32
|
+
(response.nil? ? nil : bounds((response.to_f * factor).to_i, 0, 100))
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2021 Base2 Incorporated--All Rights Reserved.
|
3
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
4
|
+
class BirdbrainHummingbirdOutput < BirdbrainRequest
|
5
|
+
def self.led(device, port, intensity)
|
6
|
+
request_status(response_body('hummingbird', 'out', 'led', port.to_s, bounds(calculate_intensity(intensity), 0, 255), device))
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.tri_led(device, port, r_intensity, g_intensity, b_intensity)
|
10
|
+
calc_r = bounds(calculate_intensity(r_intensity), 0, 255)
|
11
|
+
calc_g = bounds(calculate_intensity(g_intensity), 0, 255)
|
12
|
+
calc_b = bounds(calculate_intensity(b_intensity), 0, 255)
|
13
|
+
|
14
|
+
request_status(response_body('hummingbird', 'out', 'triled', port.to_s, calc_r, calc_g, calc_b, device))
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.position_servo(device, port, angle)
|
18
|
+
# QUESTION: 254 max (255 is ignored)
|
19
|
+
request_status(response_body('hummingbird', 'out', 'servo', port.to_s, bounds(calculate_angle(angle), 0, 254), device))
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.rotation_servo(device, port, speed)
|
23
|
+
# QUESTION: why this range...255 means stop
|
24
|
+
request_status(response_body('hummingbird', 'out', 'rotation', port.to_s, bounds(calculate_speed(speed), 99, 145, 255), device))
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.play_note(device, note, beats)
|
28
|
+
calc_note = bounds(note, 32, 135)
|
29
|
+
calc_beats = bounds(beats, 0, 16) * 1000 # 100=(60000 / TEMPO) where TEMPO=60
|
30
|
+
|
31
|
+
request_status(response_body('hummingbird', 'out', 'playnote', calc_note, calc_beats, device))
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2021 Base2 Incorporated--All Rights Reserved.
|
3
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
4
|
+
class BirdbrainMicrobit < BirdbrainDevice
|
5
|
+
VALID_BUTTONS = 'AB'
|
6
|
+
|
7
|
+
def microbit_accelerometer
|
8
|
+
BirdbrainMicrobitInput.microbit_accelerometer(device) if connected?
|
9
|
+
end
|
10
|
+
|
11
|
+
def microbit_compass
|
12
|
+
BirdbrainMicrobitInput.microbit_compass(device) if connected?
|
13
|
+
end
|
14
|
+
|
15
|
+
def microbit_magnetometer
|
16
|
+
BirdbrainMicrobitInput.microbit_magnetometer(device) if connected?
|
17
|
+
end
|
18
|
+
|
19
|
+
def microbit_button?(button)
|
20
|
+
BirdbrainMicrobitInput.microbit_button?(device, button) if connected_and_valid?(button, VALID_BUTTONS)
|
21
|
+
end
|
22
|
+
|
23
|
+
def microbit_shaking?
|
24
|
+
BirdbrainMicrobitInput.microbit_shaking?(device) if connected?
|
25
|
+
end
|
26
|
+
|
27
|
+
def microbit_orientation
|
28
|
+
BirdbrainMicrobitInput.microbit_orientation(device) if connected?
|
29
|
+
end
|
30
|
+
|
31
|
+
def microbit_display(led_list)
|
32
|
+
BirdbrainMicrobitOutput.microbit_display(state, device, led_list) if connected?
|
33
|
+
end
|
34
|
+
|
35
|
+
def microbit_clear_display
|
36
|
+
BirdbrainMicrobitOutput.microbit_clear_display(state, device) if connected?
|
37
|
+
end
|
38
|
+
|
39
|
+
def microbit_point(x, y, value)
|
40
|
+
BirdbrainMicrobitOutput.microbit_point(state, device, x, y, value) if connected?
|
41
|
+
end
|
42
|
+
|
43
|
+
def microbit_print(message)
|
44
|
+
BirdbrainMicrobitOutput.microbit_print(device, message) if connected?
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2021 Base2 Incorporated--All Rights Reserved.
|
3
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
4
|
+
class BirdbrainMicrobitInput < BirdbrainRequest
|
5
|
+
ORIENTATIONS = ['Screen%20Up', 'Screen%20Down', 'Tilt%20Left', 'Tilt%20Right', 'Logo%20Up', 'Logo%20Down']
|
6
|
+
ORIENTATION_RESULTS = ['Screen up', 'Screen down', 'Tilt left', 'Tilt right', 'Logo up', 'Logo down']
|
7
|
+
ORIENTATION_IN_BETWEEN = 'In between'
|
8
|
+
|
9
|
+
def self.microbit?(device)
|
10
|
+
request_status(response_body('hummingbird', 'in', 'isHummingbird', 'static', device))
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.microbit_accelerometer(device)
|
14
|
+
xyz_response(device, 'Accelerometer')
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.microbit_compass(device)
|
18
|
+
(response = response_body('hummingbird', 'in', 'Compass', device)).nil? ? response : response.to_i
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.microbit_magnetometer(device)
|
22
|
+
xyz_response(device, 'Magnetometer')
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.microbit_button?(device, button)
|
26
|
+
request_status(response_body('hummingbird', 'in', 'button', button, device))
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.microbit_shaking?(device)
|
30
|
+
request_status(response_body('hummingbird', 'in', 'orientation', 'Shake', device))
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.microbit_orientation(device)
|
34
|
+
ORIENTATIONS.each_with_index do |orientation, index|
|
35
|
+
return nil if (response = response_body('hummingbird', 'in', 'orientation', orientation, device)).nil?
|
36
|
+
|
37
|
+
return ORIENTATION_RESULTS[index] if request_status(response)
|
38
|
+
end
|
39
|
+
|
40
|
+
ORIENTATION_IN_BETWEEN
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.orientation_screen_up?(device)
|
44
|
+
orientation_check(device, 0)
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.orientation_screen_down?(device)
|
48
|
+
orientation_check(device, 1)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.orientation_tilt_left?(device)
|
52
|
+
orientation_check(device, 2)
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.orientation_tilt_right?(device)
|
56
|
+
orientation_check(device, 3)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.orientation_logo_up?(device)
|
60
|
+
orientation_check(device, 4)
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.orientation_logo_down?(device)
|
64
|
+
orientation_check(device, 5)
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.orientation_check(device, index)
|
68
|
+
request_status(response_body('hummingbird', 'in', 'orientation', ORIENTATIONS[index], device))
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2021 Base2 Incorporated--All Rights Reserved.
|
3
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
4
|
+
class BirdbrainMicrobitOutput < BirdbrainRequest
|
5
|
+
def self.microbit_display(state, device, led_list)
|
6
|
+
state.microbit_display_map = led_list.collect { |pixel| (((pixel == 1) || pixel.is_a?(TrueClass)) ? 1 : 0) }
|
7
|
+
|
8
|
+
request_status(response_body('hummingbird', 'out', 'symbol', device, state.microbit_display_map_as_strings))
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.microbit_clear_display(state, device)
|
12
|
+
microbit_display(state, device, BirdbrainState.microbit_empty_display_map)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.microbit_point(state, device, x, y, value)
|
16
|
+
index = ((x * 5) + y - 6)
|
17
|
+
|
18
|
+
state.microbit_display_map[index] = value
|
19
|
+
|
20
|
+
microbit_display(state, device, state.microbit_display_map)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.microbit_print(device, message)
|
24
|
+
calc_message = message.gsub(' ', '%20')
|
25
|
+
|
26
|
+
request_status(response_body('hummingbird', 'out', 'print', calc_message, device))
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2021 Base2 Incorporated--All Rights Reserved.
|
3
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
4
|
+
require 'net/http'
|
5
|
+
|
6
|
+
class BirdbrainRequest
|
7
|
+
BIRDBRAIN_TEST = false
|
8
|
+
|
9
|
+
def self.uri(*args)
|
10
|
+
uri = 'http://127.0.0.1:30061'
|
11
|
+
args.flatten.each { |s| uri += "/#{s}" }
|
12
|
+
|
13
|
+
puts "Test: uri is #{uri}" if BIRDBRAIN_TEST
|
14
|
+
|
15
|
+
uri
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.response(*args)
|
19
|
+
return false if (valid_args = args.flatten).include?(false)
|
20
|
+
|
21
|
+
response = Net::HTTP.get_response(URI.parse(uri(valid_args)))
|
22
|
+
|
23
|
+
sleep(0.01) # HACK: prevent http requests from overloading the bluebird connector
|
24
|
+
|
25
|
+
response
|
26
|
+
rescue Errno::ECONNREFUSED
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.response_body(*args)
|
31
|
+
response = response(args)
|
32
|
+
|
33
|
+
return false if response == false
|
34
|
+
|
35
|
+
return nil if response.nil?
|
36
|
+
return nil if response.body.downcase == 'not connected'
|
37
|
+
|
38
|
+
puts "Test: response: #{response.body.inspect}" if BIRDBRAIN_TEST
|
39
|
+
|
40
|
+
response.body
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.connected?(device)
|
44
|
+
response = response_body('hummingbird', 'in', 'orientation', 'Shake', device)
|
45
|
+
|
46
|
+
!response.nil?
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.not_connected?(device)
|
50
|
+
!connected?(device)
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.disconnect(device)
|
54
|
+
request_status(response_body('hummingbird', 'out', 'stopall', device))
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.request_status(status)
|
58
|
+
puts "Test: request status is #{status.inspect}" if BIRDBRAIN_TEST
|
59
|
+
|
60
|
+
return nil if status.nil?
|
61
|
+
|
62
|
+
return true if status == 'true'
|
63
|
+
return true if status == 'led set'
|
64
|
+
return true if status == 'triled set'
|
65
|
+
return true if status == 'servo set'
|
66
|
+
return true if status == 'buzzer set'
|
67
|
+
return true if status == 'symbol set'
|
68
|
+
return true if status == 'print set'
|
69
|
+
return true if status == 'all stopped'
|
70
|
+
|
71
|
+
return true if status == 'finch moved'
|
72
|
+
return true if status == 'finch turned'
|
73
|
+
return true if status == 'finch wheels started'
|
74
|
+
return true if status == 'finch wheels stopped'
|
75
|
+
return true if status == 'finch encoders reset'
|
76
|
+
|
77
|
+
return false if status == 'false'
|
78
|
+
return false if status == 'Not Connected'
|
79
|
+
return false if status == 'Invalid orientation'
|
80
|
+
|
81
|
+
nil
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.xyz_response(device, sensor, type_method = 'to_f')
|
85
|
+
return nil if (x = response_body('hummingbird', 'in', sensor, 'X', device)).nil?
|
86
|
+
|
87
|
+
y = response_body('hummingbird', 'in', sensor, 'Y', device)
|
88
|
+
z = response_body('hummingbird', 'in', sensor, 'Z', device)
|
89
|
+
|
90
|
+
[x.send(type_method), y.send(type_method), z.send(type_method)]
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.calculate_angle(intensity)
|
94
|
+
intensity * 255 / 180
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.calculate_intensity(intensity)
|
98
|
+
intensity * 255 / 100
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.calculate_speed(speed)
|
102
|
+
return 255 if speed.between?(-10, 10)
|
103
|
+
|
104
|
+
# QUESTION: why this calculation instead of normal mapping to 0..255 (and 255 means stop)
|
105
|
+
((speed * 23 / 100) + 122)
|
106
|
+
end
|
107
|
+
|
108
|
+
def self.calculate_left_or_right(direction)
|
109
|
+
return 'Left' if direction == BirdbrainDevice::LEFT
|
110
|
+
return 'Right' if direction == BirdbrainDevice::RIGHT
|
111
|
+
|
112
|
+
false
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.bounds(input, input_min, input_max, pass_through_input = nil)
|
116
|
+
return input if !pass_through_input.nil? && (input == pass_through_input)
|
117
|
+
|
118
|
+
return input_min if input < input_min
|
119
|
+
return input_max if input > input_max
|
120
|
+
|
121
|
+
input
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2021 Base2 Incorporated--All Rights Reserved.
|
3
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
4
|
+
class BirdbrainState
|
5
|
+
attr_accessor :microbit_display_map
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
microbit_display_map_clear
|
9
|
+
end
|
10
|
+
|
11
|
+
def microbit_display_map_clear
|
12
|
+
self.microbit_display_map = BirdbrainState.microbit_empty_display_map
|
13
|
+
end
|
14
|
+
|
15
|
+
def microbit_display_map_as_strings
|
16
|
+
microbit_display_map.collect { |pixel| ((pixel == 1) ? 'true' : 'false') }
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.microbit_empty_display_map
|
20
|
+
[0] * 25
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2021 Base2 Incorporated--All Rights Reserved.
|
3
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
4
|
+
# frozen_string_literal: true
|
5
|
+
|
6
|
+
module Birdbrain
|
7
|
+
VERSION = '0.2.1'
|
8
|
+
end
|
data/lib/birdbrain.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
2
|
+
# Copyright (c) 2021 Base2 Incorporated--All Rights Reserved.
|
3
|
+
#-----------------------------------------------------------------------------------------------------------------------------------
|
4
|
+
module Birdbrain
|
5
|
+
class Error < StandardError; end
|
6
|
+
|
7
|
+
require_relative 'birdbrain/version'
|
8
|
+
require_relative 'birdbrain/birdbrain_device'
|
9
|
+
require_relative 'birdbrain/birdbrain_exception'
|
10
|
+
require_relative 'birdbrain/birdbrain_state'
|
11
|
+
require_relative 'birdbrain/birdbrain_request'
|
12
|
+
require_relative 'birdbrain/birdbrain_microbit_input'
|
13
|
+
require_relative 'birdbrain/birdbrain_microbit_output'
|
14
|
+
require_relative 'birdbrain/birdbrain_microbit'
|
15
|
+
require_relative 'birdbrain/birdbrain_hummingbird_input'
|
16
|
+
require_relative 'birdbrain/birdbrain_hummingbird_output'
|
17
|
+
require_relative 'birdbrain/birdbrain_hummingbird'
|
18
|
+
require_relative 'birdbrain/birdbrain_finch'
|
19
|
+
require_relative 'birdbrain/birdbrain_finch_input'
|
20
|
+
require_relative 'birdbrain/birdbrain_finch_output'
|
21
|
+
end
|