sphero_pwn 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/bin/sphero_diagnostics.rb +71 -0
  4. data/bin/sphero_map_flash.rb +82 -0
  5. data/bin/sphero_save_flash_block.rb +47 -0
  6. data/bin/sphero_set_flag.rb +38 -0
  7. data/bin/sphero_soft_reboot.rb +33 -0
  8. data/bin/sphero_toggle_user_hack.rb +36 -0
  9. data/lib/sphero_pwn.rb +24 -14
  10. data/lib/sphero_pwn/asyncs/flash_block.rb +26 -0
  11. data/lib/sphero_pwn/channel.rb +72 -29
  12. data/lib/sphero_pwn/commands/boot_main_app.rb +17 -0
  13. data/lib/sphero_pwn/commands/enter_bootloader.rb +15 -0
  14. data/lib/sphero_pwn/commands/get_device_mode.rb +35 -0
  15. data/lib/sphero_pwn/commands/get_flash_block.rb +34 -0
  16. data/lib/sphero_pwn/commands/get_permanent_flags.rb +44 -0
  17. data/lib/sphero_pwn/commands/get_versions.rb +12 -10
  18. data/lib/sphero_pwn/commands/is_page_blank.rb +36 -0
  19. data/lib/sphero_pwn/commands/l1_diagnostics.rb +0 -1
  20. data/lib/sphero_pwn/commands/l2_diagnostics.rb +50 -0
  21. data/lib/sphero_pwn/commands/set_device_mode.rb +25 -0
  22. data/lib/sphero_pwn/commands/set_permanent_flags.rb +29 -0
  23. data/lib/sphero_pwn/session.rb +12 -4
  24. data/sphero_pwn.gemspec +130 -0
  25. data/test/command_test.rb +10 -0
  26. data/test/commands/boot_main_app_test.rb +11 -0
  27. data/test/commands/enter_bootloader_test.rb +33 -0
  28. data/test/commands/get_device_mode_test.rb +40 -0
  29. data/test/commands/get_flash_block_test.rb +101 -0
  30. data/test/commands/get_permanent_flags_test.rb +48 -0
  31. data/test/commands/get_versions_test.rb +10 -1
  32. data/test/commands/is_page_blank_test.rb +65 -0
  33. data/test/commands/l2_diagnostics_test.rb +58 -0
  34. data/test/commands/set_device_mode_test.rb +56 -0
  35. data/test/commands/set_permanent_flags_test.rb +55 -0
  36. data/test/data/enter_bootloader.txt +4 -0
  37. data/test/data/get_device_mode.txt +2 -0
  38. data/test/data/get_factory_config.txt +2 -0
  39. data/test/data/get_permanent_flags.txt +2 -0
  40. data/test/data/get_soul.txt +2 -0
  41. data/test/data/get_version.txt +2 -2
  42. data/test/data/is_page_blank.txt +6 -0
  43. data/test/data/l2_diagnostics.txt +8 -0
  44. data/test/data/ping.txt +2 -2
  45. data/test/data/set_device_mode.txt +12 -0
  46. data/test/data/set_permanent_flags.txt +8 -0
  47. metadata +44 -3
@@ -10,6 +10,16 @@ describe SpheroPwn::Command do
10
10
  assert_equal Encoding::BINARY, bytes.encoding
11
11
  end
12
12
 
13
+ it 'stringifies a command with data correctly' do
14
+ set_device_mode = SpheroPwn::Command.new 0x02, 0x42, [0x00]
15
+ sequence = 0x52
16
+
17
+ bytes = set_device_mode.to_bytes sequence
18
+ assert_equal [0xFF, 0xFF, 0x02, 0x42, 0x52, 0x02, 0x00, 0x67],
19
+ bytes.unpack('C*')
20
+ assert_equal Encoding::BINARY, bytes.encoding
21
+ end
22
+
13
23
  it 'clears the response bit correctly' do
14
24
  ping = SpheroPwn::Command.new 0x00, 0x01, nil
15
25
  assert_equal true, ping.expects_response?
