Class: SpheroClient

Inherits:
SpheroBase show all
Includes:
SpheroUtilities
Defined in:
lib/rubysphero.rb

Constant Summary collapse

COMMS_RETRY =
5
COLOURS =
{ 	:blue 	=> 	[0x00,0x00,0xFF],
:green 	=> 	[0x00,0xFF,0x00],
:red	=>	[0xFF,0x00,0x00],
:orange	=>	[0xFF,0x8C,0x00],
:yellow	=>	[0xFF,0xFF,0x00],
:white	=>	[0xFF,0xFF,0xFF],
:black	=>	[0x00,0x00,0x00],
:pink	=>	[0xFF,0x00,0xFF],
:grey	=>	[0x80,0x80,0x80]}

Instance Attribute Summary

Attributes inherited from SpheroBase

#debug

Instance Method Summary collapse

Methods included from SpheroUtilities

#add_checksum, #do_checksum, #print_format_bytes

Methods inherited from SpheroBase

#logd

Constructor Details

#initialize(bluetooth_address, debugval = false) ⇒ SpheroClient

def



388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
# File 'lib/rubysphero.rb', line 388

def initialize(bluetooth_address, debugval=false)
	@sequence_val=0 
	@responses=Hash.new
	@collision_actions=[]

	@debug=debugval
	
	@queued_requests=[]
	logd("Calling open connnection next. Using: #{bluetooth_address}")
	
	conn = open(bluetooth_address)
	
	@read_thread = Thread.new {
		logd("Listen thread started...")
		listen_to_sphero
		logd("Listen thread ending...")
	} # thread 
	
	return conn

end

Instance Method Details

#closeObject

def



423
424
425
# File 'lib/rubysphero.rb', line 423

def close
	@connection.close
end

#collision_detection(status = true) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/rubysphero.rb', line 75

def collision_detection(status=true)
	logd()
	logd "Building request: Collision detection"
	if status == true
		meth=0x01
	else
		meth=0x00
	end #  else
	
	request=SpheroRequest.new(:synchronous, self.debug)

	request.did=0x02 
	request.cid=0x12 # Collision Detection
	request.seq=get_sequence
	request.dlen=0x07
	
	request.push_data meth
	request.push_data 0x7F # xt
	request.push_data 0x40 # xspd
	request.push_data 0x7F # yt
	request.push_data 0x40 # yspd		
	request.push_data 0x40 # dead		
	
	if send_and_check(request) then
		return true
	else
		return false
	end #  else 
end

#define_event_handling_for(event_type, &actions) ⇒ Object

def



125
126
127
128
129
# File 'lib/rubysphero.rb', line 125

def define_event_handling_for(event_type, &actions)
	if event_type==:collision then
		@collision_actions.push actions
	end # if 
end

#forget_a_request(request) ⇒ Object

def



374
375
376
# File 'lib/rubysphero.rb', line 374

def forget_a_request(request)
	@queued_requests.delete request
end

#get_sequenceObject

def



378
379
380
381
382
383
384
385
386
# File 'lib/rubysphero.rb', line 378

def get_sequence
	@sequence_val+=1
	if @sequence_val > 255
		@sequence_val=0 
	end # if
	logd("Getting seq: #{@sequence_val}")
	
	return @sequence_val
end

#handle_collision_event(the_event_response) ⇒ Object

def 



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/rubysphero.rb', line 131

def handle_collision_event(the_event_response )
	logd("Handling collision event!")
	Thread.new do
		if @collision_actions != nil then 
			logd "Collision action was NOT nil"
			
			@collision_actions.each do |collision_action_item| 
				collision_action_item.call the_event_response
			end # each
			
		else
			logd "Collision action was nil"
		end # if 
	end # thread 
end

#listen_to_spheroObject

def



181
182
183
184
185
186
187
188
189
190
# File 'lib/rubysphero.rb', line 181

def listen_to_sphero
	while true do
		logd("Listening...")

		response=read_data
		@responses[response.echoed_seq] =response 
		sleep 0 
	end # while 

end

#open(bluetooth_address) ⇒ Object

class



410
411
412
413
414
415
416
417
418
419
420
421
# File 'lib/rubysphero.rb', line 410

def open(bluetooth_address)
	begin
		logd("About to open Connection")
		@connection   = Serial.new bluetooth_address, BAUD_RATE ,8
		logd("Connection:#{@connection.to_s}")
	rescue RubySerial::Exception
		logd("Connection failed, about to retry...")
		sleep 1
		open bluetooth_address
	end
	return @connection
end

#orientationObject

def



256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/rubysphero.rb', line 256

def orientation
		
	set_back_led_output(255)
	set_colour(:black)
	1.step(720,5) do | heading | 	
		roll(heading , 0)
		
		inputted_text=gets.chomp
		
		if inputted_text =="" then
			# spin
		elsif inputted_text==" "			
			set_back_led_output(0)
			set_heading(heading)
			set_colour(:white)
			return true
		else 
			sleep 1	
		end # if 
	end # upto 	
	return false
end

#pingObject



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/rubysphero.rb', line 107

def ping
	logd()
	logd "Building request: ping"
	request=SpheroRequest.new(:synchronous, self.debug)

	request.did=0x00 
	request.cid=0x01 # Ping
	request.seq=get_sequence
	request.dlen=0x01
	
	if send_and_check(request) then
		logd("PING RESPONSE RECEIVED!!!")
		return true
	else
		return false
	end #  else 
