hybridgroup-firmata 0.2.0

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.
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .rvmrc
19
+ harness.rb
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in firmata.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 'Mike Breen'
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # Firmata
2
+
3
+ A Ruby implementation of the [Firmata protocol](http://firmata.org/wiki/V2.2ProtocolDetails).
4
+
5
+ This library is inspired by the awesome [firmata](http://jgautier.github.com/firmata/) by [jgautier](https://github.com/jgautier).
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'firmata'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install firmata
20
+
21
+ ## Prerequisites
22
+
23
+ 1. Download the [Arduio IDE](http://www.arduino.cc/en/Main/Software) for your OS
24
+ 2. Plug in your Arduino via USB
25
+ 3. Open the Arduino IDE, select: File > Examples > Firmata > StandardFirmata
26
+ 4. Click the Upload button
27
+ 5. Make note of the serial port: Tools > Serial Port
28
+
29
+ There have been reports of [issues](https://github.com/jgautier/firmata/issues/8) with Firmata 2.3.
30
+ Try downgrading to [Firmata 2.2](http://at.or.at/hans/pd/Firmata-2.2.zip) if you're having a problem.
31
+
32
+ ## Usage
33
+
34
+ Here is a simple example using IRB that will turn pin 13 on and off.
35
+ (Replace xxxxx with the USB port from step 5 in Prerequisites)
36
+
37
+ 1.9.3p194 :001 > require 'firmata'
38
+ 1.9.3p194 :002 > board = Firmata::Board.new('/dev/tty.usbmodemxxxxx')
39
+ 1.9.3p194 :003 > board.connect
40
+ 1.9.3p194 :004 > board.connected?
41
+ => true
42
+ 1.9.3p194 :005 > board.version
43
+ => "2.3"
44
+ 1.9.3p194 :006 > board.firmware_name
45
+ => "StandardFirmata"
46
+ 1.9.3p194 :007 > board.digital_write(13, Firmata::Board::HIGH)
47
+ 1.9.3p194 :008 > board.digital_write(13, Firmata::Board::LOW)
48
+
49
+ ## Contributing
50
+
51
+ 1. Fork it
52
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
53
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
54
+ 4. Push to the branch (`git push origin my-new-feature`)
55
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs.push "lib"
7
+ t.test_files = FileList['test/*_test.rb']
8
+ t.verbose = true
9
+ end
10
+
11
+ task :default => [:test]
@@ -0,0 +1,22 @@
1
+ require 'bundler/setup'
2
+ require 'firmata'
3
+ require 'socket'
4
+
5
+ sp = TCPSocket.open 'localhost', 4567
6
+ #sp = '/dev/tty.usbserial-A700636n'
7
+ board = Firmata::Board.new(sp)
8
+
9
+ board.connect
10
+
11
+ pin_number = 3
12
+ rate = 0.5
13
+
14
+ 10.times do
15
+ board.digital_write pin_number, Firmata::Board::HIGH
16
+ puts '+'
17
+ board.delay rate
18
+
19
+ board.digital_write pin_number, Firmata::Board::LOW
20
+ puts '-'
21
+ board.delay rate
22
+ end
data/firmata.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/firmata/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["'Mike Breen', 'Adrian Zankich'"]
6
+ gem.email = ["info@hybridgroup.com"]
7
+ gem.description = %q{A lib for working with the Firmata protocol in Ruby.}
8
+ gem.summary = %q{}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "hybridgroup-firmata"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Firmata::VERSION
17
+
18
+ gem.add_development_dependency("pry")
19
+
20
+ gem.add_runtime_dependency("event_spitter")
21
+ end
data/lib/firmata.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'firmata/version'
2
+ require 'firmata/board'
@@ -0,0 +1,403 @@
1
+ require 'stringio'
2
+ require 'event_spitter'
3
+
4
+ module Firmata
5
+ class Board
6
+ include EventSpitter
7
+
8
+ # Internal: Data structure representing a pin on Arduino.
9
+ Pin = Struct.new(:supported_modes, :mode, :value, :analog_channel)
10
+
11
+ # Public: Fixnum byte for pin mode input.
12
+ INPUT = 0x00
13
+ # Public: Fixnum byte for pin mode output.
14
+ OUTPUT = 0x01
15
+ # Public: Fixnum byte for pin mode analog.
16
+ ANALOG = 0x02
17
+ # Public: Fixnum byte for pin mode pulse width modulation.
18
+ PWM = 0x03
19
+ # Public: Fixnum byte for pin mode servo.
20
+ SERVO = 0x04
21
+
22
+ LOW = 0
23
+ HIGH = 1
24
+
25
+ # Internal: Fixnum byte command for protocol version
26
+ REPORT_VERSION = 0xF9
27
+ # Internal: Fixnum byte command for system reset
28
+ SYSTEM_RESET = 0xFF
29
+ # Internal: Fixnum byte command for digital I/O message
30
+ DIGITAL_MESSAGE = 0x90
31
+ # Pubilc: Fixnum byte for range for digital pins for digital 2 byte data format
32
+ DIGITAL_MESSAGE_RANGE = 0x90..0x9F
33
+ # Internal: Fixnum byte command for an analog I/O message
34
+ ANALOG_MESSAGE = 0xE0
35
+ # Internal: Fixnum byte range for analog pins for analog 14-bit data format
36
+ ANALOG_MESSAGE_RANGE = 0xE0..0xEF
37
+ # Internal: Fixnum byte command to report analog pin
38
+ REPORT_ANALOG = 0xC0
39
+ # Internal: Fixnum byte command to report digital port
40
+ REPORT_DIGITAL = 0xD0
41
+ # Internal: Fixnum byte command to set pin mode (I/O)
42
+ PIN_MODE = 0xF4
43
+
44
+ # Internal: Fixnum byte command for start of Sysex message
45
+ START_SYSEX = 0xF0
46
+ # Internal: Fixnum byte command for end of Sysex message
47
+ END_SYSEX = 0xF7
48
+ # Internal: Fixnum byte sysex command for capabilities query
49
+ CAPABILITY_QUERY = 0x6B
50
+ # Internal: Fixnum byte sysex command for capabilities response
51
+ CAPABILITY_RESPONSE = 0x6C
52
+ # Internal: Fixnum byte sysex command for pin state query
53
+ PIN_STATE_QUERY = 0x6D
54
+ # Internal: Fixnum byte sysex command for pin state response
55
+ PIN_STATE_RESPONSE = 0x6E
56
+ # Internal: Fixnum byte sysex command for analog mapping query
57
+ ANALOG_MAPPING_QUERY = 0x69
58
+ # Internal: Fixnum byte sysex command for analog mapping response
59
+ ANALOG_MAPPING_RESPONSE = 0x6A
60
+ # Internal: Fixnum byte sysex command for firmware query and response
61
+ FIRMWARE_QUERY = 0x79
62
+
63
+ # Public: Returns the SerialPort port the Arduino is attached to.
64
+ attr_reader :serial_port
65
+ # Public: Returns the Array of pins on Arduino.
66
+ attr_reader :pins
67
+ # Public: Returns the Array of analog pins on Arduino.
68
+ attr_reader :analog_pins
69
+ # Public: Returns the String firmware name of Arduion.
70
+ attr_reader :firmware_name
71
+
72
+ # Public: Initialize a Board
73
+ #
74
+ # port - a String port or an Object that responds to read and write.
75
+ def initialize(port)
76
+ if port.is_a?(String)
77
+ require 'serialport'
78
+ @serial_port = SerialPort.new(port, 57600, 8, 1, SerialPort::NONE)
79
+ @serial_port.read_timeout = 2
80
+ else
81
+ @serial_port = port
82
+ end
83
+
84
+ @major_version = 0
85
+ @minor_version = 0
86
+ @pins = []
87
+ @analog_pins = []
88
+ @connected = false
89
+ rescue LoadError
90
+ puts "Please 'gem install hybridgroup-serialport' for serial port support."
91
+ end
92
+
93
+ # Pubilc: Check if a connection to Arduino has been made.
94
+ #
95
+ # Returns Boolean connected state.
96
+ def connected?
97
+ @connected
98
+ end
99
+
100
+ # Public: Make connection to Arduino.
101
+ #
102
+ # Returns Firmata::Board board.
103
+ def connect
104
+ unless @connected
105
+ once('report_version', ->() do
106
+ once('firmware_query', ->() do
107
+ once('capability_query', ->() do
108
+ once('analog_mapping_query', ->() do
109
+
110
+ 2.times { |i| toggle_pin_reporting(i) }
111
+
112
+ @connected = true
113
+ emit('ready')
114
+ end)
115
+ query_analog_mapping
116
+ end)
117
+ query_capabilities
118
+ end)
119
+ end)
120
+
121
+ until connected?
122
+ read_and_process
123
+ delay(0.5)
124
+ end
125
+ end
126
+
127
+ self
128
+ end
129
+
130
+ # Internal: Write data to the underlying serial port.
131
+ #
132
+ # commands - Zero or more byte commands to be written.
133
+ #
134
+ # Examples
135
+ #
136
+ # write(START_SYSEX, CAPABILITY_QUERY, END_SYSEX)
137
+ #
138
+ # Returns nothing.
139
+ def write(*commands)
140
+ serial_port.write_nonblock(commands.map(&:chr).join)
141
+ end
142
+
143
+ # Internal: Read data from the underlying serial port.
144
+ #
145
+ # Returns String data read for serial port.
146
+ def read
147
+ serial_port.read_nonblock(4096)
148
+ rescue EOFError
149
+ rescue Errno::EAGAIN
150
+ end
151
+
152
+ # Internal: Process a series of bytes.
153
+ #
154
+ # data: The String data to process.
155
+ #
156
+ # Returns nothing.
157
+ def process(data)
158
+ bytes = StringIO.new(String(data)).bytes
159
+ bytes.each do |byte|
160
+ case byte
161
+ when REPORT_VERSION
162
+ @major_version = bytes.next
163
+ @minor_version = bytes.next
164
+
165
+ emit('report_version')
166
+
167
+ when ANALOG_MESSAGE_RANGE
168
+ least_significant_byte = bytes.next
169
+ most_significant_byte = bytes.next
170
+
171
+ value = least_significant_byte | (most_significant_byte << 7)
172
+ pin = byte & 0x0F
173
+
174
+ if analog_pin = analog_pins[pin]
175
+ pins[analog_pin].value = value
176
+
177
+ emit('analog-read', pin, value)
178
+ emit("analog-read-#{pin}", value)
179
+ end
180
+
181
+ when DIGITAL_MESSAGE_RANGE
182
+ port = byte & 0x0F
183
+ first_bitmask = bytes.next
184
+ second_bitmask = bytes.next
185
+ port_value = first_bitmask | (second_bitmask << 7)
186
+
187
+ 8.times do |i|
188
+ pin_number = 8 * port + i
189
+ if pin = pins[pin_number] and pin.mode == INPUT
190
+ value = (port_value >> (i & 0x07)) & 0x01
191
+ pin.value = value
192
+ emit('digital-read', pin_number, value)
193
+ emit("digital-read-#{pin_number}", value)
194
+ end
195
+ end
196
+
197
+ when START_SYSEX
198
+ current_buffer = [byte]
199
+ begin
200
+ current_buffer.push(bytes.next)
201
+ end until current_buffer.last == END_SYSEX
202
+
203
+ command = current_buffer[1]
204
+
205
+ case command
206
+ when CAPABILITY_RESPONSE
207
+ supported_modes = 0
208
+ n = 0
209
+
210
+ current_buffer.slice(2, current_buffer.length - 3).each do |byte|
211
+ if byte == 127
212
+ modes = []
213
+ # the pin modes
214
+ [ INPUT, OUTPUT, ANALOG, PWM, SERVO ].each do |mode|
215
+ modes.push(mode) unless (supported_modes & (1 << mode)).zero?
216
+ end
217
+
218
+ @pins.push(Pin.new(modes, OUTPUT, 0))
219
+
220
+ supported_modes = 0
221
+ n = 0
222
+ next
223
+ end
224
+
225
+ supported_modes |= (1 << byte) if n.zero?
226
+
227
+ n ^= 1
228
+ end
229
+
230
+ emit('capability_query')
231
+
232
+ when ANALOG_MAPPING_RESPONSE
233
+ pin_index = 0
234
+
235
+ current_buffer.slice(2, current_buffer.length - 3).each do |byte|
236
+
237
+ @pins[pin_index].analog_channel = byte
238
+
239
+ @analog_pins.push(pin_index) unless byte == 127
240
+
241
+ pin_index += 1
242
+ end
243
+
244
+ emit('analog_mapping_query')
245
+
246
+ when PIN_STATE_RESPONSE
247
+ pin = pins[current_buffer[2]]
248
+ pin.mode = current_buffer[3]
249
+ pin.value = current_buffer[4]
250
+
251
+ pin.value |= (current_buffer[5] << 7) if current_buffer.size > 6
252
+
253
+ pin.value |= (current_buffer[6] << 14) if current_buffer.size > 7
254
+
255
+ when FIRMWARE_QUERY
256
+ @firmware_name = current_buffer.slice(4, current_buffer.length - 5).reject { |b| b.zero? }.map(&:chr).join
257
+ emit('firmware_query')
258
+
259
+ else
260
+ puts 'bad byte'
261
+ end
262
+ end
263
+ end
264
+ rescue StopIteration
265
+ # do nadda
266
+ end
267
+
268
+ # Public: Read the serial port and process the results
269
+ #
270
+ # Returns nothing.
271
+ def read_and_process
272
+ process(read)
273
+ end
274
+
275
+ # Public: Send a SYSTEM_RESET to the Arduino
276
+ #
277
+ # Returns nothing.
278
+ def reset
279
+ write(SYSTEM_RESET)
280
+ end
281
+
282
+ # Public: Set the mode for a pin.
283
+ #
284
+ # pin - The Integer pin to set.
285
+ # mode - The Fixnum mode (INPUT, OUTPUT, ANALOG, PWM or SERVO)
286
+ #
287
+ # Examples
288
+ #
289
+ # set_pin_mode(13, OUTPUT)
290
+ #
291
+ # Returns nothing.
292
+ def set_pin_mode(pin, mode)
293
+ pins[pin].mode = mode
294
+ write(PIN_MODE, pin, mode)
295
+ end
296
+
297
+ # Public: Write a value to a digital pin.
298
+ #
299
+ # pin - The Integer pin to write to.
300
+ # value - The value to write (HIGH or LOW).
301
+ #
302
+ # Returns nothing.
303
+ def digital_write(pin, value)
304
+ port = (pin / 8).floor
305
+ port_value = 0
306
+
307
+ @pins[pin].value = value
308
+
309
+ 8.times do |i|
310
+ port_value |= (1 << i) unless @pins[8 * port + i].value.zero?
311
+ end
312
+
313
+ write(DIGITAL_MESSAGE | port, port_value & 0x7F, (port_value >> 7) & 0x7F)
314
+ end
315
+
316
+ # Public: Write an analog messege.
317
+ #
318
+ # pin - The Integer pin to write to.
319
+ # value - The Integer value to write to the pin between 0-255.
320
+ #
321
+ # Returns nothing.
322
+ def analog_write(pin, value)
323
+ @pins[pin].value = value
324
+ write(ANALOG_MESSAGE | pin, value & 0x7F, (value >> 7) & 0x7F)
325
+ end
326
+
327
+ # Public: Write to a servo.
328
+ #
329
+ # pin - The Integer pin to write to.
330
+ # degrees - The Integer degrees to move the servo.
331
+ #
332
+ # Returns nothing.
333
+ alias_method :servo_write, :analog_write
334
+
335
+ # Public: Ask the Arduino to sleep for a number of seconds.
336
+ #
337
+ # seconds - The Integer seconds to sleep for.
338
+ #
339
+ # Returns nothing.
340
+ def delay(seconds)
341
+ sleep(seconds)
342
+ end
343
+
344
+ # Public: The major and minor firmware version on the board. Will report as
345
+ # "0.0" if report_version command has not been run.
346
+ #
347
+ # Returns String the firmware version as "minor.major".
348
+ def version
349
+ [@major_version, @minor_version].join('.')
350
+ end
351
+
352
+ # Public: Ask the Arduino to report its version.
353
+ #
354
+ # Returns nothing.
355
+ def report_version
356
+ write(REPORT_VERSION)
357
+ end
358
+
359
+ # Public: Ask the Ardution for its firmware name.
360
+ #
361
+ # Returns nothing.
362
+ def query_firmware
363
+ write(FIRMWARE_QUERY)
364
+ end
365
+
366
+ # Public: Ask the Arduino for the current configuration of any pin.
367
+ #
368
+ # pin - The Integer pin to query on the board.
369
+ #
370
+ # Returns nothing.
371
+ def query_pin_state(pin)
372
+ write(START_SYSEX, PIN_STATE_QUERY, pin.to_i, END_SYSEX)
373
+ end
374
+
375
+ # Public: Ask the Arduino about its capabilities and current state.
376
+ #
377
+ # Returns nothing.
378
+ def query_capabilities
379
+ write(START_SYSEX, CAPABILITY_QUERY, END_SYSEX)
380
+ end
381
+
382
+ # Public: Ask the Arduino which pins (used with pin mode message) correspond to the analog channels.
383
+ #
384
+ # Returns nothing.
385
+ def query_analog_mapping
386
+ write(START_SYSEX, ANALOG_MAPPING_QUERY, END_SYSEX)
387
+ end
388
+
389
+ # Public: Toggle pin reporting on or off.
390
+ #
391
+ # pin - The Integer pin to toggle.
392
+ # mode - The Integer mode the pin will report. The valid values are
393
+ # REPORT_DIGITAL or REPORT_ANALOG (default: REPORT_DIGITAL).
394
+ # state - The Integer state to toggle the pin. The valid value are
395
+ # HIGH or LOW (default: HIGH)
396
+ #
397
+ # Returns nothing.
398
+ def toggle_pin_reporting(pin, state = HIGH, mode = REPORT_DIGITAL)
399
+ write(mode | pin, state)
400
+ end
401
+
402
+ end
403
+ end
@@ -0,0 +1,3 @@
1
+ module Firmata
2
+ VERSION = "0.2.0"
3
+ end
@@ -0,0 +1,223 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/pride'
3
+
4
+ require_relative '../lib/firmata'
5
+ require_relative 'fake_serial_port'
6
+
7
+ class BoardTest < MiniTest::Unit::TestCase
8
+
9
+ def mock_serial_port(*args, &block)
10
+ mock_port = MiniTest::Mock.new
11
+ mock_port.expect(:is_a?, false, [nil])
12
+
13
+ if block_given?
14
+ yield mock_port
15
+ else
16
+ expected = args.map(&:chr).join
17
+ mock_port.expect(:write_nonblock, 1, [expected])
18
+ end
19
+
20
+ mock_port
21
+ end
22
+
23
+ def test_writing_report_version
24
+ mock_sp = mock_serial_port(Firmata::Board::REPORT_VERSION)
25
+
26
+ board = Firmata::Board.new(mock_sp)
27
+ board.report_version
28
+
29
+ mock_sp.verify
30
+ end
31
+
32
+ def test_processing_report_version
33
+ board = Firmata::Board.new(FakeSerialPort.new)
34
+ board.report_version
35
+ board.read_and_process
36
+
37
+ assert_equal '2.3', board.version
38
+ end
39
+
40
+ def test_writing_capability_query
41
+ mock_sp = mock_serial_port(Firmata::Board::START_SYSEX, Firmata::Board::CAPABILITY_QUERY, Firmata::Board::END_SYSEX)
42
+
43
+ board = Firmata::Board.new(mock_sp)
44
+ board.query_capabilities
45
+
46
+ mock_sp.verify
47
+ end
48
+
49
+ def test_processing_capabilities_query
50
+ board = Firmata::Board.new(FakeSerialPort.new)
51
+ board.query_capabilities
52
+ board.read_and_process
53
+
54
+ assert_equal 20, board.pins.size
55
+ end
56
+
57
+ def test_writing_analog_mapping_query
58
+ mock_sp = mock_serial_port(Firmata::Board::START_SYSEX, Firmata::Board::ANALOG_MAPPING_QUERY, Firmata::Board::END_SYSEX)
59
+
60
+ board = Firmata::Board.new(mock_sp)
61
+ board.query_analog_mapping
62
+
63
+ mock_sp.verify
64
+ end
65
+
66
+ def test_processing_analog_mapping_query
67
+ board = Firmata::Board.new(FakeSerialPort.new)
68
+ board.query_capabilities
69
+ board.read_and_process
70
+
71
+ board.query_analog_mapping
72
+ board.read_and_process
73
+
74
+ assert_equal 6, board.analog_pins.size
75
+ end
76
+
77
+ def test_processing_digital_message
78
+ board = Firmata::Board.new(FakeSerialPort.new)
79
+
80
+ board.query_capabilities
81
+ board.read_and_process
82
+
83
+ board.query_analog_mapping
84
+ board.read_and_process
85
+
86
+ pin = board.pins[8]
87
+ pin.mode = Firmata::Board::INPUT
88
+
89
+ board.process("\x91\x01\x00")
90
+
91
+ assert_equal Firmata::Board::HIGH, pin.value
92
+ end
93
+
94
+ def test_set_pin_mode
95
+ mock_sp = mock_serial_port(Firmata::Board::PIN_MODE, 13, Firmata::Board::OUTPUT)
96
+
97
+ board = Firmata::Board.new(mock_sp)
98
+ board.pins[13] = Firmata::Board::Pin.new([0, 1, 4], 0, 0, nil)
99
+
100
+ board.set_pin_mode(13, Firmata::Board::OUTPUT)
101
+
102
+ assert_equal Firmata::Board::OUTPUT, board.pins[13].mode
103
+ mock_sp.verify
104
+ end
105
+
106
+ def test_write_pin_state_query
107
+ mock_sp = mock_serial_port(Firmata::Board::START_SYSEX, Firmata::Board::PIN_STATE_QUERY, 13, Firmata::Board::END_SYSEX)
108
+
109
+ board = Firmata::Board.new(mock_sp)
110
+ board.query_pin_state(13)
111
+
112
+ mock_sp.verify
113
+ end
114
+
115
+ def test_processing_pin_state_query
116
+ board = Firmata::Board.new(FakeSerialPort.new)
117
+ board.query_capabilities
118
+ board.read_and_process
119
+
120
+ board.pins[13].mode = Firmata::Board::INPUT
121
+
122
+ board.query_pin_state(13)
123
+ board.read_and_process
124
+
125
+ assert_equal Firmata::Board::OUTPUT, board.pins[13].mode
126
+ end
127
+
128
+
129
+ def test_toggling_pin_reporting
130
+ mock_sp = mock_serial_port do |mock|
131
+ mock.expect(:write_nonblock, 2, [[Firmata::Board::REPORT_DIGITAL | 13, 1].map(&:chr).join])
132
+ end
133
+
134
+ board = Firmata::Board.new(mock_sp)
135
+
136
+ board.toggle_pin_reporting(13)
137
+ mock_sp.verify
138
+
139
+ mock_sp.expect(:write_nonblock, 2, [[Firmata::Board::REPORT_DIGITAL | 13, 0].map(&:chr).join])
140
+ board.toggle_pin_reporting(13, 0)
141
+ mock_sp.verify
142
+
143
+ end
144
+
145
+ def test_processing_analog_message
146
+ fake_port = FakeSerialPort.new
147
+ board = Firmata::Board.new(fake_port)
148
+
149
+ board.query_capabilities
150
+ board.read_and_process
151
+
152
+ board.query_analog_mapping
153
+ board.read_and_process
154
+
155
+ fake_port.buffer = "\xE0\e\u0005\xE1N\u0004\xE2A\u0004\xE3C\u0004\xE4o\u0004\xE5f\u0004\xE0w\u0004\xE1]\u0004\xE2N\u0004\xE3I\u0004\xE4x\u0004\xE5m\u0004\xE0m\u0004\xE1`\u0004\xE2T\u0004\xE3L\u0004\xE4s\u0004\xE5l\u0004\xE0i\u0004\xE1`\u0004\xE2V\u0004\xE3N\u0004\xE4m\u0004\xE5j\u0004\xE0f\u0004\xE1^\u0004\xE2U\u0004\xE3O\u0004\xE4h\u0004\xE5g\u0004\xE0d\u0004\xE1\\\u0004\xE2T\u0004\xE3O\u0004\xE4d\u0004\xE5d\u0004\xE0b\u0004\xE1Z\u0004\xE2S\u0004\xE3N\u0004\xE4`\u0004\xE5a\u0004\xE0_\u0004\xE1X\u0004\xE2Q\u0004\xE3L\u0004\xE4\\\u0004\xE5^\u0004\xE0\\\u0004\xE1T\u0004\xE2N\u0004\xE3J\u0004\xE4X\u0004\xE5Z\u0004\xE0X\u0004\xE1Q\u0004\xE2K\u0004\xE3G\u0004\xE4T\u0004\xE5W\u0004\xE0V\u0004\xE1O\u0004\xE2H\u0004\xE3D\u0004\xE4Q\u0004\xE5T\u0004\xE0S\u0004\xE1L\u0004\xE2F\u0004\xE3B\u0004\xE4N\u0004\xE5Q\u0004\xE0P\u0004\xE1J\u0004\xE2C\u0004\xE3@\u0004\xE4K\u0004\xE5N\u0004\xE0N\u0004\xE1G\u0004\xE2A\u0004\xE3>\u0004\xE4I\u0004\xE5L\u0004\xE0L\u0004\xE1D\u0004\xE2?\u0004\xE3<\u0004\xE4F\u0004\xE5I\u0004\xE0I\u0004\xE1B\u0004\xE2=\u0004\xE39\u0004\xE4C\u0004\xE5F\u0004\xE0F\u0004\xE1?\u0004\xE2:\u0004\xE37\u0004\xE4@\u0004\xE5C\u0004\xE0C\u0004\xE1<\u0004\xE28\u0004\xE34\u0004\xE4>\u0004\xE5A\u0004\xE0A\u0004\xE1:\u0004\xE26\u0004\xE32\u0004\xE4<\u0004\xE5?\u0004\xE0?\u0004\xE19\u0004\xE24\u0004\xE31\u0004\xE4:\u0004\xE5=\u0004\xE0>\u0004\xE17\u0004\xE22\u0004\xE3/\u0004\xE49\u0004\xE5;\u0004\xE0<\u0004\xE15\u0004\xE20\u0004\xE3-\u0004\xE46\u0004\xE59\u0004\xE09\u0004\xE12\u0004\xE2.\u0004\xE3+\u0004\xE44\u0004\xE57\u0004\xE07\u0004\xE10\u0004\xE2,\u0004\xE3)\u0004\xE42\u0004\xE55\u0004\xE05\u0004\xE1.\u0004\xE2*\u0004\xE3'\u0004\xE40\u0004\xE52\u0004\xE03\u0004\xE1-\u0004\xE2(\u0004\xE3&\u0004\xE4/\u0004\xE51\u0004\xE02\u0004\xE1+\u0004\xE2&\u0004\xE3$\u0004\xE4-\u0004\xE50\u0004\xE00\u0004\xE1*\u0004\xE2%\u0004\xE3#\u0004\xE4,\u0004\xE5.\u0004\xE0/\u0004\xE1(\u0004\xE2$\u0004\xE3!\u0004\xE4*\u0004\xE5,\u0004\xE0-\u0004\xE1&\u0004\xE2\"\u0004\xE3\u001F\u0004\xE4(\u0004\xE5*\u0004\xE0+\u0004\xE1$\u0004\xE2 \u0004\xE3\u001D\u0004\xE4&\u0004\xE5(\u0004\xE0)\u0004\xE1\"\u0004\xE2\u001F\u0004\xE3\u001C\u0004\xE4%\u0004\xE5'\u0004\xE0(\u0004\xE1!\u0004\xE2\u001D\u0004\xE3\e\u0004\xE4$\u0004\xE5&\u0004\xE0&\u0004\xE1 \u0004\xE2\u001C\u0004\xE3\u001A\u0004\xE4#\u0004\xE5%\u0004\xE0&\u0004\xE1\u001F\u0004\xE2\e\u0004\xE3\u0019\u0004\xE4\"\u0004\xE5$\u0004\xE0$\u0004\xE1\u001E\u0004\xE2\u0019\u0004\xE3\u0018\u0004\xE4 \u0004\xE5\"\u0004\xE0\"\u0004\xE1\u001C\u0004\xE2\u0018\u0004\xE3\u0016\u0004\xE4\u001F\u0004\xE5 \u0004\xE0!\u0004\xE1\u001A\u0004\xE2\u0017\u0004\xE3\u0014\u0004\xE4\u001D\u0004\xE5\u001E\u0004\xE0\u001F\u0004\xE1\u0019\u0004\xE2\u0015\u0004\xE3\u0013\u0004\xE4\u001C\u0004\xE5\u001D\u0004\xE0\u001E\u0004\xE1\u0018\u0004\xE2\u0013\u0004\xE3\u0012\u0004\xE4\e\u0004\xE5\u001C\u0004\xE0\u001D\u0004\xE1\u0017\u0004\xE2\u0014\u0004\xE3\u0012\u0004\xE4\e\u0004\xE5\u001C\u0004\xE0\u001D\u0004\xE1\u0016\u0004\xE2\u0013\u0004\xE3\u0011\u0004\xE4\u001A\u0004\xE5\e\u0004\xE0\u001C\u0004\xE1\u0015\u0004\xE2\u0011\u0004\xE3\u0010\u0004\xE4\u0018\u0004\xE5\u0019\u0004\xE0\u001A\u0004\xE1\u0014\u0004\xE2\u0010\u0004\xE3\u000E\u0004\xE4\u0017\u0004\xE5\u0018\u0004\xE0\u0018\u0004\xE1\u0012\u0004\xE2\u000E\u0004\xE3\r\u0004\xE4\u0015\u0004\xE5\u0016\u0004\xE0\u0017\u0004\xE1\u0011\u0004\xE2\u000E\u0004\xE3\f\u0004\xE4\u0015\u0004\xE5\u0016\u0004\xE0\u0016\u0004\xE1\u0010\u0004\xE2\f\u0004\xE3\v\u0004\xE4\u0014\u0004\xE5\u0015\u0004\xE0\u0016\u0004\xE1\u000F\u0004\xE2\v\u0004\xE3\n\u0004\xE4\u0013\u0004\xE5\u0014\u0004\xE0\u0015\u0004\xE1\u000F\u0004\xE2\v\u0004\xE3\t\u0004\xE4\u0012\u0004\xE5\u0013\u0004\xE0\u0014\u0004\xE1\u000E\u0004\xE2\n\u0004\xE3\t\u0004\xE4\u0012\u0004\xE5\u0012\u0004\xE0\u0013\u0004\xE1\f\u0004\xE2\t\u0004\xE3\a\u0004\xE4\u0010\u0004\xE5\u0011\u0004\xE0\u0011\u0004\xE1\v\u0004\xE2\b\u0004\xE3\u0006\u0004\xE4\u000F\u0004\xE5\u000F\u0004\xE0\u0010\u0004\xE1\n\u0004\xE2\u0006\u0004\xE3\u0005\u0004\xE4\u000E\u0004\xE5\u000F\u0004\xE0\u000F\u0004\xE1\t\u0004\xE2\u0006\u0004\xE3\u0004\u0004\xE4\r\u0004\xE5\u000E\u0004\xE0\u000F\u0004\xE1\t\u0004\xE2\u0006\u0004\xE3\u0004\u0004\xE4\r\u0004\xE5\u000E\u0004\xE0\u000E\u0004\xE1\b\u0004\xE2\u0004\u0004\xE3\u0003\u0004\xE4\f\u0004\xE5\r\u0004\xE0\u000E\u0004\xE1\a\u0004\xE2\u0004\u0004\xE3\u0003\u0004"
156
+ board.read_and_process
157
+
158
+ board.analog_pins.each do |pin|
159
+ refute_nil board.pins[pin].analog_channel, "Analog channel not set for pin #{pin}"
160
+ end
161
+ end
162
+
163
+ def test_reset
164
+ mock_sp = mock_serial_port(Firmata::Board::SYSTEM_RESET)
165
+
166
+ board = Firmata::Board.new(mock_sp)
167
+ board.reset
168
+
169
+ mock_sp.verify
170
+ end
171
+
172
+ def test_write_firmware_query
173
+ mock_sp = mock_serial_port(Firmata::Board::FIRMWARE_QUERY)
174
+
175
+ board = Firmata::Board.new(mock_sp)
176
+ board.query_firmware
177
+
178
+ mock_sp.verify
179
+ end
180
+
181
+ def test_process_firmware_query
182
+ fake_port = FakeSerialPort.new
183
+ fake_port.buffer = "\xF0y\u0002\u0003S\u0000t\u0000a\u0000n\u0000d\u0000a\u0000r\u0000d\u0000F\u0000i\u0000r\u0000m\u0000a\u0000t\u0000a\u0000\xF7"
184
+ board = Firmata::Board.new(fake_port)
185
+
186
+ board.read_and_process
187
+
188
+ assert_equal 'StandardFirmata', board.firmware_name, 'Firmware Name is incorrect'
189
+ end
190
+
191
+ def test_digital_write
192
+ mock_sp = mock_serial_port(145, 127, 1)
193
+ board = Firmata::Board.new(mock_sp)
194
+
195
+ 8.times do |x|
196
+ board.pins[x + 8] = Firmata::Board::Pin.new([], 0, 250 + x, nil)
197
+ end
198
+
199
+ board.digital_write(13, 1)
200
+
201
+ assert_equal 1, board.pins[13].value, "Pin value not set"
202
+ mock_sp.verify
203
+ end
204
+
205
+ def test_analog_write
206
+ mock_sp = mock_serial_port(233, 127, 1)
207
+ board = Firmata::Board.new(mock_sp)
208
+
209
+ 8.times do |x|
210
+ board.pins[x + 8] = Firmata::Board::Pin.new([], 0, 250 + x, nil)
211
+ end
212
+
213
+ board.analog_write(9, 255)
214
+
215
+ assert_equal 255, board.pins[9].value
216
+ mock_sp.verify
217
+ end
218
+
219
+ def test_servo_write
220
+ board = Firmata::Board.new(FakeSerialPort.new)
221
+ assert board.respond_to? :servo_write
222
+ end
223
+ end
@@ -0,0 +1,55 @@
1
+ require 'stringio'
2
+
3
+ class FakeSerialPort
4
+ Board = Firmata::Board
5
+
6
+ attr_accessor :buffer
7
+ attr_accessor :read_timeout
8
+
9
+ def initialize
10
+ @buffer = ""
11
+ @read_timeout = 0
12
+ end
13
+
14
+ def write(command)
15
+ val = case command.getbyte(0)
16
+ when Board::SYSTEM_RESET
17
+ ""
18
+ when Board::REPORT_VERSION
19
+ "\xF9\u0002\u0003"
20
+
21
+ when Board::REPORT_DIGITAL, Board::REPORT_ANALOG
22
+ "\xE0\e\u0005\xE1N\u0004\xE2A\u0004\xE3C\u0004\xE4o\u0004\xE5f\u0004\xE0w\u0004\xE1]\u0004\xE2N\u0004\xE3I\u0004\xE4x\u0004\xE5m\u0004\xE0m\u0004\xE1`\u0004\xE2T\u0004\xE3L\u0004\xE4s\u0004\xE5l\u0004\xE0i\u0004\xE1`\u0004\xE2V\u0004\xE3N\u0004\xE4m\u0004\xE5j\u0004\xE0f\u0004\xE1^\u0004\xE2U\u0004\xE3O\u0004\xE4h\u0004\xE5g\u0004\xE0d\u0004\xE1\\\u0004\xE2T\u0004\xE3O\u0004\xE4d\u0004\xE5d\u0004\xE0b\u0004\xE1Z\u0004\xE2S\u0004\xE3N\u0004\xE4`\u0004\xE5a\u0004\xE0_\u0004\xE1X\u0004\xE2Q\u0004\xE3L\u0004\xE4\\\u0004\xE5^\u0004\xE0\\\u0004\xE1T\u0004\xE2N\u0004\xE3J\u0004\xE4X\u0004\xE5Z\u0004\xE0X\u0004\xE1Q\u0004\xE2K\u0004\xE3G\u0004\xE4T\u0004\xE5W\u0004\xE0V\u0004\xE1O\u0004\xE2H\u0004\xE3D\u0004\xE4Q\u0004\xE5T\u0004\xE0S\u0004\xE1L\u0004\xE2F\u0004\xE3B\u0004\xE4N\u0004\xE5Q\u0004\xE0P\u0004\xE1J\u0004\xE2C\u0004\xE3@\u0004\xE4K\u0004\xE5N\u0004\xE0N\u0004\xE1G\u0004\xE2A\u0004\xE3>\u0004\xE4I\u0004\xE5L\u0004\xE0L\u0004\xE1D\u0004\xE2?\u0004\xE3<\u0004\xE4F\u0004\xE5I\u0004\xE0I\u0004\xE1B\u0004\xE2=\u0004\xE39\u0004\xE4C\u0004\xE5F\u0004\xE0F\u0004\xE1?\u0004\xE2:\u0004\xE37\u0004\xE4@\u0004\xE5C\u0004\xE0C\u0004\xE1<\u0004\xE28\u0004\xE34\u0004\xE4>\u0004\xE5A\u0004\xE0A\u0004\xE1:\u0004\xE26\u0004\xE32\u0004\xE4<\u0004\xE5?\u0004\xE0?\u0004\xE19\u0004\xE24\u0004\xE31\u0004\xE4:\u0004\xE5=\u0004\xE0>\u0004\xE17\u0004\xE22\u0004\xE3/\u0004\xE49\u0004\xE5;\u0004\xE0<\u0004\xE15\u0004\xE20\u0004\xE3-\u0004\xE46\u0004\xE59\u0004\xE09\u0004\xE12\u0004\xE2.\u0004\xE3+\u0004\xE44\u0004\xE57\u0004\xE07\u0004\xE10\u0004\xE2,\u0004\xE3)\u0004\xE42\u0004\xE55\u0004\xE05\u0004\xE1.\u0004\xE2*\u0004\xE3'\u0004\xE40\u0004\xE52\u0004\xE03\u0004\xE1-\u0004\xE2(\u0004\xE3&\u0004\xE4/\u0004\xE51\u0004\xE02\u0004\xE1+\u0004\xE2&\u0004\xE3$\u0004\xE4-\u0004\xE50\u0004\xE00\u0004\xE1*\u0004\xE2%\u0004\xE3#\u0004\xE4,\u0004\xE5.\u0004\xE0/\u0004\xE1(\u0004\xE2$\u0004\xE3!\u0004\xE4*\u0004\xE5,\u0004\xE0-\u0004\xE1&\u0004\xE2\"\u0004\xE3\u001F\u0004\xE4(\u0004\xE5*\u0004\xE0+\u0004\xE1$\u0004\xE2 \u0004\xE3\u001D\u0004\xE4&\u0004\xE5(\u0004\xE0)\u0004\xE1\"\u0004\xE2\u001F\u0004\xE3\u001C\u0004\xE4%\u0004\xE5'\u0004\xE0(\u0004\xE1!\u0004\xE2\u001D\u0004\xE3\e\u0004\xE4$\u0004\xE5&\u0004\xE0&\u0004\xE1 \u0004\xE2\u001C\u0004\xE3\u001A\u0004\xE4#\u0004\xE5%\u0004\xE0&\u0004\xE1\u001F\u0004\xE2\e\u0004\xE3\u0019\u0004\xE4\"\u0004\xE5$\u0004\xE0$\u0004\xE1\u001E\u0004\xE2\u0019\u0004\xE3\u0018\u0004\xE4 \u0004\xE5\"\u0004\xE0\"\u0004\xE1\u001C\u0004\xE2\u0018\u0004\xE3\u0016\u0004\xE4\u001F\u0004\xE5 \u0004\xE0!\u0004\xE1\u001A\u0004\xE2\u0017\u0004\xE3\u0014\u0004\xE4\u001D\u0004\xE5\u001E\u0004\xE0\u001F\u0004\xE1\u0019\u0004\xE2\u0015\u0004\xE3\u0013\u0004\xE4\u001C\u0004\xE5\u001D\u0004\xE0\u001E\u0004\xE1\u0018\u0004\xE2\u0013\u0004\xE3\u0012\u0004\xE4\e\u0004\xE5\u001C\u0004\xE0\u001D\u0004\xE1\u0017\u0004\xE2\u0014\u0004\xE3\u0012\u0004\xE4\e\u0004\xE5\u001C\u0004\xE0\u001D\u0004\xE1\u0016\u0004\xE2\u0013\u0004\xE3\u0011\u0004\xE4\u001A\u0004\xE5\e\u0004\xE0\u001C\u0004\xE1\u0015\u0004\xE2\u0011\u0004\xE3\u0010\u0004\xE4\u0018\u0004\xE5\u0019\u0004\xE0\u001A\u0004\xE1\u0014\u0004\xE2\u0010\u0004\xE3\u000E\u0004\xE4\u0017\u0004\xE5\u0018\u0004\xE0\u0018\u0004\xE1\u0012\u0004\xE2\u000E\u0004\xE3\r\u0004\xE4\u0015\u0004\xE5\u0016\u0004\xE0\u0017\u0004\xE1\u0011\u0004\xE2\u000E\u0004\xE3\f\u0004\xE4\u0015\u0004\xE5\u0016\u0004\xE0\u0016\u0004\xE1\u0010\u0004\xE2\f\u0004\xE3\v\u0004\xE4\u0014\u0004\xE5\u0015\u0004\xE0\u0016\u0004\xE1\u000F\u0004\xE2\v\u0004\xE3\n\u0004\xE4\u0013\u0004\xE5\u0014\u0004\xE0\u0015\u0004\xE1\u000F\u0004\xE2\v\u0004\xE3\t\u0004\xE4\u0012\u0004\xE5\u0013\u0004\xE0\u0014\u0004\xE1\u000E\u0004\xE2\n\u0004\xE3\t\u0004\xE4\u0012\u0004\xE5\u0012\u0004\xE0\u0013\u0004\xE1\f\u0004\xE2\t\u0004\xE3\a\u0004\xE4\u0010\u0004\xE5\u0011\u0004\xE0\u0011\u0004\xE1\v\u0004\xE2\b\u0004\xE3\u0006\u0004\xE4\u000F\u0004\xE5\u000F\u0004\xE0\u0010\u0004\xE1\n\u0004\xE2\u0006\u0004\xE3\u0005\u0004\xE4\u000E\u0004\xE5\u000F\u0004\xE0\u000F\u0004\xE1\t\u0004\xE2\u0006\u0004\xE3\u0004\u0004\xE4\r\u0004\xE5\u000E\u0004\xE0\u000F\u0004\xE1\t\u0004\xE2\u0006\u0004\xE3\u0004\u0004\xE4\r\u0004\xE5\u000E\u0004\xE0\u000E\u0004\xE1\b\u0004\xE2\u0004\u0004\xE3\u0003\u0004\xE4\f\u0004\xE5\r\u0004\xE0\u000E\u0004\xE1\a\u0004\xE2\u0004\u0004\xE3\u0003\u0004"
23
+
24
+ when Board::FIRMWARE_QUERY
25
+ "\xF0y\u0002\u0003S\u0000t\u0000a\u0000n\u0000d\u0000a\u0000r\u0000d\u0000F\u0000i\u0000r\u0000m\u0000a\u0000t\u0000a\u0000\xF7"
26
+
27
+ when Board::START_SYSEX
28
+ case command.getbyte(1)
29
+ when Board::ANALOG_MAPPING_QUERY
30
+ "\xF0j\u007F\u007F\u007F\u007F\u007F\u007F\u007F\u007F\u007F\u007F\u007F\u007F\u007F\u007F\u0000\u0001\u0002\u0003\u0004\u0005\xF7"
31
+
32
+ when Board::CAPABILITY_QUERY
33
+ "\xF0l\u007F\u007F\u0000\u0001\u0001\u0001\u0004\u000E\u007F\u0000\u0001\u0001\u0001\u0003\b\u0004\u000E\u007F\u0000\u0001\u0001\u0001\u0004\u000E\u007F\u0000\u0001\u0001\u0001\u0003\b\u0004\u000E\u007F\u0000\u0001\u0001\u0001\u0003\b\u0004\u000E\u007F\u0000\u0001\u0001\u0001\u0004\u000E\u007F\u0000\u0001\u0001\u0001\u0004\u000E\u007F\u0000\u0001\u0001\u0001\u0003\b\u0004\u000E\u007F\u0000\u0001\u0001\u0001\u0003\b\u0004\u000E\u007F\u0000\u0001\u0001\u0001\u0003\b\u0004\u000E\u007F\u0000\u0001\u0001\u0001\u0004\u000E\u007F\u0000\u0001\u0001\u0001\u0004\u000E\u007F\u0000\u0001\u0001\u0001\u0002\n\u007F\u0000\u0001\u0001\u0001\u0002\n\u007F\u0000\u0001\u0001\u0001\u0002\n\u007F\u0000\u0001\u0001\u0001\u0002\n\u007F\u0000\u0001\u0001\u0001\u0002\n\u0006\u0001\u007F\u0000\u0001\u0001\u0001\u0002\n\u0006\u0001\u007F\xF7"
34
+
35
+ when Board::PIN_STATE_QUERY
36
+ "\xF0n\r\u0001\u0000\xF7"
37
+ end
38
+ end
39
+
40
+ @buffer << val
41
+ val.length
42
+ end
43
+ alias_method :write_nonblock, :write
44
+
45
+ def bytes
46
+ bytes = StringIO.new(@buffer).bytes
47
+ @buffer = ""
48
+ bytes
49
+ end
50
+
51
+ def read(size)
52
+ @buffer
53
+ end
54
+ alias_method :read_nonblock, :read
55
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hybridgroup-firmata
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - ! '''Mike Breen'', ''Adrian Zankich'''
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: pry
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: event_spitter
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: A lib for working with the Firmata protocol in Ruby.
47
+ email:
48
+ - info@hybridgroup.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - Gemfile
55
+ - LICENSE
56
+ - README.md
57
+ - Rakefile
58
+ - examples/blink_led.rb
59
+ - firmata.gemspec
60
+ - lib/firmata.rb
61
+ - lib/firmata/board.rb
62
+ - lib/firmata/version.rb
63
+ - test/board_test.rb
64
+ - test/fake_serial_port.rb
65
+ homepage: ''
66
+ licenses: []
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ none: false
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 1.8.23
86
+ signing_key:
87
+ specification_version: 3
88
+ summary: ''
89
+ test_files:
90
+ - test/board_test.rb
91
+ - test/fake_serial_port.rb