@@ -0,0 +1,11 @@
1
+ require_relative '../helper.rb'
2
+
3
+ describe SpheroPwn::Commands::BootMainApp do
4
+ it 'stringifies correctly' do
5
+ set_device_mode = SpheroPwn::Commands::BootMainApp.new
6
+ sequence = 0x52
7
+
8
+ assert_equal [0xFF, 0xFF, 0x01, 0x04, 0x52, 0x01, 0xA7],
9
+ set_device_mode.to_bytes(sequence).unpack('C*')
10
+ end
11
+ end
@@ -0,0 +1,33 @@
1
+ require_relative '../helper.rb'
2
+
3
+ describe SpheroPwn::Commands::EnterBootloader do
4
+ it 'stringifies correctly' do
5
+ set_device_mode = SpheroPwn::Commands::EnterBootloader.new
6
+ sequence = 0x52
7
+
8
+ assert_equal [0xFF, 0xFF, 0x00, 0x30, 0x52, 0x01, 0x7C],
9
+ set_device_mode.to_bytes(sequence).unpack('C*')
10
+ end
11
+
12
+ describe 'when sent to the robot' do
13
+ before do
14
+ @session = new_test_session :enter_bootloader
15
+ end
16
+ after do
17
+ @session.send_command SpheroPwn::Commands::BootMainApp.new
18
+ response = @session.recv_until_response
19
+ unless response.code == :ok
20
+ raise RuntimeError, 'Could not boot back into the main application'
21
+ end
22
+
23
+ @session.close
24
+ end
25
+
26
+ it 'gets an ok response' do
27
+ @session.send_command SpheroPwn::Commands::EnterBootloader.new
28
+ response = @session.recv_until_response
29
+ assert_kind_of SpheroPwn::Commands::EnterBootloader::Response, response
30
+ assert_equal :ok, response.code
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,40 @@
1
+ require_relative '../helper.rb'
2
+
3
+ describe SpheroPwn::Commands::GetDeviceMode do
4
+ it 'parses a normal mode response correctly' do
5
+ response = SpheroPwn::Commands::GetDeviceMode::Response.new 0x00, 0x00,
6
+ [0x00]
7
+
8
+ assert_equal :ok, response.code
9
+ assert_equal :normal, response.mode
10
+ end
11
+
12
+ it 'parses a user hack mode response correctly' do
13
+ response = SpheroPwn::Commands::GetDeviceMode::Response.new 0x00, 0x00,
14
+ [0x01]
15
+
16
+ assert_equal :ok, response.code
17
+ assert_equal :user_hack, response.mode
18
+ end
19
+
20
+ it 'does not crash when parsing an error response' do
21
+ response = SpheroPwn::Commands::GetDeviceMode::Response.new 0x05, 0x00,
22
+ [0x00]
23
+
24
+ assert_equal :unsupported, response.code
25
+ assert_equal :error, response.mode
26
+ end
27
+
28
+ describe 'when sent to the robot' do
29
+ before { @session = new_test_session :get_device_mode }
30
+ after { @session.close }
31
+
32
+ it 'receives a response' do
33
+ @session.send_command SpheroPwn::Commands::GetDeviceMode.new
34
+ response = @session.recv_until_response
35
+ assert_kind_of SpheroPwn::Commands::GetDeviceMode::Response, response
36
+
37
+ assert_equal :ok, response.code
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,101 @@
1
+ require_relative '../helper.rb'
2
+
3
+ describe SpheroPwn::Commands::GetFlashBlock do
4
+ it 'stringifies get soul correctly' do
5
+ get_block = SpheroPwn::Commands::GetFlashBlock.new :soul
6
+ sequence = 0x52
7
+
8
+ bytes = get_block.to_bytes sequence
9
+ assert_equal [0xFF, 0xFF, 0x02, 0x46, 0x52, 0x01, 0x64], bytes.unpack('C*')
10
+ assert_equal Encoding::BINARY, bytes.encoding
11
+ end
12
+
13
+ it 'stringifies get factory config correctly' do
14
+ get_block = SpheroPwn::Commands::GetFlashBlock.new :factory_config
15
+ sequence = 0x52
16
+
17
+ bytes = get_block.to_bytes sequence
18
+ assert_equal [0xFF, 0xFF, 0x02, 0x40, 0x52, 0x02, 0x00, 0x69],
19
+ bytes.unpack('C*')
20
+ assert_equal Encoding::BINARY, bytes.encoding
21
+ end
22
+
23
+ it 'stringifies get user config correctly' do
24
+ get_block = SpheroPwn::Commands::GetFlashBlock.new :user_config
25
+ sequence = 0x52
26
+
27
+ bytes = get_block.to_bytes sequence
28
+ assert_equal [0xFF, 0xFF, 0x02, 0x40, 0x52, 0x02, 0x01, 0x68],
29
+ bytes.unpack('C*')
30
+ assert_equal Encoding::BINARY, bytes.encoding
31
+ end
32
+
33
+ it 'stringifies a custom block number correctly' do
34
+ get_block = SpheroPwn::Commands::GetFlashBlock.new :block_01_42_ff
35
+ sequence = 0x52
36
+
37
+ bytes = get_block.to_bytes sequence
38
+ assert_equal [0xFF, 0xFF, 0x02, 0x40, 0x52, 0x04, 0x01, 0x42, 0xff, 0x25],
39
+ bytes.unpack('C*')
40
+ assert_equal Encoding::BINARY, bytes.encoding
41
+ end
42
+
43
+ describe 'when get soul is sent to the robot' do
44
+ before { @session = new_test_session :get_soul }
45
+ after { @session.close }
46
+
47
+ it 'receives a response and an async result' do
48
+ @session.send_command SpheroPwn::Commands::GetFlashBlock.new :soul
49
+
50
+ response = nil
51
+ async = nil
52
+ while response.nil? || async.nil?
53
+ message = @session.recv_message
54
+ if message.nil?
55
+ sleep 0.05
56
+ next
57
+ end
58
+
59
+ if message.kind_of? SpheroPwn::Response
60
+ response = message
61
+ assert_kind_of SpheroPwn::Commands::GetFlashBlock::Response, response
62
+ assert_equal :ok, response.code
63
+ else
64
+ async = message
65
+ assert_kind_of SpheroPwn::Asyncs::FlashBlock::Soul, async
66
+ assert_equal 0x400, async.data_bytes.length
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ describe 'when get factory config is sent to the robot' do
73
+ before { @session = new_test_session :get_factory_config }
74
+ after { @session.close }
75
+
76
+ it 'receives a response and an async result' do
77
+ @session.send_command(
78
+ SpheroPwn::Commands::GetFlashBlock.new(:factory_config))
79
+
80
+ response = nil
81
+ async = nil
82
+ while response.nil? || async.nil?
83
+ message = @session.recv_message
84
+ if message.nil?
85
+ sleep 0.05
86
+ next
87
+ end
88
+
89
+ if message.kind_of? SpheroPwn::Response
90
+ response = message
91
+ assert_kind_of SpheroPwn::Commands::GetFlashBlock::Response, response
92
+ assert_equal :ok, response.code
93
+ else
94
+ async = message
95
+ assert_kind_of SpheroPwn::Asyncs::FlashBlock::Config, async
96
+ assert_equal 0x400, async.data_bytes.length
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,48 @@
1
+ require_relative '../helper.rb'
2
+
3
+ describe SpheroPwn::Commands::GetPermanentFlags do
4
+ it 'parses a response correctly' do
5
+ response = SpheroPwn::Commands::GetPermanentFlags::Response.new 0x00, 0x00,
6
+ [0x00, 0x00, 0x01, 0x5A]
7
+
8
+ assert_equal :ok, response.code
9
+ assert_equal false, response.flags[:no_sleep_while_charging]
10
+ assert_equal true, response.flags[:vector_drive]
11
+ assert_equal false, response.flags[:no_leveling_while_charging]
12
+ assert_equal true, response.flags[:tail_led_always_on]
13
+ assert_equal true, response.flags[:motion_timeouts]
14
+ assert_equal false, response.flags[:demo_mode]
15
+ assert_equal true, response.flags[:light_double_tap]
16
+ assert_equal false, response.flags[:heavy_double_tap]
17
+ assert_equal true, response.flags[:gyro_max_async]
18
+ end
19
+
20
+ it 'does not crash when parsing an error response' do
21
+ response = SpheroPwn::Commands::GetPermanentFlags::Response.new 0x05, 0x00,
22
+ []
23
+
24
+ assert_equal :unsupported, response.code
25
+ assert_equal nil, response.flags[:no_sleep_while_charging]
26
+ assert_equal nil, response.flags[:vector_drive]
27
+ assert_equal nil, response.flags[:no_leveling_while_charging]
28
+ assert_equal nil, response.flags[:tail_led_always_on]
29
+ assert_equal nil, response.flags[:motion_timeouts]
30
+ assert_equal nil, response.flags[:demo_mode]
31
+ assert_equal nil, response.flags[:light_double_tap]
32
+ assert_equal nil, response.flags[:heavy_double_tap]
33
+ assert_equal nil, response.flags[:gyro_max_async]
34
+ end
35
+
36
+ describe 'when sent to the robot' do
37
+ before { @session = new_test_session :get_permanent_flags }
38
+ after { @session.close }
39
+
40
+ it 'gets an ok response' do
41
+ @session.send_command SpheroPwn::Commands::GetPermanentFlags.new
42
+ response = @session.recv_until_response
43
+ assert_kind_of SpheroPwn::Commands::GetPermanentFlags::Response, response
44
+ assert_equal :ok, response.code
45
+ end
46
+ end
47
+ end
48
+
@@ -2,9 +2,11 @@ require_relative '../helper.rb'
2
2
 
