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.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/bin/sphero_diagnostics.rb +71 -0
- data/bin/sphero_map_flash.rb +82 -0
- data/bin/sphero_save_flash_block.rb +47 -0
- data/bin/sphero_set_flag.rb +38 -0
- data/bin/sphero_soft_reboot.rb +33 -0
- data/bin/sphero_toggle_user_hack.rb +36 -0
- data/lib/sphero_pwn.rb +24 -14
- data/lib/sphero_pwn/asyncs/flash_block.rb +26 -0
- data/lib/sphero_pwn/channel.rb +72 -29
- data/lib/sphero_pwn/commands/boot_main_app.rb +17 -0
- data/lib/sphero_pwn/commands/enter_bootloader.rb +15 -0
- data/lib/sphero_pwn/commands/get_device_mode.rb +35 -0
- data/lib/sphero_pwn/commands/get_flash_block.rb +34 -0
- data/lib/sphero_pwn/commands/get_permanent_flags.rb +44 -0
- data/lib/sphero_pwn/commands/get_versions.rb +12 -10
- data/lib/sphero_pwn/commands/is_page_blank.rb +36 -0
- data/lib/sphero_pwn/commands/l1_diagnostics.rb +0 -1
- data/lib/sphero_pwn/commands/l2_diagnostics.rb +50 -0
- data/lib/sphero_pwn/commands/set_device_mode.rb +25 -0
- data/lib/sphero_pwn/commands/set_permanent_flags.rb +29 -0
- data/lib/sphero_pwn/session.rb +12 -4
- data/sphero_pwn.gemspec +130 -0
- data/test/command_test.rb +10 -0
- data/test/commands/boot_main_app_test.rb +11 -0
- data/test/commands/enter_bootloader_test.rb +33 -0
- data/test/commands/get_device_mode_test.rb +40 -0
- data/test/commands/get_flash_block_test.rb +101 -0
- data/test/commands/get_permanent_flags_test.rb +48 -0
- data/test/commands/get_versions_test.rb +10 -1
- data/test/commands/is_page_blank_test.rb +65 -0
- data/test/commands/l2_diagnostics_test.rb +58 -0
- data/test/commands/set_device_mode_test.rb +56 -0
- data/test/commands/set_permanent_flags_test.rb +55 -0
- data/test/data/enter_bootloader.txt +4 -0
- data/test/data/get_device_mode.txt +2 -0
- data/test/data/get_factory_config.txt +2 -0
- data/test/data/get_permanent_flags.txt +2 -0
- data/test/data/get_soul.txt +2 -0
- data/test/data/get_version.txt +2 -2
- data/test/data/is_page_blank.txt +6 -0
- data/test/data/l2_diagnostics.txt +8 -0
- data/test/data/ping.txt +2 -2
- data/test/data/set_device_mode.txt +12 -0
- data/test/data/set_permanent_flags.txt +8 -0
- metadata +44 -3
@@ -0,0 +1,17 @@
|
|
1
|
+
# Asks the robot's bootloader to boot the main application.
|
2
|
+
#
|
3
|
+
# This command is only valid when the robot is executing the bootloader.
|
4
|
+
class SpheroPwn::Commands::BootMainApp < SpheroPwn::Command
|
5
|
+
def initialize
|
6
|
+
super 0x01, 0x04, nil
|
7
|
+
end
|
8
|
+
|
9
|
+
# @see {SpheroPwn::Command#response_class}
|
10
|
+
def response_class
|
11
|
+
SpheroPwn::Commands::BootMainApp::Response
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# The response to a boot main application command.
|
16
|
+
class SpheroPwn::Commands::BootMainApp::Response < SpheroPwn::Response
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Asks the robot to jump into its bootloader.
|
2
|
+
class SpheroPwn::Commands::EnterBootloader < SpheroPwn::Command
|
3
|
+
def initialize
|
4
|
+
super 0x00, 0x30, nil
|
5
|
+
end
|
6
|
+
|
7
|
+
# @see {SpheroPwn::Command#response_class}
|
8
|
+
def response_class
|
9
|
+
SpheroPwn::Commands::EnterBootloader::Response
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# The response to an enter bootloader command.
|
14
|
+
class SpheroPwn::Commands::EnterBootloader::Response < SpheroPwn::Response
|
15
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Asks the robot about the versions of its software stack components.
|
2
|
+
class SpheroPwn::Commands::GetDeviceMode < SpheroPwn::Command
|
3
|
+
def initialize
|
4
|
+
super 0x02, 0x44, nil
|
5
|
+
end
|
6
|
+
|
7
|
+
# @see {SpheroPwn::Command#response_class}
|
8
|
+
def response_class
|
9
|
+
SpheroPwn::Commands::GetDeviceMode::Response
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# The development mode of the robot.
|
14
|
+
class SpheroPwn::Commands::GetDeviceMode::Response < SpheroPwn::Response
|
15
|
+
# @return {Symbol} the device's mode; can be :normal or :user_hack
|
16
|
+
attr_reader :mode
|
17
|
+
|
18
|
+
# @see {SpheroPwn::Response#initialize}
|
19
|
+
def initialize(code_byte, sequence_byte, data_bytes)
|
20
|
+
super
|
21
|
+
|
22
|
+
if code == :ok
|
23
|
+
@mode = case data_bytes[0]
|
24
|
+
when 0x00
|
25
|
+
:normal
|
26
|
+
when 0x01
|
27
|
+
:user_hack
|
28
|
+
else
|
29
|
+
:unknown
|
30
|
+
end
|
31
|
+
else
|
32
|
+
@mode = :error
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Asks the robot to send a configuration block from the flash memory.
|
2
|
+
class SpheroPwn::Commands::GetFlashBlock < SpheroPwn::Command
|
3
|
+
# @param {Symbol} block_type :soul, :factory_config or :user_config
|
4
|
+
def initialize(block_type)
|
5
|
+
case block_type
|
6
|
+
when :soul
|
7
|
+
command_id = 0x46
|
8
|
+
data_bytes = nil
|
9
|
+
when :factory_config
|
10
|
+
command_id = 0x40
|
11
|
+
data_bytes = [0x00]
|
12
|
+
when :user_config
|
13
|
+
command_id = 0x40
|
14
|
+
data_bytes = [0x01]
|
15
|
+
when /^block_/
|
16
|
+
command_id = 0x40
|
17
|
+
data_bytes = block_type.to_s.split('_')[1..-1].
|
18
|
+
map { |char| char.to_i(16) }
|
19
|
+
else
|
20
|
+
raise ArgumentError, "Unimplemented block type #{block_type.inspect}"
|
21
|
+
end
|
22
|
+
|
23
|
+
super 0x02, command_id, data_bytes
|
24
|
+
end
|
25
|
+
|
26
|
+
# @see {SpheroPwn::Command#response_class}
|
27
|
+
def response_class
|
28
|
+
SpheroPwn::Commands::GetFlashBlock::Response
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# The response to a get flash block command.
|
33
|
+
class SpheroPwn::Commands::GetFlashBlock::Response < SpheroPwn::Response
|
34
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Obtains the robot's configuration flags that persist across power cycles.
|
2
|
+
class SpheroPwn::Commands::GetPermanentFlags < SpheroPwn::Command
|
3
|
+
def initialize
|
4
|
+
super 0x02, 0x36, nil
|
5
|
+
end
|
6
|
+
|
7
|
+
# @see {SpheroPwn::Command#response_class}
|
8
|
+
def response_class
|
9
|
+
SpheroPwn::Commands::GetPermanentFlags::Response
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return {Hash<Number, Symbol>} symbolic values for the returned flags
|
13
|
+
FLAGS = {
|
14
|
+
0x01 => :no_sleep_while_charging,
|
15
|
+
0x02 => :vector_drive,
|
16
|
+
0x04 => :no_leveling_while_charging,
|
17
|
+
0x08 => :tail_led_always_on,
|
18
|
+
0x10 => :motion_timeouts,
|
19
|
+
0x20 => :demo_mode,
|
20
|
+
0x40 => :light_double_tap,
|
21
|
+
0x80 => :heavy_double_tap,
|
22
|
+
0x100 => :gyro_max_async,
|
23
|
+
}.freeze
|
24
|
+
end
|
25
|
+
|
26
|
+
# The robot's configuration flags that persist across power cycles.
|
27
|
+
class SpheroPwn::Commands::GetPermanentFlags::Response < SpheroPwn::Response
|
28
|
+
# @return {Hash<Symbol, Boolean>} maps developer-friendly flag names to
|
29
|
+
# whether the corresponding bits were set in the flags field
|
30
|
+
attr_reader :flags
|
31
|
+
|
32
|
+
# @see {SpheroPwn::Response#initialize}
|
33
|
+
def initialize(code_byte, sequence_byte, data_bytes)
|
34
|
+
super
|
35
|
+
|
36
|
+
@flags = {}
|
37
|
+
if code == :ok
|
38
|
+
flags_number = data_bytes[0, 4].pack('C*').unpack('N').first
|
39
|
+
SpheroPwn::Commands::GetPermanentFlags::FLAGS.each do |mask, name|
|
40
|
+
@flags[name] = (flags_number & mask) != 0
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -21,16 +21,18 @@ class SpheroPwn::Commands::GetVersions::Response < SpheroPwn::Response
|
|
21
21
|
super
|
22
22
|
|
23
23
|
@versions = {}
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
24
|
+
if code == :ok
|
25
|
+
response_version = data_bytes[0]
|
26
|
+
if response_version >= 1
|
27
|
+
@versions.merge! model: data_bytes[1], hardware: data_bytes[2],
|
28
|
+
sphero_app: { version: data_bytes[3], revision: data_bytes[4] },
|
29
|
+
bootloader: self.class.parse_packed_nibble(data_bytes[5]),
|
30
|
+
basic: self.class.parse_packed_nibble(data_bytes[6]),
|
31
|
+
macros: self.class.parse_packed_nibble(data_bytes[7])
|
32
|
+
end
|
33
|
+
if response_version >= 2
|
34
|
+
@versions.merge! api: { major: data_bytes[8], minor: data_bytes[9] }
|
35
|
+
end
|
34
36
|
end
|
35
37
|
end
|
36
38
|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# Asks the robot's bootloader if a flash page is blank.
|
2
|
+
#
|
3
|
+
# This command is only valid when the robot is executing the bootloader.
|
4
|
+
class SpheroPwn::Commands::IsPageBlank < SpheroPwn::Command
|
5
|
+
# @param {Number} page_number the flash page that the command will ask the
|
6
|
+
# robot to look at
|
7
|
+
def initialize(page_number)
|
8
|
+
if page_number > 255
|
9
|
+
raise ArgumentError, "Page number #{page_number} exceeds 255"
|
10
|
+
end
|
11
|
+
super 0x01, 0x05, [page_number]
|
12
|
+
end
|
13
|
+
|
14
|
+
# @see {SpheroPwn::Command#response_class}
|
15
|
+
def response_class
|
16
|
+
SpheroPwn::Commands::IsPageBlank::Response
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# The response to a boot main application command.
|
21
|
+
class SpheroPwn::Commands::IsPageBlank::Response < SpheroPwn::Response
|
22
|
+
# @return {Boolean} true if the flash memory page is blank
|
23
|
+
attr_reader :is_blank
|
24
|
+
alias_method :is_blank?, :is_blank
|
25
|
+
|
26
|
+
# @see {SpheroPwn::Response#initialize}
|
27
|
+
def initialize(code_byte, sequence_byte, data_bytes)
|
28
|
+
super
|
29
|
+
|
30
|
+
if code == :ok
|
31
|
+
@is_blank = data_bytes[0] > 0
|
32
|
+
else
|
33
|
+
@is_blank = nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# Asks the robot for its debugging counters.
|
2
|
+
#
|
3
|
+
# This command only works when the robot is in user hacking mode.
|
4
|
+
class SpheroPwn::Commands::L2Diagnostics < SpheroPwn::Command
|
5
|
+
def initialize
|
6
|
+
super 0x00, 0x41, nil
|
7
|
+
end
|
8
|
+
|
9
|
+
# @see {SpheroPwn::Command#response_class}
|
10
|
+
def response_class
|
11
|
+
SpheroPwn::Commands::L2Diagnostics::Response
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# The response to an L2 diagnostics command.
|
16
|
+
class SpheroPwn::Commands::L2Diagnostics::Response < SpheroPwn::Response
|
17
|
+
# @return {Hash<Symbol, Number>} debugging information counters
|
18
|
+
attr_reader :counters
|
19
|
+
|
20
|
+
# @see {SpheroPwn::Response#initialize}
|
21
|
+
def initialize(code_byte, sequence_byte, data_bytes)
|
22
|
+
super
|
23
|
+
|
24
|
+
@counters = {}
|
25
|
+
if code == :ok
|
26
|
+
data_string = data_bytes.pack('C*')
|
27
|
+
response_version = data_bytes[0x02]
|
28
|
+
if response_version >= 1
|
29
|
+
@counters.merge! received_good: data_string[0x03, 4].unpack('N'),
|
30
|
+
reserved1: data_bytes[0x02],
|
31
|
+
bad_device_id: data_string[0x07, 4].unpack('N'),
|
32
|
+
bad_data_length: data_string[0x0B, 4].unpack('N'),
|
33
|
+
bad_command_id: data_string[0x0F, 4].unpack('N'),
|
34
|
+
bad_checksum: data_string[0x13, 4].unpack('N'),
|
35
|
+
rx_buffer_overrun: data_string[0x17, 4].unpack('N'),
|
36
|
+
transmitted: data_string[0x1B, 4].unpack('N'),
|
37
|
+
tx_buffer_overrun: data_string[0x1F, 4].unpack('N'),
|
38
|
+
last_boot_reason: data_bytes[0x23],
|
39
|
+
boots_by_reason: data_string[0x24, 32].unpack('n*'),
|
40
|
+
reserved2: data_string[0x44, 2].unpack('n'),
|
41
|
+
charge_count: data_string[0x46, 2].unpack('n'),
|
42
|
+
seconds_since_charge: data_string[0x48, 2].unpack('n'),
|
43
|
+
seconds_on: data_string[0x4A, 4].unpack('N'),
|
44
|
+
distance_rolled: data_string[0x4E, 4].unpack('N'),
|
45
|
+
i2c_failures: data_string[0x52, 2].unpack('n'),
|
46
|
+
gyro_adjusts: data_string[0x54, 4].unpack('N')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Asks the robot about the versions of its software stack components.
|
2
|
+
class SpheroPwn::Commands::SetDeviceMode < SpheroPwn::Command
|
3
|
+
def initialize(mode)
|
4
|
+
|
5
|
+
mode_byte = case mode
|
6
|
+
when :normal
|
7
|
+
0x00
|
8
|
+
when :user_hack
|
9
|
+
0x01
|
10
|
+
else
|
11
|
+
raise ArgumentError, "Unimplemented mode #{mode.inspect}"
|
12
|
+
end
|
13
|
+
|
14
|
+
super 0x02, 0x42, [mode_byte]
|
15
|
+
end
|
16
|
+
|
17
|
+
# @see {SpheroPwn::Command#response_class}
|
18
|
+
def response_class
|
19
|
+
SpheroPwn::Commands::SetDeviceMode::Response
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# The versions of a robot's software stack.
|
24
|
+
class SpheroPwn::Commands::SetDeviceMode::Response < SpheroPwn::Response
|
25
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Sets the robot's configuration flags that persist across power cycles.
|
2
|
+
class SpheroPwn::Commands::SetPermanentFlags < SpheroPwn::Command
|
3
|
+
# @param {Hash<Symbol, Boolean>} maps developer-friendly flag names to
|
4
|
+
# whether the corresponding bits will be set in the flags field
|
5
|
+
def initialize(new_flags)
|
6
|
+
flags_number = 0
|
7
|
+
new_flags.each do |name, value|
|
8
|
+
mask = SpheroPwn::Commands::SetPermanentFlags::FLAGS[name]
|
9
|
+
if mask.nil?
|
10
|
+
raise ArgumentError, "Unknown flag #{name.inspect}"
|
11
|
+
end
|
12
|
+
flags_number |= mask if value
|
13
|
+
end
|
14
|
+
|
15
|
+
super 0x02, 0x35, [flags_number].pack('N').unpack('C*')
|
16
|
+
end
|
17
|
+
|
18
|
+
# @see {SpheroPwn::Command#response_class}
|
19
|
+
def response_class
|
20
|
+
SpheroPwn::Commands::SetPermanentFlags::Response
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return {Hash<Symbol, Number>} numbers for the symbolic values
|
24
|
+
FLAGS = SpheroPwn::Commands::GetPermanentFlags::FLAGS.invert.freeze
|
25
|
+
end
|
26
|
+
|
27
|
+
# The robot's configuration flags that persist across power cycles.
|
28
|
+
class SpheroPwn::Commands::SetPermanentFlags::Response < SpheroPwn::Response
|
29
|
+
end
|
data/lib/sphero_pwn/session.rb
CHANGED
@@ -65,14 +65,18 @@ class SpheroPwn::Session
|
|
65
65
|
# @return {Response, Async} the response read from the channel; can be nil if
|
66
66
|
# no message was received or if the checksum verification failed
|
67
67
|
def recv_message
|
68
|
-
|
68
|
+
start_of_packet = @channel.recv_bytes 1
|
69
|
+
return nil if start_of_packet.empty? || start_of_packet.ord != 0xFF
|
69
70
|
|
70
71
|
packet_type = @channel.recv_bytes 1
|
72
|
+
return nil if packet_type.empty?
|
71
73
|
case packet_type.ord
|
72
74
|
when 0xFF
|
73
75
|
read_response
|
74
76
|
when 0xFE
|
75
77
|
read_async_message
|
78
|
+
else
|
79
|
+
nil
|
76
80
|
end
|
77
81
|
end
|
78
82
|
|
@@ -103,12 +107,14 @@ class SpheroPwn::Session
|
|
103
107
|
def read_response
|
104
108
|
header_bytes = @channel.recv_bytes(3).unpack('C*')
|
105
109
|
response_code, sequence, data_length = *header_bytes
|
110
|
+
return nil unless data_length
|
106
111
|
|
107
112
|
# It may seem that it'd be better to look up the sequence number and bail
|
108
113
|
# early if we don't find it. However, in order to avoid misleading error
|
109
114
|
# messages, we don't want to touch anything in the message until we know
|
110
115
|
# that the checksum is valid.
|
111
|
-
|
116
|
+
return nil unless data = @channel.recv_bytes(data_length)
|
117
|
+
data_bytes = data.unpack 'C*'
|
112
118
|
checksum = data_bytes.pop
|
113
119
|
unless self.class.valid_checksum?(header_bytes, data_bytes, checksum)
|
114
120
|
return nil
|
@@ -130,13 +136,15 @@ class SpheroPwn::Session
|
|
130
136
|
def read_async_message
|
131
137
|
header_bytes = @channel.recv_bytes(3).unpack('C*')
|
132
138
|
class_id, length_msb, length_lsb = *header_bytes
|
133
|
-
|
139
|
+
return nil unless length_msb && length_lsb
|
134
140
|
|
135
141
|
# It may seem that it'd be better to look up the sequence number and bail
|
136
142
|
# early if we don't find it. However, in order to avoid misleading error
|
137
143
|
# messages, we don't want to touch anything in the message until we know
|
138
144
|
# that the checksum is valid.
|
139
|
-
|
145
|
+
data_length = (length_msb << 8) | length_lsb
|
146
|
+
return nil unless data = @channel.recv_bytes(data_length)
|
147
|
+
data_bytes = data.unpack 'C*'
|
140
148
|
checksum = data_bytes.pop
|
141
149
|
unless self.class.valid_checksum?(header_bytes, data_bytes, checksum)
|
142
150
|
return nil
|
data/sphero_pwn.gemspec
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
# stub: sphero_pwn 0.0.1 ruby lib
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = "sphero_pwn"
|
9
|
+
s.version = "0.0.1"
|
10
|
+
|
11
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
|
+
s.require_paths = ["lib"]
|
13
|
+
s.authors = ["Victor Costan"]
|
14
|
+
s.date = "2015-12-15"
|
15
|
+
s.description = "This library is currently focused on reverse-engineering\n the undocumented parts of Sphero"
|
16
|
+
s.email = "victor@costan.us"
|
17
|
+
s.executables = ["sphero_diagnostics.rb", "sphero_map_flash.rb", "sphero_save_flash_block.rb", "sphero_set_flag.rb", "sphero_soft_reboot.rb", "sphero_toggle_user_hack.rb"]
|
18
|
+
s.extra_rdoc_files = [
|
19
|
+
"LICENSE.txt",
|
20
|
+
"README.markdown"
|
21
|
+
]
|
22
|
+
s.files = [
|
23
|
+
".document",
|
24
|
+
".travis.yml",
|
25
|
+
"Gemfile",
|
26
|
+
"Gemfile.lock",
|
27
|
+
"LICENSE.txt",
|
28
|
+
"README.markdown",
|
29
|
+
"Rakefile",
|
30
|
+
"VERSION",
|
31
|
+
"bin/sphero_diagnostics.rb",
|
32
|
+
"bin/sphero_map_flash.rb",
|
33
|
+
"bin/sphero_save_flash_block.rb",
|
34
|
+
"bin/sphero_set_flag.rb",
|
35
|
+
"bin/sphero_soft_reboot.rb",
|
36
|
+
"bin/sphero_toggle_user_hack.rb",
|
37
|
+
"lib/sphero_pwn.rb",
|
38
|
+
"lib/sphero_pwn/async.rb",
|
39
|
+
"lib/sphero_pwn/asyncs.rb",
|
40
|
+
"lib/sphero_pwn/asyncs/flash_block.rb",
|
41
|
+
"lib/sphero_pwn/asyncs/l1_diagnostics.rb",
|
42
|
+
"lib/sphero_pwn/channel.rb",
|
43
|
+
"lib/sphero_pwn/channel_recorder.rb",
|
44
|
+
"lib/sphero_pwn/command.rb",
|
45
|
+
"lib/sphero_pwn/commands.rb",
|
46
|
+
"lib/sphero_pwn/commands/boot_main_app.rb",
|
47
|
+
"lib/sphero_pwn/commands/enter_bootloader.rb",
|
48
|
+
"lib/sphero_pwn/commands/get_device_mode.rb",
|
49
|
+
"lib/sphero_pwn/commands/get_flash_block.rb",
|
50
|
+
"lib/sphero_pwn/commands/get_permanent_flags.rb",
|
51
|
+
"lib/sphero_pwn/commands/get_versions.rb",
|
52
|
+
"lib/sphero_pwn/commands/is_page_blank.rb",
|
53
|
+
"lib/sphero_pwn/commands/l1_diagnostics.rb",
|
54
|
+
"lib/sphero_pwn/commands/l2_diagnostics.rb",
|
55
|
+
"lib/sphero_pwn/commands/ping.rb",
|
56
|
+
"lib/sphero_pwn/commands/set_device_mode.rb",
|
57
|
+
"lib/sphero_pwn/commands/set_permanent_flags.rb",
|
58
|
+
"lib/sphero_pwn/replay_channel.rb",
|
59
|
+
"lib/sphero_pwn/response.rb",
|
60
|
+
"lib/sphero_pwn/session.rb",
|
61
|
+
"lib/sphero_pwn/test_channel.rb",
|
62
|
+
"sphero_pwn.gemspec",
|
63
|
+
"test/channel_recorder_test.rb",
|
64
|
+
"test/command_test.rb",
|
65
|
+
"test/commands/boot_main_app_test.rb",
|
66
|
+
"test/commands/enter_bootloader_test.rb",
|
67
|
+
"test/commands/get_device_mode_test.rb",
|
68
|
+
"test/commands/get_flash_block_test.rb",
|
69
|
+
"test/commands/get_permanent_flags_test.rb",
|
70
|
+
"test/commands/get_versions_test.rb",
|
71
|
+
"test/commands/is_page_blank_test.rb",
|
72
|
+
"test/commands/l1_diagnostics_test.rb",
|
73
|
+
"test/commands/l2_diagnostics_test.rb",
|
74
|
+
"test/commands/ping_test.rb",
|
75
|
+
"test/commands/set_device_mode_test.rb",
|
76
|
+
"test/commands/set_permanent_flags_test.rb",
|
77
|
+
"test/data/enter_bootloader.txt",
|
78
|
+
"test/data/get_device_mode.txt",
|
79
|
+
"test/data/get_factory_config.txt",
|
80
|
+
"test/data/get_permanent_flags.txt",
|
81
|
+
"test/data/get_soul.txt",
|
82
|
+
"test/data/get_version.txt",
|
83
|
+
"test/data/is_page_blank.txt",
|
84
|
+
"test/data/l1_diagnostics.txt",
|
85
|
+
"test/data/l2_diagnostics.txt",
|
86
|
+
"test/data/ping.txt",
|
87
|
+
"test/data/set_device_mode.txt",
|
88
|
+
"test/data/set_permanent_flags.txt",
|
89
|
+
"test/helper.rb",
|
90
|
+
"test/replay_channel_test.rb",
|
91
|
+
"test/response_test.rb",
|
92
|
+
"test/session_test.rb",
|
93
|
+
"test/sphero_pwn_test.rb"
|
94
|
+
]
|
95
|
+
s.homepage = "http://github.com/pwnall/sphero_pwn"
|
96
|
+
s.licenses = ["MIT"]
|
97
|
+
s.rubygems_version = "2.4.5.1"
|
98
|
+
s.summary = "Wrapper for Sphero's bluetooth protocol"
|
99
|
+
|
100
|
+
if s.respond_to? :specification_version then
|
101
|
+
s.specification_version = 4
|
102
|
+
|
103
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
104
|
+
s.add_runtime_dependency(%q<rubyserial>, [">= 0.2.4"])
|
105
|
+
s.add_development_dependency(%q<bundler>, [">= 1.3.5"])
|
106
|
+
s.add_development_dependency(%q<jeweler>, [">= 2.0.1"])
|
107
|
+
s.add_development_dependency(%q<minitest>, [">= 5.8.3"])
|
108
|
+
s.add_development_dependency(%q<mocha>, [">= 1.1.0"])
|
109
|
+
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
110
|
+
s.add_development_dependency(%q<yard>, [">= 0.8.7.6"])
|
111
|
+
else
|
112
|
+
s.add_dependency(%q<rubyserial>, [">= 0.2.4"])
|
113
|
+
s.add_dependency(%q<bundler>, [">= 1.3.5"])
|
114
|
+
s.add_dependency(%q<jeweler>, [">= 2.0.1"])
|
115
|
+
s.add_dependency(%q<minitest>, [">= 5.8.3"])
|
116
|
+
s.add_dependency(%q<mocha>, [">= 1.1.0"])
|
117
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
118
|
+
s.add_dependency(%q<yard>, [">= 0.8.7.6"])
|
119
|
+
end
|
120
|
+
else
|
121
|
+
s.add_dependency(%q<rubyserial>, [">= 0.2.4"])
|
122
|
+
s.add_dependency(%q<bundler>, [">= 1.3.5"])
|
123
|
+
s.add_dependency(%q<jeweler>, [">= 2.0.1"])
|
124
|
+
s.add_dependency(%q<minitest>, [">= 5.8.3"])
|
125
|
+
s.add_dependency(%q<mocha>, [">= 1.1.0"])
|
126
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
127
|
+
s.add_dependency(%q<yard>, [">= 0.8.7.6"])
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|