sphero_pwn 0.0.0 → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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