From e761e5ada918aa609875bf3299ccf6b7307f7fb6 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 24 Jul 2012 14:53:53 -0700 Subject: [PATCH] adding request objects --- README.markdown | 13 ++---- lib/sphero.rb | 89 +++++++++++++++++------------------------- lib/sphero/request.rb | 85 ++++++++++++++++++++++++++++++++++++++++ lib/sphero/response.rb | 48 +++++++++++++++++++++++ test/test_sphero.rb | 5 ++- 5 files changed, 174 insertions(+), 66 deletions(-) create mode 100644 lib/sphero/request.rb create mode 100644 lib/sphero/response.rb diff --git a/README.markdown b/README.markdown index 192a128..a6d8b64 100644 --- a/README.markdown +++ b/README.markdown @@ -15,18 +15,12 @@ provided by the bluetooth connection. ```ruby s = Sphero.new "/dev/tty.Sphero-PRG-RN-SPP" -p s.ping +s.ping # Roll 0 degrees, speed 125 -p s.roll(125, 0) +s.roll(125, 0) -trap(:INT) { - s.stop # Stop the ball - exit! -} - -sleep 1 -loop do +# Turn 360 degrees, 30 degrees at a time 0.step(360, 30) { |h| h = 0 if h == 360 @@ -34,7 +28,6 @@ loop do s.heading = h sleep 1 } -end sleep 1 s.stop ``` diff --git a/lib/sphero.rb b/lib/sphero.rb index f750375..c66fc27 100644 --- a/lib/sphero.rb +++ b/lib/sphero.rb @@ -1,37 +1,10 @@ require 'serialport' +require 'sphero/request' +require 'sphero/response' class Sphero VERSION = '1.0.0' - class Response - SOP1 = 0 - SOP2 = 1 - MRSP = 2 - SEQ = 3 - DLEN = 4 - - CODE_OK = 0 - - attr_reader :body - - def initialize header, body - @header = header - @body = body - end - - def empty? - @header[DLEN] == 1 - end - - def success? - @header[MRSP] == CODE_OK - end - - def seq - @header[SEQ] - end - end - def initialize dev @sp = SerialPort.new dev, 115200, 8, 1, SerialPort::NONE @dev = 0x00 @@ -39,28 +12,27 @@ def initialize dev end def ping - write 0x01 + write_packet Request::Ping.new(@seq) end def version - write 0x02 + write_packet Request::GetVersioning.new(@seq) end def bluetooth_info - resp = write 0x11 - [resp.body.take(15).pack('C*'), resp.body.drop(15).pack('C*')] + write_packet Request::GetBluetoothInfo.new(@seq) end def auto_reconnect= time_s - write 0x12, [0x01, time_s] + write_packet Request::SetAutoReconnect.new(@seq, time_s) end def auto_reconnect - write(0x13).body[1] + write_packet(Request::GetAutoReconnect.new(@seq)).time end def disable_auto_reconnect - write 0x12, [0x00, 0x05] + write_packet Request::SetAutoReconnect.new(@seq, 0, false) end def roll speed, heading, delay = 0x01 @@ -78,6 +50,21 @@ def heading= h private + def write_packet packet + @sp.write packet.to_str + @seq += 1 + + header = @sp.read(5).unpack 'C5' + body = @sp.read header.last + response = packet.response header, body + + if response.success? + response + else + raise response + end + end + def write cmd, data = [], did = @dev data_len = data.length + 1 @@ -103,29 +90,23 @@ def write cmd, data = [], did = @dev if $0 == __FILE__ begin - s = Sphero.new "/dev/tty.Sphero-PRG-RN-SPP" + s = Sphero.new "/dev/tty.Sphero-BRR-RN-SPP" rescue Errno::EBUSY p :wtf retry end - p s.ping - p s.roll(125, 0) - - trap(:INT) { - s.stop - exit! + 10.times { + p s.ping } - sleep 1 - loop do - 0.step(360, 30) { |h| - h = 0 if h == 360 - - s.heading = h - sleep 1 - } - end - sleep 1 - s.stop + obj = s.bluetooth_info + p obj + p obj.name + p obj.bta + p s.auto_reconnect + s.auto_reconnect = 3 + p s.auto_reconnect + s.auto_reconnect = 0 + p s.auto_reconnect end diff --git a/lib/sphero/request.rb b/lib/sphero/request.rb new file mode 100644 index 0000000..189d9ea --- /dev/null +++ b/lib/sphero/request.rb @@ -0,0 +1,85 @@ +class Sphero + class Request + SOP1 = 0xFF + SOP2 = 0xFF + + def initialize seq, data = [] + @seq = seq + @data = data + @did = 0x00 + @dlen = @data.length + 1 + @format = 'C*' + end + + def data_bytes + [SOP1, SOP2, @did, @cid, @seq, @dlen] + @data + end + + def checksum + ~(data_bytes.drop(2).reduce(:+) % 256) & 0xFF + end + + def bytes + data_bytes << checksum + end + + # The data to write to the socket + def to_str + bytes.pack @format + end + + def response header, body + Response.new header, body + end + + class Ping < Request + def initialize seq + super(seq, []) + @cid = 0x01 + end + end + + class GetVersioning < Request + def initialize seq + super(seq, []) + @cid = 0x02 + end + end + + class GetBluetoothInfo < Request + def initialize seq + super(seq, []) + @cid = 0x11 + end + + def response header, body + Response::GetBluetoothInfo.new header, body + end + end + + class SetAutoReconnect < Request + def initialize seq, time = 7, enabled = true + super(seq, [enabled ? 0x01 : 0x00, time]) + @cid = 0x12 + end + end + + class GetAutoReconnect < Request + def initialize seq + super(seq, []) + @cid = 0x13 + end + + def response header, body + Response::GetAutoReconnect.new header, body + end + end + + class GetPowerState < Request + def initialize seq + super(seq, []) + @cid = 0x20 + end + end + end +end diff --git a/lib/sphero/response.rb b/lib/sphero/response.rb new file mode 100644 index 0000000..6152b1f --- /dev/null +++ b/lib/sphero/response.rb @@ -0,0 +1,48 @@ +class Sphero + class Response + SOP1 = 0 + SOP2 = 1 + MRSP = 2 + SEQ = 3 + DLEN = 4 + + CODE_OK = 0 + + def initialize header, body + @header = header + @body = body + end + + def empty? + @header[DLEN] == 1 + end + + def success? + @header[MRSP] == CODE_OK + end + + def seq + @header[SEQ] + end + + def body + @body.unpack 'C*' + end + + class GetAutoReconnect < Response + def time + body[1] + end + end + + class GetBluetoothInfo < Response + def name + body.take(16).slice_before(0x00).first.pack 'C*' + end + + def bta + body.drop(16).slice_before(0x00).first.pack 'C*' + end + end + end +end diff --git a/test/test_sphero.rb b/test/test_sphero.rb index 32b266f..7fa07ba 100644 --- a/test/test_sphero.rb +++ b/test/test_sphero.rb @@ -2,7 +2,8 @@ require 'sphero' class TestSphero < MiniTest::Unit::TestCase - def test_sanity - flunk "write tests or I will kneecap you" + def test_ping_checksum + ping = Sphero::Request::Ping.new 1 + assert_equal 1, ping.checksum end end