nxt 0.3.0 → 0.5.0
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 +15 -0
- data/README.md +45 -0
- data/lib/communication/bluetooth_communication.rb +85 -0
- data/lib/communication/serial_port_profile.rb +71 -0
- data/lib/nxt.rb +111 -20
- data/lib/ruby-nxt.sublime-project +8 -0
- data/lib/ruby-nxt.sublime-workspace +288 -0
- data/lib/telegrams/commands/direct/get_battery_level.rb +8 -0
- data/lib/telegrams/commands/direct/get_current_program_name.rb +8 -0
- data/lib/{nxt/commands/sound.rb → telegrams/commands/direct/get_input_values.rb} +0 -0
- data/lib/{nxt/commands/tone.rb → telegrams/commands/direct/keep_alive.rb} +0 -0
- data/lib/telegrams/commands/direct/ls_get_status.rb +0 -0
- data/lib/telegrams/commands/direct/ls_read.rb +0 -0
- data/lib/telegrams/commands/direct/ls_write.rb +0 -0
- data/lib/telegrams/commands/direct/message_read.rb +0 -0
- data/lib/telegrams/commands/direct/message_write.rb +0 -0
- data/lib/telegrams/commands/direct/output_state.rb +229 -0
- data/lib/telegrams/commands/direct/play_sound_file.rb +38 -0
- data/lib/telegrams/commands/direct/play_tone.rb +34 -0
- data/lib/telegrams/commands/direct/replies/get_battery_level_reply.rb +28 -0
- data/lib/telegrams/commands/direct/replies/get_current_program_name_reply.rb +30 -0
- data/lib/telegrams/commands/direct/replies/play_sound_file_reply.rb +13 -0
- data/lib/telegrams/commands/direct/replies/play_tone_reply.rb +14 -0
- data/lib/telegrams/commands/direct/replies/reset_motor_position_reply.rb +13 -0
- data/lib/telegrams/commands/direct/replies/set_input_mode_reply.rb +11 -0
- data/lib/telegrams/commands/direct/replies/set_output_state_reply.rb +11 -0
- data/lib/telegrams/commands/direct/replies/start_program_reply.rb +13 -0
- data/lib/telegrams/commands/direct/replies/stop_program_reply.rb +13 -0
- data/lib/telegrams/commands/direct/replies/stop_sound_playback_reply.rb +13 -0
- data/lib/telegrams/commands/direct/reset_input_scaled_value.rb +0 -0
- data/lib/telegrams/commands/direct/reset_motor_position.rb +8 -0
- data/lib/telegrams/commands/direct/set_input_mode.rb +101 -0
- data/lib/telegrams/commands/direct/set_output_state.rb +29 -0
- data/lib/telegrams/commands/direct/start_program.rb +30 -0
- data/lib/telegrams/commands/direct/stop_program.rb +9 -0
- data/lib/telegrams/commands/direct/stop_sound_playback.rb +8 -0
- data/lib/telegrams/commands/direct_command.rb +8 -0
- data/lib/telegrams/commands/direct_command_reply.rb +10 -0
- data/lib/telegrams/commands/message_translator.rb +46 -0
- data/lib/telegrams/commands/system/get_device_info.rb +8 -0
- data/lib/telegrams/commands/system/replies/get_device_info_reply.rb +41 -0
- data/lib/telegrams/commands/system_command.rb +8 -0
- data/lib/telegrams/messages/error.rb +0 -0
- data/lib/telegrams/messages/message.rb +0 -0
- data/lib/telegrams/messages/success.rb +0 -0
- data/lib/telegrams/no_message_reply.rb +10 -0
- data/lib/telegrams/reply.rb +82 -0
- data/lib/telegrams/respondable_telegram.rb +29 -0
- data/lib/telegrams/telegram.rb +14 -0
- data/spec/communication/bluetooth_communication_spec.rb +170 -0
- data/spec/communication/serial_port_profile_spec.rb +139 -0
- data/spec/helper.rb +1 -0
- data/spec/nxt_spec.rb +438 -0
- data/spec/telegrams/commands/direct/get_battery_level_spec.rb +26 -0
- data/spec/telegrams/commands/direct/get_current_program_name_spec.rb +26 -0
- data/spec/telegrams/commands/direct/output_state_spec.rb +198 -0
- data/spec/telegrams/commands/direct/play_sound_file_spec.rb +75 -0
- data/spec/telegrams/commands/direct/play_tone_spec.rb +63 -0
- data/spec/telegrams/commands/direct/replies/get_battery_level_reply_spec.rb +40 -0
- data/spec/telegrams/commands/direct/replies/get_current_program_name_reply_spec.rb +33 -0
- data/spec/telegrams/commands/direct/replies/play_sound_file_reply_spec.rb +13 -0
- data/spec/telegrams/commands/direct/replies/play_tone_reply_spec.rb +14 -0
- data/spec/telegrams/commands/direct/replies/reset_motor_position_reply_spec.rb +13 -0
- data/spec/telegrams/commands/direct/replies/set_input_mode_reply_spec.rb +12 -0
- data/spec/telegrams/commands/direct/replies/set_output_state_reply_spec.rb +12 -0
- data/spec/telegrams/commands/direct/replies/start_program_reply_spec.rb +12 -0
- data/spec/telegrams/commands/direct/replies/stop_program_reply_spec.rb +13 -0
- data/spec/telegrams/commands/direct/replies/stop_sound_playback_reply_spec.rb +13 -0
- data/spec/telegrams/commands/direct/reset_motor_position_spec.rb +31 -0
- data/spec/telegrams/commands/direct/set_input_mode_spec.rb +122 -0
- data/spec/telegrams/commands/direct/set_output_state_spec.rb +72 -0
- data/spec/telegrams/commands/direct/start_program_spec.rb +58 -0
- data/spec/telegrams/commands/direct/stop_program_spec.rb +34 -0
- data/spec/telegrams/commands/direct/stop_sound_playback_spec.rb +34 -0
- data/spec/telegrams/commands/direct_command_reply_spec.rb +7 -0
- data/spec/telegrams/commands/direct_command_spec.rb +34 -0
- data/spec/telegrams/commands/system/get_device_info_spec.rb +16 -0
- data/spec/telegrams/commands/system/replies/get_device_info_reply_spec.rb +63 -0
- data/spec/telegrams/commands/system_command_spec.rb +26 -0
- data/spec/telegrams/no_message_reply_spec.rb +12 -0
- data/spec/telegrams/reply_spec.rb +63 -0
- data/spec/telegrams/respondable_telegram_spec.rb +66 -0
- data/spec/telegrams/telegram_spec.rb +38 -0
- metadata +97 -116
- data/README.markdown +0 -52
- data/Rakefile +0 -35
- data/lib/nxt/commands/base.rb +0 -51
- data/lib/nxt/commands/input.rb +0 -60
- data/lib/nxt/commands/output.rb +0 -105
- data/lib/nxt/commands/program.rb +0 -70
- data/lib/nxt/connectors/base.rb +0 -35
- data/lib/nxt/connectors/input/color.rb +0 -30
- data/lib/nxt/connectors/input/touch.rb +0 -11
- data/lib/nxt/connectors/input/ultrasonic.rb +0 -11
- data/lib/nxt/connectors/output/motor.rb +0 -114
- data/lib/nxt/errors.rb +0 -25
- data/lib/nxt/exceptions.rb +0 -26
- data/lib/nxt/interfaces/base.rb +0 -36
- data/lib/nxt/interfaces/serial_port.rb +0 -88
- data/lib/nxt/interfaces/usb.rb +0 -8
- data/lib/nxt/nxt_brick.rb +0 -167
- data/lib/nxt/patches/module.rb +0 -22
- data/lib/nxt/patches/string.rb +0 -29
- data/lib/nxt/utils/accessors.rb +0 -24
- data/spec/matchers.rb +0 -7
- data/spec/nxt/connectors/output/motor_spec.rb +0 -55
- data/spec/nxt/interfaces/serial_port_spec.rb +0 -73
- data/spec/nxt/nxt_brick_spec.rb +0 -199
- data/spec/spec_helper.rb +0 -4
@@ -0,0 +1,11 @@
|
|
1
|
+
require_relative '../../direct_command_reply'
|
2
|
+
|
3
|
+
class SetOutputStateReply < DirectCommandReply
|
4
|
+
def initialize(bytes)
|
5
|
+
super(bytes)
|
6
|
+
end
|
7
|
+
|
8
|
+
def validate_bytes(bytes)
|
9
|
+
raise ArgumentError, "must be a reply for a SetOutputState command" unless bytes[1] == 0x04
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative '../../direct_command_reply'
|
2
|
+
|
3
|
+
class StartProgramReply < DirectCommandReply
|
4
|
+
def initialize(bytes)
|
5
|
+
super(bytes)
|
6
|
+
end
|
7
|
+
|
8
|
+
# override
|
9
|
+
def validate_bytes(bytes)
|
10
|
+
super(bytes)
|
11
|
+
raise ArgumentError, "must be a reply for a StartProgram command" unless bytes[1] == 0x00
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative '../../direct_command_reply'
|
2
|
+
|
3
|
+
class StopProgramReply < DirectCommandReply
|
4
|
+
def initialize(bytes)
|
5
|
+
super(bytes)
|
6
|
+
end
|
7
|
+
|
8
|
+
# override
|
9
|
+
def validate_bytes(bytes)
|
10
|
+
super(bytes)
|
11
|
+
raise ArgumentError, "must be a reply for a StopProgram command" unless bytes[1] == 0x01
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative '../../direct_command_reply'
|
2
|
+
|
3
|
+
class StopSoundPlaybackReply < DirectCommandReply
|
4
|
+
def initialize(bytes)
|
5
|
+
super(bytes)
|
6
|
+
end
|
7
|
+
|
8
|
+
# override
|
9
|
+
def validate_bytes(bytes)
|
10
|
+
super(bytes)
|
11
|
+
raise ArgumentError, "must be a reply for a StopSoundPlayback command" unless bytes[1] == 0x0C
|
12
|
+
end
|
13
|
+
end
|
File without changes
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require_relative '../direct_command'
|
2
|
+
|
3
|
+
class SetInputMode < DirectCommand
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def input_ports; INPUT_PORTS.keys; end
|
7
|
+
def sensor_types; SENSOR_TYPES.keys; end
|
8
|
+
def sensor_modes; SENSOR_MODES.keys; end
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :input_port, :sensor_type, :sensor_mode
|
12
|
+
|
13
|
+
def initialize(input_port, sensor_type, sensor_mode, response_required=true)
|
14
|
+
super(response_required)
|
15
|
+
@command = 0x05
|
16
|
+
|
17
|
+
validate_arguments(input_port, sensor_type, sensor_mode)
|
18
|
+
@input_port = input_port
|
19
|
+
@sensor_type = sensor_type
|
20
|
+
@sensor_mode = sensor_mode
|
21
|
+
end
|
22
|
+
|
23
|
+
INPUT_PORTS = {
|
24
|
+
one: 0x00,
|
25
|
+
two: 0x01,
|
26
|
+
three: 0x02,
|
27
|
+
four: 0x03
|
28
|
+
}
|
29
|
+
|
30
|
+
SENSOR_TYPES = {}
|
31
|
+
[:no_sensor,
|
32
|
+
:switch,
|
33
|
+
:temperature,
|
34
|
+
:reflection,
|
35
|
+
:angle,
|
36
|
+
:light_active,
|
37
|
+
:light_inactive,
|
38
|
+
:sound_db,
|
39
|
+
:sound_dba,
|
40
|
+
:custom,
|
41
|
+
:lowspeed,
|
42
|
+
:lowspeed_9v,
|
43
|
+
:highspeed,
|
44
|
+
:colorfull,
|
45
|
+
:colorred,
|
46
|
+
:colorgreen,
|
47
|
+
:colorblue,
|
48
|
+
:colornone
|
49
|
+
].each_with_index do |key, index|
|
50
|
+
SENSOR_TYPES[key] = index
|
51
|
+
end
|
52
|
+
|
53
|
+
SENSOR_MODES = {
|
54
|
+
:rawmode => 0x00,
|
55
|
+
:booleanmode => 0x20,
|
56
|
+
:transitioncntmode => 0x40,
|
57
|
+
:periodcountermode => 0x60,
|
58
|
+
:pctfullscalemode => 0x80,
|
59
|
+
:celsiusmode => 0xA0,
|
60
|
+
:fahrenheitmode => 0xC0,
|
61
|
+
:anglestepmode => 0xE0,
|
62
|
+
:slopemask => 0x1F,
|
63
|
+
:modemask => 0xE0
|
64
|
+
}
|
65
|
+
|
66
|
+
def sensor_types
|
67
|
+
self.class.sensor_types
|
68
|
+
end
|
69
|
+
|
70
|
+
def sensor_modes
|
71
|
+
self.class.sensor_modes
|
72
|
+
end
|
73
|
+
|
74
|
+
def input_ports
|
75
|
+
self.class.input_ports
|
76
|
+
end
|
77
|
+
|
78
|
+
def as_bytes
|
79
|
+
super << INPUT_PORTS[@input_port] << SENSOR_TYPES[@sensor_type] << SENSOR_MODES[@sensor_mode]
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
def validate_arguments(input_port, sensor_type, sensor_mode)
|
84
|
+
validate_input_port(input_port)
|
85
|
+
validate_sensor_type(sensor_type)
|
86
|
+
validate_sensor_mode(sensor_mode)
|
87
|
+
end
|
88
|
+
|
89
|
+
def validate_input_port(input_port)
|
90
|
+
raise ArgumentError, "Invalid input port" unless input_ports.include? input_port
|
91
|
+
end
|
92
|
+
|
93
|
+
def validate_sensor_type(sensor_type)
|
94
|
+
raise ArgumentError, "Invalid sensor type" unless sensor_types.include? sensor_type
|
95
|
+
end
|
96
|
+
|
97
|
+
def validate_sensor_mode(sensor_mode)
|
98
|
+
raise ArgumentError, "Invalid sensor mode" unless sensor_modes.include? sensor_mode
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative '../direct_command'
|
2
|
+
require_relative './output_state'
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
class SetOutputState < DirectCommand
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
def initialize(output_state, wait_for_reply=true)
|
9
|
+
super(wait_for_reply)
|
10
|
+
@command = 0x04
|
11
|
+
|
12
|
+
raise ArgumentError, "output_state must be a valid OutputState object" if output_state.nil?
|
13
|
+
@output_state = output_state
|
14
|
+
end
|
15
|
+
|
16
|
+
def as_bytes
|
17
|
+
super.concat(@output_state.as_bytes)
|
18
|
+
end
|
19
|
+
|
20
|
+
# follow Law of Demeter and hide internal access to output_state
|
21
|
+
def_delegators :@output_state, :port, :power, :mode_flags, :regulation_mode,
|
22
|
+
:turn_ratio, :run_state, :tacho_limit
|
23
|
+
|
24
|
+
private
|
25
|
+
def output_state
|
26
|
+
@output_state
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative '../direct_command'
|
2
|
+
require_relative '../message_translator'
|
3
|
+
|
4
|
+
class StartProgram < DirectCommand
|
5
|
+
include MessageTranslator
|
6
|
+
|
7
|
+
attr_reader :name
|
8
|
+
|
9
|
+
def initialize(program_name, require_response=true)
|
10
|
+
raise ArgumentError, "program_name is required" if program_name.nil?
|
11
|
+
|
12
|
+
super(require_response)
|
13
|
+
@command = 0x00 # startprogram
|
14
|
+
@name = adjust_program_name(program_name)
|
15
|
+
end
|
16
|
+
|
17
|
+
def as_bytes
|
18
|
+
bytes = super
|
19
|
+
bytes.concat program_name_as_bytes
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def program_name_as_bytes
|
24
|
+
string_as_bytes(@name)
|
25
|
+
end
|
26
|
+
|
27
|
+
def adjust_program_name(name)
|
28
|
+
add_default_extension_if_missing(name, 'rxe')
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module MessageTranslator
|
2
|
+
FILENAME_MAX_LENGTH = 20 # 15.3 + null terminator
|
3
|
+
|
4
|
+
def string_as_bytes(string, max_length=FILENAME_MAX_LENGTH)
|
5
|
+
# pad out to max length with null characters and then
|
6
|
+
# convert all to ASCIIZ (null-terminated ascii string)
|
7
|
+
string.ljust(max_length, "\0").unpack('C*')
|
8
|
+
end
|
9
|
+
|
10
|
+
def string_from_bytes(bytes)
|
11
|
+
# convert from ASCIIZ (null-terminated ascii), removing all the
|
12
|
+
# trailing null characters
|
13
|
+
bytes.pack("C*").strip
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_default_extension_if_missing(filename, default_extension)
|
17
|
+
/.+\.[A-Za-z0-9]{3}$/.match(filename).nil? ? "#{filename}.#{default_extension}" : filename
|
18
|
+
end
|
19
|
+
|
20
|
+
def boolean_as_bytes(boolean)
|
21
|
+
boolean ? [0xff] : [0x00]
|
22
|
+
end
|
23
|
+
|
24
|
+
def boolean_from_bytes(bytes)
|
25
|
+
bytes == [0x00] ? false : true
|
26
|
+
end
|
27
|
+
|
28
|
+
def integer_as_uword_bytes(integer)
|
29
|
+
integer_as_bytes(integer, 4) # make sure number is 4 bytes, or 2, 2 digit hex values
|
30
|
+
end
|
31
|
+
|
32
|
+
def integer_as_ulong_bytes(integer)
|
33
|
+
integer_as_bytes(integer, 8) # (4 bytes as 2 digit hex values each)
|
34
|
+
end
|
35
|
+
|
36
|
+
def integer_as_bytes(integer, bytes_length)
|
37
|
+
uword_byte_length = bytes_length
|
38
|
+
bytes_string = integer.to_s(16).rjust(uword_byte_length, "0")
|
39
|
+
[bytes_string].pack('H*').bytes.to_a.reverse # reverse because it's MSB
|
40
|
+
end
|
41
|
+
|
42
|
+
def integer_from_bytes(bytes)
|
43
|
+
bytes.reverse.pack('C*').unpack('H*')[0].hex
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative '../../../reply'
|
2
|
+
|
3
|
+
class GetDeviceInfoReply < Reply
|
4
|
+
attr_reader :nxt_brick_name, :bt_address,
|
5
|
+
:signal_strength, :free_user_flash_memory_bytes
|
6
|
+
|
7
|
+
def initialize(bytes)
|
8
|
+
super
|
9
|
+
raise ArgumentError, "must be a GetDeviceInfoReply (0x9B)" unless bytes[1] == 0x9B
|
10
|
+
|
11
|
+
@nxt_brick_name = parse_brick_name(bytes)
|
12
|
+
@bt_address = parse_bt_address(bytes)
|
13
|
+
@signal_strength = parse_signal_strength(bytes)
|
14
|
+
@free_user_flash_memory_bytes = parse_free_user_flash_memory(bytes)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
def parse_brick_name(bytes)
|
19
|
+
bytes[3..17].pack("C*").strip
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse_bt_address(bytes)
|
23
|
+
# skip the null terminator, so 18-23 with 24 at null terminator
|
24
|
+
address = bytes[18..23].map { | byte | byte.to_s(8).rjust(2, "0") }
|
25
|
+
"btspp://#{address.join('')}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def parse_signal_strength(bytes)
|
29
|
+
signal_strength_bytes = bytes[25..28]
|
30
|
+
convert_byte_array_of_little_endian_to_number(signal_strength_bytes)
|
31
|
+
end
|
32
|
+
|
33
|
+
def parse_free_user_flash_memory(bytes)
|
34
|
+
free_memory_bytes = bytes[29..32]
|
35
|
+
convert_byte_array_of_little_endian_to_number(free_memory_bytes)
|
36
|
+
end
|
37
|
+
|
38
|
+
def convert_byte_array_of_little_endian_to_number(byte_array)
|
39
|
+
byte_array.pack('C*').unpack('v*')[0]
|
40
|
+
end
|
41
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require_relative './telegram'
|
2
|
+
|
3
|
+
class Reply < Telegram
|
4
|
+
COMMAND_TYPE = 0x02
|
5
|
+
SUCCESS = 0x00
|
6
|
+
STATUS_MESSAGES = {
|
7
|
+
SUCCESS => 'Success',
|
8
|
+
# base error messages
|
9
|
+
0x81 => 'No more handles',
|
10
|
+
0x82 => 'No space',
|
11
|
+
0x83 => 'No more files',
|
12
|
+
0x84 => 'End of file expected',
|
13
|
+
0x85 => 'End of file',
|
14
|
+
0x86 => 'Not a linear file',
|
15
|
+
0x87 => 'File not found',
|
16
|
+
0x88 => 'Handle all ready closed',
|
17
|
+
0x89 => 'No linear space',
|
18
|
+
0x8A => 'Undefined error',
|
19
|
+
0x8B => 'File is busy',
|
20
|
+
0x8C => 'No write buffers',
|
21
|
+
0x8D => 'Append not possible',
|
22
|
+
0x8E => 'File is full',
|
23
|
+
0x8F => 'File exists',
|
24
|
+
0x90 => 'Module not found',
|
25
|
+
0x91 => 'Out of boundary',
|
26
|
+
0x92 => 'Illegal file name',
|
27
|
+
0x93 => 'Illegal handle',
|
28
|
+
|
29
|
+
# command replies
|
30
|
+
0x20 => 'Pending communication transaction in progress',
|
31
|
+
0x40 => 'Specified mailbox queue is empty',
|
32
|
+
0xBD => 'Request failed (i.e., specified file not found)',
|
33
|
+
0xBE => 'Unknown command opcode',
|
34
|
+
0xBF => 'Insane packet',
|
35
|
+
0xC0 => 'Data contains out-of-range values',
|
36
|
+
0xDD => 'Communication bus error',
|
37
|
+
0xDE => 'No free memory in communication buffer',
|
38
|
+
0xDF => 'Specified channel/connection is not valid',
|
39
|
+
0xE0 => 'Specified channel/connection not configured or busy',
|
40
|
+
0xEC => 'No active program',
|
41
|
+
0xED => 'Illegal size specified',
|
42
|
+
0xEE => 'Illegal mailbox queue ID specified',
|
43
|
+
0xEF => 'Attempted to access invalid field of a structure',
|
44
|
+
0xF0 => 'Bad input or output specified',
|
45
|
+
0xFB => 'Insufficient memory available',
|
46
|
+
0xFF => 'Bad arguments'
|
47
|
+
}
|
48
|
+
|
49
|
+
attr_accessor :type, :command, :status, :message_bytes, :status_description
|
50
|
+
|
51
|
+
def initialize(bytes=nil)
|
52
|
+
validate_bytes(bytes)
|
53
|
+
@type = bytes[0]
|
54
|
+
@command = bytes[1]
|
55
|
+
@status = bytes[2]
|
56
|
+
@message_bytes = bytes[3..-1]
|
57
|
+
set_status_description
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
def success?
|
62
|
+
status == SUCCESS
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
def message
|
67
|
+
# override in subclasses to translate bytes to something meaningful
|
68
|
+
message_bytes
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
private
|
73
|
+
def validate_bytes(bytes)
|
74
|
+
raise ArgumentError, "must be non-nil" if bytes.nil?
|
75
|
+
raise ArgumentError, "must have a type, command, and status" unless bytes.size && bytes.size >= 3
|
76
|
+
raise ArgumentError, "must be a reply telegram" unless bytes[0] == COMMAND_TYPE
|
77
|
+
end
|
78
|
+
|
79
|
+
def set_status_description
|
80
|
+
@status_description = STATUS_MESSAGES.include?(status) ? STATUS_MESSAGES[status] : ''
|
81
|
+
end
|
82
|
+
end
|