3
3
  describe SpheroPwn::Commands::GetVersions do
4
4
  it 'parses a v1 response record correctly' do
5
- response = SpheroPwn::Commands::GetVersions::Response.new 0x01, 0x00,
5
+ response = SpheroPwn::Commands::GetVersions::Response.new 0x00, 0x00,
6
6
  [0x02, 0x03, 0x01, 0xaa, 0xbb, 0x51, 0x67, 0x89]
7
7
 
8
+ assert_equal :ok, response.code
9
+
8
10
  assert_equal 3, response.versions[:model]
9
11
  assert_equal 1, response.versions[:hardware]
10
12
  assert_equal({ version: 0xaa, revision: 0xbb },
@@ -14,6 +16,13 @@ describe SpheroPwn::Commands::GetVersions do
14
16
  assert_equal({ major: 8, minor: 9}, response.versions[:macros])
15
17
  end
16
18
 
19
+ it 'does not crash when receiving an error' do
20
+ response = SpheroPwn::Commands::GetVersions::Response.new 0x05, 0x00, []
21
+
22
+ assert_equal :unsupported, response.code
23
+ refute_nil response.versions
24
+ end
25
+
17
26
  describe 'when sent to the robot' do
18
27
  before { @session = new_test_session :get_version }
19
28
  after { @session.close }
@@ -0,0 +1,65 @@
1
+ require_relative '../helper.rb'
2
+
3
+ describe SpheroPwn::Commands::IsPageBlank do
4
+ it 'stringifies correctly' do
5
+ is_page_blank = SpheroPwn::Commands::IsPageBlank.new 0x67
6
+ sequence = 0x52
7
+
8
+ assert_equal [0xFF, 0xFF, 0x01, 0x05, 0x52, 0x02, 0x67, 0x3E],
9
+ is_page_blank.to_bytes(sequence).unpack('C*')
10
+ end
11
+
12
+ it 'parses a yes response correctly' do
13
+ response = SpheroPwn::Commands::IsPageBlank::Response.new 0x00, 0x00,
14
+ [0x01]
15
+
16
+ assert_equal :ok, response.code
17
+ assert_equal true, response.is_blank
18
+ assert_equal true, response.is_blank?
19
+ end
20
+
21
+ it 'parses a no response correctly' do
22
+ response = SpheroPwn::Commands::IsPageBlank::Response.new 0x00, 0x00,
23
+ [0x00]
24
+
25
+ assert_equal :ok, response.code
26
+ assert_equal false, response.is_blank
27
+ assert_equal false, response.is_blank?
28
+ end
29
+
30
+ it 'does not crash when parsing an error response' do
31
+ response = SpheroPwn::Commands::IsPageBlank::Response.new 0x32, 0x00,
32
+ [0x01]
33
+
34
+ assert_equal :bad_page, response.code
35
+ assert_equal nil, response.is_blank
36
+ assert_equal nil, response.is_blank?
37
+ end
38
+
39
+ describe 'when sent to the robot' do
40
+ before do
41
+ @session = new_test_session :is_page_blank
42
+ @session.send_command SpheroPwn::Commands::EnterBootloader.new
43
+ response = @session.recv_until_response
44
+ unless response.code == :ok
45
+ raise RuntimeError, 'Could not jump into bootloader'
46
+ end
47
+ end
48
+ after do
49
+ @session.send_command SpheroPwn::Commands::BootMainApp.new
50
+ response = @session.recv_until_response
51
+ unless response.code == :ok
52
+ raise RuntimeError, 'Could not boot back into the main application'
53
+ end
54
+
55
+ @session.close
56
+ end
57
+
58
+ it 'gets an ok response' do
59
+ @session.send_command SpheroPwn::Commands::IsPageBlank.new(16)
60
+ response = @session.recv_until_response
61
+ assert_kind_of SpheroPwn::Commands::IsPageBlank::Response, response
62
+ assert_equal :ok, response.code
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,58 @@
1
+ require_relative '../helper.rb'
2
+
3
+ describe SpheroPwn::Commands::L2Diagnostics do
4
+ it 'parses a v1 response record correctly' do
5
+ # TODO(pwnall): Find a device tht implements this command.
6
+ end
7
+
8
+ it 'does not crash when receiving an error' do
9
+ response = SpheroPwn::Commands::L2Diagnostics::Response.new 0x05, 0x00, []
10
+
11
+ assert_equal :unsupported, response.code
12
+ refute_nil response.counters
13
+ end
14
+
15
+ describe 'when sent to the robot' do
16
+ before do
17
+ @session = new_test_session :l2_diagnostics
18
+
19
+ @session.send_command SpheroPwn::Commands::GetDeviceMode.new
20
+ response = @session.recv_until_response
21
+ unless response.code == :ok
22
+ raise RuntimeError, 'Could not retrieve initial mode from device'
23
+ end
24
+ @old_mode = response.mode
25
+
26
+ @session.send_command SpheroPwn::Commands::SetDeviceMode.new :user_hack
27
+ response = @session.recv_until_response
28
+ unless response.code == :ok
29
+ raise RuntimeError, 'Could not set user hack mode'
30
+ end
31
+ end
32
+ after do
33
+ @session.send_command SpheroPwn::Commands::SetDeviceMode.new(@old_mode)
34
+ response = @session.recv_until_response
35
+ unless response.code == :ok
36
+ raise RuntimeError,
37
+ "Could not restore initial device mode #{@old_mode}"
38
+ end
39
+
40
+ @session.close
41
+ end
42
+
43
+ it 'receives a response with counters' do
44
+ @session.send_command SpheroPwn::Commands::L2Diagnostics.new
45
+ response = @session.recv_until_response
46
+ assert_kind_of SpheroPwn::Commands::L2Diagnostics::Response, response
47
+
48
+ # TODO(pwnall): Find a device that implements this command so we can
49
+ # test it.
50
+ # assert_equal :ok, response.code
51
+ # assert_operator response.counters[:received_good], :>, 0
52
+ # assert_operator response.counters[:seconds_on], :>, 0
53
+ # refute_nil response.counters[:i2c_failures]
54
+ # refute_nil response.counters[:gyro_adjusts]
55
+ end
56
+ end
57
+ end
58
+
@@ -0,0 +1,56 @@
1
+ require_relative '../helper.rb'
2
+
3
+ describe SpheroPwn::Commands::SetDeviceMode do
4
+ it 'stringifies a normal mode request correctly' do
5
+ set_device_mode = SpheroPwn::Commands::SetDeviceMode.new :normal
6
+ sequence = 0x52
7
+
8
+ assert_equal [0xFF, 0xFF, 0x02, 0x42, 0x52, 0x02, 0x00, 0x67],
9
+ set_device_mode.to_bytes(sequence).unpack('C*')
10
+ end
11
+
12
+ it 'stringifies a user hack mode request correctly' do
13
+ set_device_mode = SpheroPwn::Commands::SetDeviceMode.new :user_hack
14
+ sequence = 0x52
15
+
16
+ assert_equal [0xFF, 0xFF, 0x02, 0x42, 0x52, 0x02, 0x01, 0x66],
17
+ set_device_mode.to_bytes(sequence).unpack('C*')
18
+ end
19
+
20
+ describe 'when sent to the robot' do
21
+ before do
22
+ @session = new_test_session :set_device_mode
23
+
24
+ @session.send_command SpheroPwn::Commands::GetDeviceMode.new
25
+ response = @session.recv_until_response
26
+ unless response.code == :ok
27
+ raise RuntimeError, 'Could not retrieve initial mode from device'
28
+ end
29
+ @old_mode = response.mode
30
+ end
31
+ after do
32
+ @session.send_command SpheroPwn::Commands::SetDeviceMode.new(@old_mode)
33
+ response = @session.recv_until_response
34
+ unless response.code == :ok
35
+ raise RuntimeError,
36
+ "Could not restore initial device mode #{@old_mode}"
37
+ end
38
+
39
+ @session.close
40
+ end
41
+
42
+ it 'impacts the result of the get device mode command' do
43
+ [:normal, :user_hack].each do |mode|
44
+ @session.send_command SpheroPwn::Commands::SetDeviceMode.new(mode)
45
+ response = @session.recv_until_response
46
+ assert_kind_of SpheroPwn::Commands::SetDeviceMode::Response, response
47
+ assert_equal :ok, response.code
48
+
49
+ @session.send_command SpheroPwn::Commands::GetDeviceMode.new
50
+ response = @session.recv_until_response
51
+ assert_equal :ok, response.code
52
+ assert_equal mode, response.mode
53
+ end
54
+ end
55
+ end
56
+ end