sphero 1.4.1 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5499fdac118804bb652308ee12b8660d8e08d4bf
4
+ data.tar.gz: 1fd2ef026bcefc25ca15de2b712b4a78a595e2db
5
+ SHA512:
6
+ metadata.gz: e148d39135d1c173e20eca97869e8342e02731a07d3ef4f9b0b928797ec1b675a9b6517e3cf11e90a75fe5ce942879eacaf0b3dbd4e928346694a7e174301e23
7
+ data.tar.gz: 6f24b58cbd89d6c0b3465486ba4051cd7a3917e6ad58cba38377795fedf53379f1db91e1bf83d6d07e9925fafa3c271b4db768394cfaa44586802cb34e925947
@@ -37,3 +37,9 @@
37
37
  * 1 enhancement
38
38
 
39
39
  * Add constants FORWARD, BACKWARD, RIGHT, & LEFT for quick directionality
40
+
41
+ === 1.5.0 / 2014-02-06
42
+
43
+ * Many enhancements and bugfixes
44
+
45
+ * Been too long since our last changelog entry. Many bugfixes and enhancements.
@@ -2,6 +2,8 @@
2
2
 
3
3
  * http://github.com/hybridgroup/sphero
4
4
 
5
+ [![Build Status](https://travis-ci.org/hybridgroup/sphero.png?branch=master)](https://travis-ci.org/hybridgroup/sphero)
6
+
5
7
  ## DESCRIPTION:
6
8
 
7
9
  A ruby gem for controlling your Sphero ball. Sends commands over the TTY
@@ -101,7 +103,7 @@ You may now access the sphero from `/dev/rfcomm0`
101
103
 
102
104
  ## INSTALL:
103
105
 
104
- * gem install hybridgroup-sphero
106
+ * gem install sphero
105
107
 
106
108
  ## LICENSE:
107
109
 
@@ -3,7 +3,7 @@ require 'sphero/response'
3
3
  require 'thread'
4
4
 
5
5
  class Sphero
6
- VERSION = '1.4.1'
6
+ VERSION = '1.5.0'
7
7
 
8
8
  FORWARD = 0
9
9
  RIGHT = 90
@@ -12,7 +12,7 @@ class Sphero
12
12
 
13
13
  DEFAULT_RETRIES = 3
14
14
 
15
- attr_accessor :connection_types, :messages
15
+ attr_accessor :connection_types, :messages, :packets, :response_queue, :responses
16
16
 
17
17
  class << self
18
18
  def start(dev, &block)
@@ -47,9 +47,23 @@ class Sphero
47
47
  @seq = 0x00
48
48
  @lock = Mutex.new
49
49
  @messages = Queue.new
50
+ @packets = Queue.new
51
+ @response_queue = Queue.new
52
+ @responses = []
53
+ Thread.new {
54
+ loop do
55
+ write @packets.pop
56
+ end
57
+ }
58
+ Thread.new {
59
+ loop do
60
+ @responses << @response_queue.pop
61
+ end
62
+ }
50
63
  end
51
64
 
52
65
  def close
66
+ return if @sp.nil? || @sp.closed?
53
67
  begin
54
68
  stop
55
69
  rescue Exception => e
@@ -60,39 +74,53 @@ class Sphero
60
74
  end
61
75
 
62
76
  def ping
63
- write Request::Ping.new(@seq)
77
+ packet = Request::Ping.new(@seq)
78
+ queue_packet packet
79
+ return sync_response packet.seq
64
80
  end
65
81
 
66
82
  def version
67
- write Request::GetVersioning.new(@seq)
83
+ packet = Request::GetVersioning.new(@seq)
84
+ queue_packet packet
85
+ return sync_response packet.seq
68
86
  end
69
87
 
70
88
  def bluetooth_info
71
- write Request::GetBluetoothInfo.new(@seq)
89
+ packet = Request::GetBluetoothInfo.new(@seq)
90
+ queue_packet packet
91
+ return sync_response packet.seq
92
+ end
93
+
94
+ # This retrieves the "user LED color" which is stored in the config block
95
+ # (which may or may not be actively driven to the RGB LED).
96
+ def user_led
97
+ packet = Request::GetRGB.new(@seq)
98
+ queue_packet packet
99
+ return sync_response packet.seq
72
100
  end
73
101
 
74
102
  def auto_reconnect= time_s
75
- write Request::SetAutoReconnect.new(@seq, time_s)
103
+ queue_packet Request::SetAutoReconnect.new(@seq, limit1(time_s) )
76
104
  end
77
105
 
78
106
  def auto_reconnect
79
- write(Request::GetAutoReconnect.new(@seq)).time
107
+ queue_packet(Request::GetAutoReconnect.new(@seq)).time
80
108
  end
81
109
 
82
110
  def disable_auto_reconnect
83
- write Request::SetAutoReconnect.new(@seq, 0, 0x00)
111
+ queue_packet Request::SetAutoReconnect.new(@seq, 0, flag(false) )
84
112
  end
85
113
 
86
114
  def power_state
87
- write Request::GetPowerState.new(@seq)
115
+ queue_packet Request::GetPowerState.new(@seq)
88
116
  end
89
117
 
90
118
  def sphero_sleep wakeup = 0, macro = 0
91
- write Request::Sleep.new(@seq, wakeup, macro)
119
+ queue_packet Request::Sleep.new(@seq, limit2(wakeup), limit1(macro) )
92
120
  end
93
121
 
94
122
  def roll speed, heading, state = true
95
- write Request::Roll.new(@seq, speed, heading, state ? 0x01 : 0x00)
123
+ queue_packet Request::Roll.new(@seq, limit1(speed), degrees(heading), flag(state) )
96
124
  end
97
125
 
98
126
  def stop
@@ -100,7 +128,11 @@ class Sphero
100
128
  end
101
129
 
102
130
  def heading= h
103
- write Request::Heading.new(@seq, h)
131
+ queue_packet Request::Heading.new(@seq, degrees(h) )
132
+ end
133
+
134
+ def stabilization= on
135
+ queue_packet Request::Stabilization.new(@seq, on)
104
136
  end
105
137
 
106
138
  def color colorname, persistant = false
@@ -109,23 +141,18 @@ class Sphero
109
141
  end
110
142
 
111
143
  def rgb r, g, b, persistant = false
112
- write Request::SetRGB.new(@seq, r, g, b, persistant ? 0x01 : 0x00)
144
+ queue_packet Request::SetRGB.new(@seq, limit1(r), limit1(g), limit1(b), flag(persistant) )
113
145
  end
114
146
 
115
- # This retrieves the "user LED color" which is stored in the config block
116
- # (which may or may not be actively driven to the RGB LED).
117
- def user_led
118
- write Request::GetRGB.new(@seq)
119
- end
120
147
 
121
148
  # Brightness 0x00 - 0xFF
122
149
  def back_led_output= h
123
- write Request::SetBackLEDOutput.new(@seq, h)
150
+ queue_packet Request::SetBackLEDOutput.new(@seq, limit1(h) )
124
151
  end
125
152
 
126
153
  # Rotation Rate 0x00 - 0xFF
127
154
  def rotation_rate= h
128
- write Request::SetRotationRate.new(@seq, h)
155
+ queue_packet Request::SetRotationRate.new(@seq, limit1(h))
129
156
  end
130
157
 
131
158
  # just a nicer alias for Ruby's own sleep
@@ -137,21 +164,82 @@ class Sphero
137
164
 
138
165
  # configure power notification messages
139
166
  def set_power_notification enable=true
140
- write Request::SetPowerNotification.new(@seq, enable ? 0x01 : 0x00)
167
+ queue_packet Request::SetPowerNotification.new(@seq, flag(enable) )
141
168
  end
142
169
 
143
170
  # configure data streaming notification messages
144
171
  def set_data_streaming n, m, mask, pcnt, mask2
145
- write Request::SetDataStreaming.new(@seq, n, m, mask, pcnt, mask2)
172
+ queue_packet Request::SetDataStreaming.new(@seq, limit2(n), limit2(m),
173
+ limit4(mask), limit1(pcnt), limit4(mask2) )
146
174
  end
147
175
 
148
176
  # configure collision detection messages
149
177
  def configure_collision_detection meth, x_t, y_t, x_spd, y_spd, dead
150
- write Request::ConfigureCollisionDetection.new(@seq, meth, x_t, y_t, x_spd, y_spd, dead)
178
+ queue_packet Request::ConfigureCollisionDetection.new(@seq, limit1(meth),
179
+ limit1(x_t), limit1(y_t),
180
+ limit1(x_spd), limit1(y_spd),
181
+ limit1(dead) )
151
182
  end
152
-
183
+
153
184
  private
154
-
185
+
186
+ def sync_response seq
187
+ 100.times do
188
+ @responses.each do |response|
189
+ if response.seq == seq
190
+ @responses.delete(response)
191
+ return response
192
+ end
193
+ end
194
+ sleep 0.001
195
+ end
196
+ return nil
197
+ end
198
+
199
+ def limit(value, max)
200
+ return nil if value.nil?
201
+
202
+ value = value.to_i
203
+ if value < 0
204
+ 0
205
+ elsif value > max
206
+ max
207
+ else
208
+ value
209
+ end
210
+ end
211
+
212
+ def wrap(value, max)
213
+ value && (value.to_i % max)
214
+ end
215
+
216
+ def degrees(value)
217
+ wrap value, 360
218
+ end
219
+
220
+ def limit1(value)
221
+ limit value, 0xFF
222
+ end
223
+
224
+ def limit2(value)
225
+ limit value, 0xFFFF
226
+ end
227
+
228
+ def limit4(value)
229
+ limit value, 0xFFFFFFFF
230
+ end
231
+
232
+ def flag(value)
233
+ case value
234
+ when true
235
+ 0x01
236
+ when false
237
+ 0x00
238
+ else
239
+ value
240
+ end
241
+ end
242
+
155
243
  def is_windows?
156
244
  os = RUBY_PLATFORM.split("-")[1]
157
245
  if (os == 'mswin' or os == 'bccwin' or os == 'mingw' or os == 'mingw32')
@@ -173,25 +261,26 @@ class Sphero
173
261
  puts "Please 'gem install hybridgroup-serialport' for serial port support."
174
262
  end
175
263
 
264
+ def queue_packet packet
265
+ @packets << packet
266
+ end
267
+
176
268
  def write packet
177
269
  header, body = nil
178
270
 
179
- IO.select([], [@sp], [], 20)
180
-
271
+ IO.select([], [@sp], [], 1)
181
272
  @lock.synchronize do
182
273
  @sp.write packet.to_str
183
274
  @seq += 1
184
275
  end
185
-
186
- IO.select([@sp], [], [], 20)
276
+ IO.select([@sp], [], [], 1)
187
277
  header = read_header(true)
188
278
  body = read_body(header.last, true) if header
189
-
190
279
  # pick off asynch packets and store, till we get to the message response
191
280
  while header && Response.async?(header)
192
281
  messages << Response::AsyncResponse.response(header, body)
193
282
 
194
- IO.select([@sp], [], [], 20)
283
+ IO.select([@sp], [], [], 1)
195
284
  header = read_header(true)
196
285
  if header
197
286
  body = read_body(header.last, true)
@@ -203,7 +292,7 @@ class Sphero
203
292
  response = packet.response header, body
204
293
 
205
294
  if response.success?
206
- response
295
+ @response_queue << response
207
296
  else
208
297
  raise "Unable to write to Sphero!"
209
298
  end
@@ -3,7 +3,7 @@ class Sphero
3
3
  SOP1 = 0xFF
4
4
  SOP2 = 0xFF
5
5
 
6
- attr_reader :data
6
+ attr_reader :data, :seq
7
7
 
8
8
  def initialize seq, data = []
9
9
  @seq = seq
@@ -89,7 +89,7 @@ class Sphero
89
89
  end
90
90
  end
91
91
 
92
- class Heading < Request
92
+ class Heading < Sphero
93
93
  def initialize seq, heading
94
94
  super(seq, [heading])
95
95
  @cid = 0x01
@@ -101,6 +101,18 @@ class Sphero
101
101
  end
102
102
  end
103
103
 
104
+ class Stabilization < Sphero
105
+ def initialize seq, on
106
+ super(seq, [on ? 1 : 0])
107
+ @cid = 0x02
108
+ end
109
+
110
+ private
111
+ def packet_body
112
+ @data.pack 'C'
113
+ end
114
+ end
115
+
104
116
  class Sleep < Request
105
117
  def initialize seq, wakeup, macro
106
118
  super(seq, [wakeup, macro])
@@ -114,7 +126,7 @@ class Sphero
114
126
  end
115
127
  end
116
128
 
117
- class SetPowerNotification < Sphero
129
+ class SetPowerNotification < Request
118
130
  def initialize seq, enable
119
131
  super(seq, [enable])
120
132
  @cid = 0x21
@@ -23,49 +23,55 @@ class TestSphero < MiniTest::Unit::TestCase
23
23
  end
24
24
 
25
25
  def test_ping
26
- Sphero::Request::Ping.expects(:new).with(@seq)
27
- @sphero.expects(:write)
26
+ packet = mock 'packet'
27
+ packet.stubs(:seq).returns(@seq)
28
+ Sphero::Request::Ping.expects(:new).with(@seq).returns(packet)
29
+ @sphero.expects(:queue_packet).returns(packet)
28
30
  @sphero.ping
29
31
  end
30
32
 
31
33
  def test_version
32
- Sphero::Request::GetVersioning.expects(:new).with(@seq)
33
- @sphero.expects(:write)
34
+ packet = mock 'packet'
35
+ packet.stubs(:seq).returns(@seq)
36
+ Sphero::Request::GetVersioning.expects(:new).with(@seq).returns(packet)
37
+ @sphero.expects(:queue_packet).returns(packet)
34
38
  @sphero.version
35
39
  end
36
40
 
37
41
  def test_bluetooth_info
38
- Sphero::Request::GetBluetoothInfo.expects(:new).with(@seq)
39
- @sphero.expects(:write)
42
+ packet = mock 'packet'
43
+ packet.stubs(:seq).returns(@seq)
44
+ Sphero::Request::GetBluetoothInfo.expects(:new).with(@seq).returns(packet)
45
+ @sphero.expects(:queue_packet).returns(packet)
40
46
  @sphero.bluetooth_info
41
47
  end
42
48
 
43
49
  def test_auto_reconnect=
44
- @time_s = "10"
50
+ @time_s = 10
45
51
  Sphero::Request::SetAutoReconnect.expects(:new).with(@seq, @time_s)
46
- @sphero.expects(:write)
52
+ @sphero.expects(:queue_packet)
47
53
  @sphero.auto_reconnect = @time_s
48
54
  end
49
55
 
50
56
  def test_auto_reconnect
51
- @time_s = "10"
57
+ @time_s = 10
52
58
  packet = mock 'packet'
53
59
  packet.stubs(:time).returns(@time_s)
54
60
 
55
61
  Sphero::Request::GetAutoReconnect.expects(:new).with(@seq)
56
- @sphero.expects(:write).returns(packet)
62
+ @sphero.expects(:queue_packet).returns(packet)
57
63
  assert_equal @sphero.auto_reconnect, @time_s
58
64
  end
59
65
 
60
66
  def test_disable_auto_reconnect
61
67
  Sphero::Request::SetAutoReconnect.expects(:new).with(@seq, 0, 0x00)
62
- @sphero.expects(:write)
68
+ @sphero.expects(:queue_packet)
63
69
  @sphero.disable_auto_reconnect
64
70
  end
65
71
 
66
72
  def test_power_state
67
73
  Sphero::Request::GetPowerState.expects(:new).with(@seq)
68
- @sphero.expects(:write)
74
+ @sphero.expects(:queue_packet)
69
75
  @sphero.power_state
70
76
  end
71
77
 
@@ -73,19 +79,73 @@ class TestSphero < MiniTest::Unit::TestCase
73
79
  wakeup = 1
74
80
  macro = 2
75
81
  Sphero::Request::Sleep.expects(:new).with(@seq, wakeup, macro)
76
- @sphero.expects(:write)
82
+ @sphero.expects(:queue_packet)
77
83
  @sphero.sphero_sleep wakeup, macro
78
84
  end
79
85
 
86
+ def test_stabilization
87
+ Sphero::Request::Stabilization.expects(:new).with(@seq, true)
88
+ @sphero.expects(:queue_packet)
89
+ @sphero.stabilization = true
90
+ end
91
+
80
92
  def test_roll
81
93
  speed = 1
82
94
  heading = 2
83
95
  state = 1
84
96
  Sphero::Request::Roll.expects(:new).with(@seq, speed, heading, state)
85
- @sphero.expects(:write)
97
+ @sphero.expects(:queue_packet)
86
98
  @sphero.roll speed, heading, true
87
99
  end
88
100
 
101
+ def test_roll_upper_limit
102
+ heading = 2
103
+ state = 1
104
+ Sphero::Request::Roll.expects(:new).with(@seq, 255, heading, state)
105
+ @sphero.expects(:queue_packet)
106
+ @sphero.roll 300, heading, true
107
+ end
108
+
109
+ def test_roll_lower_limit
110
+ heading = 2
111
+ state = 1
112
+ Sphero::Request::Roll.expects(:new).with(@seq, 0, heading, state)
113
+ @sphero.expects(:queue_packet)
114
+ @sphero.roll( -10, heading, true )
115
+ end
116
+
117
+ def test_roll_limit_conversion
118
+ heading = 2
119
+ state = 1
120
+ Sphero::Request::Roll.expects(:new).with(@seq, 123, heading, state)
121
+ @sphero.expects(:queue_packet)
122
+ @sphero.roll 123.4, heading, true
123
+ end
124
+
125
+ def test_roll_upper_wrap
126
+ speed = 3
127
+ state = 1
128
+ Sphero::Request::Roll.expects(:new).with(@seq, speed, 1, state)
129
+ @sphero.expects(:queue_packet)
130
+ @sphero.roll speed, 361, true
131
+ end
132
+
133
+ def test_roll_lower_wrap
134
+ speed = 3
135
+ state = 1
136
+ Sphero::Request::Roll.expects(:new).with(@seq, speed, 359, state)
137
+ @sphero.expects(:queue_packet)
138
+ @sphero.roll( speed, -1, true )
139
+ end
140
+
141
+ def test_roll_limit_wrap
142
+ speed = 3
143
+ state = 1
144
+ Sphero::Request::Roll.expects(:new).with(@seq, speed, 123, state)
145
+ @sphero.expects(:queue_packet)
146
+ @sphero.roll speed, 123.4, true
147
+ end
148
+
89
149
  def test_stop
90
150
  @sphero.expects(:roll).with(0, 0)
91
151
  @sphero.stop
metadata CHANGED
@@ -1,20 +1,32 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sphero
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
5
- prerelease:
4
+ version: 1.5.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Hybrid Group
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-07-25 00:00:00.000000000 Z
11
+ date: 2014-02-06 00:00:00.000000000 Z
13
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '5.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '5.0'
14
27
  - !ruby/object:Gem::Dependency
15
28
  name: rdoc
16
29
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
30
  requirements:
19
31
  - - ~>
20
32
  - !ruby/object:Gem::Version
@@ -22,7 +34,6 @@ dependencies:
22
34
  type: :development
23
35
  prerelease: false
24
36
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
37
  requirements:
27
38
  - - ~>
28
39
  - !ruby/object:Gem::Version
@@ -30,7 +41,6 @@ dependencies:
30
41
  - !ruby/object:Gem::Dependency
31
42
  name: hoe
32
43
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
44
  requirements:
35
45
  - - ~>
36
46
  - !ruby/object:Gem::Version
@@ -38,15 +48,13 @@ dependencies:
38
48
  type: :development
39
49
  prerelease: false
40
50
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
51
  requirements:
43
52
  - - ~>
44
53
  - !ruby/object:Gem::Version
45
54
  version: '3.6'
46
- description: ! 'A ruby gem for controlling your Sphero ball. Sends commands over
47
- the TTY
48
-
49
- provided by the bluetooth connection.'
55
+ description: |-
56
+ A ruby gem for controlling your Sphero ball. Sends commands over the TTY
57
+ provided by the bluetooth connection.
50
58
  email:
51
59
  - sphero@hybridgroup.com
52
60
  executables:
@@ -58,6 +66,7 @@ extra_rdoc_files:
58
66
  - README.markdown
59
67
  files:
60
68
  - .autotest
69
+ - .gemtest
61
70
  - CHANGELOG.rdoc
62
71
  - Manifest.txt
63
72
  - README.markdown
@@ -68,9 +77,9 @@ files:
68
77
  - lib/sphero/response.rb
69
78
  - test/test_sphero.rb
70
79
  - test/test_sphero_request.rb
71
- - .gemtest
72
80
  homepage: http://github.com/hybridgroup/sphero
73
81
  licenses: []
82
+ metadata: {}
74
83
  post_install_message:
75
84
  rdoc_options:
76
85
  - --main
@@ -78,23 +87,21 @@ rdoc_options:
78
87
  require_paths:
79
88
  - lib
80
89
  required_ruby_version: !ruby/object:Gem::Requirement
81
- none: false
82
90
  requirements:
83
- - - ! '>='
91
+ - - '>='
84
92
  - !ruby/object:Gem::Version
85
93
  version: 1.9.2
86
94
  required_rubygems_version: !ruby/object:Gem::Requirement
87
- none: false
88
95
  requirements:
89
- - - ! '>='
96
+ - - '>='
90
97
  - !ruby/object:Gem::Version
91
98
  version: '0'
92
99
  requirements: []
93
100
  rubyforge_project: sphero
94
- rubygems_version: 1.8.24
101
+ rubygems_version: 2.2.1
95
102
  signing_key:
96
- specification_version: 3
103
+ specification_version: 4
97
104
  summary: A ruby gem for controlling your Sphero ball
98
105
  test_files:
99
- - test/test_sphero.rb
100
106
  - test/test_sphero_request.rb
107
+ - test/test_sphero.rb