sphero 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'autotest/restart'
4
+
5
+ Autotest.add_hook :initialize do |at|
6
+ at.testlib = 'minitest/autorun'
7
+ at.find_directories = ARGV unless ARGV.empty?
8
+ end
File without changes
@@ -0,0 +1,6 @@
1
+ === 1.0.0 / 2012-07-20
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
@@ -0,0 +1,10 @@
1
+ .autotest
2
+ CHANGELOG.rdoc
3
+ Manifest.txt
4
+ README.markdown
5
+ Rakefile
6
+ bin/sphero
7
+ lib/sphero.rb
8
+ lib/sphero/request.rb
9
+ lib/sphero/response.rb
10
+ test/test_sphero.rb
@@ -0,0 +1,66 @@
1
+ # sphero
2
+
3
+ * http://github.com/tenderlove/sphero
4
+
5
+ ## DESCRIPTION:
6
+
7
+ A ruby gem for controlling your Sphero ball. Sends commands over the TTY
8
+ provided by the bluetooth connection.
9
+
10
+ ## FEATURES/PROBLEMS:
11
+
12
+ * You need a Sphero
13
+
14
+ ## SYNOPSIS:
15
+
16
+ ```ruby
17
+ s = Sphero.new "/dev/tty.Sphero-PRG-RN-SPP"
18
+ s.ping
19
+
20
+ # Roll 0 degrees, speed 125
21
+ s.roll(125, 0)
22
+
23
+ # Turn 360 degrees, 30 degrees at a time
24
+ 0.step(360, 30) { |h|
25
+ h = 0 if h == 360
26
+
27
+ # Set the heading to h degrees
28
+ s.heading = h
29
+ sleep 1
30
+ }
31
+ sleep 1
32
+ s.stop
33
+ ```
34
+
35
+ ## REQUIREMENTS:
36
+
37
+ * A Sphero ball connected to your computer
38
+
39
+ ## INSTALL:
40
+
41
+ * gem install sphero
42
+
43
+ ## LICENSE:
44
+
45
+ (The MIT License)
46
+
47
+ Copyright (c) 2012 Aaron Patterson
48
+
49
+ Permission is hereby granted, free of charge, to any person obtaining
50
+ a copy of this software and associated documentation files (the
51
+ 'Software'), to deal in the Software without restriction, including
52
+ without limitation the rights to use, copy, modify, merge, publish,
53
+ distribute, sublicense, and/or sell copies of the Software, and to
54
+ permit persons to whom the Software is furnished to do so, subject to
55
+ the following conditions:
56
+
57
+ The above copyright notice and this permission notice shall be
58
+ included in all copies or substantial portions of the Software.
59
+
60
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
61
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
62
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
63
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
64
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
65
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
66
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,23 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+
6
+ Hoe.plugins.delete :rubyforge
7
+ Hoe.plugin :minitest
8
+ Hoe.plugin :gemspec # `gem install hoe-gemspec`
9
+ Hoe.plugin :git # `gem install hoe-git`
10
+
11
+ Hoe.spec 'sphero' do
12
+ developer('Aaron Patterson', 'aaron@tenderlovemaking.com')
13
+ self.readme_file = 'README.markdown'
14
+ self.history_file = 'CHANGELOG.rdoc'
15
+ self.extra_rdoc_files = FileList['*.{rdoc,markdown}']
16
+ self.extra_deps << ['serialport']
17
+
18
+ self.spec_extras = {
19
+ :required_ruby_version => '>= 1.9.3'
20
+ }
21
+ end
22
+
23
+ # vim: syntax=ruby
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ abort "you need to write me"
@@ -0,0 +1,133 @@
1
+ require 'serialport'
2
+ require 'sphero/request'
3
+ require 'sphero/response'
4
+ require 'thread'
5
+
6
+ class Sphero
7
+ VERSION = '1.0.0'
8
+
9
+ def initialize dev
10
+ @sp = SerialPort.new dev, 115200, 8, 1, SerialPort::NONE
11
+ @dev = 0x00
12
+ @seq = 0x00
13
+ @lock = Mutex.new
14
+ end
15
+
16
+ def ping
17
+ write Request::Ping.new(@seq)
18
+ end
19
+
20
+ def version
21
+ write Request::GetVersioning.new(@seq)
22
+ end
23
+
24
+ def bluetooth_info
25
+ write Request::GetBluetoothInfo.new(@seq)
26
+ end
27
+
28
+ def auto_reconnect= time_s
29
+ write Request::SetAutoReconnect.new(@seq, time_s)
30
+ end
31
+
32
+ def auto_reconnect
33
+ write(Request::GetAutoReconnect.new(@seq)).time
34
+ end
35
+
36
+ def disable_auto_reconnect
37
+ write Request::SetAutoReconnect.new(@seq, 0, 0x00)
38
+ end
39
+
40
+ def power_state
41
+ write Request::GetPowerState.new(@seq)
42
+ end
43
+
44
+ def sleep wakeup = 0, macro = 0
45
+ write Request::Sleep.new(@seq, wakeup, macro)
46
+ end
47
+
48
+ def roll speed, heading, state = true
49
+ write Request::Roll.new(@seq, speed, heading, state ? 0x01 : 0x00)
50
+ end
51
+
52
+ def stop
53
+ roll 0, 0
54
+ end
55
+
56
+ def heading= h
57
+ write Request::Heading.new(@seq, h)
58
+ end
59
+
60
+ def rgb r, g, b, persistant = false
61
+ write Request::SetRGB.new(@seq, r, g, b, persistant ? 0x01 : 0x00)
62
+ end
63
+
64
+ # This retrieves the "user LED color" which is stored in the config block
65
+ # (which may or may not be actively driven to the RGB LED).
66
+ def user_led
67
+ write Request::GetRGB.new(@seq)
68
+ end
69
+
70
+ # Brightness 0x00 - 0xFF
71
+ def back_led_output= h
72
+ write Request::SetBackLEDOutput.new(@seq, h)
73
+ end
74
+
75
+ # Rotation Rate 0x00 - 0xFF
76
+ def rotation_rate= h
77
+ write Request::SetRotationRate.new(@seq, h)
78
+ end
79
+
80
+ private
81
+
82
+ def write packet
83
+ header = nil
84
+ body = nil
85
+
86
+ @lock.synchronize do
87
+ @sp.write packet.to_str
88
+ @seq += 1
89
+
90
+ header = @sp.read(5).unpack 'C5'
91
+ body = @sp.read header.last
92
+ end
93
+
94
+ response = packet.response header, body
95
+
96
+ if response.success?
97
+ response
98
+ else
99
+ raise response
100
+ end
101
+ end
102
+ end
103
+
104
+ if $0 == __FILE__
105
+ begin
106
+ s = Sphero.new "/dev/tty.Sphero-BRR-RN-SPP"
107
+ rescue Errno::EBUSY
108
+ retry
109
+ end
110
+
111
+ 10.times {
112
+ p s.ping
113
+ }
114
+
115
+ trap(:INT) {
116
+ s.stop
117
+ }
118
+
119
+ s.roll 100, 0
120
+
121
+ loop do
122
+ [0, 180].each do |dir|
123
+ s.heading = dir
124
+ end
125
+ end
126
+
127
+ #36.times {
128
+ # i = 10
129
+ # p :step => i
130
+ # s.heading = i
131
+ # sleep 0.5
132
+ #}
133
+ end
@@ -0,0 +1,175 @@
1
+ class Sphero
2
+ class Request
3
+ SOP1 = 0xFF
4
+ SOP2 = 0xFF
5
+
6
+ def initialize seq, data = []
7
+ @seq = seq
8
+ @data = data
9
+ @did = 0x00
10
+ end
11
+
12
+ def header
13
+ [SOP1, SOP2, @did, @cid, @seq, dlen]
14
+ end
15
+
16
+ # The data to write to the socket
17
+ def to_str
18
+ bytes
19
+ end
20
+
21
+ def response header, body
22
+ Response.new header, body
23
+ end
24
+
25
+ def packet_header
26
+ header.pack 'CCCCCC'
27
+ end
28
+
29
+ def packet_body
30
+ @data.pack 'C*'
31
+ end
32
+
33
+ def checksum
34
+ ~((packet_header + packet_body).unpack('C*').drop(2).reduce(:+) % 256) & 0xFF
35
+ end
36
+
37
+ def bytes
38
+ packet_header + packet_body + checksum.chr
39
+ end
40
+
41
+ def dlen
42
+ packet_body.bytesize + 1
43
+ end
44
+
45
+ class Sphero < Request
46
+ def initialize seq, data = []
47
+ super
48
+ @did = 0x02
49
+ end
50
+ end
51
+
52
+ class Heading < Sphero
53
+ def initialize seq, heading
54
+ super(seq, [heading])
55
+ @cid = 0x01
56
+ end
57
+
58
+ private
59
+ def packet_body
60
+ @data.pack 'n'
61
+ end
62
+ end
63
+
64
+ class SetBackLEDOutput < Sphero
65
+ def initialize seq, brightness
66
+ super(seq, [brightness])
67
+ @cid = 0x21
68
+ end
69
+ end
70
+
71
+ class SetRotationRate < Sphero
72
+ def initialize seq, rate
73
+ super(seq, [rate])
74
+ @cid = 0x03
75
+ end
76
+ end
77
+
78
+ class SetRGB < Sphero
79
+ def initialize seq, r, g, b, persistant
80
+ super(seq, [r, g, b, persistant])
81
+ @cid = 0x20
82
+ end
83
+ end
84
+
85
+ class GetRGB < Sphero
86
+ def initialize seq
87
+ super(seq, [])
88
+ @cid = 0x22
89
+ end
90
+
91
+ def response header, body
92
+ Response::GetRGB.new header, body
93
+ end
94
+ end
95
+
96
+ class Roll < Sphero
97
+ def initialize seq, speed, heading, delay
98
+ super(seq, [speed, heading, delay])
99
+ @cid = 0x30
100
+ end
101
+
102
+ private
103
+ def packet_body
104
+ @data.pack 'CnC'
105
+ end
106
+ end
107
+
108
+ class Ping < Request
109
+ def initialize seq
110
+ super(seq, [])
111
+ @cid = 0x01
112
+ end
113
+ end
114
+
115
+ class GetVersioning < Request
116
+ def initialize seq
117
+ super(seq, [])
118
+ @cid = 0x02
119
+ end
120
+ end
121
+
122
+ class GetBluetoothInfo < Request
123
+ def initialize seq
124
+ super(seq, [])
125
+ @cid = 0x11
126
+ end
127
+
128
+ def response header, body
129
+ Response::GetBluetoothInfo.new header, body
130
+ end
131
+ end
132
+
133
+ class SetAutoReconnect < Request
134
+ def initialize seq, time = 7, enabled = 0x01
135
+ super(seq, [enabled, time])
136
+ @cid = 0x12
137
+ end
138
+ end
139
+
140
+ class GetAutoReconnect < Request
141
+ def initialize seq
142
+ super(seq, [])
143
+ @cid = 0x13
144
+ end
145
+
146
+ def response header, body
147
+ Response::GetAutoReconnect.new header, body
148
+ end
149
+ end
150
+
151
+ class GetPowerState < Request
152
+ def initialize seq
153
+ super(seq, [])
154
+ @cid = 0x20
155
+ end
156
+
157
+ def response header, body
158
+ Response::GetPowerState.new header, body
159
+ end
160
+ end
161
+
162
+ class Sleep < Request
163
+ def initialize seq, wakeup, macro
164
+ super(seq, [wakeup, macro])
165
+ @cid = 0x22
166
+ end
167
+
168
+ private
169
+
170
+ def packet_body
171
+ @data.pack 'nC'
172
+ end
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,88 @@
1
+ class Sphero
2
+ class Response
3
+ SOP1 = 0
4
+ SOP2 = 1
5
+ MRSP = 2
6
+ SEQ = 3
7
+ DLEN = 4
8
+
9
+ CODE_OK = 0
10
+
11
+ def initialize header, body
12
+ @header = header
13
+ @body = body
14
+ end
15
+
16
+ def empty?
17
+ @header[DLEN] == 1
18
+ end
19
+
20
+ def success?
21
+ @header[MRSP] == CODE_OK
22
+ end
23
+
24
+ def seq
25
+ @header[SEQ]
26
+ end
27
+
28
+ def body
29
+ @body.unpack 'C*'
30
+ end
31
+
32
+ class GetAutoReconnect < Response
33
+ def time
34
+ body[1]
35
+ end
36
+ end
37
+
38
+ class GetPowerState < Response
39
+ # constants for power_state
40
+ CHARGING = 0x01
41
+ OK = 0x02
42
+ LOW = 0x03
43
+ CRITICAL = 0x04
44
+
45
+ def body
46
+ @body.unpack 'CCnnnC'
47
+ end
48
+
49
+ def rec_ver
50
+ body[0]
51
+ end
52
+
53
+ def power_state
54
+ body[1]
55
+ end
56
+
57
+ # Voltage * 100
58
+ def batt_voltage
59
+ body[2]
60
+ end
61
+
62
+ def num_charges
63
+ body[3]
64
+ end
65
+
66
+ # Time since awakened in seconds
67
+ def time_since_charge
68
+ body[4]
69
+ end
70
+ end
71
+
72
+ class GetBluetoothInfo < Response
73
+ def name
74
+ body.take(16).slice_before(0x00).first.pack 'C*'
75
+ end
76
+
77
+ def bta
78
+ body.drop(16).slice_before(0x00).first.pack 'C*'
79
+ end
80
+ end
81
+
82
+ class GetRGB < Response
83
+ def r; body[0]; end
84
+ def g; body[1]; end
85
+ def b; body[2]; end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,14 @@
1
+ require 'minitest/autorun'
2
+ require 'sphero'
3
+
4
+ class TestSphero < MiniTest::Unit::TestCase
5
+ def test_ping_checksum
6
+ ping = Sphero::Request::Ping.new 0
7
+ assert_equal "\xFF\xFF\x00\x01\x00\x01\xFD", ping.to_str
8
+ end
9
+
10
+ def test_sleep_dlen
11
+ sleep = Sphero::Request::Sleep.new 0, 0, 0
12
+ assert_equal 0x04, sleep.dlen
13
+ end
14
+ end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sphero
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Aaron Patterson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: serialport
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
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: minitest
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '3.2'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '3.2'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rdoc
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '3.10'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '3.10'
62
+ - !ruby/object:Gem::Dependency
63
+ name: hoe
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '3.0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '3.0'
78
+ description: ! 'A ruby gem for controlling your Sphero ball. Sends commands over
79
+ the TTY
80
+
81
+ provided by the bluetooth connection.'
82
+ email:
83
+ - aaron@tenderlovemaking.com
84
+ executables:
85
+ - sphero
86
+ extensions: []
87
+ extra_rdoc_files:
88
+ - CHANGELOG.rdoc
89
+ - Manifest.txt
90
+ - README.markdown
91
+ files:
92
+ - .autotest
93
+ - CHANGELOG.rdoc
94
+ - Manifest.txt
95
+ - README.markdown
96
+ - Rakefile
97
+ - bin/sphero
98
+ - lib/sphero.rb
99
+ - lib/sphero/request.rb
100
+ - lib/sphero/response.rb
101
+ - test/test_sphero.rb
102
+ - .gemtest
103
+ homepage: http://github.com/tenderlove/sphero
104
+ licenses: []
105
+ post_install_message:
106
+ rdoc_options:
107
+ - --main
108
+ - README.markdown
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: 1.9.3
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ none: false
119
+ requirements:
120
+ - - ! '>='
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project: sphero
125
+ rubygems_version: 1.8.23
126
+ signing_key:
127
+ specification_version: 3
128
+ summary: A ruby gem for controlling your Sphero ball
129
+ test_files:
130
+ - test/test_sphero.rb