end

#queue_a_request(request) ⇒ Object

def



370
371
372
# File 'lib/rubysphero.rb', line 370

def queue_a_request(request)
	@queued_requests.push request
end

#queued_requestsObject

def



366
367
368
# File 'lib/rubysphero.rb', line 366

def queued_requests
	return @queued_requests
end

#read_dataObject

def



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/rubysphero.rb', line 192

def read_data()
	bytes=[]

	logd("Reading...")
	
	while @connection !=nil do  
		byte_maybe=@connection.getbyte

		if byte_maybe
		
			bytes.push byte_maybe
			
			logd("Received a byte: #{byte_maybe}")
	
			# Check response is long enough to bother with.
			if bytes.length >= MIN_LENGTH_OF_PACKET then
			
				if (bytes[0] == 0xFF) && (bytes[1] == 0xFE)
				
					logd("First 2 bytes indicate it is an Asyschronous Packet")
				
				elsif (bytes[0] == 0xFF) && (bytes[1] == 0xFF)
				
					logd("First 2 bytes indicate it is a Syschronous Packet")			
		
				else
				
					logd("Odd response starts with: #{bytes}, will try removing first byte.")		
					bytes.shift
				
				end # else 
	
				response = SpheroResponse.new(bytes.dup, self.debug)

				if response.valid
					
					# Handle Asynchronous Collision detection responses.
					if (response.synchronicity? == :asynchronous) && (bytes[2] == 0x07) then
						handle_collision_event(response )
					end # else
					
					return response
					
				else
				
					logd("Response not valid yet, keep reading.")
				
				end # else  

				
			end # if bytes > length					
			
		else
			# No Bytes to read
			sleep 0
		end # else 
		
	end # while conn not nil
	
	logd("Connection must have nbeen lost")
	
	return false
end

#roll(heading_raw = 0, speed = 0xFF) ⇒ Object

def



343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
# File 'lib/rubysphero.rb', line 343

def roll(heading_raw=0, speed=0xFF)
	logd()
	logd( "Building request: roll")

	request=SpheroRequest.new(:synchronous, self.debug)
	heading = heading_raw%359
	logd( "Heading: #{heading}")

	request.did=0x02 
	request.cid=0x30 # Roll
	request.seq=get_sequence
	request.dlen=0x05

	state=0x01
	
	request.push_data speed
	request.push_data(heading , :a16bit)
	request.push_data state
	
	return send_and_check(request)	

end

#send_and_check(request) ⇒ Object

 



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/rubysphero.rb', line 147

def send_and_check(request)
	queue_a_request(request)

	send_data(request.build_packet)

	responded =nil
	start_time=Time.now.getutc.to_i
	logd("Start time: #{start_time}")
	begin
		
		if @responses.has_key? request.seq
			logd("Response Queue has matching sequence")
			forget_a_request request
			return @responses[request.seq]
		end # if
		
		sleep 0
		
		if Time.now.getutc.to_i > (start_time+RESPONSE_TIMEOUT_SECONDS)
			logd("Timing out waiting for a response.")
			forget_a_request request
			return false
		end # if 

	end while !responded
	
	return response.valid
	
end

#send_data(data) ⇒ Object

data



177
178
179
# File 'lib/rubysphero.rb', line 177

def send_data(data)
	@connection.write data
end

#set_back_led_output(brightness) ⇒ Object



280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
# File 'lib/rubysphero.rb', line 280

def set_back_led_output(brightness)
	logd()
	logd "Building request: set back led output b"
	
	request=SpheroRequest.new(:synchronous, self.debug)

	request.did=0x02 
	request.cid=0x21 
	request.seq=get_sequence
	request.dlen=0x02
	request.push_data brightness 
	
	return send_and_check(request)	

end

#set_colour(chosen_colour) ⇒ Object

def



315
316
317
318
319
# File 'lib/rubysphero.rb', line 315

def set_colour(chosen_colour) 
	logd
	logd("Locating RGB values for: #{chosen_colour}")
	return set_colour_rgb(COLOURS[chosen_colour][0],COLOURS[chosen_colour][1],COLOURS[chosen_colour][2])
end

#set_colour_rgb(red_value, green_value, blue_value) ⇒ Object



322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
# File 'lib/rubysphero.rb', line 322

def set_colour_rgb(red_value,green_value,blue_value)
	logd
	logd "Building request: colour"
	
	request=SpheroRequest.new(:synchronous, self.debug)


	request.did=0x02 
	request.cid=0x20 # Set RGB Output
	request.seq=get_sequence
	request.dlen=0x05
	request.push_data red_value 
	request.push_data green_value
	request.push_data blue_value  
	flag=0x01
	request.push_data flag 
	
	return send_and_check(request)

end

#set_heading(heading_raw) ⇒ Object

def



296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
# File 'lib/rubysphero.rb', line 296

def set_heading(heading_raw) 
	logd
	logd( "Building request: Set Heading")

	request=SpheroRequest.new(:synchronous)
	heading = heading_raw%359
	logd( "Heading: #{heading}")

	request.did=0x02 
	request.cid=0x01
	request.seq=get_sequence
	request.dlen=0x03
	
	request.push_data(heading , :a16bit)
	
	return send_and_check(request)	

end