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,26 @@
|
|
1
|
+
require './spec/helper'
|
2
|
+
require './lib/telegrams/commands/direct/get_battery_level'
|
3
|
+
|
4
|
+
describe GetBatteryLevel do
|
5
|
+
describe "when constructing the object" do
|
6
|
+
it "must not accept any parameters" do
|
7
|
+
-> { GetBatteryLevel.new false }.must_raise ArgumentError
|
8
|
+
end
|
9
|
+
|
10
|
+
it "must default to requiring a response since it is asking for one" do
|
11
|
+
GetBatteryLevel.new.require_response?.must_equal true
|
12
|
+
end
|
13
|
+
|
14
|
+
it "must have a command of 0x0B for getbatterylevel" do
|
15
|
+
GetBatteryLevel.new.command.must_equal 0x0B
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "as_bytes" do
|
20
|
+
it "must have the command as the second byte" do
|
21
|
+
command = GetBatteryLevel.new
|
22
|
+
command.as_bytes[1].must_equal command.command
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require './spec/helper'
|
2
|
+
|
3
|
+
require './lib/telegrams/commands/direct/get_current_program_name'
|
4
|
+
|
5
|
+
describe GetCurrentProgramName do
|
6
|
+
describe "when constructing the object" do
|
7
|
+
it "must not accept any parameters" do
|
8
|
+
-> { GetCurrentProgramName.new false }.must_raise ArgumentError
|
9
|
+
end
|
10
|
+
|
11
|
+
it "must default to requiring a response since it is asking for one" do
|
12
|
+
GetCurrentProgramName.new.require_response?.must_equal true
|
13
|
+
end
|
14
|
+
|
15
|
+
it "must have a command of 0x11 for getcurrentprogramname" do
|
16
|
+
GetCurrentProgramName.new.command.must_equal 0x11
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "as_bytes" do
|
21
|
+
it "must have the command as the second byte" do
|
22
|
+
command = GetCurrentProgramName.new
|
23
|
+
command.as_bytes[1].must_equal command.command
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
require './spec/helper'
|
2
|
+
require './lib/telegrams/commands/direct/output_state'
|
3
|
+
|
4
|
+
describe OutputState do
|
5
|
+
# attr_reader :port, :power, :mode, :regulation_mode, :turn_ratio, :run_state, :tacho_limit
|
6
|
+
|
7
|
+
# this next group can only be read from a GetOutputState call:
|
8
|
+
# tacho_count # internal count; number of counts since last reset of the motor counter
|
9
|
+
# block_tacho_count # current position relative to last programmed movement
|
10
|
+
# rotation_count # current position relative to last reset of the rotation sensor for this motor
|
11
|
+
describe "when constructing the object" do
|
12
|
+
it "must accept hash contructor arguments with defaults of 0" do
|
13
|
+
state = OutputState.new({ :port => :a })
|
14
|
+
state.port.must_equal :a
|
15
|
+
state.mode_flags.must_equal 0
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "when using the builder structure" do
|
20
|
+
before do
|
21
|
+
@state = OutputState.new
|
22
|
+
end
|
23
|
+
|
24
|
+
it "must accept a 'for_port(port_symbol) message that sets the value and returns the object itself" do
|
25
|
+
@state.for_port(:a).must_equal @state
|
26
|
+
@state.port.must_equal :a
|
27
|
+
end
|
28
|
+
|
29
|
+
it "must accept a 'with_power(power)' message that sets the value and returns the object itself" do
|
30
|
+
@state.with_power(100).must_equal @state
|
31
|
+
@state.power.must_equal 100
|
32
|
+
end
|
33
|
+
|
34
|
+
it "must accept a 'with_mode_flags(mode_flags)' that sets the value and returns the object itself" do
|
35
|
+
@state.with_mode_flags(OutputModeFlags.MOTORON | OutputModeFlags.REGULATED).must_equal @state
|
36
|
+
@state.mode_flags.must_equal OutputModeFlags.MOTORON | OutputModeFlags.REGULATED
|
37
|
+
end
|
38
|
+
|
39
|
+
it "must accept a 'with_regulation_mode(regulation_mode)' that sets the value and returns the object itself" do
|
40
|
+
@state.with_regulation_mode(:motor_speed).must_equal @state
|
41
|
+
@state.regulation_mode.must_equal :motor_speed
|
42
|
+
end
|
43
|
+
|
44
|
+
it "must accept a 'with_turn_ratio(turn_ratio)' message that sets the value and returns the object itself" do
|
45
|
+
@state.with_turn_ratio(100).must_equal @state
|
46
|
+
@state.turn_ratio.must_equal 100
|
47
|
+
end
|
48
|
+
|
49
|
+
it "must accept a 'with_run_state(run_state)' that sets the value and returns the object itself" do
|
50
|
+
@state.with_run_state(:ramp_up).must_equal @state
|
51
|
+
@state.run_state.must_equal :ramp_up
|
52
|
+
end
|
53
|
+
|
54
|
+
it "must accept a 'with_tacho_limit(tacho_limit)' that sets the value and returns the object itself" do
|
55
|
+
@state.with_tacho_limit(325).must_equal @state
|
56
|
+
@state.tacho_limit.must_equal 325
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "when using the setter methods" do
|
61
|
+
before do
|
62
|
+
@state = OutputState.new
|
63
|
+
end
|
64
|
+
|
65
|
+
it "must validate that the port is :a, :b, :c, or :all" do
|
66
|
+
@state.port = :a
|
67
|
+
@state.port = :b
|
68
|
+
@state.port = :c
|
69
|
+
@state.port = :all
|
70
|
+
-> { @state.port = :d }.must_raise ArgumentError
|
71
|
+
end
|
72
|
+
|
73
|
+
it "must set the port when it is set" do
|
74
|
+
@state.port = :b
|
75
|
+
@state.port.must_equal :b
|
76
|
+
end
|
77
|
+
|
78
|
+
it "must validate that the power is between -100 and 100" do
|
79
|
+
[-100, 0, 100].each do |power|
|
80
|
+
@state.power = power
|
81
|
+
@state.power.must_equal power
|
82
|
+
end
|
83
|
+
-> { @state.power = -101 }.must_raise ArgumentError
|
84
|
+
-> { @state.power = 101 }.must_raise ArgumentError
|
85
|
+
end
|
86
|
+
|
87
|
+
it "must vaidate that the mode_flags is a valid combination of 0 to all flags (0-7 as an integer)" do
|
88
|
+
(0..7).each do |mode|
|
89
|
+
@state.mode_flags = mode
|
90
|
+
@state.mode_flags.must_equal mode
|
91
|
+
end
|
92
|
+
|
93
|
+
-> { @state.mode_flags = 8 }.must_raise ArgumentError
|
94
|
+
end
|
95
|
+
|
96
|
+
it "must validate that the regulation_mode is one of the valid enumerations" do
|
97
|
+
[:idle, :motor_speed, :motor_sync].each do |regulation_mode|
|
98
|
+
@state.regulation_mode = regulation_mode
|
99
|
+
@state.regulation_mode.must_equal regulation_mode
|
100
|
+
end
|
101
|
+
|
102
|
+
-> { @state.regulation_mode = :garbage }.must_raise ArgumentError
|
103
|
+
-> { @state.regulation_mode = 1 }.must_raise ArgumentError
|
104
|
+
end
|
105
|
+
|
106
|
+
it "must validate that the turn_ratio is between -100 and 100" do
|
107
|
+
[-100, 0, 100].each do |turn_ratio|
|
108
|
+
@state.turn_ratio = turn_ratio
|
109
|
+
@state.turn_ratio.must_equal turn_ratio
|
110
|
+
end
|
111
|
+
-> { @state.turn_ratio = -101 }.must_raise ArgumentError
|
112
|
+
-> { @state.turn_ratio = 101 }.must_raise ArgumentError
|
113
|
+
end
|
114
|
+
|
115
|
+
it "must validate that the run_state is one of the valid enumerations" do
|
116
|
+
[:idle, :running, :ramp_up, :ramp_down].each do |run_state|
|
117
|
+
@state.run_state = run_state
|
118
|
+
@state.run_state.must_equal run_state
|
119
|
+
end
|
120
|
+
|
121
|
+
-> { @state.run_state = :garbage }.must_raise ArgumentError
|
122
|
+
-> { @state.run_state = 1 }.must_raise ArgumentError
|
123
|
+
end
|
124
|
+
|
125
|
+
it "must have a constant representing 'run forever' or 'unlimited'" do
|
126
|
+
OutputState.RUN_FOREVER.must_equal 0
|
127
|
+
end
|
128
|
+
|
129
|
+
it "must set the tacho_limit" do
|
130
|
+
@state.tacho_limit = 39123 # it's an unsigned long value, 4 bytes
|
131
|
+
@state.tacho_limit.must_equal 39123
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
describe OutputModeFlags do
|
137
|
+
it "must have MOTORON set to 0x01" do
|
138
|
+
OutputModeFlags.MOTORON.must_equal 0x01
|
139
|
+
end
|
140
|
+
|
141
|
+
it "must have BRAKE set to 0x02" do
|
142
|
+
OutputModeFlags.BRAKE.must_equal 0x02
|
143
|
+
end
|
144
|
+
|
145
|
+
it "must have REGULATED set to 0x04" do
|
146
|
+
OutputModeFlags.REGULATED.must_equal 0x04
|
147
|
+
end
|
148
|
+
|
149
|
+
it "must allow MOTORON and BRAKE to be combined into 0x03" do
|
150
|
+
(OutputModeFlags.MOTORON | OutputModeFlags.BRAKE).must_equal 0x03
|
151
|
+
end
|
152
|
+
|
153
|
+
it "must allow MOTORON and REGULATED to be combined into 0x05" do
|
154
|
+
(OutputModeFlags.MOTORON | OutputModeFlags.REGULATED).must_equal 0x05
|
155
|
+
end
|
156
|
+
|
157
|
+
it "must allow BRAKE and REGULATED to be combined into 0x06" do
|
158
|
+
(OutputModeFlags.BRAKE | OutputModeFlags.REGULATED).must_equal 0x06
|
159
|
+
end
|
160
|
+
|
161
|
+
it "must allow all three to be combined into 0x07" do
|
162
|
+
(OutputModeFlags.MOTORON | OutputModeFlags.BRAKE | OutputModeFlags.REGULATED).must_equal 0x07
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
describe RegulationMode do
|
168
|
+
it "must have IDLE defined as 0x00" do
|
169
|
+
RegulationMode.IDLE.must_equal 0x00
|
170
|
+
end
|
171
|
+
|
172
|
+
it "must have MOTOR_SPEED defined as 0x01" do
|
173
|
+
RegulationMode.MOTOR_SPEED.must_equal 0x01
|
174
|
+
end
|
175
|
+
|
176
|
+
it "must have MOTOR_SYNC defined as 0x02" do
|
177
|
+
RegulationMode.MOTOR_SYNC.must_equal 0x02
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
describe RunState do
|
183
|
+
it "must have IDLE defined as 0x00" do
|
184
|
+
RunState.IDLE.must_equal 0x00
|
185
|
+
end
|
186
|
+
|
187
|
+
it "must have RAMPUP defined as 0x10" do
|
188
|
+
RunState.RAMPUP.must_equal 0x10
|
189
|
+
end
|
190
|
+
|
191
|
+
it "must have RUNNING defined as 0x20" do
|
192
|
+
RunState.RUNNING.must_equal 0x20
|
193
|
+
end
|
194
|
+
|
195
|
+
it "must have RAMPDOWN defined as 0x40" do
|
196
|
+
RunState.RAMPDOWN.must_equal 0x40
|
197
|
+
end
|
198
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require './spec/helper'
|
2
|
+
|
3
|
+
require './lib/telegrams/commands/direct/play_sound_file'
|
4
|
+
|
5
|
+
|
6
|
+
describe PlaySoundFile do
|
7
|
+
describe "when creating the play sound file command" do
|
8
|
+
it "must default to requiring a response" do
|
9
|
+
PlaySoundFile.new('name').require_response?.must_equal true
|
10
|
+
end
|
11
|
+
|
12
|
+
it "must set the require_response member to the value passed in" do
|
13
|
+
PlaySoundFile.new('name', true, false).require_response?.must_equal false
|
14
|
+
end
|
15
|
+
|
16
|
+
it "must raise an ArgumentError when the filename is nil" do
|
17
|
+
-> { PlaySoundFile.new(nil) }.must_raise ArgumentError
|
18
|
+
end
|
19
|
+
|
20
|
+
it "must set the command value to 0x02 (startprogram)" do
|
21
|
+
PlaySoundFile.new('name').command.must_equal 0x02
|
22
|
+
end
|
23
|
+
|
24
|
+
it "must set the filename to the value passed in" do
|
25
|
+
PlaySoundFile.new('name.mp3').name.must_equal 'name.mp3'
|
26
|
+
end
|
27
|
+
|
28
|
+
it "must default the loop_sound value to false" do
|
29
|
+
PlaySoundFile.new('name.mp3').loop_sound?.must_equal false
|
30
|
+
end
|
31
|
+
|
32
|
+
it "must set the loop_sound boolean to the value passed in" do
|
33
|
+
PlaySoundFile.new('name.mp3', true).loop_sound?.must_equal true
|
34
|
+
end
|
35
|
+
|
36
|
+
it "must set the loop_sound? value to false unless explicitely set to true" do
|
37
|
+
PlaySoundFile.new('name.mp3', "bizbuzz").loop_sound?.must_equal false
|
38
|
+
end
|
39
|
+
|
40
|
+
it "must try adding '.rso' to the end of the filename if there is no file extension" do
|
41
|
+
name = 'sound'
|
42
|
+
PlaySoundFile.new(name).name.must_equal "#{name}.rso"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "must leave the filename alone if there is a 3 letter extension of any kind" do
|
46
|
+
name = 'sound.foo'
|
47
|
+
PlaySoundFile.new(name).name.must_equal name
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "when rendering the command using as_bytes" do
|
52
|
+
it "must have the command value as the second byte" do
|
53
|
+
command = PlaySoundFile.new('name')
|
54
|
+
command.as_bytes[1].must_equal command.command
|
55
|
+
end
|
56
|
+
|
57
|
+
it "must have the loop_sound value as the third byte" do
|
58
|
+
PlaySoundFile.new('name.mp3', false).as_bytes[2].must_equal 0x00
|
59
|
+
PlaySoundFile.new('name.mp3', true).as_bytes[2].must_equal 0xff
|
60
|
+
end
|
61
|
+
|
62
|
+
it "must have the program name in ASCIIZ (null terminated ascii) for bytes 4-23" do
|
63
|
+
name = 'sound.mp3'
|
64
|
+
name_as_asciiz = [115, 111, 117, 110, 100, 46, 109, 112, 51, 0,
|
65
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
66
|
+
|
67
|
+
command = PlaySoundFile.new(name)
|
68
|
+
bytes = command.as_bytes
|
69
|
+
name_bytes = bytes.slice(3, 20)
|
70
|
+
|
71
|
+
name_bytes.must_equal name_as_asciiz
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require './spec/helper'
|
2
|
+
require './lib/telegrams/commands/direct/play_tone'
|
3
|
+
|
4
|
+
describe PlayTone do
|
5
|
+
describe "when constructing the command" do
|
6
|
+
before do
|
7
|
+
@command = PlayTone.new(200, 100)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "must be a direct command" do
|
11
|
+
@command.type.must_equal DirectCommand.new.type
|
12
|
+
end
|
13
|
+
|
14
|
+
it "must have a command of 0x03" do
|
15
|
+
@command.command.must_equal 0x03
|
16
|
+
end
|
17
|
+
|
18
|
+
it "must require a response by default" do
|
19
|
+
@command.require_response?.must_equal true
|
20
|
+
end
|
21
|
+
|
22
|
+
it "must throw an ArgumentException if the frequency is not passed in" do
|
23
|
+
-> { PlayTone.new }.must_raise ArgumentError
|
24
|
+
end
|
25
|
+
|
26
|
+
it "must throw an ArgumentException if the duration is not passed in" do
|
27
|
+
-> { PlayTone.new(500) }.must_raise ArgumentError
|
28
|
+
end
|
29
|
+
|
30
|
+
it "must set the frequency to what is passed in" do
|
31
|
+
PlayTone.new(500, 100).frequency.must_equal 500
|
32
|
+
end
|
33
|
+
|
34
|
+
it "must set the duration to what is passed in" do
|
35
|
+
PlayTone.new(500, 100).duration.must_equal 100
|
36
|
+
end
|
37
|
+
|
38
|
+
it "must validate that the frequency (in Hz) is between 200 and 14000 Hz (the valid range)" do
|
39
|
+
-> { PlayTone.new(199, 100) }.must_raise ArgumentError
|
40
|
+
-> { PlayTone.new(14001, 100) }.must_raise ArgumentError
|
41
|
+
end
|
42
|
+
|
43
|
+
it "must validate that the duration (in ms) is positive or zero" do
|
44
|
+
-> { PlayTone.new(500, -1) }.must_raise ArgumentError
|
45
|
+
PlayTone.new(500, 0)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "when rendering the command as bytes" do
|
50
|
+
it "must set byte 1 to 0x03 as the playtone command" do
|
51
|
+
PlayTone.new(500, 1).as_bytes[1].must_equal 0x03
|
52
|
+
end
|
53
|
+
|
54
|
+
it "must set bytes 2-3 to a UWORD of the frequency to play in reverse order" do
|
55
|
+
PlayTone.new(500, 1).as_bytes[2..3].must_equal [0xf4, 0x01]
|
56
|
+
end
|
57
|
+
|
58
|
+
it "must set bytes 4-5 to a UWORD of the duration to play the tone" do
|
59
|
+
PlayTone.new(500, 2000).as_bytes[4..5].must_equal [0xd0, 0x07]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require './spec/helper'
|
2
|
+
require './lib/telegrams/commands/direct/replies/get_battery_level_reply'
|
3
|
+
|
4
|
+
describe GetBatteryLevelReply do
|
5
|
+
describe "when creating the reply" do
|
6
|
+
before do
|
7
|
+
@millivolts = 4100
|
8
|
+
|
9
|
+
# null pad out to max length and convert to ASCIIZ bytes
|
10
|
+
@millivolts_bytes = [@millivolts.to_s(16).rjust(4, "0")].pack("H*").bytes.to_a.reverse
|
11
|
+
@reply_bytes = [2, 0x0B, 0].concat(@millivolts_bytes)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "must parse the millivolts into the message member" do
|
15
|
+
reply = GetBatteryLevelReply.new(@reply_bytes)
|
16
|
+
|
17
|
+
reply.message.must_equal @millivolts
|
18
|
+
end
|
19
|
+
|
20
|
+
it "must allow access to the message through the millivolts member" do
|
21
|
+
reply = GetBatteryLevelReply.new(@reply_bytes)
|
22
|
+
|
23
|
+
reply.millivolts.must_equal @millivolts
|
24
|
+
end
|
25
|
+
|
26
|
+
it "must convert the millivolts to volts through the volts member" do
|
27
|
+
reply = GetBatteryLevelReply.new(@reply_bytes)
|
28
|
+
|
29
|
+
reply.volts.must_equal @millivolts/1000.0
|
30
|
+
end
|
31
|
+
|
32
|
+
it "must raise an ArgumentError if the reply is not for GetBatteryLevel" do
|
33
|
+
reply_bytes = [2, 0x01, 0].concat(@millivolts_bytes)
|
34
|
+
|
35
|
+
-> { reply = GetBatteryLevelReply.new(reply_bytes) }.must_raise ArgumentError
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require './spec/helper'
|
2
|
+
require './lib/telegrams/commands/direct/replies/get_current_program_name_reply'
|
3
|
+
|
4
|
+
describe GetCurrentProgramNameReply do
|
5
|
+
describe "when creating the reply" do
|
6
|
+
before do
|
7
|
+
@filename = "foobar.rxe"
|
8
|
+
|
9
|
+
# null pad out to max length and convert to ASCIIZ bytes
|
10
|
+
@filename_bytes = @filename.ljust(20, "\0").unpack('C*')
|
11
|
+
@reply_bytes = [2, 0x11, 0].concat(@filename_bytes)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "must parse the filename into the message member" do
|
15
|
+
reply = GetCurrentProgramNameReply.new(@reply_bytes)
|
16
|
+
|
17
|
+
reply.message.must_equal @filename
|
18
|
+
end
|
19
|
+
|
20
|
+
it "must allow access to the message through the program_name member" do
|
21
|
+
reply = GetCurrentProgramNameReply.new(@reply_bytes)
|
22
|
+
|
23
|
+
reply.program_name.must_equal @filename
|
24
|
+
end
|
25
|
+
|
26
|
+
it "must raise an ArgumentError if the reply is not for GetCurrentProgramName" do
|
27
|
+
reply_bytes = [2, 0x01, 0].concat(@filename_bytes)
|
28
|
+
|
29
|
+
-> { reply = GetCurrentProgramNameReply.new(reply_bytes) }.must_raise ArgumentError
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|