dino 0.9.1 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,19 +1,41 @@
1
1
  # Welcome to Dino
2
2
  [![Build Status](https://secure.travis-ci.org/austinbv/dino.png)](http://travis-ci.org/austinbv/dino)
3
3
 
4
- ## Get started in no time
4
+ ## Get Started In No Time
5
+
5
6
  Dino was designed to help you start working with your Arduino in minutes.
6
7
 
7
- > * `gem install dino`
8
- > * Burn the file `src/du.ino` to your Arduino
9
- > ** You can do this in the [Arduino IDE](http://www.arduino.cc/en/Main/software)
10
- > * Plug in your Arduino and wire the led like in `examples/led/led.png`
11
- > * Run `ruby example/led/led.rb`
8
+ #### Install the Gem
9
+
10
+ ```
11
+ gem install dino
12
+ ```
13
+
14
+ #### Upload the Bootstrapper
15
+
16
+ * Open [the normal Arduino IDE](http://arduino.cc/en/Main/Software)
17
+ * Download the bootstrapper [src/du.ino](https://raw.github.com/austinbv/dino/master/src/du.ino)
18
+ * Open the file in the Arduino IDE
19
+ * Plug in your Arduino via USB
20
+ * Click the upload button (an arrow)
21
+
22
+ #### Verify Install
23
+
24
+ * Build the sample circuit [examples/led/led.png](https://raw.github.com/austinbv/dino/master/examples/led/led.png)
25
+ * From your terminal, execute `ruby example/led/led.rb`
26
+ * Observe your LED blinking continuously
12
27
 
13
- By now you should be blinking away
28
+ ## Examples and Tutorials
14
29
 
30
+ ### Circuits and Programs
15
31
 
16
- Take a look in the example directory for more information
32
+ * Take a look in [the example directory](https://github.com/austinbv/dino/tree/master/examples) for small component examples
33
+ * Try [Getting Started with Arduino and Dino](http://tutorials.jumpstartlab.com/projects/arduino/introducing_arduino.html) from [Jumpstart Lab](http://jumpstartlab.com), building a number-guessing game and a simple nightlight
34
+ * An example [rails app using Dino and Pusher](https://github.com/austinbv/dino_rails_example)
35
+ * For a Sinatra example look at the [site used to shoot the cannon at RubyConf2012](https://github.com/austinbv/dino_cannon)
17
36
 
37
+ ### Explanatory Talks
18
38
 
19
- I gave a [talk on this library at RubyConf](http://confreaks.com/videos/1294-rubyconf2012-arduino-the-ruby-way), you can see the slides here: [Arudino The Ruby Way](https://speakerdeck.com/austinbv/arduino-the-ruby-way)
39
+ * "Arduino the Ruby Way" at RubyConf 2012
40
+ * [Video by ConFreaks](http://confreaks.com/videos/1294-rubyconf2012-arduino-the-ruby-way)
41
+ * [Slides on SpeakerDeck](https://speakerdeck.com/austinbv/arduino-the-ruby-way)
@@ -9,15 +9,12 @@ require File.expand_path('../../../lib/dino', __FILE__)
9
9
  board = Dino::Board.new(Dino::TxRx.new)
10
10
  button = Dino::Components::Button.new(pin: 13, board: board)
11
11
 
12
- button_down = Proc.new do
12
+ button.down do
13
13
  puts "button down"
14
14
  end
15
15
 
16
- button_up = Proc.new do
16
+ button.up do
17
17
  puts "button up"
18
18
  end
19
19
 
20
- button.down(button_down)
21
- button.up(button_up)
22
-
23
20
  sleep
@@ -1,8 +1,5 @@
1
1
  #
2
- # This is an example of how to use the button class
3
- # You must register helpers and have the main thread
4
- # sleep or in someway keep running or your program
5
- # will exit before any callbacks can be called
2
+ # This is an example of how to use the servo class
6
3
  #
7
4
 
8
5
  require File.expand_path('../../lib/dino', __FILE__)
@@ -0,0 +1,28 @@
1
+ #
2
+ # Example showing how to access an Arduino over a telnet connection.
3
+ # Running ser2net on the machine that the Arduino is connected to will serve up the serial interface over telnet.
4
+ # You can then communicate with that Arduino over your local network or the Internet.
5
+ #
6
+ # Example ser2net command for an Arduino UNO on Mac:
7
+ # ser2net -u -C "9000:raw:0:/dev/cu.usbmodem621:115200"
8
+ #
9
+ # Replace 9000 with the port number you want to use and /dev/cu.usbmodem621 with your Arduino device.
10
+ # Arduino UNOs are usually /dev/ACM0 under Linux.
11
+ #
12
+ # ser2net is preinstalled on many Linuxes. Install ser2net on Mac with:
13
+ # brew install ser2net
14
+ #
15
+ # http://sourceforge.net/projects/ser2net/ for more info on configuring ser2net.
16
+ #
17
+
18
+ require File.expand_path('../../lib/dino', __FILE__)
19
+
20
+ # The host and port for the telnet connection must be passed in as arguments.
21
+ connection = Dino::TxRx::Telnet.new("localhost", 9000)
22
+ board = Dino::Board.new(connection)
23
+ led = Dino::Components::Led.new(pin: 13, board: board)
24
+
25
+ [:on, :off].cycle do |switch|
26
+ led.send(switch)
27
+ sleep 0.5
28
+ end
@@ -11,11 +11,11 @@ module Dino
11
11
  self.board.start_read
12
12
  end
13
13
 
14
- def down(callback)
14
+ def down(&callback)
15
15
  @down_callbacks << callback
16
16
  end
17
17
 
18
- def up(callback)
18
+ def up(&callback)
19
19
  @up_callbacks << callback
20
20
  end
21
21
 
@@ -1,67 +1,10 @@
1
- require 'serialport'
2
- require 'observer'
3
-
4
1
  module Dino
5
- class TxRx
6
- include Observable
7
-
8
- BAUD = 115200
9
-
10
- def initialize
11
- @first_write = true
12
- end
13
-
14
- def io
15
- raise BoardNotFound unless @io ||= find_arduino
16
- @io
17
- end
18
-
19
- def io=(device)
20
- @io = SerialPort.new(device, BAUD)
21
- end
22
-
23
- def read
24
- @thread ||= Thread.new do
25
- loop do
26
- if IO.select([io], nil, nil, 0.005)
27
- pin, message = *io.gets.chop.split(/::/)
28
- pin && message && changed && notify_observers(pin, message)
29
- end
30
- sleep 0.004
31
- end
32
- end
33
- end
34
-
35
- def close_read
36
- return nil if @thread.nil?
37
- Thread.kill(@thread)
38
- @thread = nil
39
- end
40
-
41
- def write(message)
42
- IO.select(nil, [io], nil)
43
- io.puts(message)
44
- end
45
-
46
- private
47
-
48
- def tty_devices
49
- if RUBY_PLATFORM.include?("mswin") || RUBY_PLATFORM.include?("mingw")
50
- ["COM1", "COM2", "COM3", "COM4"]
51
- else
52
- `ls /dev`.split("\n").grep(/usb|ACM/).map{|d| "/dev/#{d}"}
53
- end
54
- end
2
+ module TxRx
3
+ require 'dino/tx_rx/usb_serial'
4
+ require 'dino/tx_rx/telnet'
55
5
 
56
- def find_arduino
57
- tty_devices.map do |device|
58
- next if device.match /^cu/
59
- begin
60
- SerialPort.new(device, BAUD)
61
- rescue
62
- nil
63
- end
64
- end.compact.first
6
+ def self.new
7
+ self::USBSerial.new
65
8
  end
66
9
  end
67
- end
10
+ end
@@ -0,0 +1,53 @@
1
+ require 'net/telnet'
2
+ require 'observer'
3
+
4
+ module Dino
5
+ module TxRx
6
+ class Telnet
7
+ include Observable
8
+
9
+ def initialize(host, port)
10
+ @host, @port = host, port
11
+ @read_buffer = ""
12
+ end
13
+
14
+ def io
15
+ @io ||= connect
16
+ end
17
+
18
+ def read
19
+ @thread ||= Thread.new do
20
+ loop do
21
+ io.waitfor("\n") do |text|
22
+ @read_buffer += text
23
+ while line = @read_buffer.slice!(/^.*\n/) do
24
+ pin, message = line.chop.split(/::/)
25
+ pin && message && changed && notify_observers(pin, message)
26
+ end
27
+ end
28
+ sleep 0.004
29
+ end
30
+ end
31
+ end
32
+
33
+ def close_read
34
+ return nil if @thread.nil?
35
+ Thread.kill(@thread)
36
+ @read_buffer = ""
37
+ @thread = nil
38
+ end
39
+
40
+ def write(message)
41
+ io.puts(message)
42
+ end
43
+
44
+ private
45
+
46
+ def connect
47
+ Net::Telnet.new("Host" => @host, "Port" => @port)
48
+ rescue
49
+ raise BoardNotFound
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,69 @@
1
+ require 'serialport'
2
+ require 'observer'
3
+
4
+ module Dino
5
+ module TxRx
6
+ class USBSerial
7
+ include Observable
8
+
9
+ BAUD = 115200
10
+
11
+ def initialize
12
+ @first_write = true
13
+ end
14
+
15
+ def io
16
+ raise BoardNotFound unless @io ||= find_arduino
17
+ @io
18
+ end
19
+
20
+ def io=(device)
21
+ @io = SerialPort.new(device, BAUD)
22
+ end
23
+
24
+ def read
25
+ @thread ||= Thread.new do
26
+ loop do
27
+ if IO.select([io], nil, nil, 0.005)
28
+ pin, message = *io.gets.chop.split(/::/)
29
+ pin && message && changed && notify_observers(pin, message)
30
+ end
31
+ sleep 0.004
32
+ end
33
+ end
34
+ end
35
+
36
+ def close_read
37
+ return nil if @thread.nil?
38
+ Thread.kill(@thread)
39
+ @thread = nil
40
+ end
41
+
42
+ def write(message)
43
+ IO.select(nil, [io], nil)
44
+ io.puts(message)
45
+ end
46
+
47
+ private
48
+
49
+ def tty_devices
50
+ if RUBY_PLATFORM.include?("mswin") || RUBY_PLATFORM.include?("mingw")
51
+ ["COM1", "COM2", "COM3", "COM4"]
52
+ else
53
+ `ls /dev`.split("\n").grep(/usb|ACM/).map{|d| "/dev/#{d}"}
54
+ end
55
+ end
56
+
57
+ def find_arduino
58
+ tty_devices.map do |device|
59
+ next if device.match /^cu/
60
+ begin
61
+ SerialPort.new(device, BAUD)
62
+ rescue
63
+ nil
64
+ end
65
+ end.compact.first
66
+ end
67
+ end
68
+ end
69
+ end
@@ -1,3 +1,3 @@
1
1
  module Dino
2
- VERSION = "0.9.1"
2
+ VERSION = "0.10.0"
3
3
  end
@@ -29,52 +29,88 @@ module Dino
29
29
  let(:button) {Button.new(board: board, pin: mock)}
30
30
  describe '#down' do
31
31
  it 'should add a callback to the down_callbacks array' do
32
- button.down(callback_mock = mock)
33
- button.instance_variable_get(:@down_callbacks).should include callback_mock
32
+ callback = mock
33
+ button.down do
34
+ callback.called
35
+ end
36
+ down_callbacks = button.instance_variable_get(:@down_callbacks)
37
+ down_callbacks.size.should == 1
38
+ callback.should_receive(:called)
39
+ down_callbacks.first.call
34
40
  end
35
41
  end
36
42
 
37
43
  describe '#up' do
38
44
  it 'should add a callback to the up_callbacks array' do
39
- button.up(callback_mock = mock)
40
- button.instance_variable_get(:@up_callbacks).should include callback_mock
45
+ callback = mock
46
+ button.up do
47
+ callback.called
48
+ end
49
+ up_callbacks = button.instance_variable_get(:@up_callbacks)
50
+ up_callbacks.size.should == 1
51
+ callback.should_receive(:called)
52
+ up_callbacks.first.call
41
53
  end
42
54
  end
43
55
 
44
56
  describe '#update' do
45
57
  it 'should call the down callbacks' do
46
- button.down(callback_mock1 = mock)
47
- button.down(callback_mock2 = mock)
48
- callback_mock1.should_receive(:call)
49
- callback_mock2.should_receive(:call)
58
+ callback_1 = mock
59
+ button.down do
60
+ callback_1.called
61
+ end
62
+
63
+ callback_2 = mock
64
+ button.down do
65
+ callback_2.called
66
+ end
67
+ callback_1.should_receive(:called)
68
+ callback_2.should_receive(:called)
50
69
  button.update(Button::DOWN)
51
70
  end
52
71
 
53
72
  it 'should call the up callbacks' do
54
- button.up(callback_mock1 = mock)
55
- button.up(callback_mock2 = mock)
73
+ callback_1 = mock
74
+ button.up do
75
+ callback_1.called
76
+ end
77
+
78
+ callback_2 = mock
79
+ button.up do
80
+ callback_2.called
81
+ end
56
82
 
57
83
  button.instance_variable_set(:@state, Button::DOWN)
58
84
 
59
- callback_mock1.should_receive(:call)
60
- callback_mock2.should_receive(:call)
85
+ callback_1.should_receive(:called)
86
+ callback_2.should_receive(:called)
61
87
  button.update(Button::UP)
62
88
  end
63
89
 
64
90
  it 'should not call the callbacks if the state has not changed' do
65
- button.up(callback_mock = mock)
91
+ callback = mock
92
+ button.up do
93
+ callback.called
94
+ end
66
95
 
67
- callback_mock.should_not_receive(:call)
96
+ callback.should_not_receive(:called)
68
97
  button.update(Button::UP)
69
98
  button.update(Button::UP)
70
99
  end
71
100
 
72
101
  it 'should not call the callbacks if the data is not UP or DOWN' do
73
- button.up(callback_mock1 = mock)
74
- button.down(callback_mock2 = mock)
102
+ callback_1 = mock
103
+ button.up do
104
+ callback_1.called
105
+ end
75
106
 
76
- callback_mock1.should_not_receive(:call)
77
- callback_mock2.should_not_receive(:call)
107
+ callback_2 = mock
108
+ button.down do
109
+ callback_2.called
110
+ end
111
+
112
+ callback_1.should_not_receive(:called)
113
+ callback_2.should_not_receive(:called)
78
114
  button.update('foobarred')
79
115
  end
80
116
  end
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+
3
+ module Dino
4
+ describe TxRx::Telnet do
5
+
6
+ before :each do
7
+ @mock_telnet = mock
8
+ Net::Telnet.stub(:new) { @mock_telnet }
9
+ @instance = TxRx::Telnet.new("127.0.0.1", 3001)
10
+ end
11
+
12
+ describe '#connect' do
13
+ it 'should raise a BoardNotFound exception if it cannot connect to the server' do
14
+ Net::Telnet.stub(:new).and_raise
15
+ @instance = TxRx::Telnet.new("0.0.0.0", 999999)
16
+ expect { @instance.io }.to raise_exception BoardNotFound
17
+ end
18
+ end
19
+
20
+ describe '#io' do
21
+ it 'should set io to a new telnet connection with the specified host and port' do
22
+ Net::Telnet.should_receive(:new).with("Host" => "127.0.0.1", "Port" => 3001)
23
+ @instance.io
24
+ end
25
+
26
+ it 'should use the existing io instance if set' do
27
+ Net::Telnet.should_receive(:new).exactly(1).times.with("Host" => "127.0.0.1", "Port" => 3001)
28
+ 2.times { @instance.io }
29
+ end
30
+ end
31
+
32
+ describe '#read' do
33
+ it 'should create a new thread' do
34
+ Thread.should_receive :new
35
+ @instance.read
36
+ end
37
+
38
+ it 'should get messages from the device' do
39
+ Thread.should_receive(:new).and_yield
40
+ @instance.should_receive(:loop).and_yield
41
+ @instance.io.should_receive(:waitfor).with("\n").and_yield("foo::bar\n")
42
+ @instance.should_receive(:changed).and_return(true)
43
+ @instance.should_receive(:notify_observers).with('foo','bar')
44
+
45
+ @instance.read
46
+ end
47
+ end
48
+
49
+ describe '#close_read' do
50
+ it 'should kill the reading thread' do
51
+ @instance.instance_variable_set(:@thread, mock_thread = mock)
52
+ Thread.should_receive(:kill).with(mock_thread)
53
+ @instance.read
54
+ @instance.close_read
55
+ end
56
+ end
57
+
58
+ describe '#write' do
59
+ it 'should write to the device' do
60
+ @mock_telnet.should_receive(:puts).with("foo::bar")
61
+ @instance.write("foo::bar")
62
+ end
63
+ end
64
+
65
+ end
66
+ end
@@ -1,12 +1,12 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  module Dino
4
- describe TxRx do
4
+ describe TxRx::USBSerial do
5
5
  it { should be }
6
6
 
7
7
  describe '#initialize' do
8
8
  it 'should set first_write to false' do
9
- TxRx.new.instance_variable_get(:@first_write).should == true
9
+ TxRx::USBSerial.new.instance_variable_get(:@first_write).should == true
10
10
  end
11
11
  end
12
12
 
@@ -16,10 +16,10 @@ module Dino
16
16
  original_platform = RUBY_PLATFORM
17
17
  RUBY_PLATFORM = "mswin"
18
18
  subject.should_receive(:tty_devices).and_return(["COM1", "COM2", "COM3", "COM4"])
19
- SerialPort.should_receive(:new).with('COM1', TxRx::BAUD).and_return(mock_serial = mock)
20
- SerialPort.should_receive(:new).with('COM2', TxRx::BAUD).and_return(mock)
21
- SerialPort.should_receive(:new).with('COM3', TxRx::BAUD).and_return(mock)
22
- SerialPort.should_receive(:new).with('COM4', TxRx::BAUD).and_return(mock)
19
+ SerialPort.should_receive(:new).with('COM1', TxRx::USBSerial::BAUD).and_return(mock_serial = mock)
20
+ SerialPort.should_receive(:new).with('COM2', TxRx::USBSerial::BAUD).and_return(mock)
21
+ SerialPort.should_receive(:new).with('COM3', TxRx::USBSerial::BAUD).and_return(mock)
22
+ SerialPort.should_receive(:new).with('COM4', TxRx::USBSerial::BAUD).and_return(mock)
23
23
 
24
24
  subject.io.should == mock_serial
25
25
  RUBY_PLATFORM = original_platform
@@ -29,9 +29,9 @@ module Dino
29
29
  context "on unix" do
30
30
  it 'should instantiate a new SerialPort for each usb tty device found' do
31
31
  subject.should_receive(:tty_devices).and_return(['/dev/tty1.usb', '/dev/tty1.usb', '/dev/tty.ACM0'])
32
- SerialPort.should_receive(:new).with('/dev/tty1.usb', TxRx::BAUD).and_return(mock_serial = mock)
33
- SerialPort.should_receive(:new).with('/dev/tty1.usb', TxRx::BAUD).and_return(mock)
34
- SerialPort.should_receive(:new).with('/dev/tty.ACM0', TxRx::BAUD).and_return(mock)
32
+ SerialPort.should_receive(:new).with('/dev/tty1.usb', TxRx::USBSerial::BAUD).and_return(mock_serial = mock)
33
+ SerialPort.should_receive(:new).with('/dev/tty1.usb', TxRx::USBSerial::BAUD).and_return(mock)
34
+ SerialPort.should_receive(:new).with('/dev/tty.ACM0', TxRx::USBSerial::BAUD).and_return(mock)
35
35
 
36
36
  subject.io.should == mock_serial
37
37
  end
@@ -53,7 +53,7 @@ module Dino
53
53
 
54
54
  describe '#io=' do
55
55
  it 'should set io to a new serial port with the specified device' do
56
- SerialPort.should_receive(:new).with('/dev/tty1.usb', TxRx::BAUD).and_return(mock_serial = mock)
56
+ SerialPort.should_receive(:new).with('/dev/tty1.usb', TxRx::USBSerial::BAUD).and_return(mock_serial = mock)
57
57
  subject.io = '/dev/tty1.usb'
58
58
  subject.instance_variable_get(:@io).should == mock_serial
59
59
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dino
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.10.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-20 00:00:00.000000000 Z
12
+ date: 2013-01-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: serialport
@@ -54,6 +54,7 @@ files:
54
54
  - examples/servo.rb
55
55
  - examples/stepper/stepper.png
56
56
  - examples/stepper/stepper.rb
57
+ - examples/telnet.rb
57
58
  - lib/dino.rb
58
59
  - lib/dino/board.rb
59
60
  - lib/dino/board_not_found.rb
@@ -67,6 +68,8 @@ files:
67
68
  - lib/dino/components/servo.rb
68
69
  - lib/dino/components/stepper.rb
69
70
  - lib/dino/tx_rx.rb
71
+ - lib/dino/tx_rx/telnet.rb
72
+ - lib/dino/tx_rx/usb_serial.rb
70
73
  - lib/dino/version.rb
71
74
  - spec/lib/board_not_found_spec.rb
72
75
  - spec/lib/board_spec.rb
@@ -77,7 +80,8 @@ files:
77
80
  - spec/lib/components/sensor_spec.rb
78
81
  - spec/lib/components/servo_spec.rb
79
82
  - spec/lib/components/stepper_spec.rb
80
- - spec/lib/tx_rx_spec.rb
83
+ - spec/lib/tx_rx/telnet_spec.rb
84
+ - spec/lib/tx_rx/usb_serial_spec.rb
81
85
  - spec/spec_helper.rb
82
86
  - src/du.ino
83
87
  homepage: https://github.com/austinbv/dino
@@ -114,5 +118,6 @@ test_files:
114
118
  - spec/lib/components/sensor_spec.rb
115
119
  - spec/lib/components/servo_spec.rb
116
120
  - spec/lib/components/stepper_spec.rb
117
- - spec/lib/tx_rx_spec.rb
121
+ - spec/lib/tx_rx/telnet_spec.rb
122
+ - spec/lib/tx_rx/usb_serial_spec.rb
118
123
  - spec/spec_helper.rb