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.
- 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
|
+
|