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.
@@ -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