class SpheroClient

Constants

COLOURS
COMMS_RETRY

Public Class Methods

new(bluetooth_address, debugval=false) click to toggle source
# 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

Public Instance Methods

close() click to toggle source
# File lib/rubysphero.rb, line 423
def close
        @connection.close
end
collision_detection(status=true) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# File lib/rubysphero.rb, line 374
def forget_a_request(request)
        @queued_requests.delete request
end
get_sequence() click to toggle source
# 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 ) click to toggle source
# 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_sphero() click to toggle source
# 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) click to toggle source
# 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
orientation() click to toggle source
# 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
ping() click to toggle source
# 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) click to toggle source
# File lib/rubysphero.rb, line 370
def queue_a_request(request)
        @queued_requests.push request
end
queued_requests() click to toggle source
# File lib/rubysphero.rb, line 366
def queued_requests
        return @queued_requests
end
read_data() click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# File lib/rubysphero.rb, line 177
def send_data(data)
        @connection.write data
end
set_back_led_output(brightness) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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