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